@radix-ng/primitives 0.23.0 → 0.24.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.
@@ -0,0 +1,153 @@
1
+ import { DOCUMENT } from '@angular/common';
2
+ import { DestroyRef, inject, Injectable, InjectionToken, isDevMode, makeEnvironmentProviders, NgZone, Renderer2, VERSION } from '@angular/core';
3
+ import { RdxCdkEventServiceWindowKey } from './constants';
4
+ import * as i0 from "@angular/core";
5
+ function eventTypeAsPrimitiveConfigKey(eventType) {
6
+ return `prevent${eventType[0].toUpperCase()}${eventType.slice(1)}`;
7
+ }
8
+ class RdxCdkEventService {
9
+ #clickDomRootEventCallbacks;
10
+ constructor() {
11
+ this.document = inject(DOCUMENT);
12
+ this.destroyRef = inject(DestroyRef);
13
+ this.ngZone = inject(NgZone);
14
+ this.renderer2 = inject(Renderer2);
15
+ this.onDestroyCallbacks = new Set([deleteRdxCdkEventServiceWindowKey]);
16
+ this.#clickDomRootEventCallbacks = new Set();
17
+ this.#listenToClickDomRootEvent();
18
+ this.#registerOnDestroyCallbacks();
19
+ }
20
+ registerPrimitive(primitiveInstance) {
21
+ if (!this.primitiveConfigs) {
22
+ this.primitiveConfigs = new Map();
23
+ }
24
+ if (!this.primitiveConfigs.has(primitiveInstance)) {
25
+ this.primitiveConfigs.set(primitiveInstance, {});
26
+ }
27
+ }
28
+ deregisterPrimitive(primitiveInstance) {
29
+ if (this.primitiveConfigs?.has(primitiveInstance)) {
30
+ this.primitiveConfigs.delete(primitiveInstance);
31
+ }
32
+ }
33
+ preventPrimitiveFromCdkEvent(primitiveInstance, eventType) {
34
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
35
+ }
36
+ allowPrimitiveForCdkEvent(primitiveInstance, eventType) {
37
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
38
+ }
39
+ preventPrimitiveFromCdkMultiEvents(primitiveInstance, eventTypes) {
40
+ eventTypes.forEach((eventType) => {
41
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
42
+ });
43
+ }
44
+ allowPrimitiveForCdkMultiEvents(primitiveInstance, eventTypes) {
45
+ eventTypes.forEach((eventType) => {
46
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
47
+ });
48
+ }
49
+ setPreventPrimitiveFromCdkMixEvents(primitiveInstance, eventTypes) {
50
+ Object.keys(eventTypes).forEach((eventType) => {
51
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, eventTypes[eventTypeAsPrimitiveConfigKey(eventType)]);
52
+ });
53
+ }
54
+ primitivePreventedFromCdkEvent(primitiveInstance, eventType) {
55
+ return this.primitiveConfigs?.get(primitiveInstance)?.[eventTypeAsPrimitiveConfigKey(eventType)];
56
+ }
57
+ addClickDomRootEventCallback(callback) {
58
+ this.#clickDomRootEventCallbacks.add(callback);
59
+ }
60
+ removeClickDomRootEventCallback(callback) {
61
+ return this.#clickDomRootEventCallbacks.delete(callback);
62
+ }
63
+ #setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, value) {
64
+ if (!this.primitiveConfigs?.has(primitiveInstance)) {
65
+ isDevMode() &&
66
+ console.error('[RdxCdkEventService.preventPrimitiveFromCdkEvent] RDX Primitive instance has not been registered!', primitiveInstance);
67
+ return;
68
+ }
69
+ switch (eventType) {
70
+ case 'cdkOverlayOutsideClick':
71
+ this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayOutsideClick = value;
72
+ break;
73
+ case 'cdkOverlayEscapeKeyDown':
74
+ this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayEscapeKeyDown = value;
75
+ break;
76
+ }
77
+ }
78
+ #registerOnDestroyCallbacks() {
79
+ this.destroyRef.onDestroy(() => {
80
+ this.onDestroyCallbacks.forEach((onDestroyCallback) => onDestroyCallback());
81
+ this.onDestroyCallbacks.clear();
82
+ });
83
+ }
84
+ #listenToClickDomRootEvent() {
85
+ const target = this.document;
86
+ const eventName = 'click';
87
+ const options = { capture: true };
88
+ const callback = (event) => {
89
+ this.#clickDomRootEventCallbacks.forEach((clickDomRootEventCallback) => clickDomRootEventCallback(event));
90
+ };
91
+ const major = parseInt(VERSION.major);
92
+ const minor = parseInt(VERSION.minor);
93
+ let destroyClickDomRootEventListener;
94
+ /**
95
+ * @see src/cdk/platform/features/backwards-compatibility.ts in @angular/cdk
96
+ */
97
+ if (major > 19 || (major === 19 && minor > 0) || (major === 0 && minor === 0)) {
98
+ destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
99
+ const destroyClickDomRootEventListenerInternal = this.renderer2.listen(target, eventName, callback,
100
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
101
+ // @ts-expect-error
102
+ options);
103
+ return () => {
104
+ destroyClickDomRootEventListenerInternal();
105
+ this.#clickDomRootEventCallbacks.clear();
106
+ };
107
+ });
108
+ }
109
+ else {
110
+ /**
111
+ * This part can get removed when v19.1 or higher is on the board
112
+ */
113
+ destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
114
+ target.addEventListener(eventName, callback, options);
115
+ return () => {
116
+ this.ngZone.runOutsideAngular(() => target.removeEventListener(eventName, callback, options));
117
+ this.#clickDomRootEventCallbacks.clear();
118
+ };
119
+ });
120
+ }
121
+ this.onDestroyCallbacks.add(destroyClickDomRootEventListener);
122
+ }
123
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
124
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService }); }
125
+ }
126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService, decorators: [{
127
+ type: Injectable
128
+ }], ctorParameters: () => [] });
129
+ const RdxCdkEventServiceToken = new InjectionToken('RdxCdkEventServiceToken');
130
+ const existsErrorMessage = 'RdxCdkEventService should be provided only once!';
131
+ const deleteRdxCdkEventServiceWindowKey = () => {
132
+ delete window[RdxCdkEventServiceWindowKey];
133
+ };
134
+ const getProvider = (throwWhenExists = true) => ({
135
+ provide: RdxCdkEventServiceToken,
136
+ useFactory: () => {
137
+ isDevMode() && console.log('providing RdxCdkEventService...');
138
+ if (window[RdxCdkEventServiceWindowKey]) {
139
+ if (throwWhenExists) {
140
+ throw Error(existsErrorMessage);
141
+ }
142
+ else {
143
+ isDevMode() && console.warn(existsErrorMessage);
144
+ }
145
+ }
146
+ window[RdxCdkEventServiceWindowKey] ??= new RdxCdkEventService();
147
+ return window[RdxCdkEventServiceWindowKey];
148
+ }
149
+ });
150
+ export const provideRdxCdkEventServiceInRoot = () => makeEnvironmentProviders([getProvider()]);
151
+ export const provideRdxCdkEventService = () => getProvider(false);
152
+ export const injectRdxCdkEventService = () => inject(RdxCdkEventServiceToken, { optional: true });
153
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLWV2ZW50LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9wcmltaXRpdmVzL3BvcG92ZXIvc3JjL3V0aWxzL2Nkay1ldmVudC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQ0gsVUFBVSxFQUVWLE1BQU0sRUFDTixVQUFVLEVBQ1YsY0FBYyxFQUNkLFNBQVMsRUFDVCx3QkFBd0IsRUFDeEIsTUFBTSxFQUVOLFNBQVMsRUFDVCxPQUFPLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sYUFBYSxDQUFDOztBQUcxRCxTQUFTLDZCQUE2QixDQUFDLFNBQW9CO0lBQ3ZELE9BQU8sVUFBVSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBbUMsQ0FBQztBQUN4RyxDQUFDO0FBRUQsTUFDTSxrQkFBa0I7SUFVcEIsMkJBQTJCLENBQStDO0lBRTFFO1FBWEEsYUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1QixlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hDLFdBQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDeEIsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUk5Qix1QkFBa0IsR0FBb0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUM7UUFFbkYsZ0NBQTJCLEdBQXFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFHdEUsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDbEMsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7SUFDdkMsQ0FB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LENBQUM7QUFFbEYsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLHVCQUF1QixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICAgIERlc3Ryb3lSZWYsXG4gICAgRW52aXJvbm1lbnRQcm92aWRlcnMsXG4gICAgaW5qZWN0LFxuICAgIEluamVjdGFibGUsXG4gICAgSW5qZWN0aW9uVG9rZW4sXG4gICAgaXNEZXZNb2RlLFxuICAgIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyxcbiAgICBOZ1pvbmUsXG4gICAgUHJvdmlkZXIsXG4gICAgUmVuZGVyZXIyLFxuICAgIFZFUlNJT05cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSZHhDZGtFdmVudFNlcnZpY2VXaW5kb3dLZXkgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBFdmVudFR5cGUsIEV2ZW50VHlwZUFzUHJpbWl0aXZlQ29uZmlnS2V5LCBQcmltaXRpdmVDb25maWcsIFByaW1pdGl2ZUNvbmZpZ3MgfSBmcm9tICcuL3R5cGVzJztcblxuZnVuY3Rpb24gZXZlbnRUeXBlQXNQcmltaXRpdmVDb25maWdLZXkoZXZlbnRUeXBlOiBFdmVudFR5cGUpOiBFdmVudFR5cGVBc1ByaW1pdGl2ZUNvbmZpZ0tleSB7XG4gICAgcmV0dXJuIGBwcmV2ZW50JHtldmVudFR5cGVbMF0udG9VcHBlckNhc2UoKX0ke2V2ZW50VHlwZS5zbGljZSgxKX1gIGFzIEV2ZW50VHlwZUFzUHJpbWl0aXZlQ29uZmlnS2V5O1xufVxuXG5ASW5qZWN0YWJsZSgpXG5jbGFzcyBSZHhDZGtFdmVudFNlcnZpY2Uge1xuICAgIGRvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcbiAgICBkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuICAgIG5nWm9uZSA9IGluamVjdChOZ1pvbmUpO1xuICAgIHJlbmRlcmVyMiA9IGluamVjdChSZW5kZXJlcjIpO1xuXG4gICAgcHJpbWl0aXZlQ29uZmlncz86IFByaW1pdGl2ZUNvbmZpZ3M7XG5cbiAgICBvbkRlc3Ryb3lDYWxsYmFja3M6IFNldDwoKSA9PiB2b2lkPiA9IG5ldyBTZXQoW2RlbGV0ZVJkeENka0V2ZW50U2VydmljZVdpbmRvd0tleV0pO1xuXG4gICAgI2NsaWNrRG9tUm9vdEV2ZW50Q2FsbGJhY2tzOiBTZXQ8KGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB2b2lkPiA9IG5ldyBTZXQoKTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLiNsaXN0ZW5Ub0NsaWNrRG9tUm9vdEV2ZW50KCk7XG4gICAgICAgIHRoaXMuI3JlZ2lzdGVyT25EZXN0cm95Q2FsbGJhY2tzKCk7XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJQcmltaXRpdmU8VCBleHRlbmRzIG9iamVjdD4ocHJpbWl0aXZlSW5zdGFuY2U6IFQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnByaW1pdGl2ZUNvbmZpZ3MpIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWl0aXZlQ29uZmlncyA9IG5ldyBNYXAoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucHJpbWl0aXZlQ29uZmlncy5oYXMocHJpbWl0aXZlSW5zdGFuY2UpKSB7XG4gICAgICAgICAgICB0aGlzLnByaW1pdGl2ZUNvbmZpZ3Muc2V0KHByaW1pdGl2ZUluc3RhbmNlLCB7fSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkZXJlZ2lzdGVyUHJpbWl0aXZlPFQgZXh0ZW5kcyBvYmplY3Q+KHByaW1pdGl2ZUluc3RhbmNlOiBUKSB7XG4gICAgICAgIGlmICh0aGlzLnByaW1pdGl2ZUNvbmZpZ3M/LmhhcyhwcmltaXRpdmVJbnN0YW5jZSkpIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWl0aXZlQ29uZmlncy5kZWxldGUocHJpbWl0aXZlSW5zdGFuY2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJldmVudFByaW1pdGl2ZUZyb21DZGtFdmVudDxUIGV4dGVuZHMgb2JqZWN0PihwcmltaXRpdmVJbnN0YW5jZTogVCwgZXZlbnRUeXBlOiBFdmVudFR5cGUpIHtcbiAgICAgICAgdGhpcy4jc2V0UHJldmVudFByaW1pdGl2ZUZyb21DZGtFdmVudChwcmltaXRpdmVJbnN0YW5jZSwgZXZlbnRUeXBlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBhbGxvd1ByaW1pdGl2ZUZvckNka0V2ZW50PFQgZXh0ZW5kcyBvYmplY3Q+KHByaW1pdGl2ZUluc3RhbmNlOiBULCBldmVudFR5cGU6IEV2ZW50VHlwZSkge1xuICAgICAgICB0aGlzLiNzZXRQcmV2ZW50UHJpbWl0aXZlRnJvbUNka0V2ZW50KHByaW1pdGl2ZUluc3RhbmNlLCBldmVudFR5cGUsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBwcmV2ZW50UHJpbWl0aXZlRnJvbUNka011bHRpRXZlbnRzPFQgZXh0ZW5kcyBvYmplY3Q+KHByaW1pdGl2ZUluc3RhbmNlOiBULCBldmVudFR5cGVzOiBFdmVudFR5cGVbXSkge1xuICAgICAgICBldmVudFR5cGVzLmZvckVhY2goKGV2ZW50VHlwZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy4jc2V0UHJldmVudFByaW1pdGl2ZUZyb21DZGtFdmVudChwcmltaXRpdmVJbnN0YW5jZSwgZXZlbnRUeXBlLCB0cnVlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYWxsb3dQcmltaXRpdmVGb3JDZGtNdWx0aUV2ZW50czxUIGV4dGVuZHMgb2JqZWN0PihwcmltaXRpdmVJbnN0YW5jZTogVCwgZXZlbnRUeXBlczogRXZlbnRUeXBlW10pIHtcbiAgICAgICAgZXZlbnRUeXBlcy5mb3JFYWNoKChldmVudFR5cGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMuI3NldFByZXZlbnRQcmltaXRpdmVGcm9tQ2RrRXZlbnQocHJpbWl0aXZlSW5zdGFuY2UsIGV2ZW50VHlwZSwgZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzZXRQcmV2ZW50UHJpbWl0aXZlRnJvbUNka01peEV2ZW50czxUIGV4dGVuZHMgb2JqZWN0PihwcmltaXRpdmVJbnN0YW5jZTogVCwgZXZlbnRUeXBlczogUHJpbWl0aXZlQ29uZmlnKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGV2ZW50VHlwZXMpLmZvckVhY2goKGV2ZW50VHlwZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy4jc2V0UHJldmVudFByaW1pdGl2ZUZyb21DZGtFdmVudChcbiAgICAgICAgICAgICAgICBwcmltaXRpdmVJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICBldmVudFR5cGUgYXMgRXZlbnRUeXBlLFxuICAgICAgICAgICAgICAgIGV2ZW50VHlwZXNbZXZlbnRUeXBlQXNQcmltaXRpdmVDb25maWdLZXkoZXZlbnRUeXBlIGFzIEV2ZW50VHlwZSldXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcmltaXRpdmVQcmV2ZW50ZWRGcm9tQ2RrRXZlbnQ8VCBleHRlbmRzIG9iamVjdD4ocHJpbWl0aXZlSW5zdGFuY2U6IFQsIGV2ZW50VHlwZTogRXZlbnRUeXBlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1pdGl2ZUNvbmZpZ3M/LmdldChwcmltaXRpdmVJbnN0YW5jZSk/LltldmVudFR5cGVBc1ByaW1pdGl2ZUNvbmZpZ0tleShldmVudFR5cGUpXTtcbiAgICB9XG5cbiAgICBhZGRDbGlja0RvbVJvb3RFdmVudENhbGxiYWNrKGNhbGxiYWNrOiAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHZvaWQpIHtcbiAgICAgICAgdGhpcy4jY2xpY2tEb21Sb290RXZlbnRDYWxsYmFja3MuYWRkKGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICByZW1vdmVDbGlja0RvbVJvb3RFdmVudENhbGxiYWNrKGNhbGxiYWNrOiAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHZvaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuI2NsaWNrRG9tUm9vdEV2ZW50Q2FsbGJhY2tzLmRlbGV0ZShjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgI3NldFByZXZlbnRQcmltaXRpdmVGcm9tQ2RrRXZlbnQ8XG4gICAgICAgIFQgZXh0ZW5kcyBvYmplY3QsXG4gICAgICAgIFIgZXh0ZW5kcyBFdmVudFR5cGUsXG4gICAgICAgIEsgZXh0ZW5kcyBQcmltaXRpdmVDb25maWdbRXZlbnRUeXBlQXNQcmltaXRpdmVDb25maWdLZXk8Uj5dXG4gICAgPihwcmltaXRpdmVJbnN0YW5jZTogVCwgZXZlbnRUeXBlOiBSLCB2YWx1ZTogSykge1xuICAgICAgICBpZiAoIXRoaXMucHJpbWl0aXZlQ29uZmlncz8uaGFzKHByaW1pdGl2ZUluc3RhbmNlKSkge1xuICAgICAgICAgICAgaXNEZXZNb2RlKCkgJiZcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAnW1JkeENka0V2ZW50U2VydmljZS5wcmV2ZW50UHJpbWl0aXZlRnJvbUNka0V2ZW50XSBSRFggUHJpbWl0aXZlIGluc3RhbmNlIGhhcyBub3QgYmVlbiByZWdpc3RlcmVkIScsXG4gICAgICAgICAgICAgICAgICAgIHByaW1pdGl2ZUluc3RhbmNlXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKGV2ZW50VHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnY2RrT3ZlcmxheU91dHNpZGVDbGljayc6XG4gICAgICAgICAgICAgICAgdGhpcy5wcmltaXRpdmVDb25maWdzLmdldChwcmltaXRpdmVJbnN0YW5jZSkhLnByZXZlbnRDZGtPdmVybGF5T3V0c2lkZUNsaWNrID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdjZGtPdmVybGF5RXNjYXBlS2V5RG93bic6XG4gICAgICAgICAgICAgICAgdGhpcy5wcmltaXRpdmVDb25maWdzLmdldChwcmltaXRpdmVJbnN0YW5jZSkhLnByZXZlbnRDZGtPdmVybGF5RXNjYXBlS2V5RG93biA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgI3JlZ2lzdGVyT25EZXN0cm95Q2FsbGJhY2tzKCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3lSZWYub25EZXN0cm95KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMub25EZXN0cm95Q2FsbGJhY2tzLmZvckVhY2goKG9uRGVzdHJveUNhbGxiYWNrKSA9PiBvbkRlc3Ryb3lDYWxsYmFjaygpKTtcbiAgICAgICAgICAgIHRoaXMub25EZXN0cm95Q2FsbGJhY2tzLmNsZWFyKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgICNsaXN0ZW5Ub0NsaWNrRG9tUm9vdEV2ZW50KCkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLmRvY3VtZW50O1xuICAgICAgICBjb25zdCBldmVudE5hbWUgPSAnY2xpY2snO1xuICAgICAgICBjb25zdCBvcHRpb25zOiBib29sZWFuIHwgQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMgfCB1bmRlZmluZWQgPSB7IGNhcHR1cmU6IHRydWUgfTtcbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgICAgIHRoaXMuI2NsaWNrRG9tUm9vdEV2ZW50Q2FsbGJhY2tzLmZvckVhY2goKGNsaWNrRG9tUm9vdEV2ZW50Q2FsbGJhY2spID0+IGNsaWNrRG9tUm9vdEV2ZW50Q2FsbGJhY2soZXZlbnQpKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBtYWpvciA9IHBhcnNlSW50KFZFUlNJT04ubWFqb3IpO1xuICAgICAgICBjb25zdCBtaW5vciA9IHBhcnNlSW50KFZFUlNJT04ubWlub3IpO1xuXG4gICAgICAgIGxldCBkZXN0cm95Q2xpY2tEb21Sb290RXZlbnRMaXN0ZW5lciE6ICgpID0+IHZvaWQ7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAc2VlIHNyYy9jZGsvcGxhdGZvcm0vZmVhdHVyZXMvYmFja3dhcmRzLWNvbXBhdGliaWxpdHkudHMgaW4gQGFuZ3VsYXIvY2RrXG4gICAgICAgICAqL1xuICAgICAgICBpZiAobWFqb3IgPiAxOSB8fCAobWFqb3IgPT09IDE5ICYmIG1pbm9yID4gMCkgfHwgKG1ham9yID09PSAwICYmIG1pbm9yID09PSAwKSkge1xuICAgICAgICAgICAgZGVzdHJveUNsaWNrRG9tUm9vdEV2ZW50TGlzdGVuZXIgPSB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVzdHJveUNsaWNrRG9tUm9vdEV2ZW50TGlzdGVuZXJJbnRlcm5hbCA9IHRoaXMucmVuZGVyZXIyLmxpc3RlbihcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgICAgICBldmVudE5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLFxuICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveUNsaWNrRG9tUm9vdEV2ZW50TGlzdGVuZXJJbnRlcm5hbCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiNjbGlja0RvbVJvb3RFdmVudENhbGxiYWNrcy5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhpcyBwYXJ0IGNhbiBnZXQgcmVtb3ZlZCB3aGVuIHYxOS4xIG9yIGhpZ2hlciBpcyBvbiB0aGUgYm9hcmRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZGVzdHJveUNsaWNrRG9tUm9vdEV2ZW50TGlzdGVuZXIgPSB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4gdGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiNjbGlja0RvbVJvb3RFdmVudENhbGxiYWNrcy5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uRGVzdHJveUNhbGxiYWNrcy5hZGQoZGVzdHJveUNsaWNrRG9tUm9vdEV2ZW50TGlzdGVuZXIpO1xuICAgIH1cbn1cblxuY29uc3QgUmR4Q2RrRXZlbnRTZXJ2aWNlVG9rZW4gPSBuZXcgSW5qZWN0aW9uVG9rZW48UmR4Q2RrRXZlbnRTZXJ2aWNlPignUmR4Q2RrRXZlbnRTZXJ2aWNlVG9rZW4nKTtcblxuY29uc3QgZXhpc3RzRXJyb3JNZXNzYWdlID0gJ1JkeENka0V2ZW50U2VydmljZSBzaG91bGQgYmUgcHJvdmlkZWQgb25seSBvbmNlISc7XG5cbmNvbnN0IGRlbGV0ZVJkeENka0V2ZW50U2VydmljZVdpbmRvd0tleSA9ICgpID0+IHtcbiAgICBkZWxldGUgKHdpbmRvdyBhcyBhbnkpW1JkeENka0V2ZW50U2VydmljZVdpbmRvd0tleV07XG59O1xuXG5jb25zdCBnZXRQcm92aWRlcjogKHRocm93V2hlbkV4aXN0cz86IGJvb2xlYW4pID0+IFByb3ZpZGVyID0gKHRocm93V2hlbkV4aXN0cyA9IHRydWUpID0+ICh7XG4gICAgcHJvdmlkZTogUmR4Q2RrRXZlbnRTZXJ2aWNlVG9rZW4sXG4gICAgdXNlRmFjdG9yeTogKCkgPT4ge1xuICAgICAgICBpc0Rldk1vZGUoKSAmJiBjb25zb2xlLmxvZygncHJvdmlkaW5nIFJkeENka0V2ZW50U2VydmljZS4uLicpO1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpW1JkeENka0V2ZW50U2VydmljZVdpbmRvd0tleV0pIHtcbiAgICAgICAgICAgIGlmICh0aHJvd1doZW5FeGlzdHMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihleGlzdHNFcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpc0Rldk1vZGUoKSAmJiBjb25zb2xlLndhcm4oZXhpc3RzRXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAod2luZG93IGFzIGFueSlbUmR4Q2RrRXZlbnRTZXJ2aWNlV2luZG93S2V5XSA/Pz0gbmV3IFJkeENka0V2ZW50U2VydmljZSgpO1xuICAgICAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpW1JkeENka0V2ZW50U2VydmljZVdpbmRvd0tleV07XG4gICAgfVxufSk7XG5cbmV4cG9ydCBjb25zdCBwcm92aWRlUmR4Q2RrRXZlbnRTZXJ2aWNlSW5Sb290OiAoKSA9PiBFbnZpcm9ubWVudFByb3ZpZGVycyA9ICgpID0+XG4gICAgbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKFtnZXRQcm92aWRlcigpXSk7XG5leHBvcnQgY29uc3QgcHJvdmlkZVJkeENka0V2ZW50U2VydmljZTogKCkgPT4gUHJvdmlkZXIgPSAoKSA9PiBnZXRQcm92aWRlcihmYWxzZSk7XG5cbmV4cG9ydCBjb25zdCBpbmplY3RSZHhDZGtFdmVudFNlcnZpY2UgPSAoKSA9PiBpbmplY3QoUmR4Q2RrRXZlbnRTZXJ2aWNlVG9rZW4sIHsgb3B0aW9uYWw6IHRydWUgfSk7XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export const RdxCdkEventServiceWindowKey = Symbol('__RdxCdkEventService__');
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcHJpbWl0aXZlcy9wb3BvdmVyL3NyYy91dGlscy9jb25zdGFudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgUmR4Q2RrRXZlbnRTZXJ2aWNlV2luZG93S2V5ID0gU3ltYm9sKCdfX1JkeENka0V2ZW50U2VydmljZV9fJyk7XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9wcmltaXRpdmVzL3BvcG92ZXIvc3JjL3V0aWxzL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdHlwZSBFdmVudFR5cGUgPSAnY2RrT3ZlcmxheU91dHNpZGVDbGljaycgfCAnY2RrT3ZlcmxheUVzY2FwZUtleURvd24nO1xuZXhwb3J0IHR5cGUgRXZlbnRUeXBlQ2FwaXRhbGl6ZWQ8UiBleHRlbmRzIEV2ZW50VHlwZSA9IEV2ZW50VHlwZT4gPSBDYXBpdGFsaXplPFI+O1xuZXhwb3J0IHR5cGUgRXZlbnRUeXBlQXNQcmltaXRpdmVDb25maWdLZXk8UiBleHRlbmRzIEV2ZW50VHlwZSA9IEV2ZW50VHlwZT4gPSBgcHJldmVudCR7RXZlbnRUeXBlQ2FwaXRhbGl6ZWQ8Uj59YDtcbmV4cG9ydCB0eXBlIFByaW1pdGl2ZUNvbmZpZyA9IHtcbiAgICBbdmFsdWUgaW4gRXZlbnRUeXBlQXNQcmltaXRpdmVDb25maWdLZXldPzogYm9vbGVhbjtcbn07XG5leHBvcnQgdHlwZSBQcmltaXRpdmVDb25maWdzID0gTWFwPG9iamVjdCwgUHJpbWl0aXZlQ29uZmlnPjtcbiJdfQ==
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, TemplateRef, DestroyRef, computed, input, output, effect, untracked, SimpleChange, Directive, ElementRef, signal, booleanAttribute, contentChild, ViewContainerRef, afterNextRender, isDevMode, assertInInjectionContext, forwardRef, Renderer2, Component, ChangeDetectionStrategy, NgModule } from '@angular/core';
2
+ import { InjectionToken, inject, TemplateRef, DestroyRef, computed, input, output, effect, untracked, SimpleChange, Directive, ElementRef, NgZone, Renderer2, isDevMode, VERSION, Injectable, makeEnvironmentProviders, signal, booleanAttribute, contentChild, ViewContainerRef, afterNextRender, assertInInjectionContext, forwardRef, Component, ChangeDetectionStrategy, NgModule } from '@angular/core';
3
3
  import * as i1 from '@angular/cdk/overlay';
