@skyux/modals 9.0.0-alpha.8 → 9.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/documentation.json +605 -739
  2. package/esm2022/index.mjs +2 -2
  3. package/esm2022/lib/modules/confirm/confirm.component.mjs +17 -6
  4. package/esm2022/lib/modules/confirm/confirm.module.mjs +7 -28
  5. package/esm2022/lib/modules/confirm/confirm.service.mjs +3 -6
  6. package/esm2022/lib/modules/modal/modal-content.component.mjs +3 -3
  7. package/esm2022/lib/modules/modal/modal-footer.component.mjs +5 -3
  8. package/esm2022/lib/modules/modal/modal-header.component.mjs +5 -3
  9. package/esm2022/lib/modules/modal/modal-host.component.mjs +23 -31
  10. package/esm2022/lib/modules/modal/modal-is-dirty.directive.mjs +3 -2
  11. package/esm2022/lib/modules/modal/modal-scroll-shadow.directive.mjs +16 -18
  12. package/esm2022/lib/modules/modal/modal.component.mjs +43 -36
  13. package/esm2022/lib/modules/modal/modal.module.mjs +7 -41
  14. package/esm2022/lib/modules/modal/modal.service.mjs +41 -20
  15. package/esm2022/lib/modules/shared/sky-modals-resources.module.mjs +4 -2
  16. package/fesm2022/skyux-modals.mjs +899 -916
  17. package/fesm2022/skyux-modals.mjs.map +1 -1
  18. package/index.d.ts +1 -1
  19. package/lib/modules/confirm/confirm.component.d.ts +1 -1
  20. package/lib/modules/confirm/confirm.module.d.ts +4 -7
  21. package/lib/modules/modal/modal-content.component.d.ts +1 -1
  22. package/lib/modules/modal/modal-footer.component.d.ts +2 -2
  23. package/lib/modules/modal/modal-header.component.d.ts +1 -1
  24. package/lib/modules/modal/modal-host.component.d.ts +4 -14
  25. package/lib/modules/modal/modal-is-dirty.directive.d.ts +1 -1
  26. package/lib/modules/modal/modal-scroll-shadow.directive.d.ts +3 -6
  27. package/lib/modules/modal/modal.component.d.ts +3 -6
  28. package/lib/modules/modal/modal.module.d.ts +2 -10
  29. package/lib/modules/modal/modal.service.d.ts +11 -2
  30. package/package.json +5 -5
@@ -1,19 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, NgModule, Component, ViewEncapsulation, Injectable, inject, Inject, EnvironmentInjector, createEnvironmentInjector, ViewContainerRef, Optional, ViewChild, InjectionToken, Directive, Output, HostListener, ChangeDetectorRef, ElementRef, Host, HostBinding, Input } from '@angular/core';
3
- import * as i4 from '@angular/common';
2
+ import { EventEmitter, NgModule, InjectionToken, Component, ViewEncapsulation, Injectable, inject, ElementRef, NgZone, Directive, Output, HostListener, ChangeDetectorRef, HostBinding, Input, ViewChild, Inject, EnvironmentInjector, ViewContainerRef } from '@angular/core';
3
+ import * as i1$1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
- import * as i2$2 from '@skyux/core';
6
- import { SkyResizeObserverMediaQueryService, SkyMediaQueryService, SKY_STACKING_CONTEXT, SkyLiveAnnouncerService, SkyDockLocation, SkyDockService, SkyIdModule, SkyTrimModule } from '@skyux/core';
7
- import * as i2$1 from '@skyux/theme';
8
- import { SkyTheme, SkyThemeModule } from '@skyux/theme';
9
- import * as i3 from '@angular/router';
10
- import { NavigationStart, RouterModule } from '@angular/router';
5
+ import * as i1 from '@skyux/core';
6
+ import { SkyMutationObserverService, SkyCoreAdapterService, SkyDockService, SkyLiveAnnouncerService, SkyResizeObserverMediaQueryService, SkyAppWindowRef, SkyDockLocation, SkyIdModule, SkyDynamicComponentService, SkyMediaQueryService, SKY_STACKING_CONTEXT, SkyTrimModule } from '@skyux/core';
7
+ import * as i5 from '@skyux/theme';
8
+ import { SkyThemeService, SkyTheme, SkyThemeModule } from '@skyux/theme';
9
+ import { BehaviorSubject, Subject, ReplaySubject } from 'rxjs';
10
+ import { takeUntil, take, takeWhile } from 'rxjs/operators';
11
11
  import * as i2 from '@skyux/indicators';
12
12
  import { SkyIconModule, SkyStatusIndicatorModule } from '@skyux/indicators';
13
- import * as i2$3 from '@skyux/i18n';
14
- import { getLibStringForLocale, SkyI18nModule, SKY_LIB_RESOURCES_PROVIDERS, SkyLibResourcesService } from '@skyux/i18n';
15
- import { BehaviorSubject, Subject, ReplaySubject } from 'rxjs';
16
- import { takeUntil, takeWhile, take } from 'rxjs/operators';
13
+ import * as i2$1 from '@skyux/i18n';
14
+ import { SkyLibResourcesService, getLibStringForLocale, SkyI18nModule, SKY_LIB_RESOURCES_PROVIDERS } from '@skyux/i18n';
15
+ import { Router, NavigationStart, RouterModule } from '@angular/router';
17
16
 
18
17
  class SkyConfirmInstance {
19
18
  constructor() {
@@ -50,6 +49,37 @@ var SkyConfirmType;
50
49
  SkyConfirmType[SkyConfirmType["YesNoCancel"] = 3] = "YesNoCancel";
51
50
  })(SkyConfirmType || (SkyConfirmType = {}));
52
51
 
52
+ /**
53
+ * @deprecated The `SkyConfirmModule` is no longer needed and can be removed from your application.
54
+ */
55
+ class SkyConfirmModule {
56
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
57
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule }); }
58
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule }); }
59
+ }
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, decorators: [{
61
+ type: NgModule,
62
+ args: [{}]
63
+ }] });
64
+
65
+ /**
66
+ * @internal
67
+ */
68
+ const SKY_CONFIRM_CONFIG = new InjectionToken('SkyConfirmConfig');
69
+
70
+ /**
71
+ * Specifies content to display in the modal's body.
72
+ */
73
+ class SkyModalContentComponent {
74
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
75
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalContentComponent, isStandalone: true, selector: "sky-modal-content", ngImport: i0, template: "<ng-content></ng-content>\n", styles: ["sky-modal-content{display:block;min-height:100%}.sky-theme-modern sky-modal-content{padding:10px 30px 30px}\n"], encapsulation: i0.ViewEncapsulation.None }); }
76
+ }
77
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalContentComponent, decorators: [{
78
+ type: Component,
79
+ args: [{ standalone: true, selector: 'sky-modal-content', encapsulation: ViewEncapsulation.None, template: "<ng-content></ng-content>\n", styles: ["sky-modal-content{display:block;min-height:100%}.sky-theme-modern sky-modal-content{padding:10px 30px 30px}\n"] }]
80
+ }] });
81
+
82
+ /* istanbul ignore file */
53
83
  /**
54
84
  * NOTICE: DO NOT MODIFY THIS FILE!
55
85
  * The contents of this file were automatically generated by
@@ -75,6 +105,7 @@ const RESOURCES = {
75
105
  skyux_modal_dirty_default_keep_working_text: { message: 'Keep working' },
76
106
  },
77
107
  };
108
+ SkyLibResourcesService.addResources(RESOURCES);
78
109
  class SkyModalsResourcesProvider {
79
110
  getString(localeInfo, name) {
80
111
  return getLibStringForLocale(RESOURCES, localeInfo.locale, name);
@@ -108,158 +139,103 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
108
139
  }]
109
140
  }] });
110
141
 
111
- /**
112
- * Specifies content to display in the modal's body.
113
- */
114
- class SkyModalContentComponent {
115
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
116
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalContentComponent, selector: "sky-modal-content", ngImport: i0, template: "<ng-content></ng-content>\n", styles: ["sky-modal-content{display:block;min-height:100%}.sky-theme-modern sky-modal-content{padding:10px 30px 30px}\n"], encapsulation: i0.ViewEncapsulation.None }); }
117
- }
118
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalContentComponent, decorators: [{
119
- type: Component,
120
- args: [{ selector: 'sky-modal-content', encapsulation: ViewEncapsulation.None, template: "<ng-content></ng-content>\n", styles: ["sky-modal-content{display:block;min-height:100%}.sky-theme-modern sky-modal-content{padding:10px 30px 30px}\n"] }]
121
- }] });
122
-
123
- /**
124
- * @internal
125
- */
126
- class SkyModalErrorsService {
127
- #formErrors = new BehaviorSubject(undefined);
128
- constructor() {
129
- this.formErrors = this.#formErrors.asObservable();
130
- }
131
- updateErrors(value) {
132
- this.#formErrors.next(value);
133
- }
134
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
135
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService }); }
136
- }
137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService, decorators: [{
138
- type: Injectable
139
- }], ctorParameters: function () { return []; } });
140
-
141
- /**
142
- * Specifies content to display in the modal's footer.
143
- */
144
- class SkyModalFooterComponent {
145
- constructor() {
146
- this.errorsSvc = inject(SkyModalErrorsService);
147
- }
148
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
149
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalFooterComponent, selector: "sky-modal-footer", ngImport: i0, template: "<div class=\"sky-modal-footer-container sky-padding-even-large\">\n <div aria-live=\"polite\">\n <div\n *ngIf=\"errorsSvc.formErrors | async as formErrors\"\n class=\"sky-modal-footer-errors sky-margin-stacked-lg\"\n >\n <sky-status-indicator\n *ngFor=\"let formError of formErrors\"\n [ngClass]=\"{\n 'sky-margin-stacked-lg':\n formErrors.indexOf(formError) < formErrors.length - 1,\n 'footer-error': true\n }\"\n descriptionType=\"error\"\n indicatorType=\"danger\"\n >\n {{ formError.message }}\n </sky-status-indicator>\n </div>\n </div>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-modal-footer-container{background-color:#fff;border-top:1px solid #e2e3e4}.sky-modal-footer-container .sky-btn-link:first-child{margin-left:-12px}.sky-modal-footer-container .sky-btn+.sky-btn{margin-left:10px}.sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:-2px}.sky-modal-footer-container .sky-modal-footer-errors{max-height:100px;overflow-y:auto}.sky-modal-footer-container .sky-modal-footer-errors .footer-error{display:block}.sky-theme-modern .sky-modal-footer-container{border-top:none;padding:20px 30px}.sky-theme-modern .sky-modal-footer-container .sky-btn-link:first-child{margin-left:0}.sky-theme-modern .sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:var(--sky-compat-modal-footer-adjacent-btn-btn-link-margin, 10px)}.sky-theme-modern-dark .sky-modal-footer-container{background-color:transparent}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.λ10, selector: "sky-status-indicator", inputs: ["indicatorType", "descriptionType", "customDescription"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None }); }
150
- }
151
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalFooterComponent, decorators: [{
152
- type: Component,
153
- args: [{ selector: 'sky-modal-footer', encapsulation: ViewEncapsulation.None, template: "<div class=\"sky-modal-footer-container sky-padding-even-large\">\n <div aria-live=\"polite\">\n <div\n *ngIf=\"errorsSvc.formErrors | async as formErrors\"\n class=\"sky-modal-footer-errors sky-margin-stacked-lg\"\n >\n <sky-status-indicator\n *ngFor=\"let formError of formErrors\"\n [ngClass]=\"{\n 'sky-margin-stacked-lg':\n formErrors.indexOf(formError) < formErrors.length - 1,\n 'footer-error': true\n }\"\n descriptionType=\"error\"\n indicatorType=\"danger\"\n >\n {{ formError.message }}\n </sky-status-indicator>\n </div>\n </div>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-modal-footer-container{background-color:#fff;border-top:1px solid #e2e3e4}.sky-modal-footer-container .sky-btn-link:first-child{margin-left:-12px}.sky-modal-footer-container .sky-btn+.sky-btn{margin-left:10px}.sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:-2px}.sky-modal-footer-container .sky-modal-footer-errors{max-height:100px;overflow-y:auto}.sky-modal-footer-container .sky-modal-footer-errors .footer-error{display:block}.sky-theme-modern .sky-modal-footer-container{border-top:none;padding:20px 30px}.sky-theme-modern .sky-modal-footer-container .sky-btn-link:first-child{margin-left:0}.sky-theme-modern .sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:var(--sky-compat-modal-footer-adjacent-btn-btn-link-margin, 10px)}.sky-theme-modern-dark .sky-modal-footer-container{background-color:transparent}\n"] }]
154
- }] });
155
-
156
- /**
157
- * Specifies a header for the modal.
158
- */
159
- class SkyModalHeaderComponent {
160
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
161
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalHeaderComponent, selector: "sky-modal-header", ngImport: i0, template: "<h2\n class=\"sky-font-emphasized\"\n [skyThemeClass]=\"{\n 'sky-font-heading-4': 'default',\n 'sky-font-display-3': 'modern'\n }\"\n skyTrim\n>\n <ng-content></ng-content>\n</h2>\n<span class=\"sky-control-help-container\" skyTrim\n ><ng-content select=\".sky-control-help\"></ng-content\n></span>\n", styles: ["h2{margin:0;line-height:1.2;display:inline}:host-context(.sky-theme-modern.sky-theme-mode-dark) h2{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark h2{color:#fbfcfe}\n"], dependencies: [{ kind: "directive", type: i2$1.λ2, selector: "[skyThemeClass]", inputs: ["class", "skyThemeClass"] }, { kind: "directive", type: i2$2.λ4, selector: "[skyTrim]" }] }); }
162
- }
163
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHeaderComponent, decorators: [{
164
- type: Component,
165
- args: [{ selector: 'sky-modal-header', template: "<h2\n class=\"sky-font-emphasized\"\n [skyThemeClass]=\"{\n 'sky-font-heading-4': 'default',\n 'sky-font-display-3': 'modern'\n }\"\n skyTrim\n>\n <ng-content></ng-content>\n</h2>\n<span class=\"sky-control-help-container\" skyTrim\n ><ng-content select=\".sky-control-help\"></ng-content\n></span>\n", styles: ["h2{margin:0;line-height:1.2;display:inline}:host-context(.sky-theme-modern.sky-theme-mode-dark) h2{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark h2{color:#fbfcfe}\n"] }]
166
- }] });
167
-
168
142
  /**
169
143
  * @internal
170
144
  */
