@clr/angular 18.0.0-beta.1 → 18.0.0-beta.3

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 (89) hide show
  1. package/fesm2022/clr-angular-accordion.mjs +1 -1
  2. package/fesm2022/clr-angular-accordion.mjs.map +1 -1
  3. package/fesm2022/clr-angular-button.mjs +6 -6
  4. package/fesm2022/clr-angular-button.mjs.map +1 -1
  5. package/fesm2022/clr-angular-data-datagrid.mjs +19 -33
  6. package/fesm2022/clr-angular-data-datagrid.mjs.map +1 -1
  7. package/fesm2022/clr-angular-data-tree-view.mjs +2 -2
  8. package/fesm2022/clr-angular-data-tree-view.mjs.map +1 -1
  9. package/fesm2022/clr-angular-data.mjs +11 -9116
  10. package/fesm2022/clr-angular-data.mjs.map +1 -1
  11. package/fesm2022/clr-angular-emphasis-alert.mjs +2 -2
  12. package/fesm2022/clr-angular-emphasis-alert.mjs.map +1 -1
  13. package/fesm2022/clr-angular-emphasis.mjs +12 -778
  14. package/fesm2022/clr-angular-emphasis.mjs.map +1 -1
  15. package/fesm2022/clr-angular-forms-checkbox.mjs +13 -44
  16. package/fesm2022/clr-angular-forms-checkbox.mjs.map +1 -1
  17. package/fesm2022/clr-angular-forms-combobox.mjs +97 -64
  18. package/fesm2022/clr-angular-forms-combobox.mjs.map +1 -1
  19. package/fesm2022/clr-angular-forms-common.mjs +62 -57
  20. package/fesm2022/clr-angular-forms-common.mjs.map +1 -1
  21. package/fesm2022/clr-angular-forms-datalist.mjs +2 -14
  22. package/fesm2022/clr-angular-forms-datalist.mjs.map +1 -1
  23. package/fesm2022/clr-angular-forms-datepicker.mjs +20 -28
  24. package/fesm2022/clr-angular-forms-datepicker.mjs.map +1 -1
  25. package/fesm2022/clr-angular-forms-file-input.mjs +72 -53
  26. package/fesm2022/clr-angular-forms-file-input.mjs.map +1 -1
  27. package/fesm2022/clr-angular-forms-input.mjs +4 -18
  28. package/fesm2022/clr-angular-forms-input.mjs.map +1 -1
  29. package/fesm2022/clr-angular-forms-number-input.mjs +2 -14
  30. package/fesm2022/clr-angular-forms-number-input.mjs.map +1 -1
  31. package/fesm2022/clr-angular-forms-password.mjs +2 -14
  32. package/fesm2022/clr-angular-forms-password.mjs.map +1 -1
  33. package/fesm2022/clr-angular-forms-radio.mjs +13 -44
  34. package/fesm2022/clr-angular-forms-radio.mjs.map +1 -1
  35. package/fesm2022/clr-angular-forms-range.mjs +3 -16
  36. package/fesm2022/clr-angular-forms-range.mjs.map +1 -1
  37. package/fesm2022/clr-angular-forms-select.mjs +3 -16
  38. package/fesm2022/clr-angular-forms-select.mjs.map +1 -1
  39. package/fesm2022/clr-angular-forms-textarea.mjs +4 -17
  40. package/fesm2022/clr-angular-forms-textarea.mjs.map +1 -1
  41. package/fesm2022/clr-angular-forms.mjs +68 -8560
  42. package/fesm2022/clr-angular-forms.mjs.map +1 -1
  43. package/fesm2022/clr-angular-layout-tabs.mjs +1 -1
  44. package/fesm2022/clr-angular-layout-tabs.mjs.map +1 -1
  45. package/fesm2022/clr-angular-layout.mjs +15 -2057
  46. package/fesm2022/clr-angular-layout.mjs.map +1 -1
  47. package/fesm2022/clr-angular-modal.mjs +2 -2
  48. package/fesm2022/clr-angular-modal.mjs.map +1 -1
  49. package/fesm2022/clr-angular-popover-common.mjs +151 -85
  50. package/fesm2022/clr-angular-popover-common.mjs.map +1 -1
  51. package/fesm2022/clr-angular-popover-dropdown.mjs +7 -4
  52. package/fesm2022/clr-angular-popover-dropdown.mjs.map +1 -1
  53. package/fesm2022/clr-angular-popover-signpost.mjs +30 -15
  54. package/fesm2022/clr-angular-popover-signpost.mjs.map +1 -1
  55. package/fesm2022/clr-angular-popover-tooltip.mjs +7 -7
  56. package/fesm2022/clr-angular-popover-tooltip.mjs.map +1 -1
  57. package/fesm2022/clr-angular-popover.mjs +12 -2242
  58. package/fesm2022/clr-angular-popover.mjs.map +1 -1
  59. package/fesm2022/clr-angular-stepper.mjs +5 -5
  60. package/fesm2022/clr-angular-stepper.mjs.map +1 -1
  61. package/fesm2022/clr-angular-utils.mjs +15 -485
  62. package/fesm2022/clr-angular-utils.mjs.map +1 -1
  63. package/fesm2022/clr-angular-wizard.mjs +19 -11
  64. package/fesm2022/clr-angular-wizard.mjs.map +1 -1
  65. package/fesm2022/clr-angular.mjs +94 -38740
  66. package/fesm2022/clr-angular.mjs.map +1 -1
  67. package/package.json +2 -2
  68. package/popover/common/README.md +14 -12
  69. package/types/clr-angular-accordion.d.ts +1 -1
  70. package/types/clr-angular-button.d.ts +1 -1
  71. package/types/clr-angular-data-datagrid.d.ts +23 -33
  72. package/types/clr-angular-data.d.ts +4 -2136
  73. package/types/clr-angular-emphasis.d.ts +4 -220
  74. package/types/clr-angular-forms-combobox.d.ts +12 -5
  75. package/types/clr-angular-forms-common.d.ts +9 -9
  76. package/types/clr-angular-forms-datepicker.d.ts +8 -1
  77. package/types/clr-angular-forms-file-input.d.ts +5 -2
  78. package/types/clr-angular-forms.d.ts +26 -2062
  79. package/types/clr-angular-layout-tabs.d.ts +1 -1
  80. package/types/clr-angular-layout.d.ts +6 -463
  81. package/types/clr-angular-popover-common.d.ts +38 -13
  82. package/types/clr-angular-popover-dropdown.d.ts +2 -1
  83. package/types/clr-angular-popover-signpost.d.ts +15 -7
  84. package/types/clr-angular-popover-tooltip.d.ts +1 -1
  85. package/types/clr-angular-popover.d.ts +7 -559
  86. package/types/clr-angular-stepper.d.ts +1 -1
  87. package/types/clr-angular-utils.d.ts +8 -175
  88. package/types/clr-angular-wizard.d.ts +7 -4
  89. package/types/clr-angular.d.ts +22 -10238
