@almoamendev/ngx-md3 0.2.0 → 0.2.2
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.
|
@@ -12,7 +12,7 @@ import { CdkScrollable } from '@angular/cdk/scrolling';
|
|
|
12
12
|
import { FormControlName } from '@angular/forms';
|
|
13
13
|
import { CdkDialogContainer, Dialog as Dialog$1 } from '@angular/cdk/dialog';
|
|
14
14
|
import { hasModifierKey } from '@angular/cdk/keycodes';
|
|
15
|
-
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
|
|
15
|
+
import { Overlay, OverlayContainer, OverlayConfig } from '@angular/cdk/overlay';
|
|
16
16
|
|
|
17
17
|
class TypeDisplay {
|
|
18
18
|
el;
|
|
@@ -3115,6 +3115,7 @@ class DialogRef {
|
|
|
3115
3115
|
isFullScreen;
|
|
3116
3116
|
closed = new Subject();
|
|
3117
3117
|
closing = new Subject();
|
|
3118
|
+
hiddenChanges = new Subject();
|
|
3118
3119
|
closePromise = null;
|
|
3119
3120
|
closeStarted = false;
|
|
3120
3121
|
closeSettled = false;
|
|
@@ -3134,7 +3135,7 @@ class DialogRef {
|
|
|
3134
3135
|
get isClosing() {
|
|
3135
3136
|
return this.closeStarted;
|
|
3136
3137
|
}
|
|
3137
|
-
/** Whether the dialog is currently hidden behind another dialog. */
|
|
3138
|
+
/** Whether the dialog is currently hidden, on request or behind another dialog. */
|
|
3138
3139
|
get isHidden() {
|
|
3139
3140
|
return this.hidden;
|
|
3140
3141
|
}
|
|
@@ -3163,6 +3164,7 @@ class DialogRef {
|
|
|
3163
3164
|
/**
|
|
3164
3165
|
* Hides the dialog with the closing animation while keeping it alive, so
|
|
3165
3166
|
* its content, form state and subscriptions survive until show() is called.
|
|
3167
|
+
* The page underneath becomes usable again while the dialog waits behind it.
|
|
3166
3168
|
* The promise resolves once the dialog is out of sight.
|
|
3167
3169
|
*/
|
|
3168
3170
|
hide() {
|
|
@@ -3172,6 +3174,7 @@ class DialogRef {
|
|
|
3172
3174
|
this.hidden = true;
|
|
3173
3175
|
this.toggleHiddenState(true);
|
|
3174
3176
|
this.dialogInstance?.setActive(false);
|
|
3177
|
+
this.hiddenChanges.next(true);
|
|
3175
3178
|
return this.waitForSurfaceAnimation();
|
|
3176
3179
|
}
|
|
3177
3180
|
/**
|
|
@@ -3187,6 +3190,7 @@ class DialogRef {
|
|
|
3187
3190
|
this.hidden = false;
|
|
3188
3191
|
this.toggleHiddenState(false);
|
|
3189
3192
|
this.dialogInstance?.setActive(true);
|
|
3193
|
+
this.hiddenChanges.next(false);
|
|
3190
3194
|
}
|
|
3191
3195
|
this.dialogInstance?.recaptureFocus();
|
|
3192
3196
|
}
|
|
@@ -3194,6 +3198,10 @@ class DialogRef {
|
|
|
3194
3198
|
beforeClosed() {
|
|
3195
3199
|
return this.closing.asObservable();
|
|
3196
3200
|
}
|
|
3201
|
+
/** Emits the new value of `isHidden` every time the dialog is hidden or shown. */
|
|
3202
|
+
hiddenChanged() {
|
|
3203
|
+
return this.hiddenChanges.asObservable();
|
|
3204
|
+
}
|
|
3197
3205
|
afterClosed() {
|
|
3198
3206
|
return this.closed.asObservable();
|
|
3199
3207
|
}
|
|
@@ -3204,7 +3212,9 @@ class DialogRef {
|
|
|
3204
3212
|
this.cdkRef.containerInstance._closeInteractionType = 'mouse';
|
|
3205
3213
|
this.close();
|
|
3206
3214
|
});
|
|
3207
|
-
|
|
3215
|
+
// A hidden dialog is not the one the Escape key is meant for, even
|
|
3216
|
+
// though the overlay it sits in is still the one receiving the event.
|
|
3217
|
+
this.cdkRef.keydownEvents.pipe(filter((event) => !this.hidden && event.key === 'Escape' && !hasModifierKey(event)), take(1)).subscribe((event) => {
|
|
3208
3218
|
event.preventDefault();
|
|
3209
3219
|
this.cdkRef.containerInstance._closeInteractionType = 'keyboard';
|
|
3210
3220
|
this.close();
|
|
@@ -3276,6 +3286,7 @@ class DialogRef {
|
|
|
3276
3286
|
// waiting on beforeClosed() is still notified.
|
|
3277
3287
|
this.startClosing();
|
|
3278
3288
|
this.closeSettled = true;
|
|
3289
|
+
this.hiddenChanges.complete();
|
|
3279
3290
|
this.closed.next(result);
|
|
3280
3291
|
this.closed.complete();
|
|
3281
3292
|
}
|
|
@@ -3312,13 +3323,13 @@ class Dialog extends CdkDialogContainer {
|
|
|
3312
3323
|
this._recaptureFocus();
|
|
3313
3324
|
}
|
|
3314
3325
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3315
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Dialog, isStandalone: true, selector: "md3-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<section\n #surface\n class=\"md3-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <ng-template cdkPortalOutlet></ng-template>\n</section>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .md3-dialog-scrim{position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-expressive-slow-spatial-duration) var(--md-motion-expressive-slow-spatial-easing);opacity:.32}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-opening{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-closing{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-hidden{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-kept{opacity:.32;transition:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-instant{transition:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 1.5rem;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel{position:absolute;pointer-events:auto;max-width:35em}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;max-width:100%;min-width:17.5em;outline:0}:host .md3-dialog-container{display:block;width:100%;max-height:inherit;overflow:auto;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-high));border-radius:var(--md-border-radius-xlarge);box-shadow:var(--md-shadow-6dp);transform-origin:center;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8);margin-top:-8rem}:host .md3-dialog-container.md3-active{opacity:1;transform:scaleY(1);margin-top:0}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
|
|
3326
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Dialog, isStandalone: true, selector: "md3-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<section\n #surface\n class=\"md3-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <ng-template cdkPortalOutlet></ng-template>\n</section>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .md3-dialog-scrim{position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-expressive-slow-spatial-duration) var(--md-motion-expressive-slow-spatial-easing);opacity:.32}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-opening{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-closing{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-hidden{opacity:0;pointer-events:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-kept{opacity:.32;transition:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-instant{transition:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 1.5rem;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel{position:absolute;pointer-events:auto;max-width:35em}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;max-width:100%;min-width:17.5em;outline:0}:host .md3-dialog-container{display:block;width:100%;max-height:inherit;overflow:auto;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-high));border-radius:var(--md-border-radius-xlarge);box-shadow:var(--md-shadow-6dp);transform-origin:center;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8);margin-top:-8rem}:host .md3-dialog-container.md3-active{opacity:1;transform:scaleY(1);margin-top:0}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
|
|
3316
3327
|
}
|
|
3317
3328
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, decorators: [{
|
|
3318
3329
|
type: Component,
|
|
3319
3330
|
args: [{ selector: 'md3-dialog', imports: [
|
|
3320
3331
|
CdkPortalOutlet,
|
|
3321
|
-
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<section\n #surface\n class=\"md3-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <ng-template cdkPortalOutlet></ng-template>\n</section>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .md3-dialog-scrim{position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-expressive-slow-spatial-duration) var(--md-motion-expressive-slow-spatial-easing);opacity:.32}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-opening{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-closing{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-hidden{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-kept{opacity:.32;transition:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-instant{transition:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 1.5rem;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel{position:absolute;pointer-events:auto;max-width:35em}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;max-width:100%;min-width:17.5em;outline:0}:host .md3-dialog-container{display:block;width:100%;max-height:inherit;overflow:auto;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-high));border-radius:var(--md-border-radius-xlarge);box-shadow:var(--md-shadow-6dp);transform-origin:center;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8);margin-top:-8rem}:host .md3-dialog-container.md3-active{opacity:1;transform:scaleY(1);margin-top:0}\n"] }]
|
|
3332
|
+
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<section\n #surface\n class=\"md3-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <ng-template cdkPortalOutlet></ng-template>\n</section>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .md3-dialog-scrim{position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-expressive-slow-spatial-duration) var(--md-motion-expressive-slow-spatial-easing);opacity:.32}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-opening{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-closing{opacity:0}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-hidden{opacity:0;pointer-events:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-kept{opacity:.32;transition:none}::ng-deep .cdk-overlay-container .md3-dialog-scrim.md3-dialog-scrim-instant{transition:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 1.5rem;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel{position:absolute;pointer-events:auto;max-width:35em}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;max-width:100%;min-width:17.5em;outline:0}:host .md3-dialog-container{display:block;width:100%;max-height:inherit;overflow:auto;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-high));border-radius:var(--md-border-radius-xlarge);box-shadow:var(--md-shadow-6dp);transform-origin:center;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8);margin-top:-8rem}:host .md3-dialog-container.md3-active{opacity:1;transform:scaleY(1);margin-top:0}\n"] }]
|
|
3322
3333
|
}], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
|
|
3323
3334
|
|
|
3324
3335
|
/**
|
|
@@ -3397,10 +3408,16 @@ const DIALOG_HANDOVER_DELAY_MS = 160;
|
|
|
3397
3408
|
class DialogService {
|
|
3398
3409
|
cdkDialog = inject(Dialog$1);
|
|
3399
3410
|
overlay = inject(Overlay);
|
|
3411
|
+
overlayContainer = inject(OverlayContainer);
|
|
3400
3412
|
injector = inject(Injector);
|
|
3401
3413
|
document = inject(DOCUMENT);
|
|
3402
3414
|
/** Open dialogs, from the first one opened to the one currently on top. */
|
|
3403
3415
|
refs = [];
|
|
3416
|
+
/**
|
|
3417
|
+
* Elements the page was made of that the CDK hid from assistive technology,
|
|
3418
|
+
* kept here while the dialogs are hidden and the page is given back.
|
|
3419
|
+
*/
|
|
3420
|
+
pageAriaHidden = new Map();
|
|
3404
3421
|
/**
|
|
3405
3422
|
* Page scrolling is blocked here instead of per overlay, so stacked dialogs
|
|
3406
3423
|
* cannot unblock the page while another dialog is still open.
|
|
@@ -3408,9 +3425,14 @@ class DialogService {
|
|
|
3408
3425
|
scrollBlock = this.overlay.scrollStrategies.block();
|
|
3409
3426
|
/** Element that was focused before the first dialog of the stack opened. */
|
|
3410
3427
|
rootTrigger = null;
|
|
3428
|
+
pageStateQueued = false;
|
|
3411
3429
|
get openDialogs() {
|
|
3412
3430
|
return this.refs;
|
|
3413
3431
|
}
|
|
3432
|
+
/** Open dialogs that are currently on screen, from the bottom one up. */
|
|
3433
|
+
get visibleDialogs() {
|
|
3434
|
+
return this.refs.filter((ref) => !ref.isHidden);
|
|
3435
|
+
}
|
|
3414
3436
|
/** The full screen dialog that is open, if there is one. */
|
|
3415
3437
|
get fullScreenDialog() {
|
|
3416
3438
|
return this.refs.find((ref) => ref.isFullScreen && !ref.isClosing);
|
|
@@ -3546,7 +3568,7 @@ class DialogService {
|
|
|
3546
3568
|
this.bindDataToInputs(cdkRef.componentRef, dialogConfig);
|
|
3547
3569
|
}
|
|
3548
3570
|
this.refs.push(dialogRef);
|
|
3549
|
-
this.
|
|
3571
|
+
this.syncPageState();
|
|
3550
3572
|
if (previousRef) {
|
|
3551
3573
|
setTimeout(() => this.startReplacingAnimation(dialogRef, previousRef), DIALOG_HANDOVER_DELAY_MS);
|
|
3552
3574
|
}
|
|
@@ -3557,6 +3579,41 @@ class DialogService {
|
|
|
3557
3579
|
// already coming back while this one is fading out.
|
|
3558
3580
|
dialogRef.beforeClosed().subscribe(() => this.restorePreviousDialog(dialogRef));
|
|
3559
3581
|
dialogRef.afterClosed().subscribe(() => this.removeRef(dialogRef));
|
|
3582
|
+
// Hiding and showing can also come straight from the reference, so the
|
|
3583
|
+
// page state is driven by what the dialogs report rather than by the
|
|
3584
|
+
// calls that went through this service.
|
|
3585
|
+
dialogRef.hiddenChanged().subscribe(() => this.syncPageState());
|
|
3586
|
+
}
|
|
3587
|
+
/**
|
|
3588
|
+
* Hides every dialog that is on screen, the full screen one included, with
|
|
3589
|
+
* the closing animation. They stay alive with their content and state, the
|
|
3590
|
+
* page underneath becomes usable, and showAll() puts them back. The promise
|
|
3591
|
+
* resolves once they are all out of sight.
|
|
3592
|
+
*/
|
|
3593
|
+
hideAll() {
|
|
3594
|
+
const visible = this.refs.filter((ref) => !ref.isHidden && !ref.isClosing);
|
|
3595
|
+
return Promise.all(visible.map((ref) => ref.hide())).then(() => undefined);
|
|
3596
|
+
}
|
|
3597
|
+
/**
|
|
3598
|
+
* Brings the dialogs back on screen, whether they were hidden one by one or
|
|
3599
|
+
* all at once: the dialog that was on top returns, along with the full
|
|
3600
|
+
* screen dialog it sits in. Dialogs hidden behind another dialog stay
|
|
3601
|
+
* hidden, since that is where they belong once the stack is back.
|
|
3602
|
+
*/
|
|
3603
|
+
showAll() {
|
|
3604
|
+
const topRef = this.topRef();
|
|
3605
|
+
if (!topRef) {
|
|
3606
|
+
return;
|
|
3607
|
+
}
|
|
3608
|
+
const fullScreenRef = this.fullScreenDialog;
|
|
3609
|
+
// The full screen dialog is the context the top one sits in, so it
|
|
3610
|
+
// comes back first and the dialog on top ends up on top, with the focus.
|
|
3611
|
+
if (fullScreenRef && fullScreenRef !== topRef && fullScreenRef.isHidden) {
|
|
3612
|
+
fullScreenRef.show();
|
|
3613
|
+
}
|
|
3614
|
+
if (topRef.isHidden) {
|
|
3615
|
+
topRef.show();
|
|
3616
|
+
}
|
|
3560
3617
|
}
|
|
3561
3618
|
/** Closes every open dialog, including the hidden and the full screen ones. */
|
|
3562
3619
|
closeAll() {
|
|
@@ -3719,15 +3776,82 @@ class DialogService {
|
|
|
3719
3776
|
if (this.refs.length === 0) {
|
|
3720
3777
|
this.rootTrigger = null;
|
|
3721
3778
|
}
|
|
3722
|
-
this.
|
|
3779
|
+
this.syncPageState();
|
|
3723
3780
|
}
|
|
3724
|
-
|
|
3725
|
-
|
|
3781
|
+
/**
|
|
3782
|
+
* State that belongs to the dialogs as a whole rather than to one of them:
|
|
3783
|
+
* page scrolling, the page being hidden from assistive technology, and
|
|
3784
|
+
* where focus sits. Applied in a task of its own, so a dialog handing the
|
|
3785
|
+
* screen over to another one does not give the page back and take it again
|
|
3786
|
+
* within the same frame.
|
|
3787
|
+
*/
|
|
3788
|
+
syncPageState() {
|
|
3789
|
+
if (this.pageStateQueued) {
|
|
3790
|
+
return;
|
|
3791
|
+
}
|
|
3792
|
+
this.pageStateQueued = true;
|
|
3793
|
+
setTimeout(() => {
|
|
3794
|
+
this.pageStateQueued = false;
|
|
3795
|
+
this.applyPageState();
|
|
3796
|
+
});
|
|
3797
|
+
}
|
|
3798
|
+
applyPageState() {
|
|
3799
|
+
const hasVisibleDialog = this.refs.some((ref) => !ref.isHidden);
|
|
3800
|
+
if (hasVisibleDialog) {
|
|
3726
3801
|
this.scrollBlock.enable();
|
|
3727
3802
|
}
|
|
3728
3803
|
else {
|
|
3729
3804
|
this.scrollBlock.disable();
|
|
3730
3805
|
}
|
|
3806
|
+
if (this.refs.length === 0) {
|
|
3807
|
+
// Nothing is open anymore: the CDK gives the page back to assistive
|
|
3808
|
+
// technology on its own, so there is nothing left to restore here.
|
|
3809
|
+
this.pageAriaHidden.clear();
|
|
3810
|
+
return;
|
|
3811
|
+
}
|
|
3812
|
+
if (hasVisibleDialog) {
|
|
3813
|
+
this.hidePageFromAssistiveTechnology();
|
|
3814
|
+
return;
|
|
3815
|
+
}
|
|
3816
|
+
this.exposePageToAssistiveTechnology();
|
|
3817
|
+
this.releaseFocus();
|
|
3818
|
+
}
|
|
3819
|
+
/**
|
|
3820
|
+
* Gives the page back to assistive technology while every dialog is hidden.
|
|
3821
|
+
* The CDK hides it for as long as a dialog is open, which would otherwise
|
|
3822
|
+
* leave nothing to read at all once the dialogs are out of sight.
|
|
3823
|
+
*/
|
|
3824
|
+
exposePageToAssistiveTechnology() {
|
|
3825
|
+
if (this.pageAriaHidden.size > 0) {
|
|
3826
|
+
return;
|
|
3827
|
+
}
|
|
3828
|
+
const container = this.overlayContainer.getContainerElement();
|
|
3829
|
+
Array.from(container.parentElement?.children ?? []).forEach((sibling) => {
|
|
3830
|
+
const value = sibling.getAttribute('aria-hidden');
|
|
3831
|
+
if (sibling === container || value === null) {
|
|
3832
|
+
return;
|
|
3833
|
+
}
|
|
3834
|
+
this.pageAriaHidden.set(sibling, value);
|
|
3835
|
+
sibling.removeAttribute('aria-hidden');
|
|
3836
|
+
});
|
|
3837
|
+
}
|
|
3838
|
+
/** Hides the page again as soon as a dialog is back on screen. */
|
|
3839
|
+
hidePageFromAssistiveTechnology() {
|
|
3840
|
+
this.pageAriaHidden.forEach((value, element) => {
|
|
3841
|
+
element.setAttribute('aria-hidden', value);
|
|
3842
|
+
});
|
|
3843
|
+
this.pageAriaHidden.clear();
|
|
3844
|
+
}
|
|
3845
|
+
/**
|
|
3846
|
+
* Focus follows the dialogs off the screen: it goes back to whatever opened
|
|
3847
|
+
* the stack, so the page stays usable with the keyboard while the dialogs
|
|
3848
|
+
* wait behind it. Focus that already moved somewhere else is left alone.
|
|
3849
|
+
*/
|
|
3850
|
+
releaseFocus() {
|
|
3851
|
+
const activeElement = this.document.activeElement;
|
|
3852
|
+
if (this.rootTrigger && (!activeElement || activeElement === this.document.body)) {
|
|
3853
|
+
this.rootTrigger.focus();
|
|
3854
|
+
}
|
|
3731
3855
|
}
|
|
3732
3856
|
getFocusedElement() {
|
|
3733
3857
|
const activeElement = this.document.activeElement;
|
|
@@ -3782,31 +3906,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3782
3906
|
* the content scrolls underneath.
|
|
3783
3907
|
*/
|
|
3784
3908
|
class FullScreenDialogHeader {
|
|
3785
|
-
title = input('', { ...(ngDevMode ? { debugName: "title" } : /* istanbul ignore next */ {}), alias: 'title' });
|
|
3786
3909
|
// context values
|
|
3787
3910
|
buttonContextSize = signal('small', /* @ts-ignore */
|
|
3788
3911
|
...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
|
|
3789
3912
|
buttonContextWidth = signal('default', /* @ts-ignore */
|
|
3790
3913
|
...(ngDevMode ? [{ debugName: "buttonContextWidth" }] : /* istanbul ignore next */ []));
|
|
3791
3914
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialogHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3792
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
3915
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: FullScreenDialogHeader, isStandalone: true, selector: "md3-fullscreen-dialog-header", providers: [
|
|
3793
3916
|
{
|
|
3794
3917
|
provide: MD3_BUTTON_CONTEXT,
|
|
3795
3918
|
useExisting: FullScreenDialogHeader,
|
|
3796
3919
|
},
|
|
3797
|
-
], ngImport: i0, template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <
|
|
3920
|
+
], ngImport: i0, template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <ng-content></ng-content>\n</div>\n<div class=\"md3-actions-container\">\n <ng-content select=\"[md3-header-trailing]\"></ng-content>\n</div>\n", styles: [":host{--foreground-color: rgb(var(--md-scheme-on-surface));position:sticky;top:0;z-index:3;grid-area:header;display:flex;align-items:center;gap:.5em;height:4em;padding:0 1em;color:var(--foreground-color);background-color:rgb(var(--md-scheme-surface))}:host ::ng-deep [md3-header-leading]:first-child{margin-inline-start:-.5em}:host .md3-title-container{flex:1 1 auto;min-width:0;color:inherit}:host .md3-title-container:first-child{padding-inline-start:.5em}:host .md3-actions-container{display:flex;flex:0 0 auto;align-items:center;gap:.5em}\n"] });
|
|
3798
3921
|
}
|
|
3799
3922
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialogHeader, decorators: [{
|
|
3800
3923
|
type: Component,
|
|
3801
|
-
args: [{ selector: 'md3-fullscreen-dialog-header', imports: [
|
|
3802
|
-
TypeTitle,
|
|
3803
|
-
], providers: [
|
|
3924
|
+
args: [{ selector: 'md3-fullscreen-dialog-header', imports: [], providers: [
|
|
3804
3925
|
{
|
|
3805
3926
|
provide: MD3_BUTTON_CONTEXT,
|
|
3806
3927
|
useExisting: FullScreenDialogHeader,
|
|
3807
3928
|
},
|
|
3808
|
-
], template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <
|
|
3809
|
-
}]
|
|
3929
|
+
], template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <ng-content></ng-content>\n</div>\n<div class=\"md3-actions-container\">\n <ng-content select=\"[md3-header-trailing]\"></ng-content>\n</div>\n", styles: [":host{--foreground-color: rgb(var(--md-scheme-on-surface));position:sticky;top:0;z-index:3;grid-area:header;display:flex;align-items:center;gap:.5em;height:4em;padding:0 1em;color:var(--foreground-color);background-color:rgb(var(--md-scheme-surface))}:host ::ng-deep [md3-header-leading]:first-child{margin-inline-start:-.5em}:host .md3-title-container{flex:1 1 auto;min-width:0;color:inherit}:host .md3-title-container:first-child{padding-inline-start:.5em}:host .md3-actions-container{display:flex;flex:0 0 auto;align-items:center;gap:.5em}\n"] }]
|
|
3930
|
+
}] });
|
|
3810
3931
|
|
|
3811
3932
|
const MENU_DATA = new InjectionToken('MD3_MENU_DATA');
|
|
3812
3933
|
const MENU_CONFIG = new InjectionToken('MD3_MENU_CONFIG');
|