@coreui/angular 5.7.37 → 5.7.38

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.
@@ -8,7 +8,7 @@ import { takeUntilDestroyed, toObservable, toSignal } from "@angular/core/rxjs-i
8
8
  import { debounceTime, filter, finalize, map, switchMap, take as take$1, tap } from "rxjs/operators";
9
9
  import { NG_ASYNC_VALIDATORS, NG_VALIDATORS, NgModel } from "@angular/forms";
10
10
  import * as i1 from "@angular/cdk/a11y";
11
- import { A11yModule, CdkTrapFocus, FocusKeyManager, FocusMonitor } from "@angular/cdk/a11y";
11
+ import { A11yModule, CdkTrapFocus, FocusKeyManager, FocusMonitor, addAriaReferencedId, getAriaReferenceIds, removeAriaReferencedId } from "@angular/cdk/a11y";
12
12
  import { createPopper } from "@popperjs/core";
13
13
  import { BreakpointObserver } from "@angular/cdk/layout";
14
14
  import { DomPortal, DomPortalOutlet } from "@angular/cdk/portal";
@@ -2703,67 +2703,74 @@ i0.ɵɵngDeclareClassMetadata({
2703
2703
  }]
2704
2704
  }]
2705
2705
  });
2706
+ const afterTransitions = async (element) => {
2707
+ const running = () => element.getAnimations?.().filter((animation) => "transitionProperty" in animation) ?? [];
2708
+ for (let transitions = running(); transitions.length;) transitions = (await Promise.allSettled(transitions.map((transition) => transition.finished))).some(({ status }) => status === "rejected") ? running() : [];
2709
+ };
2706
2710
  var BackdropService = class BackdropService {
2707
2711
  #backdropClick = new Subject();
2708
2712
  backdropClick$ = this.#backdropClick.asObservable();
2709
2713
  #document = inject(DOCUMENT);
2710
2714
  activeBackdrop;
2711
- #clearBackdropId;
2712
- #pendingBackdrop;
2715
+ #backdrops = /* @__PURE__ */ new Map();
2716
+ #clickHandler = () => this.onClickHandler();
2713
2717
  get #scrollbarWidth() {
2714
2718
  const documentWidth = this.#document.documentElement.clientWidth;
2715
2719
  return `${Math.abs((this.#document.defaultView?.innerWidth ?? documentWidth) - documentWidth)}px`;
2716
2720
  }
2717
2721
  scrollbarWidth = this.#scrollbarWidth;