@@ -4,19 +4,11 @@ import { OverlayConfig } from '@angular/cdk/overlay';
4
4
  import { DomPortal } from '@angular/cdk/portal';
5
5
  import { isPlatformBrowser } from '@angular/common';
6
6
  import * as i0 from '@angular/core';
7
- import { Injectable, ElementRef, PLATFORM_ID, Input, Optional, SkipSelf, Inject, Directive, InjectionToken, HostListener, EventEmitter, Output, NgModule } from '@angular/core';
8
- import { preventArrowKeyScroll, ClrPosition, normalizeKey, Keys } from '@clr/angular/utils';
9
- import { Subject, merge, fromEvent } from 'rxjs';
7
+ import { ElementRef, Injectable, PLATFORM_ID, Input, Optional, SkipSelf, Inject, Directive, InjectionToken, HostListener, EventEmitter, Output, NgModule } from '@angular/core';
8
+ import { preventArrowKeyScroll, ClrPosition, Keys } from '@clr/angular/utils';
9
+ import { Subject, merge, timer, switchMap, fromEvent } from 'rxjs';
10
10
  import { filter } from 'rxjs/operators';
11
11
 
12
- /*
13
- * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
14
- * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
15
- * This software is released under MIT license.
16
- * The full license information can be found in LICENSE in the root directory of this project.
17
- */
18
- // Popovers might need to ignore click events on an element
19
- // (eg: popover opens on focus on an input field. Clicks should be ignored in this case)
20
12
  class ClrPopoverService {
21
13
  constructor() {
22
14
  this.panelClass = [];
@@ -28,6 +20,12 @@ class ClrPopoverService {
28
20
  this._updatePosition = new Subject();
29
21
  this._popoverVisible = new Subject();
30
22
  }
23
+ get originElement() {
24
+ return this.origin instanceof ElementRef ? this.origin : null;
25
+ }
26
+ get originPoint() {
27
+ return this.origin && 'x' in this.origin && 'y' in this.origin ? this.origin : null;
28
+ }
31
29
  get openChange() {
32
30
  return this._openChange.asObservable();
33
31
  }
@@ -75,6 +73,18 @@ class ClrPopoverService {
75
73
  this.openEvent = event;
76
74
  this.open = !this.open;
77
75
  }
76
+ /**
77
+ * Opens the popover at a specific screen coordinate.
78
+ * Useful for context menus where the popover should appear at the cursor position.
79
+ */
80
+ openAtPoint(point) {
81
+ if (this._open) {
82
+ this._open = false;
83
+ this._openChange.next(false);
84
+ }
85
+ this.origin = point;
86
+ this.open = true;
87
+ }
78
88
  popoverVisibleEmit(visible) {
79
89
  this._popoverVisible.next(visible);
80
90
  }
@@ -87,8 +97,8 @@ class ClrPopoverService {
87
97
  focusCloseButton() {
88
98
  this.closeButtonRef.nativeElement?.focus();
89
99
  }
90
- focusAnchor() {
91
- this.anchorElementRef?.nativeElement?.focus({ preventScroll: true });
100
+ focusOrigin() {
101
+ this.originElement?.nativeElement?.focus({ preventScroll: true });
92
102
  }
93
103
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
94
104
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverService }); }
@@ -224,52 +234,52 @@ function getOffset(key, type) {
224
234
  };
225
235
  }
