@radix-ng/primitives 0.22.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.
Files changed (66) hide show
  1. package/accordion/src/accordion-item.directive.d.ts +22 -13
  2. package/accordion/src/accordion-root.directive.d.ts +22 -3
  3. package/aspect-ratio/src/aspect-ratio.directive.d.ts +5 -3
  4. package/avatar/index.d.ts +9 -0
  5. package/avatar/src/avatar-fallback.directive.d.ts +9 -0
  6. package/avatar/src/avatar-image.directive.d.ts +12 -0
  7. package/collapsible/src/collapsible-content.directive.d.ts +0 -3
  8. package/collapsible/src/collapsible-root.directive.d.ts +11 -4
  9. package/compodoc/documentation.json +3848 -3623
  10. package/dropdown-menu/src/dropdown-menu-trigger.directive.d.ts +30 -3
  11. package/esm2022/accordion/src/accordion-item.directive.mjs +23 -14
  12. package/esm2022/accordion/src/accordion-root.directive.mjs +19 -3
  13. package/esm2022/aspect-ratio/src/aspect-ratio.directive.mjs +4 -2
  14. package/esm2022/avatar/index.mjs +27 -1
  15. package/esm2022/avatar/src/avatar-fallback.directive.mjs +10 -1
  16. package/esm2022/avatar/src/avatar-image.directive.mjs +13 -1
  17. package/esm2022/collapsible/src/collapsible-content.directive.mjs +1 -4
  18. package/esm2022/collapsible/src/collapsible-root.directive.mjs +17 -8
  19. package/esm2022/dropdown-menu/src/dropdown-menu-trigger.directive.mjs +35 -4
  20. package/esm2022/label/src/label.directive.mjs +6 -8
  21. package/esm2022/popover/src/popover-anchor.directive.mjs +8 -3
  22. package/esm2022/popover/src/popover-content.directive.mjs +30 -15
  23. package/esm2022/popover/src/popover-root.directive.mjs +6 -1
  24. package/esm2022/popover/src/popover.utils.mjs +17 -23
  25. package/esm2022/popover/src/utils/cdk-event.service.mjs +153 -0
  26. package/esm2022/popover/src/utils/constants.mjs +2 -0
  27. package/esm2022/popover/src/utils/types.mjs +2 -0
  28. package/esm2022/progress/src/progress-indicator.directive.mjs +1 -2
  29. package/esm2022/progress/src/progress-root.directive.mjs +8 -3
  30. package/esm2022/separator/src/separator.directive.mjs +9 -2
  31. package/esm2022/switch/src/switch-input.directive.mjs +4 -1
  32. package/esm2022/switch/src/switch-root.directive.mjs +28 -3
  33. package/esm2022/switch/src/switch-thumb.directive.mjs +4 -1
  34. package/fesm2022/radix-ng-primitives-accordion.mjs +40 -15
  35. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  36. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs +3 -1
  37. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-avatar.mjs +45 -2
  39. package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
  40. package/fesm2022/radix-ng-primitives-collapsible.mjs +16 -10
  41. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  42. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +34 -3
  43. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs.map +1 -1
  44. package/fesm2022/radix-ng-primitives-label.mjs +5 -7
  45. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  46. package/fesm2022/radix-ng-primitives-popover.mjs +208 -39
  47. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  48. package/fesm2022/radix-ng-primitives-progress.mjs +7 -3
  49. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  50. package/fesm2022/radix-ng-primitives-separator.mjs +8 -1
  51. package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
  52. package/fesm2022/radix-ng-primitives-switch.mjs +33 -2
  53. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  54. package/label/src/label.directive.d.ts +5 -7
  55. package/package.json +1 -1
  56. package/popover/src/popover-content.directive.d.ts +14 -6
  57. package/popover/src/popover-root.directive.d.ts +24 -1
  58. package/popover/src/utils/cdk-event.service.d.ts +29 -0
  59. package/popover/src/utils/constants.d.ts +1 -0
  60. package/popover/src/utils/types.d.ts +7 -0
  61. package/progress/src/progress-indicator.directive.d.ts +0 -1
  62. package/progress/src/progress-root.directive.d.ts +7 -2
  63. package/separator/src/separator.directive.d.ts +8 -1
  64. package/switch/src/switch-input.directive.d.ts +3 -0
  65. package/switch/src/switch-root.directive.d.ts +27 -2
  66. package/switch/src/switch-thumb.directive.d.ts +3 -0