4
4
  import { Overlay, CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
5
5
  import { DOCUMENT } from '@angular/common';
@@ -277,15 +277,21 @@ class RdxPopoverContentDirective {
277
277
  * @description Whether to add some alternate positions of the content.
278
278
  * @default false
279
279
  */
280
- this.disableAlternatePositions = input(false);
280
+ this.alternatePositionsDisabled = input(false);
281
+ /** @description Whether to prevent `onOverlayEscapeKeyDown` handler from calling. */
282
+ this.onOverlayEscapeKeyDownDisabled = input(false);
283
+ /** @description Whether to prevent `onOverlayOutsideClick` handler from calling. */
284
+ this.onOverlayOutsideClickDisabled = input(false);
281
285
  /**
282
- * @description Event handler called when the escape key is down. It can be prevented by calling event.preventDefault.
286
+ * @description Event handler called when the escape key is down.
287
+ * It can be prevented by setting `onOverlayEscapeKeyDownDisabled` input to `true`.
283
288
  */
284
- this.onEscapeKeyDown = output();
289
+ this.onOverlayEscapeKeyDown = output();
285
290
  /**
286
- * @description Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling event.preventDefault.
291
+ * @description Event handler called when a pointer event occurs outside the bounds of the component.
292
+ * It can be prevented by setting `onOverlayOutsideClickDisabled` input to `true`.
287
293
  */
288
- this.onOutsideClick = output();
294
+ this.onOverlayOutsideClick = output();
289
295
  /**
290
296
  * @description Event handler called after the overlay is open
291
297
  */
@@ -302,6 +308,7 @@ class RdxPopoverContentDirective {
302
308
  /** @ignore */
303
309
  ngOnInit() {
304
310
  this.setScrollStrategy();
311
+ this.setHasBackdrop();
305
312
  this.setDisableClose();
306
313
  this.onAttach();
307
314
  this.onDetach();
@@ -334,9 +341,10 @@ class RdxPopoverContentDirective {
334
341
  connectKeydownEscape() {
335
342
  this.connectedOverlay.overlayKeydown
336
343
  .asObservable()
337
- .pipe(filter((event) => event.key === 'Escape'), tap((event) => {
338
- this.onEscapeKeyDown.emit(event);
339
- }), filter((event) => !event.defaultPrevented && !this.popoverRoot.firstDefaultOpen()), tap(() => {
344
+ .pipe(filter(() => !this.onOverlayEscapeKeyDownDisabled() &&
345
+ !this.popoverRoot.rdxCdkEventService?.primitivePreventedFromCdkEvent(this.popoverRoot, 'cdkOverlayEscapeKeyDown')), filter((event) => event.key === 'Escape'), tap((event) => {
346
+ this.onOverlayEscapeKeyDown.emit(event);
347
+ }), filter(() => !this.popoverRoot.firstDefaultOpen()), tap(() => {
340
348
  this.popoverRoot.handleClose();
341
349
  }), takeUntilDestroyed(this.destroyRef))
342
350
  .subscribe();
@@ -345,7 +353,8 @@ class RdxPopoverContentDirective {
345
353
  connectOutsideClick() {
346
354
  this.connectedOverlay.overlayOutsideClick
347
355
  .asObservable()
348
- .pipe(
356
+ .pipe(filter(() => !this.onOverlayOutsideClickDisabled() &&
357
+ !this.popoverRoot.rdxCdkEventService?.primitivePreventedFromCdkEvent(this.popoverRoot, 'cdkOverlayOutsideClick')),
349
358
  /**
350
359
  * Handle the situation when an anchor is added and the anchor becomes the origin of the overlay
351
360
  * hence the trigger will be considered the outside element
@@ -356,8 +365,8 @@ class RdxPopoverContentDirective {
356
365
  .popoverTriggerDirective()
357
366
  .elementRef.nativeElement.contains(event.target));
358
367
  }), tap((event) => {
359
- this.onOutsideClick.emit(event);
360
- }), filter((event) => !event.defaultPrevented && !this.popoverRoot.firstDefaultOpen()), tap(() => {
368
+ this.onOverlayOutsideClick.emit(event);
369
+ }), filter(() => !this.popoverRoot.firstDefaultOpen()), tap(() => {
361
370
  this.popoverRoot.handleClose();
362
371
  }), takeUntilDestroyed(this.destroyRef))
363
372
  .subscribe();
@@ -393,6 +402,12 @@ class RdxPopoverContentDirective {
393
402
  this.fireOverlayNgOnChanges('scrollStrategy', this.connectedOverlay.scrollStrategy, prevScrollStrategy);
394
403
  }
395
404
  /** @ignore */
405
+ setHasBackdrop() {
406
+ const prevHasBackdrop = this.connectedOverlay.hasBackdrop;
407
+ this.connectedOverlay.hasBackdrop = false;
408
+ this.fireOverlayNgOnChanges('hasBackdrop', this.connectedOverlay.hasBackdrop, prevHasBackdrop);
409
+ }
410
+ /** @ignore */
396
411
  setDisableClose() {
397
412
  const prevDisableClose = this.connectedOverlay.disableClose;
398
413
  this.connectedOverlay.disableClose = true;
@@ -425,7 +440,7 @@ class RdxPopoverContentDirective {
425
440
  alignOffset: offsets.alignOffset
426
441
  });
427
442
  const positions = [basePosition];
428
- if (!this.disableAlternatePositions()) {
443
+ if (!this.alternatePositionsDisabled()) {
429
444
  /**
430
445
  * Alternate positions for better user experience along the X/Y axis (e.g. vertical/horizontal scrolling)
431
446
  */
@@ -458,7 +473,7 @@ class RdxPopoverContentDirective {
458
473
  onPositionChangeEffect() {
459
474
  effect(() => {
460
475
  const positions = this.positions();
461
- this.disableAlternatePositions();
476
+ this.alternatePositionsDisabled();
462
477
  untracked(() => {
463
478
  this.setPositions(positions);
464
479
  });
@@ -471,7 +486,7 @@ class RdxPopoverContentDirective {
471
486
  });
472
487
  }
473
488
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
474
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.11", type: RdxPopoverContentDirective, isStandalone: true, selector: "[rdxPopoverContent]", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, disableAlternatePositions: { classPropertyName: "disableAlternatePositions", publicName: "disableAlternatePositions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onEscapeKeyDown: "onEscapeKeyDown", onOutsideClick: "onOutsideClick", onOpen: "onOpen", onClosed: "onClosed" }, hostDirectives: [{ directive: i1.CdkConnectedOverlay }], ngImport: i0 }); }
489
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.11", type: RdxPopoverContentDirective, isStandalone: true, selector: "[rdxPopoverContent]", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, alternatePositionsDisabled: { classPropertyName: "alternatePositionsDisabled", publicName: "alternatePositionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, onOverlayEscapeKeyDownDisabled: { classPropertyName: "onOverlayEscapeKeyDownDisabled", publicName: "onOverlayEscapeKeyDownDisabled", isSignal: true, isRequired: false, transformFunction: null }, onOverlayOutsideClickDisabled: { classPropertyName: "onOverlayOutsideClickDisabled", publicName: "onOverlayOutsideClickDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOverlayEscapeKeyDown: "onOverlayEscapeKeyDown", onOverlayOutsideClick: "onOverlayOutsideClick", onOpen: "onOpen", onClosed: "onClosed" }, hostDirectives: [{ directive: i1.CdkConnectedOverlay }], ngImport: i0 }); }
475
490
  }
476
491
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, decorators: [{
477
492
  type: Directive,
@@ -520,6 +535,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImpo
520
535
  }]
521
536
  }] });
522
537
 
538
+ const RdxCdkEventServiceWindowKey = Symbol('__RdxCdkEventService__');
539
+
540
+ function eventTypeAsPrimitiveConfigKey(eventType) {
541
+ return `prevent${eventType[0].toUpperCase()}${eventType.slice(1)}`;
542
+ }
543
+ class RdxCdkEventService {
544
+ #clickDomRootEventCallbacks;
545
+ constructor() {
546
+ this.document = inject(DOCUMENT);
547
+ this.destroyRef = inject(DestroyRef);
548
+ this.ngZone = inject(NgZone);
549
+ this.renderer2 = inject(Renderer2);
550
+ this.onDestroyCallbacks = new Set([deleteRdxCdkEventServiceWindowKey]);
551
+ this.#clickDomRootEventCallbacks = new Set();
552
+ this.#listenToClickDomRootEvent();
553
+ this.#registerOnDestroyCallbacks();
554
+ }
555
+ registerPrimitive(primitiveInstance) {
556
+ if (!this.primitiveConfigs) {
557
+ this.primitiveConfigs = new Map();
558
+ }
559
+ if (!this.primitiveConfigs.has(primitiveInstance)) {
560
+ this.primitiveConfigs.set(primitiveInstance, {});
561
+ }
562
+ }
563
+ deregisterPrimitive(primitiveInstance) {
564
+ if (this.primitiveConfigs?.has(primitiveInstance)) {
565
+ this.primitiveConfigs.delete(primitiveInstance);
566
+ }
567
+ }
568
+ preventPrimitiveFromCdkEvent(primitiveInstance, eventType) {
569
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
570
+ }
571
+ allowPrimitiveForCdkEvent(primitiveInstance, eventType) {
572
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
573
+ }
574
+ preventPrimitiveFromCdkMultiEvents(primitiveInstance, eventTypes) {
575
+ eventTypes.forEach((eventType) => {
576
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
577
+ });
578
+ }
579
+ allowPrimitiveForCdkMultiEvents(primitiveInstance, eventTypes) {
580
+ eventTypes.forEach((eventType) => {
581
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
582
+ });
583
+ }
584
+ setPreventPrimitiveFromCdkMixEvents(primitiveInstance, eventTypes) {
585
+ Object.keys(eventTypes).forEach((eventType) => {
586
+ this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, eventTypes[eventTypeAsPrimitiveConfigKey(eventType)]);
587
+ });
588
+ }
589
+ primitivePreventedFromCdkEvent(primitiveInstance, eventType) {
590
+ return this.primitiveConfigs?.get(primitiveInstance)?.[eventTypeAsPrimitiveConfigKey(eventType)];
591
+ }
592
+ addClickDomRootEventCallback(callback) {
593
+ this.#clickDomRootEventCallbacks.add(callback);
594
+ }
595
+ removeClickDomRootEventCallback(callback) {
596
+ return this.#clickDomRootEventCallbacks.delete(callback);
597
+ }
598
+ #setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, value) {
599
+ if (!this.primitiveConfigs?.has(primitiveInstance)) {
600
+ isDevMode() &&
601
+ console.error('[RdxCdkEventService.preventPrimitiveFromCdkEvent] RDX Primitive instance has not been registered!', primitiveInstance);
602
+ return;
603
+ }
604
+ switch (eventType) {
605
+ case 'cdkOverlayOutsideClick':
606
+ this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayOutsideClick = value;
607
+ break;
608
+ case 'cdkOverlayEscapeKeyDown':
609
+ this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayEscapeKeyDown = value;
610
+ break;
611
+ }
612
+ }
613
+ #registerOnDestroyCallbacks() {
614
+ this.destroyRef.onDestroy(() => {
615
+ this.onDestroyCallbacks.forEach((onDestroyCallback) => onDestroyCallback());
616
+ this.onDestroyCallbacks.clear();
617
+ });
618
+ }
619
+ #listenToClickDomRootEvent() {
620
+ const target = this.document;
621
+ const eventName = 'click';
622
+ const options = { capture: true };
623
+ const callback = (event) => {
624
+ this.#clickDomRootEventCallbacks.forEach((clickDomRootEventCallback) => clickDomRootEventCallback(event));
625
+ };
626
+ const major = parseInt(VERSION.major);
627
+ const minor = parseInt(VERSION.minor);
628
+ let destroyClickDomRootEventListener;
629
+ /**
630
+ * @see src/cdk/platform/features/backwards-compatibility.ts in @angular/cdk
631
+ */
632
+ if (major > 19 || (major === 19 && minor > 0) || (major === 0 && minor === 0)) {
633
+ destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
634
+ const destroyClickDomRootEventListenerInternal = this.renderer2.listen(target, eventName, callback,
635
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
636
+ // @ts-expect-error
637
+ options);
638
+ return () => {
639
+ destroyClickDomRootEventListenerInternal();
640
+ this.#clickDomRootEventCallbacks.clear();
641
+ };
642
+ });
643
+ }
644
+ else {
645
+ /**
646
+ * This part can get removed when v19.1 or higher is on the board
647
+ */
648
+ destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
649
+ target.addEventListener(eventName, callback, options);
650
+ return () => {
651
+ this.ngZone.runOutsideAngular(() => target.removeEventListener(eventName, callback, options));
652
+ this.#clickDomRootEventCallbacks.clear();
653
+ };
654
+ });
655
+ }
656
+ this.onDestroyCallbacks.add(destroyClickDomRootEventListener);
657
+ }
658
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
659
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService }); }
660
+ }
661
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxCdkEventService, decorators: [{
662
+ type: Injectable
663
+ }], ctorParameters: () => [] });
664
+ const RdxCdkEventServiceToken = new InjectionToken('RdxCdkEventServiceToken');
665
+ const existsErrorMessage = 'RdxCdkEventService should be provided only once!';
666
+ const deleteRdxCdkEventServiceWindowKey = () => {
667
+ delete window[RdxCdkEventServiceWindowKey];
668
+ };
669
+ const getProvider = (throwWhenExists = true) => ({
670
+ provide: RdxCdkEventServiceToken,
671
+ useFactory: () => {
672
+ isDevMode() && console.log('providing RdxCdkEventService...');
673
+ if (window[RdxCdkEventServiceWindowKey]) {
674
+ if (throwWhenExists) {
675
+ throw Error(existsErrorMessage);
676
+ }
677
+ else {
678
+ isDevMode() && console.warn(existsErrorMessage);
679
+ }
680
+ }
681
+ window[RdxCdkEventServiceWindowKey] ??= new RdxCdkEventService();
682
+ return window[RdxCdkEventServiceWindowKey];
683
+ }
684
+ });
685
+ const provideRdxCdkEventServiceInRoot = () => makeEnvironmentProviders([getProvider()]);
686
+ const provideRdxCdkEventService = () => getProvider(false);
687
+ const injectRdxCdkEventService = () => inject(RdxCdkEventServiceToken, { optional: true });
688
+
523
689
  let nextId = 0;
