@villedemontreal/angular-ui 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { SecurityContext, Injectable, Inject, Component, ViewEncapsulation, ChangeDetectionStrategy, Attribute, Input, NgModule, Directive, EventEmitter, Output, CUSTOM_ELEMENTS_SCHEMA, ViewChild, forwardRef, InjectionToken, ContentChildren, Optional, HostListener, ContentChild } from '@angular/core';
2
+ import { SecurityContext, Injectable, Inject, Component, ViewEncapsulation, ChangeDetectionStrategy, Input, NgModule, Directive, EventEmitter, Output, CUSTOM_ELEMENTS_SCHEMA, ViewChild, forwardRef, InjectionToken, ContentChildren, Optional, HostListener, ContentChild, Injector, TemplateRef, SkipSelf } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { DOCUMENT, CommonModule } from '@angular/common';
5
5
  import * as i1 from '@angular/platform-browser';
@@ -9,6 +9,16 @@ import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/fo
9
9
  import * as i1$3 from '@angular/cdk/a11y';
10
10
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
11
11
  import * as i2 from '@angular/cdk/collections';
12
+ import * as i1$4 from '@angular/cdk/overlay';
13
+ import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
14
+ import * as i3 from '@angular/cdk/portal';
15
+ import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, TemplatePortal, PortalModule } from '@angular/cdk/portal';
16
+ import { Subject, filter, take, defer, startWith, Subscription } from 'rxjs';
17
+ import { __awaiter } from 'tslib';
18
+ import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform';
19
+ import { trigger, state, style, transition, group, animate, query, animateChild } from '@angular/animations';
20
+ import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
21
+ import { ANIMATION_MODULE_TYPE, BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
12
22
 
13
23
  function baoColorToHex(baoColor) {
14
24
  switch (baoColor) {
@@ -215,7 +225,7 @@ const TITLE = 'title';
215
225
  * `<bao-icon svgIcon="heart"></bao-icon>`
216
226
  */
217
227
  class BaoIconComponent {
218
- constructor(elementRef, iconRegistry, renderer, ariaHidden) {
228
+ constructor(elementRef, iconRegistry, renderer) {
219
229
  this.elementRef = elementRef;
220
230
  this.iconRegistry = iconRegistry;
221
231
  this.renderer = renderer;
@@ -223,11 +233,6 @@ class BaoIconComponent {
223
233
  * The size of the icon
224
234
  */
225
235
  this.size = 'x-small';
226
- // If the user has not explicitly set aria-hidden, mark the icon as hidden, as this is
227
- // the right thing to do for the majority of icon use-cases.
228
- if (!ariaHidden) {
229
- this.elementRef.nativeElement.setAttribute('aria-hidden', 'true');
230
- }
231
236
  this._titleId = '';
232
237
  this._title = '';
233
238
  this._svgIcon = '';
@@ -308,6 +313,9 @@ class BaoIconComponent {
308
313
  if (title) {
309
314
  svg = this.addTitleToSVG(svg, title);
310
315
  }
316
+ if (!title) {
317
+ svg.setAttribute('aria-hidden', 'true');
318
+ }
311
319
  this.setSvgElement(svg);
312
320
  }
313
321
  }
@@ -317,16 +325,19 @@ class BaoIconComponent {
317
325
  const titleText = this.renderer.createText(title);
318
326
  this.renderer.appendChild(titleNode, titleText);
319
327
  this.renderer.appendChild(svg, titleNode);
328
+ svg.setAttribute('aria-labelledby', this._titleId);
320
329
  return svg;
321
330
  }
322
331
  generateUniqueTitleId() {
323
332
  return this.title
324
- ? `${this.title}-${Math.random() * 10000000000000000}`
333
+ ? `${this.title
334
+ .replace(/[^A-Z0-9]+/gi, '')
335
+ .toLocaleLowerCase()}-${Math.floor(Math.random() * 10000000000000000)}`
325
336
  : '';
326
337
  }
327
338
  }
328
- BaoIconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoIconComponent, deps: [{ token: i0.ElementRef }, { token: BaoIconDictionary }, { token: i0.Renderer2 }, { token: 'aria-hidden', attribute: true }], target: i0.ɵɵFactoryTarget.Component });
329
- BaoIconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.1", type: BaoIconComponent, selector: "bao-icon", inputs: { color: "color", size: "size", svgIcon: "svgIcon", title: "title" }, host: { attributes: { "role": "img" }, properties: { "class.bao-icon": "true", "class.notranslate": "true", "class.bao-icon-medium": "size === \"medium\"", "class.bao-icon-small": "size === \"small\"", "class.bao-icon-x-small": "size === \"x-small\"", "class.bao-icon-xx-small": "size === \"xx-small\"", "attr.data-bao-icon-type": "\"svg\"", "attr.aria-labelledby": "titleId", "attr.aria-hidden": "!title", "style.color": "hexColor" } }, exportAs: ["baoIcon"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["bao-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;line-height:normal}bao-icon.bao-icon-medium{height:2.5rem;width:2.5rem}bao-icon.bao-icon-small{height:2rem;width:2rem;line-height:1.75rem}bao-icon.bao-icon-x-small{height:1.5rem;width:1.5rem;line-height:.5rem}bao-icon.bao-icon-xx-small{height:1rem;width:1rem;line-height:.85rem}bao-icon.bao-icon-spinner{animation:spin .75s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
339
+ BaoIconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoIconComponent, deps: [{ token: i0.ElementRef }, { token: BaoIconDictionary }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
340
+ BaoIconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.1", type: BaoIconComponent, selector: "bao-icon", inputs: { color: "color", size: "size", svgIcon: "svgIcon", title: "title" }, host: { attributes: { "role": "img" }, properties: { "class.bao-icon": "true", "class.notranslate": "true", "class.bao-icon-medium": "size === \"medium\"", "class.bao-icon-small": "size === \"small\"", "class.bao-icon-x-small": "size === \"x-small\"", "class.bao-icon-xx-small": "size === \"xx-small\"", "attr.data-bao-icon-type": "\"svg\"", "style.color": "hexColor" } }, exportAs: ["baoIcon"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["bao-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;line-height:normal}bao-icon svg{height:100%;width:100%}bao-icon.bao-icon-medium{height:2.5rem;width:2.5rem}bao-icon.bao-icon-small{height:2rem;width:2rem;line-height:1.75rem}bao-icon.bao-icon-x-small{height:1.5rem;width:1.5rem;line-height:.5rem}bao-icon.bao-icon-xx-small{height:1rem;width:1rem;line-height:.85rem}bao-icon.bao-icon-spinner{animation:spin .75s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
330
341
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoIconComponent, decorators: [{
331
342
  type: Component,
332
343
  args: [{ template: '<ng-content></ng-content>', selector: 'bao-icon', exportAs: 'baoIcon', host: {
@@ -339,16 +350,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImpor
339
350
  '[class.bao-icon-x-small]': 'size === "x-small"',
340
351
  '[class.bao-icon-xx-small]': 'size === "xx-small"',
341
352
  '[attr.data-bao-icon-type]': '"svg"',
342
- '[attr.aria-labelledby]': 'titleId',
343
- '[attr.aria-hidden]': '!title',
344
353
  '[style.color]': 'hexColor'
345
- }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["bao-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;line-height:normal}bao-icon.bao-icon-medium{height:2.5rem;width:2.5rem}bao-icon.bao-icon-small{height:2rem;width:2rem;line-height:1.75rem}bao-icon.bao-icon-x-small{height:1.5rem;width:1.5rem;line-height:.5rem}bao-icon.bao-icon-xx-small{height:1rem;width:1rem;line-height:.85rem}bao-icon.bao-icon-spinner{animation:spin .75s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
346
- }], ctorParameters: function () {
347
- return [{ type: i0.ElementRef }, { type: BaoIconDictionary }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
348
- type: Attribute,
349
- args: ['aria-hidden']
350
- }] }];
351
- }, propDecorators: { color: [{
354
+ }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["bao-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;line-height:normal}bao-icon svg{height:100%;width:100%}bao-icon.bao-icon-medium{height:2.5rem;width:2.5rem}bao-icon.bao-icon-small{height:2rem;width:2rem;line-height:1.75rem}bao-icon.bao-icon-x-small{height:1.5rem;width:1.5rem;line-height:.5rem}bao-icon.bao-icon-xx-small{height:1rem;width:1rem;line-height:.85rem}bao-icon.bao-icon-spinner{animation:spin .75s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
355
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: BaoIconDictionary }, { type: i0.Renderer2 }]; }, propDecorators: { color: [{
352
356
  type: Input
353
357
  }], size: [{
354
358
  type: Input
@@ -2936,6 +2940,942 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImpor
2936
2940
  * See LICENSE file in the project root for full license information.
2937
2941
  */
2938
2942
 
2943
+ /*
2944
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
2945
+ * Licensed under the MIT license.
2946
+ * See LICENSE file in the project root for full license information.
2947
+ */
2948
+ /**
2949
+ * Animations used by MatDialog.
2950
+ * @docs-private
2951
+ */
2952
+ const baoModalAnimations = {
2953
+ /** Animation that is applied on the modal container by default. */
2954
+ modalContainer: trigger('modalContainer', [
2955
+ // Note: The `enter` animation transitions to `transform: none`, because for some reason
2956
+ // specifying the transform explicitly, causes IE both to blur the modal content and
2957
+ // decimate the animation performance. Leaving it as `none` solves both issues.
2958
+ state('void, exit', style({ opacity: 0, transform: 'scale(0.7)' })),
2959
+ state('enter', style({ transform: 'none' })),
2960
+ transition('* => enter', group([
2961
+ animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({ transform: 'none', opacity: 1 })),
2962
+ query('@*', animateChild(), { optional: true })
2963
+ ])),
2964
+ transition('* => void, * => exit', group([
2965
+ animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 })),
2966
+ query('@*', animateChild(), { optional: true })
2967
+ ]))
2968
+ ])
2969
+ };
2970
+
2971
+ /*
2972
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
2973
+ * Licensed under the MIT license.
2974
+ * See LICENSE file in the project root for full license information.
2975
+ */
2976
+ var eModalDesktopWidthSize;
2977
+ (function (eModalDesktopWidthSize) {
2978
+ eModalDesktopWidthSize["SMALL"] = "bao-modal-sm";
2979
+ eModalDesktopWidthSize["MEDIUM"] = "bao-modal-md";
2980
+ eModalDesktopWidthSize["LARGE"] = "bao-modal-lg"; // Full width minus 32px (global margin : left and rigth)
2981
+ })(eModalDesktopWidthSize || (eModalDesktopWidthSize = {}));
2982
+ var eModalMobileWidthSize;
2983
+ (function (eModalMobileWidthSize) {
2984
+ eModalMobileWidthSize["FULL"] = "bao-modal-mobil-full";
2985
+ eModalMobileWidthSize["COMPACT"] = "bao-modal-mobil-compact"; // 300px
2986
+ })(eModalMobileWidthSize || (eModalMobileWidthSize = {}));
2987
+ /**
2988
+ * Configuration for opening a modal dialog with the BaoModal service.
2989
+ */
2990
+ class BaoModalInitialConfig {
2991
+ constructor() {
2992
+ /** The ARIA role of the dialog element. */
2993
+ this.role = 'dialog';
2994
+ /** Custom class for the overlay pane. */
2995
+ this.panelClass = '';
2996
+ /** Whether the dialog has a backdrop. */
2997
+ this.hasBackdrop = true;
2998
+ /** Custom class for the backdrop. */
2999
+ this.backdropClass = '';
3000
+ /** Whether the user can use escape or clicking on the backdrop to close the modal. */
3001
+ this.disableClose = false;
3002
+ /** Width of the dialog. */
3003
+ this.width = '';
3004
+ /** Height of the dialog. */
3005
+ this.height = '';
3006
+ /** Max-width of the dialog. If a number is provided, assumes pixel units. Defaults to 80vw. */
3007
+ this.maxWidth = '80vw';
3008
+ /** Data being injected into the child component. */
3009
+ this.data = null;
3010
+ /** ID of the element that describes the dialog. */
3011
+ this.ariaDescribedBy = null;
3012
+ /** ID of the element that labels the dialog. */
3013
+ this.ariaLabelledBy = null;
3014
+ /** Aria label to assign to the dialog element. */
3015
+ this.ariaLabel = null;
3016
+ /**
3017
+ * Where the dialog should focus on open.
3018
+ */
3019
+ this.autoFocus = 'first-tabbable';
3020
+ /**
3021
+ * Whether the dialog should restore focus to the
3022
+ * previously-focused element, after it's closed.
3023
+ */
3024
+ this.restoreFocus = true;
3025
+ /** Whether to wait for the opening animation to finish before trapping focus. */
3026
+ this.delayFocusTrap = true;
3027
+ /**
3028
+ * Whether the dialog should close when the user goes backwards/forwards in history.
3029
+ * Note that this usually doesn't include clicking on links (unless the user is using
3030
+ * the `HashLocationStrategy`).
3031
+ */
3032
+ this.closeOnNavigation = true;
3033
+ }
3034
+ }
3035
+
3036
+ /**
3037
+ * Throws an exception for the case when a ComponentPortal is
3038
+ * attached to a DomPortalOutlet without an origin.
3039
+ * @docs-private
3040
+ */
3041
+ function throwBaoModalContentAlreadyAttachedError() {
3042
+ throw Error('Attempting to attach modal content after content is already attached');
3043
+ }
3044
+ /**
3045
+ * Base class for the `BaoModalContainer`. The base class does not implement
3046
+ * animations as these are left to implementers of the modal container.
3047
+ */
3048
+ class _BaoModalContainerBase extends BasePortalOutlet {
3049
+ constructor(_elementRef, _focusTrapFactory, _changeDetectorRef, _document,
3050
+ /** The modal configuration. */
3051
+ _config, _interactivityChecker, _ngZone, _focusMonitor) {
3052
+ super();
3053
+ this._elementRef = _elementRef;
3054
+ this._focusTrapFactory = _focusTrapFactory;
3055
+ this._changeDetectorRef = _changeDetectorRef;
3056
+ this._config = _config;
3057
+ this._interactivityChecker = _interactivityChecker;
3058
+ this._ngZone = _ngZone;
3059
+ this._focusMonitor = _focusMonitor;
3060
+ /** Emits when an animation state changes. */
3061
+ this._animationStateChanged = new EventEmitter();
3062
+ /**
3063
+ * Type of interaction that led to the modal being closed. This is used to determine
3064
+ * whether the focus style will be applied when returning focus to its original location
3065
+ * after the modal is closed.
3066
+ */
3067
+ this._closeInteractionType = null;
3068
+ /** Element that was focused before the modal was opened. Save this to restore upon close. */
3069
+ this._elementFocusedBeforeDialogWasOpened = null;
3070
+ this._ariaLabelledBy = _config.ariaLabelledBy || null;
3071
+ this._document = _document;
3072
+ }
3073
+ /** Initializes the modal container with the attached content. */
3074
+ _initializeWithAttachedContent() {
3075
+ this._setupFocusTrap();
3076
+ // Save the previously focused element. This element will be re-focused
3077
+ // when the modal closes.
3078
+ this._capturePreviouslyFocusedElement();
3079
+ }
3080
+ /**
3081
+ * Attach a ComponentPortal as content to this modal container.
3082
+ */
3083
+ attachComponentPortal(portal) {
3084
+ return this._portalOutlet.attachComponentPortal(portal);
3085
+ }
3086
+ /**
3087
+ * Attach a TemplatePortal as content to this modal container.
3088
+ */
3089
+ attachTemplatePortal(portal) {
3090
+ return this._portalOutlet.attachTemplatePortal(portal);
3091
+ }
3092
+ /** Moves focus back into the modal if it was moved out. */
3093
+ _recaptureFocus() {
3094
+ return __awaiter(this, void 0, void 0, function* () {
3095
+ if (!this._containsFocus()) {
3096
+ yield this._trapFocus();
3097
+ }
3098
+ });
3099
+ }
3100
+ /**
3101
+ * Moves the focus inside the focus trap. When autoFocus is not set to 'modal', if focus
3102
+ * cannot be moved then focus will go to the modal container.
3103
+ */
3104
+ _trapFocus() {
3105
+ return __awaiter(this, void 0, void 0, function* () {
3106
+ const element = this._elementRef.nativeElement;
3107
+ // If were to attempt to focus immediately, then the content of the modal would not yet be
3108
+ // ready in instances where change detection has to run first. To deal with this, we simply
3109
+ // wait for the microtask queue to be empty when setting focus when autoFocus isn't set to
3110
+ // modal. If the element inside the modal can't be focused, then the container is focused
3111
+ // so the user can't tab into other elements behind it.
3112
+ switch (this._config.autoFocus) {
3113
+ case 'modal':
3114
+ // Ensure that focus is on the modal container. It's possible that a different
3115
+ // component tried to move focus while the open animation was running. See:
3116
+ // https://github.com/angular/components/issues/16215. Note that we only want to do this
3117
+ // if the focus isn't inside the modal already, because it's possible that the consumer
3118
+ // turned off `autoFocus` in order to move focus themselves.
3119
+ if (!this._containsFocus()) {
3120
+ element.focus();
3121
+ }
3122
+ break;
3123
+ case 'first-tabbable':
3124
+ // If we weren't able to find a focusable element in the modal, then focus the modal
3125
+ // container instead.
3126
+ const focusedSuccessfully = yield this._focusTrap.focusInitialElementWhenReady();
3127
+ if (!focusedSuccessfully) {
3128
+ this._focusDialogContainer();
3129
+ }
3130
+ break;
3131
+ case 'first-heading':
3132
+ this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role="heading"]');
3133
+ break;
3134
+ default:
3135
+ this._focusByCssSelector(this._config.autoFocus);
3136
+ break;
3137
+ }
3138
+ });
3139
+ }
3140
+ /** Restores focus to the element that was focused before the modal opened. */
3141
+ _restoreFocus() {
3142
+ const previousElement = this._elementFocusedBeforeDialogWasOpened;
3143
+ // We need the extra check, because IE can set the `activeElement` to null in some cases.
3144
+ if (this._config.restoreFocus &&
3145
+ previousElement &&
3146
+ typeof previousElement.focus === 'function') {
3147
+ const activeElement = _getFocusedElementPierceShadowDom();
3148
+ const element = this._elementRef.nativeElement;
3149
+ // Make sure that focus is still inside the modal or is on the body (usually because a
3150
+ // non-focusable element like the backdrop was clicked) before moving it. It's possible that
3151
+ // the consumer moved it themselves before the animation was done, in which case we shouldn't
3152
+ // do anything.
3153
+ if (!activeElement ||
3154
+ activeElement === this._document.body ||
3155
+ activeElement === element ||
3156
+ element.contains(activeElement)) {
3157
+ if (this._focusMonitor) {
3158
+ this._focusMonitor.focusVia(previousElement, this._closeInteractionType);
3159
+ this._closeInteractionType = null;
3160
+ }
3161
+ else {
3162
+ previousElement.focus();
3163
+ }
3164
+ }
3165
+ }
3166
+ if (this._focusTrap) {
3167
+ this._focusTrap.destroy();
3168
+ }
3169
+ }
3170
+ /**
3171
+ * Focuses the provided element. If the element is not focusable, it will add a tabIndex
3172
+ * attribute to forcefully focus it. The attribute is removed after focus is moved.
3173
+ */
3174
+ _forceFocus(element, options) {
3175
+ if (!this._interactivityChecker.isFocusable(element)) {
3176
+ element.tabIndex = -1;
3177
+ // The tabindex attribute should be removed to avoid navigating to that element again
3178
+ this._ngZone.runOutsideAngular(() => {
3179
+ element.addEventListener('blur', () => element.removeAttribute('tabindex'));
3180
+ element.addEventListener('mousedown', () => element.removeAttribute('tabindex'));
3181
+ });
3182
+ }
3183
+ element.focus(options);
3184
+ }
3185
+ /**
3186
+ * Focuses the first element that matches the given selector within the focus trap.
3187
+ */
3188
+ _focusByCssSelector(selector, options) {
3189
+ const elementToFocus = this._elementRef.nativeElement.querySelector(selector);
3190
+ if (elementToFocus) {
3191
+ this._forceFocus(elementToFocus, options);
3192
+ }
3193
+ }
3194
+ /** Sets up the focus trap. */
3195
+ _setupFocusTrap() {
3196
+ this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
3197
+ }
3198
+ /** Captures the element that was focused before the modal was opened. */
3199
+ _capturePreviouslyFocusedElement() {
3200
+ if (this._document) {
3201
+ this._elementFocusedBeforeDialogWasOpened =
3202
+ _getFocusedElementPierceShadowDom();
3203
+ }
3204
+ }
3205
+ /** Focuses the modal container. */
3206
+ _focusDialogContainer() {
3207
+ // Note that there is no focus method when rendering on the server.
3208
+ if (this._elementRef.nativeElement.focus) {
3209
+ this._elementRef.nativeElement.focus();
3210
+ }
3211
+ }
3212
+ /** Returns whether focus is inside the modal. */
3213
+ _containsFocus() {
3214
+ const element = this._elementRef.nativeElement;
3215
+ const activeElement = _getFocusedElementPierceShadowDom();
3216
+ return element === activeElement || element.contains(activeElement);
3217
+ }
3218
+ }
3219
+ _BaoModalContainerBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: _BaoModalContainerBase, deps: [{ token: i0.ElementRef }, { token: i1$3.ConfigurableFocusTrapFactory }, { token: i0.ChangeDetectorRef }, { token: DOCUMENT, optional: true }, { token: BaoModalInitialConfig }, { token: i1$3.InteractivityChecker }, { token: i0.NgZone }, { token: i1$3.FocusMonitor }], target: i0.ɵɵFactoryTarget.Directive });
3220
+ _BaoModalContainerBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.1.1", type: _BaoModalContainerBase, viewQueries: [{ propertyName: "_portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 });
3221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: _BaoModalContainerBase, decorators: [{
3222
+ type: Directive
3223
+ }], ctorParameters: function () {
3224
+ return [{ type: i0.ElementRef }, { type: i1$3.ConfigurableFocusTrapFactory }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
3225
+ type: Optional
3226
+ }, {
3227
+ type: Inject,
3228
+ args: [DOCUMENT]
3229
+ }] }, { type: BaoModalInitialConfig }, { type: i1$3.InteractivityChecker }, { type: i0.NgZone }, { type: i1$3.FocusMonitor }];
3230
+ }, propDecorators: { _portalOutlet: [{
3231
+ type: ViewChild,
3232
+ args: [CdkPortalOutlet, { static: true }]
3233
+ }] } });
3234
+ class BaoModalContainer extends _BaoModalContainerBase {
3235
+ constructor() {
3236
+ super(...arguments);
3237
+ /** State of the modal animation. */
3238
+ this._state = 'enter';
3239
+ }
3240
+ /** Callback, invoked whenever an animation on the host completes. */
3241
+ _onAnimationDone({ toState, totalTime }) {
3242
+ return __awaiter(this, void 0, void 0, function* () {
3243
+ if (toState === 'enter') {
3244
+ yield this._trapFocus();
3245
+ this._animationStateChanged.next({ state: 'opened', totalTime });
3246
+ }
3247
+ else if (toState === 'exit') {
3248
+ this._restoreFocus();
3249
+ this._animationStateChanged.next({ state: 'closed', totalTime });
3250
+ }
3251
+ });
3252
+ }
3253
+ /** Callback, invoked when an animation on the host starts. */
3254
+ _onAnimationStart({ toState, totalTime }) {
3255
+ if (toState === 'enter') {
3256
+ this._animationStateChanged.next({ state: 'opening', totalTime });
3257
+ }
3258
+ else if (toState === 'exit' || toState === 'void') {
3259
+ this._animationStateChanged.next({ state: 'closing', totalTime });
3260
+ }
3261
+ }
3262
+ /** Starts the modal exit animation. */
3263
+ _startExitAnimation() {
3264
+ this._state = 'exit';
3265
+ // Mark the container for check so it can react if the
3266
+ // view container is using OnPush change detection.
3267
+ this._changeDetectorRef.markForCheck();
3268
+ }
3269
+ }
3270
+ BaoModalContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalContainer, deps: null, target: i0.ɵɵFactoryTarget.Component });
3271
+ BaoModalContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.1", type: BaoModalContainer, selector: "bao-modal-container", host: { attributes: { "tabindex": "-1", "aria-modal": "true" }, listeners: { "@modalContainer.start": "_onAnimationStart($event)", "@modalContainer.done": "_onAnimationDone($event)" }, properties: { "id": "_id", "attr.role": "_config.role", "attr.aria-labelledby": "_config.ariaLabel ? null : _ariaLabelledBy", "attr.aria-label": "_config.ariaLabel", "attr.aria-describedby": "_config.ariaDescribedBy || null", "@modalContainer": "_state" }, classAttribute: "bao-modal-container" }, usesInheritance: true, ngImport: i0, template: "<ng-template cdkPortalOutlet></ng-template>\n", styles: [".bao-container{padding-right:16px;padding-left:16px;margin-right:auto;margin-left:auto;width:100%}@media (min-width: 576px){.bao-container{max-width:576px}}@media (min-width: 768px){.bao-container{max-width:768px}}@media (min-width: 992px){.bao-container{max-width:992px}}@media (min-width: 1200px){.bao-container{max-width:1200px}}.bao-row{display:flex;flex-wrap:wrap;margin-right:-16px;margin-left:-16px}.bao-col-12,.bao-col-lg-7{position:relative;width:100%;padding-right:1rem;padding-left:1rem}@media (min-width: 992px){.bao-col-lg-7{flex:0 0 58.33333%;max-width:58.33333%}}.cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex}.cdk-overlay-pane.bao-modal-mobil-full{width:100%;height:100%}.cdk-overlay-pane.bao-modal-mobil-compact{width:300px;height:100%}@media (min-width: 768px){.cdk-overlay-pane{width:500px;height:auto}.cdk-overlay-pane.bao-modal-lg{width:calc(100% - 4rem);height:calc(100% - 4rem)}.cdk-overlay-pane.bao-modal-md,.cdk-overlay-pane.bao-modal-sm{width:500px;height:auto}}@media (min-width: 992px){.cdk-overlay-pane{width:500px;height:auto}.cdk-overlay-pane.bao-modal-lg{width:calc(100% - 4rem);height:calc(100% - 4rem)}.cdk-overlay-pane.bao-modal-md{width:800px;height:auto}.cdk-overlay-pane.bao-modal-sm{width:500px;height:auto}}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.5}.cdk-high-contrast-active .cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.cdk-overlay-dark-backdrop{background:black}.cdk-overlay-transparent-backdrop,.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:.5}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.bao-modal-container{display:block;overflow:auto;width:100%;height:100%;min-height:inherit;max-height:inherit;background-color:#fff;background-clip:padding-box;border:0 solid rgba(0,0,0,.2);border-radius:.5rem;outline:0}.bao-modal-content{display:flex;flex-direction:column;height:100%}.bao-modal-header{flex:0 0 auto;display:flex;align-items:flex-start;justify-content:space-between;border-bottom:1px solid #ced4da;border-top-left-radius:.5rem;border-top-right-radius:.5rem}.bao-modal-header .bao-modal-title{font-size:1rem;line-height:1.5rem;margin:1rem 0 1rem 1rem}.bao-modal-header button{margin:.5rem}.bao-modal-body{display:block;padding:1rem;overflow:auto;flex-grow:1}@media (min-width: 768px){.bao-modal-body{padding:2rem}}.bao-modal-footer{display:flex;flex-wrap:wrap;padding:1rem;border-top:1px solid #ced4da;border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.bao-modal-footer.bao-modal-footer-order{justify-content:unset;flex-direction:column-reverse}.bao-modal-footer button{text-align:center}.bao-modal-footer .bao-button-primary,.bao-modal-footer .bao-button-secondary{width:100%;display:block}.bao-modal-footer .bao-button-secondary{margin-bottom:.5rem}.bao-modal-footer .bao-button-tertiary{display:none}@media (min-width: 768px){.bao-modal-footer{justify-content:flex-end}.bao-modal-footer.bao-modal-footer-order{flex-direction:row-reverse}.bao-modal-footer .bao-button-primary{margin-left:1rem}.bao-modal-footer .bao-button-secondary{margin-bottom:0}.bao-modal-footer .bao-button-primary,.bao-modal-footer .bao-button-secondary{width:auto}.bao-modal-footer .bao-button-tertiary{display:block}}\n"], directives: [{ type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], animations: [baoModalAnimations.modalContainer], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None });
3272
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalContainer, decorators: [{
3273
+ type: Component,
3274
+ args: [{ selector: 'bao-modal-container', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, animations: [baoModalAnimations.modalContainer], host: {
3275
+ class: 'bao-modal-container',
3276
+ tabindex: '-1',
3277
+ 'aria-modal': 'true',
3278
+ '[id]': '_id',
3279
+ '[attr.role]': '_config.role',
3280
+ '[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',
3281
+ '[attr.aria-label]': '_config.ariaLabel',
3282
+ '[attr.aria-describedby]': '_config.ariaDescribedBy || null',
3283
+ '[@modalContainer]': '_state',
3284
+ '(@modalContainer.start)': '_onAnimationStart($event)',
3285
+ '(@modalContainer.done)': '_onAnimationDone($event)'
3286
+ }, template: "<ng-template cdkPortalOutlet></ng-template>\n", styles: [".bao-container{padding-right:16px;padding-left:16px;margin-right:auto;margin-left:auto;width:100%}@media (min-width: 576px){.bao-container{max-width:576px}}@media (min-width: 768px){.bao-container{max-width:768px}}@media (min-width: 992px){.bao-container{max-width:992px}}@media (min-width: 1200px){.bao-container{max-width:1200px}}.bao-row{display:flex;flex-wrap:wrap;margin-right:-16px;margin-left:-16px}.bao-col-12,.bao-col-lg-7{position:relative;width:100%;padding-right:1rem;padding-left:1rem}@media (min-width: 992px){.bao-col-lg-7{flex:0 0 58.33333%;max-width:58.33333%}}.cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex}.cdk-overlay-pane.bao-modal-mobil-full{width:100%;height:100%}.cdk-overlay-pane.bao-modal-mobil-compact{width:300px;height:100%}@media (min-width: 768px){.cdk-overlay-pane{width:500px;height:auto}.cdk-overlay-pane.bao-modal-lg{width:calc(100% - 4rem);height:calc(100% - 4rem)}.cdk-overlay-pane.bao-modal-md,.cdk-overlay-pane.bao-modal-sm{width:500px;height:auto}}@media (min-width: 992px){.cdk-overlay-pane{width:500px;height:auto}.cdk-overlay-pane.bao-modal-lg{width:calc(100% - 4rem);height:calc(100% - 4rem)}.cdk-overlay-pane.bao-modal-md{width:800px;height:auto}.cdk-overlay-pane.bao-modal-sm{width:500px;height:auto}}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.5}.cdk-high-contrast-active .cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.cdk-overlay-dark-backdrop{background:black}.cdk-overlay-transparent-backdrop,.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:.5}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.bao-modal-container{display:block;overflow:auto;width:100%;height:100%;min-height:inherit;max-height:inherit;background-color:#fff;background-clip:padding-box;border:0 solid rgba(0,0,0,.2);border-radius:.5rem;outline:0}.bao-modal-content{display:flex;flex-direction:column;height:100%}.bao-modal-header{flex:0 0 auto;display:flex;align-items:flex-start;justify-content:space-between;border-bottom:1px solid #ced4da;border-top-left-radius:.5rem;border-top-right-radius:.5rem}.bao-modal-header .bao-modal-title{font-size:1rem;line-height:1.5rem;margin:1rem 0 1rem 1rem}.bao-modal-header button{margin:.5rem}.bao-modal-body{display:block;padding:1rem;overflow:auto;flex-grow:1}@media (min-width: 768px){.bao-modal-body{padding:2rem}}.bao-modal-footer{display:flex;flex-wrap:wrap;padding:1rem;border-top:1px solid #ced4da;border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.bao-modal-footer.bao-modal-footer-order{justify-content:unset;flex-direction:column-reverse}.bao-modal-footer button{text-align:center}.bao-modal-footer .bao-button-primary,.bao-modal-footer .bao-button-secondary{width:100%;display:block}.bao-modal-footer .bao-button-secondary{margin-bottom:.5rem}.bao-modal-footer .bao-button-tertiary{display:none}@media (min-width: 768px){.bao-modal-footer{justify-content:flex-end}.bao-modal-footer.bao-modal-footer-order{flex-direction:row-reverse}.bao-modal-footer .bao-button-primary{margin-left:1rem}.bao-modal-footer .bao-button-secondary{margin-bottom:0}.bao-modal-footer .bao-button-primary,.bao-modal-footer .bao-button-secondary{width:auto}.bao-modal-footer .bao-button-tertiary{display:block}}\n"] }]
3287
+ }] });
3288
+
3289
+ // Counter for unique modal ids.
3290
+ let uniqueId = 0;
3291
+ /**
3292
+ * Reference to a modal opened via the BaoModalService.
3293
+ */
3294
+ class BaoModalRef {
3295
+ constructor(_overlayRef, _containerInstance,
3296
+ /** Id of the modal. */
3297
+ id = `bao-modal-${uniqueId++}`) {
3298
+ this._overlayRef = _overlayRef;
3299
+ this._containerInstance = _containerInstance;
3300
+ this.id = id;
3301
+ /** Whether the user is allowed to close the modal. */
3302
+ this.disableClose = this._containerInstance._config.disableClose;
3303
+ /** Subject for notifying the user that the modal has finished opening. */
3304
+ this._afterOpened = new Subject();
3305
+ /** Subject for notifying the user that the modal has finished closing. */
3306
+ this._afterClosed = new Subject();
3307
+ /** Subject for notifying the user that the modal has started closing. */
3308
+ this._beforeClosed = new Subject();
3309
+ /** Current state of the modal. */
3310
+ this._state = 0 /* OPEN */;
3311
+ // Pass the id along to the container.
3312
+ _containerInstance._id = id;
3313
+ // Emit when opening animation completes
3314
+ _containerInstance._animationStateChanged
3315
+ .pipe(filter(event => event.state === 'opened'), take(1))
3316
+ .subscribe(() => {
3317
+ this._afterOpened.next();
3318
+ this._afterOpened.complete();
3319
+ });
3320
+ // Dispose overlay when closing animation is complete
3321
+ _containerInstance._animationStateChanged
3322
+ .pipe(filter(event => event.state === 'closed'), take(1))
3323
+ .subscribe(() => {
3324
+ clearTimeout(this._closeFallbackTimeout);
3325
+ this._finishModalClose();
3326
+ });
3327
+ _overlayRef.detachments().subscribe(() => {
3328
+ this._beforeClosed.next(this._result);
3329
+ this._beforeClosed.complete();
3330
+ this._afterClosed.next(this._result);
3331
+ this._afterClosed.complete();
3332
+ this.componentInstance = null;
3333
+ this._overlayRef.dispose();
3334
+ });
3335
+ _overlayRef
3336
+ .keydownEvents()
3337
+ .pipe(filter(event => {
3338
+ return (event.keyCode === ESCAPE &&
3339
+ !this.disableClose &&
3340
+ !hasModifierKey(event));
3341
+ }))
3342
+ .subscribe(event => {
3343
+ event.preventDefault();
3344
+ _closeModalVia(this, 'keyboard');
3345
+ });
3346
+ _overlayRef.backdropClick().subscribe(() => __awaiter(this, void 0, void 0, function* () {
3347
+ if (this.disableClose) {
3348
+ yield this._containerInstance._recaptureFocus();
3349
+ }
3350
+ else {
3351
+ _closeModalVia(this, 'mouse');
3352
+ }
3353
+ }));
3354
+ }
3355
+ /**
3356
+ * Close the modal.
3357
+ * @param modalResult Optional result to return to the modal opener.
3358
+ */
3359
+ close(modalResult) {
3360
+ this._result = modalResult;
3361
+ // Transition the backdrop in parallel to the modal.
3362
+ this._containerInstance._animationStateChanged
3363
+ .pipe(filter(event => event.state === 'closing'), take(1))
3364
+ .subscribe(event => {
3365
+ this._beforeClosed.next(modalResult);
3366
+ this._beforeClosed.complete();
3367
+ this._overlayRef.detachBackdrop();
3368
+ // The logic that disposes of the overlay depends on the exit animation completing, however
3369
+ // it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback
3370
+ // timeout which will clean everything up if the animation hasn't fired within the specified
3371
+ // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the
3372
+ // vast majority of cases the timeout will have been cleared before it has the chance to fire.
3373
+ this._closeFallbackTimeout = setTimeout(() => this._finishModalClose(), event.totalTime + 100);
3374
+ });
3375
+ this._state = 1 /* CLOSING */;
3376
+ this._containerInstance._startExitAnimation();
3377
+ }
3378
+ /**
3379
+ * Gets an observable that is notified when the modal is finished opening.
3380
+ */
3381
+ afterOpened() {
3382
+ return this._afterOpened;
3383
+ }
3384
+ /**
3385
+ * Gets an observable that is notified when the modal is finished closing.
3386
+ */
3387
+ afterClosed() {
3388
+ return this._afterClosed;
3389
+ }
3390
+ /**
3391
+ * Gets an observable that is notified when the modal has started closing.
3392
+ */
3393
+ beforeClosed() {
3394
+ return this._beforeClosed;
3395
+ }
3396
+ /**
3397
+ * Gets an observable that emits when the overlay's backdrop has been clicked.
3398
+ */
3399
+ backdropClick() {
3400
+ return this._overlayRef.backdropClick();
3401
+ }
3402
+ /**
3403
+ * Gets an observable that emits when keydown events are targeted on the overlay.
3404
+ */
3405
+ keydownEvents() {
3406
+ return this._overlayRef.keydownEvents();
3407
+ }
3408
+ /**
3409
+ * Updates the dialog's position.
3410
+ */
3411
+ updatePosition(position) {
3412
+ const strategy = this._getPositionStrategy();
3413
+ if (position && (position.left || position.right)) {
3414
+ position.left
3415
+ ? strategy.left(position.left)
3416
+ : strategy.right(position.right);
3417
+ }
3418
+ else {
3419
+ strategy.centerHorizontally();
3420
+ }
3421
+ if (position && (position.top || position.bottom)) {
3422
+ position.top
3423
+ ? strategy.top(position.top)
3424
+ : strategy.bottom(position.bottom);
3425
+ }
3426
+ else {
3427
+ strategy.centerVertically();
3428
+ }
3429
+ this._overlayRef.updatePosition();
3430
+ return this;
3431
+ }
3432
+ /**
3433
+ * Updates the modal's width and height.
3434
+ */
3435
+ updateSize(width = '', height = '') {
3436
+ this._overlayRef.updateSize({ width, height });
3437
+ this._overlayRef.updatePosition();
3438
+ return this;
3439
+ }
3440
+ /** Add a CSS class or an array of classes to the overlay pane. */
3441
+ addPanelClass(classes) {
3442
+ this._overlayRef.addPanelClass(classes);
3443
+ return this;
3444
+ }
3445
+ /** Remove a CSS class or an array of classes from the overlay pane. */
3446
+ removePanelClass(classes) {
3447
+ this._overlayRef.removePanelClass(classes);
3448
+ return this;
3449
+ }
3450
+ /** Gets the current state of the modal's lifecycle. */
3451
+ getState() {
3452
+ return this._state;
3453
+ }
3454
+ /**
3455
+ * Finishes the modal close by updating the state of the modal
3456
+ * and disposing the overlay.
3457
+ */
3458
+ _finishModalClose() {
3459
+ this._state = 2 /* CLOSED */;
3460
+ this._overlayRef.dispose();
3461
+ }
3462
+ /** Fetches the position strategy object from the overlay ref. */
3463
+ _getPositionStrategy() {
3464
+ return this._overlayRef.getConfig()
3465
+ .positionStrategy;
3466
+ }
3467
+ }
3468
+ /**
3469
+ * Closes the modal with the specified interaction type. This is currently not part of
3470
+ * `BaoModalRef` as that would conflict with custom modal ref mocks provided in tests.
3471
+ * More details. See: https://github.com/angular/components/pull/9257#issuecomment-651342226.
3472
+ */
3473
+ function _closeModalVia(ref, interactionType, result) {
3474
+ // Some mock modal ref instances in tests do not have the `_containerInstance` property.
3475
+ // For those, we keep the behavior as is and do not deal with the interaction type.
3476
+ if (ref._containerInstance !== undefined) {
3477
+ ref._containerInstance._closeInteractionType = interactionType;
3478
+ }
3479
+ return ref.close(result);
3480
+ }
3481
+
3482
+ /*
3483
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
3484
+ * Licensed under the MIT license.
3485
+ * See LICENSE file in the project root for full license information.
3486
+ */
3487
+ /** Injection token that can be used to access the data that was passed in to a modal. */
3488
+ const BAO_MODAL_DATA = new InjectionToken('BaoModalData');
3489
+ class BaoModalBase {
3490
+ constructor(_overlay, _injector, _parentModal, _overlayContainer, _modalRefConstructor, _modalContainerType, _modalDataToken, _animationMode) {
3491
+ this._overlay = _overlay;
3492
+ this._injector = _injector;
3493
+ this._parentModal = _parentModal;
3494
+ this._overlayContainer = _overlayContainer;
3495
+ this._modalRefConstructor = _modalRefConstructor;
3496
+ this._modalContainerType = _modalContainerType;
3497
+ this._modalDataToken = _modalDataToken;
3498
+ this._animationMode = _animationMode;
3499
+ this.afterAllClosed = defer(() => this.openModals.length
3500
+ ? this.getAfterAllClosed()
3501
+ : this.getAfterAllClosed().pipe(startWith(undefined)));
3502
+ this._openModalsAtThisLevel = [];
3503
+ this._afterAllClosedAtThisLevel = new Subject();
3504
+ this._afterOpenedAtThisLevel = new Subject();
3505
+ this._ariaHiddenElements = new Map();
3506
+ this._modalAnimatingOpen = false;
3507
+ }
3508
+ /** Keeps track of the currently-open modals. */
3509
+ get openModals() {
3510
+ return this._parentModal
3511
+ ? this._parentModal.openModals
3512
+ : this._openModalsAtThisLevel;
3513
+ }
3514
+ /** Stream that emits when a modal has been opened. */
3515
+ get afterOpened() {
3516
+ // Maybe typescript version difference
3517
+ return this._parentModal
3518
+ ? this._parentModal.afterOpened
3519
+ : this._afterOpenedAtThisLevel;
3520
+ }
3521
+ getAfterAllClosed() {
3522
+ const parent = this._parentModal;
3523
+ return (parent ? parent.getAfterAllClosed() : this._afterAllClosedAtThisLevel);
3524
+ }
3525
+ /**
3526
+ * Opens a modal modal containing the given template.
3527
+ */
3528
+ open(componentOrTemplateRef, config) {
3529
+ const conf = this._applyConfigDefaults(config, new BaoModalInitialConfig());
3530
+ // If there is a modal that is currently animating open, return the MatmodalRef of that modal
3531
+ if (this._modalAnimatingOpen) {
3532
+ return this._lastModalRef;
3533
+ }
3534
+ const overlayRef = this._createOverlay(conf);
3535
+ const modalContainer = this._attachModalContainer(overlayRef, conf);
3536
+ if (this._animationMode !== 'NoopAnimations') {
3537
+ const animationStateSubscription = modalContainer._animationStateChanged.subscribe(modalAnimationEvent => {
3538
+ if (modalAnimationEvent.state === 'opening') {
3539
+ this._modalAnimatingOpen = true;
3540
+ }
3541
+ if (modalAnimationEvent.state === 'opened') {
3542
+ this._modalAnimatingOpen = false;
3543
+ animationStateSubscription.unsubscribe();
3544
+ }
3545
+ });
3546
+ if (!this._animationStateSubscriptions) {
3547
+ this._animationStateSubscriptions = new Subscription();
3548
+ }
3549
+ this._animationStateSubscriptions.add(animationStateSubscription);
3550
+ }
3551
+ const modalRef = this._attachModalContent(componentOrTemplateRef, modalContainer, overlayRef, conf);
3552
+ this._lastModalRef = modalRef;
3553
+ // If this is the first modal that we're opening, hide all the non-overlay content.
3554
+ if (!this.openModals.length) {
3555
+ this._hideNonModalContentFromAssistiveTechnology();
3556
+ }
3557
+ this.openModals.push(modalRef);
3558
+ modalRef.afterClosed().subscribe(() => this._removeOpenModal(modalRef));
3559
+ this.afterOpened.next(modalRef);
3560
+ // Notify the modal container that the content has been attached.
3561
+ modalContainer._initializeWithAttachedContent();
3562
+ return modalRef;
3563
+ }
3564
+ /**
3565
+ * Closes all of the currently-open modals.
3566
+ */
3567
+ closeAll() {
3568
+ this._closeModals(this.openModals);
3569
+ }
3570
+ /**
3571
+ * Finds an open modal by its id.
3572
+ */
3573
+ getModalById(id) {
3574
+ return this.openModals.find(modal => modal.id === id);
3575
+ }
3576
+ ngOnDestroy() {
3577
+ // Only close the modals at this level on destroy
3578
+ // since the parent service may still be active.
3579
+ this._closeModals(this._openModalsAtThisLevel);
3580
+ this._afterAllClosedAtThisLevel.complete();
3581
+ this._afterOpenedAtThisLevel.complete();
3582
+ // Clean up any subscriptions to modals that never finished opening.
3583
+ if (this._animationStateSubscriptions) {
3584
+ this._animationStateSubscriptions.unsubscribe();
3585
+ }
3586
+ }
3587
+ /**
3588
+ * Creates the overlay into which the modal will be loaded.
3589
+ */
3590
+ _createOverlay(config) {
3591
+ const overlayConfig = this._getOverlayConfig(config);
3592
+ return this._overlay.create(overlayConfig);
3593
+ }
3594
+ /**
3595
+ * Creates an overlay config from a modal config.
3596
+ */
3597
+ _getOverlayConfig(config) {
3598
+ const state = new OverlayConfig({
3599
+ positionStrategy: this._overlay.position().global(),
3600
+ scrollStrategy: this._overlay.scrollStrategies.block(),
3601
+ panelClass: config.panelClass,
3602
+ hasBackdrop: config.hasBackdrop,
3603
+ disposeOnNavigation: config.closeOnNavigation
3604
+ });
3605
+ if (config.backdropClass) {
3606
+ state.backdropClass = config.backdropClass;
3607
+ }
3608
+ return state;
3609
+ }
3610
+ /**
3611
+ * Attaches a modal container to a modal's already-created overlay.
3612
+ */
3613
+ _attachModalContainer(overlay, config) {
3614
+ const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
3615
+ const injector = Injector.create({
3616
+ parent: userInjector || this._injector,
3617
+ providers: [{ provide: BaoModalInitialConfig, useValue: config }]
3618
+ });
3619
+ const containerPortal = new ComponentPortal(this._modalContainerType, config.viewContainerRef, injector);
3620
+ const containerRef = overlay.attach(containerPortal);
3621
+ return containerRef.instance;
3622
+ }
3623
+ /**
3624
+ * Attaches the user-provided component to the already-created modal container.
3625
+ */
3626
+ _attachModalContent(componentOrTemplateRef, modalContainer, overlayRef, config) {
3627
+ // Create a reference to the modal we're creating in order to give the user a handle
3628
+ // to modify and close it.
3629
+ const modalRef = new this._modalRefConstructor(overlayRef, modalContainer, config.id);
3630
+ if (componentOrTemplateRef instanceof TemplateRef) {
3631
+ modalContainer.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, null, {
3632
+ $implicit: config.data,
3633
+ modalRef
3634
+ }));
3635
+ }
3636
+ else {
3637
+ const injector = this._createInjector(config, modalRef, modalContainer);
3638
+ const contentRef = modalContainer.attachComponentPortal(new ComponentPortal(componentOrTemplateRef, config.viewContainerRef, injector));
3639
+ modalRef.componentInstance = contentRef.instance;
3640
+ }
3641
+ modalRef
3642
+ .updateSize(config.width, config.height)
3643
+ .updatePosition(config.position);
3644
+ return modalRef;
3645
+ }
3646
+ /**
3647
+ * Creates a custom injector to be used inside the modal. This allows a component loaded inside
3648
+ * of a modal to close itself and, optionally, to return a value.
3649
+ */
3650
+ _createInjector(config, modalRef, modalContainer) {
3651
+ const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
3652
+ // The modal container should be provided as the modal container and the modal's
3653
+ // content are created out of the same `ViewContainerRef` and as such, are siblings
3654
+ // for injector purposes. To allow the hierarchy that is expected, the modal
3655
+ // container is explicitly provided in the injector.
3656
+ const providers = [
3657
+ { provide: this._modalContainerType, useValue: modalContainer },
3658
+ { provide: this._modalDataToken, useValue: config.data },
3659
+ { provide: this._modalRefConstructor, useValue: modalRef }
3660
+ ];
3661
+ return Injector.create({
3662
+ parent: userInjector || this._injector,
3663
+ providers
3664
+ });
3665
+ }
3666
+ /**
3667
+ * Removes a modal from the array of open modals.
3668
+ */
3669
+ _removeOpenModal(modalRef) {
3670
+ const index = this.openModals.indexOf(modalRef);
3671
+ if (index > -1) {
3672
+ this.openModals.splice(index, 1);
3673
+ // If all the modals were closed, remove/restore the `aria-hidden`
3674
+ // to a the siblings and emit to the `afterAllClosed` stream.
3675
+ if (!this.openModals.length) {
3676
+ this._ariaHiddenElements.forEach((previousValue, element) => {
3677
+ if (previousValue) {
3678
+ element.setAttribute('aria-hidden', previousValue);
3679
+ }
3680
+ else {
3681
+ element.removeAttribute('aria-hidden');
3682
+ }
3683
+ });
3684
+ this._ariaHiddenElements.clear();
3685
+ this.getAfterAllClosed().next();
3686
+ }
3687
+ }
3688
+ }
3689
+ /**
3690
+ * Hides all of the content that isn't an overlay from assistive technology.
3691
+ */
3692
+ _hideNonModalContentFromAssistiveTechnology() {
3693
+ const overlayContainer = this._overlayContainer.getContainerElement();
3694
+ // Ensure that the overlay container is attached to the DOM.
3695
+ if (overlayContainer.parentElement) {
3696
+ const siblings = overlayContainer.parentElement.children;
3697
+ for (let i = siblings.length - 1; i > -1; i--) {
3698
+ const sibling = siblings[i];
3699
+ if (sibling !== overlayContainer &&
3700
+ sibling.nodeName !== 'SCRIPT' &&
3701
+ sibling.nodeName !== 'STYLE' &&
3702
+ !sibling.hasAttribute('aria-live')) {
3703
+ this._ariaHiddenElements.set(sibling, sibling.getAttribute('aria-hidden'));
3704
+ sibling.setAttribute('aria-hidden', 'true');
3705
+ }
3706
+ }
3707
+ }
3708
+ }
3709
+ /** Closes all of the modals in an array. */
3710
+ _closeModals(modals) {
3711
+ let i = modals.length;
3712
+ while (i--) {
3713
+ modals[i].close();
3714
+ }
3715
+ }
3716
+ /**
3717
+ * Applies default options to the modal config.
3718
+ */
3719
+ _applyConfigDefaults(config, defaultOptions) {
3720
+ const desktopClass = (config === null || config === void 0 ? void 0 : config.size) || eModalDesktopWidthSize.SMALL;
3721
+ const mobilClass = (config === null || config === void 0 ? void 0 : config.mobileSize) || eModalMobileWidthSize.FULL;
3722
+ const data = (config === null || config === void 0 ? void 0 : config.data) || null;
3723
+ const ariaLabelledBy = (config === null || config === void 0 ? void 0 : config.ariaLabelledBy) || null;
3724
+ return Object.assign(Object.assign({}, defaultOptions), {
3725
+ panelClass: [desktopClass, mobilClass],
3726
+ ariaLabelledBy,
3727
+ data
3728
+ });
3729
+ }
3730
+ }
3731
+ BaoModalBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalBase, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
3732
+ BaoModalBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.1.1", type: BaoModalBase, ngImport: i0 });
3733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalBase, decorators: [{
3734
+ type: Directive
3735
+ }], ctorParameters: function () { return [{ type: i1$4.Overlay }, { type: i0.Injector }, { type: undefined }, { type: i1$4.OverlayContainer }, { type: i0.Type }, { type: i0.Type }, { type: i0.InjectionToken }, { type: undefined }]; } });
3736
+ /**
3737
+ * Service to open modal.
3738
+ */
3739
+ class BaoModal extends BaoModalBase {
3740
+ constructor(overlay, injector, parentModal, overlayContainer, animationMode) {
3741
+ super(overlay, injector, parentModal, overlayContainer, BaoModalRef, BaoModalContainer, BAO_MODAL_DATA, animationMode);
3742
+ }
3743
+ }
3744
+ BaoModal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModal, deps: [{ token: i1$4.Overlay }, { token: i0.Injector }, { token: BaoModal, optional: true, skipSelf: true }, { token: i1$4.OverlayContainer }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
3745
+ BaoModal.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModal });
3746
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModal, decorators: [{
3747
+ type: Injectable
3748
+ }], ctorParameters: function () {
3749
+ return [{ type: i1$4.Overlay }, { type: i0.Injector }, { type: BaoModal, decorators: [{
3750
+ type: Optional
3751
+ }, {
3752
+ type: SkipSelf
3753
+ }] }, { type: i1$4.OverlayContainer }, { type: undefined, decorators: [{
3754
+ type: Optional
3755
+ }, {
3756
+ type: Inject,
3757
+ args: [ANIMATION_MODULE_TYPE]
3758
+ }] }];
3759
+ } });
3760
+
3761
+ /*
3762
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
3763
+ * Licensed under the MIT license.
3764
+ * See LICENSE file in the project root for full license information.
3765
+ */
3766
+ /**
3767
+ * Button that will close the current dialog.
3768
+ */
3769
+ class BaoModalClose {
3770
+ constructor(modalRef, _elementRef, _dialog) {
3771
+ this.modalRef = modalRef;
3772
+ this._elementRef = _elementRef;
3773
+ this._dialog = _dialog;
3774
+ /** Default to "button" to prevents accidental form submits. */
3775
+ this.type = 'button';
3776
+ }
3777
+ ngOnInit() {
3778
+ if (!this.modalRef) {
3779
+ // When this directive is included in a dialog via TemplateRef (rather than being
3780
+ // in a Component), the modalRef isn't available via injection because embedded
3781
+ // views cannot be given a custom injector. Instead, we look up the modalRef by
3782
+ // ID. This must occur in `onInit`, as the ID binding for the dialog container won't
3783
+ // be resolved at constructor time.
3784
+ this.modalRef =
3785
+ getClosestDialog(this._elementRef, this._dialog.openModals) || null;
3786
+ }
3787
+ }
3788
+ ngOnChanges(changes) {
3789
+ const proxiedChange = changes['_baoModalClose'] || changes['_baoModalCloseResult'];
3790
+ if (proxiedChange) {
3791
+ this.dialogResult = proxiedChange.currentValue;
3792
+ }
3793
+ }
3794
+ _onButtonClick(event) {
3795
+ // Determinate the focus origin using the click event, because using the FocusMonitor will
3796
+ // result in incorrect origins. Most of the time, close buttons will be auto focused in the
3797
+ // dialog, and therefore clicking the button won't result in a focus change. This means that
3798
+ // the FocusMonitor won't detect any origin change, and will always output `program`.
3799
+ _closeModalVia(this.modalRef, event.screenX === 0 && event.screenY === 0 ? 'keyboard' : 'mouse', this.dialogResult);
3800
+ }
3801
+ }
3802
+ BaoModalClose.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalClose, deps: [{ token: BaoModalRef, optional: true }, { token: i0.ElementRef }, { token: BaoModal }], target: i0.ɵɵFactoryTarget.Directive });
3803
+ BaoModalClose.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.1.1", type: BaoModalClose, selector: "[bao-modal-close], [baoModalClose]", inputs: { ariaLabel: ["aria-label", "ariaLabel"], type: "type", dialogResult: ["bao-modal-close", "dialogResult"], _baoModalClose: ["baoModalClose", "_baoModalClose"] }, host: { listeners: { "click": "_onButtonClick($event)" }, properties: { "attr.aria-label": "ariaLabel || null", "attr.type": "type" } }, exportAs: ["BaoModalClose"], usesOnChanges: true, ngImport: i0 });
3804
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalClose, decorators: [{
3805
+ type: Directive,
3806
+ args: [{
3807
+ selector: '[bao-modal-close], [baoModalClose]',
3808
+ exportAs: 'BaoModalClose',
3809
+ host: {
3810
+ '(click)': '_onButtonClick($event)',
3811
+ '[attr.aria-label]': 'ariaLabel || null',
3812
+ '[attr.type]': 'type'
3813
+ }
3814
+ }]
3815
+ }], ctorParameters: function () {
3816
+ return [{ type: BaoModalRef, decorators: [{
3817
+ type: Optional
3818
+ }] }, { type: i0.ElementRef }, { type: BaoModal }];
3819
+ }, propDecorators: { ariaLabel: [{
3820
+ type: Input,
3821
+ args: ['aria-label']
3822
+ }], type: [{
3823
+ type: Input
3824
+ }], dialogResult: [{
3825
+ type: Input,
3826
+ args: ['bao-modal-close']
3827
+ }], _baoModalClose: [{
3828
+ type: Input,
3829
+ args: ['baoModalClose']
3830
+ }] } });
3831
+ /**
3832
+ * Finds the closest BaoModalRef to an element by looking at the DOM.
3833
+ */
3834
+ function getClosestDialog(element, openDialogs) {
3835
+ let parent = element.nativeElement.parentElement;
3836
+ while (parent && !parent.classList.contains('bao-modal-container')) {
3837
+ parent = parent.parentElement;
3838
+ }
3839
+ return parent ? openDialogs.find(dialog => dialog.id === parent.id) : null;
3840
+ }
3841
+
3842
+ /*
3843
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
3844
+ * Licensed under the MIT license.
3845
+ * See LICENSE file in the project root for full license information.
3846
+ */
3847
+ const MODAL_DIRECTIVES = [BaoModalContainer, BaoModalClose];
3848
+ class BaoModalModule {
3849
+ }
3850
+ BaoModalModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3851
+ BaoModalModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalModule, declarations: [BaoModalContainer, BaoModalClose], imports: [CommonModule,
3852
+ OverlayModule,
3853
+ PortalModule,
3854
+ BrowserAnimationsModule,
3855
+ NoopAnimationsModule], exports: [BaoModalContainer, BaoModalClose] });
3856
+ BaoModalModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalModule, providers: [BaoModal], imports: [[
3857
+ CommonModule,
3858
+ OverlayModule,
3859
+ PortalModule,
3860
+ BrowserAnimationsModule,
3861
+ NoopAnimationsModule
3862
+ ]] });
3863
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: BaoModalModule, decorators: [{
3864
+ type: NgModule,
3865
+ args: [{
3866
+ imports: [
3867
+ CommonModule,
3868
+ OverlayModule,
3869
+ PortalModule,
3870
+ BrowserAnimationsModule,
3871
+ NoopAnimationsModule
3872
+ ],
3873
+ declarations: MODAL_DIRECTIVES,
3874
+ exports: MODAL_DIRECTIVES,
3875
+ providers: [BaoModal]
3876
+ }]
3877
+ }] });
3878
+
2939
3879
  /*
2940
3880
  * Copyright (c) 2022 Ville de Montreal. All rights reserved.
2941
3881
  * Licensed under the MIT license.
@@ -2961,7 +3901,8 @@ BaoModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.
2961
3901
  BaoRadioModule,
2962
3902
  BaoSummaryModule,
2963
3903
  BaoAvatarModule,
2964
- BaoTabsModule
3904
+ BaoTabsModule,
3905
+ BaoModalModule
2965
3906
  // TODO: reactivate once component does not depend on global css BaoBadgeModule,
2966
3907
  // TODO: reactivate once component does not depend on global css BaoSnackBarModule,
2967
3908
  ] });
@@ -2984,7 +3925,8 @@ BaoModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.
2984
3925
  BaoRadioModule,
2985
3926
  BaoSummaryModule,
2986
3927
  BaoAvatarModule,
2987
- BaoTabsModule
3928
+ BaoTabsModule,
3929
+ BaoModalModule
2988
3930
  // TODO: reactivate once component does not depend on global css BaoBadgeModule,
2989
3931
  // TODO: reactivate once component does not depend on global css BaoSnackBarModule,
2990
3932
  ] });
@@ -3012,7 +3954,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImpor
3012
3954
  BaoRadioModule,
3013
3955
  BaoSummaryModule,
3014
3956
  BaoAvatarModule,
3015
- BaoTabsModule
3957
+ BaoTabsModule,
3958
+ BaoModalModule
3016
3959
  // TODO: reactivate once component does not depend on global css BaoBadgeModule,
3017
3960
  // TODO: reactivate once component does not depend on global css BaoSnackBarModule,
3018
3961
  ]
@@ -3082,9 +4025,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImpor
3082
4025
  * See LICENSE file in the project root for full license information.
3083
4026
  */