171
- class SkyModalAdapterService {
172
- static { this.MODAL_BODY_FULL_CLASS = 'sky-modal-body-full-page'; }
173
- static { this.MODAL_BODY_CLASS = 'sky-modal-body-open'; }
174
- #docRef;
175
- #bodyEl;
176
- #windowRef;
177
- #hostSiblingAriaHiddenCache = new Map();
178
- constructor(windowRef) {
179
- this.#windowRef = windowRef;
180
- this.#docRef = this.#windowRef.nativeWindow.document;
181
- this.#bodyEl = this.#windowRef.nativeWindow.document.body;
182
- }
183
- toggleFullPageModalClass(isAddFull) {
184
- if (isAddFull) {
185
- this.#addClassToBody(SkyModalAdapterService.MODAL_BODY_FULL_CLASS);
186
- }
187
- else {
188
- this.#removeClassFromBody(SkyModalAdapterService.MODAL_BODY_FULL_CLASS);
189
- }
145
+ class SkyModalComponentAdapterService {
146
+ #coreAdapter;
147
+ constructor(coreAdapter) {
148
+ this.#coreAdapter = coreAdapter;
190
149
  }
191
- setPageScroll(isAdd) {
192
- if (isAdd) {
193
- this.#addClassToBody(SkyModalAdapterService.MODAL_BODY_CLASS);
150
+ handleWindowChange(modalEl) {
151
+ const boundedHeightEl = modalEl.nativeElement.querySelector('.sky-modal');
152
+ const fullPageModalEl = modalEl.nativeElement.querySelector('.sky-modal-full-page');
153
+ /*
154
+ Set modal height equal to max height of window (accounting for padding above and below modal)
155
+ */
156
+ const newHeight = window.innerHeight - 40;
157
+ boundedHeightEl.style.maxHeight = newHeight.toString() + 'px';
158
+ if (fullPageModalEl) {
159
+ this.#setFullPageHeight(fullPageModalEl);
194
160
  }
195
161
  else {
196
- this.#removeClassFromBody(SkyModalAdapterService.MODAL_BODY_CLASS);
162
+ /*
163
+ IE11 doesn't handle flex and max-height correctly so we have to explicitly add
164
+ max-height to the content that accounts for standard header and footer height.
165
+ */
166
+ const modalContentEl = modalEl.nativeElement.querySelector('.sky-modal-content');
167
+ const contentHeight = newHeight - 114;
168
+ modalContentEl.style.maxHeight = contentHeight.toString() + 'px';
197
169
  }
198
170
  }
199
- getModalOpener() {
200
- return this.#docRef.activeElement;
171
+ isFocusInFirstItem(event, list) {
172
+ /* istanbul ignore next */
173
+ /* sanity check */
174
+ const eventTarget = event.target || event.srcElement;
175
+ return list.length > 0 && eventTarget === list[0];
201
176
  }
202
- #addClassToBody(className) {
203
- this.#bodyEl.classList.add(className);
177
+ isFocusInLastItem(event, list) {
178
+ /* istanbul ignore next */
179
+ /* sanity check */
180
+ const eventTarget = event.target || event.srcElement;
181
+ return list.length > 0 && eventTarget === list[list.length - 1];
204
182
  }
205
- #removeClassFromBody(className) {
206
- this.#bodyEl.classList.remove(className);
183
+ isModalFocused(event, modalEl) {
184
+ /* istanbul ignore next */
185
+ /* sanity check */
186
+ const eventTarget = event.target || event.srcElement;
187
+ return (modalEl &&
188
+ eventTarget === modalEl.nativeElement.querySelector('.sky-modal-dialog'));
207
189
  }
208
- scrollContentToTop(element) {
209
- element.nativeElement.querySelector('.sky-modal-content').scrollTop = 0;
190
+ focusLastElement(list) {
191
+ if (list.length > 0) {
192
+ list[list.length - 1].focus();
193
+ return true;
194
+ }
195
+ return false;
210
196
  }
211
- /**
212
- * Hides siblings of modal-host from screen readers
213
- * @param hostElRef reference to modal-host element
214
- */
215
- hideHostSiblingsFromScreenReaders(hostElRef) {
216
- const hostElement = hostElRef.nativeElement;
217
- const hostSiblings = hostElement.parentElement.children;
218
- for (let i = 0; i < hostSiblings.length; i++) {
219
- const element = hostSiblings[i];
220
- if (element !== hostElement &&
221
- !element.hasAttribute('aria-live') &&
222
- element.nodeName.toLowerCase() !== 'script' &&
223
- element.nodeName.toLowerCase() !== 'style') {
224
- // preserve previous aria-hidden status of elements outside of modal host
225
- this.#hostSiblingAriaHiddenCache.set(element, element.getAttribute('aria-hidden'));
226
- element.setAttribute('aria-hidden', 'true');
227
- }
197
+ focusFirstElement(list) {
198
+ if (list.length > 0) {
199
+ list[0].focus();
200
+ return true;
228
201
  }
202
+ return false;
229
203
  }
230
- /**
231
- * Restores modal-host siblings to screen reader status prior to modals being opened
232
- */
233
- unhideOrRestoreHostSiblingsFromScreenReaders() {
234
- this.#hostSiblingAriaHiddenCache.forEach((previousValue, element) => {
235
- // if element had aria-hidden status prior, restore status
236
- if (element.parentElement) {
237
- if (previousValue) {
238
- element.setAttribute('aria-hidden', previousValue);
239
- }
240
- else {
241
- element.removeAttribute('aria-hidden');
242
- }
243
- }
244
- });
245
- this.#hostSiblingAriaHiddenCache.clear();
204
+ modalContentHasDirectChildViewkeeper(modalContentEl) {
205
+ return !!modalContentEl.nativeElement.querySelector('sky-modal-content > .sky-viewkeeper-fixed');
246
206
  }
247
- hidePreviousModalFromScreenReaders(topModal) {
248
- if (topModal && topModal.nativeElement.previousElementSibling) {
249
- topModal.nativeElement.previousElementSibling.setAttribute('aria-hidden', 'true');
207
+ modalOpened(modalEl) {
208
+ /* istanbul ignore else */
209
+ /* handle the case where somehow there is a focused element already in the modal */
210
+ if (!(document.activeElement &&
211
+ modalEl.nativeElement.contains(document.activeElement))) {
212
+ const currentScrollX = window.pageXOffset;
213
+ const currentScrollY = window.pageYOffset;
214
+ const inputWithAutofocus = modalEl.nativeElement.querySelector('[autofocus]');
215
+ if (inputWithAutofocus) {
216
+ inputWithAutofocus.focus();
217
+ }
218
+ else {
219
+ this.#coreAdapter.getFocusableChildrenAndApplyFocus(modalEl, '.sky-modal-content', true);
220
+ }
221
+ window.scrollTo(currentScrollX, currentScrollY);
250
222
  }
251
223
  }
252
- unhidePreviousModalFromScreenReaders(topModal) {
253
- if (topModal && topModal.nativeElement.previousElementSibling) {
254
- topModal.nativeElement.previousElementSibling.removeAttribute('aria-hidden');
255
- }
224
+ #setFullPageHeight(fullPageModalEl) {
225
+ const windowHeight = window.innerHeight;
226
+ const fullPageModalStyle = getComputedStyle(fullPageModalEl);
227
+ const marginTopBottom = parseInt(fullPageModalStyle.marginTop, 10) +
228
+ parseInt(fullPageModalStyle.marginBottom, 10);
229
+ const fullPageModalHeight = windowHeight - marginTopBottom + 'px';
230
+ fullPageModalEl.style.height = fullPageModalHeight;
231
+ fullPageModalEl.style.maxHeight = fullPageModalHeight;
256
232
  }
257
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService, deps: [{ token: i2$2.SkyAppWindowRef }], target: i0.ɵɵFactoryTarget.Injectable }); }
258
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService }); }
233
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService, deps: [{ token: i1.SkyCoreAdapterService }], target: i0.ɵɵFactoryTarget.Injectable }); }
234
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService }); }
259
235
  }
260
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService, decorators: [{
236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService, decorators: [{
261
237
  type: Injectable
262
- }], ctorParameters: function () { return [{ type: i2$2.SkyAppWindowRef }]; } });
238
+ }], ctorParameters: function () { return [{ type: i1.SkyCoreAdapterService }]; } });
263
239
 
264
240
  /**
265
241
  * @internal
@@ -275,6 +251,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
275
251
  type: Injectable
276
252
  }], ctorParameters: function () { return []; } });
277
253
 
254
+ /**
255
+ * @internal
256
+ */
257
+ class SkyModalErrorsService {
258
+ #formErrors = new BehaviorSubject(undefined);
259
+ constructor() {
260
+ this.formErrors = this.#formErrors.asObservable();
261
+ }
262
+ updateErrors(value) {
263
+ this.#formErrors.next(value);
264
+ }
265
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
266
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService }); }
267
+ }
268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalErrorsService, decorators: [{
269
+ type: Injectable
270
+ }], ctorParameters: function () { return []; } });
271
+
278
272
  const BASE_Z_INDEX = 1040;
279
273
  const modalHosts = [];
280
274
  /**
@@ -335,215 +329,401 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
335
329
  }], ctorParameters: function () { return []; } });
336
330
 
337
331
  /**
338
- * Provided by the modal service to give the modal host
339
- * component additional context and features.
332
+ * Raises an event when the box shadow for the modal header or footer should be adjusted
333
+ * based on the scroll position of the host element.
340
334
  * @internal
341
335
  */
342
- class SkyModalHostContext {
343
- constructor(args) {
344
- this.args = args;
336
+ class SkyModalScrollShadowDirective {
337
+ constructor() {
338
+ this.skyModalScrollShadow = new EventEmitter();
339
+ this.#ngUnsubscribe = new Subject();
340
+ this.#elRef = inject(ElementRef);
341
+ this.#mutationObserverSvc = inject(SkyMutationObserverService);
342
+ this.#ngZone = inject(NgZone);
343
+ this.#themeSvc = inject(SkyThemeService, { optional: true });
345
344
  }
346
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext, deps: [{ token: 'SkyModalHostContextArgs' }], target: i0.ɵɵFactoryTarget.Injectable }); }
347
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext }); }
348
- }
349
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext, decorators: [{
350
- type: Injectable
351
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
352
- type: Inject,
353
- args: ['SkyModalHostContextArgs']
354
- }] }]; } });
355
-
356
- /**
357
- * @internal
358
- */
359
- class SkyModalHostComponent {
360
- get modalOpen() {
361
- return SkyModalHostService.openModalCount > 0;
345
+ #currentShadow;
346
+ #currentTheme;
347
+ #mutationObserver;
348
+ #ngUnsubscribe;
349
+ #elRef;
350
+ #mutationObserverSvc;
351
+ #ngZone;
352
+ #themeSvc;
353
+ windowResize() {
354
+ this.#checkForShadow();
362
355
  }
363
- get backdropZIndex() {
364
- return SkyModalHostService.backdropZIndex;
356
+ scroll() {
357
+ this.#checkForShadow();
365
358
  }
366
- #adapter;
367
- #environmentInjector = inject(EnvironmentInjector);
368
- #router;
369
- #changeDetector;
370
- #modalHostContext;
371
- #elRef;
372
- #modalInstances = [];
373
- constructor(adapter, changeDetector, modalHostContext, elRef, router) {
374
- this.#adapter = adapter;
375
- this.#router = router;
376
- this.#changeDetector = changeDetector;
377
- this.#modalHostContext = modalHostContext;
378
- this.#elRef = elRef;
359
+ ngOnInit() {
360
+ if (this.#themeSvc) {
361
+ this.#themeSvc.settingsChange
362
+ .pipe(takeUntil(this.#ngUnsubscribe))
363
+ .subscribe((themeSettings) => {
364
+ this.#currentTheme = themeSettings.currentSettings.theme;
365
+ if (this.#currentTheme === SkyTheme.presets.modern) {
366
+ this.#initMutationObserver();
367
+ }
368
+ else {
369
+ this.#emitShadow({
370
+ bottomShadow: 'none',
371
+ topShadow: 'none',
372
+ });
373
+ this.#destroyMutationObserver();
374
+ }
375
+ });
376
+ }
379
377
  }
380
378
  ngOnDestroy() {
381
- // Close all modal instances before disposing of the host container.
382
- this.#closeAllModalInstances();
383
- this.#modalHostContext.args.teardownCallback();
379
+ this.#ngUnsubscribe.next();
380
+ this.#ngUnsubscribe.complete();
381
+ this.#destroyMutationObserver();
384
382
  }
385
- open(modalInstance, component, config) {
386
- /* Ignore coverage as we specify the target element and so the view child should never be undefined unless
387
- * we were to call the `open` method in an early lifecycle hook. */
388
- /* istanbul ignore next */
389
- if (!this.target) {
390
- return;
383
+ #initMutationObserver() {
384
+ if (!this.#mutationObserver) {
385
+ const el = this.#elRef.nativeElement;
386
+ // MutationObserver is patched by Zone.js and therefore becomes part of the
387
+ // Angular change detection cycle, but this can lead to infinite loops in some
388
+ // scenarios. This will keep MutationObserver from triggering change detection.
389
+ this.#ngZone.runOutsideAngular(() => {
390
+ this.#mutationObserver = this.#mutationObserverSvc.create(() => {
391
+ this.#checkForShadow();
392
+ });
393
+ this.#mutationObserver.observe(el, {
394
+ attributes: true,
395
+ characterData: true,
396
+ childList: true,
397
+ subtree: true,
398
+ });
399
+ });
391
400
  }
392
- const params = Object.assign({}, config);
393
- const hostService = new SkyModalHostService();
394
- hostService.fullPage = !!params.fullPage;
395
- const adapter = this.#adapter;
396
- const modalOpener = adapter.getModalOpener();
397
- let isOpen = true;
398
- params.providers ||= [];
399
- params.providers.push({ provide: SkyResizeObserverMediaQueryService }, {
400
- provide: SkyModalHostService,
401
- useValue: hostService,
402
- }, {
403
- provide: SkyModalConfiguration,
404
- useValue: params,
405
- }, {
406
- provide: SkyMediaQueryService,
407
- useExisting: SkyResizeObserverMediaQueryService,
408
- }, {
409
- provide: SKY_STACKING_CONTEXT,
410
- useValue: {
411
- zIndex: new BehaviorSubject(hostService.getModalZIndex())
412
- .asObservable()
413
- .pipe(takeUntil(modalInstance.closed)),
414
- },
415
- });
416
- adapter.setPageScroll(SkyModalHostService.openModalCount > 0);
417
- adapter.toggleFullPageModalClass(SkyModalHostService.fullPageModalCount > 0);
418
- const providers = params.providers || /* istanbul ignore next */ [];
419
- const environmentInjector = createEnvironmentInjector(providers, this.#environmentInjector);
420
- const modalComponentRef = this.target.createComponent(component, {
421
- environmentInjector,
422
- });
423
- // modal element that was just opened
424
- const modalElement = modalComponentRef.location;
425
- modalInstance.adapter = this.#adapter;
426
- modalInstance.componentRef = modalComponentRef;
427
- this.#registerModalInstance(modalInstance);
428
- // hiding all elements at the modal-host level from screen readers when the a modal is opened
429
- this.#adapter.hideHostSiblingsFromScreenReaders(this.#elRef);
430
- if (SkyModalHostService.openModalCount > 1 &&
431
- SkyModalHostService.topModal === hostService) {
432
- // hiding the lower modals when more than one modal is opened
433
- this.#adapter.hidePreviousModalFromScreenReaders(modalElement);
401
+ }
402
+ #destroyMutationObserver() {
403
+ if (this.#mutationObserver) {
404
+ this.#mutationObserver.disconnect();
405
+ this.#mutationObserver = undefined;
434
406
  }
435
- const closeModal = () => {
436
- // unhide siblings if last modal is closing
437
- if (SkyModalHostService.openModalCount === 1) {
438
- this.#adapter.unhideOrRestoreHostSiblingsFromScreenReaders();
439
- }
440
- else if (SkyModalHostService.topModal === hostService) {
441
- // if there are more than 1 modal then unhide the one behind this one before closing it
442
- this.#adapter.unhidePreviousModalFromScreenReaders(modalElement);
443
- }
444
- hostService.destroy();
445
- adapter.setPageScroll(SkyModalHostService.openModalCount > 0);
446
- adapter.toggleFullPageModalClass(SkyModalHostService.fullPageModalCount > 0);
447
- /* istanbul ignore else */
448
- /* sanity check */
449
- if (modalOpener && modalOpener.focus) {
450
- modalOpener.focus();
451
- }
452
- modalComponentRef.destroy();
453
- };
454
- hostService.openHelp.subscribe((helpKey) => {
455
- modalInstance.openHelp(helpKey);
456
- });
457
- hostService.close.subscribe(() => {
458
- modalInstance.close();
459
- });
460
- this.#router?.events.pipe(takeWhile(() => isOpen)).subscribe((event) => {
461
- /* istanbul ignore else */
462
- if (event instanceof NavigationStart) {
463
- modalInstance.close();
464
- }
465
- });
466
- modalInstance.closed.subscribe(() => {
467
- isOpen = false;
468
- this.#unregisterModalInstance(modalInstance);
469
- closeModal();
470
- });
471
- // Necessary if the host was created via a consumer's lifecycle hook such as ngOnInit
472
- this.#changeDetector.detectChanges();
473
407
  }
474
- #registerModalInstance(instance) {
475
- this.#modalInstances.push(instance);
408
+ #checkForShadow() {
409
+ if (this.#currentTheme === SkyTheme.presets.modern) {
410
+ const el = this.#elRef.nativeElement;
411
+ const topShadow = this.#buildShadowStyle(el.scrollTop);
412
+ const bottomShadow = this.#buildShadowStyle(el.scrollHeight - el.scrollTop - el.clientHeight);
413
+ this.#emitShadow({
414
+ bottomShadow,
415
+ topShadow,
416
+ });
417
+ }
476
418
  }
477
- #unregisterModalInstance(instance) {
478
- this.#modalInstances.slice(this.#modalInstances.indexOf(instance), 1);
419
+ #buildShadowStyle(pixelsFromEnd) {
420
+ // Progressively darken the shadow until the user scrolls 30 pixels from the top or bottom
421
+ // of the scrollable element, with a max opacity of 0.3.
422
+ const opacity = Math.min(pixelsFromEnd / 30, 1) * 0.3;
423
+ return opacity > 0 ? `0px 1px 8px 0px rgba(0, 0, 0, ${opacity})` : 'none';
479
424
  }
480
- #closeAllModalInstances() {
481
- for (const instance of this.#modalInstances) {
482
- instance.close();
425
+ #emitShadow(shadow) {
426
+ if (!this.#currentShadow ||
427
+ this.#currentShadow.bottomShadow !== shadow.bottomShadow ||
428
+ this.#currentShadow.topShadow !== shadow.topShadow) {
429
+ this.skyModalScrollShadow.emit(shadow);
430
+ this.#currentShadow = shadow;
483
431
  }
484
432
  }
485
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostComponent, deps: [{ token: SkyModalAdapterService }, { token: i0.ChangeDetectorRef }, { token: SkyModalHostContext }, { token: i0.ElementRef }, { token: i3.Router, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
486
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalHostComponent, selector: "sky-modal-host", viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"sky-modal-host-backdrop\"\n [hidden]=\"!modalOpen\"\n [ngStyle]=\"{\n zIndex: backdropZIndex\n }\"\n></div>\n<div #target></div>\n", styles: [".sky-modal-host-backdrop{background-color:#00000080;position:fixed;inset:0}\n"], dependencies: [{ kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], viewProviders: [SkyModalAdapterService] }); }
433
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalScrollShadowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
434
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalScrollShadowDirective, isStandalone: true, selector: "[skyModalScrollShadow]", outputs: { skyModalScrollShadow: "skyModalScrollShadow" }, host: { listeners: { "window:resize": "windowResize()", "scroll": "scroll()" } }, ngImport: i0 }); }
487
435
  }