@@ -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';
@@ -173,29 +173,23 @@ function getContentPosition(sideAndAlignWithOffsets) {
173
173
  const position = {
174
174
  ...(POPOVER_POSITIONS[side]?.[align] ?? POPOVER_POSITIONS[RdxPopoverSide.Top][RdxPopoverAlign.Center])
175
175
  };
176
- if (sideOffset > 0) {
177
- let xFactor = 0;
178
- let yFactor = 0;
179
- switch (side) {
180
- case RdxPopoverSide.Top:
181
- yFactor = -1;
182
- break;
183
- case RdxPopoverSide.Bottom:
184
- yFactor = 1;
185
- break;
186
- case RdxPopoverSide.Left:
187
- xFactor = -1;
188
- break;
189
- case RdxPopoverSide.Right:
190
- xFactor = 1;
191
- break;
176
+ if (sideOffset || alignOffset) {
177
+ if ([RdxPopoverSide.Top, RdxPopoverSide.Bottom].includes(side)) {
178
+ if (sideOffset) {
179
+ position.offsetY = side === RdxPopoverSide.Top ? -sideOffset : sideOffset;
180
+ }
181
+ if (alignOffset) {
182
+ position.offsetX = alignOffset;
183
+ }
184
+ }
185
+ else {
186
+ if (sideOffset) {
187
+ position.offsetX = side === RdxPopoverSide.Left ? -sideOffset : sideOffset;
188
+ }
189
+ if (alignOffset) {
190
+ position.offsetY = alignOffset;
191
+ }
192
192
  }
193
- position.offsetX = xFactor * sideOffset;
194
- position.offsetY = yFactor * sideOffset;
195
- }
196
- if ([RdxPopoverAlign.Start, RdxPopoverAlign.End].includes(align) && alignOffset) {
197
- const alignOffsetFactor = align === RdxPopoverAlign.End ? -1 : 1;
198
- position.offsetX = alignOffsetFactor * alignOffset;
199
193
  }
200
194
  return position;
201
195
  }
@@ -283,15 +277,21 @@ class RdxPopoverContentDirective {
283
277
  * @description Whether to add some alternate positions of the content.
284
278
  * @default false
285
279
  */
286
- 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);
287
285
  /**
288
- * @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`.
289
288
  */
290
- this.onEscapeKeyDown = output();
289
+ this.onOverlayEscapeKeyDown = output();
291
290
  /**
292
- * @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`.
293
293
  */
294
- this.onOutsideClick = output();
294
+ this.onOverlayOutsideClick = output();
295
295
  /**
296
296
  * @description Event handler called after the overlay is open
297
297
  */
@@ -308,6 +308,7 @@ class RdxPopoverContentDirective {
308
308
  /** @ignore */
309
309
  ngOnInit() {
310
310
  this.setScrollStrategy();
311
+ this.setHasBackdrop();
311
312
  this.setDisableClose();
312
313
  this.onAttach();
313
314
  this.onDetach();
@@ -340,9 +341,10 @@ class RdxPopoverContentDirective {
340
341
  connectKeydownEscape() {
341
342
  this.connectedOverlay.overlayKeydown
342
343
  .asObservable()
343
- .pipe(filter((event) => event.key === 'Escape'), tap((event) => {
344
- this.onEscapeKeyDown.emit(event);
345
- }), 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(() => {
346
348
  this.popoverRoot.handleClose();
347
349
  }), takeUntilDestroyed(this.destroyRef))
348
350
  .subscribe();
@@ -351,7 +353,8 @@ class RdxPopoverContentDirective {
351
353
  connectOutsideClick() {
352
354
  this.connectedOverlay.overlayOutsideClick
353
355
  .asObservable()
354
- .pipe(
356
+ .pipe(filter(() => !this.onOverlayOutsideClickDisabled() &&
357
+ !this.popoverRoot.rdxCdkEventService?.primitivePreventedFromCdkEvent(this.popoverRoot, 'cdkOverlayOutsideClick')),
355
358
  /**
356
359
  * Handle the situation when an anchor is added and the anchor becomes the origin of the overlay
357
360
  * hence the trigger will be considered the outside element
@@ -362,8 +365,8 @@ class RdxPopoverContentDirective {
362
365
  .popoverTriggerDirective()
363
366
  .elementRef.nativeElement.contains(event.target));
364
367
  }), tap((event) => {
365
- this.onOutsideClick.emit(event);
366
- }), filter((event) => !event.defaultPrevented && !this.popoverRoot.firstDefaultOpen()), tap(() => {
368
+ this.onOverlayOutsideClick.emit(event);
369
+ }), filter(() => !this.popoverRoot.firstDefaultOpen()), tap(() => {
367
370
  this.popoverRoot.handleClose();
368
371
  }), takeUntilDestroyed(this.destroyRef))
369
372
  .subscribe();
@@ -399,6 +402,12 @@ class RdxPopoverContentDirective {
399
402
  this.fireOverlayNgOnChanges('scrollStrategy', this.connectedOverlay.scrollStrategy, prevScrollStrategy);
400
403
  }
401
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 */
402
411
  setDisableClose() {
403
412
  const prevDisableClose = this.connectedOverlay.disableClose;
404
413
  this.connectedOverlay.disableClose = true;
@@ -431,7 +440,7 @@ class RdxPopoverContentDirective {
431
440
  alignOffset: offsets.alignOffset
432
441
  });
433
442
  const positions = [basePosition];
434
- if (!this.disableAlternatePositions()) {
443
+ if (!this.alternatePositionsDisabled()) {
435
444
  /**
436
445
  * Alternate positions for better user experience along the X/Y axis (e.g. vertical/horizontal scrolling)
437
446
  */
@@ -464,7 +473,7 @@ class RdxPopoverContentDirective {
464
473
  onPositionChangeEffect() {
465
474
  effect(() => {
466
475
  const positions = this.positions();
467
- this.disableAlternatePositions();
476
+ this.alternatePositionsDisabled();
468
477
  untracked(() => {
469
478
  this.setPositions(positions);
470
479
  });
@@ -477,7 +486,7 @@ class RdxPopoverContentDirective {
477
486
  });
478
487
  }
479
488
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
480
- 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 }); }
481
490
  }
482
491
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, decorators: [{
483
492
  type: Directive,
@@ -526,6 +535,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImpo
526
535
  }]
527
536
  }] });
528
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
+
529
689
  let nextId = 0;
530
690
  class RdxPopoverRootDirective {
531
691
  constructor() {
@@ -585,6 +745,8 @@ class RdxPopoverRootDirective {
585
745
  /** @ignore */
586
746
  this.viewContainerRef = inject(ViewContainerRef);
587
747
  /** @ignore */
748
+ this.rdxCdkEventService = injectRdxCdkEventService();
749
+ /** @ignore */
588
750
  this.destroyRef = inject(DestroyRef);
589
751
  /** @ignore */
590
752
  this.state = signal(RdxPopoverState.CLOSED);
@@ -605,6 +767,8 @@ class RdxPopoverRootDirective {
605
767
  });
606
768
  });
607
769
  };
770
+ this.rdxCdkEventService?.registerPrimitive(this);
771
+ this.destroyRef.onDestroy(() => this.rdxCdkEventService?.deregisterPrimitive(this));
608
772
  this.onStateChangeEffect();
609
773
  this.onCssAnimationStatusChangeChangeEffect();
610
774
  this.onOpenChangeEffect();
@@ -863,12 +1027,17 @@ class RdxPopoverAnchorDirective {
863
1027
  this.popoverRoot = popoverRoot;
864
1028
  }
865
1029
  emitOutsideClick() {
1030
+ if (!this.popoverRoot?.isOpen() ||
1031
+ this.popoverRoot?.popoverContentDirective().onOverlayOutsideClickDisabled()) {
1032
+ return;
1033
+ }
866
1034
  const clickEvent = new MouseEvent('click', {
867
1035
  view: this.document.defaultView,
868
1036
  bubbles: true,
869
- cancelable: true
1037
+ cancelable: true,
1038
+ relatedTarget: this.elementRef.nativeElement
870
1039
  });
871
- this.document.body.dispatchEvent(clickEvent);
1040
+ this.popoverRoot?.popoverTriggerDirective().elementRef.nativeElement.dispatchEvent(clickEvent);
872
1041
  }
873
1042
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverAnchorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
874
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: [