@quadrel-enterprise-ui/framework 20.6.1-beta.127.1 → 20.6.2
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.
- package/fesm2022/quadrel-enterprise-ui-framework.mjs +159 -118
- package/fesm2022/quadrel-enterprise-ui-framework.mjs.map +1 -1
- package/index.d.ts +76 -46
- package/package.json +1 -1
- package/src/assets/styles/components/_components.all.scss +0 -1
- package/src/assets/styles/components/_components.filter.scss +0 -52
- package/src/lib/filter/shared/filter.constants.scss +0 -32
|
@@ -6046,20 +6046,16 @@ class QdDataFacetsCurrencyComponent {
|
|
|
6046
6046
|
return '';
|
|
6047
6047
|
// Swiss speciality with a period instead of a comma
|
|
6048
6048
|
const localeWithSuffix = ['de', 'fr', 'it'].includes(lang) ? `${lang}-CH` : lang;
|
|
6049
|
-
// Normalize U+0027 (apostrophe) to U+2019 (right single quotation mark), which is the
|
|
6050
|
-
// correct Swiss thousands separator. Older ICU versions (used in some CI environments)
|
|
6051
|
-
// incorrectly emit U+0027 instead.
|
|
6052
|
-
const normalize = (s) => s.replace(/\u0027/g, '\u2019');
|
|
6053
6049
|
if (this.config?.showCurrencyUnit) {
|
|
6054
|
-
return
|
|
6050
|
+
return new Intl.NumberFormat(localeWithSuffix, {
|
|
6055
6051
|
style: 'currency',
|
|
6056
6052
|
currency: this.config?.currency ?? 'chf'
|
|
6057
|
-
}).format(this.data)
|
|
6053
|
+
}).format(this.data);
|
|
6058
6054
|
}
|
|
6059
|
-
return
|
|
6055
|
+
return new Intl.NumberFormat(localeWithSuffix, {
|
|
6060
6056
|
minimumFractionDigits: 2,
|
|
6061
6057
|
maximumFractionDigits: 2
|
|
6062
|
-
}).format(this.data)
|
|
6058
|
+
}).format(this.data);
|
|
6063
6059
|
}
|
|
6064
6060
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDataFacetsCurrencyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6065
6061
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDataFacetsCurrencyComponent, isStandalone: false, selector: "qd-data-facets-currency", inputs: { config: "config", data: "data", testId: "testId" }, host: { properties: { "attr.data-test-id": "testId" }, classAttribute: "qd-data-facets" }, usesOnChanges: true, ngImport: i0, template: "{{ currency$ | async }}\n", styles: [":host{text-align:right}\n"], dependencies: [{ kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -6859,185 +6855,230 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
6859
6855
|
}] });
|
|
6860
6856
|
|
|
6861
6857
|
/**
|
|
6862
|
-
*
|
|
6858
|
+
* Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
|
|
6863
6859
|
*
|
|
6864
|
-
*
|
|
6860
|
+
* All service endpoints — including SSE — must be protected. The connection is therefore secured
|
|
6861
|
+
* via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
|
|
6862
|
+
* transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
|
|
6865
6863
|
*
|
|
6866
|
-
*
|
|
6867
|
-
*
|
|
6868
|
-
* - **
|
|
6869
|
-
* - **
|
|
6864
|
+
* ### Reconnection behavior
|
|
6865
|
+
*
|
|
6866
|
+
* - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
|
|
6867
|
+
* - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
|
|
6868
|
+
* - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
|
|
6869
|
+
*
|
|
6870
|
+
* Existing `observe()` subscriptions are preserved across reconnections.
|
|
6870
6871
|
*
|
|
6871
6872
|
* ### Usage
|
|
6872
6873
|
*
|
|
6873
6874
|
* ```ts
|
|
6874
|
-
*
|
|
6875
|
-
* pushEventsService.connect('http://service-endpint/events');
|
|
6876
|
-
* // or start without authentication in case you don't need:
|
|
6877
|
-
* pushEventsService.connect('http://service-endpint/events', { disableAuthentication: true });
|
|
6878
|
-
*
|
|
6879
|
-
* // Subscribe to the event (Side Effect)
|
|
6880
|
-
* const subscription = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6875
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6881
6876
|
*
|
|
6882
|
-
*
|
|
6883
|
-
* subscription.unsubscribe();
|
|
6877
|
+
* const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6884
6878
|
*
|
|
6885
|
-
*
|
|
6879
|
+
* sub.unsubscribe();
|
|
6886
6880
|
* pushEventsService.disconnect();
|
|
6887
6881
|
* ```
|
|
6888
6882
|
*/
|
|
6889
6883
|
class QdPushEventsService {
|
|
6890
6884
|
authenticationService = inject('QdAuthenticationService', { optional: true });
|
|
6891
6885
|
_eventSource;
|
|
6892
|
-
|
|
6886
|
+
_subjects = new Map();
|
|
6893
6887
|
_listeners = [];
|
|
6894
|
-
_heartbeatTimeout;
|
|
6895
|
-
_reconnectDelayTime = 10000;
|
|
6896
|
-
_heartbeatReconnectDelayTime = 100;
|
|
6897
6888
|
_accessTokenSub;
|
|
6898
6889
|
_options;
|
|
6890
|
+
_heartbeatTimeout;
|
|
6891
|
+
_heartbeatGracePeriod = 100;
|
|
6892
|
+
_initialHeartbeatTimeout = 10000;
|
|
6899
6893
|
_isUnauthorized = false;
|
|
6894
|
+
_reconnectAttempts = 0;
|
|
6895
|
+
_maxReconnectAttempts = 5;
|
|
6896
|
+
_backoffTimer;
|
|
6900
6897
|
/**
|
|
6901
|
-
*
|
|
6902
|
-
* Automatically reconnects if heartbeat fails or is delayed.
|
|
6903
|
-
* Subscribers are retained across reconnections.
|
|
6898
|
+
* Opens an SSE connection to the given URL.
|
|
6904
6899
|
*
|
|
6905
|
-
*
|
|
6906
|
-
*
|
|
6900
|
+
* With authentication enabled (default), the service subscribes to the `accessToken$` observable
|
|
6901
|
+
* provided by Quadrel Auth and rebuilds the connection whenever the token changes.
|
|
6902
|
+
* No-op if already connected.
|
|
6903
|
+
*
|
|
6904
|
+
* @param url The SSE endpoint URL.
|
|
6905
|
+
* @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
|
|
6906
|
+
*
|
|
6907
|
+
* @example
|
|
6908
|
+
* ```ts
|
|
6909
|
+
* // Authenticated (default — requires Quadrel Auth)
|
|
6910
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6911
|
+
*
|
|
6912
|
+
* // Without authentication (only for public endpoints)
|
|
6913
|
+
* pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
|
|
6914
|
+
* ```
|
|
6907
6915
|
*/
|
|
6908
6916
|
connect(url, options) {
|
|
6909
6917
|
if (this.isConnectedOrConnecting())
|
|
6910
6918
|
return;
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
return;
|
|
6915
|
-
}
|
|
6916
|
-
if (this._accessTokenSub)
|
|
6917
|
-
this._accessTokenSub.unsubscribe();
|
|
6918
|
-
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
6919
|
-
this._options = { url, options };
|
|
6920
|
-
this.connectEventSource(url, {
|
|
6921
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
6922
|
-
}, true);
|
|
6923
|
-
});
|
|
6919
|
+
this._options = { url, options };
|
|
6920
|
+
if (options?.disableAuthentication) {
|
|
6921
|
+
this.openEventSource(url);
|
|
6924
6922
|
}
|
|
6925
6923
|
else {
|
|
6926
|
-
this.
|
|
6927
|
-
this.connectEventSource(url);
|
|
6924
|
+
this.connectWithAuth(url);
|
|
6928
6925
|
}
|
|
6929
6926
|
}
|
|
6930
6927
|
/**
|
|
6931
|
-
* Closes the EventSource connection
|
|
6932
|
-
*
|
|
6928
|
+
* Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
|
|
6929
|
+
* Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
|
|
6930
|
+
*
|
|
6931
|
+
* @example
|
|
6932
|
+
* ```ts
|
|
6933
|
+
* pushEventsService.disconnect();
|
|
6934
|
+
* // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
|
|
6935
|
+
* ```
|
|
6933
6936
|
*/
|
|
6934
6937
|
disconnect() {
|
|
6935
6938
|
if (!this._eventSource) {
|
|
6936
6939
|
this.logWarn('No active connection to disconnect.');
|
|
6937
6940
|
return;
|
|
6938
6941
|
}
|
|
6939
|
-
this.
|
|
6942
|
+
if (this._accessTokenSub) {
|
|
6943
|
+
this._accessTokenSub.unsubscribe();
|
|
6944
|
+
this._accessTokenSub = undefined;
|
|
6945
|
+
}
|
|
6946
|
+
if (this._heartbeatTimeout)
|
|
6947
|
+
clearTimeout(this._heartbeatTimeout);
|
|
6948
|
+
if (this._backoffTimer) {
|
|
6949
|
+
clearTimeout(this._backoffTimer);
|
|
6950
|
+
this._backoffTimer = undefined;
|
|
6951
|
+
}
|
|
6952
|
+
this.removeAllListeners();
|
|
6940
6953
|
this._eventSource.close();
|
|
6941
6954
|
}
|
|
6942
6955
|
/**
|
|
6943
|
-
* Returns an Observable
|
|
6944
|
-
*
|
|
6945
|
-
*
|
|
6956
|
+
* Returns an Observable that emits whenever the server sends an event of the given type.
|
|
6957
|
+
*
|
|
6958
|
+
* Lazily registers an EventSource listener on first call per event name.
|
|
6959
|
+
* Returns `NEVER` and logs an error if no connection exists.
|
|
6946
6960
|
*
|
|
6947
|
-
* @param eventName The event type
|
|
6948
|
-
*
|
|
6961
|
+
* @param eventName The SSE event type to listen for.
|
|
6962
|
+
*
|
|
6963
|
+
* @example
|
|
6964
|
+
* ```ts
|
|
6965
|
+
* pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
|
|
6966
|
+
* ```
|
|
6949
6967
|
*/
|
|
6950
6968
|
observe(eventName) {
|
|
6951
6969
|
if (!this._eventSource) {
|
|
6952
|
-
this.
|
|
6970
|
+
this.logWarn('Cannot observe events without a connection. Call connect() first.');
|
|
6953
6971
|
return NEVER;
|
|
6954
6972
|
}
|
|
6955
|
-
if (!this.
|
|
6956
|
-
this.
|
|
6957
|
-
this.
|
|
6973
|
+
if (!this._subjects.has(eventName)) {
|
|
6974
|
+
this._subjects.set(eventName, new Subject());
|
|
6975
|
+
this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
|
|
6958
6976
|
}
|
|
6959
|
-
return this.
|
|
6977
|
+
return this._subjects.get(eventName).asObservable();
|
|
6960
6978
|
}
|
|
6961
6979
|
/**
|
|
6962
|
-
* Removes all listeners and clears all
|
|
6963
|
-
*
|
|
6980
|
+
* Removes all event listeners and clears all subscription subjects. The connection stays open.
|
|
6981
|
+
* Use this to reset all subscriptions without disconnecting the SSE stream.
|
|
6982
|
+
*
|
|
6983
|
+
* @example
|
|
6984
|
+
* ```ts
|
|
6985
|
+
* pushEventsService.unobserveAll();
|
|
6986
|
+
* // Connection remains open, but no events are forwarded until observe() is called again.
|
|
6987
|
+
* ```
|
|
6964
6988
|
*/
|
|
6965
6989
|
unobserveAll() {
|
|
6966
|
-
this.
|
|
6967
|
-
this.
|
|
6990
|
+
this.removeAllListeners();
|
|
6991
|
+
this._subjects.clear();
|
|
6968
6992
|
}
|
|
6969
|
-
/**
|
|
6970
|
-
* Checks if the EventSource is connected or in the process of connecting.
|
|
6971
|
-
*/
|
|
6993
|
+
/** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
|
|
6972
6994
|
isConnectedOrConnecting() {
|
|
6973
6995
|
return (this._eventSource &&
|
|
6974
6996
|
(this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
|
|
6975
6997
|
}
|
|
6976
|
-
|
|
6977
|
-
if (this.
|
|
6998
|
+
connectWithAuth(url) {
|
|
6999
|
+
if (!this.authenticationService) {
|
|
7000
|
+
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.");
|
|
6978
7001
|
return;
|
|
6979
|
-
|
|
7002
|
+
}
|
|
7003
|
+
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
7004
|
+
this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
7005
|
+
});
|
|
7006
|
+
}
|
|
7007
|
+
openEventSource(url, options = {}) {
|
|
7008
|
+
this._isUnauthorized = false;
|
|
7009
|
+
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7010
|
+
this._eventSource.close();
|
|
7011
|
+
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7012
|
+
this._eventSource.onerror = (err) => this.handleError(err);
|
|
7013
|
+
this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
|
|
7014
|
+
if (this._heartbeatTimeout)
|
|
7015
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7016
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
|
|
7017
|
+
if (this._backoffTimer) {
|
|
7018
|
+
clearTimeout(this._backoffTimer);
|
|
7019
|
+
this._backoffTimer = undefined;
|
|
7020
|
+
}
|
|
7021
|
+
this._listeners = [];
|
|
7022
|
+
this.reattachListeners();
|
|
7023
|
+
}
|
|
7024
|
+
reconnect() {
|
|
7025
|
+
if (this.isConnectedOrConnecting() || this._isUnauthorized)
|
|
6980
7026
|
return;
|
|
6981
7027
|
this.disconnect();
|
|
6982
7028
|
this.connect(this._options.url, this._options.options);
|
|
6983
7029
|
}
|
|
6984
|
-
|
|
6985
|
-
const
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
7030
|
+
handleError(err) {
|
|
7031
|
+
const status = err?.status || err?.target?.status;
|
|
7032
|
+
if (status === 401) {
|
|
7033
|
+
this._isUnauthorized = true;
|
|
7034
|
+
this.logError('SSE connection unauthorized (401):', err);
|
|
7035
|
+
this._eventSource.close();
|
|
7036
|
+
this.scheduleRetry();
|
|
7037
|
+
return;
|
|
7038
|
+
}
|
|
7039
|
+
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7040
|
+
this.reconnect();
|
|
7041
|
+
this.logError('SSE connection error:', err);
|
|
6992
7042
|
}
|
|
6993
|
-
|
|
6994
|
-
this.
|
|
7043
|
+
scheduleRetry() {
|
|
7044
|
+
if (this._reconnectAttempts >= this._maxReconnectAttempts) {
|
|
7045
|
+
this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
|
|
7046
|
+
return;
|
|
7047
|
+
}
|
|
7048
|
+
const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
|
|
7049
|
+
this._reconnectAttempts++;
|
|
7050
|
+
this._backoffTimer = setTimeout(() => {
|
|
7051
|
+
this._isUnauthorized = false;
|
|
7052
|
+
this.reconnect();
|
|
7053
|
+
}, delay);
|
|
7054
|
+
}
|
|
7055
|
+
handleHeartbeat(message) {
|
|
7056
|
+
if (this._isUnauthorized)
|
|
7057
|
+
return;
|
|
7058
|
+
if (this._heartbeatTimeout)
|
|
7059
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7060
|
+
this._reconnectAttempts = 0;
|
|
7061
|
+
const interval = JSON.parse(message.data).interval;
|
|
7062
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
|
|
6995
7063
|
}
|
|
6996
|
-
|
|
7064
|
+
addListener(eventName, callback) {
|
|
6997
7065
|
this._eventSource.addEventListener(eventName, callback);
|
|
6998
7066
|
this._listeners.push([eventName, callback]);
|
|
6999
7067
|
}
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7068
|
+
reattachListeners() {
|
|
7069
|
+
this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
|
|
7070
|
+
}
|
|
7071
|
+
removeAllListeners() {
|
|
7072
|
+
if (!this._eventSource)
|
|
7003
7073
|
return;
|
|
7004
|
-
}
|
|
7005
7074
|
this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
|
|
7006
7075
|
this._listeners = [];
|
|
7007
7076
|
}
|
|
7008
7077
|
logWarn(message) {
|
|
7009
|
-
console.warn(`QD-UI |
|
|
7078
|
+
console.warn(`QD-UI | QdPushEvents - ${message}`);
|
|
7010
7079
|
}
|
|
7011
7080
|
logError(message, err) {
|
|
7012
|
-
console.error(`QD-UI |
|
|
7013
|
-
}
|
|
7014
|
-
connectEventSource(url, options = {}, reconnect) {
|
|
7015
|
-
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7016
|
-
this._eventSource.close();
|
|
7017
|
-
if (!this._eventSource || this._eventSource.readyState === EventSource.CLOSED || reconnect)
|
|
7018
|
-
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7019
|
-
this._eventSource.onerror = (err) => {
|
|
7020
|
-
const status = err?.status || err?.target?.status;
|
|
7021
|
-
if (status === 401) {
|
|
7022
|
-
this._isUnauthorized = true;
|
|
7023
|
-
this.logError('SSE connection unauthorized (401):', err);
|
|
7024
|
-
this._eventSource.close();
|
|
7025
|
-
return;
|
|
7026
|
-
}
|
|
7027
|
-
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7028
|
-
this.reconnect();
|
|
7029
|
-
this.logError('SSE connection error:', err);
|
|
7030
|
-
};
|
|
7031
|
-
this._eventSource.addEventListener('HEARTBEAT', (message) => {
|
|
7032
|
-
if (this._isUnauthorized)
|
|
7033
|
-
return;
|
|
7034
|
-
if (this._heartbeatTimeout)
|
|
7035
|
-
clearTimeout(this._heartbeatTimeout);
|
|
7036
|
-
const interval = JSON.parse(message.data).interval;
|
|
7037
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatReconnectDelayTime);
|
|
7038
|
-
});
|
|
7039
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._reconnectDelayTime);
|
|
7040
|
-
this.addEventListenersForExistingSubscriptions();
|
|
7081
|
+
console.error(`QD-UI | QdPushEvents - ${message}`, err);
|
|
7041
7082
|
}
|
|
7042
7083
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7043
7084
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
|
|
@@ -20740,11 +20781,11 @@ class QdFilterItemSelectCategoryComponent {
|
|
|
20740
20781
|
}));
|
|
20741
20782
|
}
|
|
20742
20783
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20743
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "positionStrategy", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20784
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:1rem 0 0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:1rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "positionStrategy", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20744
20785
|
}
|
|
20745
20786
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, decorators: [{
|
|
20746
20787
|
type: Component,
|
|
20747
|
-
args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n" }]
|
|
20788
|
+
args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:1rem 0 0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:1rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"] }]
|
|
20748
20789
|
}], propDecorators: { filterId: [{
|
|
20749
20790
|
type: Input
|
|
20750
20791
|
}], categoryIndex: [{
|