226
236
  }
227
- const STANDARD_ANCHORS = {
237
+ const STANDARD_ORIGINS = {
228
238
  // TOP
229
- [ClrPopoverPosition.TOP_RIGHT]: { anchor: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_LEFT },
230
- [ClrPopoverPosition.TOP_MIDDLE]: { anchor: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_CENTER },
231
- [ClrPopoverPosition.TOP_LEFT]: { anchor: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_RIGHT },
239
+ [ClrPopoverPosition.TOP_RIGHT]: { origin: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_LEFT },
240
+ [ClrPopoverPosition.TOP_MIDDLE]: { origin: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_CENTER },
241
+ [ClrPopoverPosition.TOP_LEFT]: { origin: ClrPosition.TOP_CENTER, content: ClrPosition.BOTTOM_RIGHT },
232
242
  // LEFT
233
- [ClrPopoverPosition.LEFT]: { anchor: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_TOP },
234
- [ClrPopoverPosition.LEFT_TOP]: { anchor: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_BOTTOM },
235
- [ClrPopoverPosition.LEFT_MIDDLE]: { anchor: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_CENTER },
236
- [ClrPopoverPosition.LEFT_BOTTOM]: { anchor: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_TOP },
243
+ [ClrPopoverPosition.LEFT]: { origin: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_TOP },
244
+ [ClrPopoverPosition.LEFT_TOP]: { origin: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_BOTTOM },
245
+ [ClrPopoverPosition.LEFT_MIDDLE]: { origin: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_CENTER },
246
+ [ClrPopoverPosition.LEFT_BOTTOM]: { origin: ClrPosition.LEFT_CENTER, content: ClrPosition.RIGHT_TOP },
237
247
  // RIGHT
238
- [ClrPopoverPosition.RIGHT]: { anchor: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_TOP },
239
- [ClrPopoverPosition.RIGHT_TOP]: { anchor: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_BOTTOM },
240
- [ClrPopoverPosition.RIGHT_MIDDLE]: { anchor: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_CENTER },
241
- [ClrPopoverPosition.RIGHT_BOTTOM]: { anchor: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_TOP },
248
+ [ClrPopoverPosition.RIGHT]: { origin: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_TOP },
249
+ [ClrPopoverPosition.RIGHT_TOP]: { origin: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_BOTTOM },
250
+ [ClrPopoverPosition.RIGHT_MIDDLE]: { origin: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_CENTER },
251
+ [ClrPopoverPosition.RIGHT_BOTTOM]: { origin: ClrPosition.RIGHT_CENTER, content: ClrPosition.LEFT_TOP },
242
252
  // BOTTOM
243
- [ClrPopoverPosition.BOTTOM_RIGHT]: { anchor: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_LEFT },
244
- [ClrPopoverPosition.BOTTOM_MIDDLE]: { anchor: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_CENTER },
245
- [ClrPopoverPosition.BOTTOM_LEFT]: { anchor: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_RIGHT },
253
+ [ClrPopoverPosition.BOTTOM_RIGHT]: { origin: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_LEFT },
254
+ [ClrPopoverPosition.BOTTOM_MIDDLE]: { origin: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_CENTER },
255
+ [ClrPopoverPosition.BOTTOM_LEFT]: { origin: ClrPosition.BOTTOM_CENTER, content: ClrPosition.TOP_RIGHT },
246
256
  };
247
- const DROPDOWN_ANCHORS = {
257
+ const DROPDOWN_ORIGINS = {
248
258
  // TOP
249
- [ClrPopoverPosition.TOP_RIGHT]: { anchor: ClrPosition.TOP_RIGHT, content: ClrPosition.BOTTOM_RIGHT },
250
- [ClrPopoverPosition.TOP_LEFT]: { anchor: ClrPosition.TOP_LEFT, content: ClrPosition.BOTTOM_LEFT },
259
+ [ClrPopoverPosition.TOP_RIGHT]: { origin: ClrPosition.TOP_RIGHT, content: ClrPosition.BOTTOM_RIGHT },
260
+ [ClrPopoverPosition.TOP_LEFT]: { origin: ClrPosition.TOP_LEFT, content: ClrPosition.BOTTOM_LEFT },
251
261
  // LEFT
252
- [ClrPopoverPosition.LEFT_TOP]: { anchor: ClrPosition.LEFT_TOP, content: ClrPosition.TOP_RIGHT },
253
- [ClrPopoverPosition.LEFT_BOTTOM]: { anchor: ClrPosition.LEFT_BOTTOM, content: ClrPosition.BOTTOM_RIGHT },
262
+ [ClrPopoverPosition.LEFT_TOP]: { origin: ClrPosition.LEFT_TOP, content: ClrPosition.TOP_RIGHT },
263
+ [ClrPopoverPosition.LEFT_BOTTOM]: { origin: ClrPosition.LEFT_BOTTOM, content: ClrPosition.BOTTOM_RIGHT },
254
264
  // RIGHT
255
- [ClrPopoverPosition.RIGHT_TOP]: { anchor: ClrPosition.RIGHT_TOP, content: ClrPosition.LEFT_TOP },
256
- [ClrPopoverPosition.RIGHT_BOTTOM]: { anchor: ClrPosition.RIGHT_BOTTOM, content: ClrPosition.LEFT_BOTTOM },
265
+ [ClrPopoverPosition.RIGHT_TOP]: { origin: ClrPosition.RIGHT_TOP, content: ClrPosition.LEFT_TOP },
266
+ [ClrPopoverPosition.RIGHT_BOTTOM]: { origin: ClrPosition.RIGHT_BOTTOM, content: ClrPosition.LEFT_BOTTOM },
257
267
  // BOTTOM
258
- [ClrPopoverPosition.BOTTOM_RIGHT]: { anchor: ClrPosition.BOTTOM_LEFT, content: ClrPosition.TOP_RIGHT },
259
- [ClrPopoverPosition.BOTTOM_LEFT]: { anchor: ClrPosition.BOTTOM_RIGHT, content: ClrPosition.TOP_LEFT },
268
+ [ClrPopoverPosition.BOTTOM_RIGHT]: { origin: ClrPosition.BOTTOM_LEFT, content: ClrPosition.TOP_RIGHT },
269
+ [ClrPopoverPosition.BOTTOM_LEFT]: { origin: ClrPosition.BOTTOM_RIGHT, content: ClrPosition.TOP_LEFT },
260
270
  };
261
271
  function mapPopoverKeyToPosition(key, type) {
262
272
  let offset = getOffset(key, type);
263
- const defaultPosition = { anchor: ClrPosition.BOTTOM_LEFT, content: ClrPosition.TOP_LEFT };
264
- const { anchor, content } = (type === ClrPopoverType.DROPDOWN ? DROPDOWN_ANCHORS[key] : STANDARD_ANCHORS[key]) ?? defaultPosition;
273
+ const defaultPosition = { origin: ClrPosition.BOTTOM_LEFT, content: ClrPosition.TOP_LEFT };
274
+ const { origin, content } = (type === ClrPopoverType.DROPDOWN ? DROPDOWN_ORIGINS[key] : STANDARD_ORIGINS[key]) ?? defaultPosition;
265
275
  return {
266
- ...getAnchorPosition(anchor),
276
+ ...getOriginPosition(origin),
267
277
  ...getContentPosition(content),
268
278
  ...offset,
269
279
  panelClass: key,
270
280
  };
271
281
  }
272
- function getAnchorPosition(key) {
282
+ function getOriginPosition(key) {
273
283
  switch (key) {
274
284
  // TOP Positions
275
285
  case ClrPosition.TOP_LEFT:
@@ -488,11 +498,19 @@ class ClrPopoverContent {
488
498
  set scrollToClose(scrollToClose) {
489
499
  this._scrollToClose = !!scrollToClose;
490
500
  }
501
+ set contentOrigin(origin) {
502
+ if (origin instanceof Element) {
503
+ this.popoverService.origin = new ElementRef(origin);
504
+ }
505
+ else {
506
+ this.popoverService.origin = origin;
507
+ }
508
+ }
491
509
  get positionStrategy() {
492
510
  return this.overlay
493
511
  .position()
494
- .flexibleConnectedTo(this.popoverService.anchorElementRef)
495
- .setOrigin(this.popoverService.anchorElementRef)
512
+ .flexibleConnectedTo(this.popoverService.origin)
513
+ .setOrigin(this.popoverService.origin)
496
514
  .withPush(true)
497
515
  .withPositions([this.preferredPosition, ...this._availablePositions])
498
516
  .withFlexibleDimensions(true);
@@ -535,13 +553,38 @@ class ClrPopoverContent {
535
553
  }), this.popoverService.updatePositionChange().subscribe(() => {
536
554
  this.overlayRef?.updatePosition();
537
555
  }), this.overlayRef.keydownEvents().subscribe(event => {
538
- if (event && event.key && normalizeKey(event.key) === Keys.Escape && !hasModifierKey(event)) {
556
+ if (event && event.key && event.key === Keys.Escape && !hasModifierKey(event)) {
539
557
  event.preventDefault();
540
558
  this.closePopover();
541
559
  }
542
- }), this.overlayRef.outsidePointerEvents().subscribe(event => {
560
+ }), this.popoverService.originPoint
561
+ ? this.createPointBasedOutsideClickSubscription()
562
+ : this.createElementBasedOutsideClickSubscription());
563
+ }
564
+ /**
565
+ * Point-based origins (context menus) delay the subscription to avoid the
566
+ * mouseup from the same right-click that opened the popover.
567
+ */
568
+ createPointBasedOutsideClickSubscription() {
569
+ return timer(500)
570
+ .pipe(switchMap(() => this.overlayRef.outsidePointerEvents()))
571
+ .subscribe(event => {
572
+ if (this.elementRef?.nativeElement?.contains(event.target)) {
573
+ return;
574
+ }
575
+ if (this._outsideClickClose) {
576
+ this.closePopover();
577
+ }
578
+ });
579
+ }
580
+ /**
581
+ * Element-based origins close on outside clicks and suppress toggle-button
582
+ * re-clicks so the popover doesn't immediately reopen.
583
+ */
584
+ createElementBasedOutsideClickSubscription() {
585
+ return this.overlayRef.outsidePointerEvents().subscribe(event => {
543
586
  // web components (cds-icon) register as outside pointer events, so if the event target is inside the content panel return early
544
- if (this.elementRef && this.elementRef.nativeElement.contains(event.target)) {
587
+ if (this.elementRef?.nativeElement?.contains(event.target)) {
545
588
  return;
546
589
  }
547
590
  // Check if the same element that opened the popover is the same element triggering the outside pointer events (toggle button)
@@ -555,7 +598,7 @@ class ClrPopoverContent {
555
598
  if (this._outsideClickClose || isToggleButton) {
556
599
  this.closePopover();
557
600
  }
558
- }));
601
+ });
559
602
  }
560
603
  resetPosition() {
561
604
  if (this.overlayRef) {
@@ -569,11 +612,13 @@ class ClrPopoverContent {
569
612
  }
570
613
  this.removeOverlay();
571
614
  this.popoverService.open = false;
572
- const shouldFocusTrigger = this.popoverType !== ClrPopoverType.TOOLTIP &&
573
- (document.activeElement === document.body ||
574
- document.activeElement === this.popoverService.anchorElementRef?.nativeElement);
575
- if (shouldFocusTrigger) {
576
- this.popoverService.focusAnchor();
615
+ if (this.popoverService.originElement) {
616
+ const shouldFocusTrigger = this.popoverType !== ClrPopoverType.TOOLTIP &&
617
+ (document.activeElement === document.body ||
618
+ document.activeElement === this.popoverService.originElement.nativeElement);
619
+ if (shouldFocusTrigger) {
620
+ this.popoverService.focusOrigin();
621
+ }
577
622
  }
578
623
  }
579
624
  showOverlay() {
@@ -591,15 +636,17 @@ class ClrPopoverContent {
591
636
  this.domPortal = new DomPortal(this.elementRef);
592
637
  this.overlayRef.attach(this.domPortal);
593
638
  }
594
- this.popoverService?.anchorElementRef?.nativeElement.scrollIntoView({
595
- behavior: 'instant',
596
- block: 'nearest',
597
- inline: 'nearest',
598
- });
599
- this.setupIntersectionObserver();
639
+ if (this.popoverService.originElement) {
640
+ this.popoverService.originElement.nativeElement.scrollIntoView({
641
+ behavior: 'instant',
642
+ block: 'nearest',
643
+ inline: 'nearest',
644
+ });
645
+ this.setupIntersectionObserver();
646
+ }
600
647
  setTimeout(() => {
601
648
  // Get Scrollable Parents
602
- this.listenToMouseEvents();
649
+ this.listenToScrollEvents();
603
650
  this.popoverService.popoverVisibleEmit(true);
604
651
  if (this.elementRef?.nativeElement?.focus) {
605
652
  this.elementRef.nativeElement.focus();
@@ -646,30 +693,46 @@ class ClrPopoverContent {
646
693
  return scrollableParents;
647
694
  }
648
695
  /**
649
- * Uses IntersectionObserver to detect when the anchor leaves the screen.
696
+ * Uses IntersectionObserver to detect when the origin element leaves the screen.
650
697
  * This handles the "Close on Scroll" logic much cheaper than getBoundingClientRect.
651
698
  */
652
699
  setupIntersectionObserver() {
653
- if (!this.popoverService.anchorElementRef || this.intersectionObserver) {
700
+ if (!this.popoverService.originElement || this.intersectionObserver) {
654
701
  return;
655
702
  }
656
703
  this.intersectionObserver = new IntersectionObserver(entries => {
657
704
  entries.forEach(entry => {
658
- // If the anchor is no longer visible (scrolled out of view)
705
+ // If the origin is no longer visible (scrolled out of view)
659
706
  if (!entry.isIntersecting && this.popoverService.open) {
660
707
  this.zone.run(() => this.closePopover());
661
708
  }
662
709
  });
663
710
  }, { root: null, threshold: 0.8 });
664
- this.intersectionObserver.observe(this.popoverService.anchorElementRef.nativeElement);
711
+ this.intersectionObserver.observe(this.popoverService.originElement.nativeElement);
665
712
  }
666
- //Align the popover on scrolling
667
- listenToMouseEvents() {
713
+ listenToScrollEvents() {
668
714
  if (!isPlatformBrowser(this.platformId)) {
669
715
  return;
670
716
  }
671
- const anchor = this.getRootPopover(this)?.popoverService?.anchorElementRef?.nativeElement;
672
- const scrollableParents = this.getScrollableParents(anchor);
717
+ if (this.popoverService.originPoint) {
718
+ this.listenToScrollForPointOrigin();
719
+ }
720
+ else {
721
+ this.listenToScrollForElementOrigin();
722
+ }
723
+ }
724
+ // Point origins have no scrollable parent chain — close on any scroll.
725
+ listenToScrollForPointOrigin() {
726
+ this.zone.runOutsideAngular(() => {
727
+ this.subscriptions.push(fromEvent(window, 'scroll', { passive: true, capture: true }).subscribe(() => {
728
+ this.zone.run(() => this.closePopover());
729
+ }));
730
+ });
731
+ }
732
+ // Element origins track ancestor scroll containers to reposition or close.
733
+ listenToScrollForElementOrigin() {
734
+ const originEl = this.getRootPopover(this)?.popoverService?.originElement?.nativeElement;
735
+ const scrollableParents = this.getScrollableParents(originEl);
673
736
  this.zone.runOutsideAngular(() => {
674
737
  this.subscriptions.push(merge(...scrollableParents.map(parent => fromEvent(parent, 'scroll', { passive: true }))).subscribe(() => {
675
738
  if (this._scrollToClose) {
@@ -687,7 +750,7 @@ class ClrPopoverContent {
687
750
  return popover;
688
751
  }
689
752
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverContent, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.TemplateRef, optional: true }, { token: i1.OverlayContainer }, { token: ClrPopoverContent, optional: true, skipSelf: true }, { token: i1.Overlay }, { token: ClrPopoverService }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
690
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverContent, isStandalone: true, selector: "[clrPopoverContent]", inputs: { open: ["clrPopoverContent", "open"], contentAt: ["clrPopoverContentAt", "contentAt"], availablePositions: ["clrPopoverContentAvailablePositions", "availablePositions"], contentType: ["clrPopoverContentType", "contentType"], outsideClickClose: ["clrPopoverContentOutsideClickToClose", "outsideClickClose"], scrollToClose: ["clrPopoverContentScrollToClose", "scrollToClose"] }, ngImport: i0 }); }
753
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverContent, isStandalone: true, selector: "[clrPopoverContent]", inputs: { open: ["clrPopoverContent", "open"], contentAt: ["clrPopoverContentAt", "contentAt"], availablePositions: ["clrPopoverContentAvailablePositions", "availablePositions"], contentType: ["clrPopoverContentType", "contentType"], outsideClickClose: ["clrPopoverContentOutsideClickToClose", "outsideClickClose"], scrollToClose: ["clrPopoverContentScrollToClose", "scrollToClose"], contentOrigin: ["clrPopoverContentOrigin", "contentOrigin"] }, ngImport: i0 }); }
691
754
  }
692
755
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverContent, decorators: [{
693
756
  type: Directive,
@@ -724,6 +787,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
724
787
  }], scrollToClose: [{
725
788
  type: Input,
726
789
  args: ['clrPopoverContentScrollToClose']
790
+ }], contentOrigin: [{
791
+ type: Input,
792
+ args: ['clrPopoverContentOrigin']
727
793
  }] } });
728
794
 
729
795
  /*
@@ -732,19 +798,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
732
798
  * This software is released under MIT license.
733
799
  * The full license information can be found in LICENSE in the root directory of this project.
734
800
  */
735
- class ClrPopoverAnchor {
801
+ class ClrPopoverOrigin {
736
802
  constructor(popoverService, element) {
737
- popoverService.anchorElementRef = element;
803
+ popoverService.origin = element;
738
804
  }
739
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverAnchor, deps: [{ token: ClrPopoverService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
740
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverAnchor, isStandalone: false, selector: "[clrPopoverAnchor]", host: { properties: { "class.clr-anchor": "true" } }, ngImport: i0 }); }
805
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverOrigin, deps: [{ token: ClrPopoverService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
806
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverOrigin, isStandalone: false, selector: "[clrPopoverOrigin]", host: { properties: { "class.clr-popover-origin": "true" } }, ngImport: i0 }); }
741
807
  }
742
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverAnchor, decorators: [{
808
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverOrigin, decorators: [{
743
809
  type: Directive,
744
810
  args: [{
745
- selector: '[clrPopoverAnchor]',
811
+ selector: '[clrPopoverOrigin]',
746
812
  host: {
747
- '[class.clr-anchor]': 'true',
813
+ '[class.clr-popover-origin]': 'true',
748
814
  },
749
815
  standalone: false,
750
816
  }]
@@ -756,7 +822,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
756
822
  * This software is released under MIT license.
757
823
  * The full license information can be found in LICENSE in the root directory of this project.
758
824
  */
759
- const POPOVER_HOST_ANCHOR = new InjectionToken('POPOVER_HOST_ANCHOR');
825
+ const POPOVER_HOST_ORIGIN = new InjectionToken('POPOVER_HOST_ORIGIN');
760
826
 
761
827
  /*
762
828
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
@@ -806,13 +872,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
806
872
  */
807
873
  class ClrPopoverHostDirective {
808
874
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverHostDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
809
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverHostDirective, isStandalone: true, providers: [ClrPopoverService, { provide: POPOVER_HOST_ANCHOR, useExisting: ElementRef }], hostDirectives: [{ directive: ClrStopEscapePropagationDirective }], ngImport: i0 }); }
875
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrPopoverHostDirective, isStandalone: true, providers: [ClrPopoverService, { provide: POPOVER_HOST_ORIGIN, useExisting: ElementRef }], hostDirectives: [{ directive: ClrStopEscapePropagationDirective }], ngImport: i0 }); }
810
876
  }
811
877
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverHostDirective, decorators: [{
812
878
  type: Directive,
813
879
  args: [{
814
880
  standalone: true,
815
- providers: [ClrPopoverService, { provide: POPOVER_HOST_ANCHOR, useExisting: ElementRef }],
881
+ providers: [ClrPopoverService, { provide: POPOVER_HOST_ORIGIN, useExisting: ElementRef }],
816
882
  hostDirectives: [ClrStopEscapePropagationDirective],
817
883
  }]
818
884
  }] });
@@ -918,12 +984,12 @@ class ClrPopoverCloseButton {
918
984
  this.closeChange = new EventEmitter();
919
985
  this.subscriptions = [];
920
986
  this.subscriptions.push(popoverService.openChange.pipe(filter(value => !value)).subscribe(() => {
921
- this.closeChange.next();
987
+ this.closeChange.emit();
922
988
  }));
923
989
  }
924
990
  handleClick(event) {
925
991
  this.popoverService.toggleWithEvent(event);
926
- this.popoverService.focusAnchor();
992
+ this.popoverService.focusOrigin();
927
993
  }
928
994
  ngAfterViewInit() {
929
995
  this.popoverService.closeButtonRef = this.elementRef;
@@ -963,7 +1029,7 @@ class ClrPopoverOpenCloseButton {
963
1029
  this.openCloseChange = new EventEmitter();
964
1030
  this.subscriptions = [];
965
1031
  this.subscriptions.push(popoverService.openChange.subscribe(change => {
966
- this.openCloseChange.next(change);
1032
+ this.openCloseChange.emit(change);
967
1033
  }));
968
1034
  }
969
1035
  handleClick(event) {
@@ -1000,15 +1066,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
1000
1066
  */
1001
1067
  class ClrPopoverModuleNext {
1002
1068
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverModuleNext, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1003
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverModuleNext, declarations: [ClrPopoverAnchor, ClrPopoverCloseButton, ClrPopoverOpenCloseButton], imports: [ClrPopoverContent, ClrIfOpen], exports: [ClrPopoverAnchor, ClrPopoverCloseButton, ClrPopoverOpenCloseButton, ClrPopoverContent, ClrIfOpen] }); }
1069
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverModuleNext, declarations: [ClrPopoverOrigin, ClrPopoverCloseButton, ClrPopoverOpenCloseButton], imports: [ClrPopoverContent, ClrIfOpen], exports: [ClrPopoverOrigin, ClrPopoverCloseButton, ClrPopoverOpenCloseButton, ClrPopoverContent, ClrIfOpen] }); }
1004
1070
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverModuleNext }); }
1005
1071
  }
