@quadrel-enterprise-ui/framework 20.14.0 → 20.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,8 +18,8 @@ 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 { EventSourcePolyfill } from 'event-source-polyfill';
22
21
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
22
+ import { EventSourcePolyfill } from 'event-source-polyfill';
23
23
  import { DomSanitizer } from '@angular/platform-browser';
24
24
  import * as i3$1 from 'ngx-editor';
25
25
  import { Editor, NgxEditorModule } from 'ngx-editor';
@@ -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,6 +6707,8 @@ 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;
@@ -6715,406 +6737,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6715
6737
  type: Input
6716
6738
  }] } });
6717
6739
 
6718
- class QdRwdDisabledDirective {
6719
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRwdDisabledDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
6720
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdRwdDisabledDirective, isStandalone: false, selector: "[qdRwdDisabled]", host: { classAttribute: "qd-rwd-disabled" }, ngImport: i0 });
6721
- }
6722
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRwdDisabledDirective, decorators: [{
6723
- type: Directive,
6724
- args: [{
6725
- selector: '[qdRwdDisabled]',
6726
- host: { class: 'qd-rwd-disabled' },
6727
- standalone: false
6728
- }]
6729
- }] });
6730
-
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"] }] });
6759
- }
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
- }] } });
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();
6800
- }
6801
- ngOnDestroy() {
6802
- this._observer$.unobserve(this._target);
6803
- this._destroyed$.next();
6804
- this._destroyed$.complete();
6805
- }
6806
- setTarget() {
6807
- this._target = this._host.nativeElement.querySelector(TARGET_SELECTOR);
6808
- }
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);
6823
- }
6824
- _setStyles() {
6825
- this._target.style.overflow = 'hidden';
6826
- this._target.style.textOverflow = 'ellipsis';
6827
- this._target.style.cursor = 'help';
6828
- }
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
- });
6836
- }
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
- });
6846
- }
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());
6851
- }
6852
- getContent() {
6853
- return {
6854
- headline: this._target.getAttribute('data-tooltip-headline') || undefined,
6855
- paragraphs: [this._target.textContent?.trim() || '']
6856
- };
6857
- }
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 });
6872
- }
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
- }] });
6881
-
6882
- /**
6883
- * Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
6884
- *
6885
- * All service endpoints — including SSE — must be protected. The connection is therefore secured
6886
- * via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
6887
- * transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
6888
- *
6889
- * ### Reconnection behavior
6890
- *
6891
- * - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
6892
- * - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
6893
- * - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
6894
- *
6895
- * Existing `observe()` subscriptions are preserved across reconnections.
6896
- *
6897
- * ### Usage
6898
- *
6899
- * ```ts
6900
- * pushEventsService.connect('https://api.example.com/events');
6901
- *
6902
- * const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
6903
- *
6904
- * sub.unsubscribe();
6905
- * pushEventsService.disconnect();
6906
- * ```
6907
- */
6908
- class QdPushEventsService {
6909
- authenticationService = inject('QdAuthenticationService', { optional: true });
6910
- _eventSource;
6911
- _subjects = new Map();
6912
- _listeners = [];
6913
- _accessTokenSub;
6914
- _options;
6915
- _heartbeatTimeout;
6916
- _heartbeatGracePeriod = 100;
6917
- _initialHeartbeatTimeout = 10000;
6918
- _isUnauthorized = false;
6919
- _reconnectAttempts = 0;
6920
- _maxReconnectAttempts = 5;
6921
- _backoffTimer;
6922
- /**
6923
- * Opens an SSE connection to the given URL.
6924
- *
6925
- * With authentication enabled (default), the service subscribes to the `accessToken$` observable
6926
- * provided by Quadrel Auth and rebuilds the connection whenever the token changes.
6927
- * No-op if already connected.
6928
- *
6929
- * @param url The SSE endpoint URL.
6930
- * @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
6931
- *
6932
- * @example
6933
- * ```ts
6934
- * // Authenticated (default — requires Quadrel Auth)
6935
- * pushEventsService.connect('https://api.example.com/events');
6936
- *
6937
- * // Without authentication (only for public endpoints)
6938
- * pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
6939
- * ```
6940
- */
6941
- connect(url, options) {
6942
- if (this.isConnectedOrConnecting())
6943
- return;
6944
- this._options = { url, options };
6945
- if (options?.disableAuthentication) {
6946
- this.openEventSource(url);
6947
- }
6948
- else {
6949
- this.connectWithAuth(url);
6950
- }
6951
- }
6952
- /**
6953
- * Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
6954
- * Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
6955
- *
6956
- * @example
6957
- * ```ts
6958
- * pushEventsService.disconnect();
6959
- * // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
6960
- * ```
6961
- */
6962
- disconnect() {
6963
- if (!this._eventSource) {
6964
- this.logWarn('No active connection to disconnect.');
6965
- return;
6966
- }
6967
- if (this._accessTokenSub) {
6968
- this._accessTokenSub.unsubscribe();
6969
- this._accessTokenSub = undefined;
6970
- }
6971
- if (this._heartbeatTimeout)
6972
- clearTimeout(this._heartbeatTimeout);
6973
- if (this._backoffTimer) {
6974
- clearTimeout(this._backoffTimer);
6975
- this._backoffTimer = undefined;
6976
- }
6977
- this.removeAllListeners();
6978
- this._eventSource.close();
6979
- }
6980
- /**
6981
- * Returns an Observable that emits whenever the server sends an event of the given type.
6982
- *
6983
- * Lazily registers an EventSource listener on first call per event name.
6984
- * Returns `NEVER` and logs an error if no connection exists.
6985
- *
6986
- * @param eventName The SSE event type to listen for.
6987
- *
6988
- * @example
6989
- * ```ts
6990
- * pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
6991
- * ```
6992
- */
6993
- observe(eventName) {
6994
- if (!this._eventSource) {
6995
- this.logWarn('Cannot observe events without a connection. Call connect() first.');
6996
- return NEVER;
6997
- }
6998
- if (!this._subjects.has(eventName)) {
6999
- this._subjects.set(eventName, new Subject());
7000
- this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
7001
- }
7002
- return this._subjects.get(eventName).asObservable();
7003
- }
7004
- /**
7005
- * Removes all event listeners and clears all subscription subjects. The connection stays open.
7006
- * Use this to reset all subscriptions without disconnecting the SSE stream.
7007
- *
7008
- * @example
7009
- * ```ts
7010
- * pushEventsService.unobserveAll();
7011
- * // Connection remains open, but no events are forwarded until observe() is called again.
7012
- * ```
7013
- */
7014
- unobserveAll() {
7015
- this.removeAllListeners();
7016
- this._subjects.clear();
7017
- }
7018
- /** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
7019
- isConnectedOrConnecting() {
7020
- return (this._eventSource &&
7021
- (this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
7022
- }
7023
- connectWithAuth(url) {
7024
- if (!this.authenticationService) {
7025
- this.logError("Can't connect to SSE without Quadrel Auth as the connection has to be secured. Please install Quadrel Auth or disable authentication when connecting.");
7026
- return;
7027
- }
7028
- this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
7029
- this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
7030
- });
7031
- }
7032
- openEventSource(url, options = {}) {
7033
- this._isUnauthorized = false;
7034
- if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
7035
- this._eventSource.close();
7036
- this._eventSource = new EventSourcePolyfill(url, options);
7037
- this._eventSource.onerror = (err) => this.handleError(err);
7038
- this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
7039
- if (this._heartbeatTimeout)
7040
- clearTimeout(this._heartbeatTimeout);
7041
- this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
7042
- if (this._backoffTimer) {
7043
- clearTimeout(this._backoffTimer);
7044
- this._backoffTimer = undefined;
7045
- }
7046
- this._listeners = [];
7047
- this.reattachListeners();
7048
- }
7049
- reconnect() {
7050
- if (this.isConnectedOrConnecting() || this._isUnauthorized)
7051
- return;
7052
- this.disconnect();
7053
- this.connect(this._options.url, this._options.options);
7054
- }
7055
- handleError(err) {
7056
- const status = err?.status || err?.target?.status;
7057
- if (status === 401) {
7058
- this._isUnauthorized = true;
7059
- this.logError('SSE connection unauthorized (401):', err);
7060
- this._eventSource.close();
7061
- this.scheduleRetry();
7062
- return;
7063
- }
7064
- if (this._eventSource.readyState === EventSource.CLOSED)
7065
- this.reconnect();
7066
- this.logError('SSE connection error:', err);
7067
- }
7068
- scheduleRetry() {
7069
- if (this._reconnectAttempts >= this._maxReconnectAttempts) {
7070
- this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
7071
- return;
7072
- }
7073
- const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
7074
- this._reconnectAttempts++;
7075
- this._backoffTimer = setTimeout(() => {
7076
- this._isUnauthorized = false;
7077
- this.reconnect();
7078
- }, delay);
7079
- }
7080
- handleHeartbeat(message) {
7081
- if (this._isUnauthorized)
7082
- return;
7083
- if (this._heartbeatTimeout)
7084
- clearTimeout(this._heartbeatTimeout);
7085
- this._reconnectAttempts = 0;
7086
- const interval = JSON.parse(message.data).interval;
7087
- this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
7088
- }
7089
- addListener(eventName, callback) {
7090
- this._eventSource.addEventListener(eventName, callback);
7091
- this._listeners.push([eventName, callback]);
7092
- }
7093
- reattachListeners() {
7094
- this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
7095
- }
7096
- removeAllListeners() {
7097
- if (!this._eventSource)
7098
- return;
7099
- this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
7100
- this._listeners = [];
7101
- }
7102
- logWarn(message) {
7103
- console.warn(`Quadrel Framework | QdPushEvents - ${message}`);
7104
- }
7105
- logError(message, err) {
7106
- console.error(`Quadrel Framework | QdPushEvents - ${message}`, err);
7107
- }
7108
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7109
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
7110
- }
7111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, decorators: [{
7112
- type: Injectable,
7113
- args: [{
7114
- providedIn: 'root'
7115
- }]
7116
- }] });
7117
-
7118
6740
  /**
7119
6741
  * Framework-wide funnel for syncing application state with the URL `?key=value` query string.
7120
6742
  *
@@ -7404,6 +7026,511 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7404
7026
  args: [{ providedIn: 'root' }]
7405
7027
  }], ctorParameters: () => [] });
7406
7028
 
7029
+ class QdRwdDisabledDirective {
7030
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRwdDisabledDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7031
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdRwdDisabledDirective, isStandalone: false, selector: "[qdRwdDisabled]", host: { classAttribute: "qd-rwd-disabled" }, ngImport: i0 });
7032
+ }
7033
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRwdDisabledDirective, decorators: [{
7034
+ type: Directive,
7035
+ args: [{
7036
+ selector: '[qdRwdDisabled]',
7037
+ host: { class: 'qd-rwd-disabled' },
7038
+ standalone: false
7039
+ }]
7040
+ }] });
7041
+
7042
+ class QdLocaleService {
7043
+ _serviceNavLanguage$ = new BehaviorSubject(null);
7044
+ locale$ = this._serviceNavLanguage$.pipe(map(serviceNavLanguage => determineLocale(serviceNavLanguage, navigator.languages)));
7045
+ setServiceNavigationLanguage(language) {
7046
+ this._serviceNavLanguage$.next(language);
7047
+ }
7048
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7049
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, providedIn: 'root' });
7050
+ }
7051
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, decorators: [{
7052
+ type: Injectable,
7053
+ args: [{ providedIn: 'root' }]
7054
+ }] });
7055
+
7056
+ class QdNumberInputService {
7057
+ _locale;
7058
+ _decimalSeparator;
7059
+ _groupSeparator;
7060
+ localeService = inject(QdLocaleService, { optional: true });
7061
+ destroyRef = inject(DestroyRef);
7062
+ ambiguityHintKeyDot = 'i18n.qd.input.number.ambiguousHint.dot';
7063
+ ambiguityHintKeyComma = 'i18n.qd.input.number.ambiguousHint.comma';
7064
+ invalidCharactersErrorKeyComma = 'i18n.qd.input.number.invalidCharacters.comma';
7065
+ invalidCharactersErrorKeyDot = 'i18n.qd.input.number.invalidCharacters.dot';
7066
+ get invalidCharactersErrorKey() {
7067
+ return this._decimalSeparator === ',' ? this.invalidCharactersErrorKeyComma : this.invalidCharactersErrorKeyDot;
7068
+ }
7069
+ get decimalSeparator() {
7070
+ return this._decimalSeparator;
7071
+ }
7072
+ get groupSeparator() {
7073
+ return this._groupSeparator;
7074
+ }
7075
+ constructor() {
7076
+ if (this.localeService) {
7077
+ this.localeService.locale$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(locale => {
7078
+ this.detectSeparatorsForLocale(locale);
7079
+ });
7080
+ }
7081
+ else {
7082
+ this.detectSeparators();
7083
+ }
7084
+ }
7085
+ detectSeparators() {
7086
+ const locale = navigator.languages && navigator.languages.length ? navigator.languages[0] : navigator.language;
7087
+ this.detectSeparatorsForLocale(locale);
7088
+ }
7089
+ isValidNumber(value) {
7090
+ if (!value)
7091
+ return false;
7092
+ const escaped = this._decimalSeparator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
7093
+ return new RegExp(`^-?\\d+(${escaped}\\d+)?$`).test(value);
7094
+ }
7095
+ detectSeparatorsForLocale(locale) {
7096
+ this._locale = locale;
7097
+ const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
7098
+ this._decimalSeparator = parts.find(p => p.type === 'decimal')?.value ?? '.';
7099
+ this._groupSeparator = parts.find(p => p.type === 'group')?.value ?? ',';
7100
+ }
7101
+ filterValue(value) {
7102
+ let result = '';
7103
+ let hasDecimal = false;
7104
+ for (let i = 0; i < value.length; i++) {
7105
+ const char = value[i];
7106
+ if (char >= '0' && char <= '9') {
7107
+ result += char;
7108
+ }
7109
+ else if (char === this._decimalSeparator && !hasDecimal) {
7110
+ result += char;
7111
+ hasDecimal = true;
7112
+ }
7113
+ else if (char === '-' && i === 0) {
7114
+ result += char;
7115
+ }
7116
+ }
7117
+ return result;
7118
+ }
7119
+ parseValue(value) {
7120
+ if (!value)
7121
+ return value;
7122
+ const normalized = value.split(this._groupSeparator).join('').replace(this._decimalSeparator, '.');
7123
+ const parsed = parseFloat(normalized);
7124
+ return isNaN(parsed) ? value : parsed;
7125
+ }
7126
+ isAmbiguous(value) {
7127
+ if (typeof value !== 'string' || !value)
7128
+ return false;
7129
+ return /^-?[1-9]\d*[.,]\d{3}$/.test(value);
7130
+ }
7131
+ getAmbiguityHintKey(value) {
7132
+ if (typeof value === 'string' && value.includes('.'))
7133
+ return this.ambiguityHintKeyDot;
7134
+ return this.ambiguityHintKeyComma;
7135
+ }
7136
+ formatNumberForViewonly(value) {
7137
+ if (value == null || value === '')
7138
+ return '';
7139
+ const str = String(value);
7140
+ const parsed = typeof value === 'number' ? value : this.parseValue(str);
7141
+ if (typeof parsed !== 'number')
7142
+ return str;
7143
+ return new Intl.NumberFormat(this._locale).format(parsed);
7144
+ }
7145
+ formatValueForDisplay(value) {
7146
+ if (value == null || value === '')
7147
+ return '';
7148
+ const str = String(value);
7149
+ if (this._decimalSeparator === '.')
7150
+ return str;
7151
+ return str.replace('.', this._decimalSeparator);
7152
+ }
7153
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7154
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService });
7155
+ }
7156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, decorators: [{
7157
+ type: Injectable
7158
+ }], ctorParameters: () => [] });
7159
+
7160
+ /**
7161
+ * Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
7162
+ *
7163
+ * All service endpoints — including SSE — must be protected. The connection is therefore secured
7164
+ * via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
7165
+ * transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
7166
+ *
7167
+ * ### Reconnection behavior
7168
+ *
7169
+ * - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
7170
+ * - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
7171
+ * - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
7172
+ *
7173
+ * Existing `observe()` subscriptions are preserved across reconnections.
7174
+ *
7175
+ * ### Usage
7176
+ *
7177
+ * ```ts
7178
+ * pushEventsService.connect('https://api.example.com/events');
7179
+ *
7180
+ * const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
7181
+ *
7182
+ * sub.unsubscribe();
7183
+ * pushEventsService.disconnect();
7184
+ * ```
7185
+ */
7186
+ class QdPushEventsService {
7187
+ authenticationService = inject('QdAuthenticationService', { optional: true });
7188
+ _eventSource;
7189
+ _subjects = new Map();
7190
+ _listeners = [];
7191
+ _accessTokenSub;
7192
+ _options;
7193
+ _heartbeatTimeout;
7194
+ _heartbeatGracePeriod = 100;
7195
+ _initialHeartbeatTimeout = 10000;
7196
+ _isUnauthorized = false;
7197
+ _reconnectAttempts = 0;
7198
+ _maxReconnectAttempts = 5;
7199
+ _backoffTimer;
7200
+ /**
7201
+ * Opens an SSE connection to the given URL.
7202
+ *
7203
+ * With authentication enabled (default), the service subscribes to the `accessToken$` observable
7204
+ * provided by Quadrel Auth and rebuilds the connection whenever the token changes.
7205
+ * No-op if already connected.
7206
+ *
7207
+ * @param url The SSE endpoint URL.
7208
+ * @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
7209
+ *
7210
+ * @example
7211
+ * ```ts
7212
+ * // Authenticated (default — requires Quadrel Auth)
7213
+ * pushEventsService.connect('https://api.example.com/events');
7214
+ *
7215
+ * // Without authentication (only for public endpoints)
7216
+ * pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
7217
+ * ```
7218
+ */
7219
+ connect(url, options) {
7220
+ if (this.isConnectedOrConnecting())
7221
+ return;
7222
+ this._options = { url, options };
7223
+ if (options?.disableAuthentication) {
7224
+ this.openEventSource(url);
7225
+ }
7226
+ else {
7227
+ this.connectWithAuth(url);
7228
+ }
7229
+ }
7230
+ /**
7231
+ * Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
7232
+ * Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
7233
+ *
7234
+ * @example
7235
+ * ```ts
7236
+ * pushEventsService.disconnect();
7237
+ * // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
7238
+ * ```
7239
+ */
7240
+ disconnect() {
7241
+ if (!this._eventSource) {
7242
+ this.logWarn('No active connection to disconnect.');
7243
+ return;
7244
+ }
7245
+ if (this._accessTokenSub) {
7246
+ this._accessTokenSub.unsubscribe();
7247
+ this._accessTokenSub = undefined;
7248
+ }
7249
+ if (this._heartbeatTimeout)
7250
+ clearTimeout(this._heartbeatTimeout);
7251
+ if (this._backoffTimer) {
7252
+ clearTimeout(this._backoffTimer);
7253
+ this._backoffTimer = undefined;
7254
+ }
7255
+ this.removeAllListeners();
7256
+ this._eventSource.close();
7257
+ }
7258
+ /**
7259
+ * Returns an Observable that emits whenever the server sends an event of the given type.
7260
+ *
7261
+ * Lazily registers an EventSource listener on first call per event name.
7262
+ * Returns `NEVER` and logs an error if no connection exists.
7263
+ *
7264
+ * @param eventName The SSE event type to listen for.
7265
+ *
7266
+ * @example
7267
+ * ```ts
7268
+ * pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
7269
+ * ```
7270
+ */
7271
+ observe(eventName) {
7272
+ if (!this._eventSource) {
7273
+ this.logWarn('Cannot observe events without a connection. Call connect() first.');
7274
+ return NEVER;
7275
+ }
7276
+ if (!this._subjects.has(eventName)) {
7277
+ this._subjects.set(eventName, new Subject());
7278
+ this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
7279
+ }
7280
+ return this._subjects.get(eventName).asObservable();
7281
+ }
7282
+ /**
7283
+ * Removes all event listeners and clears all subscription subjects. The connection stays open.
7284
+ * Use this to reset all subscriptions without disconnecting the SSE stream.
7285
+ *
7286
+ * @example
7287
+ * ```ts
7288
+ * pushEventsService.unobserveAll();
7289
+ * // Connection remains open, but no events are forwarded until observe() is called again.
7290
+ * ```
7291
+ */
7292
+ unobserveAll() {
7293
+ this.removeAllListeners();
7294
+ this._subjects.clear();
7295
+ }
7296
+ /** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
7297
+ isConnectedOrConnecting() {
7298
+ return (this._eventSource &&
7299
+ (this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
7300
+ }
7301
+ connectWithAuth(url) {
7302
+ if (!this.authenticationService) {
7303
+ this.logError("Can't connect to SSE without Quadrel Auth as the connection has to be secured. Please install Quadrel Auth or disable authentication when connecting.");
7304
+ return;
7305
+ }
7306
+ this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
7307
+ this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
7308
+ });
7309
+ }
7310
+ openEventSource(url, options = {}) {
7311
+ this._isUnauthorized = false;
7312
+ if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
7313
+ this._eventSource.close();
7314
+ this._eventSource = new EventSourcePolyfill(url, options);
7315
+ this._eventSource.onerror = (err) => this.handleError(err);
7316
+ this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
7317
+ if (this._heartbeatTimeout)
7318
+ clearTimeout(this._heartbeatTimeout);
7319
+ this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
7320
+ if (this._backoffTimer) {
7321
+ clearTimeout(this._backoffTimer);
7322
+ this._backoffTimer = undefined;
7323
+ }
7324
+ this._listeners = [];
7325
+ this.reattachListeners();
7326
+ }
7327
+ reconnect() {
7328
+ if (this.isConnectedOrConnecting() || this._isUnauthorized)
7329
+ return;
7330
+ this.disconnect();
7331
+ this.connect(this._options.url, this._options.options);
7332
+ }
7333
+ handleError(err) {
7334
+ const status = err?.status || err?.target?.status;
7335
+ if (status === 401) {
7336
+ this._isUnauthorized = true;
7337
+ this.logError('SSE connection unauthorized (401):', err);
7338
+ this._eventSource.close();
7339
+ this.scheduleRetry();
7340
+ return;
7341
+ }
7342
+ if (this._eventSource.readyState === EventSource.CLOSED)
7343
+ this.reconnect();
7344
+ this.logError('SSE connection error:', err);
7345
+ }
7346
+ scheduleRetry() {
7347
+ if (this._reconnectAttempts >= this._maxReconnectAttempts) {
7348
+ this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
7349
+ return;
7350
+ }
7351
+ const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
7352
+ this._reconnectAttempts++;
7353
+ this._backoffTimer = setTimeout(() => {
7354
+ this._isUnauthorized = false;
7355
+ this.reconnect();
7356
+ }, delay);
7357
+ }
7358
+ handleHeartbeat(message) {
7359
+ if (this._isUnauthorized)
7360
+ return;
7361
+ if (this._heartbeatTimeout)
7362
+ clearTimeout(this._heartbeatTimeout);
7363
+ this._reconnectAttempts = 0;
7364
+ const interval = JSON.parse(message.data).interval;
7365
+ this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
7366
+ }
7367
+ addListener(eventName, callback) {
7368
+ this._eventSource.addEventListener(eventName, callback);
7369
+ this._listeners.push([eventName, callback]);
7370
+ }
7371
+ reattachListeners() {
7372
+ this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
7373
+ }
7374
+ removeAllListeners() {
7375
+ if (!this._eventSource)
7376
+ return;
7377
+ this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
7378
+ this._listeners = [];
7379
+ }
7380
+ logWarn(message) {
7381
+ console.warn(`Quadrel Framework | QdPushEvents - ${message}`);
7382
+ }
7383
+ logError(message, err) {
7384
+ console.error(`Quadrel Framework | QdPushEvents - ${message}`, err);
7385
+ }
7386
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7387
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
7388
+ }
7389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, decorators: [{
7390
+ type: Injectable,
7391
+ args: [{
7392
+ providedIn: 'root'
7393
+ }]
7394
+ }] });
7395
+
7396
+ var breakpoints$1 = {
7397
+ xs: 320,
7398
+ sm: 600,
7399
+ md: 960,
7400
+ lg: 1280,
7401
+ xl: 1600,
7402
+ xxl: 1800
7403
+ };
7404
+ var panel = {
7405
+ sm: 432,
7406
+ md: 588,
7407
+ lg: 720
7408
+ };
7409
+ var base = {
7410
+ fontsize: 16
7411
+ };
7412
+ var globalVars = {
7413
+ breakpoints: breakpoints$1,
7414
+ panel: panel,
7415
+ base: base
7416
+ };
7417
+
7418
+ const convertPxToRem = (pixel) => `${parseFloat((pixel / globalVars.base.fontsize).toFixed(3))}rem`;
7419
+
7420
+ class QdTooltipComponent {
7421
+ content;
7422
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7423
+ 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"] }] });
7424
+ }
7425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipComponent, decorators: [{
7426
+ type: Component,
7427
+ 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"] }]
7428
+ }], propDecorators: { content: [{
7429
+ type: Input
7430
+ }] } });
7431
+
7432
+ const TARGET_SELECTOR = '.qd-intersection-target';
7433
+ const SHOW_EVENTS = ['mouseenter', 'mousemove'];
7434
+ const HIDE_EVENTS = ['mouseleave', 'click'];
7435
+ const HIDE_DELAY = 300;
7436
+ const OVERLAY_WIDTH = 280;
7437
+ const UNSUBSCRIBE_IMMEDIATELY = true;
7438
+ const THRESHOLD = 1;
7439
+ /**
7440
+ * QdTooltipAtIntersectionDirective provides a tooltip. This will be triggered if the content is intersected.
7441
+ *
7442
+ * * Selector: [qdTooltipAtIntersection]
7443
+ * * Target Selector: .qd-intersection-target
7444
+ *
7445
+ * The IntersectionObserver API is used for the implementation.
7446
+ * * @see https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
7447
+ *
7448
+ * * 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.
7449
+ * */
7450
+ class QdTooltipAtIntersectionDirective {
7451
+ _host = inject(ElementRef);
7452
+ _positionBuilder = inject(OverlayPositionBuilder);
7453
+ _overlay = inject(Overlay);
7454
+ _overlayRef;
7455
+ _target;
7456
+ _observer$;
7457
+ _isIntersected = false;
7458
+ _destroyed$ = new Subject();
7459
+ ngAfterViewInit() {
7460
+ this.setTarget();
7461
+ this.observeTarget();
7462
+ this.createOverlay();
7463
+ this.subscribeShow();
7464
+ this.subscribeHide();
7465
+ }
7466
+ ngOnDestroy() {
7467
+ this._observer$.unobserve(this._target);
7468
+ this._destroyed$.next();
7469
+ this._destroyed$.complete();
7470
+ }
7471
+ setTarget() {
7472
+ this._target = this._host.nativeElement.querySelector(TARGET_SELECTOR);
7473
+ }
7474
+ observeTarget() {
7475
+ const options = {
7476
+ root: this._host.nativeElement,
7477
+ threshold: THRESHOLD
7478
+ };
7479
+ this._observer$ = new IntersectionObserver(entries => {
7480
+ this._isIntersected = entries[0].intersectionRatio < 1;
7481
+ if (this._isIntersected) {
7482
+ this._setStyles();
7483
+ if (UNSUBSCRIBE_IMMEDIATELY)
7484
+ this._observer$.unobserve(this._target);
7485
+ }
7486
+ }, options);
7487
+ this._observer$.observe(this._target);
7488
+ }
7489
+ _setStyles() {
7490
+ this._target.style.overflow = 'hidden';
7491
+ this._target.style.textOverflow = 'ellipsis';
7492
+ this._target.style.cursor = 'help';
7493
+ }
7494
+ createOverlay() {
7495
+ this._overlayRef = this._overlay.create({
7496
+ positionStrategy: this._positionBuilder
7497
+ .flexibleConnectedTo(this._host)
7498
+ .withPositions([{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' }]),
7499
+ width: convertPxToRem(OVERLAY_WIDTH)
7500
+ });
7501
+ }
7502
+ subscribeShow() {
7503
+ merge(...SHOW_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
7504
+ .pipe(takeUntil(this._destroyed$), filter(() => !this._overlayRef.hasAttached() && this._isIntersected))
7505
+ .subscribe(() => {
7506
+ const content = this.getContent();
7507
+ const tooltipPortal = new ComponentPortal(QdTooltipComponent);
7508
+ const tooltipRef = this._overlayRef.attach(tooltipPortal);
7509
+ tooltipRef.instance.content = content;
7510
+ });
7511
+ }
7512
+ subscribeHide() {
7513
+ merge(...HIDE_EVENTS.map(event => fromEvent(this._host.nativeElement, event)))
7514
+ .pipe(takeUntil(this._destroyed$), filter(() => this._overlayRef.hasAttached()), debounceTime(HIDE_DELAY))
7515
+ .subscribe(() => this._overlayRef.detach());
7516
+ }
7517
+ getContent() {
7518
+ return {
7519
+ headline: this._target.getAttribute('data-tooltip-headline') || undefined,
7520
+ paragraphs: [this._target.textContent?.trim() || '']
7521
+ };
7522
+ }
7523
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7524
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdTooltipAtIntersectionDirective, isStandalone: false, selector: "[qdTooltipAtIntersection]", ngImport: i0 });
7525
+ }
7526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTooltipAtIntersectionDirective, decorators: [{
7527
+ type: Directive,
7528
+ args: [{
7529
+ selector: '[qdTooltipAtIntersection]',
7530
+ standalone: false
7531
+ }]
7532
+ }] });
7533
+
7407
7534
  const MAX_TOOLTIP_CHARACTER = 512;
7408
7535
  const TOOLTIP_POSITIONS = [
7409
7536
  { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom' },
@@ -7509,9 +7636,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7509
7636
  type: Input
7510
7637
  }] } });