2718
- setBackdrop(type = "modal") {
2719
- this.#flushClearBackdrop();
2720
- const backdropElement = this.#document.createElement("div");
2721
- backdropElement.classList.add(`${type}-backdrop`);
2722
- backdropElement.classList.add("fade");
2723
- this.#document.body.appendChild(backdropElement);
2724
- const clickHandler = () => {
2725
- this.onClickHandler();
2722
+ setBackdrop(type = "modal", fade = true) {
2723
+ const existing = this.#backdrops.get(type);
2724
+ const backdrop = existing?.element.isConnected ? existing : this.#createBackdrop(type);
2725
+ const fading = backdrop.fading;
2726
+ backdrop.users++;
2727
+ backdrop.element.classList.toggle("fade", fade);
2728
+ if (fading) {
2729
+ backdrop.fading = void 0;
2730
+ backdrop.element.addEventListener("click", this.#clickHandler);
2731
+ }
2732
+ if (fading && backdrop.shown || !fade) this.#show(backdrop);
2733
+ this.activeBackdrop = backdrop.element;
2734
+ return backdrop.element;
2735
+ }
2736
+ clearBackdrop(backdropElement) {
2737
+ const backdrop = [...this.#backdrops.values()].find(({ element }) => element === backdropElement);
2738
+ if (backdrop?.users && --backdrop.users === 0) this.#fadeOut(backdrop);
2739
+ }
2740
+ #createBackdrop(type) {
2741
+ const element = this.#document.createElement("div");
2742
+ const backdrop = {
2743
+ type,
2744
+ element,
2745
+ users: 0
2726
2746
  };
2727
- backdropElement.__backdropClickHandler = clickHandler;
2728
- backdropElement.addEventListener("click", clickHandler);
2729
- this.scrollbarWidth = this.#scrollbarWidth;
2747
+ element.classList.add(`${type}-backdrop`);
2748
+ this.#document.body.appendChild(element);
2749
+ element.addEventListener("click", this.#clickHandler);
2750
+ this.#backdrops.set(type, backdrop);
2730
2751
  setTimeout(() => {
2731
- backdropElement.classList.add("show");
2752
+ if (backdrop.users && !backdrop.fading) this.#show(backdrop);
2732
2753
  });
2733
- this.activeBackdrop = backdropElement;
2734
- return backdropElement;
2754
+ return backdrop;
2735
2755
  }
2736
- clearBackdrop(backdropElement) {
2737
- if (backdropElement) {
2738
- const storedHandler = backdropElement.__backdropClickHandler;
2739
- if (storedHandler) {
2740
- backdropElement.removeEventListener("click", storedHandler);
2741
- delete backdropElement.__backdropClickHandler;
2742
- }
2743
- backdropElement.classList.remove("show");
2744
- this.#flushClearBackdrop();
2745
- this.#pendingBackdrop = backdropElement;
2746
- this.#clearBackdropId = setTimeout(() => {
2747
- this.#clearBackdropId = void 0;
2748
- this.#pendingBackdrop = void 0;
2749
- if (this.activeBackdrop === backdropElement) {
2750
- this.resetScrollbar();
2751
- this.activeBackdrop = void 0;
2752
- }
2753
- this.#removeBackdrop(backdropElement);
2754
- }, 300);
2755
- }
2756
+ #show(backdrop) {
2757
+ backdrop.element.classList.add("show");
2758
+ backdrop.shown = true;
2756
2759
  }
2757
- #flushClearBackdrop() {
2758
- if (this.#clearBackdropId === void 0) return;
2759
- clearTimeout(this.#clearBackdropId);
2760
- this.#clearBackdropId = void 0;
2761
- const pending = this.#pendingBackdrop;
2762
- this.#pendingBackdrop = void 0;
2763
- if (pending) this.#removeBackdrop(pending);
2764
- }
2765
- #removeBackdrop(backdropElement) {
2766
- if (backdropElement.parentElement === this.#document.body) this.#document.body.removeChild(backdropElement);
2760
+ #fadeOut(backdrop) {
2761
+ const fading = {};
2762
+ backdrop.fading = fading;
2763
+ backdrop.element.removeEventListener("click", this.#clickHandler);
2764
+ queueMicrotask(() => {
2765
+ if (backdrop.fading !== fading) return;
2766
+ backdrop.element.classList.remove("show");
2767
+ afterTransitions(backdrop.element).then(() => {
2768
+ if (backdrop.fading !== fading) return;
2769
+ if (this.#backdrops.get(backdrop.type) === backdrop) this.#backdrops.delete(backdrop.type);
2770
+ backdrop.element.remove();
2771
+ if (this.activeBackdrop === backdrop.element) this.activeBackdrop = void 0;
2772
+ });
2773
+ });
2767
2774
  }
2768
2775
  get #isRTL() {
2769
2776
  return [this.#document.documentElement.dir, this.#document.body.dir].includes("rtl");
@@ -2771,18 +2778,29 @@ var BackdropService = class BackdropService {
2771
2778
  get #padding() {
2772
2779
  return `padding-${this.#isRTL ? "left" : "right"}`;
2773
2780
  }
2774
- #scrollBarVisible = true;
2775
- hideScrollbar() {
2776
- if (this.#scrollBarVisible) {
2781
+ #scrollLockOwners = /* @__PURE__ */ new Set();
2782
+ #lockedPadding = "";
2783
+ lockScroll(owner) {
2784
+ if (this.#scrollLockOwners.has(owner)) return;
2785
+ this.#scrollLockOwners.add(owner);
2786
+ if (this.#scrollLockOwners.size === 1) {
2787
+ this.scrollbarWidth = this.#scrollbarWidth;
2788
+ this.#lockedPadding = this.#padding;
2777
2789
  this.#document.body.style.setProperty("overflow", "hidden");
2778
- this.#document.body.style.setProperty(this.#padding, this.scrollbarWidth);
2779
- this.#scrollBarVisible = false;
2790
+ this.#document.body.style.setProperty(this.#lockedPadding, this.scrollbarWidth);
2791
+ }
2792
+ }
2793
+ unlockScroll(owner) {
2794
+ if (this.#scrollLockOwners.delete(owner) && this.#scrollLockOwners.size === 0) {
2795
+ this.#document.body.style.removeProperty("overflow");
2796
+ this.#document.body.style.removeProperty(this.#lockedPadding);
2780
2797
  }
2781
2798
  }
2799
+ hideScrollbar() {
2800
+ this.lockScroll(this);
2801
+ }
2782
2802
  resetScrollbar() {
2783
- this.#document.body.style.removeProperty("overflow");
2784
- this.#document.body.style.removeProperty(this.#padding);
2785
- this.#scrollBarVisible = true;
2803
+ this.unlockScroll(this);
2786
2804
  }
2787
2805
  onClickHandler() {
2788
2806
  this.#backdropClick.next(true);
@@ -4519,11 +4537,15 @@ i0.ɵɵngDeclareClassMetadata({
4519
4537
  });
4520
4538
  var UIDService = class UIDService {
4521
4539
  #document = inject(DOCUMENT);
4540
+ #infix = Math.floor(Math.random() * 36 ** 5).toString(36).padStart(5, "0");
4541
+ #counters = /* @__PURE__ */ new Map();
4522
4542
  getUID(prefix = "random-id") {
4523
- let uid = prefix;
4524
- do
4525
- uid = `${prefix}-${Math.floor(Math.random() * 1e6).toString(10)}`;
4526
- while (this.#document.getElementById(uid));
4543
+ let uid;
4544
+ do {
4545
+ const count = (this.#counters.get(prefix) ?? 0) + 1;
4546
+ this.#counters.set(prefix, count);
4547
+ uid = `${prefix}-${this.#infix}-${count}`;
4548
+ } while (this.#document.getElementById(uid));
4527
4549
  return uid;
4528
4550
  }
4529
4551
  static ɵfac = i0.ɵɵngDeclareFactory({
@@ -8209,6 +8231,7 @@ const alignmentClasses = (alignment) => {
8209
8231
  return Object.fromEntries(Object.entries(alignment).map(([breakpoint, direction]) => [`dropdown-menu${breakpoint === BreakpointInfix.xs ? "" : `-${breakpoint}`}-${direction}`, true]));
8210
8232
  };
8211
8233
  const FOCUSABLE_SELECTOR = "a[href], button, input, select, textarea, [tabindex]";
8234
+ const FORM_TAG = /^(form|input|option|select|textarea)$/;
8212
8235
  var DropdownToken = class {};
8213
8236
  var DropdownToggleDirective = class DropdownToggleDirective {
8214
8237
  elementRef = inject(ElementRef);
@@ -8497,10 +8520,6 @@ var DropdownComponent = class DropdownComponent {
8497
8520
  hostStyle = computed(() => {
8498
8521
  return this.variant() === "input-group" ? { display: "contents" } : {};
8499
8522
  }, ...ngDevMode ? [{ debugName: "hostStyle" }] : /* istanbul ignore next */ []);
8500
- clickedTarget;
8501
- onHostClick($event) {
8502
- this.clickedTarget = $event.target;
8503
- }
8504
8523
  dropdownStateSubscribe() {
8505
8524
  this.dropdownService.dropdownState$.pipe(filter((state) => {
8506
8525
  return this === state.dropdown;
@@ -8554,30 +8573,16 @@ var DropdownComponent = class DropdownComponent {
8554
8573
  }
8555
8574
  setListeners() {
8556
8575
  this.listeners.push(this.#renderer.listen(this.#document, "click", (event) => {
8557
- const target = event.target;
8558
- if (this._menuElementRef()?.nativeElement.contains(event.target)) this.clickedTarget = target;
8559
- if (this.#togglerElement()?.contains(event.target)) return;
8576
+ const part = this.#eventPart(event);
8577
+ if (part === "toggler" || part === "menu" && this.#isFormInteraction(event)) return;
8560
8578
  const autoClose = this.autoClose();
8561
- if (autoClose === true) {
8562
- this.setVisibleState(false);
8563
- return;
8564
- }
8565
- if (this.clickedTarget === target && autoClose === "inside") {
8566
- this.setVisibleState(false);
8567
- return;
8568
- }
8569
- if (this.clickedTarget !== target && autoClose === "outside") {
8570
- this.setVisibleState(false);
8571
- return;
8572
- }
8579
+ if (autoClose === true || autoClose === "inside" && part === "menu" || autoClose === "outside" && part !== "menu") this.setVisibleState(false);
8573
8580
  }));
8574
8581
  this.listeners.push(this.#renderer.listen(this.#elementRef.nativeElement, "keydown", this.#onEscape));
8575
8582
  const toggler = this.#togglerElement();
8576
8583
  if (toggler && !this.#elementRef.nativeElement.contains(toggler)) this.listeners.push(this.#renderer.listen(toggler, "keydown", this.#onEscape));
8577
8584
  this.listeners.push(this.#renderer.listen(this.#document, "keyup", (event) => {
8578
- const path = event.composedPath();
8579
- const toggler = this.#togglerElement();
8580
- if (event.key === "Tab" && this.autoClose() !== false && !path.includes(this.#elementRef.nativeElement) && !(toggler && path.includes(toggler))) this.setVisibleState(false);
8585
+ if (event.key === "Tab" && this.autoClose() !== false && !this.#eventPart(event)) this.setVisibleState(false);
8581
8586
  }));
8582
8587
  }
8583
8588
  #onEscape = (event) => {
@@ -8602,6 +8607,17 @@ var DropdownComponent = class DropdownComponent {
8602
8607
  #togglerElement() {
8603
8608
  return (this._toggler() ?? this.toggler)?.elementRef.nativeElement;
8604
8609
  }
8610
+ #eventPart(event) {
8611
+ const path = event.composedPath();
8612
+ const toggler = this.#togglerElement();
8613
+ if (toggler && path.includes(toggler)) return "toggler";
8614
+ const menu = this._menuElementRef()?.nativeElement;
8615
+ return menu && path.includes(menu) ? "menu" : void 0;
8616
+ }
8617
+ #isFormInteraction(event) {
8618
+ const path = event.composedPath();
8619
+ return path.slice(0, path.indexOf(this._menuElementRef()?.nativeElement) + 1).some((node) => node instanceof Element && FORM_TAG.test(node.localName));
8620
+ }
8605
8621
  #focusToggler() {
8606
8622
  const toggler = this.#togglerElement();
8607
8623
  if (!toggler) return;
@@ -8693,13 +8709,10 @@ var DropdownComponent = class DropdownComponent {
8693
8709
  }
8694
8710
  },
8695
8711
  outputs: { visibleChange: "visibleChange" },
8696
- host: {
8697
- listeners: { "click": "onHostClick($event)" },
8698
- properties: {
8699
- "class": "hostClasses()",
8700
- "style": "hostStyle()"
8701
- }
8702
- },
8712
+ host: { properties: {
8713
+ "class": "hostClasses()",
8714
+ "style": "hostStyle()"
8715
+ } },
8703
8716
  providers: [DropdownService],
8704
8717
  queries: [
8705
8718
  {
@@ -8754,8 +8767,7 @@ i0.ɵɵngDeclareClassMetadata({
8754
8767
  }],
8755
8768
  host: {
8756
8769
  "[class]": "hostClasses()",
8757
- "[style]": "hostStyle()",
8758
- "(click)": "onHostClick($event)"
8770
+ "[style]": "hostStyle()"
8759
8771
  },
8760
8772
  styles: [":host-context(.dropdown,.dropup):not(.btn-group){display:block}:host-context(.dropstart,.dropend):not(.btn-group){display:inline-flex}:host-context(.input-group) :host.dropdown:first-child::ng-deep :first-child{border-start-end-radius:0;border-end-end-radius:0}:host-context(.input-group) :host.dropdown:first-child::ng-deep :not(:first-child):not(.dropdown-menu){margin-left:-1px;border-start-start-radius:0;border-end-start-radius:0}:host-context(.input-group) :host.dropdown:first-child::ng-deep :not(:first-child):not(.dropdown-menu):not(:only-of-type){border-start-end-radius:0;border-end-end-radius:0}:host-context(.input-group) :host.dropdown:last-child::ng-deep :first-child{border-start-start-radius:0;border-end-start-radius:0}:host-context(.input-group) :host.dropdown:last-child::ng-deep :first-child:not(:only-of-type){border-start-end-radius:0;border-end-end-radius:0}:host-context(.input-group) :host.dropdown:last-child::ng-deep :not(:first-child):not(.dropdown-menu){margin-left:-1px;border-start-start-radius:0;border-end-start-radius:0}\n"]
8761
8773
  }]
@@ -8892,7 +8904,7 @@ var DropdownItemDirective = class DropdownItemDirective {
8892
8904
  };
8893
8905
  }, ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
8894
8906
  onClick($event) {
8895
- this.handleInteraction();
8907
+ if ($event.target === this.elementRef.nativeElement || !isEditableTarget$1($event.target)) this.handleInteraction();
8896
8908
  }
8897
8909
  onKeyUp($event) {
8898
8910
  const target = $event.target;
@@ -8900,7 +8912,7 @@ var DropdownItemDirective = class DropdownItemDirective {
8900
8912
  }
8901
8913
  handleInteraction() {
8902
8914
  if (this.autoClose()) this.#dropdownService.toggle({
8903
- visible: "toggle",
8915
+ visible: false,
8904
8916
  dropdown: this.dropdown
8905
8917
  });
8906
8918
  }
@@ -13600,14 +13612,31 @@ i0.ɵɵngDeclareClassMetadata({
13600
13612
  }
13601
13613
  });
13602
13614
  var ModalService = class ModalService {
13615
+ #document = inject(DOCUMENT);
13603
13616
  #modalState = new Subject();
13604
13617
  modalState$ = this.#modalState.asObservable();
13618
+ #opened = new Subject();
13619
+ opened$ = this.#opened.asObservable();
13620
+ #openClassHolders = /* @__PURE__ */ new Set();
13605
13621
  toggle(action) {
13606
13622
  this.#modalState.next({
13607
13623
  ...action,
13608
13624
  focusFallback: [...action.focusFallback ?? []]
13609
13625
  });
13610
13626
  }
13627
+ announceOpened(modal, focusFallback) {
13628
+ this.#opened.next({
13629
+ modal,
13630
+ focusFallback
13631
+ });
13632
+ }
13633
+ addOpenClass(modal) {
13634
+ this.#openClassHolders.add(modal);
13635
+ this.#document.body.classList.add("modal-open");
13636
+ }
13637
+ removeOpenClass(modal) {
13638
+ if (this.#openClassHolders.delete(modal) && this.#openClassHolders.size === 0) this.#document.body.classList.remove("modal-open");
13639
+ }
13611
13640
  static ɵfac = i0.ɵɵngDeclareFactory({
13612
13641
  minVersion: "12.0.0",
13613
13642
  version: "22.2.3",
@@ -13815,6 +13844,7 @@ var ModalComponent = class ModalComponent {
13815
13844
  #backdropService = inject(BackdropService);
13816
13845
  #destroyRef = inject(DestroyRef);
13817
13846
  #platformId = inject(PLATFORM_ID);
13847
+ #generatedId = inject(UIDService).getUID("modal");
13818
13848
  alignment = input("top", ...ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []);
13819
13849
  backdrop = input(true, ...ngDevMode ? [{ debugName: "backdrop" }] : /* istanbul ignore next */ []);
13820
13850
  container = input(this.#document.body, ...ngDevMode ? [{ debugName: "container" }] : /* istanbul ignore next */ []);
@@ -13828,7 +13858,7 @@ var ModalComponent = class ModalComponent {
13828
13858
  alias: "id"
13829
13859
  });
13830
13860
  get id() {
13831
- return this.attrId();
13861
+ return this.attrId() || this.#generatedId;
13832
13862
  }
13833
13863
  portal = input(false, {
13834
13864
  ...ngDevMode ? { debugName: "portal" } : /* istanbul ignore next */ {},
@@ -13911,24 +13941,16 @@ var ModalComponent = class ModalComponent {
13911
13941
  ...ngDevMode ? { debugName: "modalDialogRef" } : /* istanbul ignore next */ {},
13912
13942
  read: ElementRef
13913
13943
  });
13914
- #modalDialogEffect = effect((OnCleanup) => {
13915
- const modalDialogElement = this.modalDialogRef().nativeElement;
13916
- const removeEventListeners = () => {
13917
- modalDialogElement?.removeEventListener("transitionend", this.#handleTransitionEnd);
13918
- };
13919
- OnCleanup(removeEventListeners);
13920
- modalDialogElement?.addEventListener("transitionend", this.#handleTransitionEnd);
13921
- }, ...ngDevMode ? [{ debugName: "#modalDialogEffect" }] : /* istanbul ignore next */ []);
13922
- #handleTransitionEnd = (event) => {
13923
- const modalDialogElement = this.modalDialogRef().nativeElement;
13924
- if (event.target === modalDialogElement && event.propertyName === "transform") {
13925
- if (!this.visible()) {
13926
- this.domPortalCleanup();
13927
- this.#renderer.setStyle(this.#hostElement.nativeElement, "display", "none");
13928
- }
13929
- }
13930
- };
13944
+ #hideEffect = afterRenderEffect({ read: (onCleanup) => {
13945
+ if (this.visible() || this.#hidden) return;
13946
+ let cancelled = false;
13947
+ onCleanup(() => cancelled = true);
13948
+ Promise.all([afterTransitions(this.#hostElement.nativeElement), afterTransitions(this.modalDialogRef().nativeElement)]).then(() => {
13949
+ if (!cancelled && !this.visible()) this.#completeHide();
13950
+ });
13951
+ } }, ...ngDevMode ? [{ debugName: "#hideEffect" }] : /* istanbul ignore next */ []);
13931
13952
  #activeBackdrop;
13953
+ #hidden = true;
13932
13954
  hostClasses = computed(() => {
13933
13955
  return {
13934
13956
  modal: true,
@@ -13948,16 +13970,23 @@ var ModalComponent = class ModalComponent {
13948
13970
  #show = signal(false, ...ngDevMode ? [{ debugName: "#show" }] : /* istanbul ignore next */ []);
13949
13971
  animateStart() {
13950
13972
  if (this.visible()) {
13951
- this.#backdropService.hideScrollbar();
13973
+ this.#hidden = false;
13952
13974
  this.#renderer.setStyle(this.#hostElement.nativeElement, "display", "block");
13953
- } else if (!this.transition()) {
13954
- this.domPortalCleanup();
13955
- this.#renderer.setStyle(this.#hostElement.nativeElement, "display", "none");
13956
- }
13975
+ } else if (!this.#hidden && !isPlatformBrowser(this.#platformId)) this.#completeHide();
13957
13976
  setTimeout(() => {
13958
13977
  this.show = this.visible();
13959
13978
  });
13960
13979
  }
13980
+ #completeHide() {
13981
+ this.#hidden = true;
13982
+ this.domPortalCleanup();
13983
+ this.#renderer.setStyle(this.#hostElement.nativeElement, "display", "none");
13984
+ this.#releaseBody();
13985
+ }
13986
+ #releaseBody() {
13987
+ this.#backdropService.unlockScroll(this);
13988
+ this.#modalService.removeOpenClass(this);
13989
+ }
13961
13990
  onKeyDownHandler(event) {
13962
13991
  if (event.key === "Escape" && !event.defaultPrevented && this.keyboard() && this.visible()) {
13963
13992
  if (this.backdrop() === "static") this.setStaticBackdrop();
@@ -14003,24 +14032,32 @@ var ModalComponent = class ModalComponent {
14003
14032
  this.#afterViewInit.set(false);
14004
14033
  this.setBackdrop(false);
14005
14034
  this.domPortalCleanup();
14035
+ this.#releaseBody();
14006
14036
  }
14007
14037
  stateToggleSubscribe() {
14008
14038
  this.#modalService.modalState$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe((action) => {
14009
- if (this === action.modal || this.id === action.id) {
14039
+ if (!action.modal && !action.id) this.#closeFor(action.focusFallback);
14040
+ else if (this === action.modal || this.id === action.id) {
14010
14041
  if ("show" in action) {
14011
14042
  const visible = this.visible();
14012
14043
  const show = action?.show === "toggle" ? !visible : !!action.show;
14013
14044
  if (show && !visible) {
14014
14045
  this.#trigger = action.trigger ?? null;
14015
14046
  this.#openAction = action;
14016
- }
14017
- this.visible.set(show);
14047
+ this.visible.set(true);
14048
+ this.#modalService.announceOpened(this, action.focusFallback);
14049
+ } else this.visible.set(show);
14018
14050
  }
14019
- } else if (this.visible()) {
14020
- for (const target of this.#focusCandidates()) if (!action.focusFallback?.includes(target)) action.focusFallback?.push(target);
14021
- this.visible.set(false);
14022
14051
  }
14023
14052
  });
14053
+ this.#modalService.opened$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(({ modal, focusFallback }) => {
14054
+ if (modal !== this) this.#closeFor(focusFallback);
14055
+ });
14056
+ }
14057
+ #closeFor(focusFallback) {
14058
+ if (!this.visible()) return;
14059
+ for (const target of this.#focusCandidates()) if (!focusFallback.includes(target)) focusFallback.push(target);
14060
+ this.visible.set(false);
14024
14061
  }
14025
14062
  #focusCandidates() {
14026
14063
  return [
@@ -14037,12 +14074,14 @@ var ModalComponent = class ModalComponent {
14037
14074
  if (isPlatformBrowser(this.#platformId)) restoreFocus(this.#hostElement.nativeElement, candidates);
14038
14075
  }
14039
14076
  setBackdrop(setBackdrop) {
14040
- this.#activeBackdrop = setBackdrop ? this.#backdropService.setBackdrop("modal") : this.#backdropService.clearBackdrop(this.#activeBackdrop);
14077
+ if (setBackdrop) this.#activeBackdrop ??= this.#backdropService.setBackdrop("modal", this.transition());
14078
+ else this.#activeBackdrop = this.#backdropService.clearBackdrop(this.#activeBackdrop);
14041
14079
  }
14042
14080
  setBodyStyles(open) {
14043
- if (open) {
14044
- if (!!this.backdrop()) this.#renderer.addClass(this.#document.body, "modal-open");
14045
- } else this.#renderer.removeClass(this.#document.body, "modal-open");
14081
+ if (!open) return;
14082
+ this.#backdropService.lockScroll(this);
14083
+ if (this.backdrop() !== false) this.#modalService.addOpenClass(this);
14084
+ else this.#modalService.removeOpenClass(this);
14046
14085
  }
14047
14086
  setStaticBackdrop() {
14048
14087
  if (this.transition()) {
@@ -14172,7 +14211,7 @@ var ModalComponent = class ModalComponent {
14172
14211
  "class": "hostClasses()",
14173
14212
  "attr.role": "visible() ? role() : null",
14174
14213
  "inert": "ariaHidden()",
14175
- "attr.id": "id",
14214
+ "attr.id": "attrId()",
14176
14215
  "aria-modal": "ariaModal()",
14177
14216
  "attr.tabindex": "-1"
14178
14217
  },
@@ -14257,7 +14296,7 @@ i0.ɵɵngDeclareClassMetadata({
14257
14296
  "[class]": "hostClasses()",
14258
14297
  "[attr.role]": "visible() ? role() : null",
14259
14298
  "[inert]": "ariaHidden()",
14260
- "[attr.id]": "id",
14299
+ "[attr.id]": "attrId()",
14261
14300
  "[aria-modal]": "ariaModal()",
14262
14301
  "[attr.tabindex]": "-1",
14263
14302
  "(mousedown)": "onMouseDownHandler($event)",
@@ -14436,7 +14475,6 @@ var ModalModule = class ModalModule {
14436
14475
  version: "22.2.3",
14437
14476
  ngImport: i0,
14438
14477
  type: ModalModule,
14439
- providers: [ModalService],
14440
14478
  imports: [ModalComponent]
14441
14479
  });
14442
14480
  };
@@ -14467,8 +14505,7 @@ i0.ɵɵngDeclareClassMetadata({
14467
14505
  ModalHeaderComponent,
14468
14506
  ModalTitleDirective,
14469
14507
  ModalToggleDirective
14470
- ],
14471
- providers: [ModalService]
14508
+ ]
14472
14509
  }]
14473
14510
  }]
14474
14511
  });
@@ -14535,10 +14572,11 @@ var OffcanvasComponent = class OffcanvasComponent {
14535
14572
  #activeBackdrop;
14536
14573
  #backdropClickSubscription;
14537
14574
  #layoutChangeSubscription;
14538
- #hideFallbackId;
14539
14575
  #focusBeforeShow = null;
14576
+ #hidden = signal(true, ...ngDevMode ? [{ debugName: "#hidden" }] : /* istanbul ignore next */ []);
14540
14577
  #isShown = false;
14541
14578
  #shownAsPanel = false;
14579
+ #transitionWait;
14542
14580
  #trigger = null;
14543
14581
  #inPlace = signal(false, ...ngDevMode ? [{ debugName: "#inPlace" }] : /* istanbul ignore next */ []);
14544
14582
  scroll = input(false, {
@@ -14574,20 +14612,36 @@ var OffcanvasComponent = class OffcanvasComponent {
14574
14612
  #afterEveryRenderFn = afterEveryRender({ read: () => this.#readPosition() });
14575
14613
  visibleEffect = effect(() => {
14576
14614
  const visible = this.visible();
14577
- const wasShown = this.#isShown;
14578
- this.animateStart(visible);
14579
- if (visible) {
14580
- if (!wasShown) this.#focusBeforeShow = this.#document.activeElement;
14581
- this.setBackdrop(this.backdrop());
14582
- this.setFocus();
14583
- } else {
14584
- this.#shownAsPanel = false;
14585
- this.#restoreFocus();
14586
- this.setBackdrop(false);
14587
- }
14588
- this.layoutChangeSubscribe(visible);
14589
- this.visibleChange?.emit(visible);
14615
+ untracked(() => {
14616
+ const wasShown = this.#isShown;
14617
+ this.animateStart(visible);
14618
+ if (visible) {
14619
+ if (!wasShown) this.#focusBeforeShow = this.#document.activeElement;
14620
+ this.setFocus();
14621
+ } else {
14622
+ this.#shownAsPanel = false;
14623
+ this.#restoreFocus();
14624
+ }
14625
+ this.visibleChange?.emit(visible);
14626
+ });
14590
14627
  }, ...ngDevMode ? [{ debugName: "visibleEffect" }] : /* istanbul ignore next */ []);
14628
+ #backdropEffect = effect(() => {
14629
+ const backdrop = this.visible() && this.backdrop();
14630
+ untracked(() => this.setBackdrop(backdrop));
14631
+ }, ...ngDevMode ? [{ debugName: "#backdropEffect" }] : /* istanbul ignore next */ []);
14632
+ #scrollLockEffect = effect(() => {
14633
+ const visible = this.visible();
14634
+ const scroll = this.scroll();
14635
+ untracked(() => {
14636
+ if (!visible) return;
14637
+ if (scroll) this.#backdropService.unlockScroll(this);
14638
+ else this.#backdropService.lockScroll(this);
14639
+ });
14640
+ }, ...ngDevMode ? [{ debugName: "#scrollLockEffect" }] : /* istanbul ignore next */ []);
14641
+ #layoutEffect = effect(() => {
14642
+ const breakpoint = this.visible() && this.responsiveBreakpoint;
14643
+ untracked(() => this.layoutChangeSubscribe(breakpoint));
14644
+ }, ...ngDevMode ? [{ debugName: "#layoutEffect" }] : /* istanbul ignore next */ []);
14591
14645
  visibleChange = output();
14592
14646
  hostClasses = computed(() => {
14593
14647
  const responsive = this.responsive();
@@ -14603,6 +14657,9 @@ var OffcanvasComponent = class OffcanvasComponent {
14603
14657
  ariaHidden = computed(() => {
14604
14658
  return this.visible() || this.#inPlace() ? null : true;
14605
14659
  }, ...ngDevMode ? [{ debugName: "ariaHidden" }] : /* istanbul ignore next */ []);
14660
+ hostInert = computed(() => {
14661
+ return this.#hidden() ? this.ariaHidden() : null;
14662
+ }, ...ngDevMode ? [{ debugName: "hostInert" }] : /* istanbul ignore next */ []);
14606
14663
  get tabIndex() {
14607
14664
  return "-1";
14608
14665
  }
@@ -14620,20 +14677,24 @@ var OffcanvasComponent = class OffcanvasComponent {
14620
14677
  return breakpointValue ? `${parseFloat(breakpointValue.trim()) - .02}px` : false;
14621
14678
  }
14622
14679
  animateStart(visible = this.visible()) {
14623
- const wasShown = this.#isShown;
14680
+ const host = this.#hostElement.nativeElement;
14624
14681
  this.#isShown = visible;
14625
- this.#clearHideFallback();
14626
14682
  if (visible) {
14627
- if (!this.scroll()) this.#backdropService.hideScrollbar();
14628
- this.#renderer.removeClass(this.#hostElement.nativeElement, "hiding");
14629
- this.#renderer.addClass(this.#hostElement.nativeElement, "showing");
14683
+ this.#hidden.set(false);
14684
+ this.#renderer.removeClass(host, "hiding");
14685
+ this.#renderer.addClass(host, "showing");
14630
14686
  } else {
14631
- this.#renderer.removeClass(this.#hostElement.nativeElement, "showing");
14632
- if (wasShown) {
14633
- this.#renderer.addClass(this.#hostElement.nativeElement, "hiding");
14634
- this.#scheduleHideFallback();
14635
- }
14687
+ this.#renderer.removeClass(host, "showing");
14688
+ if (this.#hidden()) return;
14689
+ this.#renderer.addClass(host, "hiding");
14636
14690
  }
14691
+ const transitionWait = {};
14692
+ this.#transitionWait = transitionWait;
14693
+ afterTransitions(host).then(() => {
14694
+ if (this.#transitionWait !== transitionWait || this.visible() !== visible) return;
14695
+ if (visible) this.#renderer.removeClass(host, "showing");
14696
+ else this.#completeHide();
14697
+ });
14637
14698
  }
14638
14699
  onKeyDownHandler(event) {
14639
14700
  if (event.key === "Escape" && !event.defaultPrevented && this.keyboard() && this.visible() && this.backdrop() !== "static") this.#offcanvasService.toggle({
@@ -14653,7 +14714,6 @@ var OffcanvasComponent = class OffcanvasComponent {
14653
14714
  setTimeout(() => {
14654
14715
  this.#renderer.setStyle(this.#hostElement.nativeElement, "display", "flex");
14655
14716
  });
14656
- this.#hostElement.nativeElement.addEventListener("transitionend", this.#handleTransitionEnd);
14657
14717
  }
14658
14718
  ngOnDestroy() {
14659
14719
  if (this.#trigger || this.#focusBeforeShow) this.#restoreFocus();
@@ -14661,38 +14721,17 @@ var OffcanvasComponent = class OffcanvasComponent {
14661
14721
  show: false,
14662
14722
  id: this.id()
14663
14723
  });
14664
- this.#removeEventListeners();
14665
- this.#clearHideFallback();
14724
+ this.#transitionWait = void 0;
14666
14725
  this.setBackdrop(false);
14726
+ this.#backdropService.unlockScroll(this);
14667
14727
  this.domPortalCleanup();
14668
14728
  }
14669
- #removeEventListeners = () => {
14670
- this.#hostElement.nativeElement.removeEventListener("transitionend", this.#handleTransitionEnd);
14671
- };
14672
- #handleTransitionEnd = (event) => {
14673
- const offcanvasElement = this.#hostElement.nativeElement;
14674
- if (event.target === offcanvasElement && event.propertyName === "transform") {
14675
- if (this.visible()) this.#renderer.removeClass(offcanvasElement, "showing");
14676
- else this.#completeHide();
14677
- }
14678
- };
14679
14729
  #completeHide() {
14680
- this.#clearHideFallback();
14730
+ this.#hidden.set(true);
14681
14731
  this.#renderer.removeClass(this.#hostElement.nativeElement, "hiding");
14682
- this.#renderer.removeStyle(this.#document.body, "overflow");
14683
- this.#renderer.removeStyle(this.#document.body, "paddingRight");
14732
+ this.#backdropService.unlockScroll(this);
14684
14733
  this.domPortalCleanup();
14685
14734
  }
14686
- #scheduleHideFallback() {
14687
- const style = this.#document.defaultView?.getComputedStyle(this.#hostElement.nativeElement);
14688
- const duration = Number.parseFloat(style?.transitionDuration ?? "") || 0;
14689
- const delay = Number.parseFloat(style?.transitionDelay ?? "") || 0;
14690
- this.#hideFallbackId = setTimeout(() => this.#completeHide(), (duration + delay) * 1e3 + 5);
14691
- }
14692
- #clearHideFallback() {
14693
- clearTimeout(this.#hideFallbackId);
14694
- this.#hideFallbackId = void 0;
14695
- }
14696
14735
  #readPosition() {
14697
14736
  const position = this.#document.defaultView?.getComputedStyle(this.#hostElement.nativeElement).position;
14698
14737
  this.#inPlace.set(!!position && position !== "fixed");
@@ -14720,27 +14759,26 @@ var OffcanvasComponent = class OffcanvasComponent {
14720
14759
  });
14721
14760
  }
14722
14761
  backdropClickSubscribe(subscribe = true) {
14762
+ this.#backdropClickSubscription?.unsubscribe();
14723
14763
  if (subscribe) this.#backdropClickSubscription = this.#backdropService.backdropClick$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe((clicked) => {
14724
14764
  this.#offcanvasService.toggle({
14725
14765
  show: !clicked,
14726
14766
  id: this.id()
14727
14767
  });
14728
14768
  });
14729
- else this.#backdropClickSubscription?.unsubscribe();
14730
14769
  }
14731
14770
  setBackdrop(setBackdrop) {
14732
- this.#activeBackdrop = !!setBackdrop ? this.#backdropService.setBackdrop("offcanvas") : this.#backdropService.clearBackdrop(this.#activeBackdrop);
14733
- setBackdrop === true ? this.backdropClickSubscribe() : this.backdropClickSubscribe(false);
14771
+ if (!setBackdrop) this.#activeBackdrop = this.#backdropService.clearBackdrop(this.#activeBackdrop);
14772
+ else if (!this.#activeBackdrop) this.#activeBackdrop = this.#backdropService.setBackdrop("offcanvas");
14773
+ this.backdropClickSubscribe(setBackdrop === true);
14734
14774
  }
14735
- layoutChangeSubscribe(subscribe = true) {
14736
- if (subscribe) {
14737
- if (!this.responsiveBreakpoint) return;
14738
- const responsiveBreakpoint = `(max-width: ${this.responsiveBreakpoint})`;
14739
- const layoutChanges = this.#breakpointObserver.observe([responsiveBreakpoint]);
14740
- this.#layoutChangeSubscription = layoutChanges.pipe(filter((breakpointState) => !breakpointState.matches), takeUntilDestroyed(this.#destroyRef)).subscribe((breakpointState) => {
14741
- this.visible.set(breakpointState.matches);
14742
- });
14743
- } else this.#layoutChangeSubscription?.unsubscribe();
14775
+ layoutChangeSubscribe(breakpoint) {
14776
+ this.#layoutChangeSubscription?.unsubscribe();
14777
+ if (!breakpoint) return;
14778
+ const layoutChanges = this.#breakpointObserver.observe([`(max-width: ${breakpoint})`]);
14779
+ this.#layoutChangeSubscription = layoutChanges.pipe(filter((breakpointState) => !breakpointState.matches), takeUntilDestroyed(this.#destroyRef)).subscribe((breakpointState) => {
14780
+ this.visible.set(breakpointState.matches);
14781
+ });
14744
14782
  }
14745
14783
  static ɵfac = i0.ɵɵngDeclareFactory({
14746
14784
  minVersion: "12.0.0",
@@ -14843,10 +14881,10 @@ var OffcanvasComponent = class OffcanvasComponent {
14843
14881
  },
14844
14882
  properties: {
14845
14883
  "attr.id": "id()",
14846
- "inert": "ariaHidden()",
14884
+ "inert": "hostInert()",
14847
14885
  "attr.role": "visible() ? role() : null",
14848
14886
  "aria-modal": "visible() ? ariaModal() : null",
14849
- "attr.tabindex": "tabIndex",
14887
+ "attr.tabindex": "ariaHidden() ? null : tabIndex",
14850
14888
  "class": "hostClasses()"
14851
14889
  }
14852
14890
  },
@@ -14856,7 +14894,7 @@ var OffcanvasComponent = class OffcanvasComponent {
14856
14894
  inputs: ["dark", "dark"]
14857
14895
  }],
14858
14896
  ngImport: i0,
14859
- template: "<div [cdkTrapFocus]=\"visible()\">\n <ng-content />\n</div>\n",
14897
+ template: "<div [cdkTrapFocus]=\"visible()\" [inert]=\"ariaHidden()\">\n <ng-content />\n</div>\n",
14860
14898
  styles: [":host{display:none}\n"],
14861
14899
  dependencies: [{
14862
14900
  kind: "ngmodule",
@@ -14887,15 +14925,15 @@ i0.ɵɵngDeclareClassMetadata({
14887
14925
  }],
14888
14926
  host: {
14889
14927
  "[attr.id]": "id()",
14890
- "[inert]": "ariaHidden()",
14928
+ "[inert]": "hostInert()",
14891
14929
  "[attr.role]": "visible() ? role() : null",
14892
14930
  "[aria-modal]": "visible() ? ariaModal() : null",
14893
- "[attr.tabindex]": "tabIndex",
14931
+ "[attr.tabindex]": "ariaHidden() ? null : tabIndex",
14894
14932
  "[class]": "hostClasses()",
14895
14933
  "(document:keydown)": "onKeyDownHandler($event)",
14896
14934
  "(window:resize)": "onResizeHandler()"
14897
14935
  },
14898
- template: "<div [cdkTrapFocus]=\"visible()\">\n <ng-content />\n</div>\n",
14936
+ template: "<div [cdkTrapFocus]=\"visible()\" [inert]=\"ariaHidden()\">\n <ng-content />\n</div>\n",
14899
14937
  styles: [":host{display:none}\n"]
14900
14938
  }]
14901
14939
  }],
@@ -15193,7 +15231,6 @@ var OffcanvasModule = class OffcanvasModule {
15193
15231
  version: "22.2.3",
15194
15232
  ngImport: i0,
15195
15233
  type: OffcanvasModule,
15196
- providers: [OffcanvasService, BackdropService],
15197
15234
  imports: [OffcanvasComponent]
15198
15235
  });
15199
15236
  };
@@ -15218,8 +15255,7 @@ i0.ɵɵngDeclareClassMetadata({
15218
15255
  OffcanvasHeaderComponent,
15219
15256
  OffcanvasTitleDirective,
15220
15257
  OffcanvasToggleDirective
15221
- ],
15222
- providers: [OffcanvasService, BackdropService]
15258
+ ]
15223
15259
  }]
15224
15260
  }]
15225
15261
  });
@@ -15971,10 +16007,11 @@ var PopoverDirective = class PopoverDirective {
15971
16007
  #hostElement = inject(ElementRef);
15972
16008
  #viewContainerRef = inject(ViewContainerRef);
15973
16009
  #listenersService = inject(ListenersService);
15974
- #changeDetectorRef = inject(ChangeDetectorRef);
15975
16010
  #intersectionService = inject(IntersectionService);
15976
16011
  #destroyRef = inject(DestroyRef);
15977
16012
  #document = inject(DOCUMENT);
16013
+ #isServer = isPlatformServer(inject(PLATFORM_ID));
16014
+ #tooltipId = inject(UIDService).getUID("popover");
15978
16015
  #timerId1;
15979
16016
  #timerId2;
15980
16017
  content = input(void 0, {
@@ -16018,13 +16055,16 @@ var PopoverDirective = class PopoverDirective {
16018
16055
  ...ngDevMode ? { debugName: "visible" } : /* istanbul ignore next */ {},
16019
16056
  alias: "cPopoverVisible"
16020
16057
  });
16058
+ #shown = computed(() => !this.#isServer && this.visible() && !!this.content(), ...ngDevMode ? [{ debugName: "#shown" }] : /* istanbul ignore next */ []);
16021
16059
  #visibleEffect = afterRenderEffect({ write: () => {
16022
16060
  this.visible() ? this.addTooltipElement() : this.removeTooltipElement();
16023
16061
  } }, ...ngDevMode ? [{ debugName: "#visibleEffect" }] : /* istanbul ignore next */ []);
