@quadrel-enterprise-ui/framework 20.11.1 → 20.11.2-beta.152.1

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,15 +1,15 @@
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, SecurityContext, NgZone, ViewChildren, forwardRef, DestroyRef, ContentChildren, ContentChild, isDevMode, QueryList, CUSTOM_ELEMENTS_SCHEMA, provideAppInitializer, TemplateRef } 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, CUSTOM_ELEMENTS_SCHEMA, provideAppInitializer, TemplateRef } from '@angular/core';
3
3
  import { Dialog, DialogRef, DialogModule } from '@angular/cdk/dialog';
4
4
  import * as i1 from '@angular/common';
5
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, delay, tap as tap$1, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize, combineLatestWith, forkJoin, delayWhen, withLatestFrom, async } from 'rxjs';
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, delay, tap as tap$1, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize, forkJoin, delayWhen, combineLatestWith, withLatestFrom, async } from 'rxjs';
7
7
  import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, tap, skip, auditTime, 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';
10
10
  import { TranslateService, TranslateModule } from '@ngx-translate/core';
11
11
  import * as i2$1 from '@angular/router';
12
- import { Router, ActivationEnd, RouterModule, ActivatedRoute, NavigationError, NavigationCancel, NavigationEnd, NavigationStart } from '@angular/router';
12
+ import { Router, ActivationEnd, RouterModule, ActivatedRoute, NavigationEnd, NavigationCancel, NavigationError, NavigationStart } from '@angular/router';
13
13
  import { HttpStatusCode, HttpEventType, HttpClient, HttpParams, HTTP_INTERCEPTORS } from '@angular/common/http';
14
14
  import * as _ from 'lodash';
15
15
  import { upperCase, lowerFirst, isEqual, range, get as get$1, cloneDeep, union, isNumber as isNumber$1 } from 'lodash';
@@ -18,6 +18,7 @@ import { NG_VALUE_ACCESSOR, FormsModule, UntypedFormControl, UntypedFormArray, U
18
18
  import { ComponentPortal } from '@angular/cdk/portal';
19
19
  import { OverlayPositionBuilder, Overlay } from '@angular/cdk/overlay';
20
20
  import isNumber from 'lodash/isNumber';
21
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
21
22
  import { EventSourcePolyfill } from 'event-source-polyfill';
22
23
  import { DomSanitizer } from '@angular/platform-browser';
23
24
  import * as i3$1 from 'ngx-editor';
@@ -31,7 +32,6 @@ import 'moment/locale/fr';
31
32
  import 'moment/locale/it';
32
33
  import moment$1 from 'moment/moment';
33
34
  import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
34
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
35
35
  import * as i1$1 from '@ngrx/store';
36
36
  import { createAction, props, createReducer, on, createSelector, createFeatureSelector, Store, StoreModule } from '@ngrx/store';
37
37
  import { diff } from 'deep-object-diff';
@@ -52,7 +52,7 @@ class QdButtonLinkDirective {
52
52
  ngOnInit() {
53
53
  // TODO: Delete directive "qd-button-link" in Version 21
54
54
  if (this._elementRef.nativeElement.attributes.hasOwnProperty('qd-button-link')) {
55
- console.warn('QD-UI | QdButtonLinkDirective - The directive "qd-button-link" is deprecated. Please use "qdButtonLink" instead.');
55
+ console.warn('Quadrel Framework | QdButtonLink - The directive "qd-button-link" is deprecated. Please use "qdButtonLink" instead.');
56
56
  }
57
57
  }
58
58
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdButtonLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -649,7 +649,7 @@ class QdIconComponent {
649
649
  this.iconCode = icon.htmlEntity;
650
650
  }
651
651
  if (!icon) {
652
- console.error(`QD-UI | QdIconComponent - ${this.icon} seems not be a valid Quadrel Icon. Please check documentation for available icons.`);
652
+ console.error(`Quadrel Framework | QdIcon - "${this.icon}" does not appear to be a valid Quadrel Icon. Please check documentation for available icons.`);
653
653
  }
654
654
  }
655
655
  insertIconSvgOnce() {
@@ -698,7 +698,7 @@ class QdSnackbarService {
698
698
  if (this.isPausing)
699
699
  return;
700
700
  if (!this._overlayRef) {
701
- console.error('QdUi | QdNotifications: You are trying to open a notification as snackbar but there is no Snackbar Listener initialized.');
701
+ console.error('Quadrel Framework | QdNotifications - You are trying to open a notification as snackbar but there is no Snackbar Listener initialized.');
702
702
  return;
703
703
  }
704
704
  this._notificationsSubject.next([...this._notificationsSubject.value, notification]);
@@ -916,7 +916,7 @@ class QdNotificationsService {
916
916
  return;
917
917
  if (this.zeroToInfinity(snackbarNotificationLifeTime) >
918
918
  this.zeroToInfinity(this.getNotificationLifeTime(notification))) {
919
- console.warn('The life time of the snackbar notification must be shorter than the life time of the main notification.');
919
+ console.warn('Quadrel Framework | QdNotifications - The life time of the snackbar notification must be shorter than the life time of the main notification.');
920
920
  return;
921
921
  }
922
922
  setTimeout(() => this.snackbarService.close(notification.uuid), snackbarNotificationLifeTime * 1000);
@@ -926,7 +926,7 @@ class QdNotificationsService {
926
926
  if (osNotificationLifeTime === undefined)
927
927
  return;
928
928
  if (this.zeroToInfinity(osNotificationLifeTime) > this.zeroToInfinity(this.getNotificationLifeTime(notification))) {
929
- console.warn('The life time of the OS notification must be shorter than the life time of the main notification.');
929
+ console.warn('Quadrel Framework | QdNotifications - The life time of the OS notification must be shorter than the life time of the main notification.');
930
930
  return;
931
931
  }
932
932
  setTimeout(() => this.osNotificationsService.close(notification.uuid), osNotificationLifeTime * 1000);
@@ -1046,7 +1046,7 @@ class QdButtonComponent {
1046
1046
  ngOnInit() {
1047
1047
  // TODO: Delete directive "qd-button" in Version 20
1048
1048
  if (this._elementRef.nativeElement.attributes.hasOwnProperty('qd-button')) {
1049
- console.warn('QD-UI | QdButtonComponent - The directive "qd-button" is deprecated. Please use "qdButton" instead.');
1049
+ console.warn('Quadrel Framework | QdButton - The directive "qd-button" is deprecated. Please use "qdButton" instead.');
1050
1050
  }
1051
1051
  }
1052
1052
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1265,7 +1265,7 @@ class QdDialogService {
1265
1265
  this.clearPageDialogCanCloseForce();
1266
1266
  this.updateDialogData(data);
1267
1267
  if (!this.pageDialogHost)
1268
- throw new Error('QdDialogService | Page dialog host component is not provided.');
1268
+ throw new Error('Quadrel Framework | QdDialog - Page dialog host component is not provided.');
1269
1269
  this.open(this.pageDialogHost, { dialogSize: QdDialogSize.FullWidth });
1270
1270
  this.navigateInsideDialog(routePath || this.getFirstDialogOutletRoutePathOrThrow());
1271
1271
  }
@@ -1326,7 +1326,7 @@ class QdDialogService {
1326
1326
  getFirstDialogOutletRoutePathOrThrow() {
1327
1327
  const firstDialogOutletRoutePath = this.router.config.find(route => route.outlet === 'dialog')?.path;
1328
1328
  if (!firstDialogOutletRoutePath || this.hasRoutePathParameters(firstDialogOutletRoutePath)) {
1329
- throw new Error('QdDialogService | Please provide a route for the openPageDialogWithBreadcrumbs method. ' +
1329
+ throw new Error('Quadrel Framework | QdDialog - Please provide a route for the openPageDialogWithBreadcrumbs method. ' +
1330
1330
  'The main dialog route could not be determined automatically.');
1331
1331
  }
1332
1332
  return firstDialogOutletRoutePath;
@@ -1368,7 +1368,7 @@ class QdIconButtonComponent {
1368
1368
  ngOnInit() {
1369
1369
  // TODO: Delete directive "qd-icon-button" in Version 15
1370
1370
  if (this._elementRef.nativeElement.attributes.hasOwnProperty('qd-icon-button')) {
1371
- console.warn('QD-UI | QdIconButtonComponent - The directive "qd-icon-button" is deprecated. Please use "qdIconButton" instead.');
1371
+ console.warn('Quadrel Framework | QdIconButton - The directive "qd-icon-button" is deprecated. Please use "qdIconButton" instead.');
1372
1372
  }
1373
1373
  }
1374
1374
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdIconButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1604,6 +1604,24 @@ const updateHtmlLang = (lang) => {
1604
1604
  const htmlNode = document.documentElement;
1605
1605
  htmlNode.setAttribute('lang', lang);
1606
1606
  };
1607
+ const SERVICE_NAV_LOCALE_DEFAULTS = {
1608
+ DE: 'de-CH',
1609
+ IT: 'it-CH',
1610
+ FR: 'fr-CH',
1611
+ EN: 'en-GB'
1612
+ };
1613
+ const determineLocale = (serviceNavLanguage, browserLocales) => {
1614
+ const browserLocale = browserLocales?.[0] ?? navigator.language;
1615
+ if (!serviceNavLanguage) {
1616
+ const browserLocaleUpper = browserLocale.toUpperCase();
1617
+ return SERVICE_NAV_LOCALE_DEFAULTS[browserLocaleUpper] ?? browserLocale;
1618
+ }
1619
+ const serviceNavLangUpper = serviceNavLanguage.toUpperCase();
1620
+ const browserLanguage = browserLocale.split('-')[0].toUpperCase();
1621
+ if (browserLanguage === serviceNavLangUpper)
1622
+ return browserLocale;
1623
+ return SERVICE_NAV_LOCALE_DEFAULTS[serviceNavLangUpper] ?? browserLocale;
1624
+ };
1607
1625
 
1608
1626
  const constantCase = (str) => upperCase(str).replace(/ /g, '_');
1609
1627
 
@@ -6636,6 +6654,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6636
6654
  }]
6637
6655
  }] });
6638
6656
 
6657
+ const QD_SAFE_BOTTOM_OFFSET = new InjectionToken('QD_SAFE_BOTTOM_OFFSET');
6658
+
6639
6659
  let QdFileSizePipe$1 = class QdFileSizePipe {
6640
6660
  translate = inject(TranslateService, { optional: true });
6641
6661
  transform(bytes) {
@@ -6687,10 +6707,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6687
6707
  }]
6688
6708
  }] });
6689
6709
 
6710
+ const QD_POPOVER_TOP_FIRST = new InjectionToken('QD_POPOVER_TOP_FIRST');
6711
+
6690
6712
  class QdProjectionGuardComponent {
6691
6713
  elementRef = inject(ElementRef);
6692
6714
  isDisabled = false;
6693
- warningMessage = 'QD-UI | QdProjectionGuard - This content is not supported and cannot be displayed:';
6715
+ warningMessage = 'Quadrel Framework | QdProjectionGuard - This content is not supported and cannot be displayed:';
6694
6716
  wildcardSlot;
6695
6717
  ngAfterContentInit() {
6696
6718
  if (this.isDisabled)
@@ -6728,156 +6750,123 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6728
6750
  }]
6729
6751
  }] });
6730
6752
 
6731
- var breakpoints$1 = {
6732
- xs: 320,
6733
- sm: 600,
6734
- md: 960,
6735
- lg: 1280,
6736
- xl: 1600,
6737
- xxl: 1800
6738
- };
6739
- var panel = {
6740
- sm: 432,
6741
- md: 588,
6742
- lg: 720
6743
- };
6744
- var base = {
6745
- fontsize: 16
6746
- };
6747
- var globalVars = {
6748
- breakpoints: breakpoints$1,
6749
- panel: panel,
6750
- base: base
6751
- };
6752
-
6753
- const convertPxToRem = (pixel) => `${parseFloat((pixel / globalVars.base.fontsize).toFixed(3))}rem`;
6754
-
6755
- class QdTooltipComponent {
6756
- content;
6757
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6758
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTooltipComponent, isStandalone: false, selector: "qd-tooltip", inputs: { content: "content" }, ngImport: i0, template: "<ng-container *ngIf=\"content?.headline\">\n <strong>{{ content.headline }}</strong>\n</ng-container>\n\n<ng-container *ngFor=\"let paragraph of content.paragraphs\">\n <p>{{ paragraph }}</p>\n</ng-container>\n", styles: [":host{box-shadow:0 0 .625rem #979797;display:block;width:100%;max-width:16rem;padding:.5rem;border-radius:.5rem;background-color:#000;color:#fff;font-size:.75rem;line-height:1rem}:host strong,:host p{display:block}:host p{margin:0 0 .5rem}:host p:last-child{margin-bottom:0}\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"] }] });
6753
+ class QdLocaleService {
6754
+ _serviceNavLanguage$ = new BehaviorSubject(null);
6755
+ locale$ = this._serviceNavLanguage$.pipe(map(serviceNavLanguage => determineLocale(serviceNavLanguage, navigator.languages)));
6756
+ setServiceNavigationLanguage(language) {
6757
+ this._serviceNavLanguage$.next(language);
6758
+ }
6759
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6760
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, providedIn: 'root' });
6759
6761
  }
6760
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, decorators: [{
6761
- type: Component,
6762
- args: [{ selector: 'qd-tooltip', standalone: false, template: "<ng-container *ngIf=\"content?.headline\">\n <strong>{{ content.headline }}</strong>\n</ng-container>\n\n<ng-container *ngFor=\"let paragraph of content.paragraphs\">\n <p>{{ paragraph }}</p>\n</ng-container>\n", styles: [":host{box-shadow:0 0 .625rem #979797;display:block;width:100%;max-width:16rem;padding:.5rem;border-radius:.5rem;background-color:#000;color:#fff;font-size:.75rem;line-height:1rem}:host strong,:host p{display:block}:host p{margin:0 0 .5rem}:host p:last-child{margin-bottom:0}\n"] }]
6763
- }], propDecorators: { content: [{
6764
- type: Input
6765
- }] } });
6762
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, decorators: [{
6763
+ type: Injectable,
6764
+ args: [{ providedIn: 'root' }]
6765
+ }] });
6766
6766
 