488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostComponent, decorators: [{
489
- type: Component,
490
- args: [{ selector: 'sky-modal-host', viewProviders: [SkyModalAdapterService], template: "<div\n class=\"sky-modal-host-backdrop\"\n [hidden]=\"!modalOpen\"\n [ngStyle]=\"{\n zIndex: backdropZIndex\n }\"\n></div>\n<div #target></div>\n", styles: [".sky-modal-host-backdrop{background-color:#00000080;position:fixed;inset:0}\n"] }]
491
- }], ctorParameters: function () { return [{ type: SkyModalAdapterService }, { type: i0.ChangeDetectorRef }, { type: SkyModalHostContext }, { type: i0.ElementRef }, { type: i3.Router, decorators: [{
492
- type: Optional
493
- }] }]; }, propDecorators: { target: [{
494
- type: ViewChild,
495
- args: ['target', {
496
- read: ViewContainerRef,
497
- static: true,
498
- }]
436
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalScrollShadowDirective, decorators: [{
437
+ type: Directive,
438
+ args: [{
439
+ standalone: true,
440
+ selector: '[skyModalScrollShadow]',
441
+ }]
442
+ }], propDecorators: { skyModalScrollShadow: [{
443
+ type: Output
444
+ }], windowResize: [{
445
+ type: HostListener,
446
+ args: ['window:resize']
447
+ }], scroll: [{
448
+ type: HostListener,
449
+ args: ['scroll']
499
450
  }] } });
500
451
 
452
+ const ARIA_ROLE_DEFAULT = 'dialog';
501
453
  /**
502
- * @internal
503
- */
504
- const SKY_CONFIRM_CONFIG = new InjectionToken('SkyConfirmConfig');
505
-
506
- /**
507
- * Properties about the modal close action and a method to close the modal.
508
- */
509
- class SkyModalBeforeCloseHandler {
510
- constructor(closeModal, closeArgs) {
511
- this.closeArgs = closeArgs;
512
- this.closeModal = closeModal;
513
- }
514
- }
515
-
516
- /**
517
- * Contains an object with the data passed from users when
518
- * a modal is closed and the reason that the modal was closed.
454
+ * Provides a common look-and-feel for modal content with options to display
455
+ * a common modal header, specify body content, and display a common modal footer
456
+ * and buttons.
519
457
  */
520
- class SkyModalCloseArgs {
521
- }
522
-
523
- class SkyModalInstance {
458
+ class SkyModalComponent {
524
459
  /**
525
- * An event that the modal instance emits when it is about to close.
526
- * It emits a `SkyModalBeforeCloseHandler` object with a `closeModal` method
527
- * that closes the modal. If a subscription exists for this event,
528
- * the modal does not close until the subscriber calls the `closeModal` method.
460
+ * A list of form-level errors to display to the user.
529
461
  */
530
- get beforeClose() {
531
- return this.#_beforeClose;
462
+ set formErrors(value) {
463
+ this.#errorsSvc.updateErrors(value);
532
464
  }
533
465
  /**
534
- * An event that the modal instance emits when it closes.
535
- * It emits a `SkyModalCloseArgs` object with a `data` property that includes
536
- * data passed from users on close or save and a `reason` property that indicates
537
- * whether the modal was saved or closed without saving.
538
- * The `reason` property accepts any string value.
539
- * Common examples include `"cancel"`, `"close"`, and `"save"`.
466
+ * @internal
540
467
  */
541
- get closed() {
542
- return this.#_closed;
468
+ set ariaRole(value) {
469
+ this.ariaRoleOrDefault = value || ARIA_ROLE_DEFAULT;
543
470
  }
544
471
  /**
545
- * An event that the modal instance emits when users click
546
- * the <i class="fa fa-question-circle" aria-hidden="true"></i> button.
472
+ * @internal
473
+ */
474
+ set ariaDescribedBy(id) {
475
+ this.#_ariaDescribedBy = id;
476
+ }
477
+ get ariaDescribedBy() {
478
+ return this.#_ariaDescribedBy;
479
+ }
480
+ /**
481
+ * @internal
482
+ */
483
+ set ariaLabelledBy(id) {
484
+ this.#_ariaLabelledBy = id;
485
+ }
486
+ get ariaLabelledBy() {
487
+ return this.#_ariaLabelledBy;
488
+ }
489
+ #ngUnsubscribe;
490
+ #_ariaDescribedBy;
491
+ #_ariaLabelledBy;
492
+ #changeDetector;
493
+ #componentAdapter;
494
+ #coreAdapter;
495
+ #dockService;
496
+ #elRef;
497
+ #errorsSvc;
498
+ #hostService;
499
+ #liveAnnouncerSvc;
500
+ #mediaQueryService;
501
+ #windowRef;
502
+ /**
503
+ * This provider is optional to account for situations where a modal component
504
+ * is implemented without the modal service. For example, when a consumer tests
505
+ * a component that uses the modal component but doesn't launch the modal from
506
+ * the modal service before executing assertions.
507
+ */
508
+ #config;
509
+ constructor() {
510
+ this.ariaRoleOrDefault = ARIA_ROLE_DEFAULT;
511
+ this.ariaOwns = null;
512
+ this.modalState = 'in';
513
+ this.#ngUnsubscribe = new Subject();
514
+ this.#changeDetector = inject(ChangeDetectorRef);
515
+ this.#componentAdapter = inject(SkyModalComponentAdapterService);
516
+ this.#coreAdapter = inject(SkyCoreAdapterService);
517
+ this.#dockService = inject(SkyDockService, { host: true });
518
+ this.#elRef = inject(ElementRef);
519
+ this.#errorsSvc = inject(SkyModalErrorsService);
520
+ this.#hostService = inject(SkyModalHostService);
521
+ this.#liveAnnouncerSvc = inject(SkyLiveAnnouncerService);
522
+ this.#mediaQueryService = inject(SkyResizeObserverMediaQueryService, {
523
+ optional: true,
524
+ });
525
+ this.#windowRef = inject(SkyAppWindowRef);
526
+ /**
527
+ * This provider is optional to account for situations where a modal component
528
+ * is implemented without the modal service. For example, when a consumer tests
529
+ * a component that uses the modal component but doesn't launch the modal from
530
+ * the modal service before executing assertions.
531
+ */
532
+ this.#config = inject(SkyModalConfiguration, { optional: true }) ??
533
+ new SkyModalConfiguration();
534
+ this.ariaDescribedBy = this.#config.ariaDescribedBy;
535
+ this.ariaLabelledBy = this.#config.ariaLabelledBy;
536
+ this.ariaRole = this.#config.ariaRole;
537
+ this.helpKey = this.#config.helpKey;
538
+ this.tiledBody = this.#config.tiledBody;
539
+ this.wrapperClass = this.#config.wrapperClass;
540
+ this.size = this.#config.fullPage
541
+ ? 'full-page'
542
+ : this.#config.size?.toLowerCase() || 'medium';
543
+ this.modalZIndex = this.#hostService.zIndex;
544
+ }
545
+ onDocumentKeyUp(event) {
546
+ /* istanbul ignore else */
547
+ /* sanity check */
548
+ if (SkyModalHostService.openModalCount > 0) {
549
+ const topModal = SkyModalHostService.topModal;
550
+ if (topModal && topModal === this.#hostService) {
551
+ if (event.which === 27) {
552
+ // Escape key up
553
+ event.preventDefault();
554
+ this.closeButtonClick();
555
+ }
556
+ }
557
+ }
558
+ }
559
+ onDocumentKeyDown(event) {
560
+ /* istanbul ignore else */
561
+ /* sanity check */
562
+ if (SkyModalHostService.openModalCount > 0) {
563
+ const topModal = SkyModalHostService.topModal;
564
+ if (topModal && topModal === this.#hostService) {
565
+ if (event.which === 9) {
566
+ // Tab pressed
567
+ let focusChanged = false;
568
+ const focusElementList = this.#coreAdapter.getFocusableChildren(this.#elRef.nativeElement);
569
+ if (event.shiftKey &&
570
+ (this.#componentAdapter.isFocusInFirstItem(event, focusElementList) ||
571
+ this.#componentAdapter.isModalFocused(event, this.#elRef))) {
572
+ focusChanged =
573
+ this.#componentAdapter.focusLastElement(focusElementList);
574
+ }
575
+ else if (!event.shiftKey &&
576
+ this.#componentAdapter.isFocusInLastItem(event, focusElementList)) {
577
+ focusChanged =
578
+ this.#componentAdapter.focusFirstElement(focusElementList);
579
+ }
580
+ if (focusChanged) {
581
+ event.preventDefault();
582
+ event.stopPropagation();
583
+ }
584
+ }
585
+ }
586
+ }
587
+ }
588
+ ngOnInit() {
589
+ this.#liveAnnouncerSvc.announcerElementChanged
590
+ .pipe(takeUntil(this.#ngUnsubscribe))
591
+ .subscribe((element) => {
592
+ if (element?.id) {
593
+ this.ariaOwns = element.id;
594
+ this.#changeDetector.markForCheck();
595
+ }
596
+ });
597
+ }
598
+ ngAfterViewInit() {
599
+ this.#componentAdapter.handleWindowChange(this.#elRef);
600
+ // Adding a timeout to avoid ExpressionChangedAfterItHasBeenCheckedError.
601
+ // https://stackoverflow.com/questions/40562845
602
+ this.#windowRef.nativeWindow.setTimeout(() => {
603
+ this.#componentAdapter.modalOpened(this.#elRef);
604
+ });
605
+ this.#dockService.setDockOptions({
606
+ location: SkyDockLocation.ElementBottom,
607
+ referenceEl: this.modalContentWrapperElement.nativeElement,
608
+ zIndex: 5,
609
+ });
610
+ /* istanbul ignore next */
611
+ if (this.#mediaQueryService) {
612
+ this.#mediaQueryService.observe(this.modalContentWrapperElement, {
613
+ updateResponsiveClasses: true,
614
+ });
615
+ }
616
+ }
617
+ ngOnDestroy() {
618
+ /* istanbul ignore next */
619
+ if (this.#mediaQueryService) {
620
+ this.#mediaQueryService.unobserve();
621
+ }
622
+ this.#ngUnsubscribe.next();
623
+ this.#ngUnsubscribe.complete();
624
+ }
625
+ helpButtonClick() {
626
+ if (this.helpKey) {
627
+ this.#hostService.onOpenHelp(this.helpKey);
628
+ }
629
+ }
630
+ closeButtonClick() {
631
+ this.#hostService.onClose();
632
+ }
633
+ windowResize() {
634
+ this.#componentAdapter.handleWindowChange(this.#elRef);
635
+ }
636
+ scrollShadowChange(args) {
637
+ this.scrollShadow = args;
638
+ }
639
+ viewkeeperEnabled() {
640
+ return this.#componentAdapter.modalContentHasDirectChildViewkeeper(this.#elRef);
641
+ }
642
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
643
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalComponent, isStandalone: true, selector: "sky-modal", inputs: { formErrors: "formErrors", ariaRole: "ariaRole", tiledBody: "tiledBody", ariaDescribedBy: "ariaDescribedBy", ariaLabelledBy: "ariaLabelledBy" }, host: { listeners: { "document:keyup": "onDocumentKeyUp($event)", "document:keydown": "onDocumentKeyDown($event)" }, properties: { "class": "this.wrapperClass" } }, providers: [
644
+ SkyModalComponentAdapterService,
645
+ SkyModalErrorsService,
646
+ SkyDockService,
647
+ ], viewQueries: [{ propertyName: "modalContentWrapperElement", first: true, predicate: ["modalContentWrapper"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"sky-modal-dialog\"\n aria-modal=\"true\"\n [attr.aria-describedby]=\"ariaDescribedBy || modalContentId.id\"\n [attr.aria-labelledby]=\"ariaLabelledBy || headerId.id\"\n [attr.aria-owns]=\"ariaOwns\"\n [attr.role]=\"ariaRoleOrDefault\"\n (window:resize)=\"windowResize()\"\n>\n <div\n class=\"sky-modal sky-shadow sky-box sky-elevation-16 sky-modal-{{ size }}\"\n tabindex=\"-1\"\n [ngClass]=\"{\n 'sky-modal-tiled': tiledBody,\n 'sky-modal-viewkeeper': viewkeeperEnabled()\n }\"\n [ngStyle]=\"{\n zIndex: modalZIndex\n }\"\n >\n <div\n class=\"sky-modal-header\"\n [hidden]=\"!headerContent || !headerContent.children || headerContent.children.length &lt; 1\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.topShadow\n }\"\n >\n <div\n class=\"sky-modal-header-content\"\n skyId\n [ngClass]=\"{\n 'sky-font-heading-2': size === 'full-page'\n }\"\n #headerContent\n #headerId=\"skyId\"\n >\n <ng-content select=\"sky-modal-header\"></ng-content>\n </div>\n <div class=\"sky-modal-header-buttons\">\n <button\n *ngIf=\"helpKey\"\n class=\"sky-btn sky-modal-btn-help\"\n name=\"help-button\"\n type=\"button\"\n [attr.aria-label]=\"'skyux_modal_open_help' | skyLibResources\"\n (click)=\"helpButtonClick()\"\n >\n <sky-icon icon=\"question-circle\"></sky-icon>\n </button>\n\n <button\n type=\"button\"\n class=\"sky-btn sky-modal-btn-close\"\n [attr.aria-label]=\"'skyux_modal_close' | skyLibResources\"\n (click)=\"closeButtonClick()\"\n >\n <sky-icon icon=\"close\"></sky-icon>\n </button>\n </div>\n </div>\n <div\n class=\"sky-modal-content sky-padding-even-large\"\n role=\"region\"\n tabindex=\"0\"\n skyId\n [attr.aria-labelledby]=\"headerId.id\"\n (skyModalScrollShadow)=\"scrollShadowChange($event)\"\n #modalContentId=\"skyId\"\n #modalContentWrapper\n >\n <ng-content select=\"sky-modal-content\"></ng-content>\n </div>\n <div\n class=\"sky-modal-footer\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.bottomShadow\n }\"\n >\n <ng-content select=\"sky-modal-footer\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [".sky-modal{border-top:1px solid #cdcfd2;border-bottom:1px solid #cdcfd2;border-left:1px solid #cdcfd2;border-right:1px solid #cdcfd2;position:fixed;width:auto;left:0;right:0;top:20px;margin:10px;display:flex;flex-direction:column;overflow:hidden}.sky-modal:focus{outline:none}@media (min-width: 768px){.sky-modal:not(.sky-modal-large){margin:0 auto}.sky-modal-small{width:300px}.sky-modal-small .sky-modal-content,.sky-modal-small .sky-modal-header,.sky-modal-small .sky-modal-footer{max-width:300px}.sky-modal-medium{width:600px}.sky-modal-medium .sky-modal-content,.sky-modal-medium .sky-modal-header,.sky-modal-medium .sky-modal-footer{max-width:600px}}@media (min-width: 920px){.sky-modal-large{margin:0 auto;width:900px}.sky-modal-large .sky-modal-content,.sky-modal-large .sky-modal-header,.sky-modal-large .sky-modal-footer{max-width:900px}}.sky-modal-content{background-color:#fff;--sky-background-color-page-default: #fff}.sky-modal-content:focus{outline-style:dotted;outline-width:thin;outline-offset:-1px}.sky-modal-tiled .sky-modal-content{background-color:#eeeeef;--sky-background-color-page-default: $sky-background-color-neutral-light}.sky-modal-tiled .sky-modal-content ::ng-deep .sky-tile-title{font-family:BLKB Sans,Helvetica Neue,Arial,sans-serif;color:var(--sky-text-color-deemphasized);font-weight:300;font-size:19px}.sky-modal-header{padding:9px 3px 9px 15px;background-color:#fff;display:flex;align-items:baseline;border-bottom:1px solid #e2e3e4}.sky-modal-header-buttons{flex-shrink:.0001}.sky-modal-header-buttons .sky-btn{border:none;color:#cdcfd2;cursor:pointer}.sky-modal-header-buttons .sky-btn:hover{color:#979ba2;transition:color .15s}.sky-modal-header-content{flex-grow:1}.sky-modal-header{flex-shrink:0;z-index:2}.sky-modal-content{overflow-y:auto}.sky-modal-footer{flex-shrink:0;z-index:2}.sky-modal-full-page{width:100%;top:0;margin:0}.sky-modal-full-page .sky-modal-header-buttons sky-icon[icon=close]{font-size:20px}.sky-modal-full-page .sky-modal-content{flex-grow:1}:host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-15px}.sky-modal-content>::ng-deep sky-dock{bottom:-15px;margin-left:-15px;margin-bottom:-15px;padding-top:15px;width:calc(100% + 30px)}:host-context(.sky-theme-modern) .sky-modal-header{border:none;padding:20px 30px}:host-context(.sky-theme-modern) .sky-modal-btn-help,:host-context(.sky-theme-modern) .sky-modal-btn-close{display:none}:host-context(.sky-theme-modern) .sky-modal-content{padding:0}:host-context(.sky-theme-modern) .sky-modal-full-page{width:calc(100% - 60px);margin:30px}:host-context(.sky-theme-modern) .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}:host-context(.sky-theme-modern) :host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-10px -30px -30px}.sky-theme-modern .sky-modal-header{border:none;padding:20px 30px}.sky-theme-modern .sky-modal-btn-help,.sky-theme-modern .sky-modal-btn-close{display:none}.sky-theme-modern .sky-modal-content{padding:0}.sky-theme-modern .sky-modal-full-page{width:calc(100% - 60px);margin:30px}.sky-theme-modern .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}.sky-theme-modern :host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-10px -30px -30px}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal{border-color:#121212}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header{color:#fbfcfe}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header,:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}.sky-theme-modern.sky-theme-mode-dark .sky-modal{border-color:#121212}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header,.sky-theme-modern.sky-theme-mode-dark .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: SkyIconModule }, { kind: "component", type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }, { kind: "ngmodule", type: SkyIdModule }, { kind: "directive", type: i1.λ2, selector: "[skyId]", exportAs: ["skyId"] }, { kind: "directive", type: SkyModalScrollShadowDirective, selector: "[skyModalScrollShadow]", outputs: ["skyModalScrollShadow"] }, { kind: "ngmodule", type: SkyModalsResourcesModule }, { kind: "pipe", type: i2$1.SkyLibResourcesPipe, name: "skyLibResources" }] }); }
648
+ }
649
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponent, decorators: [{
650
+ type: Component,
651
+ args: [{ standalone: true, selector: 'sky-modal', providers: [
652
+ SkyModalComponentAdapterService,
653
+ SkyModalErrorsService,
654
+ SkyDockService,
655
+ ], imports: [
656
+ CommonModule,
657
+ SkyIconModule,
658
+ SkyIdModule,
659
+ SkyModalScrollShadowDirective,
660
+ SkyModalsResourcesModule,
661
+ ], template: "<div\n class=\"sky-modal-dialog\"\n aria-modal=\"true\"\n [attr.aria-describedby]=\"ariaDescribedBy || modalContentId.id\"\n [attr.aria-labelledby]=\"ariaLabelledBy || headerId.id\"\n [attr.aria-owns]=\"ariaOwns\"\n [attr.role]=\"ariaRoleOrDefault\"\n (window:resize)=\"windowResize()\"\n>\n <div\n class=\"sky-modal sky-shadow sky-box sky-elevation-16 sky-modal-{{ size }}\"\n tabindex=\"-1\"\n [ngClass]=\"{\n 'sky-modal-tiled': tiledBody,\n 'sky-modal-viewkeeper': viewkeeperEnabled()\n }\"\n [ngStyle]=\"{\n zIndex: modalZIndex\n }\"\n >\n <div\n class=\"sky-modal-header\"\n [hidden]=\"!headerContent || !headerContent.children || headerContent.children.length &lt; 1\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.topShadow\n }\"\n >\n <div\n class=\"sky-modal-header-content\"\n skyId\n [ngClass]=\"{\n 'sky-font-heading-2': size === 'full-page'\n }\"\n #headerContent\n #headerId=\"skyId\"\n >\n <ng-content select=\"sky-modal-header\"></ng-content>\n </div>\n <div class=\"sky-modal-header-buttons\">\n <button\n *ngIf=\"helpKey\"\n class=\"sky-btn sky-modal-btn-help\"\n name=\"help-button\"\n type=\"button\"\n [attr.aria-label]=\"'skyux_modal_open_help' | skyLibResources\"\n (click)=\"helpButtonClick()\"\n >\n <sky-icon icon=\"question-circle\"></sky-icon>\n </button>\n\n <button\n type=\"button\"\n class=\"sky-btn sky-modal-btn-close\"\n [attr.aria-label]=\"'skyux_modal_close' | skyLibResources\"\n (click)=\"closeButtonClick()\"\n >\n <sky-icon icon=\"close\"></sky-icon>\n </button>\n </div>\n </div>\n <div\n class=\"sky-modal-content sky-padding-even-large\"\n role=\"region\"\n tabindex=\"0\"\n skyId\n [attr.aria-labelledby]=\"headerId.id\"\n (skyModalScrollShadow)=\"scrollShadowChange($event)\"\n #modalContentId=\"skyId\"\n #modalContentWrapper\n >\n <ng-content select=\"sky-modal-content\"></ng-content>\n </div>\n <div\n class=\"sky-modal-footer\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.bottomShadow\n }\"\n >\n <ng-content select=\"sky-modal-footer\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [".sky-modal{border-top:1px solid #cdcfd2;border-bottom:1px solid #cdcfd2;border-left:1px solid #cdcfd2;border-right:1px solid #cdcfd2;position:fixed;width:auto;left:0;right:0;top:20px;margin:10px;display:flex;flex-direction:column;overflow:hidden}.sky-modal:focus{outline:none}@media (min-width: 768px){.sky-modal:not(.sky-modal-large){margin:0 auto}.sky-modal-small{width:300px}.sky-modal-small .sky-modal-content,.sky-modal-small .sky-modal-header,.sky-modal-small .sky-modal-footer{max-width:300px}.sky-modal-medium{width:600px}.sky-modal-medium .sky-modal-content,.sky-modal-medium .sky-modal-header,.sky-modal-medium .sky-modal-footer{max-width:600px}}@media (min-width: 920px){.sky-modal-large{margin:0 auto;width:900px}.sky-modal-large .sky-modal-content,.sky-modal-large .sky-modal-header,.sky-modal-large .sky-modal-footer{max-width:900px}}.sky-modal-content{background-color:#fff;--sky-background-color-page-default: #fff}.sky-modal-content:focus{outline-style:dotted;outline-width:thin;outline-offset:-1px}.sky-modal-tiled .sky-modal-content{background-color:#eeeeef;--sky-background-color-page-default: $sky-background-color-neutral-light}.sky-modal-tiled .sky-modal-content ::ng-deep .sky-tile-title{font-family:BLKB Sans,Helvetica Neue,Arial,sans-serif;color:var(--sky-text-color-deemphasized);font-weight:300;font-size:19px}.sky-modal-header{padding:9px 3px 9px 15px;background-color:#fff;display:flex;align-items:baseline;border-bottom:1px solid #e2e3e4}.sky-modal-header-buttons{flex-shrink:.0001}.sky-modal-header-buttons .sky-btn{border:none;color:#cdcfd2;cursor:pointer}.sky-modal-header-buttons .sky-btn:hover{color:#979ba2;transition:color .15s}.sky-modal-header-content{flex-grow:1}.sky-modal-header{flex-shrink:0;z-index:2}.sky-modal-content{overflow-y:auto}.sky-modal-footer{flex-shrink:0;z-index:2}.sky-modal-full-page{width:100%;top:0;margin:0}.sky-modal-full-page .sky-modal-header-buttons sky-icon[icon=close]{font-size:20px}.sky-modal-full-page .sky-modal-content{flex-grow:1}:host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-15px}.sky-modal-content>::ng-deep sky-dock{bottom:-15px;margin-left:-15px;margin-bottom:-15px;padding-top:15px;width:calc(100% + 30px)}:host-context(.sky-theme-modern) .sky-modal-header{border:none;padding:20px 30px}:host-context(.sky-theme-modern) .sky-modal-btn-help,:host-context(.sky-theme-modern) .sky-modal-btn-close{display:none}:host-context(.sky-theme-modern) .sky-modal-content{padding:0}:host-context(.sky-theme-modern) .sky-modal-full-page{width:calc(100% - 60px);margin:30px}:host-context(.sky-theme-modern) .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}:host-context(.sky-theme-modern) :host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-10px -30px -30px}.sky-theme-modern .sky-modal-header{border:none;padding:20px 30px}.sky-theme-modern .sky-modal-btn-help,.sky-theme-modern .sky-modal-btn-close{display:none}.sky-theme-modern .sky-modal-content{padding:0}.sky-theme-modern .sky-modal-full-page{width:calc(100% - 60px);margin:30px}.sky-theme-modern .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}.sky-theme-modern :host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-10px -30px -30px}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal{border-color:#121212}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header{color:#fbfcfe}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header,:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}.sky-theme-modern.sky-theme-mode-dark .sky-modal{border-color:#121212}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header,.sky-theme-modern.sky-theme-mode-dark .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}\n"] }]
662
+ }], ctorParameters: function () { return []; }, propDecorators: { wrapperClass: [{
663
+ type: HostBinding,
664
+ args: ['class']
665
+ }], formErrors: [{
666
+ type: Input
667
+ }], ariaRole: [{
668
+ type: Input
669
+ }], tiledBody: [{
670
+ type: Input
671
+ }], ariaDescribedBy: [{
672
+ type: Input
673
+ }], ariaLabelledBy: [{
674
+ type: Input
675
+ }], modalContentWrapperElement: [{
676
+ type: ViewChild,
677
+ args: ['modalContentWrapper', { read: ElementRef }]
678
+ }], onDocumentKeyUp: [{
679
+ type: HostListener,
680
+ args: ['document:keyup', ['$event']]
681
+ }], onDocumentKeyDown: [{
682
+ type: HostListener,
683
+ args: ['document:keydown', ['$event']]
684
+ }] } });
685
+
686
+ /**
687
+ * Properties about the modal close action and a method to close the modal.
688
+ */
689
+ class SkyModalBeforeCloseHandler {
690
+ constructor(closeModal, closeArgs) {
691
+ this.closeArgs = closeArgs;
692
+ this.closeModal = closeModal;
693
+ }
694
+ }
695
+
696
+ /**
697
+ * Contains an object with the data passed from users when
698
+ * a modal is closed and the reason that the modal was closed.
699
+ */
700
+ class SkyModalCloseArgs {
701
+ }
702
+
703
+ class SkyModalInstance {
704
+ /**
705
+ * An event that the modal instance emits when it is about to close.
706
+ * It emits a `SkyModalBeforeCloseHandler` object with a `closeModal` method
707
+ * that closes the modal. If a subscription exists for this event,
708
+ * the modal does not close until the subscriber calls the `closeModal` method.
709
+ */
710
+ get beforeClose() {
711
+ return this.#_beforeClose;
712
+ }
713
+ /**
714
+ * An event that the modal instance emits when it closes.
715
+ * It emits a `SkyModalCloseArgs` object with a `data` property that includes
716
+ * data passed from users on close or save and a `reason` property that indicates
717
+ * whether the modal was saved or closed without saving.
718
+ * The `reason` property accepts any string value.
719
+ * Common examples include `"cancel"`, `"close"`, and `"save"`.
720
+ */
721
+ get closed() {
722
+ return this.#_closed;
723
+ }
724
+ /**
725
+ * An event that the modal instance emits when users click
726
+ * the <i class="fa fa-question-circle" aria-hidden="true"></i> button.
547
727
  * If a `helpKey` parameter was specified, the `helpOpened` event broadcasts the `helpKey`.
548
728
  */
549
729
  get helpOpened() {
@@ -640,559 +820,370 @@ class SkyModalInstance {
640
820
  }
641
821
  }
642
822
 
643
- /**
644
- * @internal
645
- */
646
- class SkyModalComponentAdapterService {
647
- #coreAdapter;
648
- constructor(coreAdapter) {
649
- this.#coreAdapter = coreAdapter;
650
- }
651
- handleWindowChange(modalEl) {
652
- const boundedHeightEl = modalEl.nativeElement.querySelector('.sky-modal');
653
- const fullPageModalEl = modalEl.nativeElement.querySelector('.sky-modal-full-page');
654
- /*
655
- Set modal height equal to max height of window (accounting for padding above and below modal)
656
- */
657
- const newHeight = window.innerHeight - 40;
658
- boundedHeightEl.style.maxHeight = newHeight.toString() + 'px';
659
- if (fullPageModalEl) {
660
- this.#setFullPageHeight(fullPageModalEl);
823
+ class SkyConfirmComponent {
824
+ #config;
825
+ #modal;
826
+ #resourcesService;
827
+ constructor(config, modal, resourcesService, idService) {
828
+ this.preserveWhiteSpace = false;
829
+ this.isOkType = false;
830
+ this.#config = config;
831
+ this.#modal = modal;
832
+ this.#resourcesService = resourcesService;
833
+ if (config.type === SkyConfirmType.Custom &&
834
+ config.buttons &&
835
+ config.buttons.length > 0) {
836
+ this.buttons = this.#getCustomButtons(config.buttons);
661
837
  }
662
838
  else {
663
- /*
664
- IE11 doesn't handle flex and max-height correctly so we have to explicitly add
665
- max-height to the content that accounts for standard header and footer height.
666
- */
667
- const modalContentEl = modalEl.nativeElement.querySelector('.sky-modal-content');
668
- const contentHeight = newHeight - 114;
669
- modalContentEl.style.maxHeight = contentHeight.toString() + 'px';
839
+ this.#getPresetButtons()
840
+ .pipe(take(1))
841
+ .subscribe((buttons) => {
842
+ this.buttons = buttons;
843
+ });
670
844
  }
845
+ this.message = config.message;
846
+ this.body = config.body;
847
+ // Using the service here instead of the directive due to the confirm component's "body" container being conditional and thus a template variable being unavailable at an outer scope
848
+ this.bodyId = idService.generateId();
849
+ this.preserveWhiteSpace = !!config.preserveWhiteSpace;
850
+ this.isOkType = config.type === SkyConfirmType.OK;
671
851
  }
672
- isFocusInFirstItem(event, list) {
673
- /* istanbul ignore next */
674
- /* sanity check */
675
- const eventTarget = event.target || event.srcElement;
676
- return list.length > 0 && eventTarget === list[0];
852
+ close(button) {
853
+ const result = {
854
+ action: button.action,
855
+ };
856
+ this.#modal.close(result);
677
857
  }
678
- isFocusInLastItem(event, list) {
679
- /* istanbul ignore next */
680
- /* sanity check */
681
- const eventTarget = event.target || event.srcElement;
682
- return list.length > 0 && eventTarget === list[list.length - 1];
858
+ #getPresetButtons() {
859
+ const emitter = new ReplaySubject(1);
860
+ this.#resourcesService
861
+ .getStrings({
862
+ cancel: 'skyux_confirm_dialog_default_cancel_text',
863
+ no: 'skyux_confirm_dialog_default_no_text',
864
+ ok: 'skyux_confirm_dialog_default_ok_text',
865
+ yes: 'skyux_confirm_dialog_default_yes_text',
866
+ })
867
+ .subscribe((values) => {
868
+ const confirmButtons = [];
869
+ switch (this.#config.type) {
870
+ case SkyConfirmType.YesNoCancel:
871
+ case SkyConfirmType.YesCancel:
872
+ confirmButtons.push({
873
+ text: values.yes,
874
+ autofocus: true,
875
+ styleType: 'primary',
876
+ action: 'yes',
877
+ });
878
+ if (this.#config.type === SkyConfirmType.YesNoCancel) {
879
+ confirmButtons.push({
880
+ text: values.no,
881
+ styleType: 'default',
882
+ action: 'no',
883
+ });
884
+ }
885
+ confirmButtons.push({
886
+ text: values.cancel,
887
+ styleType: 'link',
888
+ action: 'cancel',
889
+ });
890
+ break;
891
+ default:
892
+ confirmButtons.push({
893
+ text: values.ok,
894
+ autofocus: true,
895
+ styleType: 'primary',
896
+ action: 'ok',
897
+ });
898
+ }
899
+ emitter.next(confirmButtons);
900
+ });
901
+ return emitter.asObservable();
683
902
  }
684
- isModalFocused(event, modalEl) {
685
- /* istanbul ignore next */
686
- /* sanity check */
687
- const eventTarget = event.target || event.srcElement;
688
- return (modalEl &&
689
- eventTarget === modalEl.nativeElement.querySelector('.sky-modal-dialog'));
903
+ #getCustomButtons(buttonConfig) {
904
+ return buttonConfig.map((config) => ({
905
+ text: config.text,
906
+ action: config.action,
907
+ styleType: config.styleType || 'default',
908
+ autofocus: config.autofocus || false,
909
+ }));
690
910
  }
691
- focusLastElement(list) {
692
- if (list.length > 0) {
693
- list[list.length - 1].focus();
694
- return true;
911
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmComponent, deps: [{ token: SKY_CONFIRM_CONFIG }, { token: SkyModalInstance }, { token: i2$1.SkyLibResourcesService }, { token: i1.SkyIdService }], target: i0.ɵɵFactoryTarget.Component }); }
912
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyConfirmComponent, isStandalone: true, selector: "sky-confirm", ngImport: i0, template: "<div class=\"sky-confirm\" [ngClass]=\"{ 'sky-confirm-type-ok': isOkType }\">\n <sky-modal\n ariaRole=\"alertdialog\"\n [ariaLabelledBy]=\"confirmMessage.id\"\n [ariaDescribedBy]=\"body ? bodyId : undefined\"\n >\n <sky-modal-content class=\"sky-confirm-content\">\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n class=\"sky-confirm-message\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n [skyThemeClass]=\"{\n 'sky-font-display-4': 'default',\n 'sky-font-heading-1 sky-font-display-3': 'modern'\n }\"\n skyId\n #confirmMessage=\"skyId\"\n >{{ message }}</div\n >\n\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n *ngIf=\"body\"\n class=\"sky-confirm-body\"\n [id]=\"bodyId\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n >{{ body }}</div\n >\n\n <div class=\"sky-confirm-buttons\">\n <button\n *ngFor=\"let button of buttons\"\n type=\"button\"\n class=\"sky-btn\"\n [ngClass]=\"'sky-btn-' + button.styleType\"\n [skyThemeClass]=\"{\n 'sky-margin-inline-sm': 'modern',\n 'sky-margin-inline-compact': 'default'\n }\"\n (click)=\"close(button)\"\n [attr.autofocus]=\"button.autofocus ? 'autofocus' : null\"\n >\n {{ button.text }}\n </button>\n </div>\n </sky-modal-content>\n </sky-modal>\n</div>\n", styles: [".sky-confirm{--sky-confirm-body-margin-top: var(--sky-margin-stacked-sm);--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-xl);--sky-confirm-content-padding: 0;--sky-confirm-message-padding-bottom: 0}:host-context(.sky-theme-modern) .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-theme-modern .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-confirm-content{padding:var(--sky-confirm-content-padding)}.sky-confirm-message{margin-top:var(--sky-margin-stacked-xs);padding-bottom:var(--sky-confirm-message-padding-bottom)}.sky-confirm-body{margin-top:var(--sky-confirm-body-margin-top)}.sky-confirm-buttons{margin-top:var(--sky-confirm-buttons-margin-top)}.sky-confirm-preserve-white-space{white-space:pre-wrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: SkyIdModule }, { kind: "directive", type: i1.λ2, selector: "[skyId]", exportAs: ["skyId"] }, { kind: "component", type: SkyModalComponent, selector: "sky-modal", inputs: ["formErrors", "ariaRole", "tiledBody", "ariaDescribedBy", "ariaLabelledBy"] }, { kind: "component", type: SkyModalContentComponent, selector: "sky-modal-content" }, { kind: "ngmodule", type: SkyModalsResourcesModule }, { kind: "ngmodule", type: SkyThemeModule }, { kind: "directive", type: i5.λ2, selector: "[skyThemeClass]", inputs: ["class", "skyThemeClass"] }] }); }
913
+ }
914
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmComponent, decorators: [{
915
+ type: Component,
916
+ args: [{ standalone: true, selector: 'sky-confirm', imports: [
917
+ CommonModule,
918
+ SkyIdModule,
919
+ SkyModalComponent,
920
+ SkyModalContentComponent,
921
+ SkyModalsResourcesModule,
922
+ SkyThemeModule,
923
+ ], template: "<div class=\"sky-confirm\" [ngClass]=\"{ 'sky-confirm-type-ok': isOkType }\">\n <sky-modal\n ariaRole=\"alertdialog\"\n [ariaLabelledBy]=\"confirmMessage.id\"\n [ariaDescribedBy]=\"body ? bodyId : undefined\"\n >\n <sky-modal-content class=\"sky-confirm-content\">\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n class=\"sky-confirm-message\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n [skyThemeClass]=\"{\n 'sky-font-display-4': 'default',\n 'sky-font-heading-1 sky-font-display-3': 'modern'\n }\"\n skyId\n #confirmMessage=\"skyId\"\n >{{ message }}</div\n >\n\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n *ngIf=\"body\"\n class=\"sky-confirm-body\"\n [id]=\"bodyId\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n >{{ body }}</div\n >\n\n <div class=\"sky-confirm-buttons\">\n <button\n *ngFor=\"let button of buttons\"\n type=\"button\"\n class=\"sky-btn\"\n [ngClass]=\"'sky-btn-' + button.styleType\"\n [skyThemeClass]=\"{\n 'sky-margin-inline-sm': 'modern',\n 'sky-margin-inline-compact': 'default'\n }\"\n (click)=\"close(button)\"\n [attr.autofocus]=\"button.autofocus ? 'autofocus' : null\"\n >\n {{ button.text }}\n </button>\n </div>\n </sky-modal-content>\n </sky-modal>\n</div>\n", styles: [".sky-confirm{--sky-confirm-body-margin-top: var(--sky-margin-stacked-sm);--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-xl);--sky-confirm-content-padding: 0;--sky-confirm-message-padding-bottom: 0}:host-context(.sky-theme-modern) .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-theme-modern .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-confirm-content{padding:var(--sky-confirm-content-padding)}.sky-confirm-message{margin-top:var(--sky-margin-stacked-xs);padding-bottom:var(--sky-confirm-message-padding-bottom)}.sky-confirm-body{margin-top:var(--sky-confirm-body-margin-top)}.sky-confirm-buttons{margin-top:var(--sky-confirm-buttons-margin-top)}.sky-confirm-preserve-white-space{white-space:pre-wrap}\n"] }]
924
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
925
+ type: Inject,
926
+ args: [SKY_CONFIRM_CONFIG]
927
+ }] }, { type: SkyModalInstance }, { type: i2$1.SkyLibResourcesService }, { type: i1.SkyIdService }]; } });
928
+
929
+ /**
930
+ * Provided by the modal service to give the modal host
931
+ * component additional context and features.
932
+ * @internal
933
+ */
934
+ class SkyModalHostContext {
935
+ constructor(args) {
936
+ this.args = args;
937
+ }
938
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext, deps: [{ token: 'SkyModalHostContextArgs' }], target: i0.ɵɵFactoryTarget.Injectable }); }
939
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext }); }
940
+ }
941
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostContext, decorators: [{
942
+ type: Injectable
943
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
944
+ type: Inject,
945
+ args: ['SkyModalHostContextArgs']
946
+ }] }]; } });
947
+
948
+ /**
949
+ * @internal
950
+ */
951
+ class SkyModalAdapterService {
952
+ static { this.MODAL_BODY_FULL_CLASS = 'sky-modal-body-full-page'; }
953
+ static { this.MODAL_BODY_CLASS = 'sky-modal-body-open'; }
954
+ #docRef;
955
+ #bodyEl;
956
+ #windowRef;
957
+ #hostSiblingAriaHiddenCache = new Map();
958
+ constructor(windowRef) {
959
+ this.#windowRef = windowRef;
960
+ this.#docRef = this.#windowRef.nativeWindow.document;
961
+ this.#bodyEl = this.#windowRef.nativeWindow.document.body;
962
+ }
963
+ toggleFullPageModalClass(isAddFull) {
964
+ if (isAddFull) {
965
+ this.#addClassToBody(SkyModalAdapterService.MODAL_BODY_FULL_CLASS);
966
+ }
967
+ else {
968
+ this.#removeClassFromBody(SkyModalAdapterService.MODAL_BODY_FULL_CLASS);
695
969
  }
696
- return false;
697
970
  }
698
- focusFirstElement(list) {
699
- if (list.length > 0) {
700
- list[0].focus();
701
- return true;
971
+ setPageScroll(isAdd) {
972
+ if (isAdd) {
973
+ this.#addClassToBody(SkyModalAdapterService.MODAL_BODY_CLASS);
974
+ }
975
+ else {
976
+ this.#removeClassFromBody(SkyModalAdapterService.MODAL_BODY_CLASS);
702
977
  }
703
- return false;
704
978
  }
705
- modalContentHasDirectChildViewkeeper(modalContentEl) {
706
- return !!modalContentEl.nativeElement.querySelector('sky-modal-content > .sky-viewkeeper-fixed');
979
+ getModalOpener() {
980
+ return this.#docRef.activeElement;
707
981
  }
708
- modalOpened(modalEl) {
709
- /* istanbul ignore else */
710
- /* handle the case where somehow there is a focused element already in the modal */
711
- if (!(document.activeElement &&
712
- modalEl.nativeElement.contains(document.activeElement))) {
713
- const currentScrollX = window.pageXOffset;
714
- const currentScrollY = window.pageYOffset;
715
- const inputWithAutofocus = modalEl.nativeElement.querySelector('[autofocus]');
716
- if (inputWithAutofocus) {
717
- inputWithAutofocus.focus();
982
+ #addClassToBody(className) {
983
+ this.#bodyEl.classList.add(className);
984
+ }
985
+ #removeClassFromBody(className) {
986
+ this.#bodyEl.classList.remove(className);
987
+ }
988
+ scrollContentToTop(element) {
989
+ element.nativeElement.querySelector('.sky-modal-content').scrollTop = 0;
990
+ }
991
+ /**
992
+ * Hides siblings of modal-host from screen readers
993
+ * @param hostElRef reference to modal-host element
994
+ */
995
+ hideHostSiblingsFromScreenReaders(hostElRef) {
996
+ const hostElement = hostElRef.nativeElement;
997
+ const hostSiblings = hostElement.parentElement.children;
998
+ for (let i = 0; i < hostSiblings.length; i++) {
999
+ const element = hostSiblings[i];
1000
+ if (element !== hostElement &&
1001
+ !element.hasAttribute('aria-live') &&
1002
+ element.nodeName.toLowerCase() !== 'script' &&
1003
+ element.nodeName.toLowerCase() !== 'style') {
1004
+ // preserve previous aria-hidden status of elements outside of modal host
1005
+ this.#hostSiblingAriaHiddenCache.set(element, element.getAttribute('aria-hidden'));
1006
+ element.setAttribute('aria-hidden', 'true');
718
1007
  }
719
- else {
720
- this.#coreAdapter.getFocusableChildrenAndApplyFocus(modalEl, '.sky-modal-content', true);
1008
+ }
1009
+ }
1010
+ /**
1011
+ * Restores modal-host siblings to screen reader status prior to modals being opened
1012
+ */
1013
+ unhideOrRestoreHostSiblingsFromScreenReaders() {
1014
+ this.#hostSiblingAriaHiddenCache.forEach((previousValue, element) => {
1015
+ // if element had aria-hidden status prior, restore status
1016
+ if (element.parentElement) {
1017
+ if (previousValue) {
1018
+ element.setAttribute('aria-hidden', previousValue);
1019
+ }
1020
+ else {
1021
+ element.removeAttribute('aria-hidden');
1022
+ }
721
1023
  }
722
- window.scrollTo(currentScrollX, currentScrollY);
1024
+ });
1025
+ this.#hostSiblingAriaHiddenCache.clear();
1026
+ }
1027
+ hidePreviousModalFromScreenReaders(topModal) {
1028
+ if (topModal && topModal.nativeElement.previousElementSibling) {
1029
+ topModal.nativeElement.previousElementSibling.setAttribute('aria-hidden', 'true');
723
1030
  }
724
1031
  }
725
- #setFullPageHeight(fullPageModalEl) {
726
- const windowHeight = window.innerHeight;
727
- const fullPageModalStyle = getComputedStyle(fullPageModalEl);
728
- const marginTopBottom = parseInt(fullPageModalStyle.marginTop, 10) +
729
- parseInt(fullPageModalStyle.marginBottom, 10);
730
- const fullPageModalHeight = windowHeight - marginTopBottom + 'px';
731
- fullPageModalEl.style.height = fullPageModalHeight;
732
- fullPageModalEl.style.maxHeight = fullPageModalHeight;
1032
+ unhidePreviousModalFromScreenReaders(topModal) {
1033
+ if (topModal && topModal.nativeElement.previousElementSibling) {
1034
+ topModal.nativeElement.previousElementSibling.removeAttribute('aria-hidden');
1035
+ }
733
1036
  }
734
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService, deps: [{ token: i2$2.SkyCoreAdapterService }], target: i0.ɵɵFactoryTarget.Injectable }); }
735
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService }); }
1037
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService, deps: [{ token: i1.SkyAppWindowRef }], target: i0.ɵɵFactoryTarget.Injectable }); }
1038
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService }); }
736
1039
  }