524
690
  class RdxPopoverRootDirective {
525
691
  constructor() {
@@ -579,6 +745,8 @@ class RdxPopoverRootDirective {
579
745
  /** @ignore */
580
746
  this.viewContainerRef = inject(ViewContainerRef);
581
747
  /** @ignore */
748
+ this.rdxCdkEventService = injectRdxCdkEventService();
749
+ /** @ignore */
582
750
  this.destroyRef = inject(DestroyRef);
583
751
  /** @ignore */
584
752
  this.state = signal(RdxPopoverState.CLOSED);
@@ -599,6 +767,8 @@ class RdxPopoverRootDirective {
599
767
  });
600
768
  });
601
769
  };
770
+ this.rdxCdkEventService?.registerPrimitive(this);
771
+ this.destroyRef.onDestroy(() => this.rdxCdkEventService?.deregisterPrimitive(this));
602
772
  this.onStateChangeEffect();
603
773
  this.onCssAnimationStatusChangeChangeEffect();
604
774
  this.onOpenChangeEffect();
@@ -857,12 +1027,17 @@ class RdxPopoverAnchorDirective {
857
1027
  this.popoverRoot = popoverRoot;
858
1028
  }
859
1029
  emitOutsideClick() {
1030
+ if (!this.popoverRoot?.isOpen() ||
1031
+ this.popoverRoot?.popoverContentDirective().onOverlayOutsideClickDisabled()) {
1032
+ return;
1033
+ }
860
1034
  const clickEvent = new MouseEvent('click', {
861
1035
  view: this.document.defaultView,
862
1036
  bubbles: true,
863
- cancelable: true
1037
+ cancelable: true,
1038
+ relatedTarget: this.elementRef.nativeElement
864
1039
  });
865
- this.document.body.dispatchEvent(clickEvent);
1040
+ this.popoverRoot?.popoverTriggerDirective().elementRef.nativeElement.dispatchEvent(clickEvent);
866
1041
  }
867
1042
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverAnchorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
868
1043
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.11", type: RdxPopoverAnchorDirective, isStandalone: true, selector: "[rdxPopoverAnchor]", host: { attributes: { "type": "button" }, listeners: { "click": "click()" }, properties: { "attr.id": "name()", "attr.aria-haspopup": "\"dialog\"" } }, providers: [