@nanahoshi/mona-ui 0.24.1 → 0.24.4

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 (52) hide show
  1. package/README.md +3 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +1 -1
  3. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +1 -1
  4. package/fesm2022/nanahoshi-mona-ui-button.mjs +122 -60
  5. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +1 -2
  6. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +1 -1
  7. package/fesm2022/nanahoshi-mona-ui-chip.mjs +1 -1
  8. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +1 -1
  9. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +2 -2
  10. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +4 -2
  11. package/fesm2022/nanahoshi-mona-ui-date-input.mjs +1 -1
  12. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +8 -4
  13. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +8 -4
  14. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +1 -1
  15. package/fesm2022/nanahoshi-mona-ui-dropdown-button.mjs +1 -1
  16. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +4 -2
  17. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +13 -3
  18. package/fesm2022/nanahoshi-mona-ui-editor.mjs +13 -13
  19. package/fesm2022/nanahoshi-mona-ui-filter.mjs +1 -1
  20. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-CnPhVIr4.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-DLOPRuFv.mjs} +2 -2
  21. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-DxY6bfTX.mjs → nanahoshi-mona-ui-grid-grid-list.component-Dw5U9H0a.mjs} +4 -4
  22. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-CaO5Lae6.mjs → nanahoshi-mona-ui-grid-grid-row.component-D1kyAzD8.mjs} +4 -4
  23. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-jNYtqg5B.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-ECK1_smx.mjs} +4 -4
  24. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-9FtfCutf.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-D4lUDbfx.mjs} +14 -18
  25. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  26. package/fesm2022/nanahoshi-mona-ui-internal-filter-input.mjs +2 -2
  27. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +1 -1
  28. package/fesm2022/nanahoshi-mona-ui-internal.mjs +15 -1
  29. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +1 -1
  30. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +3 -3
  31. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +1 -1
  32. package/fesm2022/nanahoshi-mona-ui-notification.mjs +1 -1
  33. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +3 -3
  34. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +1 -1
  35. package/fesm2022/nanahoshi-mona-ui-pager.mjs +1 -1
  36. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +2 -2
  37. package/fesm2022/nanahoshi-mona-ui-popup.mjs +269 -182
  38. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +1 -1
  39. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +1 -1
  40. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +1 -1
  41. package/fesm2022/nanahoshi-mona-ui-switch.mjs +1 -1
  42. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +1 -1
  43. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +95 -58
  44. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +7 -5
  45. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +2 -2
  46. package/fesm2022/nanahoshi-mona-ui-window.mjs +1 -1
  47. package/package.json +1 -1
  48. package/types/nanahoshi-mona-ui-button.d.ts +44 -20
  49. package/types/nanahoshi-mona-ui-dropdowns.d.ts +6 -0
  50. package/types/nanahoshi-mona-ui-internal.d.ts +9 -1
  51. package/types/nanahoshi-mona-ui-popup.d.ts +97 -36
  52. package/types/nanahoshi-mona-ui-text-box.d.ts +62 -14
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, DestroyRef, DOCUMENT, viewChild, ViewContainerRef, computed, signal, TemplateRef, Component, Injector, ElementRef, Injectable, input, output, effect } from '@angular/core';
2
+ import { InjectionToken, inject, DestroyRef, DOCUMENT, viewChild, ViewContainerRef, computed, signal, TemplateRef, Component, Injector, ElementRef, Injectable, input, output, booleanAttribute, effect } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { rxTimeout } from '@nanahoshi/mona-ui/internal';
5
- import { take, asapScheduler, Subject, ReplaySubject, asyncScheduler, fromEvent, takeUntil, Subscription, filter, tap, exhaustMap, merge } from 'rxjs';
4
+ import { take, asapScheduler, Subject, ReplaySubject, asyncScheduler, fromEvent, Subscription, merge, takeUntil } from 'rxjs';
6
5
  import { PreventableEvent } from '@nanahoshi/mona-ui/common';
7
6
  import { Directionality } from '@angular/cdk/bidi';
8
7
  import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
9
8
  import { ComponentPortal } from '@angular/cdk/portal';
10
9
  import { ScrollDispatcher } from '@angular/cdk/scrolling';
11
10
  import { MonaI18nService, resolveComponentDirection, observeComponentDirection } from '@nanahoshi/mona-ui/i18n';
11
+ import { focusCanReturn } from '@nanahoshi/mona-ui/internal';
12
12
  import { NgTemplateOutlet } from '@angular/common';
13
13
 