737
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponentAdapterService, decorators: [{
1040
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalAdapterService, decorators: [{
738
1041
  type: Injectable
739
- }], ctorParameters: function () { return [{ type: i2$2.SkyCoreAdapterService }]; } });
1042
+ }], ctorParameters: function () { return [{ type: i1.SkyAppWindowRef }]; } });
740
1043
 
741
1044
  /**
742
- * Raises an event when the box shadow for the modal header or footer should be adjusted
743
- * based on the scroll position of the host element.
744
1045
  * @internal
745
1046
  */
746
- class SkyModalScrollShadowDirective {
747
- #currentShadow;
748
- #currentTheme;
749
- #mutationObserver;
750
- #ngUnsubscribe;
751
- #elRef;
752
- #mutationObserverSvc;
753
- #ngZone;
754
- #themeSvc;
755
- constructor(elRef, mutationObserverSvc, ngZone, themeSvc) {
756
- this.skyModalScrollShadow = new EventEmitter();
757
- this.#ngUnsubscribe = new Subject();
758
- this.#elRef = elRef;
759
- this.#mutationObserverSvc = mutationObserverSvc;
760
- this.#ngZone = ngZone;
761
- this.#themeSvc = themeSvc;
762
- }
763
- windowResize() {
764
- this.#checkForShadow();
765
- }
766
- scroll() {
767
- this.#checkForShadow();
1047
+ class SkyModalHostComponent {
1048
+ get modalOpen() {
1049
+ return SkyModalHostService.openModalCount > 0;
768
1050
  }
769
- ngOnInit() {
770
- if (this.#themeSvc) {
771
- this.#themeSvc.settingsChange
772
- .pipe(takeUntil(this.#ngUnsubscribe))
773
- .subscribe((themeSettings) => {
774
- this.#currentTheme = themeSettings.currentSettings.theme;
775
- if (this.#currentTheme === SkyTheme.presets.modern) {
776
- this.#initMutationObserver();
777
- }
778
- else {
779
- this.#emitShadow({
780
- bottomShadow: 'none',
781
- topShadow: 'none',
782
- });
783
- this.#destroyMutationObserver();
784
- }
785
- });
786
- }
1051
+ get backdropZIndex() {
1052
+ return SkyModalHostService.backdropZIndex;
787
1053
  }
1054
+ #modalInstances = [];
1055
+ #adapter = inject(SkyModalAdapterService);
1056
+ #changeDetector = inject(ChangeDetectorRef);
1057
+ #dynamicComponentSvc = inject(SkyDynamicComponentService);
1058
+ #elRef = inject(ElementRef);
1059
+ #environmentInjector = inject(EnvironmentInjector);
1060
+ #modalHostContext = inject(SkyModalHostContext);
1061
+ #router = inject(Router, { optional: true });
788
1062
  ngOnDestroy() {
789
- this.#ngUnsubscribe.next();
790
- this.#ngUnsubscribe.complete();
791
- this.#destroyMutationObserver();
792
- }
793
- #initMutationObserver() {
794
- if (!this.#mutationObserver) {
795
- const el = this.#elRef.nativeElement;
796
- // MutationObserver is patched by Zone.js and therefore becomes part of the
797
- // Angular change detection cycle, but this can lead to infinite loops in some
798
- // scenarios. This will keep MutationObserver from triggering change detection.
799
- this.#ngZone.runOutsideAngular(() => {
800
- this.#mutationObserver = this.#mutationObserverSvc.create(() => {
801
- this.#checkForShadow();
802
- });
803
- this.#mutationObserver.observe(el, {
804
- attributes: true,
805
- characterData: true,
806
- childList: true,
807
- subtree: true,
808
- });
809
- });
810
- }
811
- }
812
- #destroyMutationObserver() {
813
- if (this.#mutationObserver) {
814
- this.#mutationObserver.disconnect();
815
- this.#mutationObserver = undefined;
816
- }
1063
+ // Close all modal instances before disposing of the host container.
1064
+ this.#closeAllModalInstances();
1065
+ this.#modalHostContext.args.teardownCallback();
817
1066
  }