7511
7638
 
7512
- const QD_SAFE_BOTTOM_OFFSET = new InjectionToken('QD_SAFE_BOTTOM_OFFSET');
7513
-
7514
- const QD_POPOVER_TOP_FIRST = new InjectionToken('QD_POPOVER_TOP_FIRST');
7639
+ class QdVisuallyHiddenDirective {
7640
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7641
+ 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 });
7642
+ }
7643
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, decorators: [{
7644
+ type: Directive,
7645
+ args: [{
7646
+ selector: '[qdVisuallyHidden]',
7647
+ host: { class: 'qd-visually-hidden' },
7648
+ standalone: false
7649
+ }]
7650
+ }] });
7515
7651
 
7516
7652
  class QdCoreModule {
7517
7653
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -8589,11 +8725,11 @@ class QdFormHintComponent {
8589
8725
  this.actionEmitterService.hintEventEmitterSubject.next(null);
8590
8726
  }
8591
8727
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8592
- 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" }] });
8728
+ 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" }] });
8593
8729
  }
8594
8730
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, decorators: [{
8595
8731
  type: Component,
8596
- 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"] }]
8732
+ 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"] }]
8597
8733
  }], propDecorators: { hint: [{
8598
8734
  type: Input
8599
8735
  }], control: [{
@@ -11218,6 +11354,7 @@ class QdInputComponent {
11218
11354
  resolverRegistry = inject(QdFormOptionsResolverRegistry);
11219
11355
  controlContainer = inject(ControlContainer, { optional: true, host: true, skipSelf: true });
11220
11356
  eventBrokerService = inject(QdEventBrokerService, { optional: true });
11357
+ numberInputService = inject(QdNumberInputService);
11221
11358
  /**
11222
11359
  * The form control name can be assigned here if you want to use Reactive Forms.
11223
11360
  */
@@ -11292,9 +11429,13 @@ class QdInputComponent {
11292
11429
  get isErrorFromOutside() {
11293
11430
  return this.isError;
11294
11431
  }
11432
+ get isAmbiguousState() {
11433
+ return this.isAmbiguousInput;
11434
+ }
11295
11435
  inputElement;
11296
11436
  inputType;
11297
11437
  inputMode;
11438
+ htmlInputType;
11298
11439
  placeholder;
11299
11440
  label;
11300
11441
  hint;
@@ -11306,6 +11447,7 @@ class QdInputComponent {
11306
11447
  control;
11307
11448
  _optionsResolver;
11308
11449
  _subs = new Subscription();
11450
+ _isUserTyped = false;
11309
11451
  _onChange = () => { };
11310
11452
  _onTouch = () => { };
11311
11453
  get hasOnlyUnitsError() {
@@ -11314,6 +11456,15 @@ class QdInputComponent {
11314
11456
  get hasUnits() {
11315
11457
  return this.config?.units?.length > 0;
11316
11458
  }
11459
+ get ambiguityHintKey() {
11460
+ return this.numberInputService.getAmbiguityHintKey(this._value.value);
11461
+ }
11462
+ get isAmbiguousInput() {
11463
+ return (this.inputType === 'number' &&
11464
+ !this.hasError &&
11465
+ this._isUserTyped &&
11466
+ this.numberInputService.isAmbiguous(this._value.value));
11467
+ }
11317
11468
  get numberOfCharacters() {
11318
11469
  if (!this._value.value)
11319
11470
  return 0;
@@ -11330,7 +11481,10 @@ class QdInputComponent {
11330
11481
  return this.control.getMaxLengthOrUndefined();
11331
11482
  }
11332
11483
  get valueAsList() {
11333
- return [`${this._value.value}${this._value.unit ? ' ' + this._value.unit : ''}`];
11484
+ const displayValue = this.inputType === 'number'
11485
+ ? this.numberInputService.formatNumberForViewonly(this._value.value)
11486
+ : this._value.value;
11487
+ return [`${displayValue}${this._value.unit ? ' ' + this._value.unit : ''}`];
11334
11488
  }
11335
11489
  ngOnInit() {
11336
11490
  this.initializeOptionsResolver();
@@ -11343,6 +11497,11 @@ class QdInputComponent {
11343
11497
  console.warn('Quadrel Framework | QdInput - Please use the QdFormControl instead of the Angular FormControl.');
11344
11498
  }
11345
11499
  }
11500
+ if (this.config.inputType === 'number' &&
11501
+ this.config.inputMode !== 'numeric' &&
11502
+ this.config.inputMode !== 'decimal' &&
11503
+ this.config.inputMode != null)
11504
+ console.error('QD-UI | QdInputComponent - Please use either decimal or numeric when using QdInputType number');
11346
11505
  this.writeValue(this.value ?? getValue(this.config));
11347
11506
  this.normalizeInitialControlValueIfNeeded();
11348
11507
  this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
@@ -11373,6 +11532,8 @@ class QdInputComponent {
11373
11532
  writeValue(value) {
11374
11533
  this._value = getValueWithUnit(value, this.config);
11375
11534
  this._displayValue = String(this._value.value ?? '');
11535
+ this._isUserTyped = false;
11536
+ this.applyDisplayFormat();
11376
11537
  }
11377
11538
  setDisabledState(disabled) {
11378
11539
  this.disabled = disabled;
@@ -11384,6 +11545,36 @@ class QdInputComponent {
11384
11545
  if (input?.validity?.badInput)
11385
11546
  return;
11386
11547
  const value = event.target.value;
11548
+ if (this.inputType === 'number' && value && !this.numberInputService.isValidNumber(value)) {
11549
+ this.control?.setErrors({
11550
+ ...this.control.errors,
11551
+ invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11552
+ });
11553
+ return;
11554
+ }
11555
+ if (this.inputType === 'number' && value) {
11556
+ const valueWithoutGroups = value.split(this.numberInputService.groupSeparator).join('');
11557
+ const filtered = this.numberInputService.filterValue(valueWithoutGroups);
11558
+ const hasInvalidChars = filtered !== valueWithoutGroups;
11559
+ if (hasInvalidChars) {
11560
+ this._value = { ...this._value, value: filtered };
11561
+ if (this.control) {
11562
+ this.control.setErrors({
11563
+ ...this.control.errors,
11564
+ invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11565
+ });
11566
+ }
11567
+ this._isUserTyped = true;
11568
+ this._onTouch();
11569
+ this.emitValue();
11570
+ return;
11571
+ }
11572
+ if (this.control?.errors?.['invalidCharacters']) {
11573
+ const remainingErrors = Object.fromEntries(Object.entries(this.control.errors).filter(([key]) => key !== 'invalidCharacters'));
11574
+ this.control.setErrors(Object.keys(remainingErrors).length ? remainingErrors : null);
11575
+ }
11576
+ }
11577
+ this._isUserTyped = true;
11387
11578
  this._value = { ...this._value, value };
11388
11579
  this.emitValue();
11389
11580
  this._onTouch();
@@ -11440,6 +11631,15 @@ class QdInputComponent {
11440
11631
  updateConfig() {
11441
11632
  this.inputType = getInputType(this.config);
11442
11633
  this.inputMode = getInputMode(this.config);
11634
+ if (this.inputType === 'number') {
11635
+ this.htmlInputType = 'text';
11636
+ if (!this.inputMode) {
11637
+ this.inputMode = this.inputMode ?? 'decimal';
11638
+ }
11639
+ }
11640
+ else {
11641
+ this.htmlInputType = this.inputType;
11642
+ }
11443
11643
  this.placeholder = getPlaceholder(this.config);
11444
11644
  this.label = getLabel(this.config);
11445
11645
  this.hint = getHint(this.config);
@@ -11458,13 +11658,15 @@ class QdInputComponent {
11458
11658
  this._optionsResolver = this.resolverRegistry.findResolver();
11459
11659
  }
11460
11660
  emitValue() {
11661
+ const emittable = this.inputType === 'number' ? this.numberInputService.parseValue(this._value.value) : this._value.value;
11461
11662
  if (this.hasUnits) {
11462
- this.valueChange.emit(this._value);
11463
- this._onChange(this._value);
11663
+ const emittableWithUnit = { ...this._value, value: emittable };
11664
+ this.valueChange.emit(emittableWithUnit);
11665
+ this._onChange(emittableWithUnit);
11464
11666
  }
11465
11667
  else {
11466
- this.valueChange.emit(this._value.value);
11467
- this._onChange(this._value.value);
11668
+ this.valueChange.emit(emittable);
11669
+ this._onChange(emittable);
11468
11670
  }
11469
11671
  }
11470
11672
  initOpModeSubscription() {
@@ -11487,9 +11689,16 @@ class QdInputComponent {
11487
11689
  if (!isEqual(modelValue, target))
11488
11690
  this.control.setValue(target, { emitEvent: false });
11489
11691
  this._value = normalized;
11692
+ this.applyDisplayFormat();
11693
+ }
11694
+ applyDisplayFormat() {
11695
+ if (this.inputType === 'number') {
11696
+ this._value = { ...this._value, value: this.numberInputService.formatValueForDisplay(this._value.value) };
11697
+ this._displayValue = String(this._value.value ?? '');
11698
+ }
11490
11699
  }
11491
11700
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11492
- 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: [
11701
+ 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: [
11493
11702
  {
11494
11703
  provide: NG_VALUE_ACCESSOR,
11495
11704
  useExisting: QdInputComponent,
@@ -11497,13 +11706,14 @@ class QdInputComponent {
11497
11706
  },
11498
11707
  QdFormsActionEmitterService,
11499
11708
  QdFormOptionsResolverRegistry,
11709
+ QdNumberInputService,
11500
11710
  // TODO: Remove when removing derived directive
11501
11711
  QdPopoverSizingService,
11502
11712
  {
11503
11713
  provide: QD_FOCUSABLE_TOKEN,
11504
11714
  useExisting: QdInputComponent
11505
11715
  }
11506
- ], 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" }] });
11716
+ ], 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" }] });
11507
11717
  }
11508
11718
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, decorators: [{
11509
11719
  type: Component,
@@ -11515,13 +11725,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11515
11725
  },
11516
11726
  QdFormsActionEmitterService,
11517
11727
  QdFormOptionsResolverRegistry,
11728
+ QdNumberInputService,
11518
11729
  // TODO: Remove when removing derived directive
11519
11730
  QdPopoverSizingService,
11520
11731
  {
11521
11732
  provide: QD_FOCUSABLE_TOKEN,
11522
11733
  useExisting: QdInputComponent
11523
11734
  }
11524
- ], 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"] }]
11735
+ ], 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"] }]
11525
11736
  }], propDecorators: { formControlName: [{
11526
11737
  type: Input
11527
11738
  }], value: [{
@@ -11581,6 +11792,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11581
11792
  }], isErrorFromOutside: [{
11582
11793
  type: HostBinding,
11583
11794
  args: ['class.qd-input-error-from-outside']
11795
+ }], isAmbiguousState: [{
11796
+ type: HostBinding,
11797
+ args: ['class.qd-input-ambiguous']
11584
11798
  }], inputElement: [{
11585
11799
  type: ViewChild,
11586
11800
  args: ['input']
@@ -31415,6 +31629,7 @@ class QdShellServiceNavigationComponent {
31415
31629
  _config;
31416
31630
  _destroyed$ = new Subject();
31417
31631
  _attributesHaveBeenSet$ = new ReplaySubject(1);
31632
+ localeService = inject(QdLocaleService);
31418
31633
  ngOnInit() {
31419
31634
  loadJavascriptAsset(this.config?.javascriptAssetPath ?? DEFAULT_JAVASCRIPT_ASSET_PATH$1, {
31420
31635
  defer: '',
@@ -31457,6 +31672,7 @@ class QdShellServiceNavigationComponent {
31457
31672
  this._destroyed$.complete();
31458
31673
  }
31459
31674
  handleLanguageChange($event) {
31675
+ this.localeService.setServiceNavigationLanguage($event.detail);
31460
31676
  this.useLanguage($event.detail);
31461
31677
  }
31462
31678
  handleLoginStatusChange($event) {
@@ -33993,5 +34209,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
33993
34209
  * Generated bundle index. Do not edit.
33994
34210
  */
33995
34211
 
33996
- 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, 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 };
34212
+ 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 };
33997
34213
  //# sourceMappingURL=quadrel-enterprise-ui-framework.mjs.map