3084
4027
 
4028
+ /*
4029
+ * Copyright (c) 2022 Ville de Montreal. All rights reserved.
4030
+ * Licensed under the MIT license.
4031
+ * See LICENSE file in the project root for full license information.
4032
+ */
4033
+
3085
4034
  /**
3086
4035
  * Generated bundle index. Do not edit.
3087
4036
  */
3088
4037
 
3089
- export { BAO_RADIO_GROUP, BaoAlertActions, BaoAlertComponent, BaoAlertContent, BaoAlertLink, BaoAlertModule, BaoAlertTitle, BaoAvatarComponent, BaoAvatarContent, BaoAvatarModule, BaoBadgeComponent, BaoBadgeModule, BaoBreadcrumbComponent, BaoBreadcrumbModule, BaoButtonComponent, BaoButtonModule, BaoCardComponent, BaoCardContent, BaoCardHeader, BaoCardModule, BaoCardTextInterface, BaoCardTitle, BaoCheckBoxDescription, BaoCheckboxComponent, BaoCheckboxGroupComponent, BaoCheckboxModule, BaoCommonComponentsModule, BaoErrorTextComponent, BaoGuidingTextComponent, BaoHeaderInfoComponent, BaoHeaderInfoContent, BaoHeaderInfoModule, BaoHeaderInfoSubtitle, BaoHeaderInfoSurtitle, BaoHeaderInfoTitle, BaoHeaderInfoTitleGroupComponent, BaoIconComponent, BaoIconModule, BaoLabelTextComponent, BaoList, BaoListItem, BaoListItemDescription, BaoListItemTitle, BaoListModule, BaoListSummary, BaoListSummaryItem, BaoModule, BaoNavList, BaoRadioButtonComponent, BaoRadioButtonGroupComponent, BaoRadioDescription, BaoRadioModule, BaoSummaryComponent, BaoSummaryDescription, BaoSummaryModule, BaoTabHeader, BaoTabPanel, BaoTablistComponent, BaoTabsContainer, BaoTabsModule, BaoTagComponent, BaoTagModule, BaoTitleTextComponent };
4038
+ export { BAO_MODAL_DATA, BAO_RADIO_GROUP, BaoAlertActions, BaoAlertComponent, BaoAlertContent, BaoAlertLink, BaoAlertModule, BaoAlertTitle, BaoAvatarComponent, BaoAvatarContent, BaoAvatarModule, BaoBadgeComponent, BaoBadgeModule, BaoBreadcrumbComponent, BaoBreadcrumbModule, BaoButtonComponent, BaoButtonModule, BaoCardComponent, BaoCardContent, BaoCardHeader, BaoCardModule, BaoCardTextInterface, BaoCardTitle, BaoCheckBoxDescription, BaoCheckboxComponent, BaoCheckboxGroupComponent, BaoCheckboxModule, BaoCommonComponentsModule, BaoErrorTextComponent, BaoGuidingTextComponent, BaoHeaderInfoComponent, BaoHeaderInfoContent, BaoHeaderInfoModule, BaoHeaderInfoSubtitle, BaoHeaderInfoSurtitle, BaoHeaderInfoTitle, BaoHeaderInfoTitleGroupComponent, BaoIconComponent, BaoIconModule, BaoLabelTextComponent, BaoList, BaoListItem, BaoListItemDescription, BaoListItemTitle, BaoListModule, BaoListSummary, BaoListSummaryItem, BaoModal, BaoModalBase, BaoModalClose, BaoModalContainer, BaoModalInitialConfig, BaoModalModule, BaoModalRef, BaoModule, BaoNavList, BaoRadioButtonComponent, BaoRadioButtonGroupComponent, BaoRadioDescription, BaoRadioModule, BaoSummaryComponent, BaoSummaryDescription, BaoSummaryModule, BaoTabHeader, BaoTabPanel, BaoTablistComponent, BaoTabsContainer, BaoTabsModule, BaoTagComponent, BaoTagModule, BaoTitleTextComponent, _BaoModalContainerBase, _closeModalVia, eModalDesktopWidthSize, eModalMobileWidthSize, throwBaoModalContentAlreadyAttachedError };
3090
4039
  //# sourceMappingURL=villedemontreal-angular-ui.mjs.map