818
- #checkForShadow() {
819
- if (this.#currentTheme === SkyTheme.presets.modern) {
820
- const el = this.#elRef.nativeElement;
821
- const topShadow = this.#buildShadowStyle(el.scrollTop);
822
- const bottomShadow = this.#buildShadowStyle(el.scrollHeight - el.scrollTop - el.clientHeight);
823
- this.#emitShadow({
824
- bottomShadow,
825
- topShadow,
826
- });
1067
+ open(modalInstance, component, config) {
1068
+ /* Ignore coverage as we specify the target element and so the view child should never be undefined unless
1069
+ * we were to call the `open` method in an early lifecycle hook. */
1070
+ /* istanbul ignore next */
1071
+ if (!this.target) {
1072
+ return;
827
1073
  }
828
- }
829
- #buildShadowStyle(pixelsFromEnd) {
830
- // Progressively darken the shadow until the user scrolls 30 pixels from the top or bottom
831
- // of the scrollable element, with a max opacity of 0.3.
832
- const opacity = Math.min(pixelsFromEnd / 30, 1) * 0.3;
833
- return opacity > 0 ? `0px 1px 8px 0px rgba(0, 0, 0, ${opacity})` : 'none';
834
- }
835
- #emitShadow(shadow) {
836
- if (!this.#currentShadow ||
837
- this.#currentShadow.bottomShadow !== shadow.bottomShadow ||
838
- this.#currentShadow.topShadow !== shadow.topShadow) {
839
- this.skyModalScrollShadow.emit(shadow);
840
- this.#currentShadow = shadow;
1074
+ const params = Object.assign({}, config);
1075
+ const hostService = new SkyModalHostService();
1076
+ hostService.fullPage = !!params.fullPage;
1077
+ const adapter = this.#adapter;
1078
+ const modalOpener = adapter.getModalOpener();
1079
+ let isOpen = true;
1080
+ params.providers ||= [];
1081
+ params.providers.push({ provide: SkyResizeObserverMediaQueryService }, {
1082
+ provide: SkyModalHostService,
1083
+ useValue: hostService,
1084
+ }, {
1085
+ provide: SkyModalConfiguration,
1086
+ useValue: params,
1087
+ }, {
1088
+ provide: SkyMediaQueryService,
1089
+ useExisting: SkyResizeObserverMediaQueryService,
1090
+ }, {
1091
+ provide: SKY_STACKING_CONTEXT,
1092
+ useValue: {
1093
+ zIndex: new BehaviorSubject(hostService.getModalZIndex())
1094
+ .asObservable()
1095
+ .pipe(takeUntil(modalInstance.closed)),
1096
+ },
1097
+ });
1098
+ adapter.setPageScroll(SkyModalHostService.openModalCount > 0);
1099
+ adapter.toggleFullPageModalClass(SkyModalHostService.fullPageModalCount > 0);
1100
+ const modalComponentRef = this.#dynamicComponentSvc.createComponent(component, {
1101
+ environmentInjector: this.#environmentInjector,
1102
+ providers: params.providers,
1103
+ viewContainerRef: this.target,
1104
+ });
1105
+ // modal element that was just opened
1106
+ const modalElement = modalComponentRef.location;
1107
+ modalInstance.adapter = this.#adapter;
1108
+ modalInstance.componentRef = modalComponentRef;
1109
+ this.#registerModalInstance(modalInstance);
1110
+ // hiding all elements at the modal-host level from screen readers when the a modal is opened
1111
+ this.#adapter.hideHostSiblingsFromScreenReaders(this.#elRef);
1112
+ if (SkyModalHostService.openModalCount > 1 &&
1113
+ SkyModalHostService.topModal === hostService) {
1114
+ // hiding the lower modals when more than one modal is opened
1115
+ this.#adapter.hidePreviousModalFromScreenReaders(modalElement);
841
1116
  }
