@almoamendev/ngx-md3 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, booleanAttribute, effect, Directive, inject, signal, computed, Injectable, InjectionToken, ViewChild, Component, ViewContainerRef, Injector, viewChild, numberAttribute, HostListener, model, contentChild, contentChildren, PLATFORM_ID, afterNextRender, output, ElementRef, HostBinding, TemplateRef } from '@angular/core';
|
|
2
|
+
import { input, booleanAttribute, effect, Directive, inject, signal, computed, Injectable, InjectionToken, ViewChild, Component, ViewContainerRef, Injector, viewChild, numberAttribute, HostListener, model, contentChild, contentChildren, PLATFORM_ID, afterNextRender, output, ElementRef, HostBinding, NgZone, TemplateRef } from '@angular/core';
|
|
3
3
|
import { DOCUMENT, isPlatformBrowser, NgClass, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
5
5
|
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
6
|
import * as i1 from '@angular/router';
|
|
7
7
|
import { Router, NavigationEnd, RouterLinkActive } from '@angular/router';
|
|
8
|
-
import { fromEvent, startWith, map, filter, Subscription, Subject, merge, take } from 'rxjs';
|
|
8
|
+
import { fromEvent, startWith, map, filter, Subscription, Subject, merge, take, takeUntil } from 'rxjs';
|
|
9
9
|
import { ComponentPortal, CdkPortalOutlet } from '@angular/cdk/portal';
|
|
10
10
|
import * as i2 from '@angular/cdk/scrolling';
|
|
11
11
|
import { CdkScrollable } from '@angular/cdk/scrolling';
|
|
@@ -4334,13 +4334,13 @@ class Dialog extends CdkDialogContainer {
|
|
|
4334
4334
|
this._recaptureFocus();
|
|
4335
4335
|
}
|
|
4336
4336
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4337
|
-
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<
|
|
4337
|
+
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<div\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</div>\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"] }] });
|
|
4338
4338
|
}
|
|
4339
4339
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, decorators: [{
|
|
4340
4340
|
type: Component,
|
|
4341
4341
|
args: [{ selector: 'md3-dialog', imports: [
|
|
4342
4342
|
CdkPortalOutlet,
|
|
4343
|
-
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<
|
|
4343
|
+
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\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</div>\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"] }]
|
|
4344
4344
|
}], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
|
|
4345
4345
|
|
|
4346
4346
|
/**
|
|
@@ -4396,18 +4396,18 @@ class FullScreenDialog extends CdkDialogContainer {
|
|
|
4396
4396
|
this._recaptureFocus();
|
|
4397
4397
|
}
|
|
4398
4398
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4399
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: FullScreenDialog, isStandalone: true, selector: "md3-fullscreen-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }, { propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<
|
|
4399
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: FullScreenDialog, isStandalone: true, selector: "md3-fullscreen-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }, { propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-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 <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\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 .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;overflow-y:visible;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
|
|
4400
4400
|
}
|
|
4401
4401
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, decorators: [{
|
|
4402
4402
|
type: Component,
|
|
4403
4403
|
args: [{ selector: 'md3-fullscreen-dialog', imports: [
|
|
4404
4404
|
CdkPortalOutlet,
|
|
4405
|
-
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<
|
|
4405
|
+
], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-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 <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\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 .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;overflow-y:visible;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
|
|
4406
4406
|
}], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }], startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }] } });
|
|
4407
4407
|
|
|
4408
|
-
const PANEL_CLASS = 'md3-dialog-panel';
|
|
4408
|
+
const PANEL_CLASS$1 = 'md3-dialog-panel';
|
|
4409
4409
|
const FULL_SCREEN_PANEL_CLASS = 'md3-fullscreen-dialog-panel';
|
|
4410
|
-
const OPENING_CLASS = 'md3-dialog-opening';
|
|
4410
|
+
const OPENING_CLASS$1 = 'md3-dialog-opening';
|
|
4411
4411
|
const SCRIM_KEPT_CLASS = 'md3-dialog-scrim-kept';
|
|
4412
4412
|
const SCRIM_INSTANT_CLASS = 'md3-dialog-scrim-instant';
|
|
4413
4413
|
/**
|
|
@@ -4492,8 +4492,8 @@ class DialogService {
|
|
|
4492
4492
|
viewContainerRef: dialogConfig.viewContainerRef,
|
|
4493
4493
|
injector: dialogConfig.injector,
|
|
4494
4494
|
hasBackdrop: true,
|
|
4495
|
-
backdropClass: ['md3-dialog-scrim', OPENING_CLASS],
|
|
4496
|
-
panelClass: [PANEL_CLASS, OPENING_CLASS],
|
|
4495
|
+
backdropClass: ['md3-dialog-scrim', OPENING_CLASS$1],
|
|
4496
|
+
panelClass: [PANEL_CLASS$1, OPENING_CLASS$1],
|
|
4497
4497
|
positionStrategy: this.overlay.position()
|
|
4498
4498
|
.global()
|
|
4499
4499
|
.centerHorizontally()
|
|
@@ -4557,7 +4557,7 @@ class DialogService {
|
|
|
4557
4557
|
// The dialog covers the page on its own, so there is nothing left
|
|
4558
4558
|
// for a scrim to dim.
|
|
4559
4559
|
hasBackdrop: false,
|
|
4560
|
-
panelClass: [FULL_SCREEN_PANEL_CLASS, OPENING_CLASS],
|
|
4560
|
+
panelClass: [FULL_SCREEN_PANEL_CLASS, OPENING_CLASS$1],
|
|
4561
4561
|
// The CDK writes the size on the panel and the global strategy then
|
|
4562
4562
|
// drops its centering margins, which is how the panel ends up
|
|
4563
4563
|
// covering the whole wrapper.
|
|
@@ -4674,8 +4674,8 @@ class DialogService {
|
|
|
4674
4674
|
requestAnimationFrame(() => {
|
|
4675
4675
|
setTimeout(() => {
|
|
4676
4676
|
panel.getBoundingClientRect();
|
|
4677
|
-
panel.classList.remove(OPENING_CLASS);
|
|
4678
|
-
backdrop?.classList.remove(OPENING_CLASS);
|
|
4677
|
+
panel.classList.remove(OPENING_CLASS$1);
|
|
4678
|
+
backdrop?.classList.remove(OPENING_CLASS$1);
|
|
4679
4679
|
}, 100);
|
|
4680
4680
|
});
|
|
4681
4681
|
dialogRef.dialogInstance?.startEnterAnimation();
|
|
@@ -4689,8 +4689,8 @@ class DialogService {
|
|
|
4689
4689
|
const backdrop = dialogRef.overlayRef.backdropElement;
|
|
4690
4690
|
this.beginScrimHandover(previousRef, dialogRef);
|
|
4691
4691
|
panel.getBoundingClientRect();
|
|
4692
|
-
panel.classList.remove(OPENING_CLASS);
|
|
4693
|
-
backdrop?.classList.remove(OPENING_CLASS);
|
|
4692
|
+
panel.classList.remove(OPENING_CLASS$1);
|
|
4693
|
+
backdrop?.classList.remove(OPENING_CLASS$1);
|
|
4694
4694
|
this.endScrimHandover(previousRef, dialogRef);
|
|
4695
4695
|
dialogRef.dialogInstance?.startEnterAnimation();
|
|
4696
4696
|
}
|
|
@@ -5622,6 +5622,507 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
5622
5622
|
}, template: "<ng-content></ng-content>", styles: [":host{padding:1em 1em 1.5em;position:relative;display:flex;gap:.5em}:host.md3-style-divider:after{content:\"\";position:absolute;height:.0625em;width:100%;inset:0 0 auto;background-color:rgb(var(--md-scheme-outline-variant));pointer-events:none}\n"] }]
|
|
5623
5623
|
}], propDecorators: { showDivider: [{ type: i0.Input, args: [{ isSignal: true, alias: "show-divider", required: false }] }] } });
|
|
5624
5624
|
|
|
5625
|
+
const BOTTOM_SHEET_DATA = new InjectionToken('MD3_BOTTOM_SHEET_DATA');
|
|
5626
|
+
const BOTTOM_SHEET_CONFIG = new InjectionToken('MD3_BOTTOM_SHEET_CONFIG');
|
|
5627
|
+
const BOTTOM_SHEET_COMPONENT = new InjectionToken('MD3_BOTTOM_SHEET_COMPONENT');
|
|
5628
|
+
const BOTTOM_SHEET_EXIT_ANIMATION_FALLBACK_MS = 300;
|
|
5629
|
+
const BOTTOM_SHEET_DRAGGING_CLASS = 'md3-bottom-sheet-dragging';
|
|
5630
|
+
/**
|
|
5631
|
+
* A bottom sheet is a single modal overlay, not a stack like dialogs can be,
|
|
5632
|
+
* so this is a smaller version of DialogRef: no hide/show, no full screen
|
|
5633
|
+
* variant, closing is always the only way out.
|
|
5634
|
+
*/
|
|
5635
|
+
class BottomSheetRef {
|
|
5636
|
+
cdkRef;
|
|
5637
|
+
closed = new Subject();
|
|
5638
|
+
closeStarted = false;
|
|
5639
|
+
closeSettled = false;
|
|
5640
|
+
/** Shell hosting the sheet. Filled by BottomSheetService once it is created. */
|
|
5641
|
+
sheetInstance;
|
|
5642
|
+
/** Filled by BottomSheetService after the sheet component is attached. */
|
|
5643
|
+
componentInstance;
|
|
5644
|
+
/** Overlay hosting the sheet, useful to reach the panel and the scrim. */
|
|
5645
|
+
get overlayRef() {
|
|
5646
|
+
return this.cdkRef.overlayRef;
|
|
5647
|
+
}
|
|
5648
|
+
/** Whether the sheet started closing. */
|
|
5649
|
+
get isClosing() {
|
|
5650
|
+
return this.closeStarted;
|
|
5651
|
+
}
|
|
5652
|
+
constructor(cdkRef) {
|
|
5653
|
+
this.cdkRef = cdkRef;
|
|
5654
|
+
this.cdkRef.closed.pipe(take(1)).subscribe((result) => this.settle(result));
|
|
5655
|
+
this.connectCloseEvents();
|
|
5656
|
+
}
|
|
5657
|
+
/** Closes the sheet. The promise resolves once the exit animation is done. */
|
|
5658
|
+
close(result) {
|
|
5659
|
+
if (this.closeStarted) {
|
|
5660
|
+
return Promise.resolve();
|
|
5661
|
+
}
|
|
5662
|
+
this.closeStarted = true;
|
|
5663
|
+
return this.startCloseAnimation().then(() => this.cdkRef.close(result));
|
|
5664
|
+
}
|
|
5665
|
+
afterClosed() {
|
|
5666
|
+
return this.closed.asObservable();
|
|
5667
|
+
}
|
|
5668
|
+
/**
|
|
5669
|
+
* Wires the shell to this reference. Called by BottomSheetService, since the shell is
|
|
5670
|
+
* created by the CDK before this reference exists and cannot reach it through DI.
|
|
5671
|
+
*/
|
|
5672
|
+
attachContainer(container) {
|
|
5673
|
+
this.sheetInstance = container;
|
|
5674
|
+
container.dismissed.pipe(take(1)).subscribe(() => this.close());
|
|
5675
|
+
container.dragProgress.pipe(takeUntil(this.closed)).subscribe((progress) => this.trackDragProgress(progress));
|
|
5676
|
+
}
|
|
5677
|
+
/** Fades the scrim along with the sheet being dragged, and hands it back to CSS on release. */
|
|
5678
|
+
trackDragProgress(progress) {
|
|
5679
|
+
const backdrop = this.cdkRef.overlayRef.backdropElement;
|
|
5680
|
+
if (!backdrop || this.closeStarted) {
|
|
5681
|
+
return;
|
|
5682
|
+
}
|
|
5683
|
+
if (progress <= 0) {
|
|
5684
|
+
backdrop.classList.remove(BOTTOM_SHEET_DRAGGING_CLASS);
|
|
5685
|
+
backdrop.style.removeProperty('--md3-drag-remaining');
|
|
5686
|
+
return;
|
|
5687
|
+
}
|
|
5688
|
+
backdrop.classList.add(BOTTOM_SHEET_DRAGGING_CLASS);
|
|
5689
|
+
backdrop.style.setProperty('--md3-drag-remaining', `${1 - progress}`);
|
|
5690
|
+
}
|
|
5691
|
+
connectCloseEvents() {
|
|
5692
|
+
// The CDK config keeps `disableClose` on, so the scrim and Escape key
|
|
5693
|
+
// are handled here instead and the sheet can animate out.
|
|
5694
|
+
this.cdkRef.backdropClick.pipe(take(1)).subscribe(() => this.close());
|
|
5695
|
+
this.cdkRef.keydownEvents.pipe(filter((event) => event.key === 'Escape' && !hasModifierKey(event)), take(1)).subscribe((event) => {
|
|
5696
|
+
event.preventDefault();
|
|
5697
|
+
this.close();
|
|
5698
|
+
});
|
|
5699
|
+
}
|
|
5700
|
+
startCloseAnimation() {
|
|
5701
|
+
const overlayRef = this.cdkRef.overlayRef;
|
|
5702
|
+
// Closing during a drag, from the Escape key for instance, leaves the scrim held
|
|
5703
|
+
// where the drag left it, so it is handed back to CSS before the exit animation.
|
|
5704
|
+
overlayRef.backdropElement?.classList.remove(BOTTOM_SHEET_DRAGGING_CLASS);
|
|
5705
|
+
overlayRef.backdropElement?.style.removeProperty('--md3-drag-remaining');
|
|
5706
|
+
overlayRef.overlayElement.classList.add('md3-bottom-sheet-closing');
|
|
5707
|
+
overlayRef.backdropElement?.classList.add('md3-bottom-sheet-closing');
|
|
5708
|
+
this.sheetInstance?.setActive(false);
|
|
5709
|
+
return this.waitForSurfaceAnimation();
|
|
5710
|
+
}
|
|
5711
|
+
/** Resolves when the surface finished animating, with a timeout as a safety net. */
|
|
5712
|
+
waitForSurfaceAnimation() {
|
|
5713
|
+
const panel = this.cdkRef.overlayRef.overlayElement;
|
|
5714
|
+
const surface = this.sheetInstance?.surfaceElement ?? panel;
|
|
5715
|
+
return new Promise((resolve) => {
|
|
5716
|
+
let isResolved = false;
|
|
5717
|
+
const timeoutId = setTimeout(done, BOTTOM_SHEET_EXIT_ANIMATION_FALLBACK_MS);
|
|
5718
|
+
function done() {
|
|
5719
|
+
if (isResolved) {
|
|
5720
|
+
return;
|
|
5721
|
+
}
|
|
5722
|
+
isResolved = true;
|
|
5723
|
+
clearTimeout(timeoutId);
|
|
5724
|
+
surface.removeEventListener('transitionend', onTransitionEnd);
|
|
5725
|
+
resolve();
|
|
5726
|
+
}
|
|
5727
|
+
function onTransitionEnd(event) {
|
|
5728
|
+
if (event.target === surface) {
|
|
5729
|
+
done();
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
surface.addEventListener('transitionend', onTransitionEnd);
|
|
5733
|
+
});
|
|
5734
|
+
}
|
|
5735
|
+
/** Emits the result once the CDK reference is closed. Focus is restored by the container. */
|
|
5736
|
+
settle(result) {
|
|
5737
|
+
if (this.closeSettled) {
|
|
5738
|
+
return;
|
|
5739
|
+
}
|
|
5740
|
+
this.closeStarted = true;
|
|
5741
|
+
this.closeSettled = true;
|
|
5742
|
+
this.closed.next(result);
|
|
5743
|
+
this.closed.complete();
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5746
|
+
|
|
5747
|
+
/** Movement shorter than this is still a tap rather than a drag. */
|
|
5748
|
+
const DRAG_START_THRESHOLD_PX = 4;
|
|
5749
|
+
/** Part of the sheet's height a drag has to cover for the sheet to be dismissed on release. */
|
|
5750
|
+
const DISMISS_DISTANCE_RATIO = 0.4;
|
|
5751
|
+
/** Downward speed, in pixels per millisecond, that dismisses the sheet whatever distance it covered. */
|
|
5752
|
+
const DISMISS_VELOCITY = 0.5;
|
|
5753
|
+
/** A release this long after the last move is a stop, so the speed before it no longer counts. */
|
|
5754
|
+
const VELOCITY_TIMEOUT_MS = 100;
|
|
5755
|
+
/**
|
|
5756
|
+
* Material 3 bottom sheet shell. Like Dialog, it extends the CDK dialog
|
|
5757
|
+
* container so focus trapping, focus restoration and the ARIA attributes are
|
|
5758
|
+
* handled by the CDK while this component only owns the MD3 surface, its
|
|
5759
|
+
* drag handle and the slide-up animation. There is no docked variant: a
|
|
5760
|
+
* bottom sheet is always a modal overlay.
|
|
5761
|
+
*
|
|
5762
|
+
* The shell also owns the drag gesture. Dragging the surface down follows the
|
|
5763
|
+
* pointer, and releasing either dismisses the sheet or snaps it back. Since the
|
|
5764
|
+
* shell is created before BottomSheetRef exists, it reports the gesture through
|
|
5765
|
+
* observables the reference subscribes to instead of closing the sheet itself.
|
|
5766
|
+
*/
|
|
5767
|
+
class BottomSheet extends CdkDialogContainer {
|
|
5768
|
+
surface = viewChild('surface', /* @ts-ignore */
|
|
5769
|
+
...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
|
|
5770
|
+
zone = inject(NgZone);
|
|
5771
|
+
dismissedSheet = new Subject();
|
|
5772
|
+
draggedSheet = new Subject();
|
|
5773
|
+
config = inject(BOTTOM_SHEET_CONFIG, { optional: true }) ?? {};
|
|
5774
|
+
isActive = signal(false, /* @ts-ignore */
|
|
5775
|
+
...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
5776
|
+
showHandle = signal(this.config.handle ?? true, /* @ts-ignore */
|
|
5777
|
+
...(ngDevMode ? [{ debugName: "showHandle" }] : /* istanbul ignore next */ []));
|
|
5778
|
+
allowGestures = signal(this.config.gestures ?? true, /* @ts-ignore */
|
|
5779
|
+
...(ngDevMode ? [{ debugName: "allowGestures" }] : /* istanbul ignore next */ []));
|
|
5780
|
+
/** How far below its resting position the drag is currently holding the sheet, in pixels. */
|
|
5781
|
+
dragOffset = signal(0, /* @ts-ignore */
|
|
5782
|
+
...(ngDevMode ? [{ debugName: "dragOffset" }] : /* istanbul ignore next */ []));
|
|
5783
|
+
isDragging = signal(false, /* @ts-ignore */
|
|
5784
|
+
...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
|
|
5785
|
+
/**
|
|
5786
|
+
* Only set while the sheet sits away from its resting position, so the opening and
|
|
5787
|
+
* closing transforms in the stylesheet stay in charge the rest of the time.
|
|
5788
|
+
*/
|
|
5789
|
+
dragTransform = computed(() => {
|
|
5790
|
+
const offset = this.dragOffset();
|
|
5791
|
+
return offset > 0 ? `translateY(${offset}px)` : null;
|
|
5792
|
+
}, /* @ts-ignore */
|
|
5793
|
+
...(ngDevMode ? [{ debugName: "dragTransform" }] : /* istanbul ignore next */ []));
|
|
5794
|
+
/** Pointer currently dragging the sheet, if there is one. */
|
|
5795
|
+
pointerId;
|
|
5796
|
+
/** Scrollable the drag started over, which owns the gesture until it is scrolled to the top. */
|
|
5797
|
+
scroller = null;
|
|
5798
|
+
startY = 0;
|
|
5799
|
+
lastY = 0;
|
|
5800
|
+
lastTimestamp = 0;
|
|
5801
|
+
velocity = 0;
|
|
5802
|
+
isPastThreshold = false;
|
|
5803
|
+
dismissed = this.dismissedSheet.asObservable();
|
|
5804
|
+
dragProgress = this.draggedSheet.asObservable();
|
|
5805
|
+
get surfaceElement() {
|
|
5806
|
+
return this.surface()?.nativeElement ?? null;
|
|
5807
|
+
}
|
|
5808
|
+
startEnterAnimation() {
|
|
5809
|
+
requestAnimationFrame(() => {
|
|
5810
|
+
this.isActive.set(true);
|
|
5811
|
+
});
|
|
5812
|
+
}
|
|
5813
|
+
setActive(value) {
|
|
5814
|
+
this.isActive.set(value);
|
|
5815
|
+
}
|
|
5816
|
+
recaptureFocus() {
|
|
5817
|
+
this._recaptureFocus();
|
|
5818
|
+
}
|
|
5819
|
+
ngOnDestroy() {
|
|
5820
|
+
this.stopTracking();
|
|
5821
|
+
super.ngOnDestroy();
|
|
5822
|
+
}
|
|
5823
|
+
onPointerDown(event) {
|
|
5824
|
+
// Only the first pointer down drags: a second finger, or a mouse button other than
|
|
5825
|
+
// the primary one, leaves context menus and multi-touch alone.
|
|
5826
|
+
if (!this.allowGestures() || this.pointerId !== undefined || !event.isPrimary) {
|
|
5827
|
+
return;
|
|
5828
|
+
}
|
|
5829
|
+
if (event.pointerType === 'mouse' && event.button !== 0) {
|
|
5830
|
+
return;
|
|
5831
|
+
}
|
|
5832
|
+
this.pointerId = event.pointerId;
|
|
5833
|
+
this.startY = this.lastY = event.clientY;
|
|
5834
|
+
this.lastTimestamp = event.timeStamp;
|
|
5835
|
+
this.velocity = 0;
|
|
5836
|
+
this.isPastThreshold = false;
|
|
5837
|
+
this.scroller = this.findScroller(event.target);
|
|
5838
|
+
// Tracking a drag at pointer rate has nothing to tell the rest of the application,
|
|
5839
|
+
// and the signals it writes schedule their own change detection.
|
|
5840
|
+
this.zone.runOutsideAngular(() => {
|
|
5841
|
+
this.surfaceElement?.addEventListener('touchmove', this.onTouchMove, { passive: false });
|
|
5842
|
+
window.addEventListener('pointermove', this.onPointerMove);
|
|
5843
|
+
window.addEventListener('pointerup', this.onPointerUp);
|
|
5844
|
+
window.addEventListener('pointercancel', this.onPointerCancel);
|
|
5845
|
+
});
|
|
5846
|
+
}
|
|
5847
|
+
onPointerMove = (event) => {
|
|
5848
|
+
if (event.pointerId !== this.pointerId) {
|
|
5849
|
+
return;
|
|
5850
|
+
}
|
|
5851
|
+
if (!this.isPastThreshold && !this.tryStartDrag(event)) {
|
|
5852
|
+
return;
|
|
5853
|
+
}
|
|
5854
|
+
const elapsed = event.timeStamp - this.lastTimestamp;
|
|
5855
|
+
if (elapsed > 0) {
|
|
5856
|
+
this.velocity = (event.clientY - this.lastY) / elapsed;
|
|
5857
|
+
this.lastY = event.clientY;
|
|
5858
|
+
this.lastTimestamp = event.timeStamp;
|
|
5859
|
+
}
|
|
5860
|
+
// Upward movement is clamped: the sheet has a single resting position to return to.
|
|
5861
|
+
this.setDragOffset(Math.max(0, event.clientY - this.startY));
|
|
5862
|
+
};
|
|
5863
|
+
onPointerUp = (event) => {
|
|
5864
|
+
if (event.pointerId !== this.pointerId) {
|
|
5865
|
+
return;
|
|
5866
|
+
}
|
|
5867
|
+
const wasDragging = this.isPastThreshold;
|
|
5868
|
+
const shouldDismiss = wasDragging && this.shouldDismiss(event.timeStamp);
|
|
5869
|
+
if (shouldDismiss) {
|
|
5870
|
+
this.releasePointer();
|
|
5871
|
+
this.slideOut();
|
|
5872
|
+
this.zone.run(() => this.dismissedSheet.next());
|
|
5873
|
+
}
|
|
5874
|
+
else {
|
|
5875
|
+
this.stopTracking();
|
|
5876
|
+
}
|
|
5877
|
+
if (wasDragging) {
|
|
5878
|
+
this.suppressClickAfterDrag();
|
|
5879
|
+
}
|
|
5880
|
+
};
|
|
5881
|
+
onPointerCancel = (event) => {
|
|
5882
|
+
if (event.pointerId === this.pointerId) {
|
|
5883
|
+
this.stopTracking();
|
|
5884
|
+
}
|
|
5885
|
+
};
|
|
5886
|
+
/** Keeps the browser from scrolling or overscrolling underneath an ongoing drag. */
|
|
5887
|
+
onTouchMove = (event) => {
|
|
5888
|
+
if (this.isPastThreshold && event.cancelable) {
|
|
5889
|
+
event.preventDefault();
|
|
5890
|
+
}
|
|
5891
|
+
};
|
|
5892
|
+
/**
|
|
5893
|
+
* Decides who owns the gesture on the first move that leaves the tap threshold. Upward
|
|
5894
|
+
* moves, and downward moves over content that still has somewhere to scroll, belong to
|
|
5895
|
+
* the content, so the sheet lets go of them for good.
|
|
5896
|
+
*/
|
|
5897
|
+
tryStartDrag(event) {
|
|
5898
|
+
const distance = event.clientY - this.startY;
|
|
5899
|
+
if (Math.abs(distance) < DRAG_START_THRESHOLD_PX) {
|
|
5900
|
+
return false;
|
|
5901
|
+
}
|
|
5902
|
+
if (distance < 0 || (this.scroller?.scrollTop ?? 0) > 0) {
|
|
5903
|
+
this.stopTracking();
|
|
5904
|
+
return false;
|
|
5905
|
+
}
|
|
5906
|
+
// Starting from where the threshold was crossed keeps the sheet from jumping under
|
|
5907
|
+
// the pointer on the first frame of the drag.
|
|
5908
|
+
this.startY = this.lastY = event.clientY;
|
|
5909
|
+
this.isPastThreshold = true;
|
|
5910
|
+
this.isDragging.set(true);
|
|
5911
|
+
return true;
|
|
5912
|
+
}
|
|
5913
|
+
shouldDismiss(timestamp) {
|
|
5914
|
+
const height = this.surfaceElement?.offsetHeight ?? 0;
|
|
5915
|
+
const isFling = timestamp - this.lastTimestamp < VELOCITY_TIMEOUT_MS
|
|
5916
|
+
&& this.velocity > DISMISS_VELOCITY;
|
|
5917
|
+
return isFling || (height > 0 && this.dragOffset() > height * DISMISS_DISTANCE_RATIO);
|
|
5918
|
+
}
|
|
5919
|
+
setDragOffset(offset) {
|
|
5920
|
+
const height = this.surfaceElement?.offsetHeight ?? 0;
|
|
5921
|
+
this.dragOffset.set(offset);
|
|
5922
|
+
this.draggedSheet.next(height > 0 ? Math.min(1, offset / height) : 0);
|
|
5923
|
+
}
|
|
5924
|
+
/**
|
|
5925
|
+
* Sees the drag out of the viewport rather than back to the resting position, so a
|
|
5926
|
+
* dismissed sheet keeps going the way it was dragged instead of springing back first.
|
|
5927
|
+
* The fade comes from the exit animation BottomSheetRef starts right after.
|
|
5928
|
+
*/
|
|
5929
|
+
slideOut() {
|
|
5930
|
+
this.dragOffset.set(this.surfaceElement?.offsetHeight ?? this.dragOffset());
|
|
5931
|
+
}
|
|
5932
|
+
/** Releases the pointer and puts the sheet back at its resting position. */
|
|
5933
|
+
stopTracking() {
|
|
5934
|
+
this.releasePointer();
|
|
5935
|
+
if (this.dragOffset() !== 0) {
|
|
5936
|
+
this.setDragOffset(0);
|
|
5937
|
+
}
|
|
5938
|
+
}
|
|
5939
|
+
releasePointer() {
|
|
5940
|
+
if (this.pointerId === undefined) {
|
|
5941
|
+
return;
|
|
5942
|
+
}
|
|
5943
|
+
this.pointerId = undefined;
|
|
5944
|
+
this.isPastThreshold = false;
|
|
5945
|
+
this.scroller = null;
|
|
5946
|
+
this.isDragging.set(false);
|
|
5947
|
+
this.surfaceElement?.removeEventListener('touchmove', this.onTouchMove);
|
|
5948
|
+
window.removeEventListener('pointermove', this.onPointerMove);
|
|
5949
|
+
window.removeEventListener('pointerup', this.onPointerUp);
|
|
5950
|
+
window.removeEventListener('pointercancel', this.onPointerCancel);
|
|
5951
|
+
}
|
|
5952
|
+
/**
|
|
5953
|
+
* A drag that ended over a button would otherwise still click it, so the click that
|
|
5954
|
+
* follows the release is swallowed. Nothing else fires in between, and the listener is
|
|
5955
|
+
* dropped right after in case the release happened over something unclickable.
|
|
5956
|
+
*/
|
|
5957
|
+
suppressClickAfterDrag() {
|
|
5958
|
+
const surface = this.surfaceElement;
|
|
5959
|
+
if (!surface) {
|
|
5960
|
+
return;
|
|
5961
|
+
}
|
|
5962
|
+
const onClick = (event) => {
|
|
5963
|
+
event.preventDefault();
|
|
5964
|
+
event.stopPropagation();
|
|
5965
|
+
};
|
|
5966
|
+
surface.addEventListener('click', onClick, { capture: true, once: true });
|
|
5967
|
+
setTimeout(() => surface.removeEventListener('click', onClick, { capture: true }));
|
|
5968
|
+
}
|
|
5969
|
+
/** Nearest scrollable between the pointer and the surface, if the drag started over one. */
|
|
5970
|
+
findScroller(target) {
|
|
5971
|
+
const surface = this.surfaceElement;
|
|
5972
|
+
let node = target instanceof HTMLElement ? target : null;
|
|
5973
|
+
while (node && surface?.contains(node)) {
|
|
5974
|
+
if (node.scrollHeight > node.clientHeight && this.isScrollable(node)) {
|
|
5975
|
+
return node;
|
|
5976
|
+
}
|
|
5977
|
+
node = node.parentElement;
|
|
5978
|
+
}
|
|
5979
|
+
return null;
|
|
5980
|
+
}
|
|
5981
|
+
isScrollable(element) {
|
|
5982
|
+
const overflowY = getComputedStyle(element).overflowY;
|
|
5983
|
+
return overflowY === 'auto' || overflowY === 'scroll';
|
|
5984
|
+
}
|
|
5985
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: BottomSheet, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5986
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: BottomSheet, isStandalone: true, selector: "md3-bottom-sheet", host: { properties: { "class.md3-hide-handle": "!showHandle()", "class.md3-draggable": "allowGestures()", "class.md3-dragging": "isDragging()" } }, 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<div\n #surface\n class=\"md3-bottom-sheet-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [style.transform]=\"dragTransform()\"\n [attr.dir]=\"config.direction ?? null\"\n (pointerdown)=\"onPointerDown($event)\">\n <div class=\"md3-bottom-sheet-handle\"></div>\n <ng-template cdkPortalOutlet></ng-template>\n</div>\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-bottom-sheet-scrim{--md3-drag-remaining: 1;position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-standard-slow-spatial-duration) var(--md-motion-standard-slow-spatial-easing);opacity:calc(.32 * var(--md3-drag-remaining))}::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-dragging{transition:none}::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-opening,::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-closing{opacity:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-bottom-sheet-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-bottom-sheet-panel{width:100%;max-width:40em;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-bottom-sheet-panel.md3-bottom-sheet-closing{pointer-events:none}:host{display:block;width:100%;max-width:100%;outline:0}:host .md3-bottom-sheet-container{position:relative;display:block;width:100%;max-height:70vh;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-low));border-start-start-radius:var(--md-border-radius-large);border-start-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-1dp);transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing);opacity:0;transform:translateY(60%) scaleY(.8);transform-origin:bottom}:host .md3-bottom-sheet-container.md3-active{opacity:1;transform:translateY(0) scaleY(1)}:host .md3-bottom-sheet-container .md3-bottom-sheet-handle{position:absolute;top:.75em;left:50%;width:2em;height:.25em;border-radius:var(--md-border-radius-rounded);background-color:rgb(var(--md-scheme-on-surface-variant));opacity:.4;transform:translate(-50%);pointer-events:none}:host .md3-bottom-sheet-container>::ng-deep *:not(.md3-bottom-sheet-handle){display:grid;grid-template-areas:\"header\" \"body\" \"actions\";grid-template-rows:auto minmax(0,1fr) auto;max-height:inherit;overflow:hidden;padding-top:1.25em}:host.md3-hide-handle .md3-bottom-sheet-container .md3-bottom-sheet-handle{display:none}:host.md3-hide-handle .md3-bottom-sheet-container>::ng-deep *:not(.md3-bottom-sheet-handle){padding-top:0}:host.md3-draggable .md3-bottom-sheet-container .md3-bottom-sheet-handle{pointer-events:auto;touch-action:none;cursor:grab}:host.md3-draggable .md3-bottom-sheet-container .md3-bottom-sheet-handle:after{content:\"\";position:absolute;inset:-.625em -1.5em}:host.md3-dragging .md3-bottom-sheet-container{transition:none}:host.md3-dragging .md3-bottom-sheet-container .md3-bottom-sheet-handle{cursor:grabbing}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
|
|
5987
|
+
}
|
|
5988
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: BottomSheet, decorators: [{
|
|
5989
|
+
type: Component,
|
|
5990
|
+
args: [{ selector: 'md3-bottom-sheet', imports: [
|
|
5991
|
+
CdkPortalOutlet,
|
|
5992
|
+
], host: {
|
|
5993
|
+
'[class.md3-hide-handle]': '!showHandle()',
|
|
5994
|
+
'[class.md3-draggable]': 'allowGestures()',
|
|
5995
|
+
'[class.md3-dragging]': 'isDragging()',
|
|
5996
|
+
}, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-bottom-sheet-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [style.transform]=\"dragTransform()\"\n [attr.dir]=\"config.direction ?? null\"\n (pointerdown)=\"onPointerDown($event)\">\n <div class=\"md3-bottom-sheet-handle\"></div>\n <ng-template cdkPortalOutlet></ng-template>\n</div>\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-bottom-sheet-scrim{--md3-drag-remaining: 1;position:absolute;inset:0;pointer-events:auto;background-color:rgb(var(--md-scheme-scrim));transition:all var(--md-motion-standard-slow-spatial-duration) var(--md-motion-standard-slow-spatial-easing);opacity:calc(.32 * var(--md3-drag-remaining))}::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-dragging{transition:none}::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-opening,::ng-deep .cdk-overlay-container .md3-bottom-sheet-scrim.md3-bottom-sheet-closing{opacity:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-bottom-sheet-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-bottom-sheet-panel{width:100%;max-width:40em;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-bottom-sheet-panel.md3-bottom-sheet-closing{pointer-events:none}:host{display:block;width:100%;max-width:100%;outline:0}:host .md3-bottom-sheet-container{position:relative;display:block;width:100%;max-height:70vh;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface-container-low));border-start-start-radius:var(--md-border-radius-large);border-start-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-1dp);transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing);opacity:0;transform:translateY(60%) scaleY(.8);transform-origin:bottom}:host .md3-bottom-sheet-container.md3-active{opacity:1;transform:translateY(0) scaleY(1)}:host .md3-bottom-sheet-container .md3-bottom-sheet-handle{position:absolute;top:.75em;left:50%;width:2em;height:.25em;border-radius:var(--md-border-radius-rounded);background-color:rgb(var(--md-scheme-on-surface-variant));opacity:.4;transform:translate(-50%);pointer-events:none}:host .md3-bottom-sheet-container>::ng-deep *:not(.md3-bottom-sheet-handle){display:grid;grid-template-areas:\"header\" \"body\" \"actions\";grid-template-rows:auto minmax(0,1fr) auto;max-height:inherit;overflow:hidden;padding-top:1.25em}:host.md3-hide-handle .md3-bottom-sheet-container .md3-bottom-sheet-handle{display:none}:host.md3-hide-handle .md3-bottom-sheet-container>::ng-deep *:not(.md3-bottom-sheet-handle){padding-top:0}:host.md3-draggable .md3-bottom-sheet-container .md3-bottom-sheet-handle{pointer-events:auto;touch-action:none;cursor:grab}:host.md3-draggable .md3-bottom-sheet-container .md3-bottom-sheet-handle:after{content:\"\";position:absolute;inset:-.625em -1.5em}:host.md3-dragging .md3-bottom-sheet-container{transition:none}:host.md3-dragging .md3-bottom-sheet-container .md3-bottom-sheet-handle{cursor:grabbing}\n"] }]
|
|
5997
|
+
}], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
|
|
5998
|
+
|
|
5999
|
+
const PANEL_CLASS = 'md3-bottom-sheet-panel';
|
|
6000
|
+
const OPENING_CLASS = 'md3-bottom-sheet-opening';
|
|
6001
|
+
/**
|
|
6002
|
+
* Opens bottom sheets as CDK dialogs anchored to the bottom of the viewport.
|
|
6003
|
+
* A bottom sheet is always a modal overlay, the same way a regular dialog is
|
|
6004
|
+
* always an overlay, so this mirrors DialogService rather than the side sheet
|
|
6005
|
+
* outlet model: there is no docked variant and nothing to register from the
|
|
6006
|
+
* scaffold.
|
|
6007
|
+
*/
|
|
6008
|
+
class BottomSheetService {
|
|
6009
|
+
cdkDialog = inject(Dialog$1);
|
|
6010
|
+
overlay = inject(Overlay);
|
|
6011
|
+
injector = inject(Injector);
|
|
6012
|
+
/** Only one bottom sheet is ever open at a time. */
|
|
6013
|
+
ref;
|
|
6014
|
+
open(component, config = {}) {
|
|
6015
|
+
const sheetConfig = this.mergeConfig(config);
|
|
6016
|
+
// Opening a new sheet always replaces the one that is open.
|
|
6017
|
+
this.ref?.close();
|
|
6018
|
+
let sheetRef;
|
|
6019
|
+
const cdkRef = this.cdkDialog.open(component, {
|
|
6020
|
+
// The MD3 shell replaces the default CDK container, so the overlay,
|
|
6021
|
+
// focus trap and focus restoration come from the CDK while the
|
|
6022
|
+
// shell only renders the surface.
|
|
6023
|
+
container: {
|
|
6024
|
+
type: BottomSheet,
|
|
6025
|
+
providers: () => [
|
|
6026
|
+
{ provide: BOTTOM_SHEET_CONFIG, useValue: sheetConfig },
|
|
6027
|
+
],
|
|
6028
|
+
},
|
|
6029
|
+
// These tokens make the sheet controllable from the dynamic
|
|
6030
|
+
// component without coupling that component to the service.
|
|
6031
|
+
providers: (cdkDialogRef) => {
|
|
6032
|
+
sheetRef = new BottomSheetRef(cdkDialogRef);
|
|
6033
|
+
return [
|
|
6034
|
+
{ provide: BottomSheetRef, useValue: sheetRef },
|
|
6035
|
+
{ provide: BOTTOM_SHEET_DATA, useValue: sheetConfig.data },
|
|
6036
|
+
{ provide: BOTTOM_SHEET_CONFIG, useValue: sheetConfig },
|
|
6037
|
+
{ provide: BOTTOM_SHEET_COMPONENT, useValue: component },
|
|
6038
|
+
];
|
|
6039
|
+
},
|
|
6040
|
+
data: sheetConfig.data,
|
|
6041
|
+
role: 'dialog',
|
|
6042
|
+
ariaModal: true,
|
|
6043
|
+
direction: sheetConfig.direction ?? undefined,
|
|
6044
|
+
viewContainerRef: sheetConfig.viewContainerRef,
|
|
6045
|
+
injector: sheetConfig.injector,
|
|
6046
|
+
hasBackdrop: true,
|
|
6047
|
+
backdropClass: ['md3-bottom-sheet-scrim', OPENING_CLASS],
|
|
6048
|
+
panelClass: [PANEL_CLASS, OPENING_CLASS],
|
|
6049
|
+
positionStrategy: this.overlay.position()
|
|
6050
|
+
.global()
|
|
6051
|
+
.centerHorizontally()
|
|
6052
|
+
.bottom('0'),
|
|
6053
|
+
// Bottom sheets block page scrolling for as long as they are open.
|
|
6054
|
+
scrollStrategy: this.overlay.scrollStrategies.block(),
|
|
6055
|
+
// Scrim and Escape handling lives in BottomSheetRef so the sheet
|
|
6056
|
+
// can play its exit animation before the overlay is disposed.
|
|
6057
|
+
disableClose: true,
|
|
6058
|
+
});
|
|
6059
|
+
sheetRef.attachContainer(cdkRef.containerInstance);
|
|
6060
|
+
sheetRef.componentInstance = cdkRef.componentInstance ?? undefined;
|
|
6061
|
+
if (cdkRef.componentRef) {
|
|
6062
|
+
this.bindDataToInputs(cdkRef.componentRef, sheetConfig);
|
|
6063
|
+
}
|
|
6064
|
+
this.ref = sheetRef;
|
|
6065
|
+
this.startOpenAnimation(sheetRef);
|
|
6066
|
+
sheetRef.afterClosed().subscribe(() => {
|
|
6067
|
+
if (this.ref === sheetRef) {
|
|
6068
|
+
this.ref = undefined;
|
|
6069
|
+
}
|
|
6070
|
+
});
|
|
6071
|
+
return sheetRef;
|
|
6072
|
+
}
|
|
6073
|
+
/** Closes the bottom sheet that is open, if there is one. */
|
|
6074
|
+
close(result) {
|
|
6075
|
+
this.ref?.close(result);
|
|
6076
|
+
}
|
|
6077
|
+
startOpenAnimation(sheetRef) {
|
|
6078
|
+
const overlayRef = sheetRef.overlayRef;
|
|
6079
|
+
const panel = overlayRef.overlayElement;
|
|
6080
|
+
const backdrop = overlayRef.backdropElement;
|
|
6081
|
+
// The overlay is inserted already rendered. Keep an initial class for
|
|
6082
|
+
// one frame, force style calculation, then remove it so CSS
|
|
6083
|
+
// transitions have a real from/to state.
|
|
6084
|
+
requestAnimationFrame(() => {
|
|
6085
|
+
setTimeout(() => {
|
|
6086
|
+
panel.getBoundingClientRect();
|
|
6087
|
+
panel.classList.remove(OPENING_CLASS);
|
|
6088
|
+
backdrop?.classList.remove(OPENING_CLASS);
|
|
6089
|
+
}, 100);
|
|
6090
|
+
});
|
|
6091
|
+
sheetRef.sheetInstance?.startEnterAnimation();
|
|
6092
|
+
}
|
|
6093
|
+
mergeConfig(config) {
|
|
6094
|
+
return {
|
|
6095
|
+
data: config.data,
|
|
6096
|
+
bindDataToInputs: config.bindDataToInputs ?? false,
|
|
6097
|
+
handle: config.handle ?? true,
|
|
6098
|
+
gestures: config.gestures ?? true,
|
|
6099
|
+
scheme: config.scheme ?? 'inherit',
|
|
6100
|
+
direction: config.direction ?? null,
|
|
6101
|
+
viewContainerRef: config.viewContainerRef,
|
|
6102
|
+
injector: config.injector ?? this.injector,
|
|
6103
|
+
};
|
|
6104
|
+
}
|
|
6105
|
+
bindDataToInputs(componentRef, config) {
|
|
6106
|
+
if (!config.bindDataToInputs || !this.canBindDataToInputs(config.data)) {
|
|
6107
|
+
return;
|
|
6108
|
+
}
|
|
6109
|
+
Object.entries(config.data).forEach(([inputName, inputValue]) => {
|
|
6110
|
+
componentRef.setInput(inputName, inputValue);
|
|
6111
|
+
});
|
|
6112
|
+
}
|
|
6113
|
+
canBindDataToInputs(data) {
|
|
6114
|
+
return typeof data === 'object' && data !== null && !Array.isArray(data);
|
|
6115
|
+
}
|
|
6116
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: BottomSheetService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6117
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: BottomSheetService, providedIn: 'root' });
|
|
6118
|
+
}
|
|
6119
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: BottomSheetService, decorators: [{
|
|
6120
|
+
type: Injectable,
|
|
6121
|
+
args: [{
|
|
6122
|
+
providedIn: 'root',
|
|
6123
|
+
}]
|
|
6124
|
+
}] });
|
|
6125
|
+
|
|
5625
6126
|
const SNACKBAR_MESSAGE = new InjectionToken('MD3_SNACKBAR_MESSAGE');
|
|
5626
6127
|
const SNACKBAR_ACTION_LABEL = new InjectionToken('MD3_SNACKBAR_ACTION_LABEL');
|
|
5627
6128
|
const SNACKBAR_CONFIG = new InjectionToken('MD3_SNACKBAR_CONFIG');
|
|
@@ -5970,5 +6471,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
5970
6471
|
* Generated bundle index. Do not edit.
|
|
5971
6472
|
*/
|
|
5972
6473
|
|
|
5973
|
-
export { AppBar, AppBarLogo, Avatar, Badge, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StateComponent, SupportingText, Switch, TextField, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
|
|
6474
|
+
export { AppBar, AppBarLogo, Avatar, BOTTOM_SHEET_COMPONENT, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, Badge, BottomSheetRef, BottomSheetService, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StateComponent, SupportingText, Switch, TextField, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
|
|
5974
6475
|
//# sourceMappingURL=almoamendev-ngx-md3.mjs.map
|