16024
16062
  #handleEscapeKey = (event) => {
16025
16063
  if (event.key !== "Escape") return;
16026
- event.preventDefault();
16027
- event.stopPropagation();
16064
+ if (this.#shown()) {
16065
+ event.preventDefault();
16066
+ event.stopPropagation();
16067
+ }
16028
16068
  this.visible.set(false);
16029
16069
  };
16030
16070
  #escapeEffect = effect((onCleanup) => {
@@ -16035,27 +16075,36 @@ var PopoverDirective = class PopoverDirective {
16035
16075
  this.#document.removeEventListener("keydown", this.#handleEscapeKey, useCapture);
16036
16076
  });
16037
16077
  }, ...ngDevMode ? [{ debugName: "#escapeEffect" }] : /* istanbul ignore next */ []);
16078
+ #ariaDescribedByEffect = afterRenderEffect(() => this.#syncAriaDescribedBy(this.#shown()), ...ngDevMode ? [{ debugName: "#ariaDescribedByEffect" }] : /* istanbul ignore next */ []);
16038
16079
  get ariaDescribedBy() {
16039
- return this.tooltipId ? this.tooltipId : null;
16080
+ return this.#shown() ? this.#tooltipId : null;
16040
16081
  }
16041
16082
  tooltip;
16042
- tooltipId;
16043
16083
  tooltipRef;