842
- }
843
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalScrollShadowDirective, deps: [{ token: i0.ElementRef }, { token: i2$2.SkyMutationObserverService }, { token: i0.NgZone }, { token: i2$1.SkyThemeService, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
844
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalScrollShadowDirective, selector: "[skyModalScrollShadow]", outputs: { skyModalScrollShadow: "skyModalScrollShadow" }, host: { listeners: { "window:resize": "windowResize()", "scroll": "scroll()" } }, ngImport: i0 }); }
845
- }
846
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalScrollShadowDirective, decorators: [{
847
- type: Directive,
848
- args: [{
849
- selector: '[skyModalScrollShadow]',
850
- }]
851
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i2$2.SkyMutationObserverService }, { type: i0.NgZone }, { type: i2$1.SkyThemeService, decorators: [{
852
- type: Optional
853
- }] }]; }, propDecorators: { skyModalScrollShadow: [{
854
- type: Output
855
- }], windowResize: [{
856
- type: HostListener,
857
- args: ['window:resize']
858
- }], scroll: [{
859
- type: HostListener,
860
- args: ['scroll']
861
- }] } });
862
-
863
- const ARIA_ROLE_DEFAULT = 'dialog';
864
- /**
865
- * Provides a common look-and-feel for modal content with options to display
866
- * a common modal header, specify body content, and display a common modal footer
867
- * and buttons.
868
- */
869
- class SkyModalComponent {
870
- /**
871
- * A list of form-level errors to display to the user.
872
- */
873
- set formErrors(value) {
874
- this.#errorsSvc.updateErrors(value);
875
- }
876
- /**
877
- * @internal
878
- */
879
- set ariaRole(value) {
880
- this.ariaRoleOrDefault = value || ARIA_ROLE_DEFAULT;
881
- }
882
- /**
883
- * @internal
884
- */
885
- set ariaDescribedBy(id) {
886
- this.#_ariaDescribedBy = id;
887
- }
888
- get ariaDescribedBy() {
889
- return this.#_ariaDescribedBy;
890
- }
891
- /**
892
- * @internal
893
- */
894
- set ariaLabelledBy(id) {
895
- this.#_ariaLabelledBy = id;
896
- }
897
- get ariaLabelledBy() {
898
- return this.#_ariaLabelledBy;
899
- }
900
- #hostService;
901
- #elRef;
902
- #windowRef;
903
- #componentAdapter;
904
- #coreAdapter;
905
- #dockService;
906
- #mediaQueryService;
907
- #ngUnsubscribe;
908
- #_ariaDescribedBy;
909
- #_ariaLabelledBy;
910
- #changeDetector;
911
- #errorsSvc;
912
- #liveAnnouncerSvc;
913
- /**
914
- * This provider is optional to account for situations where a modal component
915
- * is implemented without the modal service. For example, when a consumer tests
916
- * a component that uses the modal component but doesn't launch the modal from
917
- * the modal service before executing assertions.
918
- */
919
- #config;
920
- constructor(hostService, elRef, windowRef, componentAdapter, coreAdapter, dockService, mediaQueryService) {
921
- this.ariaRoleOrDefault = ARIA_ROLE_DEFAULT;
922
- this.ariaOwns = null;
923
- this.modalState = 'in';
924
- this.#ngUnsubscribe = new Subject();
925
- this.#changeDetector = inject(ChangeDetectorRef);
926
- this.#errorsSvc = inject(SkyModalErrorsService);
927
- this.#liveAnnouncerSvc = inject(SkyLiveAnnouncerService);
928
- /**
929
- * This provider is optional to account for situations where a modal component
930
- * is implemented without the modal service. For example, when a consumer tests
931
- * a component that uses the modal component but doesn't launch the modal from
932
- * the modal service before executing assertions.
933
- */
934
- this.#config = inject(SkyModalConfiguration, { optional: true }) ??
935
- new SkyModalConfiguration();
936
- this.#hostService = hostService;
937
- this.#elRef = elRef;
938
- this.#windowRef = windowRef;
939
- this.#componentAdapter = componentAdapter;
940
- this.#coreAdapter = coreAdapter;
941
- this.#dockService = dockService;
942
- this.#mediaQueryService = mediaQueryService;
943
- this.ariaDescribedBy = this.#config.ariaDescribedBy;
944
- this.ariaLabelledBy = this.#config.ariaLabelledBy;
945
- this.ariaRole = this.#config.ariaRole;
946
- this.helpKey = this.#config.helpKey;
947
- this.tiledBody = this.#config.tiledBody;
948
- this.wrapperClass = this.#config.wrapperClass;
949
- this.size = this.#config.fullPage
950
- ? 'full-page'
951
- : this.#config.size?.toLowerCase() || 'medium';
952
- this.modalZIndex = this.#hostService.zIndex;
953
- }
954
- onDocumentKeyUp(event) {
955
- /* istanbul ignore else */
956
- /* sanity check */
957
- if (SkyModalHostService.openModalCount > 0) {
958
- const topModal = SkyModalHostService.topModal;
959
- if (topModal && topModal === this.#hostService) {
960
- if (event.which === 27) {
961
- // Escape key up
962
- event.preventDefault();
963
- this.closeButtonClick();
964
- }
1117
+ const closeModal = () => {
1118
+ // unhide siblings if last modal is closing
1119
+ if (SkyModalHostService.openModalCount === 1) {
1120
+ this.#adapter.unhideOrRestoreHostSiblingsFromScreenReaders();
965
1121
  }
966
- }
967
- }
968
- onDocumentKeyDown(event) {
969
- /* istanbul ignore else */
970
- /* sanity check */
971
- if (SkyModalHostService.openModalCount > 0) {
972
- const topModal = SkyModalHostService.topModal;
973
- if (topModal && topModal === this.#hostService) {
974
- if (event.which === 9) {
975
- // Tab pressed
976
- let focusChanged = false;
977
- const focusElementList = this.#coreAdapter.getFocusableChildren(this.#elRef.nativeElement);
978
- if (event.shiftKey &&
979
- (this.#componentAdapter.isFocusInFirstItem(event, focusElementList) ||
980
- this.#componentAdapter.isModalFocused(event, this.#elRef))) {
981
- focusChanged =
982
- this.#componentAdapter.focusLastElement(focusElementList);
983
- }
984
- else if (!event.shiftKey &&
985
- this.#componentAdapter.isFocusInLastItem(event, focusElementList)) {
986
- focusChanged =
987
- this.#componentAdapter.focusFirstElement(focusElementList);
988
- }
989
- if (focusChanged) {
990
- event.preventDefault();
991
- event.stopPropagation();
992
- }
993
- }
1122
+ else if (SkyModalHostService.topModal === hostService) {
1123
+ // if there are more than 1 modal then unhide the one behind this one before closing it
1124
+ this.#adapter.unhidePreviousModalFromScreenReaders(modalElement);
994
1125
  }
995
- }
996
- }
997
- ngOnInit() {
998
- this.#liveAnnouncerSvc.announcerElementChanged
999
- .pipe(takeUntil(this.#ngUnsubscribe))
1000
- .subscribe((element) => {
1001
- if (element?.id) {
1002
- this.ariaOwns = element.id;
1003
- this.#changeDetector.markForCheck();
1126
+ hostService.destroy();
1127
+ adapter.setPageScroll(SkyModalHostService.openModalCount > 0);
1128
+ adapter.toggleFullPageModalClass(SkyModalHostService.fullPageModalCount > 0);
1129
+ /* istanbul ignore else */
1130
+ /* sanity check */
1131
+ if (modalOpener && modalOpener.focus) {
1132
+ modalOpener.focus();
1133
+ }
1134
+ modalComponentRef.destroy();
1135
+ };
1136
+ hostService.openHelp.subscribe((helpKey) => {
1137
+ modalInstance.openHelp(helpKey);
1138
+ });
1139
+ hostService.close.subscribe(() => {
1140
+ modalInstance.close();
1141
+ });
1142
+ this.#router?.events.pipe(takeWhile(() => isOpen)).subscribe((event) => {
1143
+ /* istanbul ignore else */
1144
+ if (event instanceof NavigationStart) {
1145
+ modalInstance.close();
1004
1146
  }
1005
1147
  });
1006
- }
1007
- ngAfterViewInit() {
1008
- this.#componentAdapter.handleWindowChange(this.#elRef);
1009
- // Adding a timeout to avoid ExpressionChangedAfterItHasBeenCheckedError.
1010
- // https://stackoverflow.com/questions/40562845
1011
- this.#windowRef.nativeWindow.setTimeout(() => {
1012
- this.#componentAdapter.modalOpened(this.#elRef);
1013
- });
1014
- this.#dockService.setDockOptions({
1015
- location: SkyDockLocation.ElementBottom,
1016
- referenceEl: this.modalContentWrapperElement.nativeElement,
1017
- zIndex: 5,
1148
+ modalInstance.closed.subscribe(() => {
1149
+ isOpen = false;
1150
+ this.#unregisterModalInstance(modalInstance);
1151
+ closeModal();
1018
1152
  });
1019
- /* istanbul ignore next */
1020
- if (this.#mediaQueryService) {
1021
- this.#mediaQueryService.observe(this.modalContentWrapperElement);
1022
- }
1023
- }
1024
- ngOnDestroy() {
1025
- /* istanbul ignore next */
1026
- if (this.#mediaQueryService) {
1027
- this.#mediaQueryService.unobserve();
1028
- }
1029
- this.#ngUnsubscribe.next();
1030
- this.#ngUnsubscribe.complete();
1031
- }
1032
- helpButtonClick() {
1033
- if (this.helpKey) {
1034
- this.#hostService.onOpenHelp(this.helpKey);
1035
- }
1036
- }
1037
- closeButtonClick() {
1038
- this.#hostService.onClose();
1153
+ // Necessary if the host was created via a consumer's lifecycle hook such as ngOnInit
1154
+ this.#changeDetector.detectChanges();
1039
1155
  }
1040
- windowResize() {
1041
- this.#componentAdapter.handleWindowChange(this.#elRef);
1156
+ #registerModalInstance(instance) {
1157
+ this.#modalInstances.push(instance);
1042
1158
  }
1043
- scrollShadowChange(args) {
1044
- this.scrollShadow = args;
1159
+ #unregisterModalInstance(instance) {
1160
+ this.#modalInstances.slice(this.#modalInstances.indexOf(instance), 1);
1045
1161
  }
1046
- viewkeeperEnabled() {
1047
- return this.#componentAdapter.modalContentHasDirectChildViewkeeper(this.#elRef);
1162
+ #closeAllModalInstances() {
1163
+ for (const instance of this.#modalInstances) {
1164
+ instance.close();
1165
+ }
1048
1166
  }
1049
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponent, deps: [{ token: SkyModalHostService }, { token: i0.ElementRef }, { token: i2$2.SkyAppWindowRef }, { token: SkyModalComponentAdapterService }, { token: i2$2.SkyCoreAdapterService }, { token: i2$2.SkyDockService, host: true }, { token: i2$2.SkyResizeObserverMediaQueryService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
1050
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalComponent, selector: "sky-modal", inputs: { formErrors: "formErrors", ariaRole: "ariaRole", tiledBody: "tiledBody", ariaDescribedBy: "ariaDescribedBy", ariaLabelledBy: "ariaLabelledBy" }, host: { listeners: { "document:keyup": "onDocumentKeyUp($event)", "document:keydown": "onDocumentKeyDown($event)" }, properties: { "class": "this.wrapperClass" } }, providers: [
1051
- SkyModalComponentAdapterService,
1052
- SkyModalErrorsService,
1053
- SkyDockService,
1054
- ], viewQueries: [{ propertyName: "modalContentWrapperElement", first: true, predicate: ["modalContentWrapper"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"sky-modal-dialog\"\n aria-modal=\"true\"\n [attr.aria-describedby]=\"ariaDescribedBy || modalContentId.id\"\n [attr.aria-labelledby]=\"ariaLabelledBy || headerId.id\"\n [attr.aria-owns]=\"ariaOwns\"\n [attr.role]=\"ariaRoleOrDefault\"\n (window:resize)=\"windowResize()\"\n>\n <div\n class=\"sky-modal sky-shadow sky-box sky-elevation-16 sky-modal-{{ size }}\"\n tabindex=\"-1\"\n [ngClass]=\"{\n 'sky-modal-tiled': tiledBody,\n 'sky-modal-viewkeeper': viewkeeperEnabled()\n }\"\n [ngStyle]=\"{\n zIndex: modalZIndex\n }\"\n >\n <div\n class=\"sky-modal-header\"\n [hidden]=\"!headerContent || !headerContent.children || headerContent.children.length &lt; 1\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.topShadow\n }\"\n >\n <div\n class=\"sky-modal-header-content\"\n skyId\n [ngClass]=\"{\n 'sky-font-heading-2': size === 'full-page'\n }\"\n #headerContent\n #headerId=\"skyId\"\n >\n <ng-content select=\"sky-modal-header\"></ng-content>\n </div>\n <div class=\"sky-modal-header-buttons\">\n <button\n *ngIf=\"helpKey\"\n class=\"sky-btn sky-modal-btn-help\"\n name=\"help-button\"\n type=\"button\"\n [attr.aria-label]=\"'skyux_modal_open_help' | skyLibResources\"\n (click)=\"helpButtonClick()\"\n >\n <sky-icon icon=\"question-circle\"></sky-icon>\n </button>\n\n <button\n type=\"button\"\n class=\"sky-btn sky-modal-btn-close\"\n [attr.aria-label]=\"'skyux_modal_close' | skyLibResources\"\n (click)=\"closeButtonClick()\"\n >\n <sky-icon icon=\"close\"></sky-icon>\n </button>\n </div>\n </div>\n <div\n class=\"sky-modal-content sky-padding-even-large\"\n role=\"region\"\n tabindex=\"0\"\n skyId\n [attr.aria-labelledby]=\"headerId.id\"\n (skyModalScrollShadow)=\"scrollShadowChange($event)\"\n #modalContentId=\"skyId\"\n #modalContentWrapper\n >\n <ng-content select=\"sky-modal-content\"></ng-content>\n </div>\n <div\n class=\"sky-modal-footer\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.bottomShadow\n }\"\n >\n <ng-content select=\"sky-modal-footer\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [".sky-modal{border-top:1px solid #cdcfd2;border-bottom:1px solid #cdcfd2;border-left:1px solid #cdcfd2;border-right:1px solid #cdcfd2;position:fixed;width:auto;left:0;right:0;top:20px;margin:10px;display:flex;flex-direction:column;overflow:hidden}.sky-modal:focus{outline:none}@media (min-width: 768px){.sky-modal:not(.sky-modal-large){margin:0 auto}.sky-modal-small{width:300px}.sky-modal-small .sky-modal-content,.sky-modal-small .sky-modal-header,.sky-modal-small .sky-modal-footer{max-width:300px}.sky-modal-medium{width:600px}.sky-modal-medium .sky-modal-content,.sky-modal-medium .sky-modal-header,.sky-modal-medium .sky-modal-footer{max-width:600px}}@media (min-width: 920px){.sky-modal-large{margin:0 auto;width:900px}.sky-modal-large .sky-modal-content,.sky-modal-large .sky-modal-header,.sky-modal-large .sky-modal-footer{max-width:900px}}.sky-modal-content{background-color:#fff;--sky-background-color-page-default: #fff}.sky-modal-content:focus{outline-style:dotted;outline-width:thin;outline-offset:-1px}.sky-modal-tiled .sky-modal-content{background-color:#eeeeef;--sky-background-color-page-default: $sky-background-color-neutral-light}.sky-modal-tiled .sky-modal-content ::ng-deep .sky-tile-title{font-family:BLKB Sans,Helvetica Neue,Arial,sans-serif;color:var(--sky-text-color-deemphasized);font-weight:300;font-size:19px}.sky-modal-header{padding:9px 3px 9px 15px;background-color:#fff;display:flex;align-items:baseline;border-bottom:1px solid #e2e3e4}.sky-modal-header-buttons{flex-shrink:.0001}.sky-modal-header-buttons .sky-btn{border:none;color:#cdcfd2;cursor:pointer}.sky-modal-header-buttons .sky-btn:hover{color:#979ba2;transition:color .15s}.sky-modal-header-content{flex-grow:1}.sky-modal-header{flex-shrink:0;z-index:2}.sky-modal-content{overflow-y:auto}.sky-modal-footer{flex-shrink:0;z-index:2}.sky-modal-full-page{width:100%;top:0;margin:0}.sky-modal-full-page .sky-modal-header-buttons sky-icon[icon=close]{font-size:20px}.sky-modal-full-page .sky-modal-content{flex-grow:1}:host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-15px}.sky-modal-content>::ng-deep sky-dock{bottom:-15px;margin-left:-15px;margin-bottom:-15px;padding-top:15px;width:calc(100% + 30px)}:host-context(.sky-theme-modern) .sky-modal-header{border:none;padding:20px 30px}:host-context(.sky-theme-modern) .sky-modal-btn-help,:host-context(.sky-theme-modern) .sky-modal-btn-close{display:none}:host-context(.sky-theme-modern) .sky-modal-content{padding:0}:host-context(.sky-theme-modern) .sky-modal-full-page{width:calc(100% - 60px);margin:30px}:host-context(.sky-theme-modern) .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}.sky-theme-modern .sky-modal-header{border:none;padding:20px 30px}.sky-theme-modern .sky-modal-btn-help,.sky-theme-modern .sky-modal-btn-close{display:none}.sky-theme-modern .sky-modal-content{padding:0}.sky-theme-modern .sky-modal-full-page{width:calc(100% - 60px);margin:30px}.sky-theme-modern .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal{border-color:#121212}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header{color:#fbfcfe}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header,:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}.sky-theme-modern.sky-theme-mode-dark .sky-modal{border-color:#121212}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header,.sky-theme-modern.sky-theme-mode-dark .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }, { kind: "directive", type: i2$2.λ2, selector: "[skyId]", exportAs: ["skyId"] }, { kind: "directive", type: SkyModalScrollShadowDirective, selector: "[skyModalScrollShadow]", outputs: ["skyModalScrollShadow"] }, { kind: "pipe", type: i2$3.SkyLibResourcesPipe, name: "skyLibResources" }] }); }
1167
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1168
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalHostComponent, isStandalone: true, selector: "sky-modal-host", viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"sky-modal-host-backdrop\"\n [hidden]=\"!modalOpen\"\n [ngStyle]=\"{\n zIndex: backdropZIndex\n }\"\n></div>\n<div #target></div>\n", styles: [".sky-modal-host-backdrop{background-color:#00000080;position:fixed;inset:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: SkyModalsResourcesModule }], viewProviders: [SkyModalAdapterService] }); }
1055
1169
  }
1056
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalComponent, decorators: [{
1170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHostComponent, decorators: [{
1057
1171
  type: Component,
1058
- args: [{ selector: 'sky-modal', providers: [
1059
- SkyModalComponentAdapterService,
1060
- SkyModalErrorsService,
1061
- SkyDockService,
1062
- ], template: "<div\n class=\"sky-modal-dialog\"\n aria-modal=\"true\"\n [attr.aria-describedby]=\"ariaDescribedBy || modalContentId.id\"\n [attr.aria-labelledby]=\"ariaLabelledBy || headerId.id\"\n [attr.aria-owns]=\"ariaOwns\"\n [attr.role]=\"ariaRoleOrDefault\"\n (window:resize)=\"windowResize()\"\n>\n <div\n class=\"sky-modal sky-shadow sky-box sky-elevation-16 sky-modal-{{ size }}\"\n tabindex=\"-1\"\n [ngClass]=\"{\n 'sky-modal-tiled': tiledBody,\n 'sky-modal-viewkeeper': viewkeeperEnabled()\n }\"\n [ngStyle]=\"{\n zIndex: modalZIndex\n }\"\n >\n <div\n class=\"sky-modal-header\"\n [hidden]=\"!headerContent || !headerContent.children || headerContent.children.length &lt; 1\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.topShadow\n }\"\n >\n <div\n class=\"sky-modal-header-content\"\n skyId\n [ngClass]=\"{\n 'sky-font-heading-2': size === 'full-page'\n }\"\n #headerContent\n #headerId=\"skyId\"\n >\n <ng-content select=\"sky-modal-header\"></ng-content>\n </div>\n <div class=\"sky-modal-header-buttons\">\n <button\n *ngIf=\"helpKey\"\n class=\"sky-btn sky-modal-btn-help\"\n name=\"help-button\"\n type=\"button\"\n [attr.aria-label]=\"'skyux_modal_open_help' | skyLibResources\"\n (click)=\"helpButtonClick()\"\n >\n <sky-icon icon=\"question-circle\"></sky-icon>\n </button>\n\n <button\n type=\"button\"\n class=\"sky-btn sky-modal-btn-close\"\n [attr.aria-label]=\"'skyux_modal_close' | skyLibResources\"\n (click)=\"closeButtonClick()\"\n >\n <sky-icon icon=\"close\"></sky-icon>\n </button>\n </div>\n </div>\n <div\n class=\"sky-modal-content sky-padding-even-large\"\n role=\"region\"\n tabindex=\"0\"\n skyId\n [attr.aria-labelledby]=\"headerId.id\"\n (skyModalScrollShadow)=\"scrollShadowChange($event)\"\n #modalContentId=\"skyId\"\n #modalContentWrapper\n >\n <ng-content select=\"sky-modal-content\"></ng-content>\n </div>\n <div\n class=\"sky-modal-footer\"\n [ngStyle]=\"{\n 'box-shadow': scrollShadow?.bottomShadow\n }\"\n >\n <ng-content select=\"sky-modal-footer\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [".sky-modal{border-top:1px solid #cdcfd2;border-bottom:1px solid #cdcfd2;border-left:1px solid #cdcfd2;border-right:1px solid #cdcfd2;position:fixed;width:auto;left:0;right:0;top:20px;margin:10px;display:flex;flex-direction:column;overflow:hidden}.sky-modal:focus{outline:none}@media (min-width: 768px){.sky-modal:not(.sky-modal-large){margin:0 auto}.sky-modal-small{width:300px}.sky-modal-small .sky-modal-content,.sky-modal-small .sky-modal-header,.sky-modal-small .sky-modal-footer{max-width:300px}.sky-modal-medium{width:600px}.sky-modal-medium .sky-modal-content,.sky-modal-medium .sky-modal-header,.sky-modal-medium .sky-modal-footer{max-width:600px}}@media (min-width: 920px){.sky-modal-large{margin:0 auto;width:900px}.sky-modal-large .sky-modal-content,.sky-modal-large .sky-modal-header,.sky-modal-large .sky-modal-footer{max-width:900px}}.sky-modal-content{background-color:#fff;--sky-background-color-page-default: #fff}.sky-modal-content:focus{outline-style:dotted;outline-width:thin;outline-offset:-1px}.sky-modal-tiled .sky-modal-content{background-color:#eeeeef;--sky-background-color-page-default: $sky-background-color-neutral-light}.sky-modal-tiled .sky-modal-content ::ng-deep .sky-tile-title{font-family:BLKB Sans,Helvetica Neue,Arial,sans-serif;color:var(--sky-text-color-deemphasized);font-weight:300;font-size:19px}.sky-modal-header{padding:9px 3px 9px 15px;background-color:#fff;display:flex;align-items:baseline;border-bottom:1px solid #e2e3e4}.sky-modal-header-buttons{flex-shrink:.0001}.sky-modal-header-buttons .sky-btn{border:none;color:#cdcfd2;cursor:pointer}.sky-modal-header-buttons .sky-btn:hover{color:#979ba2;transition:color .15s}.sky-modal-header-content{flex-grow:1}.sky-modal-header{flex-shrink:0;z-index:2}.sky-modal-content{overflow-y:auto}.sky-modal-footer{flex-shrink:0;z-index:2}.sky-modal-full-page{width:100%;top:0;margin:0}.sky-modal-full-page .sky-modal-header-buttons sky-icon[icon=close]{font-size:20px}.sky-modal-full-page .sky-modal-content{flex-grow:1}:host ::ng-deep .sky-sectioned-form{min-height:460px;margin:-15px}.sky-modal-content>::ng-deep sky-dock{bottom:-15px;margin-left:-15px;margin-bottom:-15px;padding-top:15px;width:calc(100% + 30px)}:host-context(.sky-theme-modern) .sky-modal-header{border:none;padding:20px 30px}:host-context(.sky-theme-modern) .sky-modal-btn-help,:host-context(.sky-theme-modern) .sky-modal-btn-close{display:none}:host-context(.sky-theme-modern) .sky-modal-content{padding:0}:host-context(.sky-theme-modern) .sky-modal-full-page{width:calc(100% - 60px);margin:30px}:host-context(.sky-theme-modern) .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}:host-context(.sky-theme-modern) .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}.sky-theme-modern .sky-modal-header{border:none;padding:20px 30px}.sky-theme-modern .sky-modal-btn-help,.sky-theme-modern .sky-modal-btn-close{display:none}.sky-theme-modern .sky-modal-content{padding:0}.sky-theme-modern .sky-modal-full-page{width:calc(100% - 60px);margin:30px}.sky-theme-modern .sky-modal-content>::ng-deep sky-dock{bottom:0;margin-left:initial;margin-bottom:initial;padding-top:initial;width:100%}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-header{box-shadow:none!important}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed{box-shadow:0 4px 8px -4px #0000004d}.sky-theme-modern .sky-modal-viewkeeper .sky-modal-content ::ng-deep sky-modal-content>.sky-viewkeeper-fixed>sky-toolbar .sky-toolbar-container{background-color:#fff;--sky-background-color-page-default: #fff;padding-left:30px;padding-right:30px}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal{border-color:#121212}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header{color:#fbfcfe}:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-header,:host-context(.sky-theme-modern.sky-theme-mode-dark) .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}.sky-theme-modern.sky-theme-mode-dark .sky-modal{border-color:#121212}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-modal-header,.sky-theme-modern.sky-theme-mode-dark .sky-modal-content{background-color:transparent;--sky-background-color-page-default: $sky-theme-modern-mode-dark-background-color-page-default}\n"] }]
1063
- }], ctorParameters: function () { return [{ type: SkyModalHostService }, { type: i0.ElementRef }, { type: i2$2.SkyAppWindowRef }, { type: SkyModalComponentAdapterService }, { type: i2$2.SkyCoreAdapterService }, { type: i2$2.SkyDockService, decorators: [{
1064
- type: Host
1065
- }] }, { type: i2$2.SkyResizeObserverMediaQueryService, decorators: [{
1066
- type: Optional
1067
- }] }]; }, propDecorators: { wrapperClass: [{
1068
- type: HostBinding,
1069
- args: ['class']
1070
- }], formErrors: [{
1071
- type: Input
1072
- }], ariaRole: [{
1073
- type: Input
1074
- }], tiledBody: [{
1075
- type: Input
1076
- }], ariaDescribedBy: [{
1077
- type: Input
1078
- }], ariaLabelledBy: [{
1079
- type: Input
1080
- }], modalContentWrapperElement: [{
1172
+ args: [{ standalone: true, selector: 'sky-modal-host', viewProviders: [SkyModalAdapterService], imports: [CommonModule, RouterModule, SkyModalsResourcesModule], template: "<div\n class=\"sky-modal-host-backdrop\"\n [hidden]=\"!modalOpen\"\n [ngStyle]=\"{\n zIndex: backdropZIndex\n }\"\n></div>\n<div #target></div>\n", styles: [".sky-modal-host-backdrop{background-color:#00000080;position:fixed;inset:0}\n"] }]
1173
+ }], propDecorators: { target: [{
1081
1174
  type: ViewChild,
1082
- args: ['modalContentWrapper', { read: ElementRef }]
1083
- }], onDocumentKeyUp: [{
1084
- type: HostListener,
1085
- args: ['document:keyup', ['$event']]
1086
- }], onDocumentKeyDown: [{
1087
- type: HostListener,
1088
- args: ['document:keydown', ['$event']]
1175
+ args: ['target', {
1176
+ read: ViewContainerRef,
1177
+ static: true,
1178
+ }]
1089
1179
  }] } });
1090
1180
 
1091
- class SkyConfirmComponent {
1092
- #config;
1093
- #modal;
1094
- #resourcesService;
1095
- constructor(config, modal, resourcesService, idService) {
1096
- this.preserveWhiteSpace = false;
1097
- this.isOkType = false;
1098
- this.#config = config;
1099
- this.#modal = modal;
1100
- this.#resourcesService = resourcesService;
1101
- if (config.type === SkyConfirmType.Custom &&
1102
- config.buttons &&
1103
- config.buttons.length > 0) {
1104
- this.buttons = this.#getCustomButtons(config.buttons);
1105
- }
1106
- else {
1107
- this.#getPresetButtons()
1108
- .pipe(take(1))
1109
- .subscribe((buttons) => {
1110
- this.buttons = buttons;
1111
- });
1112
- }
1113
- this.message = config.message;
1114
- this.body = config.body;
1115
- // Using the service here instead of the directive due to the confirm component's "body" container being conditional and thus a template variable being unavailable at an outer scope
1116
- this.bodyId = idService.generateId();
1117
- this.preserveWhiteSpace = !!config.preserveWhiteSpace;
1118
- this.isOkType = config.type === SkyConfirmType.OK;
1119
- }
1120
- close(button) {
1121
- const result = {
1122
- action: button.action,
1123
- };
1124
- this.#modal.close(result);
1125
- }
1126
- #getPresetButtons() {
1127
- const emitter = new ReplaySubject(1);
1128
- this.#resourcesService
1129
- .getStrings({
1130
- cancel: 'skyux_confirm_dialog_default_cancel_text',
1131
- no: 'skyux_confirm_dialog_default_no_text',
1132
- ok: 'skyux_confirm_dialog_default_ok_text',
1133
- yes: 'skyux_confirm_dialog_default_yes_text',
1134
- })
1135
- .subscribe((values) => {
1136
- const confirmButtons = [];
1137
- switch (this.#config.type) {
1138
- case SkyConfirmType.YesNoCancel:
1139
- case SkyConfirmType.YesCancel:
1140
- confirmButtons.push({
1141
- text: values.yes,
1142
- autofocus: true,
1143
- styleType: 'primary',
1144
- action: 'yes',
1145
- });
1146
- if (this.#config.type === SkyConfirmType.YesNoCancel) {
1147
- confirmButtons.push({
1148
- text: values.no,
1149
- styleType: 'default',
1150
- action: 'no',
1151
- });
1152
- }
1153
- confirmButtons.push({
1154
- text: values.cancel,
1155
- styleType: 'link',
1156
- action: 'cancel',
1157
- });
1158
- break;
1159
- default:
1160
- confirmButtons.push({
1161
- text: values.ok,
1162
- autofocus: true,
1163
- styleType: 'primary',
1164
- action: 'ok',
1165
- });
1166
- }
1167
- emitter.next(confirmButtons);
1168
- });
1169
- return emitter.asObservable();
1170
- }
1171
- #getCustomButtons(buttonConfig) {
1172
- return buttonConfig.map((config) => ({
1173
- text: config.text,
1174
- action: config.action,
1175
- styleType: config.styleType || 'default',
1176
- autofocus: config.autofocus || false,
1177
- }));
1178
- }
1179
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmComponent, deps: [{ token: SKY_CONFIRM_CONFIG }, { token: SkyModalInstance }, { token: i2$3.SkyLibResourcesService }, { token: i2$2.SkyIdService }], target: i0.ɵɵFactoryTarget.Component }); }
1180
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyConfirmComponent, selector: "sky-confirm", ngImport: i0, template: "<div class=\"sky-confirm\" [ngClass]=\"{ 'sky-confirm-type-ok': isOkType }\">\n <sky-modal\n ariaRole=\"alertdialog\"\n [ariaLabelledBy]=\"confirmMessage.id\"\n [ariaDescribedBy]=\"body ? bodyId : undefined\"\n >\n <sky-modal-content class=\"sky-confirm-content\">\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n class=\"sky-confirm-message\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n [skyThemeClass]=\"{\n 'sky-font-display-4': 'default',\n 'sky-font-heading-1 sky-font-display-3': 'modern'\n }\"\n skyId\n #confirmMessage=\"skyId\"\n >{{ message }}</div\n >\n\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n *ngIf=\"body\"\n class=\"sky-confirm-body\"\n [id]=\"bodyId\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n >{{ body }}</div\n >\n\n <div class=\"sky-confirm-buttons\">\n <button\n *ngFor=\"let button of buttons\"\n type=\"button\"\n class=\"sky-btn\"\n [ngClass]=\"'sky-btn-' + button.styleType\"\n [skyThemeClass]=\"{\n 'sky-margin-inline-sm': 'modern',\n 'sky-margin-inline-compact': 'default'\n }\"\n (click)=\"close(button)\"\n [attr.autofocus]=\"button.autofocus ? 'autofocus' : null\"\n >\n {{ button.text }}\n </button>\n </div>\n </sky-modal-content>\n </sky-modal>\n</div>\n", styles: [".sky-confirm{--sky-confirm-body-margin-top: var(--sky-margin-stacked-sm);--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-xl);--sky-confirm-content-padding: 0;--sky-confirm-message-padding-bottom: 0}:host-context(.sky-theme-modern) .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-theme-modern .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-confirm-content{padding:var(--sky-confirm-content-padding)}.sky-confirm-message{margin-top:var(--sky-margin-stacked-xs);padding-bottom:var(--sky-confirm-message-padding-bottom)}.sky-confirm-body{margin-top:var(--sky-confirm-body-margin-top)}.sky-confirm-buttons{margin-top:var(--sky-confirm-buttons-margin-top)}.sky-confirm-preserve-white-space{white-space:pre-wrap}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.λ2, selector: "[skyId]", exportAs: ["skyId"] }, { kind: "component", type: SkyModalComponent, selector: "sky-modal", inputs: ["formErrors", "ariaRole", "tiledBody", "ariaDescribedBy", "ariaLabelledBy"] }, { kind: "component", type: SkyModalContentComponent, selector: "sky-modal-content" }, { kind: "directive", type: i2$1.λ2, selector: "[skyThemeClass]", inputs: ["class", "skyThemeClass"] }] }); }
1181
- }
1182
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmComponent, decorators: [{
1183
- type: Component,
1184
- args: [{ selector: 'sky-confirm', template: "<div class=\"sky-confirm\" [ngClass]=\"{ 'sky-confirm-type-ok': isOkType }\">\n <sky-modal\n ariaRole=\"alertdialog\"\n [ariaLabelledBy]=\"confirmMessage.id\"\n [ariaDescribedBy]=\"body ? bodyId : undefined\"\n >\n <sky-modal-content class=\"sky-confirm-content\">\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n class=\"sky-confirm-message\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n [skyThemeClass]=\"{\n 'sky-font-display-4': 'default',\n 'sky-font-heading-1 sky-font-display-3': 'modern'\n }\"\n skyId\n #confirmMessage=\"skyId\"\n >{{ message }}</div\n >\n\n <!--\n The following \"magic comment\" keeps Prettier from adding line breaks\n inside the div and causing leading and trailing whitespace when\n `preserveWhiteSpace` is `true`.\n https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting\n -->\n <!-- display: inline -->\n <div\n *ngIf=\"body\"\n class=\"sky-confirm-body\"\n [id]=\"bodyId\"\n [ngClass]=\"{\n 'sky-confirm-preserve-white-space': preserveWhiteSpace\n }\"\n >{{ body }}</div\n >\n\n <div class=\"sky-confirm-buttons\">\n <button\n *ngFor=\"let button of buttons\"\n type=\"button\"\n class=\"sky-btn\"\n [ngClass]=\"'sky-btn-' + button.styleType\"\n [skyThemeClass]=\"{\n 'sky-margin-inline-sm': 'modern',\n 'sky-margin-inline-compact': 'default'\n }\"\n (click)=\"close(button)\"\n [attr.autofocus]=\"button.autofocus ? 'autofocus' : null\"\n >\n {{ button.text }}\n </button>\n </div>\n </sky-modal-content>\n </sky-modal>\n</div>\n", styles: [".sky-confirm{--sky-confirm-body-margin-top: var(--sky-margin-stacked-sm);--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-xl);--sky-confirm-content-padding: 0;--sky-confirm-message-padding-bottom: 0}:host-context(.sky-theme-modern) .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-theme-modern .sky-confirm{--sky-confirm-body-margin-top: 0;--sky-confirm-buttons-margin-top: var(--sky-margin-stacked-lg);--sky-confirm-content-padding: var(--sky-margin-stacked-lg) var(--sky-margin-inline-xl);--sky-confirm-message-padding-bottom: var(--sky-margin-stacked-lg)}.sky-confirm-content{padding:var(--sky-confirm-content-padding)}.sky-confirm-message{margin-top:var(--sky-margin-stacked-xs);padding-bottom:var(--sky-confirm-message-padding-bottom)}.sky-confirm-body{margin-top:var(--sky-confirm-body-margin-top)}.sky-confirm-buttons{margin-top:var(--sky-confirm-buttons-margin-top)}.sky-confirm-preserve-white-space{white-space:pre-wrap}\n"] }]
1185
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1186
- type: Inject,
1187
- args: [SKY_CONFIRM_CONFIG]
1188
- }] }, { type: SkyModalInstance }, { type: i2$3.SkyLibResourcesService }, { type: i2$2.SkyIdService }]; } });
1189
-
1190
1181
  /**
1191
1182
  * A service that launches modals.
1192
- * @dynamic
1193
1183
  */
1194
1184
  class SkyModalService {
1195
1185
  #dynamicComponentService;
1186
+ #environmentInjector = inject(EnvironmentInjector);
1196
1187
  constructor(dynamicComponentService) {
1197
1188
  this.#dynamicComponentService = dynamicComponentService;
1198
1189
  }
@@ -1213,7 +1204,9 @@ class SkyModalService {
1213
1204
  */
1214
1205
  open(component, config) {
1215
1206
  const modalInstance = new SkyModalInstance();
1216
- this.#createHostComponent();
1207
+ if (!SkyModalService.host) {
1208
+ SkyModalService.host = this.#createHostComponent();
1209
+ }
1217
1210
  const params = this.#getConfigFromParameter(config);
1218
1211
  params.providers ||= [];
1219
1212
  params.providers.push({
@@ -1250,25 +1243,44 @@ class SkyModalService {
1250
1243
  return params;
1251
1244
  }
1252
1245
  #createHostComponent() {
1253
- if (!SkyModalService.host) {
1254
- SkyModalService.host = this.#dynamicComponentService.createComponent(SkyModalHostComponent, {
1255
- providers: [
1256
- {
1257
- provide: SkyModalHostContext,
1258
- useValue: new SkyModalHostContext({
1259
- teardownCallback: () => {
1260
- this.dispose();
1261
- },
1262
- }),
1263
- },
1264
- ],
1265
- });
1266
- }
1246
+ const componentRef = this.#dynamicComponentService.createComponent(SkyModalHostComponent, {
1247
+ environmentInjector: this.#environmentInjector,
1248
+ providers: [
1249
+ {
1250
+ provide: SkyModalHostContext,
1251
+ useValue: new SkyModalHostContext({
1252
+ teardownCallback: () => {
1253
+ this.dispose();
1254
+ },
1255
+ }),
1256
+ },
1257
+ ],
1258
+ });
1259
+ return componentRef;
1267
1260
  }
1268
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalService, deps: [{ token: i2$2.SkyDynamicComponentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1269
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalService, providedIn: 'any' }); }
1261
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalService, deps: [{ token: i1.SkyDynamicComponentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1262
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalService, providedIn: 'root' }); }
1270
1263
  }
1271
1264
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalService, decorators: [{
1265
+ type: Injectable,
1266
+ args: [{
1267
+ providedIn: 'root',
1268
+ }]
1269
+ }], ctorParameters: function () { return [{ type: i1.SkyDynamicComponentService }]; } });
1270
+ /**
1271
+ * A service that launches modals.
1272
+ * @internal
1273
+ * @deprecated Use `SkyModalService` to open a standalone component instead.
1274
+ */
1275
+ class SkyModalLegacyService extends SkyModalService {
1276
+ /* istanbul ignore next */
1277
+ constructor(dynamicComponentSvc) {
1278
+ super(dynamicComponentSvc);
1279
+ }
1280
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalLegacyService, deps: [{ token: i1.SkyDynamicComponentLegacyService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1281
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalLegacyService, providedIn: 'any' }); }
1282
+ }
1283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalLegacyService, decorators: [{
1272
1284
  type: Injectable,
1273
1285
  args: [{
1274
1286
  // Must be 'any' so that the modal component is created in the context of its module's injector.
@@ -1276,7 +1288,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
1276
1288
  // injector and may lose context if the modal was opened from within a lazy-loaded module.
1277
1289
  providedIn: 'any',
1278
1290
  }]
1279
- }], ctorParameters: function () { return [{ type: i2$2.SkyDynamicComponentService }]; } });
1291
+ }], ctorParameters: function () { return [{ type: i1.SkyDynamicComponentLegacyService }]; } });
1280
1292
 