6767
- const TARGET_SELECTOR = '.qd-intersection-target';
6768
- const SHOW_EVENTS = ['mouseenter', 'mousemove'];
6769
- const HIDE_EVENTS = ['mouseleave', 'click'];
6770
- const HIDE_DELAY = 300;
6771
- const OVERLAY_WIDTH = 280;
6772
- const UNSUBSCRIBE_IMMEDIATELY = true;
6773
- const THRESHOLD = 1;
6774
- /**
6775
- * QdTooltipAtIntersectionDirective provides a tooltip. This will be triggered if the content is intersected.
6776
- *
6777
- * * Selector: [qdTooltipAtIntersection]
6778
- * * Target Selector: .qd-intersection-target
6779
- *
6780
- * The IntersectionObserver API is used for the implementation.
6781
- * * @see https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
6782
- *
6783
- * * Note: The intersection of the target is calculated by the IntersectionObserver only once, initially (can be extended later if required). After that it will be unsubscribed immediately.
6784
- * */
6785
- class QdTooltipAtIntersectionDirective {
6786
- _host = inject(ElementRef);
6787
- _positionBuilder = inject(OverlayPositionBuilder);
6788
- _overlay = inject(Overlay);
6789
- _overlayRef;
6790
- _target;
6791
- _observer$;
6792
- _isIntersected = false;
6793
- _destroyed$ = new Subject();
6794
- ngAfterViewInit() {
6795
- this.setTarget();
6796
- this.observeTarget();
6797
- this.createOverlay();
6798
- this.subscribeShow();
6799
- this.subscribeHide();
6767
+ class QdNumberInputService {
6768
+ _locale;
6769
+ _decimalSeparator;
6770
+ _groupSeparator;
6771
+ localeService = inject(QdLocaleService, { optional: true });
6772
+ destroyRef = inject(DestroyRef);
6773
+ ambiguityHintKeyDot = 'i18n.qd.input.number.ambiguousHint.dot';
6774
+ ambiguityHintKeyComma = 'i18n.qd.input.number.ambiguousHint.comma';
6775
+ invalidCharactersErrorKeyComma = 'i18n.qd.input.number.invalidCharacters.comma';
6776
+ invalidCharactersErrorKeyDot = 'i18n.qd.input.number.invalidCharacters.dot';
6777
+ get invalidCharactersErrorKey() {
6778
+ return this._decimalSeparator === ',' ? this.invalidCharactersErrorKeyComma : this.invalidCharactersErrorKeyDot;
6800
6779
  }
6801
- ngOnDestroy() {
6802
- this._observer$.unobserve(this._target);
6803
- this._destroyed$.next();
6804
- this._destroyed$.complete();
6780
+ get decimalSeparator() {
6781
+ return this._decimalSeparator;
6805
6782
  }
6806
- setTarget() {
6807
- this._target = this._host.nativeElement.querySelector(TARGET_SELECTOR);
6783
+ get groupSeparator() {
6784
+ return this._groupSeparator;
6808
6785
  }
6809
- observeTarget() {
6810
- const options = {
6811
- root: this._host.nativeElement,
6812
- threshold: THRESHOLD
6813
- };
6814
- this._observer$ = new IntersectionObserver(entries => {
6815
- this._isIntersected = entries[0].intersectionRatio < 1;
6816
- if (this._isIntersected) {
6817
- this._setStyles();
6818
- if (UNSUBSCRIBE_IMMEDIATELY)
6819
- this._observer$.unobserve(this._target);
6820
- }
6821
- }, options);
6822
- this._observer$.observe(this._target);
6786
+ constructor() {
6787
+ if (this.localeService) {
6788
+ this.localeService.locale$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(locale => {
6789
+ this.detectSeparatorsForLocale(locale);
6790
+ });
6791
+ }
6792
+ else {
6793
+ this.detectSeparators();
6794
+ }
6823
6795
  }
6824
- _setStyles() {
6825
- this._target.style.overflow = 'hidden';
6826
- this._target.style.textOverflow = 'ellipsis';
6827
- this._target.style.cursor = 'help';
6796
+ detectSeparators() {
6797
+ const locale = navigator.languages && navigator.languages.length ? navigator.languages[0] : navigator.language;
6798
+ this.detectSeparatorsForLocale(locale);
6828
6799
  }
6829
- createOverlay() {
6830
- this._overlayRef = this._overlay.create({
6831
- positionStrategy: this._positionBuilder
6832
- .flexibleConnectedTo(this._host)
6833
- .withPositions([{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' }]),
6834
- width: convertPxToRem(OVERLAY_WIDTH)
6835
- });
6800
+ isValidNumber(value) {
6801
+ if (!value)
6802
+ return false;
6803
+ const escaped = this._decimalSeparator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
6804
+ return new RegExp(`^-?\\d+(${escaped}\\d+)?$`).test(value);
6805
+ }
6806
+ detectSeparatorsForLocale(locale) {
6807
+ this._locale = locale;
6808
+ const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
6809
+ this._decimalSeparator = parts.find(p => p.type === 'decimal')?.value ?? '.';
6810
+ this._groupSeparator = parts.find(p => p.type === 'group')?.value ?? ',';
6811
+ }
6812
+ filterValue(value) {
6813
+ let result = '';
6814
+ let hasDecimal = false;
6815
+ for (let i = 0; i < value.length; i++) {
6816
+ const char = value[i];
6817
+ if (char >= '0' && char <= '9') {
6818
+ result += char;
6819
+ }
6820
+ else if (char === this._decimalSeparator && !hasDecimal) {
6821
+ result += char;
6822
+ hasDecimal = true;
6823
+ }
6824
+ else if (char === '-' && i === 0) {
6825
+ result += char;
6826
+ }
6827
+ }
6828
+ return result;
6836
6829
  }
6837
- subscribeShow() {
6838
- merge(...SHOW_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
6839
- .pipe(takeUntil(this._destroyed$), filter(() => !this._overlayRef.hasAttached() && this._isIntersected))
6840
- .subscribe(() => {
6841
- const content = this.getContent();
6842
- const tooltipPortal = new ComponentPortal(QdTooltipComponent);
6843
- const tooltipRef = this._overlayRef.attach(tooltipPortal);
6844
- tooltipRef.instance.content = content;
6845
- });
6830
+ parseValue(value) {
6831
+ if (!value)
6832
+ return value;
6833
+ const normalized = value.split(this._groupSeparator).join('').replace(this._decimalSeparator, '.');
6834
+ const parsed = parseFloat(normalized);
6835
+ return isNaN(parsed) ? value : parsed;
6846
6836
  }
6847
- subscribeHide() {
6848
- merge(...HIDE_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
6849
- .pipe(takeUntil(this._destroyed$), filter(() => this._overlayRef.hasAttached()), debounceTime(HIDE_DELAY))
6850
- .subscribe(() => this._overlayRef.detach());
6837
+ isAmbiguous(value) {
6838
+ if (typeof value !== 'string' || !value)
6839
+ return false;
6840
+ return /^-?[1-9]\d*[.,]\d{3}$/.test(value);
6851
6841
  }
6852
- getContent() {
6853
- return {
6854
- headline: this._target.getAttribute('data-tooltip-headline') || undefined,
6855
- paragraphs: [this._target.textContent?.trim() || '']
6856
- };
6842
+ getAmbiguityHintKey(value) {
6843
+ if (typeof value === 'string' && value.includes('.'))
6844
+ return this.ambiguityHintKeyDot;
6845
+ return this.ambiguityHintKeyComma;
6857
6846
  }
6858
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
6859
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdTooltipAtIntersectionDirective, isStandalone: false, selector: "[qdTooltipAtIntersection]", ngImport: i0 });
6860
- }
6861
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, decorators: [{
6862
- type: Directive,
6863
- args: [{
6864
- selector: '[qdTooltipAtIntersection]',
6865
- standalone: false
6866
- }]
6867
- }] });
6868
-
6869
- class QdVisuallyHiddenDirective {
6870
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
6871
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdVisuallyHiddenDirective, isStandalone: false, selector: "[qdVisuallyHidden]", host: { classAttribute: "qd-visually-hidden" }, ngImport: i0 });
6847
+ formatNumberForViewonly(value) {
6848
+ if (value == null || value === '')
6849
+ return '';
6850
+ const str = String(value);
6851
+ const parsed = typeof value === 'number' ? value : this.parseValue(str);
6852
+ if (typeof parsed !== 'number')
6853
+ return str;
6854
+ return new Intl.NumberFormat(this._locale).format(parsed);
6855
+ }
6856
+ formatValueForDisplay(value) {
6857
+ if (value == null || value === '')
6858
+ return '';
6859
+ const str = String(value);
6860
+ if (this._decimalSeparator === '.')
6861
+ return str;
6862
+ return str.replace('.', this._decimalSeparator);
6863
+ }
6864
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6865
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService });
6872
6866
  }
6873
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, decorators: [{
6874
- type: Directive,
6875
- args: [{
6876
- selector: '[qdVisuallyHidden]',
6877
- host: { class: 'qd-visually-hidden' },
6878
- standalone: false
6879
- }]
6880
- }] });
6867
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, decorators: [{
6868
+ type: Injectable
6869
+ }], ctorParameters: () => [] });
6881
6870
 
6882
6871
  /**
6883
6872
  * Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
@@ -7100,10 +7089,10 @@ class QdPushEventsService {
7100
7089
  this._listeners = [];
7101
7090
  }
7102
7091
  logWarn(message) {
7103
- console.warn(`QD-UI | QdPushEvents - ${message}`);
7092
+ console.warn(`Quadrel Framework | QdPushEvents - ${message}`);
7104
7093
  }
7105
7094
  logError(message, err) {
7106
- console.error(`QD-UI | QdPushEvents - ${message}`, err);
7095
+ console.error(`Quadrel Framework | QdPushEvents - ${message}`, err);
7107
7096
  }
7108
7097
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7109
7098
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
@@ -7115,6 +7104,415 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7115
7104
  }]
7116
7105
  }] });
7117
7106
 
7107
+ /**
7108
+ * Framework-wide funnel for syncing application state with the URL `?key=value` query string.
7109
+ *
7110
+ * Several Quadrel features mirror their state to the URL — the table's sort and pagination today,
7111
+ * filter, search, and `qd-page-tabs` over time. Without coordination they each call
7112
+ * `router.navigate(...)` directly, which produces two failure modes:
7113
+ *
7114
+ * 1. **Race**: two navigates issued in the same JS turn cancel each other. Only the last writer
7115
+ * wins; the URL silently loses the cancelled feature's params.
7116
+ * 2. **History pollution**: a single user action that changes two features (e.g. clicking a sort
7117
+ * header resets the page index) ends up as two history entries. Browser-back only undoes one.
7118
+ *
7119
+ * `QdRouterQueryParamHubService` is the single funnel through which features run their query-param
7120
+ * reads and writes. It does three jobs:
7121
+ *
7122
+ * - **Ownership** — `claim()` / `release()` enforce one writer per param key, app-wide.
7123
+ * - **Shared reads** — `queryParams()` and `snapshotQueryParam()` expose the route state without
7124
+ * each feature needing its own `ActivatedRoute` subscription.
7125
+ * - **Coordinated writes** — `write()` buffers param updates within a microtask and serializes
7126
+ * navigations via a Promise chain, so two writes in the same JS turn become one history entry
7127
+ * and concurrent writes never race.
7128
+ *
7129
+ * The hub is feature-agnostic. Per-feature adapters (e.g. `QdTableSortRouterConnectorService`)
7130
+ * own their parsing/serialization and delegate the URL plumbing to the hub.
7131
+ *
7132
+ * ### Usage
7133
+ *
7134
+ * ```ts
7135
+ * @Injectable()
7136
+ * export class FilterRouterAdapterService {
7137
+ * private readonly _hub = inject(QdRouterQueryParamHubService);
7138
+ * private readonly _destroyRef = inject(DestroyRef);
7139
+ *
7140
+ * connect(state$: Observable<FilterState>, dispatch: (state: FilterState) => void): void {
7141
+ * if (!this._hub.isAvailable()) return;
7142
+ * if (!this._hub.claim(['filter'], this, this._destroyRef)) return;
7143
+ *
7144
+ * this._hub
7145
+ * .queryParams()
7146
+ * .pipe(takeUntilDestroyed(this._destroyRef))
7147
+ * .subscribe(params => dispatch(parseFilter(params['filter'])));
7148
+ *
7149
+ * state$
7150
+ * .pipe(takeUntilDestroyed(this._destroyRef))
7151
+ * .subscribe(state => this._hub.write({ filter: serializeFilter(state) }, false));
7152
+ * }
7153
+ * }
7154
+ * ```
7155
+ */
7156
+ class QdRouterQueryParamHubService {
7157
+ /**
7158
+ * Replays whenever the router has finished a navigation (`NavigationEnd`, `NavigationCancel`
7159
+ * or `NavigationError` — every event that ends a navigation, regardless of outcome).
7160
+ * Adapters that want to delay a write until any in-flight navigation has settled can take(1)
7161
+ * on this stream before calling `write()`.
7162
+ *
7163
+ * Late subscribers receive the most recent settling event immediately, so an adapter that
7164
+ * mounts after the initial route navigation can observe the route as already-settled. The
7165
+ * first replayed tick may represent that initial route navigation rather than a user-driven
7166
+ * settling event — adapters that need to distinguish "the route just changed" should compare
7167
+ * `ActivatedRoute.snapshot` themselves.
7168
+ *
7169
+ * **When the hub is unavailable** (no `Router` / `ActivatedRoute` in the injector — see
7170
+ * `isAvailable()`) this observable never emits. Adapters that compose `navigationSettled$`
7171
+ * via operators like `switchMap` or `concat` must guard with `isAvailable()` first, otherwise
7172
+ * their pipelines hang silently.
7173
+ */
7174
+ navigationSettled$;
7175
+ _router = inject(Router, { optional: true });
7176
+ _activatedRoute = inject(ActivatedRoute, { optional: true });
7177
+ _destroyRef = inject(DestroyRef);
7178
+ _ownership = new Map();
7179
+ _destroyClaims = new WeakMap();
7180
+ _navigationSettledSubject = new ReplaySubject(1);
7181
+ _pendingParams = {};
7182
+ _pendingReplaceUrl = false;
7183
+ _flushScheduled = false;
7184
+ _navigationChain = Promise.resolve();
7185
+ constructor() {
7186
+ this.navigationSettled$ = this._navigationSettledSubject.asObservable();
7187
+ if (!this._router || !this._activatedRoute)
7188
+ return;
7189
+ this.replayCurrentRouterStateForLateSubscribers(this._router);
7190
+ this.forwardSettlingRouterEventsToNavigationSettled(this._router);
7191
+ }
7192
+ /**
7193
+ * Returns whether the hub can sync at all. False when the consuming injector has neither a
7194
+ * `Router` nor an `ActivatedRoute` available — for example in unit tests that omit
7195
+ * `RouterTestingModule`. Adapters should bail out early when this returns false.
7196
+ */
7197
+ isAvailable() {
7198
+ return !!this._router && !!this._activatedRoute;
7199
+ }
7200
+ /**
7201
+ * Reserves exclusive write access to the given query-param keys for `owner`.
7202
+ *
7203
+ * The same `owner` may claim the same keys repeatedly without conflict — claims are idempotent
7204
+ * per owner. A different owner attempting to claim an already-claimed key fails: the hub logs
7205
+ * a `console.error` listing every contested key and returns `false`. The original owner keeps
7206
+ * the keys until it calls `release()` (or until its `DestroyRef` fires, if a `destroyRef` is
7207
+ * passed here).
7208
+ *
7209
+ * Atomicity: when the call fails, no keys are claimed, even partially. The hub checks every
7210
+ * requested key against the registry before mutating anything.
7211
+ *
7212
+ * **Pass `destroyRef` to opt into auto-release.** Without it, the hub keeps a strong reference
7213
+ * to `owner` until `release()` is called manually — a destroyed adapter that forgets to release
7214
+ * pins itself in the registry. Passing the adapter's `DestroyRef` registers an `onDestroy`
7215
+ * callback that releases exactly the keys claimed via this call (and any later claims that
7216
+ * reuse the same `destroyRef`), which is the recommended path.
7217
+ *
7218
+ * Each `destroyRef` releases only the keys it owns. If the same owner uses two different
7219
+ * `DestroyRef`s in two `claim()` calls, each fires independently and only releases its own
7220
+ * keys — keys claimed via the still-alive `destroyRef` stay reserved.
7221
+ *
7222
+ * Re-claiming with the same `destroyRef` appends to the same destroy listener — no duplicate
7223
+ * listeners are registered, even when the second claim names a different owner. Each appended
7224
+ * entry carries its own owner, so when the `destroyRef` fires the hub releases each entry's
7225
+ * keys against that entry's owner. An empty `keys` array is a no-op even when `destroyRef`
7226
+ * is provided: no listener is attached, so the hub does not pin a destroy hook that would
7227
+ * release nothing.
7228
+ *
7229
+ * @param keys The query-param keys this adapter wants to own (e.g. `['sort']`, `['page', 'size']`).
7230
+ * @param owner Stable identity of the caller — usually `this`. Used as the registry key.
7231
+ * @param destroyRef Optional. If provided, the hub releases the keys automatically when the
7232
+ * `DestroyRef` fires. Pass the adapter's `inject(DestroyRef)` to make leaks impossible.
7233
+ * @returns `true` if every requested key is now owned by `owner`. `false` if at least one key
7234
+ * was already owned by a different adapter; the registry is left untouched and `destroyRef`
7235
+ * is not registered.
7236
+ */
7237
+ claim(keys, owner, destroyRef) {
7238
+ const conflicts = [];
7239
+ for (const key of keys) {
7240
+ const existing = this._ownership.get(key);
7241
+ if (existing && existing !== owner)
7242
+ conflicts.push(key);
7243
+ }
7244
+ if (conflicts.length > 0) {
7245
+ const list = conflicts.map(k => `"${k}"`).join(', ');
7246
+ console.error(`Quadrel Framework | QdRouterQueryParamHub - Query param ${list} ${conflicts.length === 1 ? 'is' : 'are'} ` +
7247
+ `already owned by another adapter. Disable the conflicting feature's URL sync or move it to a ` +
7248
+ `different param key.`);
7249
+ return false;
7250
+ }
7251
+ keys.forEach(key => this._ownership.set(key, owner));
7252
+ if (destroyRef && keys.length > 0)
7253
+ this.registerAutoRelease(owner, keys, destroyRef);
7254
+ return true;
7255
+ }
7256
+ /**
7257
+ * Drops `owner`'s claim on the given keys. Keys not owned by `owner` are left untouched —
7258
+ * a foreign release call cannot steal another adapter's ownership.
7259
+ *
7260
+ * Adapters typically release in their `DestroyRef.onDestroy` callback so a destroyed component
7261
+ * frees its keys for the next adapter that mounts.
7262
+ */
7263
+ release(keys, owner) {
7264
+ keys.forEach(key => {
7265
+ if (this._ownership.get(key) === owner)
7266
+ this._ownership.delete(key);
7267
+ });
7268
+ }
7269
+ /**
7270
+ * Reactive view of `ActivatedRoute.queryParams`. Returns the empty observable if the hub is
7271
+ * not available (no Router/ActivatedRoute). Adapters subscribe here instead of injecting
7272
+ * `ActivatedRoute` themselves so the hub stays the single read funnel.
7273
+ *
7274
+ * The observable is hot — late subscribers receive the current params immediately.
7275
+ */
7276
+ queryParams() {
7277
+ return this._activatedRoute?.queryParams ?? of({});
7278
+ }
7279
+ /**
7280
+ * Synchronous read of a single query param from the latest `ActivatedRoute` snapshot.
7281
+ * Adapters use this to detect "URL already matches the desired state" and skip a redundant
7282
+ * `write()`.
7283
+ *
7284
+ * @returns The param value, or `undefined` if the param is missing or the hub is unavailable.
7285
+ */
7286
+ snapshotQueryParam(key) {
7287
+ return this._activatedRoute?.snapshot.queryParamMap.get(key) ?? undefined;
7288
+ }
7289
+ /**
7290
+ * Schedules a query-param update.
7291
+ *
7292
+ * Two coordination guarantees:
7293
+ *
7294
+ * - **Microtask batching** — every `write()` issued in the same JavaScript turn is merged into
7295
+ * a single `router.navigate(...)` call. A user action that changes two features at once
7296
+ * (e.g. sort change resets the page) becomes one history entry, not two. Note: batching is
7297
+ * per JS turn, not per logical user action — writes that fall into the next microtask after
7298
+ * a settled navigation produce a separate history entry, even when they belong to the same
7299
+ * conceptual gesture.
7300
+ * - **Serialized navigations** — flushes are chained on a Promise so a second flush only fires
7301
+ * after the previous `router.navigate` has settled. Concurrent navigates can therefore not
7302
+ * cancel each other. A rejected `router.navigate` (cancelled by a guard, redirected, or
7303
+ * failed) does not stop the chain — the next pending flush still runs. Rejections are not
7304
+ * logged here; consumers that need routing diagnostics should subscribe to `router.events`.
7305
+ *
7306
+ * Adapters are still responsible for skipping no-op writes (compare the desired value against
7307
+ * `snapshotQueryParam()` first), since the hub does not deduplicate identical values.
7308
+ *
7309
+ * Setting a param value to `undefined` removes the param from the URL via Angular Router's
7310
+ * `merge` behavior. Other params not mentioned in the call are preserved.
7311
+ *
7312
+ * @param params Partial map of query-param keys to their new values. Missing keys are not touched.
7313
+ * An empty object short-circuits and is a no-op.
7314
+ * @param replaceUrl `true` replaces the current history entry; `false` pushes a new entry.
7315
+ * When several `write()` calls in the same microtask disagree, `true` wins (so an initial
7316
+ * replace is preserved when a follow-up write would otherwise push). The escalation is
7317
+ * per-batch — after each flush the pending flag resets to `false`, so writes that arrive
7318
+ * in the next microtask start a fresh batch with their own `replaceUrl` argument.
7319
+ */
7320
+ write(params, replaceUrl) {
7321
+ const router = this._router;
7322
+ const activatedRoute = this._activatedRoute;
7323
+ if (!router || !activatedRoute)
7324
+ return;
7325
+ if (Object.keys(params).length === 0)
7326
+ return;
7327
+ Object.assign(this._pendingParams, params);
7328
+ this._pendingReplaceUrl = this._pendingReplaceUrl || replaceUrl;
7329
+ if (this._flushScheduled)
7330
+ return;
7331
+ this._flushScheduled = true;
7332
+ Promise.resolve().then(() => this.flush(router, activatedRoute));
7333
+ }
7334
+ replayCurrentRouterStateForLateSubscribers(router) {
7335
+ if (router.navigated)
7336
+ this._navigationSettledSubject.next();
7337
+ }
7338
+ forwardSettlingRouterEventsToNavigationSettled(router) {
7339
+ router.events
7340
+ .pipe(filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError), takeUntilDestroyed(this._destroyRef))
7341
+ .subscribe(() => this._navigationSettledSubject.next());
7342
+ }
7343
+ registerAutoRelease(owner, keys, destroyRef) {
7344
+ const existingClaims = this._destroyClaims.get(destroyRef);
7345
+ if (existingClaims) {
7346
+ existingClaims.push({ owner, keys });
7347
+ return;
7348
+ }
7349
+ const claims = [{ owner, keys }];
7350
+ this._destroyClaims.set(destroyRef, claims);
7351
+ destroyRef.onDestroy(() => {
7352
+ for (const claim of claims)
7353
+ this.release(claim.keys, claim.owner);
7354
+ });
7355
+ }
7356
+ flush(router, activatedRoute) {
7357
+ const params = this._pendingParams;
7358
+ const replaceUrl = this._pendingReplaceUrl;
7359
+ this._pendingParams = {};
7360
+ this._pendingReplaceUrl = false;
7361
+ this._flushScheduled = false;
7362
+ const exec = () => router.navigate([], {
7363
+ relativeTo: activatedRoute,
7364
+ queryParams: params,
7365
+ queryParamsHandling: 'merge',
7366
+ replaceUrl
7367
+ });
7368
+ this._navigationChain = this._navigationChain.catch(() => undefined).then(exec);
7369
+ }
7370
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7371
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, providedIn: 'root' });
7372
+ }
7373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, decorators: [{
7374
+ type: Injectable,
7375
+ args: [{ providedIn: 'root' }]
7376
+ }], ctorParameters: () => [] });
7377
+
7378
+ var breakpoints$1 = {
7379
+ xs: 320,
7380
+ sm: 600,
7381
+ md: 960,
7382
+ lg: 1280,
7383
+ xl: 1600,
7384
+ xxl: 1800
7385
+ };
7386
+ var panel = {
7387
+ sm: 432,
7388
+ md: 588,
7389
+ lg: 720
7390
+ };
7391
+ var base = {
7392
+ fontsize: 16
7393
+ };
7394
+ var globalVars = {
7395
+ breakpoints: breakpoints$1,
7396
+ panel: panel,
7397
+ base: base
7398
+ };
7399
+
7400
+ const convertPxToRem = (pixel) => `${parseFloat((pixel / globalVars.base.fontsize).toFixed(3))}rem`;
7401
+
7402
+ class QdTooltipComponent {
7403
+ content;
7404
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7405
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTooltipComponent, isStandalone: false, selector: "qd-tooltip", inputs: { content: "content" }, ngImport: i0, template: "<ng-container *ngIf=\"content?.headline\">\n <strong>{{ content.headline }}</strong>\n</ng-container>\n\n<ng-container *ngFor=\"let paragraph of content.paragraphs\">\n <p>{{ paragraph }}</p>\n</ng-container>\n", styles: [":host{box-shadow:0 0 .625rem #979797;display:block;width:100%;max-width:16rem;padding:.5rem;border-radius:.5rem;background-color:#000;color:#fff;font-size:.75rem;line-height:1rem}:host strong,:host p{display:block}:host p{margin:0 0 .5rem}:host p:last-child{margin-bottom:0}\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"] }] });
7406
+ }
7407
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, decorators: [{
7408
+ type: Component,
7409
+ args: [{ selector: 'qd-tooltip', standalone: false, template: "<ng-container *ngIf=\"content?.headline\">\n <strong>{{ content.headline }}</strong>\n</ng-container>\n\n<ng-container *ngFor=\"let paragraph of content.paragraphs\">\n <p>{{ paragraph }}</p>\n</ng-container>\n", styles: [":host{box-shadow:0 0 .625rem #979797;display:block;width:100%;max-width:16rem;padding:.5rem;border-radius:.5rem;background-color:#000;color:#fff;font-size:.75rem;line-height:1rem}:host strong,:host p{display:block}:host p{margin:0 0 .5rem}:host p:last-child{margin-bottom:0}\n"] }]
7410
+ }], propDecorators: { content: [{
7411
+ type: Input
7412
+ }] } });
7413
+
7414
+ const TARGET_SELECTOR = '.qd-intersection-target';
7415
+ const SHOW_EVENTS = ['mouseenter', 'mousemove'];
7416
+ const HIDE_EVENTS = ['mouseleave', 'click'];
7417
+ const HIDE_DELAY = 300;
7418
+ const OVERLAY_WIDTH = 280;
7419
+ const UNSUBSCRIBE_IMMEDIATELY = true;
7420
+ const THRESHOLD = 1;
7421
+ /**
7422
+ * QdTooltipAtIntersectionDirective provides a tooltip. This will be triggered if the content is intersected.
7423
+ *
7424
+ * * Selector: [qdTooltipAtIntersection]
7425
+ * * Target Selector: .qd-intersection-target
7426
+ *
7427
+ * The IntersectionObserver API is used for the implementation.
7428
+ * * @see https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
7429
+ *
7430
+ * * Note: The intersection of the target is calculated by the IntersectionObserver only once, initially (can be extended later if required). After that it will be unsubscribed immediately.
7431
+ * */
7432
+ class QdTooltipAtIntersectionDirective {
7433
+ _host = inject(ElementRef);
7434
+ _positionBuilder = inject(OverlayPositionBuilder);
7435
+ _overlay = inject(Overlay);
7436
+ _overlayRef;
7437
+ _target;
7438
+ _observer$;
7439
+ _isIntersected = false;
7440
+ _destroyed$ = new Subject();
7441
+ ngAfterViewInit() {
7442
+ this.setTarget();
7443
+ this.observeTarget();
7444
+ this.createOverlay();
7445
+ this.subscribeShow();
7446
+ this.subscribeHide();
7447
+ }
7448
+ ngOnDestroy() {
7449
+ this._observer$.unobserve(this._target);
7450
+ this._destroyed$.next();
7451
+ this._destroyed$.complete();
7452
+ }
7453
+ setTarget() {
7454
+ this._target = this._host.nativeElement.querySelector(TARGET_SELECTOR);
7455
+ }
7456
+ observeTarget() {
7457
+ const options = {
7458
+ root: this._host.nativeElement,
7459
+ threshold: THRESHOLD
7460
+ };
7461
+ this._observer$ = new IntersectionObserver(entries => {
7462
+ this._isIntersected = entries[0].intersectionRatio < 1;
7463
+ if (this._isIntersected) {
7464
+ this._setStyles();
7465
+ if (UNSUBSCRIBE_IMMEDIATELY)
7466
+ this._observer$.unobserve(this._target);
7467
+ }
7468
+ }, options);
7469
+ this._observer$.observe(this._target);
7470
+ }
7471
+ _setStyles() {
7472
+ this._target.style.overflow = 'hidden';
7473
+ this._target.style.textOverflow = 'ellipsis';
7474
+ this._target.style.cursor = 'help';
7475
+ }
7476
+ createOverlay() {
7477
+ this._overlayRef = this._overlay.create({
7478
+ positionStrategy: this._positionBuilder
7479
+ .flexibleConnectedTo(this._host)
7480
+ .withPositions([{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' }]),
7481
+ width: convertPxToRem(OVERLAY_WIDTH)
7482
+ });
7483
+ }
7484
+ subscribeShow() {
7485
+ merge(...SHOW_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
7486
+ .pipe(takeUntil(this._destroyed$), filter(() => !this._overlayRef.hasAttached() && this._isIntersected))
7487
+ .subscribe(() => {
7488
+ const content = this.getContent();
7489
+ const tooltipPortal = new ComponentPortal(QdTooltipComponent);
7490
+ const tooltipRef = this._overlayRef.attach(tooltipPortal);
7491
+ tooltipRef.instance.content = content;
7492
+ });
7493
+ }
7494
+ subscribeHide() {
7495
+ merge(...HIDE_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
7496
+ .pipe(takeUntil(this._destroyed$), filter(() => this._overlayRef.hasAttached()), debounceTime(HIDE_DELAY))
7497
+ .subscribe(() => this._overlayRef.detach());
7498
+ }
7499
+ getContent() {
7500
+ return {
7501
+ headline: this._target.getAttribute('data-tooltip-headline') || undefined,
7502
+ paragraphs: [this._target.textContent?.trim() || '']
7503
+ };
7504
+ }
7505
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7506
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdTooltipAtIntersectionDirective, isStandalone: false, selector: "[qdTooltipAtIntersection]", ngImport: i0 });
7507
+ }
7508
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, decorators: [{
7509
+ type: Directive,
7510
+ args: [{
7511
+ selector: '[qdTooltipAtIntersection]',
7512
+ standalone: false
7513
+ }]
7514
+ }] });
7515
+
7118
7516
  const MAX_TOOLTIP_CHARACTER = 512;
7119
7517
  const TOOLTIP_POSITIONS = [
7120
7518
  { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom' },
@@ -7180,7 +7578,7 @@ class QdTooltipOnClickDirective {
7180
7578
  truncateText(text) {
7181
7579
  if (text.length <= MAX_TOOLTIP_CHARACTER)
7182
7580
  return text.trim();
7183
- console.warn(`QdUi | QdTooltip - Tooltip content exceeds ${MAX_TOOLTIP_CHARACTER} characters. It will be truncated.`);
7581
+ console.warn(`Quadrel Framework | QdTooltip - Tooltip content exceeds ${MAX_TOOLTIP_CHARACTER} characters. It will be truncated.`);
7184
7582
  return `${text.substring(0, MAX_TOOLTIP_CHARACTER).trim()}...`;
7185
7583
  }
7186
7584
  translate(key) {
@@ -7220,9 +7618,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7220
7618
  type: Input
7221
7619
  }] } });
7222
7620
 
7223
- const QD_SAFE_BOTTOM_OFFSET = new InjectionToken('QD_SAFE_BOTTOM_OFFSET');
7224
-
7225
- const QD_POPOVER_TOP_FIRST = new InjectionToken('QD_POPOVER_TOP_FIRST');
7621
+ class QdVisuallyHiddenDirective {
7622
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7623
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdVisuallyHiddenDirective, isStandalone: false, selector: "[qdVisuallyHidden]", host: { classAttribute: "qd-visually-hidden" }, ngImport: i0 });
7624
+ }
7625
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, decorators: [{
7626
+ type: Directive,
7627
+ args: [{
7628
+ selector: '[qdVisuallyHidden]',
7629
+ host: { class: 'qd-visually-hidden' },
7630
+ standalone: false
7631
+ }]
7632
+ }] });
7226
7633
 