16044
16084
  popperInstance;
16045
16085
  _popperOptions = { modifiers: [{
16046
16086
  name: "offset",
16047
16087
  options: { offset: [0, 9] }
16048
16088
  }] };
16089
+ ngAfterViewChecked() {
16090
+ this.#syncAriaDescribedBy(this.#shown());
16091
+ }
16049
16092
  ngAfterViewInit() {
16050
16093
  this.intersectionServiceSubscribe();
16051
16094
  }
16052
16095
  ngOnDestroy() {
16053
16096
  this.clearListeners();
16054
16097
  this.destroyTooltipElement();
16098
+ this.#syncAriaDescribedBy(false);
16055
16099
  }
16056
16100
  ngOnInit() {
16057
16101
  this.setListeners();
16058
16102
  }
16103
+ #syncAriaDescribedBy(shown) {
16104
+ const host = this.#hostElement.nativeElement;
16105
+ if (shown) addAriaReferencedId(host, "aria-describedby", this.#tooltipId);
16106
+ else if (getAriaReferenceIds(host, "aria-describedby").includes(this.#tooltipId)) removeAriaReferencedId(host, "aria-describedby", this.#tooltipId);
16107
+ }
16059
16108
  setListeners() {
16060
16109
  const config = {
16061
16110
  hostElement: this.#hostElement,
@@ -16083,23 +16132,20 @@ var PopoverDirective = class PopoverDirective {
16083
16132
  this.visible.set(next.isIntersecting ? this.visible() : false);
16084
16133
  });
16085
16134
  }
16086
- getUID(prefix) {
16087
- let uid = prefix ?? "random-id";
16088
- do
16089
- uid = `${prefix}-${Math.floor(Math.random() * 1e6).toString(10)}`;
16090
- while (this.#document.getElementById(uid));
16091
- return uid;
16092
- }
16093
16135
  createTooltipElement() {
16094
- if (!this.tooltipRef) this.tooltipRef = this.#viewContainerRef.createComponent(PopoverComponent);
16136
+ if (!this.tooltipRef) {
16137
+ this.tooltipRef = this.#viewContainerRef.createComponent(PopoverComponent);
16138
+ this.tooltipRef.setInput("id", this.#tooltipId);
16139
+ }
16095
16140
  }
16096
16141
  destroyTooltipElement() {
16142
+ clearTimeout(this.#timerId1);
16143
+ clearTimeout(this.#timerId2);
16097
16144
  this.tooltip?.remove();
16098
16145
  this.tooltipRef?.destroy();
16099
16146
  this.tooltipRef = void 0;
16100
16147
  this.popperInstance?.destroy();
16101
- this.#viewContainerRef?.detach();
16102
- this.#viewContainerRef?.clear();
16148
+ this.popperInstance = void 0;
16103
16149
  }
16104
16150
  addTooltipElement() {
16105
16151
  if (!this.content()) {
@@ -16115,33 +16161,27 @@ var PopoverDirective = class PopoverDirective {
16115
16161
  this.#viewContainerRef.insert(this.tooltipRef.hostView);
16116
16162
  this.#renderer.appendChild(this.#document.body, this.tooltip);
16117
16163
  this.popperInstance = createPopper(this.referenceRef().nativeElement, this.tooltip, { ...this.popperOptionsComputed() });
16118
- if (!this.visible()) {
16119
- this.removeTooltipElement();
16120
- return;
16121
- }
16122
16164
  clearTimeout(this.#timerId2);
16123
16165
  clearTimeout(this.#timerId1);
16124
16166
  this.#timerId1 = setTimeout(() => {
16125
- this.tooltipId = this.getUID("popover");
16126
- this.tooltipRef?.setInput("id", this.tooltipId);
16127
16167
  this.#renderer.removeClass(this.tooltip, "d-none");
16128
16168
  this.tooltipRef?.setInput("visible", this.visible());
16129
16169
  this.popperInstance?.forceUpdate();
16130
- this.#changeDetectorRef?.markForCheck();
16131
16170
  this.#timerId1 = void 0;
16132
16171
  }, 150);
16133
16172
  }
16134
16173
  removeTooltipElement() {
16135
- this.tooltipId = "";
16174
+ clearTimeout(this.#timerId1);
16136
16175
  if (!this.tooltipRef) return;
16137
16176
  clearTimeout(this.#timerId2);
16138
16177
  this.#timerId2 = setTimeout(() => {
16139
- this.#viewContainerRef?.detach();
16178
+ const index = this.#viewContainerRef.indexOf(this.tooltipRef.hostView);
16179
+ if (index >= 0) this.#viewContainerRef.detach(index);
16180
+ this.popperInstance?.destroy();
16181
+ this.popperInstance = void 0;
16140
16182
  this.#timerId2 = void 0;
16141
16183
  }, 300);
16142
16184
  this.tooltipRef.setInput("visible", false);
16143
- this.tooltipRef.setInput("id", void 0);
16144
- this.#changeDetectorRef.markForCheck();
16145
16185
  }
16146
16186
  static ɵfac = i0.ɵɵngDeclareFactory({
16147
16187
  minVersion: "12.0.0",
@@ -16202,7 +16242,6 @@ var PopoverDirective = class PopoverDirective {
16202
16242
  }
16203
16243
  },
16204
16244
  outputs: { visible: "cPopoverVisibleChange" },
16205
- host: { properties: { "aria-describedby": "ariaDescribedBy" } },
16206
16245
  providers: [ListenersService, IntersectionService],
16207
16246
  exportAs: ["cPopover"],
16208
16247
  ngImport: i0
@@ -16218,8 +16257,7 @@ i0.ɵɵngDeclareClassMetadata({
16218
16257
  args: [{
16219
16258
  selector: "[cPopover]",
16220
16259
  exportAs: "cPopover",
16221
- providers: [ListenersService, IntersectionService],
16222
- host: { "[aria-describedby]": "ariaDescribedBy" }
16260
+ providers: [ListenersService, IntersectionService]
16223
16261
  }]
16224
16262
  }],
16225
16263
  propDecorators: {
@@ -22299,10 +22337,11 @@ var TooltipDirective = class TooltipDirective {
22299
22337
  #hostElement = inject(ElementRef);
22300
22338
  #viewContainerRef = inject(ViewContainerRef);
22301
22339
  #listenersService = inject(ListenersService);
22302
- #changeDetectorRef = inject(ChangeDetectorRef);
22303
22340
  #intersectionService = inject(IntersectionService);
22304
22341
  #destroyRef = inject(DestroyRef);
22305
22342
  #document = inject(DOCUMENT);
22343
+ #isServer = isPlatformServer(inject(PLATFORM_ID));
22344
+ #tooltipId = inject(UIDService).getUID("tooltip");
22306
22345
  #timerId1;
22307
22346
  #timerId2;
22308
22347
  content = input(void 0, {
@@ -22346,13 +22385,16 @@ var TooltipDirective = class TooltipDirective {
22346
22385
  ...ngDevMode ? { debugName: "visible" } : /* istanbul ignore next */ {},
22347
22386
  alias: "cTooltipVisible"
22348
22387
  });
22388
+ #shown = computed(() => !this.#isServer && this.visible() && !!this.content(), ...ngDevMode ? [{ debugName: "#shown" }] : /* istanbul ignore next */ []);
22349
22389
  #visibleEffect = afterRenderEffect({ write: () => {
22350
22390
  this.visible() ? this.addTooltipElement() : this.removeTooltipElement();
22351
22391
  } }, ...ngDevMode ? [{ debugName: "#visibleEffect" }] : /* istanbul ignore next */ []);
22352
22392
  #handleEscapeKey = (event) => {
22353
22393
  if (event.key !== "Escape") return;
22354
- event.preventDefault();
22355
- event.stopPropagation();
22394
+ if (this.#shown()) {
22395
+ event.preventDefault();
22396
+ event.stopPropagation();
22397
+ }
22356
22398
  this.visible.set(false);
22357
22399
  };
22358
22400
  #escapeEffect = effect((onCleanup) => {
@@ -22361,27 +22403,36 @@ var TooltipDirective = class TooltipDirective {
22361
22403
  this.#document.addEventListener("keydown", this.#handleEscapeKey, useCapture);
22362
22404
  onCleanup(() => this.#document.removeEventListener("keydown", this.#handleEscapeKey, useCapture));
22363
22405
  }, ...ngDevMode ? [{ debugName: "#escapeEffect" }] : /* istanbul ignore next */ []);
22406
+ #ariaDescribedByEffect = afterRenderEffect(() => this.#syncAriaDescribedBy(this.#shown()), ...ngDevMode ? [{ debugName: "#ariaDescribedByEffect" }] : /* istanbul ignore next */ []);
22364
22407
  get ariaDescribedBy() {
22365
- return this.tooltipId ? this.tooltipId : null;
22408
+ return this.#shown() ? this.#tooltipId : null;
22366
22409
  }
22367
22410
  tooltip;
22368
- tooltipId;
22369
22411
  tooltipRef;
22370
22412
  popperInstance;
22371
22413
  _popperOptions = { modifiers: [{
22372
22414
  name: "offset",
22373
22415
  options: { offset: [0, 5] }
22374
22416
  }] };
22417
+ ngAfterViewChecked() {
22418
+ this.#syncAriaDescribedBy(this.#shown());
22419
+ }
22375
22420
  ngAfterViewInit() {
22376
22421
  this.intersectionServiceSubscribe();
22377
22422
  }
22378
22423
  ngOnDestroy() {
22379
22424
  this.clearListeners();
22380
22425
  this.destroyTooltipElement();
22426
+ this.#syncAriaDescribedBy(false);
22381
22427
  }
22382
22428
  ngOnInit() {
22383
22429
  this.setListeners();
22384
22430
  }
22431
+ #syncAriaDescribedBy(shown) {
22432
+ const host = this.#hostElement.nativeElement;
22433
+ if (shown) addAriaReferencedId(host, "aria-describedby", this.#tooltipId);
22434
+ else if (getAriaReferenceIds(host, "aria-describedby").includes(this.#tooltipId)) removeAriaReferencedId(host, "aria-describedby", this.#tooltipId);
22435
+ }
22385
22436
  setListeners() {
22386
22437
  const config = {
22387
22438
  hostElement: this.#hostElement,
@@ -22409,23 +22460,20 @@ var TooltipDirective = class TooltipDirective {
22409
22460
  this.visible.set(next.isIntersecting ? this.visible() : false);
22410
22461
  });
22411
22462
  }
22412
- getUID(prefix) {
22413
- let uid = prefix ?? "random-id";
22414
- do
22415
- uid = `${prefix}-${Math.floor(Math.random() * 1e6).toString(10)}`;
22416
- while (this.#document.getElementById(uid));
22417
- return uid;
22418
- }
22419
22463
  createTooltipElement() {
22420
- if (!this.tooltipRef) this.tooltipRef = this.#viewContainerRef.createComponent(TooltipComponent);
22464
+ if (!this.tooltipRef) {
22465
+ this.tooltipRef = this.#viewContainerRef.createComponent(TooltipComponent);
22466
+ this.tooltipRef.setInput("id", this.#tooltipId);
22467
+ }
22421
22468
  }
22422
22469
  destroyTooltipElement() {
22470
+ clearTimeout(this.#timerId1);
22471
+ clearTimeout(this.#timerId2);
22423
22472
  this.tooltip?.remove();
22424
22473
  this.tooltipRef?.destroy();
22425
22474
  this.tooltipRef = void 0;
22426
22475
  this.popperInstance?.destroy();
22427
- this.#viewContainerRef?.detach();
22428
- this.#viewContainerRef?.clear();
22476
+ this.popperInstance = void 0;
22429
22477
  }
22430
22478
  addTooltipElement() {
22431
22479
  if (!this.content()) {
@@ -22441,33 +22489,27 @@ var TooltipDirective = class TooltipDirective {
22441
22489
  this.#viewContainerRef.insert(this.tooltipRef.hostView);
22442
22490
  this.#renderer.appendChild(this.#document.body, this.tooltip);
22443
22491
  this.popperInstance = createPopper(this.referenceRef().nativeElement, this.tooltip, { ...this.popperOptionsComputed() });
22444
- if (!this.visible()) {
22445
- this.removeTooltipElement();
22446
- return;
22447
- }
22448
22492
  clearTimeout(this.#timerId2);
22449
22493
  clearTimeout(this.#timerId1);
22450
22494
  this.#timerId1 = setTimeout(() => {
22451
- this.tooltipId = this.getUID("tooltip");
22452
- this.tooltipRef?.setInput("id", this.tooltipId);
22453
22495
  this.#renderer.removeClass(this.tooltip, "d-none");
22454
22496
  this.tooltipRef?.setInput("visible", this.visible());
22455
22497
  this.popperInstance?.forceUpdate();
22456
- this.#changeDetectorRef?.markForCheck();
22457
22498
  this.#timerId1 = void 0;
22458
22499
  }, 150);
22459
22500
  }
22460
22501
  removeTooltipElement() {
22461
- this.tooltipId = "";
22502
+ clearTimeout(this.#timerId1);
22462
22503
  if (!this.tooltipRef) return;
22463
22504
  clearTimeout(this.#timerId2);
22464
22505
  this.#timerId2 = setTimeout(() => {
22465
- this.#viewContainerRef?.detach();
22506
+ const index = this.#viewContainerRef.indexOf(this.tooltipRef.hostView);
22507
+ if (index >= 0) this.#viewContainerRef.detach(index);
22508
+ this.popperInstance?.destroy();
22509
+ this.popperInstance = void 0;
22466
22510
  this.#timerId2 = void 0;
22467
22511
  }, 300);
22468
22512
  this.tooltipRef.setInput("visible", false);
22469
- this.tooltipRef.setInput("id", void 0);
22470
- this.#changeDetectorRef.markForCheck();
22471
22513
  }
22472
22514
  static ɵfac = i0.ɵɵngDeclareFactory({
22473
22515
  minVersion: "12.0.0",
@@ -22528,7 +22570,6 @@ var TooltipDirective = class TooltipDirective {
22528
22570
  }
22529
22571
  },
22530
22572
  outputs: { visible: "cTooltipVisibleChange" },
22531
- host: { properties: { "aria-describedby": "ariaDescribedBy" } },
22532
22573
  providers: [ListenersService, IntersectionService],
22533
22574
  exportAs: ["cTooltip"],
22534
22575
  ngImport: i0
@@ -22544,8 +22585,7 @@ i0.ɵɵngDeclareClassMetadata({
22544
22585
  args: [{
22545
22586
  selector: "[cTooltip]",
22546
22587
  exportAs: "cTooltip",
22547
- providers: [ListenersService, IntersectionService],
22548
- host: { "[aria-describedby]": "ariaDescribedBy" }
22588
+ providers: [ListenersService, IntersectionService]
22549
22589
  }]
22550
22590
  }],
22551
22591
  propDecorators: {
@@ -23011,7 +23051,7 @@ var WidgetStatCComponent = class WidgetStatCComponent extends CardComponent {
23011
23051
  exportAs: ["cWidgetStatC"],
23012
23052
  usesInheritance: true,
23013
23053
  ngImport: i0,
23014
- template: "@let _templates = templates();\n<c-card-body>\n @if (icon() || _templates?.['widgetIconTemplate']) {\n <div [class]=\"iconClasses()\">\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate\" />\n </div>\n }\n @if (!!value()) {\n <div [class]=\"valueClasses()\">\n {{ value() }}\n </div>\n }\n @if (!!title()) {\n <div [class]=\"titleClasses()\">\n {{ title() }}\n </div>\n }\n @if (_templates?.['widgetProgressTemplate']) {\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetProgressTemplate'] || defaultWidgetProgressTemplate\" />\n }\n</c-card-body>\n\n<ng-template #defaultWidgetIconTemplate>\n {{ icon() }}\n</ng-template>\n\n<ng-template #defaultWidgetProgressTemplate>\n <ng-content />\n</ng-template>\n",
23054
+ template: "@let _templates = templates();\n<c-card-body>\n @if (icon() || _templates?.['widgetIconTemplate']) {\n <div [class]=\"iconClasses()\">\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate\" />\n </div>\n }\n @if (!!value()) {\n <div [class]=\"valueClasses()\">\n {{ value() }}\n </div>\n }\n @if (!!title()) {\n <div [class]=\"titleClasses()\">\n {{ title() }}\n </div>\n }\n @if (_templates?.['widgetProgressTemplate']) {\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetProgressTemplate']\" />\n }\n</c-card-body>\n\n<ng-template #defaultWidgetIconTemplate>\n {{ icon() }}\n</ng-template>\n",
23015
23055
  dependencies: [{
23016
23056
  kind: "component",
23017
23057
  type: CardBodyComponent,
@@ -23040,7 +23080,7 @@ i0.ɵɵngDeclareClassMetadata({
23040
23080
  exportAs: "cWidgetStatC",
23041
23081
  imports: [CardBodyComponent, NgTemplateOutlet],
23042
23082
  host: { "[class]": "hostExtendedClass()" },
23043
- template: "@let _templates = templates();\n<c-card-body>\n @if (icon() || _templates?.['widgetIconTemplate']) {\n <div [class]=\"iconClasses()\">\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate\" />\n </div>\n }\n @if (!!value()) {\n <div [class]=\"valueClasses()\">\n {{ value() }}\n </div>\n }\n @if (!!title()) {\n <div [class]=\"titleClasses()\">\n {{ title() }}\n </div>\n }\n @if (_templates?.['widgetProgressTemplate']) {\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetProgressTemplate'] || defaultWidgetProgressTemplate\" />\n }\n</c-card-body>\n\n<ng-template #defaultWidgetIconTemplate>\n {{ icon() }}\n</ng-template>\n\n<ng-template #defaultWidgetProgressTemplate>\n <ng-content />\n</ng-template>\n"
23083
+ template: "@let _templates = templates();\n<c-card-body>\n @if (icon() || _templates?.['widgetIconTemplate']) {\n <div [class]=\"iconClasses()\">\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate\" />\n </div>\n }\n @if (!!value()) {\n <div [class]=\"valueClasses()\">\n {{ value() }}\n </div>\n }\n @if (!!title()) {\n <div [class]=\"titleClasses()\">\n {{ title() }}\n </div>\n }\n @if (_templates?.['widgetProgressTemplate']) {\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetProgressTemplate']\" />\n }\n</c-card-body>\n\n<ng-template #defaultWidgetIconTemplate>\n {{ icon() }}\n</ng-template>\n"
23044
23084
  }]
23045
23085
  }],
23046
23086
  ctorParameters: () => [],
@@ -23392,7 +23432,7 @@ var WidgetStatFComponent = class WidgetStatFComponent extends CardComponent {
23392
23432
  descendants: true,
23393
23433
  isSignal: true
23394
23434
  }],
23395
- exportAs: ["cWidgetStatB"],
23435
+ exportAs: ["cWidgetStatF", "cWidgetStatB"],
23396
23436
  usesInheritance: true,
23397
23437
  ngImport: i0,
23398
23438
  template: "@let _templates = templates();\n<ng-container>\n <c-card-body [class]=\"cardBodyClasses()\">\n <div [class]=\"iconClasses()\">\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate\" />\n </div>\n <div>\n <div [class]=\"valueClasses()\">{{ value() }}</div>\n <div [class]=\"titleClasses()\">{{ title() }}</div>\n </div>\n </c-card-body>\n @if (footer() || _templates?.['widgetFooterTemplate']) {\n <c-card-footer>\n <ng-container *ngTemplateOutlet=\"_templates?.['widgetFooterTemplate'] || defaultFooterIconTemplate\" />\n </c-card-footer>\n }\n</ng-container>\n\n<ng-template #defaultWidgetIconTemplate>\n <span>{{ icon() }}</span>\n</ng-template>\n\n<ng-template #defaultFooterIconTemplate>\n <span>{{ footer() }}</span>\n</ng-template>\n",
@@ -23429,7 +23469,7 @@ i0.ɵɵngDeclareClassMetadata({
23429
23469
  type: Component,
23430
23470
  args: [{
23431
23471
  selector: "c-widget-stat-f",
23432
- exportAs: "cWidgetStatB",
23472
+ exportAs: "cWidgetStatF, cWidgetStatB",
23433
23473
  imports: [
23434
23474
  CardBodyComponent,
23435
23475
  CardFooterComponent,