1281
1293
  /**
1282
1294
  * Launches a dialog.
@@ -1314,18 +1326,42 @@ class SkyConfirmService {
1314
1326
  return confirmInstance;
1315
1327
  }
1316
1328
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmService, deps: [{ token: SkyModalService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1317
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmService, providedIn: 'any' }); }
1329
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmService, providedIn: 'root' }); }
1318
1330
  }
1319
1331
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmService, decorators: [{
1320
1332
  type: Injectable,
1321
1333
  args: [{
1322
- // Must be 'any' so that the modal component is created in the context of its module's injector.
1323
- // If set to 'root', the component's dependency injections would only be derived from the root
1324
- // injector and may loose context if the modal was opened from within a lazy-loaded module.
1325
- providedIn: 'any',
1334
+ providedIn: 'root',
1326
1335
  }]
1327
1336
  }], ctorParameters: function () { return [{ type: SkyModalService }]; } });
1328
1337
 
1338
+ /**
1339
+ * Specifies content to display in the modal's footer.
1340
+ */
1341
+ class SkyModalFooterComponent {
1342
+ constructor() {
1343
+ this.errorsSvc = inject(SkyModalErrorsService);
1344
+ }
1345
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1346
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalFooterComponent, isStandalone: true, selector: "sky-modal-footer", ngImport: i0, template: "<div class=\"sky-modal-footer-container sky-padding-even-large\">\n <div aria-live=\"polite\">\n <div\n *ngIf=\"errorsSvc.formErrors | async as formErrors\"\n class=\"sky-modal-footer-errors sky-margin-stacked-lg\"\n >\n <sky-status-indicator\n *ngFor=\"let formError of formErrors\"\n [ngClass]=\"{\n 'sky-margin-stacked-lg':\n formErrors.indexOf(formError) < formErrors.length - 1,\n 'footer-error': true\n }\"\n descriptionType=\"error\"\n indicatorType=\"danger\"\n >\n {{ formError.message }}\n </sky-status-indicator>\n </div>\n </div>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-modal-footer-container{background-color:#fff;border-top:1px solid #e2e3e4}.sky-modal-footer-container .sky-btn-link:first-child{margin-left:-12px}.sky-modal-footer-container .sky-btn+.sky-btn{margin-left:10px}.sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:-2px}.sky-modal-footer-container .sky-modal-footer-errors{max-height:100px;overflow-y:auto}.sky-modal-footer-container .sky-modal-footer-errors .footer-error{display:block}.sky-theme-modern .sky-modal-footer-container{border-top:none;padding:20px 30px}.sky-theme-modern .sky-modal-footer-container .sky-btn-link:first-child{margin-left:0}.sky-theme-modern .sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:var(--sky-compat-modal-footer-adjacent-btn-btn-link-margin, 10px)}.sky-theme-modern-dark .sky-modal-footer-container{background-color:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: SkyStatusIndicatorModule }, { kind: "component", type: i2.λ10, selector: "sky-status-indicator", inputs: ["indicatorType", "descriptionType", "customDescription"] }], encapsulation: i0.ViewEncapsulation.None }); }
1347
+ }
1348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalFooterComponent, decorators: [{
1349
+ type: Component,
1350
+ args: [{ standalone: true, selector: 'sky-modal-footer', encapsulation: ViewEncapsulation.None, imports: [CommonModule, SkyStatusIndicatorModule], template: "<div class=\"sky-modal-footer-container sky-padding-even-large\">\n <div aria-live=\"polite\">\n <div\n *ngIf=\"errorsSvc.formErrors | async as formErrors\"\n class=\"sky-modal-footer-errors sky-margin-stacked-lg\"\n >\n <sky-status-indicator\n *ngFor=\"let formError of formErrors\"\n [ngClass]=\"{\n 'sky-margin-stacked-lg':\n formErrors.indexOf(formError) < formErrors.length - 1,\n 'footer-error': true\n }\"\n descriptionType=\"error\"\n indicatorType=\"danger\"\n >\n {{ formError.message }}\n </sky-status-indicator>\n </div>\n </div>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-modal-footer-container{background-color:#fff;border-top:1px solid #e2e3e4}.sky-modal-footer-container .sky-btn-link:first-child{margin-left:-12px}.sky-modal-footer-container .sky-btn+.sky-btn{margin-left:10px}.sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:-2px}.sky-modal-footer-container .sky-modal-footer-errors{max-height:100px;overflow-y:auto}.sky-modal-footer-container .sky-modal-footer-errors .footer-error{display:block}.sky-theme-modern .sky-modal-footer-container{border-top:none;padding:20px 30px}.sky-theme-modern .sky-modal-footer-container .sky-btn-link:first-child{margin-left:0}.sky-theme-modern .sky-modal-footer-container .sky-btn+.sky-btn-link{margin-left:var(--sky-compat-modal-footer-adjacent-btn-btn-link-margin, 10px)}.sky-theme-modern-dark .sky-modal-footer-container{background-color:transparent}\n"] }]
1351
+ }] });
1352
+
1353
+ /**
1354
+ * Specifies a header for the modal.
1355
+ */
1356
+ class SkyModalHeaderComponent {
1357
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1358
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalHeaderComponent, isStandalone: true, selector: "sky-modal-header", ngImport: i0, template: "<h2\n class=\"sky-font-emphasized\"\n [skyThemeClass]=\"{\n 'sky-font-heading-4': 'default',\n 'sky-font-display-3': 'modern'\n }\"\n skyTrim\n>\n <ng-content></ng-content>\n</h2>\n<span class=\"sky-control-help-container\" skyTrim\n ><ng-content select=\".sky-control-help\"></ng-content\n></span>\n", styles: ["h2{margin:0;line-height:1.2;display:inline}:host-context(.sky-theme-modern.sky-theme-mode-dark) h2{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark h2{color:#fbfcfe}\n"], dependencies: [{ kind: "ngmodule", type: SkyThemeModule }, { kind: "directive", type: i5.λ2, selector: "[skyThemeClass]", inputs: ["class", "skyThemeClass"] }, { kind: "ngmodule", type: SkyTrimModule }, { kind: "directive", type: i1.λ4, selector: "[skyTrim]" }] }); }
1359
+ }
1360
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalHeaderComponent, decorators: [{
1361
+ type: Component,
1362
+ args: [{ standalone: true, selector: 'sky-modal-header', imports: [SkyThemeModule, SkyTrimModule], template: "<h2\n class=\"sky-font-emphasized\"\n [skyThemeClass]=\"{\n 'sky-font-heading-4': 'default',\n 'sky-font-display-3': 'modern'\n }\"\n skyTrim\n>\n <ng-content></ng-content>\n</h2>\n<span class=\"sky-control-help-container\" skyTrim\n ><ng-content select=\".sky-control-help\"></ng-content\n></span>\n", styles: ["h2{margin:0;line-height:1.2;display:inline}:host-context(.sky-theme-modern.sky-theme-mode-dark) h2{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark h2{color:#fbfcfe}\n"] }]
1363
+ }] });
1364
+
1329
1365
  /**
1330
1366
  * Provides a way to mark a modal as "dirty" and displays a confirmation
1331
1367
  * message when a user closes the modal without saving.
@@ -1395,11 +1431,12 @@ class SkyModalIsDirtyDirective {
1395
1431
  }
1396
1432
  }
1397
1433
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalIsDirtyDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1398
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalIsDirtyDirective, selector: "sky-modal[isDirty]", inputs: { isDirty: "isDirty" }, host: { properties: { "attr.data-sky-modal-is-dirty": "this.isDirty" } }, ngImport: i0 }); }
1434
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: SkyModalIsDirtyDirective, isStandalone: true, selector: "sky-modal[isDirty]", inputs: { isDirty: "isDirty" }, host: { properties: { "attr.data-sky-modal-is-dirty": "this.isDirty" } }, ngImport: i0 }); }
1399
1435
  }
1400
1436
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalIsDirtyDirective, decorators: [{
1401
1437
  type: Directive,
1402
1438
  args: [{
1439
+ standalone: true,
1403
1440
  // Since this is limited to sky-modal, it should be safe to
1404
1441
  // leave off the sky prefix.
1405
1442
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -1414,54 +1451,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
1414
1451
 
1415
1452
  class SkyModalModule {
1416
1453
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1417
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, declarations: [SkyModalComponent,
1454
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, imports: [SkyModalComponent,
1418
1455
  SkyModalContentComponent,
1419
1456
  SkyModalFooterComponent,
1420
1457
  SkyModalHeaderComponent,
1421
- SkyModalHostComponent,
1422
- SkyModalIsDirtyDirective,
1423
- SkyModalScrollShadowDirective], imports: [CommonModule,
1424
- RouterModule,
1425
- SkyIconModule,
1426
- SkyIdModule,
1427
- SkyModalsResourcesModule,
1428
- SkyStatusIndicatorModule,
1429
- SkyThemeModule,
1430
- SkyTrimModule], exports: [SkyModalComponent,
1458
+ SkyModalIsDirtyDirective], exports: [SkyModalComponent,
1431
1459
  SkyModalContentComponent,
1432
1460
  SkyModalFooterComponent,
1433
1461
  SkyModalHeaderComponent,
1434
1462
  SkyModalIsDirtyDirective] }); }
1435
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, imports: [CommonModule,
1436
- RouterModule,
1437
- SkyIconModule,
1438
- SkyIdModule,
1439
- SkyModalsResourcesModule,
1440
- SkyStatusIndicatorModule,
1441
- SkyThemeModule,
1442
- SkyTrimModule] }); }
1463
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, imports: [SkyModalComponent,
1464
+ SkyModalFooterComponent,
1465
+ SkyModalHeaderComponent] }); }
1443
1466
  }
1444
1467
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyModalModule, decorators: [{
1445
1468
  type: NgModule,
1446
1469
  args: [{
1447
- declarations: [
1470
+ imports: [
1448
1471
  SkyModalComponent,
1449
1472
  SkyModalContentComponent,
1450
1473
  SkyModalFooterComponent,
1451
1474
  SkyModalHeaderComponent,
1452
- SkyModalHostComponent,
1453
1475
  SkyModalIsDirtyDirective,
1454
- SkyModalScrollShadowDirective,
1455
- ],
1456
- imports: [
1457
- CommonModule,
1458
- RouterModule,
1459
- SkyIconModule,
1460
- SkyIdModule,
1461
- SkyModalsResourcesModule,
1462
- SkyStatusIndicatorModule,
1463
- SkyThemeModule,
1464
- SkyTrimModule,
1465
1476
  ],
1466
1477
  exports: [
1467
1478
  SkyModalComponent,
@@ -1473,37 +1484,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
1473
1484
  }]
1474
1485
  }] });
1475
1486
 
1476
- class SkyConfirmModule {
1477
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1478
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, declarations: [SkyConfirmComponent], imports: [CommonModule,
1479
- SkyIdModule,
1480
- SkyModalModule,
1481
- SkyModalsResourcesModule,
1482
- SkyThemeModule], exports: [SkyConfirmComponent] }); }
1483
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, imports: [CommonModule,
1484
- SkyIdModule,
1485
- SkyModalModule,
1486
- SkyModalsResourcesModule,
1487
- SkyThemeModule] }); }
1488
- }
1489
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: SkyConfirmModule, decorators: [{
1490
- type: NgModule,
1491
- args: [{
1492
- declarations: [SkyConfirmComponent],
1493
- imports: [
1494
- CommonModule,
1495
- SkyIdModule,
1496
- SkyModalModule,
1497
- SkyModalsResourcesModule,
1498
- SkyThemeModule,
1499
- ],
1500
- exports: [SkyConfirmComponent],
1501
- }]
1502
- }] });
1503
-
1504
1487
  /**
1505
1488
  * Generated bundle index. Do not edit.
1506
1489
  */
1507
1490
 
1508
- export { SkyConfirmInstance, SkyConfirmModule, SkyConfirmService, SkyConfirmType, SkyModalBeforeCloseHandler, SkyModalCloseArgs, SkyModalConfiguration, SkyModalErrorsService, SkyModalHostService, SkyModalInstance, SkyModalModule, SkyModalService, SkyConfirmComponent as λ1, SkyModalContentComponent as λ2, SkyModalFooterComponent as λ3, SkyModalHeaderComponent as λ4, SkyModalComponent as λ5, SkyModalIsDirtyDirective as λ6 };
1491
+ export { SkyConfirmInstance, SkyConfirmModule, SkyConfirmService, SkyConfirmType, SkyModalBeforeCloseHandler, SkyModalCloseArgs, SkyModalConfiguration, SkyModalErrorsService, SkyModalHostService, SkyModalInstance, SkyModalLegacyService, SkyModalModule, SkyModalService, SkyConfirmComponent as λ1, SkyModalContentComponent as λ2, SkyModalFooterComponent as λ3, SkyModalHeaderComponent as λ4, SkyModalComponent as λ5, SkyModalIsDirtyDirective as λ6 };
1509
1492
  //# sourceMappingURL=skyux-modals.mjs.map