7227
7634
  class QdCoreModule {
7228
7635
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -7871,7 +8278,7 @@ class QdAutofocusDirective {
7871
8278
  if (!this.qdAutofocus)
7872
8279
  return;
7873
8280
  if (this.autofocusService.isAutofocusActivated) {
7874
- console.warn('QD-UI | QdAutofocus - "hasAutofocus" can be used only once!');
8281
+ console.warn('Quadrel Framework | QdAutofocus - "hasAutofocus" can be used only once.');
7875
8282
  return;
7876
8283
  }
7877
8284
  this.autofocusService.isAutofocusActivated = true;
@@ -8194,7 +8601,7 @@ class QdEventBrokerService {
8194
8601
  }
8195
8602
  consume(topic) {
8196
8603
  if (!this._topics.has(topic)) {
8197
- console.warn(`QD-UI | QdEventBrokerService - Topic "${topic}" does not exist.`);
8604
+ console.warn(`Quadrel Framework | QdEventBroker - Topic "${topic}" does not exist.`);
8198
8605
  return EMPTY;
8199
8606
  }
8200
8607
  return this._topics.get(topic).pipe(filter(event => event.payload != null), distinctUntilChanged((prev, curr) => isEqual(prev, curr)), shareReplay(1));
@@ -8300,11 +8707,11 @@ class QdFormHintComponent {
8300
8707
  this.actionEmitterService.hintEventEmitterSubject.next(null);
8301
8708
  }
8302
8709
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8303
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFormHintComponent, isStandalone: false, selector: "qd-form-hint", inputs: { hint: "hint", control: "control", hasError: "hasError", hintAction: "hintAction", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-form-hint" }, ngImport: i0, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdFormErrorComponent, selector: "qd-form-error", inputs: ["control"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
8710
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFormHintComponent, isStandalone: false, selector: "qd-form-hint", inputs: { hint: "hint", control: "control", hasError: "hasError", hintAction: "hintAction", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-form-hint" }, ngImport: i0, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}.qd-input-ambiguous :host{color:#069}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdFormErrorComponent, selector: "qd-form-error", inputs: ["control"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
8304
8711
  }
8305
8712
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, decorators: [{
8306
8713
  type: Component,
8307
- args: [{ selector: 'qd-form-hint', host: { class: 'qd-form-hint' }, standalone: false, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"] }]
8714
+ args: [{ selector: 'qd-form-hint', host: { class: 'qd-form-hint' }, standalone: false, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}.qd-input-ambiguous :host{color:#069}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"] }]
8308
8715
  }], propDecorators: { hint: [{
8309
8716
  type: Input
8310
8717
  }], control: [{
@@ -8558,11 +8965,11 @@ class QdCheckboxChipsComponent {
8558
8965
  if (this.formControlName) {
8559
8966
  this.control = this.controlContainer.control.get(this.formControlName);
8560
8967
  if (!(this.control instanceof QdFormControl)) {
8561
- console.warn('QD-UI | QdCheckboxChipsComponent - Please use the QdFormControl instead of the Angular FormControl');
8968
+ console.warn('Quadrel Framework | QdCheckboxChips - Please use the QdFormControl instead of the Angular FormControl.');
8562
8969
  }
8563
8970
  }
8564
8971
  else {
8565
- console.warn('QD-UI | QdCheckboxChipsComponent - Missing FormControlName directive from host element of the component');
8972
+ console.warn('Quadrel Framework | QdCheckboxChips - Missing FormControlName directive from host element of the component.');
8566
8973
  }
8567
8974
  }
8568
8975
  this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
@@ -9010,7 +9417,7 @@ class QdCheckboxesComponent {
9010
9417
  this.control = this.controlContainer.control.get(this.formControlName);
9011
9418
  }
9012
9419
  else {
9013
- console.warn('QD-UI | QdCheckboxGroupComponent - Missing FormControlName directive from host element of the component');
9420
+ console.warn('Quadrel Framework | QdCheckboxGroup - Missing FormControlName directive from host element of the component.');
9014
9421
  }
9015
9422
  }
9016
9423
  this.setInitialValues();
@@ -9604,7 +10011,7 @@ class QdFormOptionsResolverRegistry {
9604
10011
  return null;
9605
10012
  const matches = this.resolvers.filter(r => r?.name === this.resolverName);
9606
10013
  if (matches.length > 1)
9607
- throw new Error(`QD-UI | QdForms - Multiple QdFormOptionsResolvers with the name "${this.resolverName}" found. Resolver names must be unique.`);
10014
+ throw new Error(`Quadrel Framework | QdForms - Multiple QdFormOptionsResolvers with the name "${this.resolverName}" found. Resolver names must be unique.`);
9608
10015
  return matches[0] ?? null;
9609
10016
  }
9610
10017
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormOptionsResolverRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -9704,9 +10111,9 @@ class QdFormOptionsService {
9704
10111
  }
9705
10112
  validateOptionsSetup(componentName) {
9706
10113
  if (!this.hasOptions())
9707
- console.warn(`QD-UI | ${componentName} - No options defined. Either provide 'options' or configure a resolver via 'optionsResolverName'.`);
10114
+ console.warn(`Quadrel Framework | ${componentName} - No options defined. Either provide "options" or configure a resolver via "optionsResolverName".`);
9708
10115
  if (this._config?.options?.length && this._resolver)
9709
- console.warn(`QD-UI | ${componentName} - Config key 'options' ignored because QD_FORM_OPTIONS_RESOLVER is configured.`);
10116
+ console.warn(`Quadrel Framework | ${componentName} - Config key "options" ignored because QD_FORM_OPTIONS_RESOLVER is configured.`);
9710
10117
  }
9711
10118
  load(value) {
9712
10119
  if (value === this._lastLoadedValue)
@@ -10203,7 +10610,7 @@ class QdDropdownComponent {
10203
10610
  this.control = directive.control;
10204
10611
  return;
10205
10612
  }
10206
- console.warn('QD-UI | QdDropdownComponent - Missing FormControlName directive from host element of the component');
10613
+ console.warn('Quadrel Framework | QdDropdown - Missing FormControlName directive from host element of the component.');
10207
10614
  }
10208
10615
  updateConfiguration() {
10209
10616
  this.label = getLabel(this.config);
@@ -10612,8 +11019,8 @@ class QdInputOptionsDirective extends QdPopoverOnClickDirective {
10612
11019
  }
10613
11020
  logWarningIfBothOptionsAndResolverAreUsed() {
10614
11021
  if (this.config?.options && this.config.options.length > 0 && !!this._optionsResolver) {
10615
- console.warn('QD-UI | QdInputComponent - If both options and QD_FORM_OPTIONS_RESOLVER are used, ' +
10616
- 'the options will be ignored!');
11022
+ console.warn('Quadrel Framework | QdInput - If both options and QD_FORM_OPTIONS_RESOLVER are used, ' +
11023
+ 'the options will be ignored.');
10617
11024
  }
10618
11025
  }
10619
11026
  closePopover() {
@@ -10929,6 +11336,7 @@ class QdInputComponent {
10929
11336
  resolverRegistry = inject(QdFormOptionsResolverRegistry);
10930
11337
  controlContainer = inject(ControlContainer, { optional: true, host: true, skipSelf: true });
10931
11338
  eventBrokerService = inject(QdEventBrokerService, { optional: true });
11339
+ numberInputService = inject(QdNumberInputService);
10932
11340
  /**
10933
11341
  * The form control name can be assigned here if you want to use Reactive Forms.
10934
11342
  */
@@ -11003,9 +11411,13 @@ class QdInputComponent {
11003
11411
  get isErrorFromOutside() {
11004
11412
  return this.isError;
11005
11413
  }
11414
+ get isAmbiguousState() {
11415
+ return this.isAmbiguousInput;
11416
+ }
11006
11417
  inputElement;
11007
11418
  inputType;
11008
11419
  inputMode;
11420
+ htmlInputType;
11009
11421
  placeholder;
11010
11422
  label;
11011
11423
  hint;
@@ -11017,6 +11429,7 @@ class QdInputComponent {
11017
11429
  control;
11018
11430
  _optionsResolver;
11019
11431
  _subs = new Subscription();
11432
+ _isUserTyped = false;
11020
11433
  _onChange = () => { };
11021
11434
  _onTouch = () => { };
11022
11435
  get hasOnlyUnitsError() {
@@ -11025,6 +11438,15 @@ class QdInputComponent {
11025
11438
  get hasUnits() {
11026
11439
  return this.config?.units?.length > 0;
11027
11440
  }
11441
+ get ambiguityHintKey() {
11442
+ return this.numberInputService.getAmbiguityHintKey(this._value.value);
11443
+ }
11444
+ get isAmbiguousInput() {
11445
+ return (this.inputType === 'number' &&
11446
+ !this.hasError &&
11447
+ this._isUserTyped &&
11448
+ this.numberInputService.isAmbiguous(this._value.value));
11449
+ }
11028
11450
  get numberOfCharacters() {
11029
11451
  if (!this._value.value)
11030
11452
  return 0;
@@ -11041,7 +11463,10 @@ class QdInputComponent {
11041
11463
  return this.control.getMaxLengthOrUndefined();
11042
11464
  }
11043
11465
  get valueAsList() {
11044
- return [`${this._value.value}${this._value.unit ? ' ' + this._value.unit : ''}`];
11466
+ const displayValue = this.inputType === 'number'
11467
+ ? this.numberInputService.formatNumberForViewonly(this._value.value)
11468
+ : this._value.value;
11469
+ return [`${displayValue}${this._value.unit ? ' ' + this._value.unit : ''}`];
11045
11470
  }
11046
11471
  ngOnInit() {
11047
11472
  this.initializeOptionsResolver();
@@ -11051,9 +11476,14 @@ class QdInputComponent {
11051
11476
  this.control = this.controlContainer.control.get(this.formControlName);
11052
11477
  // TODO remove logic for support of angular FormControl with angular 20 update
11053
11478
  if (!(this.control instanceof QdFormControl))
11054
- console.warn('QD-UI | QdInputComponent - Please use the QdFormControl instead of the Angular FormControl');
11479
+ console.warn('Quadrel Framework | QdInput - Please use the QdFormControl instead of the Angular FormControl.');
11055
11480
  }
11056
11481
  }
11482
+ if (this.config.inputType === 'number' &&
11483
+ this.config.inputMode !== 'numeric' &&
11484
+ this.config.inputMode !== 'decimal' &&
11485
+ this.config.inputMode != null)
11486
+ console.error('QD-UI | QdInputComponent - Please use either decimal or numeric when using QdInputType number');
11057
11487
  this.writeValue(this.value ?? getValue(this.config));
11058
11488
  this.normalizeInitialControlValueIfNeeded();
11059
11489
  this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
@@ -11084,6 +11514,11 @@ class QdInputComponent {
11084
11514
  writeValue(value) {
11085
11515
  this._value = getValueWithUnit(value, this.config);
11086
11516
  this._displayValue = String(this._value.value ?? '');
11517
+ this._isUserTyped = false;
11518
+ if (this.inputType === 'number') {
11519
+ this._value = { ...this._value, value: this.numberInputService.formatValueForDisplay(this._value.value) };
11520
+ this._displayValue = String(this._value.value ?? '');
11521
+ }
11087
11522
  }
11088
11523
  setDisabledState(disabled) {
11089
11524
  this.disabled = disabled;
@@ -11095,6 +11530,36 @@ class QdInputComponent {
11095
11530
  if (input?.validity?.badInput)
11096
11531
  return;
11097
11532
  const value = event.target.value;
11533
+ if (this.inputType === 'number' && value && !this.numberInputService.isValidNumber(value)) {
11534
+ this.control?.setErrors({
11535
+ ...this.control.errors,
11536
+ invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11537
+ });
11538
+ return;
11539
+ }
11540
+ if (this.inputType === 'number' && value) {
11541
+ const valueWithoutGroups = value.split(this.numberInputService.groupSeparator).join('');
11542
+ const filtered = this.numberInputService.filterValue(valueWithoutGroups);
11543
+ const hasInvalidChars = filtered !== valueWithoutGroups;
11544
+ if (hasInvalidChars) {
11545
+ this._value = { ...this._value, value: filtered };
11546
+ if (this.control) {
11547
+ this.control.setErrors({
11548
+ ...this.control.errors,
11549
+ invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11550
+ });
11551
+ }
11552
+ this._isUserTyped = true;
11553
+ this._onTouch();
11554
+ this.emitValue();
11555
+ return;
11556
+ }
11557
+ if (this.control?.errors?.['invalidCharacters']) {
11558
+ const remainingErrors = Object.fromEntries(Object.entries(this.control.errors).filter(([key]) => key !== 'invalidCharacters'));
11559
+ this.control.setErrors(Object.keys(remainingErrors).length ? remainingErrors : null);
11560
+ }
11561
+ }
11562
+ this._isUserTyped = true;
11098
11563
  this._value = { ...this._value, value };
11099
11564
  this.emitValue();
11100
11565
  this._onTouch();
@@ -11151,6 +11616,15 @@ class QdInputComponent {
11151
11616
  updateConfig() {
11152
11617
  this.inputType = getInputType(this.config);
11153
11618
  this.inputMode = getInputMode(this.config);
11619
+ if (this.inputType === 'number') {
11620
+ this.htmlInputType = 'text';
11621
+ if (!this.inputMode) {
11622
+ this.inputMode = this.inputMode ?? 'decimal';
11623
+ }
11624
+ }
11625
+ else {
11626
+ this.htmlInputType = this.inputType;
11627
+ }
11154
11628
  this.placeholder = getPlaceholder(this.config);
11155
11629
  this.label = getLabel(this.config);
11156
11630
  this.hint = getHint(this.config);
@@ -11169,13 +11643,15 @@ class QdInputComponent {
11169
11643
  this._optionsResolver = this.resolverRegistry.findResolver();
11170
11644
  }
11171
11645
  emitValue() {
11646
+ const emittable = this.inputType === 'number' ? this.numberInputService.parseValue(this._value.value) : this._value.value;
11172
11647
  if (this.hasUnits) {
11173
- this.valueChange.emit(this._value);
11174
- this._onChange(this._value);
11648
+ const emittableWithUnit = { ...this._value, value: emittable };
11649
+ this.valueChange.emit(emittableWithUnit);
11650
+ this._onChange(emittableWithUnit);
11175
11651
  }
11176
11652
  else {
11177
- this.valueChange.emit(this._value.value);
11178
- this._onChange(this._value.value);
11653
+ this.valueChange.emit(emittable);
11654
+ this._onChange(emittable);
11179
11655
  }
11180
11656
  }
11181
11657
  initOpModeSubscription() {
@@ -11198,9 +11674,13 @@ class QdInputComponent {
11198
11674
  if (!isEqual(modelValue, target))
11199
11675
  this.control.setValue(target, { emitEvent: false });
11200
11676
  this._value = normalized;
11677
+ if (this.inputType === 'number') {
11678
+ this._value = { ...this._value, value: this.numberInputService.formatValueForDisplay(this._value.value) };
11679
+ this._displayValue = String(this._value.value ?? '');
11680
+ }
11201
11681
  }
11202
11682
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11203
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdInputComponent, isStandalone: false, selector: "qd-input", inputs: { formControlName: "formControlName", value: "value", config: "config", isError: "isError", testId: ["data-test-id", "testId"] }, outputs: { valueChange: "valueChange", enterClick: "enterClick", clickClear: "clickClear", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly" }, host: { properties: { "class.qd-input-readonly": "this.readonly", "class.qd-input--readonly-action": "this.readonlyAction", "class.qd-input-viewonly": "this.viewonly", "class.qd-input--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-input-hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-input-disabled": "this.disabled", "class.qd-input-focus": "this.isInputFocused", "class.qd-form-error": "this.hasError", "class.qd-input-error": "this.hasError", "class.qd-input-error-from-outside": "this.isErrorFromOutside" } }, providers: [
11683
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdInputComponent, isStandalone: false, selector: "qd-input", inputs: { formControlName: "formControlName", value: "value", config: "config", isError: "isError", testId: ["data-test-id", "testId"] }, outputs: { valueChange: "valueChange", enterClick: "enterClick", clickClear: "clickClear", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly" }, host: { properties: { "class.qd-input-readonly": "this.readonly", "class.qd-input--readonly-action": "this.readonlyAction", "class.qd-input-viewonly": "this.viewonly", "class.qd-input--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-input-hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-input-disabled": "this.disabled", "class.qd-input-focus": "this.isInputFocused", "class.qd-form-error": "this.hasError", "class.qd-input-error": "this.hasError", "class.qd-input-error-from-outside": "this.isErrorFromOutside", "class.qd-input-ambiguous": "this.isAmbiguousState" } }, providers: [
11204
11684
  {
11205
11685
  provide: NG_VALUE_ACCESSOR,
11206
11686
  useExisting: QdInputComponent,
@@ -11208,13 +11688,14 @@ class QdInputComponent {
11208
11688
  },
11209
11689
  QdFormsActionEmitterService,
11210
11690
  QdFormOptionsResolverRegistry,
11691
+ QdNumberInputService,
11211
11692
  // TODO: Remove when removing derived directive
11212
11693
  QdPopoverSizingService,
11213
11694
  {
11214
11695
  provide: QD_FOCUSABLE_TOKEN,
11215
11696
  useExisting: QdInputComponent
11216
11697
  }
11217
- ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], 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<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"], dependencies: [{ 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: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { 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: QdInputUnitsComponent, selector: "qd-input-units", inputs: ["config", "unit"], outputs: ["unitChange", "opened", "closed"] }, { kind: "directive", type: QdInputOptionsDirective, selector: "[qdInputOptions]", inputs: ["value", "config"], outputs: ["enterClick", "optionSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
11698
+ ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], 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<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n <qd-form-hint *ngIf=\"isAmbiguousInput\" [hint]=\"ambiguityHintKey\" [data-test-id]=\"testId\"></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n <qd-form-hint *ngIf=\"isAmbiguousInput\" [hint]=\"ambiguityHintKey\" [data-test-id]=\"testId\"></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"htmlInputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"isAmbiguousInput\" class=\"qd-input-ambiguous-icon\" icon=\"circleInfoSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-ambiguous .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(0,102,153)}:host.qd-input-ambiguous .qd-input-input:hover,:host.qd-input-ambiguous .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153)}:host.qd-input-ambiguous.qd-input-focus .qd-input-input{border-color:#069}:host.qd-input-ambiguous .qd-input-suffix ::ng-deep .qd-input-ambiguous-icon{padding-right:.5rem;color:#069}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"], dependencies: [{ 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: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { 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: QdInputUnitsComponent, selector: "qd-input-units", inputs: ["config", "unit"], outputs: ["unitChange", "opened", "closed"] }, { kind: "directive", type: QdInputOptionsDirective, selector: "[qdInputOptions]", inputs: ["value", "config"], outputs: ["enterClick", "optionSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
11218
11699
  }
11219
11700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, decorators: [{
11220
11701
  type: Component,
@@ -11226,13 +11707,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11226
11707
  },
11227
11708
  QdFormsActionEmitterService,
11228
11709
  QdFormOptionsResolverRegistry,
11710
+ QdNumberInputService,
11229
11711
  // TODO: Remove when removing derived directive
11230
11712
  QdPopoverSizingService,
11231
11713
  {
11232
11714
  provide: QD_FOCUSABLE_TOKEN,
11233
11715
  useExisting: QdInputComponent
11234
11716
  }
11235
- ], 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<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"] }]
11717
+ ], 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<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n <qd-form-hint *ngIf=\"isAmbiguousInput\" [hint]=\"ambiguityHintKey\" [data-test-id]=\"testId\"></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n <qd-form-hint *ngIf=\"isAmbiguousInput\" [hint]=\"ambiguityHintKey\" [data-test-id]=\"testId\"></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"htmlInputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"isAmbiguousInput\" class=\"qd-input-ambiguous-icon\" icon=\"circleInfoSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-ambiguous .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(0,102,153)}:host.qd-input-ambiguous .qd-input-input:hover,:host.qd-input-ambiguous .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153)}:host.qd-input-ambiguous.qd-input-focus .qd-input-input{border-color:#069}:host.qd-input-ambiguous .qd-input-suffix ::ng-deep .qd-input-ambiguous-icon{padding-right:.5rem;color:#069}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"] }]
11236
11718
  }], propDecorators: { formControlName: [{
11237
11719
  type: Input
11238
11720
  }], value: [{
@@ -11292,6 +11774,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11292
11774
  }], isErrorFromOutside: [{
11293
11775
  type: HostBinding,
11294
11776
  args: ['class.qd-input-error-from-outside']
11777
+ }], isAmbiguousState: [{
11778
+ type: HostBinding,
11779
+ args: ['class.qd-input-ambiguous']
11295
11780
  }], inputElement: [{
11296
11781
  type: ViewChild,
11297
11782
  args: ['input']
@@ -11418,6 +11903,8 @@ class QdDatepickerComponent {
11418
11903
  timePicker;
11419
11904
  _disabledDatesValidator;
11420
11905
  _disabledTimesValidator;
11906
+ _boundDisabledDates;
11907
+ _boundDisabledTimes;
11421
11908
  _subs = new Subscription();
11422
11909
  _onChange = () => { };
11423
11910
  _onTouched = () => { };
@@ -11429,17 +11916,17 @@ class QdDatepickerComponent {
11429
11916
  this.updateConfiguration();
11430
11917
  this.updateDisplayedDate();
11431
11918
  this.updateDisplayedDateTime();
11432
- this.validateDisabledDates();
11433
- this.validateDisabledTimes();
11434
11919
  this._subs.add(this.initOpModeSubscription());
11435
11920
  }
11436
11921
  ngOnChanges(changes) {
11437
11922
  if (changes.config) {
11438
11923
  this.updateConfiguration();
11439
- this.validateDisabledDates();
11440
- this.validateDisabledTimes();
11441
11924
  }
11442
11925
  }
11926
+ ngDoCheck() {
11927
+ this.rebindDisabledDatesValidatorIfChanged();
11928
+ this.rebindDisabledTimesValidatorIfChanged();
11929
+ }
11443
11930
  ngOnDestroy() {
11444
11931
  this._subs.unsubscribe();
11445
11932
  }
@@ -11576,7 +12063,7 @@ class QdDatepickerComponent {
11576
12063
  this.control = this.controlContainer.control.get(this.formControlName);
11577
12064
  }
11578
12065
  else {
11579
- console.warn('QD-UI | QdDatepickerComponent - Missing FormControlName directive from host element of the component');
12066
+ console.warn('Quadrel Framework | QdDatepicker - Missing FormControlName directive from host element of the component.');
11580
12067
  }
11581
12068
  }
11582
12069
  initInnerControl() {
@@ -11610,6 +12097,20 @@ class QdDatepickerComponent {
11610
12097
  this.displayedDateTime = QdDateAdapter.formatToDateTimeLocaleString(currentValue, this.config?.enableSeconds);
11611
12098
  this.displayedTime = QdDateAdapter.formatToTimeLocaleString(currentValue, this.config?.enableSeconds);
11612
12099
  }
12100
+ rebindDisabledDatesValidatorIfChanged() {
12101
+ const current = this.config?.disabledDates;
12102
+ if (current === this._boundDisabledDates)
12103
+ return;
12104
+ this._boundDisabledDates = current;
12105
+ this.validateDisabledDates();
12106
+ }
12107
+ rebindDisabledTimesValidatorIfChanged() {
12108
+ const current = this.config?.timePicker?.disabledTimes;
12109
+ if (current === this._boundDisabledTimes)
12110
+ return;
12111
+ this._boundDisabledTimes = current;
12112
+ this.validateDisabledTimes();
12113
+ }
11613
12114
  validateDisabledDates() {
11614
12115
  if (!this.control)
11615
12116
  return;
@@ -12147,7 +12648,7 @@ class QdTranslateService {
12147
12648
  else if (translatable.translation) {
12148
12649
  translation = translatable.translation[this.translateService.currentLang || 'de'];
12149
12650
  if (translation === undefined) {
12150
- console.error(`Language "${this.translateService.currentLang}" is not implemented!`);
12651
+ console.error(`Quadrel Framework | QdTranslate - Language "${this.translateService.currentLang}" is not implemented.`);
12151
12652
  }
12152
12653
  }
12153
12654
  return translation || '';
@@ -12732,21 +13233,7 @@ function removeListItem(list, el) {
12732
13233
  if (index > -1)
12733
13234
  list.splice(index, 1);
12734
13235
  }
12735
- const validatorsDroppedWithOptsWarning = `
12736
- It looks like you're constructing using a QdFormControl with both an options argument and an
12737
- validators argument. Mixing these arguments will cause your validators in the argument to be dropped.
12738
- You should either put all your validators in the options object, or in separate validators
12739
- arguments. For example:
12740
-
12741
- // Using validators arguments
12742
- fc = new QdFormControl(42, Validators.required, myAsyncValidator);
12743
-
12744
- // Using AbstractControlOptions
12745
- fc = new QdFormControl(42, {validators: Validators.required, asyncValidators: myAV});
12746
-
12747
- // Do NOT mix them: validators in additional argument will be dropped!
12748
- fc = new QdFormControl(42, {validators: Validators.required}, /* Oops! */ myAsyncValidator);
12749
- `;
13236
+ const validatorsDroppedWithOptsWarning = 'Quadrel Framework | QdForms - QdFormControl received both an options object and a separate validators argument. The standalone validators argument is dropped. Pass all validators inside the options object or via the separate arguments, not both.';
12750
13237
 
12751
13238
  function hasUnit(control) {
12752
13239
  return control.value?.value != null && control.value?.unit != null;
@@ -13113,7 +13600,7 @@ class QdMultiInputComponent {
13113
13600
  * TODO remove logic for support of [formControlName] directive and FormControl with angular 14 update
13114
13601
  */
13115
13602
  set formControlName(formControlName) {
13116
- console.warn('QD-UI | QdMultiInputComponent - Please use the MultiInput with the QdFormArray form control and the [formArrayName] directive!');
13603
+ console.warn('Quadrel Framework | QdMultiInput - Please use <qd-multi-input> with the QdFormArray form control and the [formArrayName] directive.');
13117
13604
  this._formControlName = formControlName;
13118
13605
  }
13119
13606
  get formControlName() {
@@ -13223,7 +13710,7 @@ class QdMultiInputComponent {
13223
13710
  if (this.formArrayName) {
13224
13711
  const formArray = this.controlContainer.control.get(this.formArrayName);
13225
13712
  if (!formArray) {
13226
- console.warn('QD-UI | QdMultiInputComponent - No form control found for the provided [formArrayName]', this.formArrayName);
13713
+ console.warn('Quadrel Framework | QdMultiInput - No form control found for the provided [formArrayName]', this.formArrayName);
13227
13714
  return;
13228
13715
  }
13229
13716
  // Updating form array programmatically from outside
@@ -13242,7 +13729,7 @@ class QdMultiInputComponent {
13242
13729
  else {
13243
13730
  // TODO remove logic for support of Angular FormControl with angular 19 update
13244
13731
  this.formArray = this.qdFormArrayFactoryService.createQdFormArrayFromFormControl(formArray);
13245
- console.warn('QD-UI | QdMultiInputComponent - Please use the MultiInput with the QdFormArray form control!');
13732
+ console.warn('Quadrel Framework | QdMultiInput - Please use <qd-multi-input> with the QdFormArray form control.');
13246
13733
  }
13247
13734
  this.disabled = formArray.disabled;
13248
13735
  this._onDisabledChange = (disabled) => {
@@ -13251,7 +13738,7 @@ class QdMultiInputComponent {
13251
13738
  this.formArray.registerOnDisabledChange(this._onDisabledChange);
13252
13739
  }
13253
13740
  else {
13254
- console.warn('QD-UI | QdMultiInputComponent - Missing [formArrayName] directive from host element of the component');
13741
+ console.warn('Quadrel Framework | QdMultiInput - Missing [formArrayName] directive from host element of the component.');
13255
13742
  }
13256
13743
  }
13257
13744
  ngOnChanges(changes) {
@@ -13777,7 +14264,7 @@ class QdPinCodeComponent {
13777
14264
  this.control = this.controlContainer.control.get(this.formControlName);
13778
14265
  }
13779
14266
  else {
13780
- console.warn('QD-UI | QdPinCodeComponent - Missing FormControlName directive from host element of the component');
14267
+ console.warn('Quadrel Framework | QdPinCode - Missing FormControlName directive from host element of the component.');
13781
14268
  }
13782
14269
  }
13783
14270
  this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
@@ -14237,7 +14724,7 @@ class QdRadioButtonsComponent {
14237
14724
  this.control = this.controlContainer.control.get(this.formControlName);
14238
14725
  }
14239
14726
  else {
14240
- console.warn('QD-UI | QdRadioButtonsComponent - Missing FormControlName directive from host element of the component');
14727
+ console.warn('Quadrel Framework | QdRadioButtons - Missing FormControlName directive from host element of the component.');
14241
14728
  }
14242
14729
  }
14243
14730
  this.initRadioButtonList();
@@ -14642,7 +15129,7 @@ class QdRichtextComponent {
14642
15129
  this.control = this.controlContainer.control?.get(this.formControlName) ?? undefined;
14643
15130
  }
14644
15131
  else {
14645
- console.warn('QD-UI | QdSwitchesComponent - Missing FormControlName directive from host element of the component');
15132
+ console.warn('Quadrel Framework | QdSwitches - Missing FormControlName directive from host element of the component.');
14646
15133
  }
14647
15134
  }
14648
15135
  this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
@@ -14967,7 +15454,7 @@ class QdSwitchesComponent {
14967
15454
  this.control = this.controlContainer.control.get(this.formControlName);
14968
15455
  }
14969
15456
  else {
14970
- console.warn('QD-UI | QdSwitchesComponent - Missing FormControlName directive from host element of the component');
15457
+ console.warn('Quadrel Framework | QdSwitches - Missing FormControlName directive from host element of the component.');
14971
15458
  }
14972
15459
  }
14973
15460
  this.switchesService.setList(this.options);
@@ -15235,11 +15722,11 @@ class QdTextareaComponent {
15235
15722
  this.control = this.controlContainer.control.get(this.formControlName);
15236
15723
  // TODO remove logic for support of angular FormControl with angular 18 update
15237
15724
  if (!(this.control instanceof QdFormControl)) {
15238
- console.warn('QD-UI | QdTextareaComponent - Please use the QdFormControl instead of the Angular FormControl');
15725
+ console.warn('Quadrel Framework | QdTextarea - Please use the QdFormControl instead of the Angular FormControl.');
15239
15726
  }
15240
15727
  }
15241
15728
  else {
15242
- console.warn('QD-UI | QdTextareaComponent - Missing FormControlName directive from host element of the component');
15729
+ console.warn('Quadrel Framework | QdTextarea - Missing FormControlName directive from host element of the component.');
15243
15730
  }
15244
15731
  }
15245
15732
  this.valueForView = this.value || getValue(this.config);
@@ -16296,7 +16783,7 @@ class QdButtonStackButtonComponent {
16296
16783
  ngOnInit() {
16297
16784
  // TODO: Delete directive "qd-button-stack" in Version 15
16298
16785
  if (this._elementRef.nativeElement.attributes.hasOwnProperty('qd-button-stack')) {
16299
- console.warn('QD-UI | QdButtonStack - The directive "qd-button-stack" is deprecated. Please use "qdButtonStack" instead.');
16786
+ console.warn('Quadrel Framework | QdButtonStack - The directive "qd-button-stack" is deprecated. Please use "qdButtonStack" instead.');
16300
16787
  }
16301
16788
  }
16302
16789
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdButtonStackButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -16389,7 +16876,7 @@ class QdMenuButtonComponent {
16389
16876
  }
16390
16877
  ngOnInit() {
16391
16878
  if (!this.config)
16392
- console.error('QD-UI | QdMenuButtonComponent - Please provide a valid config.');
16879
+ console.error('Quadrel Framework | QdMenuButton - Please provide a valid config.');
16393
16880
  }
16394
16881
  hasUnhiddenActions() {
16395
16882
  return this.config?.actions?.some(action => !action.isHidden) ?? false;
@@ -16648,7 +17135,7 @@ class QdColumnAutoFillDirective {
16648
17135
  }
16649
17136
  }
16650
17137
  logErrorMessage(message) {
16651
- console.error(`${QdColumnAutoFillDirective.name} | ${message}`);
17138
+ console.error(`Quadrel Framework | QdColumnAutoFill - ${message}`);
16652
17139
  }
16653
17140
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnAutoFillDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
16654
17141
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnAutoFillDirective, isStandalone: false, selector: "[qdColumnAutoFill]", ngImport: i0 });
@@ -16697,7 +17184,7 @@ class QdColumnsDisableAutoFillDirective {
16697
17184
  }
16698
17185
  }
16699
17186
  logErrorMessage(message) {
16700
- console.error(`${QdColumnsDisableAutoFillDirective.name} | ${message}`);
17187
+ console.error(`Quadrel Framework | QdColumnsDisableAutoFill - ${message}`);
16701
17188
  }
16702
17189
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnsDisableAutoFillDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
16703
17190
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnsDisableAutoFillDirective, isStandalone: false, selector: "[qdColumnsDisableAutoFill]", ngImport: i0 });
@@ -16971,7 +17458,7 @@ class QdColumnDisableResponsiveColspansDirective {
16971
17458
  }
16972
17459
  }
16973
17460
  logErrorMessage(message) {
16974
- console.error(`${QdColumnDisableResponsiveColspansDirective.name} | ${message}`);
17461
+ console.error(`Quadrel Framework | QdColumnDisableResponsiveColspans - ${message}`);
16975
17462
  }
16976
17463
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnDisableResponsiveColspansDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
16977
17464
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnDisableResponsiveColspansDirective, isStandalone: false, selector: "[qdColumnDisableResponsiveColspans]", ngImport: i0 });
@@ -17030,7 +17517,7 @@ class QdColumnsMaxDirective {
17030
17517
  }
17031
17518
  }
17032
17519
  logErrorMessage(message) {
17033
- console.error(`${QdColumnsMaxDirective.name} | ${message}`);
17520
+ console.error(`Quadrel Framework | QdColumnsMax - ${message}`);
17034
17521
  }
17035
17522
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnsMaxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17036
17523
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnsMaxDirective, isStandalone: false, selector: "[qdColumnsMax]", inputs: { qdColumnsMax: "qdColumnsMax" }, ngImport: i0 });
@@ -17197,7 +17684,7 @@ class QdColumnBreakBeforeDirective {
17197
17684
  }
17198
17685
  }
17199
17686
  logErrorMessage(message) {
17200
- console.error(`${QdColumnBreakBeforeDirective.name} | ${message}`);
17687
+ console.error(`Quadrel Framework | QdColumnBreakBefore - ${message}`);
17201
17688
  }
17202
17689
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnBreakBeforeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17203
17690
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnBreakBeforeDirective, isStandalone: false, selector: "[qdColumnBreakBefore]", ngImport: i0 });
@@ -17248,7 +17735,7 @@ class QdColumnNextInSameRowDirective {
17248
17735
  }
17249
17736
  if (!nextSiblingColspan) {
17250
17737
  this.logErrorMessage('The next sibling of the element marked with qdColumnNextInSameRow ' +
17251
- 'has to be an element with a qdColumn directive!');
17738
+ 'has to be an element with a qdColumn directive.');
17252
17739
  }
17253
17740
  if (nextSiblingColspan) {
17254
17741
  this._renderer.addClass(this.element, QdColumnNextInSameRowDirective.className);
@@ -17270,7 +17757,7 @@ class QdColumnNextInSameRowDirective {
17270
17757
  return QdColumnDirective.getQdColumnColspan(nextSibling);
17271
17758
  }
17272
17759
  logErrorMessage(message) {
17273
- console.error(`${QdColumnNextInSameRowDirective.name} | ${message}`);
17760
+ console.error(`Quadrel Framework | QdColumnNextInSameRow - ${message}`);
17274
17761
  }
17275
17762
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnNextInSameRowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17276
17763
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnNextInSameRowDirective, isStandalone: false, selector: "[qdColumnNextInSameRow]", ngImport: i0 });
@@ -17320,7 +17807,7 @@ class QdColumnFullGridWidthDirective {
17320
17807
  }
17321
17808
  }
17322
17809
  logErrorMessage(message) {
17323
- console.error(`${QdColumnFullGridWidthDirective.name} | ${message}`);
17810
+ console.error(`Quadrel Framework | QdColumnFullGridWidth - ${message}`);
17324
17811
  }
17325
17812
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnFullGridWidthDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17326
17813
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnFullGridWidthDirective, isStandalone: false, selector: "[qdColumnFullGridWidth]", ngImport: i0 });
@@ -17368,7 +17855,7 @@ class QdColumnsDisableResponsiveColspansDirective {
17368
17855
  }
17369
17856
  }
17370
17857
  logErrorMessage(message) {
17371
- console.error(`${QdColumnsDisableResponsiveColspansDirective.name} | ${message}`);
17858
+ console.error(`Quadrel Framework | QdColumnsDisableResponsiveColspans - ${message}`);
17372
17859
  }
17373
17860
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdColumnsDisableResponsiveColspansDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17374
17861
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdColumnsDisableResponsiveColspansDirective, isStandalone: false, selector: "[qdColumnsDisableResponsiveColspans]", ngImport: i0 });
@@ -18166,7 +18653,7 @@ class QdPendingChangesGuardDirective {
18166
18653
  formGroup;
18167
18654
  constructor() {
18168
18655
  if (!this.ngForm && !this.formGroupDirective) {
18169
- console.error('QD-UI | QdPendingChangesGuardDirective - requires NgForm or FormGroupDirective to be present on the host element.');
18656
+ console.error('Quadrel Framework | QdPendingChangesGuard - requires NgForm or FormGroupDirective to be present on the host element.');
18170
18657
  }
18171
18658
  }
18172
18659
  ngOnInit() {
@@ -19341,7 +19828,7 @@ class QdFileCollectorComponent {
19341
19828
  isEqual$1(config.allowedFileNamePattern, this.fileTypeService.getFileNamePattern(config.allowedFileTypes)));
19342
19829
  }
19343
19830
  logError(message) {
19344
- console.error(`QD-UI | QdFileCollector - ${message}`);
19831
+ console.error(`Quadrel Framework | QdFileCollector - ${message}`);
19345
19832
  }
19346
19833
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19347
19834
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorComponent, isStandalone: false, selector: "qd-file-collector", inputs: { config: "config", testId: ["data-test-id", "testId"] }, providers: [QdFileCollectorService, QdFileCollectorValidationService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n *ngIf=\"canShowAddButton\"\n (click)=\"clickFileInput()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n>\n {{ config?.standaloneAddNewLabel?.i18n || \"i18n.qd.fileCollector.standalone.addNew\" | translate }}\n</button>\n\n<input\n [disabled]=\"config?.readonly || config?.viewonly\"\n type=\"file\"\n (change)=\"handleFiles($event)\"\n #fileInput\n hidden\n multiple=\"multiple\"\n/>\n\n<qd-file-collector-allowed-files-description\n *ngIf=\"!config?.readonly && !config?.viewonly\"\n [attr.data-test-id]=\"testId + '-allowed-files-description'\"\n></qd-file-collector-allowed-files-description>\n\n<ng-container *ngFor=\"let fileUpload of this.fileUploads; let i = index\">\n <qd-file-collector-item\n *ngIf=\"!fileUpload.error && fileUpload.progress === 100\"\n [progress]=\"fileUpload.progress\"\n [newlyUploaded]=\"fileUpload.newlyUploaded\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [readonly]=\"config?.readonly\"\n [viewonly]=\"config?.viewonly\"\n [downloadFilesWithHttpClient]=\"config?.downloadFilesWithHttpClient\"\n [data-test-id]=\"testId + '-item-' + i\"\n ></qd-file-collector-item>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column}:host>.qd-button{align-self:end;margin-bottom:1.5rem}\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: 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: QdFileCollectorAllowedFilesDescriptionComponent, selector: "qd-file-collector-allowed-files-description" }, { kind: "component", type: QdFileCollectorItemComponent, selector: "qd-file-collector-item", inputs: ["progress", "newlyUploaded", "collectedFile", "error", "readonly", "viewonly", "downloadFilesWithHttpClient", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
@@ -19582,7 +20069,7 @@ function resetCategoryFilter$1(state, categoryIndex) {
19582
20069
  const isIsoTimestampValid = (isoTimestamp) => {
19583
20070
  const valid = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d((:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|([+-][0-2]\d:[0-5]\d|Z))/).test(isoTimestamp);
19584
20071
  if (!valid && isoTimestamp !== '') {
19585
- console.warn('QD-UI | QdFilterService - The given ISO 8601 date string is not valid.');
20072
+ console.warn('Quadrel Framework | QdFilter - The given ISO 8601 date string is not valid.');
19586
20073
  }
19587
20074
  return valid;
19588
20075
  };
@@ -19694,7 +20181,7 @@ function validateFilterSelection(filterSelection, filterCategories, selectionSou
19694
20181
  Object.keys(filterSelection).forEach(selectionCategory => {
19695
20182
  const categoryInFilter = filterCategories.find(category => category.category === selectionCategory);
19696
20183
  if (!categoryInFilter) {
19697
- console.warn(`The category "${selectionCategory}" that is given in the ${selectionSource} is not part of the filter!`);
20184
+ console.warn(`Quadrel Framework | QdFilter - The category "${selectionCategory}" that is given in the ${selectionSource} is not part of the filter.`);
19698
20185
  return;
19699
20186
  }
19700
20187
  switch (categoryInFilter.type) {
@@ -19704,8 +20191,8 @@ function validateFilterSelection(filterSelection, filterCategories, selectionSou
19704
20191
  const items = categoryInFilter.items;
19705
20192
  filterSelection[selectionCategory].forEach(selectionItem => {
19706
20193
  if (!items.some(item => item.item === selectionItem)) {
19707
- console.warn(`The item "${selectionItem}" that is given in the ${selectionSource} ` +
19708
- `is not contained in the filter category "${selectionCategory}"!`);
20194
+ console.warn(`Quadrel Framework | QdFilter - The item "${selectionItem}" that is given in the ${selectionSource} ` +
20195
+ `is not contained in the filter category "${selectionCategory}".`);
19709
20196
  }
19710
20197
  });
19711
20198
  break;
@@ -19715,7 +20202,7 @@ function validateFilterSelection(filterSelection, filterCategories, selectionSou
19715
20202
  case 'dateTimeRange':
19716
20203
  filterSelection[selectionCategory].forEach((selectionItem, itemIndex) => {
19717
20204
  if (selectionItem !== '' && isNaN(Date.parse(selectionItem))) {
19718
- console.error(`The given ${selectionSource} contains an invalid date for the category "${selectionCategory}"!`);
20205
+ console.error(`Quadrel Framework | QdFilter - The given ${selectionSource} contains an invalid date for the category "${selectionCategory}".`);
19719
20206
  filterSelection[selectionCategory][itemIndex] = '';
19720
20207
  }
19721
20208
  });
@@ -19727,7 +20214,7 @@ function validateFilterSelection(filterSelection, filterCategories, selectionSou
19727
20214
  const initialState$2 = {};
19728
20215
  const _filterReducer = createReducer(initialState$2, on(QdFilterActions.initFilterState, (state, { filterId, filterData }) => {
19729
20216
  if (filterData === undefined || filterData.categories.length === 0) {
19730
- console.warn('QD-UI | QdFilterService - The filterData input is invalid. To use this input, please read the documentation.');
20217
+ console.warn('Quadrel Framework | QdFilter - The "filterData" input is invalid. To use this input, please read the documentation.');
19731
20218
  return state;
19732
20219
  }
19733
20220
  return updateStateWithNewFilter(state, filterId, createFilterState(filterData));
@@ -19767,7 +20254,7 @@ const _filterReducer = createReducer(initialState$2, on(QdFilterActions.initFilt
19767
20254
  }), on(QdFilterActions.updateCategoryTranslation, (state, { filterId, filterData }) => {
19768
20255
  const newFilter = getNewFilter(state, filterId);
19769
20256
  if (filterData === undefined || filterData.categories.length === 0) {
19770
- console.warn('QD-UI | QdFilterService - The filterData input is invalid. To use this input, please read the documentation.');
20257
+ console.warn('Quadrel Framework | QdFilter - The "filterData" input is invalid. To use this input, please read the documentation.');
19771
20258
  return state;
19772
20259
  }
19773
20260
  newFilter.categories.forEach((_category, i) => {
@@ -20963,7 +21450,7 @@ class QdFilterRouterConnectorService {
20963
21450
  return of(false);
20964
21451
  }
20965
21452
  if (this._connectedFilter) {
20966
- console.error('QdUi | QdFilterComponent | More than one filter with enabled connectWithRouter config is not allowed! ' +
21453
+ console.error('Quadrel Framework | QdFilter - More than one filter with enabled "connectWithRouter" config is not allowed. ' +
20967
21454
  'Please set connectWithRouter to false except for one filter.');
20968
21455
  return of(false);
20969
21456
  }
@@ -21251,7 +21738,7 @@ class QdFilterComponent {
21251
21738
  }
21252
21739
  validateConfig() {
21253
21740
  if (this.filterData?.outputLegacyQueryStringFormat !== false && this.queryStringOutput.observers.length > 0) {
21254
- console.warn('QdFilter | You use the queryStringOutput with the legacy format. To use the new format please set outputLegacyQueryStringFormat to false. The legacy format will be removed in future releases.');
21741
+ console.warn('Quadrel Framework | QdFilter - You use the "queryStringOutput" with the legacy format. To use the new format please set "outputLegacyQueryStringFormat" to false. The legacy format will be removed in future releases.');
21255
21742
  }
21256
21743
  }
21257
21744
  init() {
@@ -21938,9 +22425,9 @@ class NavigationTileComponent {
21938
22425
  }
21939
22426
  validate() {
21940
22427
  if (!this.title)
21941
- console.error('QdUi | Navigation Tiles | You should provide a title.');
22428
+ console.error('Quadrel Framework | QdNavigationTile - You should provide a title.');
21942
22429
  if (!this.icon)
21943
- console.error('QdUi | Navigation Tiles | You should provide an icon.');
22430
+ console.error('Quadrel Framework | QdNavigationTile - You should provide an icon.');
21944
22431
  }
21945
22432
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NavigationTileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21946
22433
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: NavigationTileComponent, isStandalone: false, selector: "a[qd-navigation-tile]", inputs: { title: "title", icon: "icon" }, ngImport: i0, template: "<qd-icon *ngIf=\"icon\" [icon]=\"icon\"></qd-icon>\n<small>{{ title | translate }}</small>\n", styles: [":host{display:block;height:10rem;align-items:unset;padding:.75rem;border:1px solid rgb(213,213,213);background-color:#fff;color:unset;line-height:unset;text-align:unset;text-decoration:unset}qd-icon{display:block;margin-bottom:2.8125rem;font-size:2rem}small{color:#171717;font-size:14px;font-weight:500;line-height:20px;text-wrap:normal}@media (min-width: 1280px){small{font-size:1rem}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
@@ -22038,7 +22525,7 @@ class QdSearchRouterConnectorService {
22038
22525
  return of(false);
22039
22526
  }
22040
22527
  if (this._connectedSearch) {
22041
- console.error('QdUi | QdSearchComponent | More than one search with enabled connectWithRouter config is not allowed! ' +
22528
+ console.error('Quadrel Framework | QdSearch - More than one search with enabled "connectWithRouter" config is not allowed. ' +
22042
22529
  'Please set connectWithRouter to false except for one search.');
22043
22530
  return of(false);
22044
22531
  }
@@ -22493,7 +22980,7 @@ class QdContextService {
22493
22980
  setValue(contextId, selection) {
22494
22981
  const index = this._configuredContexts.value.findIndex(context => context.id === contextId);
22495
22982
  if (index < 0)
22496
- throw new Error(`QdUi | QdContextService - Cannot set value of unconfigured context ${contextId}`);
22983
+ throw new Error(`Quadrel Framework | QdContext - Cannot set value of unconfigured context ${contextId}`);
22497
22984
  this._values.next([
22498
22985
  ...this._values.value.filter(value => value.contextId !== contextId),
22499
22986
  { contextId, value: selection }
@@ -22718,6 +23205,9 @@ class QdTableStoreSelectorService {
22718
23205
  return sort.find(entry => entry.column === column)?.direction ?? QdSortDirection.NONE;
22719
23206
  });
22720
23207
  }
23208
+ tableSort() {
23209
+ return createSelector(this.selectTables, tables => this.getTable(tables)?.sort);
23210
+ }
22721
23211
  selectIsLoading() {
22722
23212
  return createSelector(this.selectTables, tables => {
22723
23213
  const { requestState } = this.getTable(tables) || {};
@@ -22904,6 +23394,9 @@ class QdTableStoreService {
22904
23394
  columnSortDirection$(column) {
22905
23395
  return this.store.select(this.tableStoreSelectorService.columnSortDirection(column));
22906
23396
  }
23397
+ tableSort$() {
23398
+ return this.store.select(this.tableStoreSelectorService.tableSort());
23399
+ }
22907
23400
  selectIsLoading$() {
22908
23401
  return this.store.select(this.tableStoreSelectorService.selectIsLoading());
22909
23402
  }
@@ -23131,7 +23624,7 @@ class QdTableResolverService {
23131
23624
  refresh(resolverOptions = {}) {
23132
23625
  const resolver = this.tableDataResolver;
23133
23626
  if (!resolver)
23134
- return console.warn('QD-UI | QdTable - Refresh skipped: resolver not provided.');
23627
+ return console.warn('Quadrel Framework | QdTable - Refresh skipped: resolver not provided.');
23135
23628
  const { pageIndex } = resolverOptions;
23136
23629
  if (this._refreshSubscription)
23137
23630
  this._refreshSubscription.unsubscribe();
@@ -23255,7 +23748,7 @@ class QdTableResponsiveRowService {
23255
23748
  const maxCurrentColumns = this.columnMapping[this._currentBreakpoint];
23256
23749
  let columnsDefinitions = this._config.columns.map(column => column.column);
23257
23750
  if (this.mainColumnIndex >= maxCurrentColumns) {
23258
- console.warn('QD-UI | QdTableComponent - The index of the "mainColumn" cannot be equal or greater than maximum columns for this breakpoint.');
23751
+ console.warn('Quadrel Framework | QdTable - The index of the "mainColumn" cannot be equal or greater than maximum columns for this breakpoint.');
23259
23752
  return columnsDefinitions;
23260
23753
  }
23261
23754
  if (maxCurrentColumns >= columnsLength)
@@ -23374,6 +23867,130 @@ var QdPaginatorDirection;
23374
23867
  QdPaginatorDirection[QdPaginatorDirection["LastPage"] = 3] = "LastPage";
23375
23868
  })(QdPaginatorDirection || (QdPaginatorDirection = {}));
23376
23869
 
23870
+ const PAGE_PARAM_NAME = 'page';
23871
+ const SIZE_PARAM_NAME = 'size';
23872
+ const OWNED_PARAMS$1 = [PAGE_PARAM_NAME, SIZE_PARAM_NAME];
23873
+ const SIZE_SANITY_MAX = 1000;
23874
+ class QdTablePaginationRouterConnectorService {
23875
+ hub = inject(QdRouterQueryParamHubService);
23876
+ destroyRef = inject(DestroyRef);
23877
+ _connection;
23878
+ _readSubscription;
23879
+ _writeSubscription;
23880
+ _activatedRouteCheckedSubject = new ReplaySubject(1);
23881
+ _activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
23882
+ _hasInitialUrlBeenSet = false;
23883
+ constructor() {
23884
+ this.destroyRef.onDestroy(() => {
23885
+ this.tearDownConnection();
23886
+ this.hub.release(OWNED_PARAMS$1, this);
23887
+ });
23888
+ }
23889
+ connectPaginationWithRouter(paginator, tableStoreService) {
23890
+ if (!paginator.shouldConnectWithRouter() || !this.hub.isAvailable())
23891
+ return of(false);
23892
+ if (!this.hub.claim(OWNED_PARAMS$1, this))
23893
+ return of(false);
23894
+ this._connection = {
23895
+ paginator: paginator,
23896
+ tableStoreService: tableStoreService
23897
+ };
23898
+ this._hasInitialUrlBeenSet = false;
23899
+ this._activatedRouteCheckedSubject = new ReplaySubject(1);
23900
+ this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
23901
+ this.subscribeToUrlChanges();
23902
+ this.subscribeToStoreChanges();
23903
+ return this._activatedRouteChecked$;
23904
+ }
23905
+ disconnectPaginationFromRouter(paginator) {
23906
+ if (this._connection?.paginator !== paginator)
23907
+ return;
23908
+ this.tearDownConnection();
23909
+ this.hub.release(OWNED_PARAMS$1, this);
23910
+ }
23911
+ tearDownConnection() {
23912
+ this._connection = undefined;
23913
+ this._hasInitialUrlBeenSet = false;
23914
+ this._readSubscription?.unsubscribe();
23915
+ this._writeSubscription?.unsubscribe();
23916
+ }
23917
+ subscribeToUrlChanges() {
23918
+ const { tableStoreService } = this._connection;
23919
+ let isFirstEmit = true;
23920
+ this._readSubscription = this.hub.navigationSettled$
23921
+ .pipe(switchMap(() => this.hub.queryParams()), map(queryParams => this.parseUrlParams(queryParams)), distinctUntilChanged((a, b) => a.page === b.page && a.size === b.size), switchMap(params => combineLatest([tableStoreService.pageChangeInfo$(), tableStoreService.totalCount$()]).pipe(take(1), map(([currentInfo, totalCount]) => ({ params, currentInfo, totalCount })))))
23922
+ .subscribe(({ params, currentInfo, totalCount }) => {
23923
+ const target = this.toStoreState(params);
23924
+ const isChanged = !currentInfo || currentInfo.pageIndex !== target.pageIndex || currentInfo.pageSize !== target.pageSize;
23925
+ if (isChanged) {
23926
+ tableStoreService.setPageParams(target.pageIndex, target.pageSize, totalCount);
23927
+ }
23928
+ if (isFirstEmit) {
23929
+ this._activatedRouteCheckedSubject.next(true);
23930
+ isFirstEmit = false;
23931
+ }
23932
+ });
23933
+ }
23934
+ subscribeToStoreChanges() {
23935
+ const { tableStoreService } = this._connection;
23936
+ this._writeSubscription = tableStoreService
23937
+ .pageChangeInfo$()
23938
+ .pipe(filter((info) => info !== undefined), distinctUntilChanged((a, b) => a.pageIndex === b.pageIndex && a.pageSize === b.pageSize), switchMap(info => this.hub.navigationSettled$.pipe(take(1), map(() => info))))
23939
+ .subscribe(info => this.writeUrl(info.pageIndex, info.pageSize));
23940
+ }
23941
+ writeUrl(pageIndex, pageSize) {
23942
+ const replaceUrl = !this._hasInitialUrlBeenSet;
23943
+ this._hasInitialUrlBeenSet = true;
23944
+ const targetPage = String(pageIndex + 1);
23945
+ const targetSize = String(pageSize);
23946
+ const urlAlreadyMatches = this.hub.snapshotQueryParam(PAGE_PARAM_NAME) === targetPage &&
23947
+ this.hub.snapshotQueryParam(SIZE_PARAM_NAME) === targetSize;
23948
+ if (urlAlreadyMatches)
23949
+ return;
23950
+ this.hub.write({ [PAGE_PARAM_NAME]: targetPage, [SIZE_PARAM_NAME]: targetSize }, replaceUrl);
23951
+ }
23952
+ parseUrlParams(queryParams) {
23953
+ const result = {};
23954
+ const rawPage = queryParams[PAGE_PARAM_NAME];
23955
+ if (typeof rawPage === 'string' && this.isValidPositiveIntegerString(rawPage)) {
23956
+ result.page = Number(rawPage);
23957
+ }
23958
+ const rawSize = queryParams[SIZE_PARAM_NAME];
23959
+ if (typeof rawSize === 'string' &&
23960
+ this.isValidPositiveIntegerString(rawSize) &&
23961
+ this.isValidSize(Number(rawSize))) {
23962
+ result.size = Number(rawSize);
23963
+ }
23964
+ return result;
23965
+ }
23966
+ isValidPositiveIntegerString(raw) {
23967
+ return /^[1-9]\d*$/.test(raw);
23968
+ }
23969
+ isValidSize(value) {
23970
+ const pageSizes = this.getConfiguredPageSizes();
23971
+ if (pageSizes && pageSizes.length > 0) {
23972
+ return pageSizes.includes(value);
23973
+ }
23974
+ return value <= SIZE_SANITY_MAX;
23975
+ }
23976
+ getConfiguredPageSizes() {
23977
+ const pagination = this._connection?.paginator.config?.pagination;
23978
+ return typeof pagination === 'object' ? pagination.pageSizes : undefined;
23979
+ }
23980
+ toStoreState(params) {
23981
+ const { paginator } = this._connection;
23982
+ return {
23983
+ pageIndex: params.page !== undefined ? params.page - 1 : 0,
23984
+ pageSize: params.size ?? paginator.getPageSizeDefault()
23985
+ };
23986
+ }
23987
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
23988
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService });
23989
+ }
23990
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, decorators: [{
23991
+ type: Injectable
23992
+ }], ctorParameters: () => [] });
23993
+
23377
23994
  class QdScrollingService {
23378
23995
  scrollIntoViewIfNeeded(element, borderDirection = 'top', targetBorderDistance = 0) {
23379
23996
  this.scrollIntoView(element, borderDirection, targetBorderDistance, true);
@@ -23602,6 +24219,7 @@ const PAGE_SIZE_DEFAULT = 25;
23602
24219
  class QdTablePaginatorComponent {
23603
24220
  tableDataResolver = inject(QD_TABLE_DATA_RESOLVER_TOKEN, { optional: true });
23604
24221
  tableStoreService = inject(QdTableStoreService);
24222
+ routerConnector = inject(QdTablePaginationRouterConnectorService);
23605
24223
  /**
23606
24224
  * @description Configuration Model for Qd-Table.
23607
24225
  */
@@ -23638,11 +24256,39 @@ class QdTablePaginatorComponent {
23638
24256
  this.totalCount$ = this.tableStoreService.totalCount$();
23639
24257
  this.selectedRowsCount$ = this.tableStoreService.selectedRows$().pipe(map(ids => ids?.length ?? 0));
23640
24258
  if (this.isConfigValid())
23641
- this.initPagination();
24259
+ this.startPagination();
23642
24260
  }
23643
24261
  ngOnDestroy() {
24262
+ this.routerConnector.disconnectPaginationFromRouter(this);
24263
+ this._destroyed$.next(null);
23644
24264
  this._destroyed$.complete();
23645
24265
  }
24266
+ /**
24267
+ * @description Whether this paginator should sync its state with the URL. Reads
24268
+ * `pagination.connectWithRouter` (default `false` — URL sync is opt-in and
24269
+ * requires an explicit `pagination: { connectWithRouter: true }`).
24270
+ *
24271
+ * Used by `QdTablePaginationRouterConnectorService` to decide whether to claim
24272
+ * the router-singleton for this paginator.
24273
+ */
24274
+ shouldConnectWithRouter() {
24275
+ const pagination = this.config?.pagination;
24276
+ if (typeof pagination !== 'object')
24277
+ return false;
24278
+ return pagination.connectWithRouter === true;
24279
+ }
24280
+ /**
24281
+ * @description The effective default page size for this paginator. Resolves
24282
+ * `pagination.pageSizeDefault` first, then falls back to the first entry of
24283
+ * `pagination.pageSizes`, finally to the framework constant `PAGE_SIZE_DEFAULT`.
24284
+ */
24285
+ getPageSizeDefault() {
24286
+ if (typeof this.config?.pagination !== 'object')
24287
+ return PAGE_SIZE_DEFAULT;
24288
+ const { pageSizeDefault, pageSizes } = this.config.pagination;
24289
+ const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
24290
+ return pageSizeDefault || pageSize;
24291
+ }
23646
24292
  navigateToPage(direction) {
23647
24293
  if (!this.paginatorButtons)
23648
24294
  return;
@@ -23655,24 +24301,30 @@ class QdTablePaginatorComponent {
23655
24301
  }
23656
24302
  isConfigValid() {
23657
24303
  if (this.config?.hasPagination) {
23658
- console.warn('QD-UI | QdTable Pagination - The config "hasPagination" is deprecated. Please use "pagination" instead.');
24304
+ console.warn('Quadrel Framework | QdTable Pagination - The config "hasPagination" is deprecated. Please use "pagination" instead.');
23659
24305
  }
23660
24306
  if (!this.tableDataResolver) {
23661
- console.error('QD-UI | QdTable Pagination - Provide a resolver for pagination. Please use the "QD_TABLE_DATA_RESOLVER_TOKEN" injection token.');
24307
+ console.error('Quadrel Framework | QdTable Pagination - Provide a resolver for pagination. Please use the "QD_TABLE_DATA_RESOLVER_TOKEN" injection token.');
23662
24308
  return false;
23663
24309
  }
23664
24310
  return true;
23665
24311
  }
24312
+ startPagination() {
24313
+ if (!this.shouldConnectWithRouter()) {
24314
+ this.initPagination();
24315
+ return;
24316
+ }
24317
+ this.routerConnector
24318
+ .connectPaginationWithRouter(this, this.tableStoreService)
24319
+ .pipe(takeUntil(this._destroyed$), first())
24320
+ .subscribe(connected => {
24321
+ if (!connected)
24322
+ this.initPagination();
24323
+ });
24324
+ }
23666
24325
  initPagination() {
23667
24326
  this.tableStoreService.setupPagination(this.getPageSizeDefault());
23668
24327
  }
23669
- getPageSizeDefault() {
23670
- if (typeof this.config?.pagination !== 'object')
23671
- return PAGE_SIZE_DEFAULT;
23672
- const { pageSizeDefault, pageSizes } = this.config.pagination;
23673
- const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
23674
- return pageSizeDefault || pageSize;
23675
- }
23676
24328
  calculatePageNumber(direction, totalCount, pageSize, currentPage) {
23677
24329
  switch (direction) {
23678
24330
  case QdPaginatorDirection.NextPage: {
@@ -23691,11 +24343,11 @@ class QdTablePaginatorComponent {
23691
24343
  }
23692
24344
  }
23693
24345
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23694
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTablePaginatorComponent, isStandalone: false, selector: "qd-table-paginator", inputs: { config: "config", testId: ["data-test-id", "testId"] }, viewQueries: [{ propertyName: "paginatorButtons", first: true, predicate: ["paginatorButtons"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdScrollToPaginationDirective, selector: "[qdScrollToPagination]" }, { kind: "component", type: QdTablePaginatorPageSizeComponent, selector: "qd-table-paginator-page-size", inputs: ["pageSizes"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24346
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTablePaginatorComponent, isStandalone: false, selector: "qd-table-paginator", inputs: { config: "config", testId: ["data-test-id", "testId"] }, providers: [QdTablePaginationRouterConnectorService], viewQueries: [{ propertyName: "paginatorButtons", first: true, predicate: ["paginatorButtons"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdScrollToPaginationDirective, selector: "[qdScrollToPagination]" }, { kind: "component", type: QdTablePaginatorPageSizeComponent, selector: "qd-table-paginator-page-size", inputs: ["pageSizes"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23695
24347
  }
23696
24348
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, decorators: [{
23697
24349
  type: Component,
23698
- args: [{ selector: 'qd-table-paginator', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"] }]
24350
+ args: [{ selector: 'qd-table-paginator', providers: [QdTablePaginationRouterConnectorService], changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"] }]
23699
24351
  }], propDecorators: { config: [{
23700
24352
  type: Input
23701
24353
  }], testId: [{
@@ -23706,6 +24358,147 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
23706
24358
  args: ['paginatorButtons']
23707
24359
  }] } });
23708
24360
 
24361
+ const SORT_PARAM_NAME = 'sort';
24362
+ const OWNED_PARAMS = [SORT_PARAM_NAME];
24363
+ const SEGMENT_SEPARATOR = ',';
24364
+ const COLUMN_DIRECTION_SEPARATOR = '.';
24365
+ class QdTableSortRouterConnectorService {
24366
+ hub = inject(QdRouterQueryParamHubService);
24367
+ destroyRef = inject(DestroyRef);
24368
+ _connection;
24369
+ _readSubscription;
24370
+ _writeSubscription;
24371
+ _activatedRouteCheckedSubject = new ReplaySubject(1);
24372
+ _activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
24373
+ _hasInitialUrlBeenSet = false;
24374
+ _hasWarnedMultiSegment = false;
24375
+ constructor() {
24376
+ this.destroyRef.onDestroy(() => {
24377
+ this.tearDownConnection();
24378
+ this.hub.release(OWNED_PARAMS, this);
24379
+ });
24380
+ }
24381
+ connectSortWithRouter(table, tableStoreService) {
24382
+ if (!this.shouldConnect(table) || !this.hub.isAvailable())
24383
+ return of(false);
24384
+ if (!this.hub.claim(OWNED_PARAMS, this))
24385
+ return of(false);
24386
+ this._connection = {
24387
+ table: table,
24388
+ tableStoreService: tableStoreService,
24389
+ configuredColumns: table.config.columns
24390
+ };
24391
+ this._hasInitialUrlBeenSet = false;
24392
+ this._hasWarnedMultiSegment = false;
24393
+ this._activatedRouteCheckedSubject = new ReplaySubject(1);
24394
+ this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
24395
+ this.subscribeToUrlChanges();
24396
+ this.subscribeToStoreChanges();
24397
+ return this._activatedRouteChecked$;
24398
+ }
24399
+ disconnectSortFromRouter(table) {
24400
+ if (this._connection?.table !== table)
24401
+ return;
24402
+ this.tearDownConnection();
24403
+ this.hub.release(OWNED_PARAMS, this);
24404
+ }
24405
+ tearDownConnection() {
24406
+ this._connection = undefined;
24407
+ this._hasInitialUrlBeenSet = false;
24408
+ this._hasWarnedMultiSegment = false;
24409
+ this._readSubscription?.unsubscribe();
24410
+ this._writeSubscription?.unsubscribe();
24411
+ }
24412
+ subscribeToUrlChanges() {
24413
+ const { tableStoreService } = this._connection;
24414
+ let isFirstEmit = true;
24415
+ this._readSubscription = this.hub.navigationSettled$
24416
+ .pipe(switchMap(() => this.hub.queryParams()), map(queryParams => (typeof queryParams[SORT_PARAM_NAME] === 'string' ? queryParams[SORT_PARAM_NAME] : '')), distinctUntilChanged(), map(raw => this.parseRawSortValue(raw)))
24417
+ .subscribe(segments => {
24418
+ if (segments.length === 1) {
24419
+ const [{ column, direction }] = segments;
24420
+ tableStoreService.setSort(column, direction);
24421
+ }
24422
+ if (isFirstEmit) {
24423
+ this._activatedRouteCheckedSubject.next(true);
24424
+ isFirstEmit = false;
24425
+ }
24426
+ });
24427
+ }
24428
+ subscribeToStoreChanges() {
24429
+ const { tableStoreService } = this._connection;
24430
+ this._writeSubscription = tableStoreService
24431
+ .tableSort$()
24432
+ .pipe(filter((sort) => Array.isArray(sort)), map(sort => this.serializeSort(sort)), distinctUntilChanged(), switchMap(serialized => this.hub.navigationSettled$.pipe(take(1), map(() => serialized))))
24433
+ .subscribe(serialized => this.writeUrl(serialized));
24434
+ }
24435
+ writeUrl(serialized) {
24436
+ const replaceUrl = !this._hasInitialUrlBeenSet;
24437
+ this._hasInitialUrlBeenSet = true;
24438
+ if (this.hub.snapshotQueryParam(SORT_PARAM_NAME) === serialized)
24439
+ return;
24440
+ this.hub.write({ [SORT_PARAM_NAME]: serialized }, replaceUrl);
24441
+ }
24442
+ shouldConnect(table) {
24443
+ const sortConfig = table.config.sort;
24444
+ if (sortConfig === true || sortConfig === undefined)
24445
+ return false;
24446
+ return sortConfig.connectWithRouter === true;
24447
+ }
24448
+ parseRawSortValue(raw) {
24449
+ if (raw.length === 0)
24450
+ return [];
24451
+ const rawSegments = raw.split(SEGMENT_SEPARATOR);
24452
+ const validSegments = rawSegments
24453
+ .map(segment => this.parseSegment(segment))
24454
+ .filter((segment) => segment !== undefined);
24455
+ if (validSegments.length > 1) {
24456
+ if (!this._hasWarnedMultiSegment) {
24457
+ console.warn('Quadrel Framework | QdTable - Multi-column sort URL is not yet supported. Using first valid segment only.');
24458
+ this._hasWarnedMultiSegment = true;
24459
+ }
24460
+ return [validSegments[0]];
24461
+ }
24462
+ return validSegments;
24463
+ }
24464
+ parseSegment(segment) {
24465
+ if (segment.length === 0)
24466
+ return undefined;
24467
+ const separatorIndex = segment.indexOf(COLUMN_DIRECTION_SEPARATOR);
24468
+ if (separatorIndex <= 0 || separatorIndex === segment.length - 1)
24469
+ return undefined;
24470
+ const column = segment.slice(0, separatorIndex);
24471
+ const directionRaw = segment.slice(separatorIndex + 1).toLowerCase();
24472
+ if (!this.isValidColumn(column))
24473
+ return undefined;
24474
+ if (directionRaw === 'asc')
24475
+ return { column, direction: QdSortDirection.ASC };
24476
+ if (directionRaw === 'desc')
24477
+ return { column, direction: QdSortDirection.DESC };
24478
+ return undefined;
24479
+ }
24480
+ isValidColumn(column) {
24481
+ const config = this._connection?.configuredColumns.find(c => c.column === column);
24482
+ return !!config && config.sort !== undefined && config.sort.isDisabled !== true;
24483
+ }
24484
+ serializeSort(sort) {
24485
+ const active = sort.filter((entry) => entry.direction === QdSortDirection.ASC || entry.direction === QdSortDirection.DESC);
24486
+ if (active.length === 0)
24487
+ return undefined;
24488
+ return active
24489
+ .map(entry => `${entry.column}${COLUMN_DIRECTION_SEPARATOR}${this.directionToString(entry.direction)}`)
24490
+ .join(SEGMENT_SEPARATOR);
24491
+ }
24492
+ directionToString(direction) {
24493
+ return direction === QdSortDirection.ASC ? 'asc' : 'desc';
24494
+ }
24495
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
24496
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService });
24497
+ }
24498
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, decorators: [{
24499
+ type: Injectable
24500
+ }], ctorParameters: () => [] });
24501
+
23709
24502
  class QdTableRowActionsSecondaryMenuComponent {
23710
24503
  actionsService = inject(QdTableSecondaryActionsService);
23711
24504
  tableStore = inject(QdTableStoreService);
@@ -23952,7 +24745,7 @@ class QdTableBodyComponent {
23952
24745
  }
23953
24746
  primaryAction(rowData, index) {
23954
24747
  if (!this.config.primaryAction?.handler)
23955
- return console.warn('QD-UI | QdTable - No handler defined for primary action.');
24748
+ return console.warn('Quadrel Framework | QdTable - No handler defined for primary action.');
23956
24749
  if (this.config.primaryAction?.highlightOnRevisit) {
23957
24750
  this.tableStoreService.setLastVisitedRow(resolveRowIdentifier(rowData, index, this.config.trackRowBy));
23958
24751
  }
@@ -24014,7 +24807,7 @@ class QdTableEmptyStateComponent {
24014
24807
  }
24015
24808
  getI18n() {
24016
24809
  if (!this.emptyStateService.i18ns)
24017
- console.warn('QD-UI | QdTable - No translations available.');
24810
+ console.warn('Quadrel Framework | QdTable - No translations available.');
24018
24811
  return this.emptyStateService.i18ns;
24019
24812
  }
24020
24813
  handleClick() {
@@ -24321,6 +25114,7 @@ class QdTableComponent {
24321
25114
  breakpointService = inject(QdBreakpointService);
24322
25115
  resolverService = inject(QdTableResolverService);
24323
25116
  confirmationDialogService = inject(QdConfirmationDialogOpenerService);
25117
+ sortRouterConnector = inject(QdTableSortRouterConnectorService);
24324
25118
  /**
24325
25119
  * Configuration of the table. The generic type specifies the column definition. <br />
24326
25120
  *
@@ -24428,6 +25222,7 @@ class QdTableComponent {
24428
25222
  this.tableStoreService.initTableState(this._data, this.hasResolver, this._connectors, this.hasPagination);
24429
25223
  this.tableStoreService.updateTableStateRecentSecondaryAction(undefined);
24430
25224
  this.tableStoreService.setupSort(this.config.columns);
25225
+ this.sortRouterConnector.connectSortWithRouter(this, this.tableStoreService).pipe(take(1)).subscribe();
24431
25226
  this.resolverService.init(this.config.refreshOnLanguageChange, this.hasPagination);
24432
25227
  this.data$ = this.tableStoreService.tableDataEntries$();
24433
25228
  this.initializeResponsiveRowService();
@@ -24458,6 +25253,7 @@ class QdTableComponent {
24458
25253
  }
24459
25254
  }
24460
25255
  ngOnDestroy() {
25256
+ this.sortRouterConnector.disconnectSortFromRouter(this);
24461
25257
  this.tableStoreService.updateTableStateRecentSecondaryAction(undefined);
24462
25258
  this.tableStoreService.resetConnectorStates();
24463
25259
  this.fillingWidthService.destroy();
@@ -24473,7 +25269,7 @@ class QdTableComponent {
24473
25269
  }
24474
25270
  registerConnector(connectorName) {
24475
25271
  if (!this.tableDataResolver) {
24476
- console.warn('QD-UI | QdTable - qdConnectToFilter only works with a resolver. Please inject the resolver using QD_TABLE_DATA_RESOLVER_TOKEN.');
25272
+ console.warn('Quadrel Framework | QdTable - qdConnectToFilter only works with a resolver. Please inject the resolver using QD_TABLE_DATA_RESOLVER_TOKEN.');
24477
25273
  return;
24478
25274
  }
24479
25275
  this._connectors.push({ connectorName, connectorState: QdTableConnectorState.AWAITING });
@@ -24522,7 +25318,7 @@ class QdTableComponent {
24522
25318
  this.secondaryActionOutput.emit(recentAction);
24523
25319
  const action = this.config.secondaryActions?.find(a => a.type === recentAction.type);
24524
25320
  if (!action?.handler)
24525
- return console.warn('QD-UI | QdTable - No handler defined for secondary action:', recentAction.type);
25321
+ return console.warn('Quadrel Framework | QdTable - No handler defined for secondary action:', recentAction.type);
24526
25322
  if (action.highlightOnRevisit) {
24527
25323
  this.tableStoreService.setLastVisitedRow(resolveRowIdentifier(recentAction.rowData, recentAction.index, this.config.trackRowBy));
24528
25324
  }
@@ -24546,13 +25342,13 @@ class QdTableComponent {
24546
25342
  if (!this.config.refreshOnPushEvent)
24547
25343
  return;
24548
25344
  if (!this.config.uid) {
24549
- console.error('QD-UI | QdTable - A uid has to be defined when refreshOnPushEvent is enabled. ' +
24550
- 'The table uid has to match the path of the server side event.');
25345
+ console.error('Quadrel Framework | QdTable - A "uid" has to be defined when "refreshOnPushEvent" is enabled. ' +
25346
+ 'The table "uid" has to match the path of the server side event.');
24551
25347
  return;
24552
25348
  }
24553
25349
  if (!this.pushEventsService || !this.pushEventsService.isConnectedOrConnecting()) {
24554
- console.error('QD-UI | QdTable - You have to connect the QdPushEventsService on your own ' +
24555
- 'if you enable the refreshOnPushEvent flag in the table.');
25350
+ console.error('Quadrel Framework | QdTable - You have to connect the QdPushEventsService on your own ' +
25351
+ 'if you enable the "refreshOnPushEvent" flag in the table.');
24556
25352
  return;
24557
25353
  }
24558
25354
  const pushEventsService = this.pushEventsService;
@@ -24565,11 +25361,11 @@ class QdTableComponent {
24565
25361
  return data.path.includes(this.config.uid);
24566
25362
  }
24567
25363
  catch (error) {
24568
- console.warn('Failed to process messageEvent:', error);
25364
+ console.warn('Quadrel Framework | QdTable - Failed to process messageEvent:', error);
24569
25365
  return false;
24570
25366
  }
24571
25367
  }), catchError(error => {
24572
- console.error('Error in event stream:', error);
25368
+ console.error('Quadrel Framework | QdTable - Error in event stream:', error);
24573
25369
  return NEVER;
24574
25370
  }))
24575
25371
  .subscribe(() => this.triggerRefresh());
@@ -24589,14 +25385,14 @@ class QdTableComponent {
24589
25385
  }
24590
25386
  validateConfig() {
24591
25387
  if (!this.config.i18ns) {
24592
- console.warn('QD-UI | QdTable - No translations available for the secondaryActions.');
25388
+ console.warn('Quadrel Framework | QdTable - No translations available for the secondaryActions.');
24593
25389
  }
24594
25390
  if (this.hasHighlightOnRevisit() && !this.config.uid) {
24595
- console.warn('QD-UI | QdTable - A uid has to be defined when highlightOnRevisit is enabled. ' +
25391
+ console.warn('Quadrel Framework | QdTable - A "uid" has to be defined when "highlightOnRevisit" is enabled. ' +
24596
25392
  'Without a uid, the table state does not persist across navigation.');
24597
25393
  }
24598
25394
  if (this.config.selection?.type === 'multiSelect' && this.hasPagination && !this.config.trackRowBy) {
24599
- throw new Error('QD-UI | QdTable - "trackRowBy" is required when combining "selection: multiSelect" with pagination. ' +
25395
+ throw new Error('Quadrel Framework | QdTable - "trackRowBy" is required when combining "selection: multiSelect" with pagination. ' +
24600
25396
  'Provide a trackRowBy function (e.g. `trackRowBy: row => row.uid`) that returns a unique identifier ' +
24601
25397
  'per row, otherwise selections cannot be persisted across pages, page-size or sort changes.');
24602
25398
  }
@@ -24612,7 +25408,7 @@ class QdTableComponent {
24612
25408
  mapColumnFillsWidth() {
24613
25409
  if (!this.config.mainColumnNotFillingWidth)
24614
25410
  return;
24615
- console.warn('QD-UI | QdTable - The config key "mainColumnNotFillingWidth" is deprecated. Please use "whichColumnFillsWidth" instead.');
25411
+ console.warn('Quadrel Framework | QdTable - The config key "mainColumnNotFillingWidth" is deprecated. Please use "whichColumnFillsWidth" instead.');
24616
25412
  if (this.config.whichColumnFillsWidth)
24617
25413
  return;
24618
25414
  this.config.whichColumnFillsWidth = 'none';
@@ -24627,7 +25423,8 @@ class QdTableComponent {
24627
25423
  QdTableRowSelectionService,
24628
25424
  QdTableFillingWidthService,
24629
25425
  QdTableResolverService,
24630
- QdTableExternalActionResultService
25426
+ QdTableExternalActionResultService,
25427
+ QdTableSortRouterConnectorService
24631
25428
  ], viewQueries: [{ propertyName: "paginator", first: true, predicate: QdTablePaginatorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<table [class]=\"'qd-table__table'\">\n <tr qd-table-head [config]=\"config\" [data-test-id]=\"testId\"></tr>\n <tbody qd-table-body [config]=\"config\" [data]=\"(data$ | async) ?? []\" [data-test-id]=\"testId\"></tbody>\n</table>\n\n<qd-table-paginator [config]=\"config\" [data-test-id]=\"testId\" *ngIf=\"hasPagination\"></qd-table-paginator>\n<qd-table-empty-state *ngIf=\"hasEmptyStateView$ | async\" [config]=\"config.emptyStateView\"></qd-table-empty-state>\n", styles: [":host{display:inline-flex;flex-direction:column}:host .qd-table__table{background:#fff;border-spacing:0;color:#171717;font-size:.875rem;font-weight:400;line-height:2.5rem}:host .qd-table__head,:host .qd-table__body{vertical-align:center}:host .qd-table__head{background:#e5e5e5;text-align:left}:host .qd-table__head ::ng-deep .qd-table__head-cell{font-weight:600}:host .qd-table__body{color:#171717}:host ::ng-deep .qd-table__head-cell,:host ::ng-deep .qd-table__body-cell{padding:.125rem 1rem 0;vertical-align:top}:host ::ng-deep .qd-table__head-cell--selection,:host ::ng-deep .qd-table__body-cell--selection{width:1.875rem;padding-top:.1875rem;text-align:center}:host ::ng-deep .qd-table__head-cell--actions-inline-menu,:host ::ng-deep .qd-table__body-cell--actions-inline-menu{padding-top:.125rem;vertical-align:top}:host.main-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep th.main-column,:host.main-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep td.main-column{width:100%}:host.main-column-fills-width.table-has-remaining-width ::ng-deep th:not(.main-column),:host.main-column-fills-width.table-has-remaining-width ::ng-deep td:not(.main-column){white-space:nowrap}:host.last-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep th.last-column,:host.last-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep td.last-column{width:100%}:host.last-column-fills-width.table-has-remaining-width ::ng-deep th:not(.last-column),:host.last-column-fills-width.table-has-remaining-width ::ng-deep td:not(.last-column){white-space:nowrap}:host.harmonized{width:100%}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdTableBodyComponent, selector: "[qd-table-body]", inputs: ["config", "data", "data-test-id"] }, { kind: "component", type: QdTableEmptyStateComponent, selector: "qd-table-empty-state", inputs: ["config"] }, { kind: "component", type: QdTableHeadComponent, selector: "[qd-table-head]", inputs: ["config", "data-test-id"] }, { kind: "component", type: QdTablePaginatorComponent, selector: "qd-table-paginator", inputs: ["config", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24632
25429
  }
24633
25430
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableComponent, decorators: [{
@@ -24641,7 +25438,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
24641
25438
  QdTableRowSelectionService,
24642
25439
  QdTableFillingWidthService,
24643
25440
  QdTableResolverService,
24644
- QdTableExternalActionResultService
25441
+ QdTableExternalActionResultService,
25442
+ QdTableSortRouterConnectorService
24645
25443
  ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
24646
25444
  '[class.qd-table]': 'true',
24647
25445
  '[class.main-column-fills-width]': 'whichColumnFillsWidth === "main"',
@@ -24865,7 +25663,7 @@ class QdConnectorTableFilterDirective {
24865
25663
  constructor() {
24866
25664
  const toolbarComponentsService = this.toolbarComponentsService;
24867
25665
  if (!toolbarComponentsService)
24868
- throw new Error('QD-UI | QdConnectorTableFilterDirective - Please use this directive only within a QdSection!');
25666
+ throw new Error('Quadrel Framework | QdConnectorTableFilter - Please use this directive only within <qd-section>.');
24869
25667
  this.tableComponent.registerConnector('filter');
24870
25668
  }
24871
25669
  ngAfterViewInit() {
@@ -24887,7 +25685,7 @@ class QdConnectorTableFilterDirective {
24887
25685
  }
24888
25686
  validateAndApplyConfig() {
24889
25687
  if (this.filterComponent.hasFilterData())
24890
- console.error('QD-UI | QdConnectorTableFilterDirective - Please remove the redundant filterConfig in the sectionConfig. Will be overridden by this directive.');
25688
+ console.error('Quadrel Framework | QdConnectorTableFilter - Please remove the redundant "filterConfig" in the "sectionConfig". Will be overridden by this directive.');
24891
25689
  this.filterComponent.setFilterConfig({ ...this.qdConnectToFilter, emitOutputsInitially: true });
24892
25690
  }
24893
25691
  subscribeToFilterChanges() {
@@ -24951,7 +25749,7 @@ class QdConnectorTableSearchDirective {
24951
25749
  constructor() {
24952
25750
  const toolbarComponentsService = this.toolbarComponentsService;
24953
25751
  if (!toolbarComponentsService)
24954
- throw new Error('QD-UI | QdConnectorTableSearchDirective - Please use this directive only within a QdSection!');
25752
+ throw new Error('Quadrel Framework | QdConnectorTableSearch - Please use this directive only within <qd-section>.');
24955
25753
  this.tableComponent.registerConnector('search');
24956
25754
  }
24957
25755
  ngAfterViewInit() {
@@ -24969,7 +25767,7 @@ class QdConnectorTableSearchDirective {
24969
25767
  }
24970
25768
  validateAndApplyConfig() {
24971
25769
  if (this.searchComponent.hasConfigData())
24972
- console.warn('QD-UI | QdConnectorTableSearchDirective - Please remove the redundant searchConfig in the sectionConfig. Will overridden by this directive.');
25770
+ console.warn('Quadrel Framework | QdConnectorTableSearch - Please remove the redundant "searchConfig" in the "sectionConfig". Will be overridden by this directive.');
24973
25771
  this.searchComponent.configData = { emitEmptySearch: true, ...this.qdConnectToSearch };
24974
25772
  }
24975
25773
  subscribeToSearchChanges() {
@@ -25038,7 +25836,7 @@ class QdSectionAdapterDirective {
25038
25836
  const toRemove = Array.from(host.children).filter(child => child.tagName !== 'QD-SECTION');
25039
25837
  toRemove.forEach(el => {
25040
25838
  this.renderer.removeChild(host, el);
25041
- console.warn('QD-UI | QdSectionAdapterDirective Only "qd-section" is supported. The following content is not rendered:', el);
25839
+ console.warn('Quadrel Framework | QdSectionAdapter - Only "qd-section" is supported. The following content is not rendered:', el);
25042
25840
  });
25043
25841
  }
25044
25842
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdSectionAdapterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -25158,13 +25956,13 @@ class QdSectionToolbarActionComponent {
25158
25956
  }
25159
25957
  validateConfig() {
25160
25958
  if (this._config.action) {
25161
- console.warn('QD-UI | QdSectionComponent - The `action` key is deprecated and will be removed in v18. Use `actions` instead.');
25959
+ console.warn('Quadrel Framework | QdSection - The "action" key is deprecated and will be removed in v18. Use "actions" instead.');
25162
25960
  }
25163
25961
  if (this._config.action && this._config.actions) {
25164
- console.error('QD-UI | QdSectionComponent - Both `action` and `actions` are defined in the configuration. Please use only `actions`.');
25962
+ console.error('Quadrel Framework | QdSection - Both "action" and "actions" are defined in the configuration. Please use only "actions".');
25165
25963
  }
25166
25964
  if (this._config.actions && this._config.actions.filter(action => action.type === 'addNew').length > 1) {
25167
- console.error('QD-UI | QdSectionComponent - The action type `addNew` is used multiple times in `actions`. Please use `addNew` only once.');
25965
+ console.error('Quadrel Framework | QdSection - The action type "addNew" is used multiple times in "actions". Please use "addNew" only once.');
25168
25966
  }
25169
25967
  }
25170
25968
  // TODO: Remove in v19
@@ -26182,7 +26980,7 @@ class QdTreeEmptyStateComponent {
26182
26980
  config;
26183
26981
  getI18n() {
26184
26982
  if (!this.emptyStateService.i18ns)
26185
- console.warn('QD-UI | QdTree - No translations available.');
26983
+ console.warn('Quadrel Framework | QdTree - No translations available.');
26186
26984
  return this.emptyStateService.i18ns;
26187
26985
  }
26188
26986
  handleClick() {
@@ -26371,7 +27169,7 @@ class QdTreeComponent {
26371
27169
  }
26372
27170
  validateConfig() {
26373
27171
  if (!this.config.i18ns) {
26374
- console.warn('QD-UI | QdTree - No translations available for the secondaryActions.');
27172
+ console.warn('Quadrel Framework | QdTree - No translations available for the secondaryActions.');
26375
27173
  }
26376
27174
  }
26377
27175
  initializeGroupService() {
@@ -26380,7 +27178,7 @@ class QdTreeComponent {
26380
27178
  }
26381
27179
  catch (err) {
26382
27180
  if (err instanceof QdGroupedIndicesNotConsecutiveError) {
26383
- console.error('QD-UI | QdTree - Non-sequential "tree" content types are not allowed.');
27181
+ console.error('Quadrel Framework | QdTree - Non-sequential "tree" content types are not allowed.');
26384
27182
  }
26385
27183
  }
26386
27184
  }
@@ -26414,7 +27212,7 @@ class QdTreeComponent {
26414
27212
  this.secondaryActionOutput.emit(recentAction);
26415
27213
  const action = this.config.secondaryActions?.find(a => a.type === recentAction.type);
26416
27214
  if (!action?.handler)
26417
- return console.warn('QD-UI | QdTree - No handler defined for secondary action:', recentAction.type);
27215
+ return console.warn('Quadrel Framework | QdTree - No handler defined for secondary action:', recentAction.type);
26418
27216
  action.handler(recentAction);
26419
27217
  });
26420
27218
  }
@@ -26665,7 +27463,7 @@ class QdPageFooterService {
26665
27463
  updates.forEach(({ actionKey, partialAction }) => {
26666
27464
  const action = currentActionsMap.get(actionKey);
26667
27465
  if (!action)
26668
- return console.warn(`QdUi | QdPageFooterService - Action with key "${actionKey}" not found.`);
27466
+ return console.warn(`Quadrel Framework | QdPageFooter - Action with key "${actionKey}" not found.`);
26669
27467
  updatedActionsMap.set(actionKey, { ...action, ...partialAction });
26670
27468
  });
26671
27469
  this._pageFooterActions.next(updatedActionsMap);
@@ -27185,7 +27983,7 @@ class QdDynamicFacetComponent {
27185
27983
  ngOnInit() {
27186
27984
  const facet = this.dynamicFacetsService.getFacet(this.facet.options.type);
27187
27985
  if (!facet) {
27188
- console.error('QdUi | QdPage | Facet could not be found.');
27986
+ console.error('Quadrel Framework | QdPage - Facet could not be found.');
27189
27987
  return;
27190
27988
  }
27191
27989
  const viewContainerRef = this.dynamicFacet.viewContainerRef;
@@ -27234,13 +28032,13 @@ class QdPageCommitActionExecutor {
27234
28032
  onAfterSnapshot?.();
27235
28033
  }
27236
28034
  catch (err) {
27237
- console.error('QD-UI | QdPage - internal onAfterSnapshot hook threw after form was marked as saved.', err);
28035
+ console.error('Quadrel Framework | QdPage - internal onAfterSnapshot hook threw after form was marked as saved.', err);
27238
28036
  }
27239
28037
  try {
27240
28038
  action.onSuccess?.();
27241
28039
  }
27242
28040
  catch (err) {
27243
- console.error('QD-UI | QdPage - onSuccess callback threw after form was marked as saved.', err);
28041
+ console.error('Quadrel Framework | QdPage - onSuccess callback threw after form was marked as saved.', err);
27244
28042
  }
27245
28043
  });
27246
28044
  };
@@ -27259,14 +28057,14 @@ class QdPageCommitActionExecutor {
27259
28057
  }
27260
28058
  static handleError(action, err) {
27261
28059
  if (!action.onError) {
27262
- console.error('QD-UI | QdPage - Commit action observable errored — form was not marked as saved. Provide an `onError` hook on the action, or handle errors in the handler.', err);
28060
+ console.error('Quadrel Framework | QdPage - Commit action observable errored — form was not marked as saved. Provide an `onError` hook on the action, or handle errors in the handler.', err);
27263
28061
  return;
27264
28062
  }
27265
28063
  try {
27266
28064
  action.onError(err);
27267
28065
  }
27268
28066
  catch (callbackErr) {
27269
- console.error('QD-UI | QdPage - onError callback threw.', callbackErr);
28067
+ console.error('Quadrel Framework | QdPage - onError callback threw.', callbackErr);
27270
28068
  }
27271
28069
  }
27272
28070
  }
@@ -27401,7 +28199,7 @@ class QdFormGroupManagerService {
27401
28199
  captured.set(key, structuredClone(fg.getRawValue()));
27402
28200
  }
27403
28201
  catch (err) {
27404
- throw new Error(`QD-UI | QdFormGroupManager - captureFormValues() failed for group "${key}". ` +
28202
+ throw new Error(`Quadrel Framework | QdFormGroupManager - captureFormValues() failed for group "${key}". ` +
27405
28203
  `Form values must be structured-cloneable. Non-cloneable values like functions, ` +
27406
28204
  `symbols, or DOM nodes are not supported. Original error: ${String(err)}`);
27407
28205
  }
@@ -27495,7 +28293,7 @@ class QdFormGroupManagerService {
27495
28293
  initFormArrayFromValues(array, values) {
27496
28294
  const protoValue = values[0];
27497
28295
  if (!protoValue || typeof protoValue !== 'object') {
27498
- console.warn('QD-UI | QdFormGroupManager - Cannot restore FormArray: no prototype and value is not object-like.');
28296
+ console.warn('Quadrel Framework | QdFormGroupManager - Cannot restore FormArray: no prototype and value is not object-like.');
27499
28297
  return;
27500
28298
  }
27501
28299
  for (let i = 0; i < values.length; i++) {
@@ -27517,7 +28315,7 @@ class QdFormGroupManagerService {
27517
28315
  const arrControls = control.controls.map(c => this.deepCloneControl(c));
27518
28316
  return new FormArray(arrControls, control.validator, control.asyncValidator);
27519
28317
  }
27520
- throw new Error('QD-UI | QdFormGroupManager - Unsupported control type');
28318
+ throw new Error('Quadrel Framework | QdFormGroupManager - Unsupported control type.');
27521
28319
  }
27522
28320
  areFormGroupsValid(fg) {
27523
28321
  return Object.values(fg.controls).every(c => (c.disabled && !c.validator && !c.asyncValidator ? true : c.valid));
@@ -27949,7 +28747,7 @@ class QdPageObjectHeaderComponent {
27949
28747
  !(metadata$ instanceof ReplaySubject) &&
27950
28748
  !(metadata$ instanceof BehaviorSubject)) {
27951
28749
  this._metadataStreamTypeWarned = true;
27952
- console.warn('QdUi | QdPageObjectHeaderComponent - metadata$ is a plain Subject. Emissions fired before the ' +
28750
+ console.warn('Quadrel Framework | QdPageObjectHeader - metadata$ is a plain Subject. Emissions fired before the ' +
27953
28751
  "header subscribes (e.g. during the consuming component's ngOnInit) will be lost. " +
27954
28752
  'Use createMetadataStream() or pass a ReplaySubject(1)/BehaviorSubject instead.');
27955
28753
  }
@@ -28061,7 +28859,7 @@ class QdPageStepperAdapterDirective {
28061
28859
  const toRemove = Array.from(host.children).filter(child => child.tagName !== 'QD-PAGE-STEPPER');
28062
28860
  toRemove.forEach(el => {
28063
28861
  this.renderer.removeChild(host, el);
28064
- console.warn('QD-UI | QdPageStepperAdapterDirective Only "qd-page-stepper" is supported. The following content is not rendered:', el);
28862
+ console.warn('Quadrel Framework | QdPageStepperAdapter - Only "qd-page-stepper" is supported. The following content is not rendered:', el);
28065
28863
  });
28066
28864
  }
28067
28865
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageStepperAdapterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -28211,7 +29009,7 @@ class QdPageStepperComponent extends CdkStepper {
28211
29009
  ngOnInit() {
28212
29010
  this.linear = true;
28213
29011
  if (this.footerService && (this.config?.submit || this.config?.cancel)) {
28214
- throw new Error('QD-UI | QdPageStepperComponent - When using the Page Stepper in QdPage, don\'t use the "submit" and "cancel" attributes. Instead, use the QdPage configuration.');
29012
+ throw new Error('Quadrel Framework | QdPageStepper - When using <qd-page-stepper> inside <qd-page>, don\'t use the "submit" and "cancel" attributes. Instead, use the QdPageConfig.');
28215
29013
  }
28216
29014
  if (this.footerService) {
28217
29015
  this.selectedIndexChange.pipe(takeUntil(this._destroyed$)).subscribe(() => this.updateFooterActionsVisibility());
@@ -28417,7 +29215,7 @@ class QdPageStepperComponent extends CdkStepper {
28417
29215
  .subscribe(isValid => this.footerService.updateActions([{ actionKey: 'submit', partialAction: { isDisabled: !isValid } }]));
28418
29216
  }
28419
29217
  blockCdkInput(inputName) {
28420
- throw new Error(`QD-UI | QdPageStepperComponent - The ${inputName} attribute is not allowed. Please use QdPageStepperConfig instead.`);
29218
+ throw new Error(`Quadrel Framework | QdPageStepper - The "${inputName}" attribute is not allowed. Please use QdPageStepperConfig instead.`);
28421
29219
  }
28422
29220
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageStepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
28423
29221
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageStepperComponent, isStandalone: true, selector: "qd-page-stepper", inputs: { config: "config", testId: ["data-test-id", "testId"] }, outputs: { submitted: "submitted" }, host: { properties: { "class.standalone": "!footerService" }, classAttribute: "qd-stepper" }, providers: [{ provide: CdkStepper, useExisting: QdPageStepperComponent }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"qd-stepper-items-container\" *ngIf=\"steps.length > 1\">\n <qd-page-step-header\n *ngFor=\"let step of steps; let i = index\"\n (click)=\"handleClickHeader(step, i)\"\n [id]=\"_getStepLabelId(i)\"\n [ngClass]=\"'qd-step'\"\n [index]=\"i\"\n [state]=\"_getIndicatorType(i, step.state)\"\n [label]=\"step.config.label.i18n | translate\"\n [selected]=\"selectedIndex === i\"\n [active]=\"step.completed || selectedIndex === i || !linear\"\n [optional]=\"step.optional\"\n [locked]=\"!step.editable && i < selectedIndex\"\n >\n </qd-page-step-header>\n</div>\n\n<div class=\"stepper-content\">\n <ng-container [ngTemplateOutlet]=\"selected?.content\"></ng-container>\n</div>\n\n<div class=\"qd-stepper-action-area\" *ngIf=\"!footerService\">\n <button qdButton qdButtonGhost (click)=\"cancel()\" [data-test-id]=\"testId + '-cancel'\">\n {{ config?.cancel?.i18n || \"i18n.qd.stepper.cancel\" | translate }}\n </button>\n\n <button\n *ngIf=\"showPreviousButton(selectedIndex)\"\n qdButton\n qdButtonGhost\n (click)=\"previousStep()\"\n [data-test-id]=\"testId + '-previous'\"\n >\n {{ config?.previous?.i18n || \"i18n.qd.stepper.previous\" | translate }}\n </button>\n\n <button\n *ngIf=\"showNextButton(selectedIndex)\"\n qdButton\n [disabled]=\"(selectedStepValid$ | async) === false\"\n (click)=\"nextStep()\"\n [data-test-id]=\"testId + '-next'\"\n >\n {{ config?.next?.i18n || \"i18n.qd.stepper.next\" | translate }}\n </button>\n\n <button\n *ngIf=\"showSubmitButton(selectedIndex)\"\n qdButton\n (click)=\"submit()\"\n [disabled]=\"(allStepsValid$ | async) === false\"\n [data-test-id]=\"testId + '-submit'\"\n >\n {{ config?.submit?.i18n || \"i18n.qd.stepper.submit\" | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column}:host.standalone{height:calc(100% - 50px)}:host .qd-stepper-items-container{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;padding:0 1.25rem;border-bottom:.125rem solid rgb(213,213,213);background-color:#fff;gap:0 .625rem}@media (max-width: 599.98px){:host .qd-stepper-items-container{padding:0 .9375rem}}:host .stepper-content{flex:1 1 auto}:host .qd-stepper-action-area{display:flex;width:100%;height:3.125rem;justify-content:flex-end}:host .qd-stepper-action-area button{margin-right:1.25rem}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: QdPageStepHeaderComponent, selector: "qd-page-step-header", inputs: ["state", "label", "index", "selected", "active", "optional", "locked"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: QdButtonModule }, { 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: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -28492,7 +29290,7 @@ class QdPageTabsAdapterDirective {
28492
29290
  const toRemove = Array.from(host.children).filter(child => child.tagName !== 'QD-PAGE-TABS');
28493
29291
  toRemove.forEach(el => {
28494
29292
  this.renderer.removeChild(host, el);
28495
- console.warn('QD-UI | QdPageTabsAdapterDirective Only "qd-page-tabs" is supported. The following content is not rendered:', el);
29293
+ console.warn('Quadrel Framework | QdPageTabsAdapter - Only "qd-page-tabs" is supported. The following content is not rendered:', el);
28496
29294
  });
28497
29295
  }
28498
29296
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsAdapterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -28841,7 +29639,7 @@ class QdPageTabsComponent extends CdkStepper {
28841
29639
  pageTab.select();
28842
29640
  }
28843
29641
  else {
28844
- console.warn('QD-UI | QdPageTabsComponent - No tab found with name ' + tabNameFromParams);
29642
+ console.warn('Quadrel Framework | QdPageTabs - No tab found with name "' + tabNameFromParams + '".');
28845
29643
  this.selectFirstNotDisabledTab(true);
28846
29644
  }
28847
29645
  });
@@ -28865,7 +29663,7 @@ class QdPageTabsComponent extends CdkStepper {
28865
29663
  });
28866
29664
  }
28867
29665
  else {
28868
- console.warn('QD-UI | QdPageTabsComponent - connectedWithRouter is active, however QdPageTab has no name attribute.');
29666
+ console.warn('Quadrel Framework | QdPageTabs - "connectedWithRouter" is active, however <qd-page-tab> has no "name" attribute.');
28869
29667
  }
28870
29668
  }
28871
29669
  });
@@ -28929,7 +29727,7 @@ class QdPageTabsComponent extends CdkStepper {
28929
29727
  return this._getStepLabelId(i);
28930
29728
  }
28931
29729
  blockCdkInput(inputName) {
28932
- throw new Error(`QD-UI | QdPageTabsComponent - The use of the ${inputName} attribute is not permitted. Please use QdPageTabsConfig instead.`);
29730
+ throw new Error(`Quadrel Framework | QdPageTabs - The use of the "${inputName}" attribute is not permitted. Please use QdPageTabsConfig instead.`);
28933
29731
  }
28934
29732
  mapSelectionChangeToTabSelectionOutput() {
28935
29733
  this.selectionChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(selectionEvent => {
@@ -29495,7 +30293,7 @@ class QdPageComponent {
29495
30293
  infoBanners;
29496
30294
  footerHasContent$;
29497
30295
  isFooterVisible;
29498
- projectionGuardMessage = 'QD-UI | QdPage - This content is not supported. Please use QdSectionAdapterDirective for custom content projection.';
30296
+ projectionGuardMessage = 'Quadrel Framework | QdPage - This content is not supported. Please use the [qdSectionAdapter] directive for custom content projection.';
29499
30297
  _isInitialized = false;
29500
30298
  _destroyed$ = new Subject();
29501
30299
  _cancelSubmitValidation$ = new Subject();
@@ -29590,7 +30388,7 @@ class QdPageComponent {
29590
30388
  }
29591
30389
  checkConfigValidity() {
29592
30390
  if (!this.config)
29593
- console.warn('QdUi | QdPageComponent - To configure the page you should provide a valid config.');
30391
+ console.warn('Quadrel Framework | QdPage - To configure the page you should provide a valid config.');
29594
30392
  }
29595
30393
  setupCreatePageFooterActions() {
29596
30394
  const pageTypeConfig = this.config?.pageTypeConfig;
@@ -29836,15 +30634,15 @@ class QdConnectFormStateToPageDirective {
29836
30634
  isValid() {
29837
30635
  const hasFormGroup = this.formGroupDirective?.control;
29838
30636
  if (!hasFormGroup) {
29839
- console.error('QD-UI | QdConnectFormStateToPageDirective - Either FormGroupDirective or QdQuickEditComponent with a FormGroup is required.');
30637
+ console.error('Quadrel Framework | QdConnectFormStateToPage - Either a [formGroup] binding or <qd-quick-edit> with a FormGroup is required.');
29840
30638
  return false;
29841
30639
  }
29842
30640
  if (!this.formGroupManagerService) {
29843
- console.error('QD-UI | QdConnectFormStateToPageDirective - The Connector must be used within a QdPage component.');
30641
+ console.error('Quadrel Framework | QdConnectFormStateToPage - The connector must be used within <qd-page>.');
29844
30642
  return false;
29845
30643
  }
29846
30644
  if (!this.formGroupManagerService.isFormGroupKeyUnique(this.qdConnectFormStateToPage)) {
29847
- console.error(`QD-UI | QdConnectFormStateToPageDirective - The FormGroup key "${this.qdConnectFormStateToPage}" is not unique.`);
30645
+ console.error(`Quadrel Framework | QdConnectFormStateToPage - The FormGroup key "${this.qdConnectFormStateToPage}" is not unique.`);
29848
30646
  return false;
29849
30647
  }
29850
30648
  return true;
@@ -30336,147 +31134,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
30336
31134
  args: [{ selector: 'qd-shell-header-search', standalone: false, template: "<qd-search [configData]=\"config\"> </qd-search>\n", styles: [":host{display:none}:host:not(:last-child){margin-right:1rem}:host ::ng-deep .qd-input-input{border-color:#fff0!important;background:#efefef!important}:host ::ng-deep input{background:#fff0!important}:host ::ng-deep input::placeholder{color:#979797!important}:host ::ng-deep input:hover::placeholder,:host ::ng-deep input:focus::placeholder{color:#171717!important}@media (min-width: 1280px){:host{display:block}}\n"] }]
30337
31135
  }] });
30338
31136
 
30339
- // @ts-strict-ignore
30340
- class QdNavigationService {
30341
- router = inject(Router);
30342
- activatedRoute = inject(ActivatedRoute);
30343
- routeLeafSnapshot$;
30344
- routeData$;
30345
- routeComponentInstanceSubject = new ReplaySubject(1);
30346
- constructor() {
30347
- this.routeLeafSnapshot$ = this.router.events.pipe(filter(event => event instanceof NavigationEnd), map(() => this.activatedRoute), map(route => this.getLeafRoute(route).snapshot), filter(snapshot => snapshot.outlet === 'primary'));
30348
- this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
30349
- }
30350
- getLeafRoute(route) {
30351
- if (!route.firstChild)
30352
- return route;
30353
- return this.getLeafRoute(route.firstChild);
30354
- }
30355
- isHome$() {
30356
- return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
30357
- }
30358
- getRouteParams$() {
30359
- return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
30360
- }
30361
- getMergedRouteParams(snapshot) {
30362
- if (!snapshot)
30363
- return {};
30364
- return {
30365
- ...this.getMergedRouteParams(snapshot.parent),
30366
- ...(snapshot.params || {})
30367
- };
30368
- }
30369
- getPreviousHref$() {
30370
- return this.routeData$.pipe(map(({ previousHref }) => previousHref));
30371
- }
30372
- navigate(commands, extras) {
30373
- return this.router.navigate(commands, extras);
30374
- }
30375
- navigateByUrl(url, extras) {
30376
- return this.router.navigateByUrl(url, extras);
30377
- }
30378
- updateRouteComponentInstance(routeComponentInstance) {
30379
- this.routeComponentInstanceSubject.next(routeComponentInstance);
30380
- }
30381
- getRouteComponentInstance$() {
30382
- return this.routeComponentInstanceSubject.asObservable();
30383
- }
30384
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30385
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
30386
- }
30387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
30388
- type: Injectable
30389
- }], ctorParameters: () => [] });
30390
-
30391
- // @ts-strict-ignore
30392
- class QdShellLeftService {
30393
- _hasNavigation = new BehaviorSubject(false);
30394
- _isNavigationPinned = new BehaviorSubject(false);
30395
- _isNavigationRolledOver = new BehaviorSubject(false);
30396
- hasNavigation$ = this._hasNavigation.asObservable();
30397
- isNavigationPinned$ = this._isNavigationPinned.asObservable();
30398
- isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
30399
- set config(config) {
30400
- this._hasNavigation.next(config.navigation?.length > 0);
30401
- }
30402
- set isNavigationRolledOver(value) {
30403
- this._isNavigationRolledOver.next(value);
30404
- }
30405
- togglePinnedNavigation() {
30406
- this._isNavigationPinned.next(!this._isNavigationPinned.value);
30407
- }
30408
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30409
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
30410
- }
30411
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
30412
- type: Injectable
30413
- }] });
30414
-
30415
- class QdShellRightService {
30416
- notificationsService = inject(QdNotificationsService);
30417
- _open = new BehaviorSubject(false);
30418
- _pinned = new BehaviorSubject(false);
30419
- _hasNotificationsToggle = new BehaviorSubject(false);
30420
- open$ = this._open.asObservable();
30421
- pinned$ = this._pinned.asObservable();
30422
- notifications$;
30423
- set open(open) {
30424
- this._open.next(open);
30425
- }
30426
- get hasNotificationsToggle$() {
30427
- return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
30428
- }
30429
- get hasNotifications$() {
30430
- return this.notifications$.pipe(map(notifications => notifications.length > 0));
30431
- }
30432
- set config(config) {
30433
- this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
30434
- }
30435
- constructor() {
30436
- const notificationsService = this.notificationsService;
30437
- this.notifications$ = notificationsService.getNotificationsForContext('shell');
30438
- this._open.pipe(filter(open => open)).subscribe(() => {
30439
- this._pinned.next(false);
30440
- });
30441
- }
30442
- toggleOpen() {
30443
- this._open.next(!this._open.value);
30444
- }
30445
- togglePinned() {
30446
- this._pinned.next(!this._pinned.value);
30447
- }
30448
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30449
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
30450
- }
30451
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
30452
- type: Injectable
30453
- }], ctorParameters: () => [] });
30454
-
30455
- // @ts-strict-ignore
30456
- class QdShellHeaderMinimizationService {
30457
- navigationService = inject(QdNavigationService);
30458
- breakpointService = inject(QdBreakpointService);
30459
- _headerMinimizedBreakpoints = ['sm', 'xs'];
30460
- _config;
30461
- _isInternal$ = new BehaviorSubject(false);
30462
- set config(config) {
30463
- this._config = config;
30464
- this._isInternal$.next(config.isInternal);
30465
- }
30466
- isHeaderMinimized$() {
30467
- const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
30468
- return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
30469
- }
30470
- _isMinimizedBreakpoint(breakpoint) {
30471
- return this._headerMinimizedBreakpoints.includes(breakpoint);
30472
- }
30473
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30474
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
30475
- }
30476
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
30477
- type: Injectable
30478
- }] });
30479
-
30480
31137
  // @ts-strict-ignore
30481
31138
  const loadJavascriptAsset = (path, scriptElementAttributes = {}) => {
30482
31139
  const scriptElement = document.createElement('script');
@@ -30844,6 +31501,7 @@ class QdShellServiceNavigationComponent {
30844
31501
  _config;
30845
31502
  _destroyed$ = new Subject();
30846
31503
  _attributesHaveBeenSet$ = new ReplaySubject(1);
31504
+ localeService = inject(QdLocaleService);
30847
31505
  ngOnInit() {
30848
31506
  loadJavascriptAsset(this.config?.javascriptAssetPath ?? DEFAULT_JAVASCRIPT_ASSET_PATH$1, {
30849
31507
  defer: '',
@@ -30858,9 +31516,7 @@ class QdShellServiceNavigationComponent {
30858
31516
  this.logPamsEnvironmentMissingError();
30859
31517
  }
30860
31518
  logPamsEnvironmentMissingError() {
30861
- console.error('QdShellServiceNavigationComponent - The service navigation could not be rendered because the ' +
30862
- 'pamsEnvrionment is missing. The pamsEnvironment has to be given in the shell service navigation config or ' +
30863
- 'has to be provided in the backend auth config!');
31519
+ console.error('Quadrel Framework | QdShell - Config key "pamsEnvironment" is required to render <qd-shell-service-navigation>. Provide it in the service-navigation config or via the backend auth config.');
30864
31520
  }
30865
31521
  setLanguageFromUrlAfterNavigation() {
30866
31522
  this.languageFromUrlService
@@ -30888,6 +31544,7 @@ class QdShellServiceNavigationComponent {
30888
31544
  this._destroyed$.complete();
30889
31545
  }
30890
31546
  handleLanguageChange($event) {
31547
+ this.localeService.setServiceNavigationLanguage($event.detail);
30891
31548
  this.useLanguage($event.detail);
30892
31549
  }
30893
31550
  handleLoginStatusChange($event) {
@@ -30934,6 +31591,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
30934
31591
  args: ['serviceNavigation']
30935
31592
  }] } });
30936
31593
 
31594
+ class QdShellServiceNavigationModule {
31595
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
31596
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
31597
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
31598
+ }
31599
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
31600
+ type: NgModule,
31601
+ args: [{
31602
+ imports: [CommonModule],
31603
+ declarations: [QdShellServiceNavigationComponent],
31604
+ exports: [QdShellServiceNavigationComponent],
31605
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
31606
+ }]
31607
+ }] });
31608
+
31609
+ // @ts-strict-ignore
31610
+ class QdNavigationService {
31611
+ router = inject(Router);
31612
+ activatedRoute = inject(ActivatedRoute);
31613
+ routeLeafSnapshot$;
31614
+ routeData$;
31615
+ routeComponentInstanceSubject = new ReplaySubject(1);
31616
+ constructor() {
31617
+ this.routeLeafSnapshot$ = this.router.events.pipe(filter(event => event instanceof NavigationEnd), map(() => this.activatedRoute), map(route => this.getLeafRoute(route).snapshot), filter(snapshot => snapshot.outlet === 'primary'));
31618
+ this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
31619
+ }
31620
+ getLeafRoute(route) {
31621
+ if (!route.firstChild)
31622
+ return route;
31623
+ return this.getLeafRoute(route.firstChild);
31624
+ }
31625
+ isHome$() {
31626
+ return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
31627
+ }
31628
+ getRouteParams$() {
31629
+ return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
31630
+ }
31631
+ getMergedRouteParams(snapshot) {
31632
+ if (!snapshot)
31633
+ return {};
31634
+ return {
31635
+ ...this.getMergedRouteParams(snapshot.parent),
31636
+ ...(snapshot.params || {})
31637
+ };
31638
+ }
31639
+ getPreviousHref$() {
31640
+ return this.routeData$.pipe(map(({ previousHref }) => previousHref));
31641
+ }
31642
+ navigate(commands, extras) {
31643
+ return this.router.navigate(commands, extras);
31644
+ }
31645
+ navigateByUrl(url, extras) {
31646
+ return this.router.navigateByUrl(url, extras);
31647
+ }
31648
+ updateRouteComponentInstance(routeComponentInstance) {
31649
+ this.routeComponentInstanceSubject.next(routeComponentInstance);
31650
+ }
31651
+ getRouteComponentInstance$() {
31652
+ return this.routeComponentInstanceSubject.asObservable();
31653
+ }
31654
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
31655
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
31656
+ }
31657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
31658
+ type: Injectable
31659
+ }], ctorParameters: () => [] });
31660
+
31661
+ // @ts-strict-ignore
31662
+ class QdShellLeftService {
31663
+ _hasNavigation = new BehaviorSubject(false);
31664
+ _isNavigationPinned = new BehaviorSubject(false);
31665
+ _isNavigationRolledOver = new BehaviorSubject(false);
31666
+ hasNavigation$ = this._hasNavigation.asObservable();
31667
+ isNavigationPinned$ = this._isNavigationPinned.asObservable();
31668
+ isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
31669
+ set config(config) {
31670
+ this._hasNavigation.next(config.navigation?.length > 0);
31671
+ }
31672
+ set isNavigationRolledOver(value) {
31673
+ this._isNavigationRolledOver.next(value);
31674
+ }
31675
+ togglePinnedNavigation() {
31676
+ this._isNavigationPinned.next(!this._isNavigationPinned.value);
31677
+ }
31678
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
31679
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
31680
+ }
31681
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
31682
+ type: Injectable
31683
+ }] });
31684
+
31685
+ class QdShellRightService {
31686
+ notificationsService = inject(QdNotificationsService);
31687
+ _open = new BehaviorSubject(false);
31688
+ _pinned = new BehaviorSubject(false);
31689
+ _hasNotificationsToggle = new BehaviorSubject(false);
31690
+ open$ = this._open.asObservable();
31691
+ pinned$ = this._pinned.asObservable();
31692
+ notifications$;
31693
+ set open(open) {
31694
+ this._open.next(open);
31695
+ }
31696
+ get hasNotificationsToggle$() {
31697
+ return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
31698
+ }
31699
+ get hasNotifications$() {
31700
+ return this.notifications$.pipe(map(notifications => notifications.length > 0));
31701
+ }
31702
+ set config(config) {
31703
+ this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
31704
+ }
31705
+ constructor() {
31706
+ const notificationsService = this.notificationsService;
31707
+ this.notifications$ = notificationsService.getNotificationsForContext('shell');
31708
+ this._open.pipe(filter(open => open)).subscribe(() => {
31709
+ this._pinned.next(false);
31710
+ });
31711
+ }
31712
+ toggleOpen() {
31713
+ this._open.next(!this._open.value);
31714
+ }
31715
+ togglePinned() {
31716
+ this._pinned.next(!this._pinned.value);
31717
+ }
31718
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
31719
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
31720
+ }
31721
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
31722
+ type: Injectable
31723
+ }], ctorParameters: () => [] });
31724
+
31725
+ // @ts-strict-ignore
31726
+ class QdShellHeaderMinimizationService {
31727
+ navigationService = inject(QdNavigationService);
31728
+ breakpointService = inject(QdBreakpointService);
31729
+ _headerMinimizedBreakpoints = ['sm', 'xs'];
31730
+ _config;
31731
+ _isInternal$ = new BehaviorSubject(false);
31732
+ set config(config) {
31733
+ this._config = config;
31734
+ this._isInternal$.next(config.isInternal);
31735
+ }
31736
+ isHeaderMinimized$() {
31737
+ const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
31738
+ return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
31739
+ }
31740
+ _isMinimizedBreakpoint(breakpoint) {
31741
+ return this._headerMinimizedBreakpoints.includes(breakpoint);
31742
+ }
31743
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
31744
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
31745
+ }
31746
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
31747
+ type: Injectable
31748
+ }] });
31749
+
30937
31750
  // @ts-strict-ignore
30938
31751
  const DEFAULT_LANGUAGE_LIST$1 = ['de', 'fr', 'it', 'en'];
30939
31752
  class QdShellHeaderWidgetService {
@@ -31406,7 +32219,7 @@ class QdShellHeaderComponent {
31406
32219
  }
31407
32220
  validateTitle() {
31408
32221
  if (this.config.title && typeof this.config.title === 'string') {
31409
- console.warn('QdUi | QdShellComponent - Title of type string is deprecated and will be removed in the next major release. Please Use the i18n key instead!');
32222
+ console.warn('Quadrel Framework | QdShell - "title" as a plain string is deprecated and will be removed in the next major release. Please use an i18n key instead.');
31410
32223
  }
31411
32224
  }
31412
32225
  async = async;
@@ -31442,7 +32255,7 @@ class QdShellNavigationLinkComponent {
31442
32255
  config;
31443
32256
  handleClick() {
31444
32257
  if (!this.config.handler) {
31445
- console.error('QD-UI | QdShell - Please provide a handler function for the navigation element!');
32258
+ console.error('Quadrel Framework | QdShell - Please provide a handler function for the navigation element.');
31446
32259
  return;
31447
32260
  }
31448
32261
  if (this.config.handler && !this.config.isCurrent)
@@ -31955,7 +32768,7 @@ class QdShellComponent {
31955
32768
  ngAfterViewInit() {
31956
32769
  // TODO: Remove in v17! The comments will be integrated in the QdPage.
31957
32770
  if (this.commentsComponent.length > 0)
31958
- console.warn('QD-UI | QdShell - Comments in the QdShell is deprecated and will be removed in v17. Will be part of QdPage.');
32771
+ console.warn('Quadrel Framework | QdShell - Using comments inside <qd-shell> is deprecated and will be removed in v17. Use <qd-page> instead.');
31959
32772
  this.closeShellRightIfCommentsDisappear();
31960
32773
  }
31961
32774
  closeShellRightIfCommentsDisappear() {
@@ -32016,21 +32829,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
32016
32829
  args: [QdCommentsComponent]
32017
32830
  }] } });
32018
32831
 
32019
- class QdShellServiceNavigationModule {
32020
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
32021
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
32022
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
32023
- }
32024
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
32025
- type: NgModule,
32026
- args: [{
32027
- imports: [CommonModule],
32028
- declarations: [QdShellServiceNavigationComponent],
32029
- exports: [QdShellServiceNavigationComponent],
32030
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
32031
- }]
32032
- }] });
32033
-
32034
32832
  function initializeBreadcrumbServices(breadcrumbsService, dialogBreadcrumbsService) {
32035
32833
  return () => {
32036
32834
  breadcrumbsService.initialize();
@@ -32464,11 +33262,11 @@ class QdPageStepComponent extends CdkStep {
32464
33262
  this._destroyed$.complete();
32465
33263
  }
32466
33264
  blockCdkInput(inputName) {
32467
- throw new Error(`QD-UI | QdPageStepComponent - The use of the ${inputName} attribute is not permitted. Please use QdPageStepConfig instead.`);
33265
+ throw new Error(`Quadrel Framework | QdPageStep - The use of the "${inputName}" attribute is not permitted. Please use QdPageStepConfig instead.`);
32468
33266
  }
32469
33267
  validateLabel() {
32470
33268
  if (!this.config?.label?.i18n)
32471
- console.error('QD-UI | QdPageStepComponent - Please provide a label for the step.');
33269
+ console.error('Quadrel Framework | QdPageStep - Please provide a label for the step.');
32472
33270
  }
32473
33271
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageStepComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32474
33272
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageStepComponent, isStandalone: true, selector: "qd-page-step", inputs: { config: "config", control: "control" }, host: { classAttribute: "qd-stepper" }, providers: [
@@ -32574,11 +33372,11 @@ class QdPageTabComponent extends CdkStep {
32574
33372
  this._destroyed$.complete();
32575
33373
  }
32576
33374
  blockCdkInput(inputName) {
32577
- throw new Error(`QD-UI | QdPageTabComponent - The use of the ${inputName} attribute is not permitted. Please use QdPageTabConfig instead.`);
33375
+ throw new Error(`Quadrel Framework | QdPageTab - The use of the "${inputName}" attribute is not permitted. Please use QdPageTabConfig instead.`);
32578
33376
  }
32579
33377
  validateLabel() {
32580
33378
  if (!this.config?.label?.i18n)
32581
- console.error('QD-UI | QdPageTabComponent - Please provide a label for the tab.');
33379
+ console.error('Quadrel Framework | QdPageTab - Please provide a label for the tab.');
32582
33380
  }
32583
33381
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
32584
33382
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageTabComponent, isStandalone: true, selector: "qd-page-tab", inputs: { config: "config", tabControl: "tabControl" }, providers: [
@@ -33026,11 +33824,11 @@ class QdQuickEditComponent {
33026
33824
  }
33027
33825
  validateSetup() {
33028
33826
  if (this.data != null && this.controlContainer != null)
33029
- console.warn('QdQuickEdit | Data is being ignored when used as FormArray');
33827
+ console.warn('Quadrel Framework | QdQuickEdit - Data is being ignored when used as FormArray.');
33030
33828
  if (!this.data && !this.controlContainer)
33031
- console.warn('QdQuickEdit | Either use QuickEdit as FormControl with formArrayName binding or provide data via input.');
33829
+ console.warn('Quadrel Framework | QdQuickEdit - Either use <qd-quick-edit> as a FormControl with formArrayName binding or provide data via input.');
33032
33830
  if (this.controlContainer && this.config.columns.some(column => column.validators != null))
33033
- console.warn('QdQuickEdit | Please provide validators in the specific FormControls directly for default validators to be added.');
33831
+ console.warn('Quadrel Framework | QdQuickEdit - Please provide validators in the specific FormControls directly for default validators to be added.');
33034
33832
  }
33035
33833
  redrawOnNextChange() {
33036
33834
  this.togglerDrawing = !this.togglerDrawing;
@@ -33283,5 +34081,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
33283
34081
  * Generated bundle index. Do not edit.
33284
34082
  */
33285
34083
 
33286
- export { APP_ENVIRONMENT, AVAILABLE_ICONS, BACKEND_ERROR_CODES, MockLocaleDatePipe, NavigationTileComponent, NavigationTilesComponent, QD_DIALOG_CONFIRMATION_RESOLVER_TOKEN, QD_FILE_MANAGER_TOKEN, QD_FILE_UPLOAD_MANAGER_TOKEN, QD_FORM_OPTIONS_RESOLVER, QD_PAGE_OBJECT_RESOLVER_TOKEN, QD_PAGE_STEP_RESOLVER_TOKEN, QD_POPOVER_TOP_FIRST, QD_SAFE_BOTTOM_OFFSET, QD_TABLE_DATA_RESOLVER_TOKEN, QD_UPLOAD_HTTP_OPTIONS, QdButtonComponent, QdButtonGhostDirective, QdButtonGridComponent, QdButtonLinkDirective, QdButtonModule, QdButtonStackButtonComponent, QdButtonStackComponent, QdCheckboxChipsComponent, QdCheckboxComponent, QdCheckboxesComponent, QdChipComponent, QdChipModule, QdColumnAutoFillDirective, QdColumnBreakBeforeDirective, QdColumnDirective, QdColumnDisableResponsiveColspansDirective, QdColumnFullGridWidthDirective, QdColumnNextInSameRowDirective, QdColumnsDirective, QdColumnsDisableAutoFillDirective, QdColumnsDisableResponsiveColspansDirective, QdColumnsMaxDirective, QdCommentsComponent, QdCommentsModule, QdConnectFormStateToPageDirective, QdConnectorTableContextDirective, QdConnectorTableFilterDirective, QdConnectorTableSearchDirective, QdContactCardComponent, QdContactCardModule, QdContainerPairsCaptionComponent, QdContainerPairsContainerComponent, QdContainerPairsHeaderComponent, QdContainerPairsItemComponent, QdContainerPairsValueComponent, QdContextService, QdCoreModule, QdDatepickerComponent, QdDialogActionComponent, QdDialogAuthSessionEndComponent, QdDialogAuthSessionEndService, QdDialogComponent, QdDialogConfirmationComponent, QdDialogConfirmationErrorDirective, QdDialogConfirmationInfoDirective, QdDialogConfirmationSuccessDirective, QdDialogModule, QdDialogRecordStepperComponent, QdDialogService, QdDialogSize, QdDisabledDirective, QdDropdownComponent, QdFileCollectorComponent, QdFileCollectorModule, QdFileSizePipe$1 as QdFileSizePipe, QdFileUploadComponent, QdFileUploadService, QdFilterComponent, QdFilterFormItemsComponent, QdFilterModule, QdFilterRestParamBuilder, QdFilterService, QdFormArray, QdFormBuilder, QdFormControl, QdFormGroup, QdFormModule, QdGridComponent, QdGridModule, QdHorizontalPairsCaptionComponent, QdHorizontalPairsComponent, QdHorizontalPairsItemComponent, QdHorizontalPairsValueComponent, QdIconButtonComponent, QdIconComponent, QdIconModule, QdImageComponent, QdImageModule, QdIndeterminateProgressBarComponent, QdInputComponent, QdListModule, QdMenuButtonComponent, QdMockBreakpointService, QdMockButtonComponent, QdMockButtonGhostDirective, QdMockButtonGridComponent, QdMockButtonLinkDirective, QdMockButtonModule, QdMockButtonStackButtonComponent, QdMockButtonStackComponent, QdMockCalendarComponent, QdMockCheckboxChipsComponent, QdMockCheckboxComponent, QdMockCheckboxesComponent, QdMockChipComponent, QdMockChipModule, QdMockColumnDirective, QdMockColumnsDirective, QdMockContactCardComponent, QdMockContactCardModule, QdMockContainerPairsCaptionComponent, QdMockContainerPairsContainerComponent, QdMockContainerPairsHeaderComponent, QdMockContainerPairsItemComponent, QdMockContainerPairsValueComponent, QdMockCoreModule, QdMockCounterBadgeComponent, QdMockDatepickerComponent, QdMockDisabledDirective, QdMockDropdownComponent, QdMockFileCollectorComponent, QdMockFileCollectorModule, QdMockFilterCategoryBooleanComponent, QdMockFilterCategoryComponent, QdMockFilterCategoryDateComponent, QdMockFilterCategoryDateRangeComponent, QdMockFilterCategoryFreeTextComponent, QdMockFilterCategorySelectComponent, QdMockFilterComponent, QdMockFilterFormItemsComponent, QdMockFilterItemBooleanComponent, QdMockFilterItemDateComponent, QdMockFilterItemDateRangeComponent, QdMockFilterItemFreeTextComponent, QdMockFilterItemMultiSelectComponent, QdMockFilterItemSingleSelectComponent, QdMockFilterModule, QdMockFilterService, QdMockFormErrorComponent, QdMockFormGroupErrorComponent, QdMockFormHintComponent, QdMockFormLabelComponent, QdMockFormReadonlyComponent, QdMockFormViewonlyComponent, QdMockFormsModule, QdMockGridModule, QdMockIconButtonComponent, QdMockIconComponent, QdMockIconModule, QdMockImageComponent, QdMockImageModule, QdMockIndeterminateProgressBarComponent, QdMockInputComponent, QdMockListModule, QdMockNavigationTileComponent, QdMockNavigationTilesComponent, QdMockNavigationTilesModule, QdMockNotificationComponent, QdMockNotificationContentComponent, QdMockNotificationsComponent, QdMockNotificationsModule, QdMockNotificationsService, QdMockPageComponent, QdMockPageModule, QdMockPercentageProgressBarComponent, QdMockPinCodeComponent, QdMockPlaceHolderModule, QdMockPopoverOnClickDirective, QdMockProgressBarModule, QdMockQdPlaceHolderComponent, QdMockRadioButtonsComponent, QdMockRwdDisabledDirective, QdMockSearchComponent, QdMockSearchModule, QdMockSectionComponent, QdMockSectionModule, QdMockShellComponent, QdMockShellFooterComponent, QdMockShellHeaderBannerComponent, QdMockShellHeaderComponent, QdMockShellHeaderSearchComponent, QdMockShellHeaderWidgetComponent, QdMockShellModule, QdMockShellToolbarComponent, QdMockShellToolbarItemComponent, QdMockStatusIndicatorCaptionComponent, QdMockStatusIndicatorComponent, QdMockStatusIndicatorItemComponent, QdMockStatusIndicatorModule, QdMockStatusPairsCaptionComponent, QdMockStatusPairsComponent, QdMockStatusPairsErrorComponent, QdMockStatusPairsItemComponent, QdMockStatusPairsValueComponent, QdMockSwitchComponent, QdMockSwitchesComponent, QdMockTableComponent, QdMockTableModule, QdMockTextSectionComponent, QdMockTextSectionHeadlineComponent, QdMockTextSectionModule, QdMockTextSectionParagraphComponent, QdMockTextareaComponent, QdMockTileButtonListComponent, QdMockTileComponent, QdMockTileTextListComponent, QdMockTileTextListItemComponent, QdMockTileTitleComponent, QdMockTilesContainerComponent, QdMockTilesContainerTitleComponent, QdMockTilesModule, QdMockTranslatePipe, QdMockVisuallyHiddenDirective, QdMultiInputComponent, QdNavigationTilesModule, QdNotificationComponent, QdNotificationContentComponent, QdNotificationsComponent, QdNotificationsHttpInterceptorService, QdNotificationsModule, QdNotificationsService, QdNotificationsSnackbarListenerDirective, QdPageComponent, QdPageControlPanelComponent, QdPageFooterComponent, QdPageFooterCustomContentDirective, QdPageInfoBannerComponent, QdPageModule, QdPageStepComponent, QdPageStepperAdapterDirective, QdPageStepperComponent, QdPageStepperModule, QdPageStoreService, QdPageTabComponent, QdPageTabsAdapterDirective, QdPageTabsComponent, QdPageTabsModule, QdPanelSectionActionsComponent, QdPanelSectionComponent, QdPanelSectionModule, QdPanelSectionStatusComponent, QdPanelSectionTextParagraphComponent, QdPendingChangesGuardDirective, QdPercentageProgressBarComponent, QdPinCodeComponent, QdPlaceHolderComponent, QdPlaceHolderModule, QdPlaceholderPipe, QdProgressBarModule, QdProjectionGuardComponent, QdPushEventsService, QdQuickEditComponent, QdQuickEditModule, QdRadioButtonsComponent, QdRichtextComponent, QdRwdDisabledDirective, QdSearchComponent, QdSearchModule, QdSectionAdapterDirective, QdSectionComponent, QdSectionModule, QdSectionToolbarComponent, QdShellComponent, QdShellModule, QdSortDirection, QdSpinnerComponent, QdSpinnerModule, QdStatusIndicatorComponent, QdStatusIndicatorModule, QdStatusPairsCaptionComponent, QdStatusPairsComponent, QdStatusPairsErrorComponent, QdStatusPairsItemComponent, QdStatusPairsValueComponent, QdSubgridComponent, QdSwitchComponent, QdSwitchesComponent, QdTableComponent, QdTableModule, QdTableSpringTools, QdTextSectionComponent, QdTextSectionHeadlineComponent, QdTextSectionModule, QdTextSectionParagraphComponent, QdTextareaComponent, QdTileButtonListComponent, QdTileComponent, QdTileTextListComponent, QdTileTextListItemComponent, QdTileTitleComponent, QdTilesComponent, QdTilesModule, QdTilesTitleComponent, QdTooltipAtIntersectionDirective, QdTooltipIconComponent, QdTreeComponent, QdTreeModule, QdTreeRowExpanderService, QdUiMockModule, QdUiModule, QdUploadErrorType, QdValidators, QdViewportAdaptiveDirective, QdVisuallyHiddenDirective, chipColorDefault, createMetadataStream, updateHtmlLang };
34084
+ export { APP_ENVIRONMENT, AVAILABLE_ICONS, BACKEND_ERROR_CODES, MockLocaleDatePipe, NavigationTileComponent, NavigationTilesComponent, QD_DIALOG_CONFIRMATION_RESOLVER_TOKEN, QD_FILE_MANAGER_TOKEN, QD_FILE_UPLOAD_MANAGER_TOKEN, QD_FORM_OPTIONS_RESOLVER, QD_PAGE_OBJECT_RESOLVER_TOKEN, QD_PAGE_STEP_RESOLVER_TOKEN, QD_POPOVER_TOP_FIRST, QD_SAFE_BOTTOM_OFFSET, QD_TABLE_DATA_RESOLVER_TOKEN, QD_UPLOAD_HTTP_OPTIONS, QdButtonComponent, QdButtonGhostDirective, QdButtonGridComponent, QdButtonLinkDirective, QdButtonModule, QdButtonStackButtonComponent, QdButtonStackComponent, QdCheckboxChipsComponent, QdCheckboxComponent, QdCheckboxesComponent, QdChipComponent, QdChipModule, QdColumnAutoFillDirective, QdColumnBreakBeforeDirective, QdColumnDirective, QdColumnDisableResponsiveColspansDirective, QdColumnFullGridWidthDirective, QdColumnNextInSameRowDirective, QdColumnsDirective, QdColumnsDisableAutoFillDirective, QdColumnsDisableResponsiveColspansDirective, QdColumnsMaxDirective, QdCommentsComponent, QdCommentsModule, QdConnectFormStateToPageDirective, QdConnectorTableContextDirective, QdConnectorTableFilterDirective, QdConnectorTableSearchDirective, QdContactCardComponent, QdContactCardModule, QdContainerPairsCaptionComponent, QdContainerPairsContainerComponent, QdContainerPairsHeaderComponent, QdContainerPairsItemComponent, QdContainerPairsValueComponent, QdContextService, QdCoreModule, QdDatepickerComponent, QdDialogActionComponent, QdDialogAuthSessionEndComponent, QdDialogAuthSessionEndService, QdDialogComponent, QdDialogConfirmationComponent, QdDialogConfirmationErrorDirective, QdDialogConfirmationInfoDirective, QdDialogConfirmationSuccessDirective, QdDialogModule, QdDialogRecordStepperComponent, QdDialogService, QdDialogSize, QdDisabledDirective, QdDropdownComponent, QdFileCollectorComponent, QdFileCollectorModule, QdFileSizePipe$1 as QdFileSizePipe, QdFileUploadComponent, QdFileUploadService, QdFilterComponent, QdFilterFormItemsComponent, QdFilterModule, QdFilterRestParamBuilder, QdFilterService, QdFormArray, QdFormBuilder, QdFormControl, QdFormGroup, QdFormModule, QdGridComponent, QdGridModule, QdHorizontalPairsCaptionComponent, QdHorizontalPairsComponent, QdHorizontalPairsItemComponent, QdHorizontalPairsValueComponent, QdIconButtonComponent, QdIconComponent, QdIconModule, QdImageComponent, QdImageModule, QdIndeterminateProgressBarComponent, QdInputComponent, QdListModule, QdMenuButtonComponent, QdMockBreakpointService, QdMockButtonComponent, QdMockButtonGhostDirective, QdMockButtonGridComponent, QdMockButtonLinkDirective, QdMockButtonModule, QdMockButtonStackButtonComponent, QdMockButtonStackComponent, QdMockCalendarComponent, QdMockCheckboxChipsComponent, QdMockCheckboxComponent, QdMockCheckboxesComponent, QdMockChipComponent, QdMockChipModule, QdMockColumnDirective, QdMockColumnsDirective, QdMockContactCardComponent, QdMockContactCardModule, QdMockContainerPairsCaptionComponent, QdMockContainerPairsContainerComponent, QdMockContainerPairsHeaderComponent, QdMockContainerPairsItemComponent, QdMockContainerPairsValueComponent, QdMockCoreModule, QdMockCounterBadgeComponent, QdMockDatepickerComponent, QdMockDisabledDirective, QdMockDropdownComponent, QdMockFileCollectorComponent, QdMockFileCollectorModule, QdMockFilterCategoryBooleanComponent, QdMockFilterCategoryComponent, QdMockFilterCategoryDateComponent, QdMockFilterCategoryDateRangeComponent, QdMockFilterCategoryFreeTextComponent, QdMockFilterCategorySelectComponent, QdMockFilterComponent, QdMockFilterFormItemsComponent, QdMockFilterItemBooleanComponent, QdMockFilterItemDateComponent, QdMockFilterItemDateRangeComponent, QdMockFilterItemFreeTextComponent, QdMockFilterItemMultiSelectComponent, QdMockFilterItemSingleSelectComponent, QdMockFilterModule, QdMockFilterService, QdMockFormErrorComponent, QdMockFormGroupErrorComponent, QdMockFormHintComponent, QdMockFormLabelComponent, QdMockFormReadonlyComponent, QdMockFormViewonlyComponent, QdMockFormsModule, QdMockGridModule, QdMockIconButtonComponent, QdMockIconComponent, QdMockIconModule, QdMockImageComponent, QdMockImageModule, QdMockIndeterminateProgressBarComponent, QdMockInputComponent, QdMockListModule, QdMockNavigationTileComponent, QdMockNavigationTilesComponent, QdMockNavigationTilesModule, QdMockNotificationComponent, QdMockNotificationContentComponent, QdMockNotificationsComponent, QdMockNotificationsModule, QdMockNotificationsService, QdMockPageComponent, QdMockPageModule, QdMockPercentageProgressBarComponent, QdMockPinCodeComponent, QdMockPlaceHolderModule, QdMockPopoverOnClickDirective, QdMockProgressBarModule, QdMockQdPlaceHolderComponent, QdMockRadioButtonsComponent, QdMockRwdDisabledDirective, QdMockSearchComponent, QdMockSearchModule, QdMockSectionComponent, QdMockSectionModule, QdMockShellComponent, QdMockShellFooterComponent, QdMockShellHeaderBannerComponent, QdMockShellHeaderComponent, QdMockShellHeaderSearchComponent, QdMockShellHeaderWidgetComponent, QdMockShellModule, QdMockShellToolbarComponent, QdMockShellToolbarItemComponent, QdMockStatusIndicatorCaptionComponent, QdMockStatusIndicatorComponent, QdMockStatusIndicatorItemComponent, QdMockStatusIndicatorModule, QdMockStatusPairsCaptionComponent, QdMockStatusPairsComponent, QdMockStatusPairsErrorComponent, QdMockStatusPairsItemComponent, QdMockStatusPairsValueComponent, QdMockSwitchComponent, QdMockSwitchesComponent, QdMockTableComponent, QdMockTableModule, QdMockTextSectionComponent, QdMockTextSectionHeadlineComponent, QdMockTextSectionModule, QdMockTextSectionParagraphComponent, QdMockTextareaComponent, QdMockTileButtonListComponent, QdMockTileComponent, QdMockTileTextListComponent, QdMockTileTextListItemComponent, QdMockTileTitleComponent, QdMockTilesContainerComponent, QdMockTilesContainerTitleComponent, QdMockTilesModule, QdMockTranslatePipe, QdMockVisuallyHiddenDirective, QdMultiInputComponent, QdNavigationTilesModule, QdNotificationComponent, QdNotificationContentComponent, QdNotificationsComponent, QdNotificationsHttpInterceptorService, QdNotificationsModule, QdNotificationsService, QdNotificationsSnackbarListenerDirective, QdNumberInputService, QdPageComponent, QdPageControlPanelComponent, QdPageFooterComponent, QdPageFooterCustomContentDirective, QdPageInfoBannerComponent, QdPageModule, QdPageStepComponent, QdPageStepperAdapterDirective, QdPageStepperComponent, QdPageStepperModule, QdPageStoreService, QdPageTabComponent, QdPageTabsAdapterDirective, QdPageTabsComponent, QdPageTabsModule, QdPanelSectionActionsComponent, QdPanelSectionComponent, QdPanelSectionModule, QdPanelSectionStatusComponent, QdPanelSectionTextParagraphComponent, QdPendingChangesGuardDirective, QdPercentageProgressBarComponent, QdPinCodeComponent, QdPlaceHolderComponent, QdPlaceHolderModule, QdPlaceholderPipe, QdProgressBarModule, QdProjectionGuardComponent, QdPushEventsService, QdQuickEditComponent, QdQuickEditModule, QdRadioButtonsComponent, QdRichtextComponent, QdRouterQueryParamHubService, QdRwdDisabledDirective, QdSearchComponent, QdSearchModule, QdSectionAdapterDirective, QdSectionComponent, QdSectionModule, QdSectionToolbarComponent, QdShellComponent, QdShellModule, QdSortDirection, QdSpinnerComponent, QdSpinnerModule, QdStatusIndicatorComponent, QdStatusIndicatorModule, QdStatusPairsCaptionComponent, QdStatusPairsComponent, QdStatusPairsErrorComponent, QdStatusPairsItemComponent, QdStatusPairsValueComponent, QdSubgridComponent, QdSwitchComponent, QdSwitchesComponent, QdTableComponent, QdTableModule, QdTableSpringTools, QdTextSectionComponent, QdTextSectionHeadlineComponent, QdTextSectionModule, QdTextSectionParagraphComponent, QdTextareaComponent, QdTileButtonListComponent, QdTileComponent, QdTileTextListComponent, QdTileTextListItemComponent, QdTileTitleComponent, QdTilesComponent, QdTilesModule, QdTilesTitleComponent, QdTooltipAtIntersectionDirective, QdTooltipIconComponent, QdTreeComponent, QdTreeModule, QdTreeRowExpanderService, QdUiMockModule, QdUiModule, QdUploadErrorType, QdValidators, QdViewportAdaptiveDirective, QdVisuallyHiddenDirective, chipColorDefault, createMetadataStream, updateHtmlLang };
33287
34085
  //# sourceMappingURL=quadrel-enterprise-ui-framework.mjs.map