14
14
  class PopupCloseEvent extends PreventableEvent {
@@ -64,13 +64,17 @@ const slideFromBottomPopupAnimation = {
64
64
  leave: "mona-popup-slide-to-bottom-leave"
65
65
  };
66
66
 
67
- const PopupDataInjectionToken = new InjectionToken("PopupInjectionToken");
68
- const PopupSettingsInjectionToken = new InjectionToken("PopupSettingsInjectionToken");
67
+ /**
68
+ * The `data` passed in `PopupSettings`, available to the popup content.
69
+ */
70
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- public API name, kept for compatibility.
71
+ const PopupDataInjectionToken = new InjectionToken("PopupDataInjectionToken");
72
+ const POPUP_SETTINGS = new InjectionToken("POPUP_SETTINGS");
69
73
 
70
74
  /**
71
75
  * @internal - used by the popup service. Do not use directly or export.
72
76
  */
73
- const PopupReferenceInjectionToken = new InjectionToken("PopupReferenceInjectionToken");
77
+ const POPUP_REFERENCE = new InjectionToken("POPUP_REFERENCE");
74
78
 
75
79
  class PopupWrapperComponent {
76
80
  #destroyRef;
@@ -83,21 +87,21 @@ class PopupWrapperComponent {
83
87
  constructor() {
84
88
  this.#destroyRef = inject(DestroyRef);
85
89
  this.#document = inject(DOCUMENT);
86
- this.#popupReference = inject(PopupReferenceInjectionToken);
87
- this.#popupSettings = inject(PopupSettingsInjectionToken);
90
+ this.#popupReference = inject(POPUP_REFERENCE);
91
+ this.#popupSettings = inject(POPUP_SETTINGS);
88
92
  this.#closeEvent = null;
89
93
  this.#fallbackTimer = null;
90
94
  this.#leaveCompleted = false;
91
95
  this.animationElement = viewChild.required("animationElement", /* @ts-ignore */
92
96
  ...(ngDevMode ? [{ debugName: "animationElement" }] : /* istanbul ignore next */ []));
93
97
  this.componentOutlet = viewChild.required("componentOutlet", { ...(ngDevMode ? { debugName: "componentOutlet" } : /* istanbul ignore next */ {}), read: ViewContainerRef });
98
+ this.enterAnimationClasses = computed(() => this.#getAnimationConfig()?.enter ?? "", /* @ts-ignore */
99
+ ...(ngDevMode ? [{ debugName: "enterAnimationClasses" }] : /* istanbul ignore next */ []));
94
100
  this.hostClasses = computed(() => {
95
101
  const wrapperClass = this.wrapperClass();
96
102
  return ["mona-popup-wrapper", "w-full", "h-full", wrapperClass].filter(Boolean).join(" ");
97
103
  }, /* @ts-ignore */
98
104
  ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
99
- this.enterAnimationClasses = computed(() => this.#getAnimationConfig()?.enter ?? "", /* @ts-ignore */
100
- ...(ngDevMode ? [{ debugName: "enterAnimationClasses" }] : /* istanbul ignore next */ []));
101
105
  this.leaveAnimationClasses = computed(() => this.#getAnimationConfig()?.leave ?? "", /* @ts-ignore */
102
106
  ...(ngDevMode ? [{ debugName: "leaveAnimationClasses" }] : /* istanbul ignore next */ []));
103
107
  this.templateRef = signal(null, /* @ts-ignore */
@@ -120,7 +124,6 @@ class PopupWrapperComponent {
120
124
  });
121
125
  this.#destroyRef.onDestroy(() => this.#clearFallbackTimer());
122
126
  }
123
- ngOnInit() { }
124
127
  attachContent(content, injector) {
125
128
  if (content instanceof TemplateRef) {
126
129
  this.templateRef.set(content);
@@ -227,8 +230,15 @@ class PopupRef {
227
230
  constructor(options) {
228
231
  this.#options = options;
229
232
  }
233
+ /**
234
+ * Requests the popup to close.
235
+ * @param result optional result passed to `beforeClose` and `closed` as the event's `result`
236
+ * @param delay optional delay in milliseconds before the popup is removed, instead of waiting for the
237
+ * leave animation
238
+ * @returns `false` when the close was prevented or the popup is already closing, `true` otherwise.
239
+ */
230
240
  close(result, delay) {
231
- this.#options.close(result, delay);
241
+ return this.#options.close(result, delay);
232
242
  }
233
243
  /**
234
244
  * Closes the popup after a delay.
@@ -317,13 +327,13 @@ class PopupReference {
317
327
  constructor(overlayReference, preventClose) {
318
328
  this.overlayReference = overlayReference;
319
329
  this.preventClose = preventClose;
330
+ this.#closed = false;
331
+ this.#closing = false;
320
332
  this.beforeClosed$ = new Subject();
321
333
  this.closeStart$ = new Subject();
322
334
  this.closed$ = new Subject();
323
335
  this.opened$ = new ReplaySubject(1);
324
336
  this.positionChanges$ = new Subject();
325
- this.#closed = false;
326
- this.#closing = false;
327
337
  this.popupRef = new PopupRef(this);
328
338
  }
329
339
  /**
@@ -361,8 +371,20 @@ class PopupReference {
361
371
  }
362
372
  return true;
363
373
  }
364
- notifyOpen() {
365
- this.opened$.next();
374
+ /**
375
+ * Finishes a close that bypassed {@link close}: the overlay was detached or disposed directly. Nothing can
376
+ * prevent it any more, so `beforeClose` is skipped; `closeStart` and `closed` still fire, in that order.
377
+ */
378
+ closeDetached() {
379
+ if (this.#closed) {
380
+ return;
381
+ }
382
+ const event = new PopupCloseEvent({ via: PopupCloseSource.Programmatic });
383
+ if (!this.#closing) {
384
+ this.#closing = true;
385
+ this.closeStart$.next(event);
386
+ }
387
+ this.completeClose(event);
366
388
  }
367
389
  completeClose(event) {
368
390
  if (this.#closed) {
@@ -374,6 +396,9 @@ class PopupReference {
374
396
  this.positionChanges$.complete();
375
397
  this.overlayRef.dispose();
376
398
  }
399
+ notifyOpen() {
400
+ this.opened$.next();
401
+ }
377
402
  get beforeClose$() {
378
403
  return this.beforeClosed$.asObservable();
379
404
  }
@@ -516,38 +541,30 @@ const generateFallbackPositions = (primaryPosition) => {
516
541
  else if (originX === "end" && originY === "top" && overlayX === "start" && overlayY === "bottom") {
517
542
  fallbacks.push({ originX: "start", originY: "bottom", overlayX: "end", overlayY: "top" });
518
543
  }
519
- //6. Complete mirroring:
520
- if (!fallbacks.find(f => f.originX !== originX && f.overlayX !== overlayX && f.originY !== originY && f.overlayY !== overlayY)) {
521
- if (originX === "start" && originY === "top") {
522
- fallbacks.push({ originX: "end", originY: "bottom", overlayX: "end", overlayY: "bottom" });
523
- }
524
- else if (originX === "center" && originY === "top") {
525
- fallbacks.push({ originX: "center", originY: "bottom", overlayX: "center", overlayY: "bottom" });
526
- }
527
- else if (originX === "end" && originY === "top") {
528
- fallbacks.push({ originX: "start", originY: "bottom", overlayX: "start", overlayY: "bottom" });
529
- }
530
- else if (originX === "start" && originY === "center") {
531
- fallbacks.push({ originX: "end", originY: "center", overlayX: "end", overlayY: "center" });
532
- }
533
- else if (originX === "center" && originY === "center") {
534
- fallbacks.push({ originX: "center", originY: "center", overlayX: "center", overlayY: "center" });
535
- }
536
- else if (originX === "end" && originY === "center") {
537
- fallbacks.push({ originX: "start", originY: "center", overlayX: "start", overlayY: "center" });
538
- }
539
- else if (originX === "start" && originY === "bottom") {
540
- fallbacks.push({ originX: "end", originY: "top", overlayX: "end", overlayY: "top" });
541
- }
542
- else if (originX === "center" && originY === "bottom") {
543
- fallbacks.push({ originX: "center", originY: "top", overlayX: "center", overlayY: "top" });
544
- }
545
- else if (originX === "end" && originY === "bottom") {
546
- fallbacks.push({ originX: "start", originY: "top", overlayX: "start", overlayY: "top" });
547
- }
544
+ // 6. Complete mirroring: flip both the anchor corner and the popup corner on both axes, so the popup lands on
545
+ // the opposite side and alignment of the anchor. Flipping only the anchor corner and copying it onto the popup
546
+ // corner, as this used to do, placed the popup over the anchor.
547
+ const mirrored = {
548
+ originX: flipX(originX),
549
+ originY: flipY(originY),
550
+ overlayX: flipX(overlayX),
551
+ overlayY: flipY(overlayY)
552
+ };
553
+ const isPrimary = mirrored.originX === originX &&
554
+ mirrored.originY === originY &&
555
+ mirrored.overlayX === overlayX &&
556
+ mirrored.overlayY === overlayY;
557
+ const isListed = fallbacks.some(f => f.originX === mirrored.originX &&
558
+ f.originY === mirrored.originY &&
559
+ f.overlayX === mirrored.overlayX &&
560
+ f.overlayY === mirrored.overlayY);
561
+ if (!isPrimary && !isListed) {
562
+ fallbacks.push(mirrored);
548
563
  }
549
564
  return fallbacks;
550
565
  };
566
+ const flipX = (value) => (value === "start" ? "end" : value === "end" ? "start" : value);
567
+ const flipY = (value) => (value === "top" ? "bottom" : value === "bottom" ? "top" : value);
551
568
 
552
569
  class PopupService {
553
570
  #destroyRef = inject(DestroyRef);
@@ -555,10 +572,13 @@ class PopupService {
555
572
  #document = inject(DOCUMENT);
556
573
  #i18n = inject(MonaI18nService, { optional: true });
557
574
  #injector = inject(Injector);
575
+ /** Open popups in the order they were opened; the last one is on top. */
576
+ #openPopups = [];
558
577
  #outsideEventsToClose = ["click", "mousedown", "dblclick", "contextmenu", "auxclick"];
559
578
  #overlay = inject(Overlay);
560
579
  #scrollDispatcher = inject(ScrollDispatcher);
561
- #selectorSubscriptions = new Map();
580
+ #escapeSubscription = null;
581
+ #escapeTarget = null;
562
582
  create(settings) {
563
583
  if (typeof settings.anchor === "string") {
564
584
  return this.createMultiElementPopup(settings);
@@ -581,35 +601,33 @@ class PopupService {
581
601
  }
582
602
  return ["mona-popup-content"].concat(popupClass);
583
603
  }
604
+ /**
605
+ * With `"auto"` (also the default), remembers the focused element when it is the anchor or inside it, such
606
+ * as the button inside a host component or the input inside a date picker, and returns focus to that element.
607
+ */
584
608
  captureOriginalFocus(settings) {
585
- if (typeof settings.anchor === "string" || settings.restoreFocus === false) {
609
+ const restoreFocus = settings.restoreFocus ?? "auto";
610
+ if (typeof settings.anchor === "string" || restoreFocus === false) {
586
611
  return null;
587
612
  }
588
613
  const activeElement = this.#document.activeElement;
589
614
  if (!(activeElement instanceof HTMLElement)) {
590
615
  return null;
591
616
  }
592
- if (settings.restoreFocus === "auto") {
617
+ if (restoreFocus === "auto") {
593
618
  const anchorElement = this.getAnchorElement(settings.anchor);
594
- return activeElement === anchorElement ? activeElement : null;
619
+ return anchorElement?.contains(activeElement) ? activeElement : null;
595
620
  }
596
621
  return this.getAnchorElement(settings.anchor);
597
622
  }
598
- cleanupEventDelegation(selector) {
599
- const subscriptions = this.#selectorSubscriptions.get(selector);
600
- if (subscriptions) {
601
- subscriptions.forEach(sub => sub.unsubscribe());
602
- this.#selectorSubscriptions.delete(selector);
603
- }
604
- }
605
623
  createInjector(settings, popupReference) {
606
624
  return Injector.create({
607
- parent: this.#injector,
625
+ parent: settings.injector ?? this.#injector,
608
626
  providers: [
609
627
  { provide: PopupRef, useFactory: () => popupReference.popupRef },
610
628
  { provide: PopupDataInjectionToken, useValue: settings.data },
611
- { provide: PopupReferenceInjectionToken, useValue: popupReference },
612
- { provide: PopupSettingsInjectionToken, useValue: settings },
629
+ { provide: POPUP_REFERENCE, useValue: popupReference },
630
+ { provide: POPUP_SETTINGS, useValue: settings },
613
631
  ...(settings.providers ?? [])
614
632
  ]
615
633
  });
@@ -619,12 +637,9 @@ class PopupService {
619
637
  // Create a virtual PopupRef that manages multi-element interactions
620
638
  const virtualOverlayRef = this.#overlay.create({ hasBackdrop: false });
621
639
  const virtualPopupReference = new PopupReference(virtualOverlayRef);
622
- // Set up the event delegation internally
623
- this.setupInternalEventDelegation(selector, settings);
624
- // Clean up when the virtual popup is closed
625
- virtualPopupReference.popupRef.closed.subscribe(() => {
626
- this.cleanupEventDelegation(selector);
627
- });
640
+ // Closing the returned ref stops the delegation and closes the popup currently showing.
641
+ const delegation = this.setupInternalEventDelegation(selector, settings);
642
+ virtualPopupReference.popupRef.closed.pipe(take(1)).subscribe(() => delegation.unsubscribe());
628
643
  return virtualPopupReference.popupRef;
629
644
  }
630
645
  createOverlay(settings) {
@@ -698,7 +713,8 @@ class PopupService {
698
713
  this.setupScrollClosing(settings, popupReference, overlayRef);
699
714
  }
700
715
  this.setupScrollTracking(settings, overlayRef, popupReference);
701
- this.setupEscapeKeyListener(settings, popupReference);
716
+ this.registerOpenPopup(settings, popupReference);
717
+ this.setupDetachTracking(overlayRef, popupReference);
702
718
  this.setupPositionChangeTracking(settings, overlayRef, popupReference);
703
719
  this.setupDirectionTracking(settings, overlayRef, popupReference);
704
720
  return popupReference.popupRef;
@@ -745,18 +761,48 @@ class PopupService {
745
761
  .forEach(scrollable => addScrollable(scrollable));
746
762
  return Array.from(scrollablesByElement.values());
747
763
  }
748
- handleFocusRestoration(settings, originallyFocusedElement) {
764
+ getTopmostOpenPopup() {
765
+ for (let index = this.#openPopups.length - 1; index >= 0; index--) {
766
+ const popup = this.#openPopups[index];
767
+ if (popup.reference.overlayRef.hasAttached()) {
768
+ return popup;
769
+ }
770
+ }
771
+ return null;
772
+ }
773
+ /**
774
+ * Escape goes to the topmost open popup only, so closing a dropdown inside a dialog leaves the dialog
775
+ * open. The topmost popup consumes the key even when it doesn't close on Escape, so a modal that can't
776
+ * be dismissed doesn't let it reach the popup underneath. An Escape that ends an IME composition is left
777
+ * alone. `preventDefault()` doesn't keep the popup open, because controls call it on every navigation key;
778
+ * a control that handles Escape itself stops its propagation instead.
779
+ */
780
+ handleEscapeKey(event) {
781
+ const escapeTarget = this.#escapeTarget;
782
+ this.#escapeTarget = null;
783
+ if (event.key !== "Escape" || event.isComposing) {
784
+ return;
785
+ }
786
+ // The popup on top when the key was pressed, before handlers further down could close it.
787
+ const popup = escapeTarget?.event === event ? escapeTarget.popup : this.getTopmostOpenPopup();
788
+ if (!popup?.closeOnEscape) {
789
+ return;
790
+ }
791
+ popup.reference.popupRef.close(new PopupCloseEvent({
792
+ event,
793
+ originalEvent: event,
794
+ via: PopupCloseSource.Escape
795
+ }));
796
+ }
797
+ handleFocusRestoration(settings, overlayRef, originallyFocusedElement) {
749
798
  const restoreFocus = settings.restoreFocus ?? "auto";
750
799
  if (restoreFocus === false) {
751
800
  return;
752
801
  }
753
- if (restoreFocus === "auto") {
754
- if (originallyFocusedElement) {
755
- originallyFocusedElement.focus();
756
- }
757
- return;
802
+ const target = restoreFocus === "auto" ? originallyFocusedElement : this.getAnchorElement(settings.anchor);
803
+ if (target && focusCanReturn(this.#document, target, overlayRef.overlayElement)) {
804
+ target.focus();
758
805
  }
759
- this.restoreFocusToAnchor(settings.anchor);
760
806
  }
761
807
  isScrollableElement(element) {
762
808
  const defaultView = this.#document.defaultView;
@@ -773,6 +819,33 @@ class PopupService {
773
819
  isScrollableOverflow(value) {
774
820
  return value === "auto" || value === "scroll" || value === "overlay";
775
821
  }
822
+ /**
823
+ * One pair of `document` listeners serves every open popup. The capturing one notes which popup is on
824
+ * top before the key reaches any control; the bubbling one closes it if nothing handled the key.
825
+ */
826
+ listenForEscape() {
827
+ if (this.#escapeSubscription) {
828
+ return;
829
+ }
830
+ const subscription = new Subscription();
831
+ subscription.add(fromEvent(this.#document, "keydown", { capture: true }).subscribe(event => {
832
+ this.#escapeTarget = event.key === "Escape" ? { event, popup: this.getTopmostOpenPopup() } : null;
833
+ }));
834
+ subscription.add(fromEvent(this.#document, "keydown").subscribe(event => this.handleEscapeKey(event)));
835
+ this.#escapeSubscription = subscription;
836
+ }
837
+ /**
838
+ * A popup leaves the stack as soon as it starts closing, so a second Escape during its leave animation
839
+ * goes to the popup underneath.
840
+ */
841
+ registerOpenPopup(settings, popupReference) {
842
+ const popup = { closeOnEscape: settings.closeOnEscape ?? true, reference: popupReference };
843
+ this.#openPopups.push(popup);
844
+ this.listenForEscape();
845
+ merge(popupReference.closeStart, popupReference.closed)
846
+ .pipe(take(1))
847
+ .subscribe(() => this.unregisterOpenPopup(popup));
848
+ }
776
849
  /**
777
850
  * Resolves a PopupAnchor to a FlexibleConnectedPositionStrategyOrigin.
778
851
  * This method should only receive actual elements or ElementRefs, not CSS selector strings.
@@ -787,16 +860,6 @@ class PopupService {
787
860
  }
788
861
  return anchor;
789
862
  }
790
- restoreFocusToAnchor(anchor) {
791
- if (typeof anchor === "string") {
792
- return;
793
- }
794
- const resolvedAnchor = this.resolveAnchor(anchor);
795
- const anchorElement = this.getAnchorElement(resolvedAnchor);
796
- if (anchorElement) {
797
- anchorElement.focus();
798
- }
799
- }
800
863
  setupBackdropCloseSubscription(settings, popupReference, overlayRef) {
801
864
  if (!(settings.closeOnBackdropClick ?? true)) {
802
865
  return null;
@@ -831,7 +894,7 @@ class PopupService {
831
894
  setupCleanupSubscription(popupReference, subscription, settings, originallyFocusedElement) {
832
895
  popupReference.closed.pipe(take(1)).subscribe(() => {
833
896
  subscription?.unsubscribe();
834
- this.handleFocusRestoration(settings, originallyFocusedElement);
897
+ this.handleFocusRestoration(settings, popupReference.overlayRef, originallyFocusedElement);
835
898
  });
836
899
  }
837
900
  setupCloseSubscriptions(settings, popupReference, overlayRef) {
@@ -861,46 +924,70 @@ class PopupService {
861
924
  subscriptions.forEach(sub => combinedSubscription.add(sub));
862
925
  return combinedSubscription;
863
926
  }
864
- setupEscapeKeyListener(settings, popupReference) {
865
- if (settings.closeOnEscape === false) {
866
- return;
867
- }
868
- fromEvent(this.#document, "keydown")
869
- .pipe(filter(() => popupReference.overlayRef.hasAttached()), filter(event => event.key === "Escape"), takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
870
- .subscribe(event => {
871
- const closeEvent = new PopupCloseEvent({
872
- event,
873
- originalEvent: event,
874
- via: PopupCloseSource.Escape
875
- });
876
- popupReference.popupRef.close(closeEvent);
927
+ /**
928
+ * `PopupRef.overlayRef` is public, so the overlay can be detached or disposed without going through
929
+ * `close()`. Finish the close then too, or `closed` never fires and focus, subscriptions and consumers
930
+ * waiting for it (the dropdowns won't reopen until it does) stay stuck.
931
+ */
932
+ setupDetachTracking(overlayRef, popupReference) {
933
+ overlayRef
934
+ .detachments()
935
+ .pipe(take(1), takeUntil(popupReference.closed))
936
+ .subscribe(() => popupReference.closeDetached());
937
+ }
938
+ setupDirectionTracking(settings, overlayRef, popupReference) {
939
+ const resolvedAnchor = this.resolveAnchor(settings.anchor);
940
+ const anchorElement = this.getAnchorElement(resolvedAnchor);
941
+ const cleanup = observeComponentDirection(anchorElement, this.#directionality, nextDir => {
942
+ overlayRef.setDirection(nextDir);
943
+ overlayRef.updatePosition();
944
+ popupReference.componentRef?.changeDetectorRef.markForCheck();
945
+ });
946
+ popupReference.closed.pipe(take(1)).subscribe(() => {
947
+ cleanup();
877
948
  });
878
949
  }
950
+ /**
951
+ * Listens on the document rather than on the elements matched at creation time, so elements added later
952
+ * get a popup too. One popup shows at a time; it closes when the pointer leaves its element, and the
953
+ * returned subscription's teardown closes it as well.
954
+ */
879
955
  setupInternalEventDelegation(selector, settings) {
880
- this.cleanupEventDelegation(selector);
881
- let currentPopupRef = null;
882
- const subscriptions = [];
883
- const elements = this.#document.querySelectorAll(selector);
884
- elements.forEach(element => {
885
- if (!(element instanceof HTMLElement)) {
956
+ let current = null;
957
+ const closeCurrent = () => {
958
+ const popup = current;
959
+ current = null;
960
+ popup?.popupRef.close();
961
+ };
962
+ const subscription = new Subscription(closeCurrent);
963
+ subscription.add(fromEvent(this.#document, "pointerover")
964
+ .pipe(takeUntilDestroyed(this.#destroyRef))
965
+ .subscribe(event => {
966
+ const target = event.target instanceof Element ? event.target : null;
967
+ const element = target?.closest(selector);
968
+ if (!(element instanceof HTMLElement) || element === current?.element) {
886
969
  return;
887
970
  }
888
- const pointerEnter$ = fromEvent(element, "pointerenter");
889
- const pointerLeave$ = fromEvent(element, "pointerleave");
890
- const subscription = pointerEnter$
891
- .pipe(filter(() => !currentPopupRef), tap(() => {
892
- const elementSettings = { ...settings, anchor: element };
893
- currentPopupRef = this.createSingleElementPopup(elementSettings);
894
- }), exhaustMap(() => pointerLeave$.pipe(take(1))), tap(() => {
895
- if (currentPopupRef) {
896
- currentPopupRef.close();
897
- currentPopupRef = null;
971
+ closeCurrent();
972
+ const popupRef = this.createSingleElementPopup({ ...settings, anchor: element });
973
+ current = { element, popupRef };
974
+ popupRef.closed.pipe(take(1)).subscribe(() => {
975
+ if (current?.popupRef === popupRef) {
976
+ current = null;
898
977
  }
899
- }), takeUntilDestroyed(this.#destroyRef))
900
- .subscribe();
901
- subscriptions.push(subscription);
902
- });
903
- this.#selectorSubscriptions.set(selector, subscriptions);
978
+ });
979
+ }));
980
+ subscription.add(fromEvent(this.#document, "pointerout")
981
+ .pipe(takeUntilDestroyed(this.#destroyRef))
982
+ .subscribe(event => {
983
+ const element = current?.element;
984
+ const target = event.target instanceof Node ? event.target : null;
985
+ const next = event.relatedTarget instanceof Node ? event.relatedTarget : null;
986
+ if (element && target && element.contains(target) && !(next && element.contains(next))) {
987
+ closeCurrent();
988
+ }
989
+ }));
990
+ return subscription;
904
991
  }
905
992
  setupMouseLeaveSubscription(settings, popupReference) {
906
993
  if (typeof settings.anchor === "string") {
@@ -927,7 +1014,7 @@ class PopupService {
927
1014
  .outsidePointerEvents()
928
1015
  .pipe(takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
929
1016
  .subscribe(event => {
930
- if (this.shouldIgnoreOutsideClick(settings, event)) {
1017
+ if (this.shouldIgnoreOutsideClick(settings, event, overlayRef)) {
931
1018
  return;
932
1019
  }
933
1020
  const closeEvent = new PopupCloseEvent({
@@ -949,18 +1036,6 @@ class PopupService {
949
1036
  .subscribe(change => popupReference.positionChanges$.next(change.connectionPair));
950
1037
  }
951
1038
  }
952
- setupDirectionTracking(settings, overlayRef, popupReference) {
953
- const resolvedAnchor = this.resolveAnchor(settings.anchor);
954
- const anchorElement = this.getAnchorElement(resolvedAnchor);
955
- const cleanup = observeComponentDirection(anchorElement, this.#directionality, nextDir => {
956
- overlayRef.setDirection(nextDir);
957
- overlayRef.updatePosition();
958
- popupReference.componentRef?.changeDetectorRef.markForCheck();
959
- });
960
- popupReference.closed.pipe(take(1)).subscribe(() => {
961
- cleanup();
962
- });
963
- }
964
1039
  setupScrollClosing(settings, popupReference, overlayRef) {
965
1040
  if (!settings.closeOnScroll) {
966
1041
  return;
@@ -978,22 +1053,26 @@ class PopupService {
978
1053
  });
979
1054
  popupReference.close(closeEvent, 0);
980
1055
  };
1056
+ // The page scrolls the anchor away whether or not it also sits in a scrollable container.
1057
+ const win = this.#document.defaultView;
1058
+ const pageEvents = [
1059
+ fromEvent(win, "scroll", { passive: true }),
1060
+ fromEvent(this.#document, "scroll", { passive: true })
1061
+ ];
981
1062
  if (scrollableContainers.length === 0) {
982
- const win = this.#document.defaultView;
983
- const globalScrollSubscription = merge(fromEvent(win, "scroll", { passive: true }), fromEvent(win, "resize", { passive: true }), fromEvent(this.#document, "scroll", { passive: true }))
984
- .pipe(takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
985
- .subscribe(event => handleScrollClose(event));
986
- subscriptions.push(globalScrollSubscription);
987
- }
988
- else {
989
- scrollableContainers.forEach(scrollable => {
990
- const containerScrollSubscription = scrollable
991
- .elementScrolled()
992
- .pipe(takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
993
- .subscribe(() => handleScrollClose());
994
- subscriptions.push(containerScrollSubscription);
995
- });
1063
+ pageEvents.push(fromEvent(win, "resize", { passive: true }));
996
1064
  }
1065
+ const pageScrollSubscription = merge(...pageEvents)
1066
+ .pipe(takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
1067
+ .subscribe(event => handleScrollClose(event));
1068
+ subscriptions.push(pageScrollSubscription);
1069
+ scrollableContainers.forEach(scrollable => {
1070
+ const containerScrollSubscription = scrollable
1071
+ .elementScrolled()
1072
+ .pipe(takeUntil(popupReference.closed), takeUntilDestroyed(this.#destroyRef))
1073
+ .subscribe(() => handleScrollClose());
1074
+ subscriptions.push(containerScrollSubscription);
1075
+ });
997
1076
  popupReference.closed.pipe(take(1)).subscribe(() => {
998
1077
  subscriptions.forEach(sub => sub.unsubscribe());
999
1078
  });
@@ -1031,8 +1110,13 @@ class PopupService {
1031
1110
  subscriptions.forEach(sub => sub.unsubscribe());
1032
1111
  });
1033
1112
  }
1034
- shouldIgnoreOutsideClick(settings, event) {
1113
+ shouldIgnoreOutsideClick(settings, event, overlayRef) {
1035
1114
  const eventTarget = event.target;
1115
+ // The backdrop lies outside the pane, so its clicks also arrive here. They belong to the backdrop
1116
+ // handler, which honours closeOnBackdropClick and reports them as BackdropClick.
1117
+ if (overlayRef.backdropElement?.contains(eventTarget)) {
1118
+ return true;
1119
+ }
1036
1120
  if (typeof settings.anchor === "string") {
1037
1121
  return !this.#outsideEventsToClose.includes(event.type);
1038
1122
  }
@@ -1042,6 +1126,17 @@ class PopupService {
1042
1126
  const isRelevantEventType = this.#outsideEventsToClose.includes(event.type);
1043
1127
  return isAnchorClick || !isRelevantEventType;
1044
1128
  }
1129
+ unregisterOpenPopup(popup) {
1130
+ const index = this.#openPopups.indexOf(popup);
1131
+ if (index !== -1) {
1132
+ this.#openPopups.splice(index, 1);
1133
+ }
1134
+ if (this.#openPopups.length === 0) {
1135
+ this.#escapeSubscription?.unsubscribe();
1136
+ this.#escapeSubscription = null;
1137
+ this.#escapeTarget = null;
1138
+ }
1139
+ }
1045
1140
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1046
1141
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupService, providedIn: "root" }); }
1047
1142
  }
@@ -1065,14 +1160,14 @@ class PopupComponent {
1065
1160
  #destroyRef;
1066
1161
  #document;
1067
1162
  #popupService;
1068
- #popupOpened;
1069
1163
  #eventListenerCleanup$;
1164
+ #popupOpened;
1070
1165
  constructor() {
1071
1166
  this.#destroyRef = inject(DestroyRef);
1072
1167
  this.#document = inject(DOCUMENT);
1073
1168
  this.#popupService = inject(PopupService);
1074
- this.#popupOpened = false;
1075
1169
  this.#eventListenerCleanup$ = new Subject();
1170
+ this.#popupOpened = false;
1076
1171
  this.contentTemplate = viewChild.required(TemplateRef, /* @ts-ignore */
1077
1172
  ...(ngDevMode ? [{ debugName: "contentTemplate" }] : /* istanbul ignore next */ []));
1078
1173
  this.popupRef = null;
@@ -1099,28 +1194,30 @@ class PopupComponent {
1099
1194
  /**
1100
1195
  * @description Emits when the popup is closed.
1101
1196
  */
1197
+ // eslint-disable-next-line @angular-eslint/no-output-native -- public API name, kept for compatibility.
1102
1198
  this.close = output();
1103
1199
  /**
1104
1200
  * @description Whether to close the popup when clicking on the backdrop.
1105
1201
  * Only applies when the popup has a backdrop.
1106
1202
  */
1107
- this.closeOnBackdropClick = input(true, /* @ts-ignore */
1108
- ...(ngDevMode ? [{ debugName: "closeOnBackdropClick" }] : /* istanbul ignore next */ []));
1203
+ this.closeOnBackdropClick = input(true, { ...(ngDevMode ? { debugName: "closeOnBackdropClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1109
1204
  /**
1110
1205
  * @description Whether to close the popup when the escape key is pressed.
1206
+ * Escape only reaches the topmost open popup.
1111
1207
  */
1112
- this.closeOnEscape = input(true, /* @ts-ignore */
1113
- ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
1208
+ this.closeOnEscape = input(true, { ...(ngDevMode ? { debugName: "closeOnEscape" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1114
1209
  /**
1115
1210
  * @description Whether to close the popup when the mouse leaves the anchor element.
1116
1211
  */
1117
- this.closeOnMouseLeave = input(false, /* @ts-ignore */
1118
- ...(ngDevMode ? [{ debugName: "closeOnMouseLeave" }] : /* istanbul ignore next */ []));
1212
+ this.closeOnMouseLeave = input(false, { ...(ngDevMode ? { debugName: "closeOnMouseLeave" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1119
1213
  /**
1120
1214
  * @description Whether to close the popup when clicking outside of it.
1121
1215
  */
1122
- this.closeOnOutsideClick = input(true, /* @ts-ignore */
1123
- ...(ngDevMode ? [{ debugName: "closeOnOutsideClick" }] : /* istanbul ignore next */ []));
1216
+ this.closeOnOutsideClick = input(true, { ...(ngDevMode ? { debugName: "closeOnOutsideClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1217
+ /**
1218
+ * @description Whether to close the popup when the user scrolls the page or a scrollable container around the anchor.
1219
+ */
1220
+ this.closeOnScroll = input(false, { ...(ngDevMode ? { debugName: "closeOnScroll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1124
1221
  /**
1125
1222
  * @description Arbitrary data to pass to the popup.
1126
1223
  */
@@ -1129,8 +1226,7 @@ class PopupComponent {
1129
1226
  /**
1130
1227
  * @description Whether the popup should have a backdrop.
1131
1228
  */
1132
- this.hasBackdrop = input(false, /* @ts-ignore */
1133
- ...(ngDevMode ? [{ debugName: "hasBackdrop" }] : /* istanbul ignore next */ []));
1229
+ this.hasBackdrop = input(false, { ...(ngDevMode ? { debugName: "hasBackdrop" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1134
1230
  /**
1135
1231
  * @description The height of the popup.
1136
1232
  */
@@ -1205,6 +1301,15 @@ class PopupComponent {
1205
1301
  */
1206
1302
  this.providers = input([], /* @ts-ignore */
1207
1303
  ...(ngDevMode ? [{ debugName: "providers" }] : /* istanbul ignore next */ []));
1304
+ /**
1305
+ * @description Controls focus restoration when the popup closes.
1306
+ * - `true`: always restore focus to the anchor element.
1307
+ * - `false`: never restore focus (recommended for tooltips).
1308
+ * - `"auto"`: restore focus only if the anchor, or an element inside it, was focused when the popup opened.
1309
+ *
1310
+ * Focus is left alone if the user moved it outside the popup and the anchor before it closed.
1311
+ */
1312
+ this.restoreFocus = input("auto", { ...(ngDevMode ? { debugName: "restoreFocus" } : /* istanbul ignore next */ {}), transform: (value) => (value === "auto" ? "auto" : booleanAttribute(value)) });
1208
1313
  /**
1209
1314
  * @description The trigger event for opening the popup.
1210
1315
  */
@@ -1218,34 +1323,16 @@ class PopupComponent {
1218
1323
  /**
1219
1324
  * @description Whether to push the popup into the screen when it is opened.
1220
1325
  */
1221
- this.withPush = input(true, /* @ts-ignore */
1222
- ...(ngDevMode ? [{ debugName: "withPush" }] : /* istanbul ignore next */ []));
1223
- /**
1224
- * @description Whether to close the popup when the user scrolls within a scrollable container.
1225
- */
1226
- this.closeOnScroll = input(false, /* @ts-ignore */
1227
- ...(ngDevMode ? [{ debugName: "closeOnScroll" }] : /* istanbul ignore next */ []));
1228
- /**
1229
- * @description Controls focus restoration when the popup closes.
1230
- * - `true`: always restore focus to the anchor element.
1231
- * - `false`: never restore focus (recommended for tooltips).
1232
- * - `"auto"`: restore focus only if the anchor was focused when the popup opened.
1233
- */
1234
- this.restoreFocus = input("auto", /* @ts-ignore */
1235
- ...(ngDevMode ? [{ debugName: "restoreFocus" }] : /* istanbul ignore next */ []));
1326
+ this.withPush = input(true, { ...(ngDevMode ? { debugName: "withPush" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1236
1327
  /**
1237
1328
  * @description Whether the popup should track scroll events and reposition itself.
1238
1329
  */
1239
- this.withScrollTracking = input(true, /* @ts-ignore */
1240
- ...(ngDevMode ? [{ debugName: "withScrollTracking" }] : /* istanbul ignore next */ []));
1330
+ this.withScrollTracking = input(true, { ...(ngDevMode ? { debugName: "withScrollTracking" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1241
1331
  effect(() => this.setupEventListeners());
1242
1332
  }
1243
1333
  closePopup() {
1244
1334
  this.popupRef?.close();
1245
1335
  }
1246
- ngAfterViewInit() {
1247
- rxTimeout(this.#destroyRef, () => this.setupEventListeners());
1248
- }
1249
1336
  ngOnDestroy() {
1250
1337
  this.popupRef?.close();
1251
1338
  this.#eventListenerCleanup$.next();
@@ -1285,7 +1372,6 @@ class PopupComponent {
1285
1372
  target = this.#document.body;
1286
1373
  pointAnchor = true;
1287
1374
  }
1288
- const width = this.getPopupWidth();
1289
1375
  fromEvent(target, trigger)
1290
1376
  .pipe(takeUntil(this.#eventListenerCleanup$), takeUntilDestroyed(this.#destroyRef))
1291
1377
  .subscribe(event => {
@@ -1325,7 +1411,8 @@ class PopupComponent {
1325
1411
  preventClose: this.preventClose(),
1326
1412
  providers: this.providers(),
1327
1413
  restoreFocus: this.restoreFocus(),
1328
- width,
1414
+ // Measured now rather than when the listener was set up, so it follows the anchor's size.
1415
+ width: this.getPopupWidth(),
1329
1416
  withPush: this.withPush(),
1330
1417
  withScrollTracking: this.withScrollTracking()
1331
1418
  };
@@ -1357,12 +1444,12 @@ class PopupComponent {
1357
1444
  });
1358
1445
  }
1359
1446
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1360
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: PopupComponent, isStandalone: true, selector: "mona-popup", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: true, transformFunction: null }, anchorConnectionPoint: { classPropertyName: "anchorConnectionPoint", publicName: "anchorConnectionPoint", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdropClick: { classPropertyName: "closeOnBackdropClick", publicName: "closeOnBackdropClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, closeOnMouseLeave: { classPropertyName: "closeOnMouseLeave", publicName: "closeOnMouseLeave", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "closeOnOutsideClick", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, popupClass: { classPropertyName: "popupClass", publicName: "popupClass", isSignal: true, isRequired: false, transformFunction: null }, popupConnectionPoint: { classPropertyName: "popupConnectionPoint", publicName: "popupConnectionPoint", isSignal: true, isRequired: false, transformFunction: null }, popupWrapperClass: { classPropertyName: "popupWrapperClass", publicName: "popupWrapperClass", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, positions: { classPropertyName: "positions", publicName: "positions", isSignal: true, isRequired: false, transformFunction: null }, preventClose: { classPropertyName: "preventClose", publicName: "preventClose", isSignal: true, isRequired: false, transformFunction: null }, providers: { classPropertyName: "providers", publicName: "providers", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, withPush: { classPropertyName: "withPush", publicName: "withPush", isSignal: true, isRequired: false, transformFunction: null }, closeOnScroll: { classPropertyName: "closeOnScroll", publicName: "closeOnScroll", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", isSignal: true, isRequired: false, transformFunction: null }, withScrollTracking: { classPropertyName: "withScrollTracking", publicName: "withScrollTracking", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", open: "open" }, viewQueries: [{ propertyName: "contentTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n" }); }
1447
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: PopupComponent, isStandalone: true, selector: "mona-popup", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: true, transformFunction: null }, anchorConnectionPoint: { classPropertyName: "anchorConnectionPoint", publicName: "anchorConnectionPoint", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdropClick: { classPropertyName: "closeOnBackdropClick", publicName: "closeOnBackdropClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, closeOnMouseLeave: { classPropertyName: "closeOnMouseLeave", publicName: "closeOnMouseLeave", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "closeOnOutsideClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnScroll: { classPropertyName: "closeOnScroll", publicName: "closeOnScroll", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, popupClass: { classPropertyName: "popupClass", publicName: "popupClass", isSignal: true, isRequired: false, transformFunction: null }, popupConnectionPoint: { classPropertyName: "popupConnectionPoint", publicName: "popupConnectionPoint", isSignal: true, isRequired: false, transformFunction: null }, popupWrapperClass: { classPropertyName: "popupWrapperClass", publicName: "popupWrapperClass", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, positions: { classPropertyName: "positions", publicName: "positions", isSignal: true, isRequired: false, transformFunction: null }, preventClose: { classPropertyName: "preventClose", publicName: "preventClose", isSignal: true, isRequired: false, transformFunction: null }, providers: { classPropertyName: "providers", publicName: "providers", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, withPush: { classPropertyName: "withPush", publicName: "withPush", isSignal: true, isRequired: false, transformFunction: null }, withScrollTracking: { classPropertyName: "withScrollTracking", publicName: "withScrollTracking", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", open: "open" }, viewQueries: [{ propertyName: "contentTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n" }); }
1361
1448
  }
1362
1449
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupComponent, decorators: [{
1363
1450
  type: Component,
1364
1451
  args: [{ selector: "mona-popup", template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n" }]
1365
- }], ctorParameters: () => [], propDecorators: { contentTemplate: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: true }] }], anchorConnectionPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorConnectionPoint", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], closeOnMouseLeave: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnMouseLeave", required: false }] }], closeOnOutsideClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsideClick", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], open: [{ type: i0.Output, args: ["open"] }], popupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupClass", required: false }] }], popupConnectionPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupConnectionPoint", required: false }] }], popupWrapperClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupWrapperClass", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], positions: [{ type: i0.Input, args: [{ isSignal: true, alias: "positions", required: false }] }], preventClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventClose", required: false }] }], providers: [{ type: i0.Input, args: [{ isSignal: true, alias: "providers", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], withPush: [{ type: i0.Input, args: [{ isSignal: true, alias: "withPush", required: false }] }], closeOnScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnScroll", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], withScrollTracking: [{ type: i0.Input, args: [{ isSignal: true, alias: "withScrollTracking", required: false }] }] } });
1452
+ }], ctorParameters: () => [], propDecorators: { contentTemplate: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: true }] }], anchorConnectionPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorConnectionPoint", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], closeOnMouseLeave: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnMouseLeave", required: false }] }], closeOnOutsideClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsideClick", required: false }] }], closeOnScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnScroll", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], open: [{ type: i0.Output, args: ["open"] }], popupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupClass", required: false }] }], popupConnectionPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupConnectionPoint", required: false }] }], popupWrapperClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "popupWrapperClass", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], positions: [{ type: i0.Input, args: [{ isSignal: true, alias: "positions", required: false }] }], preventClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventClose", required: false }] }], providers: [{ type: i0.Input, args: [{ isSignal: true, alias: "providers", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], withPush: [{ type: i0.Input, args: [{ isSignal: true, alias: "withPush", required: false }] }], withScrollTracking: [{ type: i0.Input, args: [{ isSignal: true, alias: "withScrollTracking", required: false }] }] } });
1366
1453
 
1367
1454
  /*
1368
1455
  * Public API Surface of @nanahoshi/mona-ui/popup