1006
1072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrPopoverModuleNext, decorators: [{
1007
1073
  type: NgModule,
1008
1074
  args: [{
1009
1075
  imports: [ClrPopoverContent, ClrIfOpen],
1010
- declarations: [ClrPopoverAnchor, ClrPopoverCloseButton, ClrPopoverOpenCloseButton],
1011
- exports: [ClrPopoverAnchor, ClrPopoverCloseButton, ClrPopoverOpenCloseButton, ClrPopoverContent, ClrIfOpen],
1076
+ declarations: [ClrPopoverOrigin, ClrPopoverCloseButton, ClrPopoverOpenCloseButton],
1077
+ exports: [ClrPopoverOrigin, ClrPopoverCloseButton, ClrPopoverOpenCloseButton, ClrPopoverContent, ClrIfOpen],
1012
1078
  }]
1013
1079
  }] });
1014
1080
 
@@ -1023,5 +1089,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
1023
1089
  * Generated bundle index. Do not edit.
1024
1090
  */
1025
1091
 
1026
- export { ClrIfOpen, ClrPopoverAnchor, ClrPopoverContent, ClrPopoverHostDirective, ClrPopoverPosition, ClrPopoverService, ClrPopoverType, ClrStopEscapePropagationDirective, DROPDOWN_POSITIONS, POPOVER_HOST_ANCHOR, SIGNPOST_POSITIONS, TOOLTIP_POSITIONS, getAnchorPosition, getConnectedPositions, getContentPosition, getPositionsArray, mapPopoverKeyToPosition, ClrPopoverCloseButton as ÇlrClrPopoverCloseButton, ClrPopoverModuleNext as ÇlrClrPopoverModuleNext, ClrPopoverOpenCloseButton as ÇlrClrPopoverOpenCloseButton };
1092
+ export { ClrIfOpen, ClrPopoverCloseButton, ClrPopoverContent, ClrPopoverHostDirective, ClrPopoverModuleNext, ClrPopoverOpenCloseButton, ClrPopoverOrigin, ClrPopoverPosition, ClrPopoverService, ClrPopoverType, ClrStopEscapePropagationDirective, DROPDOWN_POSITIONS, POPOVER_HOST_ORIGIN, SIGNPOST_POSITIONS, TOOLTIP_POSITIONS, getConnectedPositions, getContentPosition, getOriginPosition, getPositionsArray, mapPopoverKeyToPosition };
1027
1093
  //# sourceMappingURL=clr-angular-popover-common.mjs.map