@almoamendev/ngx-md3 0.7.4 → 0.8.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.
@@ -8,12 +8,12 @@ import * as i1 from '@angular/router';
8
8
  import { Router, NavigationEnd, RouterLinkActive } from '@angular/router';
9
9
  import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
10
10
  import { CdkDialogContainer, Dialog as Dialog$1 } from '@angular/cdk/dialog';
11
- import { Overlay, OverlayContainer, OverlayConfig } from '@angular/cdk/overlay';
11
+ import { Overlay, OverlayConfig, OverlayContainer } from '@angular/cdk/overlay';
12
12
  import { hasModifierKey } from '@angular/cdk/keycodes';
13
13
  import * as i2 from '@angular/cdk/scrolling';
14
14
  import { CdkScrollable } from '@angular/cdk/scrolling';
15
15
  import { Directionality } from '@angular/cdk/bidi';
16
- import { FormControlName } from '@angular/forms';
16
+ import { FormControlName, NgControl } from '@angular/forms';
17
17
 
18
18
  class TypeDisplay {
19
19
  el;
@@ -4353,7 +4353,6 @@ class Switch {
4353
4353
  inputDisabledState = signal(false, /* @ts-ignore */
4354
4354
  ...(ngDevMode ? [{ debugName: "inputDisabledState" }] : /* istanbul ignore next */ []));
4355
4355
  isDisabled = computed(() => {
4356
- console.log('Switch disabled');
4357
4356
  return this.inputDisabledState();
4358
4357
  }, /* @ts-ignore */
4359
4358
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
@@ -5741,6 +5740,7 @@ class NavigationRail {
5741
5740
  transform: booleanAttribute });
5742
5741
  fullWidthIndicator = input(false, { ...(ngDevMode ? { debugName: "fullWidthIndicator" } : /* istanbul ignore next */ {}), alias: 'full-width-indicator',
5743
5742
  transform: booleanAttribute });
5743
+ menuAlignment = input('start', { ...(ngDevMode ? { debugName: "menuAlignment" } : /* istanbul ignore next */ {}), alias: 'menu-alignment' });
5744
5744
  containerStyle = input('none', { ...(ngDevMode ? { debugName: "containerStyle" } : /* istanbul ignore next */ {}), alias: 'container-style' });
5745
5745
  collapsedMode = input('compact', { ...(ngDevMode ? { debugName: "collapsedMode" } : /* istanbul ignore next */ {}), alias: 'collapsed-layout' });
5746
5746
  expandedMode = input('standard', { ...(ngDevMode ? { debugName: "expandedMode" } : /* istanbul ignore next */ {}), alias: 'expanded-layout' });
@@ -5813,12 +5813,12 @@ class NavigationRail {
5813
5813
  this.expanded.set(true);
5814
5814
  }
5815
5815
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: NavigationRail, deps: [], target: i0.ɵɵFactoryTarget.Component });
5816
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: NavigationRail, isStandalone: true, selector: "md3-navigation-rail", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, hideMenuButton: { classPropertyName: "hideMenuButton", publicName: "hide-menu-button", isSignal: true, isRequired: false, transformFunction: null }, fullWidthIndicator: { classPropertyName: "fullWidthIndicator", publicName: "full-width-indicator", isSignal: true, isRequired: false, transformFunction: null }, containerStyle: { classPropertyName: "containerStyle", publicName: "container-style", isSignal: true, isRequired: false, transformFunction: null }, collapsedMode: { classPropertyName: "collapsedMode", publicName: "collapsed-layout", isSignal: true, isRequired: false, transformFunction: null }, expandedMode: { classPropertyName: "expandedMode", publicName: "expanded-layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { properties: { "class.md3-expanded": "this.expanded()" } }, providers: [
5816
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: NavigationRail, isStandalone: true, selector: "md3-navigation-rail", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, hideMenuButton: { classPropertyName: "hideMenuButton", publicName: "hide-menu-button", isSignal: true, isRequired: false, transformFunction: null }, fullWidthIndicator: { classPropertyName: "fullWidthIndicator", publicName: "full-width-indicator", isSignal: true, isRequired: false, transformFunction: null }, menuAlignment: { classPropertyName: "menuAlignment", publicName: "menu-alignment", isSignal: true, isRequired: false, transformFunction: null }, containerStyle: { classPropertyName: "containerStyle", publicName: "container-style", isSignal: true, isRequired: false, transformFunction: null }, collapsedMode: { classPropertyName: "collapsedMode", publicName: "collapsed-layout", isSignal: true, isRequired: false, transformFunction: null }, expandedMode: { classPropertyName: "expandedMode", publicName: "expanded-layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { properties: { "class.md3-expanded": "this.expanded()" } }, providers: [
5817
5817
  {
5818
5818
  provide: MD3_BUTTON_CONTEXT,
5819
5819
  useExisting: NavigationRail,
5820
5820
  },
5821
- ], queries: [{ propertyName: "menuIcons", predicate: IconElement, isSignal: true }, { propertyName: "floatingActionButton", first: true, predicate: FloatingActionButton, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"md3-nav-scrim\" (click)=\"collapse()\"></div>\n<div class=\"md3-nav-container\">\n <div class=\"md3-nav-header\" [class.md3-hidden]=\"hideMenuButton() && !hasFab()\">\n @if (!hideMenuButton()) {\n <button md3-icon-button button-type=\"standard\" class=\"md3-menu-button\" (click)=\"toggle()\">\n <ng-content select=\"[md3-icon-element=expand]\"></ng-content>\n @if (!menuExpandIcon()) {\n <md3-icon md3-icon-element md3-menu-expand>menu</md3-icon>\n }\n <ng-content select=\"[md3-icon-element=collapse]\"></ng-content>\n @if (!menuCollapseIcon()) {\n <md3-icon md3-icon-element md3-menu-collapse bi-directional>menu_open</md3-icon>\n }\n </button>\n }\n\n <ng-content select=\"[md3-fab]\"></ng-content>\n </div>\n <div class=\"md3-menu-container md3-scrollable\" [class.md3-full-width-indicator]=\"fullWidthIndicator()\">\n <ng-content select=\"[md3-nav-item], md3-nav-group\"></ng-content>\n </div>\n</div>", styles: [":host{display:flex;width:6em;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-scrim{position:fixed;inset:0;z-index:399;pointer-events:none;display:none;background-color:rgb(var(--md-scheme-scrim));opacity:0;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container{flex:1 1 auto;display:flex;flex-direction:column;align-items:start;position:relative;background-color:rgb(var(--md-scheme-surface));color:rgb(var(--md-scheme-on-surface));height:100%;max-width:6em}:host .md3-nav-container .md3-nav-header{display:flex;flex-direction:column;align-items:start;gap:.25em;padding:2.75em 1.25em 1.5em;width:100%;min-width:fit-content}:host .md3-nav-container .md3-nav-header.md3-hidden{display:none}:host .md3-nav-container .md3-nav-header .md3-menu-button{margin:.5em}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:inline-block}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:none}:host .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{box-shadow:var(--md-shadow-0dp)}:host .md3-nav-container .md3-menu-container{display:flex;flex-direction:column;align-items:stretch;width:100%;padding-top:1.25em;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container .md3-menu-container ::ng-deep md3-nav-group .md3-nav-label{max-height:3.25em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item]{margin-bottom:.25em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:0;transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-style-elevated{box-shadow:var(--md-shadow-1dp)}:host.md3-style-divider .md3-nav-container:after{content:\"\";position:absolute;height:100%;width:.0625em;top:0;bottom:0;inset-inline-end:0;background-color:rgb(var(--md-scheme-outline-variant));pointer-events:none;opacity:1;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host.md3-collapsed-narrow{width:5em}:host.md3-collapsed-narrow .md3-nav-container{max-width:5em}:host.md3-collapsed-narrow .md3-nav-container .md3-nav-header{padding-inline:.75em}:host.md3-collapsed-hidden{width:0}:host.md3-collapsed-hidden .md3-nav-container{max-width:0em}:host.md3-collapsed-hidden .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:0}:host.md3-collapsed-hidden .md3-nav-container .md3-menu-container{opacity:0}:host.md3-collapsed-hidden .md3-nav-container:after{opacity:0}:host.md3-expanded-modal .md3-nav-scrim{display:block}:host.md3-expanded-modal .md3-nav-container{position:fixed;z-index:400;inset-inline-start:0;top:0;bottom:0}:host:not(.md3-expanded) ::ng-deep md3-nav-group.md3-hide-on-collapse{transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host:not(.md3-expanded) ::ng-deep md3-nav-group .md3-nav-label{transform:scaleY(0);opacity:0;max-height:0em}:host.md3-expanded .md3-nav-container{min-width:13.75em;max-width:22.5em;width:fit-content}:host.md3-expanded .md3-nav-container .md3-nav-header{padding-inline:1.25em}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:none}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:inline-block}:host.md3-expanded .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container{padding-bottom:2.5em;opacity:1;overflow-y:auto}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item]{padding-inline:1.25em;margin-bottom:.5em}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:.5em;transform:scaleY(1);opacity:1;max-height:5em;max-width:100%}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container{padding:0 1em;flex-direction:row;align-items:center;justify-content:start;width:fit-content;height:3.5em}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container:before,:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container:after{inset:0;height:auto;width:auto;border-radius:var(--md-border-radius-xlarge)}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-icon-container{padding:0}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-label{font-size:.875em;line-height:1.428571em;letter-spacing:.007143em;max-height:2.857143em;padding-inline:0}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container{position:relative;inset:auto}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container.md3-small{position:absolute;height:1.875em;width:1.625em}:host.md3-expanded .md3-nav-container .md3-menu-container.md3-full-width-indicator ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-expanded.md3-expanded-standard{width:auto}:host.md3-expanded.md3-expanded-modal .md3-nav-scrim{pointer-events:all;opacity:.32}:host.md3-expanded.md3-expanded-modal .md3-nav-container{background-color:rgb(var(--md-scheme-surface-container));border-start-end-radius:var(--md-border-radius-large);border-end-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-3dp);width:fit-content;max-width:22.5em}:host.md3-expanded.md3-expanded-modal .md3-nav-container:after{opacity:0}\n"], dependencies: [{ kind: "component", type: IconButton, selector: "button[md3-icon-button], a[md3-icon-button]", inputs: ["button-size", "button-type", "button-width", "button-squared", "selected"], outputs: ["selectedChange"] }, { kind: "directive", type: IconElement, selector: "[md3-icon-element]", inputs: ["md3-icon-element"] }, { kind: "component", type: MaterialIcon, selector: "md3-icon", inputs: ["icon-version", "filled", "icon-style", "icon-size", "bi-directional"] }] });
5821
+ ], queries: [{ propertyName: "menuIcons", predicate: IconElement, isSignal: true }, { propertyName: "floatingActionButton", first: true, predicate: FloatingActionButton, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"md3-nav-scrim\" (click)=\"collapse()\"></div>\n<div class=\"md3-nav-container\">\n <div class=\"md3-nav-header\" [class.md3-hidden]=\"hideMenuButton() && !hasFab()\">\n @if (!hideMenuButton()) {\n <button md3-icon-button button-type=\"standard\" class=\"md3-menu-button\" (click)=\"toggle()\">\n <ng-content select=\"[md3-icon-element=expand]\"></ng-content>\n @if (!menuExpandIcon()) {\n <md3-icon md3-icon-element md3-menu-expand>menu</md3-icon>\n }\n <ng-content select=\"[md3-icon-element=collapse]\"></ng-content>\n @if (!menuCollapseIcon()) {\n <md3-icon md3-icon-element md3-menu-collapse bi-directional>menu_open</md3-icon>\n }\n </button>\n }\n\n <ng-content select=\"[md3-fab]\"></ng-content>\n </div>\n <div class=\"md3-menu-container\" [class.md3-full-width-indicator]=\"fullWidthIndicator()\" [ngClass]=\"'md3-' + menuAlignment()\">\n <div class=\"md3-menu-list md3-scrollable\">\n <ng-content select=\"[md3-nav-item], md3-nav-group\"></ng-content>\n </div>\n </div>\n</div>", styles: [":host{display:flex;width:6em;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-scrim{position:fixed;inset:0;z-index:399;pointer-events:none;display:none;background-color:rgb(var(--md-scheme-scrim));opacity:0;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container{flex:1 1 auto;display:flex;flex-direction:column;align-items:start;position:relative;background-color:rgb(var(--md-scheme-surface));color:rgb(var(--md-scheme-on-surface));height:100%;max-width:6em}:host .md3-nav-container .md3-nav-header{display:flex;flex-direction:column;align-items:start;gap:.25em;padding:2.75em 1.25em 1.5em;width:100%;min-width:fit-content}:host .md3-nav-container .md3-nav-header.md3-hidden{display:none}:host .md3-nav-container .md3-nav-header .md3-menu-button{margin:.5em}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:inline-block}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:none}:host .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{box-shadow:var(--md-shadow-0dp)}:host .md3-nav-container .md3-menu-container{flex:1 1 100%;display:flex;flex-direction:column;align-items:stretch;overflow:hidden;width:100%;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container .md3-menu-container.md3-start{justify-content:start}:host .md3-nav-container .md3-menu-container.md3-center{justify-content:center}:host .md3-nav-container .md3-menu-container.md3-end{justify-content:end}:host .md3-nav-container .md3-menu-container .md3-menu-list{display:flex;flex-direction:column;align-items:stretch;width:100%;max-height:100%;padding-top:1.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep md3-nav-group .md3-nav-label{max-height:3.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item]{margin-bottom:.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:0;transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-style-elevated{box-shadow:var(--md-shadow-1dp)}:host.md3-style-divider .md3-nav-container:after{content:\"\";position:absolute;height:100%;width:.0625em;top:0;bottom:0;inset-inline-end:0;background-color:rgb(var(--md-scheme-outline-variant));pointer-events:none;opacity:1;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host.md3-collapsed-narrow{width:5em}:host.md3-collapsed-narrow .md3-nav-container{max-width:5em}:host.md3-collapsed-narrow .md3-nav-container .md3-nav-header{padding-inline:.75em}:host.md3-collapsed-hidden{width:0}:host.md3-collapsed-hidden .md3-nav-container{max-width:0em}:host.md3-collapsed-hidden .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:0}:host.md3-collapsed-hidden .md3-nav-container .md3-menu-container{opacity:0}:host.md3-collapsed-hidden .md3-nav-container:after{opacity:0}:host.md3-expanded-modal .md3-nav-scrim{display:block}:host.md3-expanded-modal .md3-nav-container{position:fixed;z-index:400;inset-inline-start:0;top:0;bottom:0}:host:not(.md3-expanded) ::ng-deep md3-nav-group.md3-hide-on-collapse{transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host:not(.md3-expanded) ::ng-deep md3-nav-group .md3-nav-label{transform:scaleY(0);opacity:0;max-height:0em}:host.md3-expanded .md3-nav-container{min-width:13.75em;max-width:22.5em;width:fit-content}:host.md3-expanded .md3-nav-container .md3-nav-header{padding-inline:1.25em}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:none}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:inline-block}:host.md3-expanded .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list{padding-bottom:2.5em;overflow-y:auto}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item]{padding-inline:1.25em;margin-bottom:.5em}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:.5em;transform:scaleY(1);opacity:1;max-height:5em;max-width:100%}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container{padding:0 1em;flex-direction:row;align-items:center;justify-content:start;width:fit-content;height:3.5em}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container:before,:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container:after{inset:0;height:auto;width:auto;border-radius:var(--md-border-radius-xlarge)}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-icon-container{padding:0}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-label{font-size:.875em;line-height:1.428571em;letter-spacing:.007143em;max-height:2.857143em;padding-inline:0}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container{position:relative;inset:auto}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container.md3-small{position:absolute;height:1.875em;width:1.625em}:host.md3-expanded .md3-nav-container .md3-menu-container.md3-full-width-indicator ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-expanded.md3-expanded-standard{width:auto}:host.md3-expanded.md3-expanded-modal .md3-nav-scrim{pointer-events:all;opacity:.32}:host.md3-expanded.md3-expanded-modal .md3-nav-container{background-color:rgb(var(--md-scheme-surface-container));border-start-end-radius:var(--md-border-radius-large);border-end-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-3dp);width:fit-content;max-width:22.5em}:host.md3-expanded.md3-expanded-modal .md3-nav-container:after{opacity:0}\n"], dependencies: [{ kind: "component", type: IconButton, selector: "button[md3-icon-button], a[md3-icon-button]", inputs: ["button-size", "button-type", "button-width", "button-squared", "selected"], outputs: ["selectedChange"] }, { kind: "directive", type: IconElement, selector: "[md3-icon-element]", inputs: ["md3-icon-element"] }, { kind: "component", type: MaterialIcon, selector: "md3-icon", inputs: ["icon-version", "filled", "icon-style", "icon-size", "bi-directional"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
5822
5822
  }
5823
5823
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: NavigationRail, decorators: [{
5824
5824
  type: Component,
@@ -5826,6 +5826,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
5826
5826
  IconButton,
5827
5827
  IconElement,
5828
5828
  MaterialIcon,
5829
+ NgClass,
5829
5830
  ], providers: [
5830
5831
  {
5831
5832
  provide: MD3_BUTTON_CONTEXT,
@@ -5833,8 +5834,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
5833
5834
  },
5834
5835
  ], host: {
5835
5836
  '[class.md3-expanded]': 'this.expanded()',
5836
- }, template: "<div class=\"md3-nav-scrim\" (click)=\"collapse()\"></div>\n<div class=\"md3-nav-container\">\n <div class=\"md3-nav-header\" [class.md3-hidden]=\"hideMenuButton() && !hasFab()\">\n @if (!hideMenuButton()) {\n <button md3-icon-button button-type=\"standard\" class=\"md3-menu-button\" (click)=\"toggle()\">\n <ng-content select=\"[md3-icon-element=expand]\"></ng-content>\n @if (!menuExpandIcon()) {\n <md3-icon md3-icon-element md3-menu-expand>menu</md3-icon>\n }\n <ng-content select=\"[md3-icon-element=collapse]\"></ng-content>\n @if (!menuCollapseIcon()) {\n <md3-icon md3-icon-element md3-menu-collapse bi-directional>menu_open</md3-icon>\n }\n </button>\n }\n\n <ng-content select=\"[md3-fab]\"></ng-content>\n </div>\n <div class=\"md3-menu-container md3-scrollable\" [class.md3-full-width-indicator]=\"fullWidthIndicator()\">\n <ng-content select=\"[md3-nav-item], md3-nav-group\"></ng-content>\n </div>\n</div>", styles: [":host{display:flex;width:6em;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-scrim{position:fixed;inset:0;z-index:399;pointer-events:none;display:none;background-color:rgb(var(--md-scheme-scrim));opacity:0;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container{flex:1 1 auto;display:flex;flex-direction:column;align-items:start;position:relative;background-color:rgb(var(--md-scheme-surface));color:rgb(var(--md-scheme-on-surface));height:100%;max-width:6em}:host .md3-nav-container .md3-nav-header{display:flex;flex-direction:column;align-items:start;gap:.25em;padding:2.75em 1.25em 1.5em;width:100%;min-width:fit-content}:host .md3-nav-container .md3-nav-header.md3-hidden{display:none}:host .md3-nav-container .md3-nav-header .md3-menu-button{margin:.5em}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:inline-block}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:none}:host .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{box-shadow:var(--md-shadow-0dp)}:host .md3-nav-container .md3-menu-container{display:flex;flex-direction:column;align-items:stretch;width:100%;padding-top:1.25em;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container .md3-menu-container ::ng-deep md3-nav-group .md3-nav-label{max-height:3.25em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item]{margin-bottom:.25em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:0;transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-style-elevated{box-shadow:var(--md-shadow-1dp)}:host.md3-style-divider .md3-nav-container:after{content:\"\";position:absolute;height:100%;width:.0625em;top:0;bottom:0;inset-inline-end:0;background-color:rgb(var(--md-scheme-outline-variant));pointer-events:none;opacity:1;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host.md3-collapsed-narrow{width:5em}:host.md3-collapsed-narrow .md3-nav-container{max-width:5em}:host.md3-collapsed-narrow .md3-nav-container .md3-nav-header{padding-inline:.75em}:host.md3-collapsed-hidden{width:0}:host.md3-collapsed-hidden .md3-nav-container{max-width:0em}:host.md3-collapsed-hidden .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:0}:host.md3-collapsed-hidden .md3-nav-container .md3-menu-container{opacity:0}:host.md3-collapsed-hidden .md3-nav-container:after{opacity:0}:host.md3-expanded-modal .md3-nav-scrim{display:block}:host.md3-expanded-modal .md3-nav-container{position:fixed;z-index:400;inset-inline-start:0;top:0;bottom:0}:host:not(.md3-expanded) ::ng-deep md3-nav-group.md3-hide-on-collapse{transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host:not(.md3-expanded) ::ng-deep md3-nav-group .md3-nav-label{transform:scaleY(0);opacity:0;max-height:0em}:host.md3-expanded .md3-nav-container{min-width:13.75em;max-width:22.5em;width:fit-content}:host.md3-expanded .md3-nav-container .md3-nav-header{padding-inline:1.25em}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:none}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:inline-block}:host.md3-expanded .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container{padding-bottom:2.5em;opacity:1;overflow-y:auto}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item]{padding-inline:1.25em;margin-bottom:.5em}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:.5em;transform:scaleY(1);opacity:1;max-height:5em;max-width:100%}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container{padding:0 1em;flex-direction:row;align-items:center;justify-content:start;width:fit-content;height:3.5em}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container:before,:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container:after{inset:0;height:auto;width:auto;border-radius:var(--md-border-radius-xlarge)}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-icon-container{padding:0}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-label{font-size:.875em;line-height:1.428571em;letter-spacing:.007143em;max-height:2.857143em;padding-inline:0}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container{position:relative;inset:auto}:host.md3-expanded .md3-nav-container .md3-menu-container ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container.md3-small{position:absolute;height:1.875em;width:1.625em}:host.md3-expanded .md3-nav-container .md3-menu-container.md3-full-width-indicator ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-expanded.md3-expanded-standard{width:auto}:host.md3-expanded.md3-expanded-modal .md3-nav-scrim{pointer-events:all;opacity:.32}:host.md3-expanded.md3-expanded-modal .md3-nav-container{background-color:rgb(var(--md-scheme-surface-container));border-start-end-radius:var(--md-border-radius-large);border-end-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-3dp);width:fit-content;max-width:22.5em}:host.md3-expanded.md3-expanded-modal .md3-nav-container:after{opacity:0}\n"] }]
5837
- }], ctorParameters: () => [], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], hideMenuButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hide-menu-button", required: false }] }], fullWidthIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "full-width-indicator", required: false }] }], containerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "container-style", required: false }] }], collapsedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed-layout", required: false }] }], expandedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded-layout", required: false }] }], menuIcons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { isSignal: true }] }], floatingActionButton: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FloatingActionButton), { isSignal: true }] }] } });
5837
+ }, template: "<div class=\"md3-nav-scrim\" (click)=\"collapse()\"></div>\n<div class=\"md3-nav-container\">\n <div class=\"md3-nav-header\" [class.md3-hidden]=\"hideMenuButton() && !hasFab()\">\n @if (!hideMenuButton()) {\n <button md3-icon-button button-type=\"standard\" class=\"md3-menu-button\" (click)=\"toggle()\">\n <ng-content select=\"[md3-icon-element=expand]\"></ng-content>\n @if (!menuExpandIcon()) {\n <md3-icon md3-icon-element md3-menu-expand>menu</md3-icon>\n }\n <ng-content select=\"[md3-icon-element=collapse]\"></ng-content>\n @if (!menuCollapseIcon()) {\n <md3-icon md3-icon-element md3-menu-collapse bi-directional>menu_open</md3-icon>\n }\n </button>\n }\n\n <ng-content select=\"[md3-fab]\"></ng-content>\n </div>\n <div class=\"md3-menu-container\" [class.md3-full-width-indicator]=\"fullWidthIndicator()\" [ngClass]=\"'md3-' + menuAlignment()\">\n <div class=\"md3-menu-list md3-scrollable\">\n <ng-content select=\"[md3-nav-item], md3-nav-group\"></ng-content>\n </div>\n </div>\n</div>", styles: [":host{display:flex;width:6em;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-scrim{position:fixed;inset:0;z-index:399;pointer-events:none;display:none;background-color:rgb(var(--md-scheme-scrim));opacity:0;transition:all var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container{flex:1 1 auto;display:flex;flex-direction:column;align-items:start;position:relative;background-color:rgb(var(--md-scheme-surface));color:rgb(var(--md-scheme-on-surface));height:100%;max-width:6em}:host .md3-nav-container .md3-nav-header{display:flex;flex-direction:column;align-items:start;gap:.25em;padding:2.75em 1.25em 1.5em;width:100%;min-width:fit-content}:host .md3-nav-container .md3-nav-header.md3-hidden{display:none}:host .md3-nav-container .md3-nav-header .md3-menu-button{margin:.5em}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:inline-block}:host .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:none}:host .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{box-shadow:var(--md-shadow-0dp)}:host .md3-nav-container .md3-menu-container{flex:1 1 100%;display:flex;flex-direction:column;align-items:stretch;overflow:hidden;width:100%;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host .md3-nav-container .md3-menu-container.md3-start{justify-content:start}:host .md3-nav-container .md3-menu-container.md3-center{justify-content:center}:host .md3-nav-container .md3-menu-container.md3-end{justify-content:end}:host .md3-nav-container .md3-menu-container .md3-menu-list{display:flex;flex-direction:column;align-items:stretch;width:100%;max-height:100%;padding-top:1.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep md3-nav-group .md3-nav-label{max-height:3.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item]{margin-bottom:.25em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:0;transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-style-elevated{box-shadow:var(--md-shadow-1dp)}:host.md3-style-divider .md3-nav-container:after{content:\"\";position:absolute;height:100%;width:.0625em;top:0;bottom:0;inset-inline-end:0;background-color:rgb(var(--md-scheme-outline-variant));pointer-events:none;opacity:1;transition:opacity var(--md-motion-standard-default-spatial-duration) var(--md-motion-standard-default-spatial-easing)}:host.md3-collapsed-narrow{width:5em}:host.md3-collapsed-narrow .md3-nav-container{max-width:5em}:host.md3-collapsed-narrow .md3-nav-container .md3-nav-header{padding-inline:.75em}:host.md3-collapsed-hidden{width:0}:host.md3-collapsed-hidden .md3-nav-container{max-width:0em}:host.md3-collapsed-hidden .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:0}:host.md3-collapsed-hidden .md3-nav-container .md3-menu-container{opacity:0}:host.md3-collapsed-hidden .md3-nav-container:after{opacity:0}:host.md3-expanded-modal .md3-nav-scrim{display:block}:host.md3-expanded-modal .md3-nav-container{position:fixed;z-index:400;inset-inline-start:0;top:0;bottom:0}:host:not(.md3-expanded) ::ng-deep md3-nav-group.md3-hide-on-collapse{transform:scaleY(0);opacity:0;max-height:0em;max-width:0em}:host:not(.md3-expanded) ::ng-deep md3-nav-group .md3-nav-label{transform:scaleY(0);opacity:0;max-height:0em}:host.md3-expanded .md3-nav-container{min-width:13.75em;max-width:22.5em;width:fit-content}:host.md3-expanded .md3-nav-container .md3-nav-header{padding-inline:1.25em}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-expand]{display:none}:host.md3-expanded .md3-nav-container .md3-nav-header .md3-menu-button ::ng-deep [md3-menu-collapse]{display:inline-block}:host.md3-expanded .md3-nav-container .md3-nav-header ::ng-deep [md3-fab]{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container{opacity:1}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list{padding-bottom:2.5em;overflow-y:auto}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item]{padding-inline:1.25em;margin-bottom:.5em}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item].md3-hide-on-collapse{margin-bottom:.5em;transform:scaleY(1);opacity:1;max-height:5em;max-width:100%}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container{padding:0 1em;flex-direction:row;align-items:center;justify-content:start;width:fit-content;height:3.5em}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container:before,:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container:after{inset:0;height:auto;width:auto;border-radius:var(--md-border-radius-xlarge)}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-icon-container{padding:0}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-label{font-size:.875em;line-height:1.428571em;letter-spacing:.007143em;max-height:2.857143em;padding-inline:0}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container{position:relative;inset:auto}:host.md3-expanded .md3-nav-container .md3-menu-container .md3-menu-list ::ng-deep [md3-nav-item] .md3-item-container .md3-badge-container.md3-small{position:absolute;height:1.875em;width:1.625em}:host.md3-expanded .md3-nav-container .md3-menu-container.md3-full-width-indicator ::ng-deep [md3-nav-item] .md3-item-container{width:100%}:host.md3-expanded.md3-expanded-standard{width:auto}:host.md3-expanded.md3-expanded-modal .md3-nav-scrim{pointer-events:all;opacity:.32}:host.md3-expanded.md3-expanded-modal .md3-nav-container{background-color:rgb(var(--md-scheme-surface-container));border-start-end-radius:var(--md-border-radius-large);border-end-end-radius:var(--md-border-radius-large);box-shadow:var(--md-shadow-3dp);width:fit-content;max-width:22.5em}:host.md3-expanded.md3-expanded-modal .md3-nav-container:after{opacity:0}\n"] }]
5838
+ }], ctorParameters: () => [], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], hideMenuButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hide-menu-button", required: false }] }], fullWidthIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "full-width-indicator", required: false }] }], menuAlignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "menu-alignment", required: false }] }], containerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "container-style", required: false }] }], collapsedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed-layout", required: false }] }], expandedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded-layout", required: false }] }], menuIcons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { isSignal: true }] }], floatingActionButton: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FloatingActionButton), { isSignal: true }] }] } });
5838
5839
 
5839
5840
  class NavigationBar {
5840
5841
  el = inject((ElementRef));
@@ -6017,7 +6018,7 @@ class TextField {
6017
6018
  provide: MD3_BUTTON_CONTEXT,
6018
6019
  useExisting: TextField,
6019
6020
  },
6020
- ], queries: [{ propertyName: "input", first: true, predicate: InputElement, descendants: true, isSignal: true }, { propertyName: "iconElements", predicate: IconElement, descendants: true, isSignal: true }, { propertyName: "iconButtons", predicate: IconButton, descendants: true, isSignal: true }, { propertyName: "controlName", first: true, predicate: FormControlName, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "inputContainer", first: true, predicate: ["inputContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<label #inputContainer class=\"md3-text-field-container\" [ngClass]=\"{\n 'md3-text-field-filled': fieldType() == 'filled',\n 'md3-text-field-outlined': fieldType() == 'outlined',\n}\">\n <ng-content></ng-content>\n <fieldset aria-hidden=\"true\" class=\"md3-text-field-outline\">\n @if (label() && fieldType() == 'outlined') {\n <legend class=\"md3-label-gap\">{{ label() }}</legend>\n }\n </fieldset>\n @if (label()) {\n <label class=\"md3-text-field-label\">{{ label() }}</label>\n }\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n <ng-content select=\"[md3-icon-button], [md3-icon-element=trailing]\"></ng-content>\n @if (fieldType() != 'outlined') {\n <div class=\"md3-text-field-state\"></div>\n }\n</label>\n<div class=\"md3-supporting-text-container\" [class.md3-has-error]=\"inputError()\">\n <ng-content select=\"[md3-supporting-text]\"></ng-content>\n @if (inputCounter()) {\n <div class=\"md3-text-input-counter\">{{ valueLength() + (maxLength() ? \"/\" + maxLength() : \"\") }}</div>\n }\n</div>\n", styles: [":host{--background-color: rgb(var(--md-scheme-surface-container-highest));--foreground-color: rgb(var(--md-scheme-on-surface));--label-color: rgb(var(--md-scheme-on-surface-variant));--caret-color: rgb(var(--md-scheme-primary));--outline-color: rgb(var(--md-scheme-on-surface-variant));font-size:1rem;width:100%}:host .md3-text-field-container{display:block;position:relative;border-radius:var(--md-border-radius-xsmall) var(--md-border-radius-xsmall) 0 0;overflow:hidden}:host .md3-text-field-container ::ng-deep [md3-icon-element=leading]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-start:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container ::ng-deep [md3-icon-element=trailing]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-end:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container ::ng-deep [md3-icon-button]{position:absolute;font-size:1em!important;top:.5em;inset-inline-end:.5em}:host .md3-text-field-container .md3-text-field-outline{position:absolute;inset:0;pointer-events:none;padding:0 .625em;margin:.0625em 0 0;border:none;border-bottom:.0625em solid var(--outline-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),border-width none}:host .md3-text-field-container .md3-text-field-outline .md3-label-gap{padding:0;max-width:0em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.041667em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:0;visibility:hidden;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing);interpolate-size:allow-keywords}:host .md3-text-field-container .md3-text-field-label{position:absolute;top:1em;inset-inline-start:1em;inset-inline-end:1em;padding:0;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;color:var(--label-color);transform-origin:top left;transform:scale(1);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container .md3-text-field-label:dir(rtl){transform-origin:top right}:host .md3-text-field-container .md3-text-field-state{position:absolute;inset:0;pointer-events:none;border-radius:inherit;background-color:rgba(var(--md-scheme-on-surface));opacity:0;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container ::ng-deep .md3-input-element{display:block;width:100%;border:none;outline:none;padding:1.5em 1em .5em;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;resize:none;background-color:var(--background-color);color:var(--foreground-color);caret-color:var(--caret-color)}:host .md3-text-field-container ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-state{opacity:.08}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-surface))}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-primary));border-bottom-width:.1875em}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-label{color:var(--caret-color);top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled{--background-color: rgba(var(--md-scheme-surface-container), .4);--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-state{display:none}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border-bottom:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]{caret-color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-label{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-filled{--background-color: rgb(var(--md-scheme-error));--foreground-color: rgb(var(--md-scheme-on-error));--state-color: var(--md-scheme-on-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-tonal{--background-color: rgb(var(--md-scheme-error-container));--foreground-color: rgb(var(--md-scheme-on-error-container));--state-color: var(--md-scheme-on-error-container)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-outlined{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error);border-color:var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-standard{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-label{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container.md3-has-leading-icon ::ng-deep .md3-input-element{padding-inline-start:3.25em}:host .md3-text-field-container.md3-has-leading-icon .md3-text-field-label{inset-inline-start:3.25em}:host .md3-text-field-container.md3-has-trailing-icon ::ng-deep .md3-input-element{padding-inline-end:3.25em}:host .md3-text-field-container.md3-has-trailing-icon .md3-text-field-label{inset-inline-end:3.25em}:host .md3-text-field-container.md3-text-field-outlined{--background-color: transparent;border-radius:var(--md-border-radius-xsmall);padding-top:.5em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-outline{border-radius:inherit;border:.0625em solid var(--outline-color)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-element=leading],:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-element=trailing],:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-button]{top:1em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-label{top:1.5em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element{padding-block:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline{padding:0 .5em;border-width:.1875em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline .md3-label-gap,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-outline .md3-label-gap{padding:0 .375em;max-width:fit-content}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-label,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:0;inset-inline:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled{--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-supporting-text-container{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1.333332em;padding:0 1.333332em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.033332em;color:var(--label-color)}:host .md3-supporting-text-container.md3-has-error{color:rgb(var(--md-scheme-error))}:host .md3-supporting-text-container .md3-text-input-counter{margin-inline-start:auto}:host .md3-supporting-text-container>::ng-deep *{margin-top:.333332em}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
6021
+ ], queries: [{ propertyName: "input", first: true, predicate: InputElement, descendants: true, isSignal: true }, { propertyName: "iconElements", predicate: IconElement, descendants: true, isSignal: true }, { propertyName: "iconButtons", predicate: IconButton, descendants: true, isSignal: true }, { propertyName: "controlName", first: true, predicate: FormControlName, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "inputContainer", first: true, predicate: ["inputContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<label #inputContainer class=\"md3-text-field-container\" [ngClass]=\"{\n 'md3-text-field-filled': fieldType() == 'filled',\n 'md3-text-field-outlined': fieldType() == 'outlined',\n}\">\n <ng-content></ng-content>\n <fieldset aria-hidden=\"true\" class=\"md3-text-field-outline\">\n @if (label() && fieldType() == 'outlined') {\n <legend class=\"md3-label-gap\">{{ label() }}</legend>\n }\n </fieldset>\n @if (label()) {\n <span class=\"md3-text-field-label\">{{ label() }}</span>\n }\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n <ng-content select=\"[md3-icon-button], [md3-icon-element=trailing]\"></ng-content>\n @if (fieldType() != 'outlined') {\n <div class=\"md3-text-field-state\"></div>\n }\n</label>\n<div class=\"md3-supporting-text-container\" [class.md3-has-error]=\"inputError()\">\n <ng-content select=\"[md3-supporting-text]\"></ng-content>\n @if (inputCounter()) {\n <div class=\"md3-text-input-counter\">{{ valueLength() + (maxLength() ? \"/\" + maxLength() : \"\") }}</div>\n }\n</div>\n", styles: [":host{--background-color: rgb(var(--md-scheme-surface-container-highest));--foreground-color: rgb(var(--md-scheme-on-surface));--label-color: rgb(var(--md-scheme-on-surface-variant));--caret-color: rgb(var(--md-scheme-primary));--outline-color: rgb(var(--md-scheme-on-surface-variant));font-size:1rem;width:100%}:host .md3-text-field-container{display:block;position:relative;border-radius:var(--md-border-radius-xsmall) var(--md-border-radius-xsmall) 0 0;overflow:hidden}:host .md3-text-field-container>::ng-deep [md3-icon-element=leading]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-start:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container>::ng-deep [md3-icon-element=trailing]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-end:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container>::ng-deep [md3-icon-button]{position:absolute;font-size:1em!important;top:.5em;inset-inline-end:.5em}:host .md3-text-field-container .md3-text-field-outline{position:absolute;inset:0;pointer-events:none;padding:0 .625em;margin:.0625em 0 0;border:none;border-bottom:.0625em solid var(--outline-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),border-width none}:host .md3-text-field-container .md3-text-field-outline .md3-label-gap{padding:0;max-width:0em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.041667em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:0;visibility:hidden;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing);interpolate-size:allow-keywords}:host .md3-text-field-container .md3-text-field-label{position:absolute;top:1em;inset-inline-start:1em;inset-inline-end:1em;padding:0;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;color:var(--label-color);transform-origin:top left;transform:scale(1);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container .md3-text-field-label:dir(rtl){transform-origin:top right}:host .md3-text-field-container .md3-text-field-state{position:absolute;inset:0;pointer-events:none;border-radius:inherit;background-color:rgba(var(--md-scheme-on-surface));opacity:0;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container ::ng-deep .md3-input-element{display:block;width:100%;border:none;outline:none;padding:1.5em 1em .5em;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;resize:none;background-color:var(--background-color);color:var(--foreground-color);caret-color:var(--caret-color)}:host .md3-text-field-container ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-state{opacity:.08}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-surface))}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-primary));border-bottom-width:.1875em}:host .md3-text-field-container ::ng-deep .md3-input-element:focus:not(:read-only)~.md3-text-field-label{color:var(--caret-color);top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled{--background-color: rgba(var(--md-scheme-surface-container), .4);--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-state{display:none}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border-bottom:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]{caret-color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-label{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-filled{--background-color: rgb(var(--md-scheme-error));--foreground-color: rgb(var(--md-scheme-on-error));--state-color: var(--md-scheme-on-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-tonal{--background-color: rgb(var(--md-scheme-error-container));--foreground-color: rgb(var(--md-scheme-on-error-container));--state-color: var(--md-scheme-on-error-container)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-outlined{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error);border-color:var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-standard{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-label{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container.md3-has-leading-icon ::ng-deep .md3-input-element{padding-inline-start:3.25em}:host .md3-text-field-container.md3-has-leading-icon .md3-text-field-label{inset-inline-start:3.25em}:host .md3-text-field-container.md3-has-trailing-icon ::ng-deep .md3-input-element{padding-inline-end:3.25em}:host .md3-text-field-container.md3-has-trailing-icon .md3-text-field-label{inset-inline-end:3.25em}:host .md3-text-field-container.md3-text-field-outlined{--background-color: transparent;border-radius:var(--md-border-radius-xsmall);padding-top:.5em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-outline{border-radius:inherit;border:.0625em solid var(--outline-color)}:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-element=leading],:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-element=trailing],:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-button]{top:1em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-label{top:1.5em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element{padding-block:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline{padding:0 .5em;border-width:.1875em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:read-only):focus~.md3-text-field-outline .md3-label-gap,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-outline .md3-label-gap{padding:0 .375em;max-width:fit-content}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:read-only):focus~.md3-text-field-label,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:0;inset-inline:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled{--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-supporting-text-container{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1.333332em;padding:0 1.333332em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.033332em;color:var(--label-color)}:host .md3-supporting-text-container.md3-has-error{color:rgb(var(--md-scheme-error))}:host .md3-supporting-text-container .md3-text-input-counter{margin-inline-start:auto}:host .md3-supporting-text-container>::ng-deep *{margin-top:.333332em}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
6021
6022
  }
6022
6023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: TextField, decorators: [{
6023
6024
  type: Component,
@@ -6028,7 +6029,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
6028
6029
  provide: MD3_BUTTON_CONTEXT,
6029
6030
  useExisting: TextField,
6030
6031
  },
6031
- ], template: "<label #inputContainer class=\"md3-text-field-container\" [ngClass]=\"{\n 'md3-text-field-filled': fieldType() == 'filled',\n 'md3-text-field-outlined': fieldType() == 'outlined',\n}\">\n <ng-content></ng-content>\n <fieldset aria-hidden=\"true\" class=\"md3-text-field-outline\">\n @if (label() && fieldType() == 'outlined') {\n <legend class=\"md3-label-gap\">{{ label() }}</legend>\n }\n </fieldset>\n @if (label()) {\n <label class=\"md3-text-field-label\">{{ label() }}</label>\n }\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n <ng-content select=\"[md3-icon-button], [md3-icon-element=trailing]\"></ng-content>\n @if (fieldType() != 'outlined') {\n <div class=\"md3-text-field-state\"></div>\n }\n</label>\n<div class=\"md3-supporting-text-container\" [class.md3-has-error]=\"inputError()\">\n <ng-content select=\"[md3-supporting-text]\"></ng-content>\n @if (inputCounter()) {\n <div class=\"md3-text-input-counter\">{{ valueLength() + (maxLength() ? \"/\" + maxLength() : \"\") }}</div>\n }\n</div>\n", styles: [":host{--background-color: rgb(var(--md-scheme-surface-container-highest));--foreground-color: rgb(var(--md-scheme-on-surface));--label-color: rgb(var(--md-scheme-on-surface-variant));--caret-color: rgb(var(--md-scheme-primary));--outline-color: rgb(var(--md-scheme-on-surface-variant));font-size:1rem;width:100%}:host .md3-text-field-container{display:block;position:relative;border-radius:var(--md-border-radius-xsmall) var(--md-border-radius-xsmall) 0 0;overflow:hidden}:host .md3-text-field-container ::ng-deep [md3-icon-element=leading]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-start:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container ::ng-deep [md3-icon-element=trailing]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-end:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container ::ng-deep [md3-icon-button]{position:absolute;font-size:1em!important;top:.5em;inset-inline-end:.5em}:host .md3-text-field-container .md3-text-field-outline{position:absolute;inset:0;pointer-events:none;padding:0 .625em;margin:.0625em 0 0;border:none;border-bottom:.0625em solid var(--outline-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),border-width none}:host .md3-text-field-container .md3-text-field-outline .md3-label-gap{padding:0;max-width:0em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.041667em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:0;visibility:hidden;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing);interpolate-size:allow-keywords}:host .md3-text-field-container .md3-text-field-label{position:absolute;top:1em;inset-inline-start:1em;inset-inline-end:1em;padding:0;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;color:var(--label-color);transform-origin:top left;transform:scale(1);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container .md3-text-field-label:dir(rtl){transform-origin:top right}:host .md3-text-field-container .md3-text-field-state{position:absolute;inset:0;pointer-events:none;border-radius:inherit;background-color:rgba(var(--md-scheme-on-surface));opacity:0;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container ::ng-deep .md3-input-element{display:block;width:100%;border:none;outline:none;padding:1.5em 1em .5em;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;resize:none;background-color:var(--background-color);color:var(--foreground-color);caret-color:var(--caret-color)}:host .md3-text-field-container ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-state{opacity:.08}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-surface))}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-primary));border-bottom-width:.1875em}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-label{color:var(--caret-color);top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled{--background-color: rgba(var(--md-scheme-surface-container), .4);--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-state{display:none}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border-bottom:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]{caret-color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-label{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-filled{--background-color: rgb(var(--md-scheme-error));--foreground-color: rgb(var(--md-scheme-on-error));--state-color: var(--md-scheme-on-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-tonal{--background-color: rgb(var(--md-scheme-error-container));--foreground-color: rgb(var(--md-scheme-on-error-container));--state-color: var(--md-scheme-on-error-container)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-outlined{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error);border-color:var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-standard{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-label{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container.md3-has-leading-icon ::ng-deep .md3-input-element{padding-inline-start:3.25em}:host .md3-text-field-container.md3-has-leading-icon .md3-text-field-label{inset-inline-start:3.25em}:host .md3-text-field-container.md3-has-trailing-icon ::ng-deep .md3-input-element{padding-inline-end:3.25em}:host .md3-text-field-container.md3-has-trailing-icon .md3-text-field-label{inset-inline-end:3.25em}:host .md3-text-field-container.md3-text-field-outlined{--background-color: transparent;border-radius:var(--md-border-radius-xsmall);padding-top:.5em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-outline{border-radius:inherit;border:.0625em solid var(--outline-color)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-element=leading],:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-element=trailing],:host .md3-text-field-container.md3-text-field-outlined ::ng-deep [md3-icon-button]{top:1em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-label{top:1.5em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element{padding-block:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline{padding:0 .5em;border-width:.1875em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline .md3-label-gap,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-outline .md3-label-gap{padding:0 .375em;max-width:fit-content}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-label,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:0;inset-inline:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled{--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-supporting-text-container{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1.333332em;padding:0 1.333332em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.033332em;color:var(--label-color)}:host .md3-supporting-text-container.md3-has-error{color:rgb(var(--md-scheme-error))}:host .md3-supporting-text-container .md3-text-input-counter{margin-inline-start:auto}:host .md3-supporting-text-container>::ng-deep *{margin-top:.333332em}\n"] }]
6032
+ ], template: "<label #inputContainer class=\"md3-text-field-container\" [ngClass]=\"{\n 'md3-text-field-filled': fieldType() == 'filled',\n 'md3-text-field-outlined': fieldType() == 'outlined',\n}\">\n <ng-content></ng-content>\n <fieldset aria-hidden=\"true\" class=\"md3-text-field-outline\">\n @if (label() && fieldType() == 'outlined') {\n <legend class=\"md3-label-gap\">{{ label() }}</legend>\n }\n </fieldset>\n @if (label()) {\n <span class=\"md3-text-field-label\">{{ label() }}</span>\n }\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n <ng-content select=\"[md3-icon-button], [md3-icon-element=trailing]\"></ng-content>\n @if (fieldType() != 'outlined') {\n <div class=\"md3-text-field-state\"></div>\n }\n</label>\n<div class=\"md3-supporting-text-container\" [class.md3-has-error]=\"inputError()\">\n <ng-content select=\"[md3-supporting-text]\"></ng-content>\n @if (inputCounter()) {\n <div class=\"md3-text-input-counter\">{{ valueLength() + (maxLength() ? \"/\" + maxLength() : \"\") }}</div>\n }\n</div>\n", styles: [":host{--background-color: rgb(var(--md-scheme-surface-container-highest));--foreground-color: rgb(var(--md-scheme-on-surface));--label-color: rgb(var(--md-scheme-on-surface-variant));--caret-color: rgb(var(--md-scheme-primary));--outline-color: rgb(var(--md-scheme-on-surface-variant));font-size:1rem;width:100%}:host .md3-text-field-container{display:block;position:relative;border-radius:var(--md-border-radius-xsmall) var(--md-border-radius-xsmall) 0 0;overflow:hidden}:host .md3-text-field-container>::ng-deep [md3-icon-element=leading]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-start:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container>::ng-deep [md3-icon-element=trailing]{position:absolute;font-size:1.5em!important;height:1em!important;width:1em!important;top:.666667em;inset-inline-end:.5em;pointer-events:none;color:var(--label-color)}:host .md3-text-field-container>::ng-deep [md3-icon-button]{position:absolute;font-size:1em!important;top:.5em;inset-inline-end:.5em}:host .md3-text-field-container .md3-text-field-outline{position:absolute;inset:0;pointer-events:none;padding:0 .625em;margin:.0625em 0 0;border:none;border-bottom:.0625em solid var(--outline-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),border-width none}:host .md3-text-field-container .md3-text-field-outline .md3-label-gap{padding:0;max-width:0em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.041667em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:0;visibility:hidden;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing);interpolate-size:allow-keywords}:host .md3-text-field-container .md3-text-field-label{position:absolute;top:1em;inset-inline-start:1em;inset-inline-end:1em;padding:0;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;color:var(--label-color);transform-origin:top left;transform:scale(1);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container .md3-text-field-label:dir(rtl){transform-origin:top right}:host .md3-text-field-container .md3-text-field-state{position:absolute;inset:0;pointer-events:none;border-radius:inherit;background-color:rgba(var(--md-scheme-on-surface));opacity:0;transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-text-field-container ::ng-deep .md3-input-element{display:block;width:100%;border:none;outline:none;padding:1.5em 1em .5em;font-size:1em;font-weight:400;line-height:1.5em;letter-spacing:.03125em;resize:none;background-color:var(--background-color);color:var(--foreground-color);caret-color:var(--caret-color)}:host .md3-text-field-container ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-state{opacity:.08}:host .md3-text-field-container ::ng-deep .md3-input-element:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-surface))}:host .md3-text-field-container ::ng-deep .md3-input-element:focus~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-primary));border-bottom-width:.1875em}:host .md3-text-field-container ::ng-deep .md3-input-element:focus:not(:read-only)~.md3-text-field-label{color:var(--caret-color);top:.4375em;transform:scale(.75)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled{--background-color: rgba(var(--md-scheme-surface-container), .4);--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-state{display:none}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border-bottom:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]{caret-color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~.md3-text-field-label{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-error))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-filled{--background-color: rgb(var(--md-scheme-error));--foreground-color: rgb(var(--md-scheme-on-error));--state-color: var(--md-scheme-on-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-tonal{--background-color: rgb(var(--md-scheme-error-container));--foreground-color: rgb(var(--md-scheme-on-error-container));--state-color: var(--md-scheme-on-error-container)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-outlined{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error);border-color:var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]~[md3-icon-button].md3-standard{--background-color: transparent;--foreground-color: rgb(var(--md-scheme-error));--state-color: var(--md-scheme-error)}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-outline{--outline-color: rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~.md3-text-field-label{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container ::ng-deep .md3-input-element[aria-invalid=true]:hover~[md3-icon-element=trailing]{color:rgb(var(--md-scheme-on-error-container))}:host .md3-text-field-container.md3-has-leading-icon ::ng-deep .md3-input-element{padding-inline-start:3.25em}:host .md3-text-field-container.md3-has-leading-icon .md3-text-field-label{inset-inline-start:3.25em}:host .md3-text-field-container.md3-has-trailing-icon ::ng-deep .md3-input-element{padding-inline-end:3.25em}:host .md3-text-field-container.md3-has-trailing-icon .md3-text-field-label{inset-inline-end:3.25em}:host .md3-text-field-container.md3-text-field-outlined{--background-color: transparent;border-radius:var(--md-border-radius-xsmall);padding-top:.5em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-outline{border-radius:inherit;border:.0625em solid var(--outline-color)}:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-element=leading],:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-element=trailing],:host .md3-text-field-container.md3-text-field-outlined>::ng-deep [md3-icon-button]{top:1em}:host .md3-text-field-container.md3-text-field-outlined .md3-text-field-label{top:1.5em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element{padding-block:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:focus~.md3-text-field-outline{padding:0 .5em;border-width:.1875em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:read-only):focus~.md3-text-field-outline .md3-label-gap,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-outline .md3-label-gap{padding:0 .375em;max-width:fit-content}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:read-only):focus~.md3-text-field-label,:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:not(:placeholder-shown)~.md3-text-field-label{top:0;inset-inline:1em}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled{--foreground-color: rgba(var(--md-scheme-on-surface), .38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-outline{border:.0625em solid rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~.md3-text-field-label{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-text-field-container.md3-text-field-outlined ::ng-deep .md3-input-element:disabled~[md3-icon-element]{color:rgba(var(--md-scheme-on-surface),.38)}:host .md3-supporting-text-container{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1.333332em;padding:0 1.333332em;font-size:.75em;font-weight:400;line-height:1.333332em;letter-spacing:.033332em;color:var(--label-color)}:host .md3-supporting-text-container.md3-has-error{color:rgb(var(--md-scheme-error))}:host .md3-supporting-text-container .md3-text-input-counter{margin-inline-start:auto}:host .md3-supporting-text-container>::ng-deep *{margin-top:.333332em}\n"] }]
6032
6033
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], fieldType: [{ type: i0.Input, args: [{ isSignal: true, alias: "field-type", required: false }] }], inputCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "input-counter", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], inputContainer: [{ type: i0.ViewChild, args: ['inputContainer', { isSignal: true }] }], input: [{ type: i0.ContentChild, args: [i0.forwardRef(() => InputElement), { isSignal: true }] }], iconElements: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { ...{ descendants: true }, isSignal: true }] }], iconButtons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconButton), { ...{ descendants: true }, isSignal: true }] }], controlName: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FormControlName), { isSignal: true }] }] } });
6033
6034
 
6034
6035
  class SupportingText {
@@ -6045,1207 +6046,1363 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
6045
6046
  }]
6046
6047
  }] });
6047
6048
 
6048
- /**
6049
- * Material 3 dialog shell. It extends the CDK dialog container, so focus
6050
- * trapping, focus restoration and the ARIA attributes are handled by the CDK
6051
- * while this component only owns the MD3 surface and its animation.
6052
- */
6053
- class Dialog extends CdkDialogContainer {
6054
- surface = viewChild('surface', /* @ts-ignore */
6055
- ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
6056
- isActive = signal(false, /* @ts-ignore */
6057
- ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
6058
- config = inject(DIALOG_CONFIG, { optional: true }) ?? {};
6059
- get surfaceElement() {
6060
- return this.surface()?.nativeElement ?? null;
6049
+ class MenuGroup {
6050
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
6051
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: MenuGroup, isStandalone: true, selector: "md3-menu-group", host: { attributes: { "role": "group" } }, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [":host{display:flex;flex-direction:column;gap:.125em;padding:.25em;background-color:var(--background-color);color:var(--foreground-color);border-radius:var(--menu-group-radius);box-shadow:var(--menu-group-shadow)}:host:first-child{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius)}:host:last-child{border-end-start-radius:var(--border-radius);border-end-end-radius:var(--border-radius)}:host ::ng-deep md3-divider{margin:.125em .5em}:host ::ng-deep [md3-menu-item]:first-child .md3-menu-item-container{--border-top-start-r: var(--md-border-radius-medium);--border-top-end-r: var(--md-border-radius-medium);border-start-start-radius:var(--border-top-start-r);border-start-end-radius:var(--border-top-end-r)}:host ::ng-deep [md3-menu-item]:last-child .md3-menu-item-container{--border-bottom-start-r: var(--md-border-radius-medium);--border-bottom-end-r: var(--md-border-radius-medium);border-end-start-radius:var(--border-bottom-start-r);border-end-end-radius:var(--border-bottom-end-r)}.md3-menu-group-label{padding:.5rem var(--menu-item-inline-padding, .75rem) .25rem;color:rgb(var(--md-scheme-on-surface-variant));font-size:.75rem;font-weight:500;line-height:1rem;letter-spacing:.03125rem}\n"] });
6052
+ }
6053
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuGroup, decorators: [{
6054
+ type: Component,
6055
+ args: [{ selector: 'md3-menu-group', imports: [], host: {
6056
+ 'role': 'group',
6057
+ }, template: "<ng-content></ng-content>\n", styles: [":host{display:flex;flex-direction:column;gap:.125em;padding:.25em;background-color:var(--background-color);color:var(--foreground-color);border-radius:var(--menu-group-radius);box-shadow:var(--menu-group-shadow)}:host:first-child{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius)}:host:last-child{border-end-start-radius:var(--border-radius);border-end-end-radius:var(--border-radius)}:host ::ng-deep md3-divider{margin:.125em .5em}:host ::ng-deep [md3-menu-item]:first-child .md3-menu-item-container{--border-top-start-r: var(--md-border-radius-medium);--border-top-end-r: var(--md-border-radius-medium);border-start-start-radius:var(--border-top-start-r);border-start-end-radius:var(--border-top-end-r)}:host ::ng-deep [md3-menu-item]:last-child .md3-menu-item-container{--border-bottom-start-r: var(--md-border-radius-medium);--border-bottom-end-r: var(--md-border-radius-medium);border-end-start-radius:var(--border-bottom-start-r);border-end-end-radius:var(--border-bottom-end-r)}.md3-menu-group-label{padding:.5rem var(--menu-item-inline-padding, .75rem) .25rem;color:rgb(var(--md-scheme-on-surface-variant));font-size:.75rem;font-weight:500;line-height:1rem;letter-spacing:.03125rem}\n"] }]
6058
+ }] });
6059
+
6060
+ class MenuItem {
6061
+ el;
6062
+ label = input('', { ...(ngDevMode ? { debugName: "label" } : /* istanbul ignore next */ {}), alias: 'label' });
6063
+ supportingText = input(null, { ...(ngDevMode ? { debugName: "supportingText" } : /* istanbul ignore next */ {}), alias: 'supporting-text' });
6064
+ trailingText = input(null, { ...(ngDevMode ? { debugName: "trailingText" } : /* istanbul ignore next */ {}), alias: 'trailing-text' });
6065
+ selected = model(null, { ...(ngDevMode ? { debugName: "selected" } : /* istanbul ignore next */ {}), alias: 'selected' });
6066
+ iconElements = contentChildren(IconElement, /* @ts-ignore */
6067
+ ...(ngDevMode ? [{ debugName: "iconElements" }] : /* istanbul ignore next */ []));
6068
+ get leading() {
6069
+ return this.iconElements().find((icon) => icon.iconType() === 'leading');
6061
6070
  }
6062
- /**
6063
- * Started by DialogService, either right after the dialog is created or
6064
- * once the dialog it replaces has had its head start. The animation runs on
6065
- * the next frame so the surface has a real from/to state.
6066
- */
6067
- startEnterAnimation() {
6068
- requestAnimationFrame(() => {
6069
- this.isActive.set(true);
6070
- });
6071
+ get trailing() {
6072
+ return this.iconElements().find((icon) => icon.iconType() === 'trailing');
6071
6073
  }
6072
- setActive(value) {
6073
- this.isActive.set(value);
6074
+ get showLeadingIcon() {
6075
+ return (!!this.leading && !this.selected()) || this.selected() == true;
6074
6076
  }
6075
- recaptureFocus() {
6076
- this._recaptureFocus();
6077
+ onHostClick() {
6078
+ const selected = this.selected();
6079
+ if (selected === null) {
6080
+ return;
6081
+ }
6082
+ this.selected.set(!selected);
6077
6083
  }
6078
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
6079
- 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"] }] });
6084
+ constructor(el) {
6085
+ this.el = el;
6086
+ }
6087
+ get element() {
6088
+ return this.el.nativeElement;
6089
+ }
6090
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuItem, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
6091
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: MenuItem, isStandalone: true, selector: "button[md3-menu-item], a[md3-menu-item]", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, supportingText: { classPropertyName: "supportingText", publicName: "supporting-text", isSignal: true, isRequired: false, transformFunction: null }, trailingText: { classPropertyName: "trailingText", publicName: "trailing-text", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange" }, host: { listeners: { "click": "onHostClick()" } }, queries: [{ propertyName: "iconElements", predicate: IconElement, isSignal: true }], ngImport: i0, template: "@if (selected() !== null) {\n <input type=\"checkbox\" md3-input-element [checked]=\"selected()\">\n}\n\n<div class=\"md3-menu-item-container\" md3-state-component>\n <div class=\"md3-menu-item-leading\" [class.has-icon]=\"showLeadingIcon\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n @if (!leading) {\n <md3-icon>check</md3-icon>\n }\n </div>\n\n <div class=\"md3-menu-item-content\">\n <md3-type-label size=\"large\">{{ label() }}</md3-type-label>\n @if (supportingText()?.length) {\n <md3-type-body size=\"small\">{{ supportingText() }}</md3-type-body>\n }\n </div>\n\n <div class=\"md3-menu-item-trailing\">\n <ng-content select=\"md3-badge\"></ng-content>\n @if (trailingText()?.length) {\n <md3-type-title size=\"small\">{{ trailingText() }}</md3-type-title>\n }\n <ng-content select=\"[md3-icon-element=trailing]\"></ng-content>\n </div>\n</div>", styles: [":host{--state-color: var(--menu-item-state-color);--border-radius: var(--menu-item-border-radius);--outline-color: var(--menu-item-outline-color);--outline-width: var(--menu-item-outline-width);--outline-offset: var(--menu-item-outline-offset);position:relative;display:block;padding:0;border:0;background:transparent;color:var(--menu-item-label-color);font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;appearance:none;-webkit-user-select:none;user-select:none;z-index:0}:host:focus{z-index:1}:host:focus:not(:hover) .md3-menu-item-container:after{opacity:1}:host:active{z-index:2}:host:active .md3-menu-item-container:after{opacity:0}:host .md3-menu-item-container{display:flex;align-items:center;min-height:3em;padding:0 .75em;border-radius:var(--border-radius);transition:background-color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading{display:inline-flex;align-items:center;justify-content:center;font-size:inherit;opacity:0;transform:scale(1.2);width:0;height:1.25em;color:var(--menu-item-supporting-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-leading.has-icon{margin-inline-end:.5em;opacity:1;transform:scale(1);height:1.25em;width:1.25em}:host .md3-menu-item-container .md3-menu-item-trailing{flex:0 1 content;display:inline-flex;gap:.5em;align-items:center;justify-content:center;font-size:inherit;margin-inline-start:.5em;color:var(--menu-item-supporting-color)}:host .md3-menu-item-container .md3-menu-item-trailing:empty{margin:0}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep md3-badge{background-color:var(--menu-item-badge-background);color:var(--menu-item-badge-foreground)}:host .md3-menu-item-container .md3-menu-item-trailing .md3-text-title.md3-text-small{margin:0;padding:0;white-space:nowrap;letter-spacing:.007143em}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-content{flex:1 1 auto}:host .md3-menu-item-container .md3-menu-item-content .md3-text-label.md3-text-large{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.007143em;color:var(--menu-item-label-color)}:host .md3-menu-item-container .md3-menu-item-content .md3-text-body.md3-text-small{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.0333334em;color:var(--menu-item-supporting-color)}:host [md3-input-element]{position:absolute;height:0;width:0;opacity:0;pointer-events:none}:host [md3-input-element]+.md3-menu-item-container .md3-menu-item-leading{opacity:0;transform:scale(1.2);width:0}:host [md3-input-element]:checked+.md3-menu-item-container{--menu-item-label-color: var(--menu-item-selected-foreground);--menu-item-supporting-color: var(--menu-item-selected-foreground);--border-radius: var(--md-border-radius-medium);background-color:var(--menu-item-selected-background)}:host [md3-input-element]:checked+.md3-menu-item-container .md3-menu-item-leading{opacity:1;transform:scale(1);width:1.25em}:host:disabled{cursor:default}:host:disabled .md3-menu-item-container{--menu-item-label-color: var(--menu-item-label-color);--menu-item-supporting-color: var(--menu-item-label-color);--menu-item-selected-background: transparent;--menu-item-selected-foreground: var(--menu-item-label-color);pointer-events:none;opacity:.38}:host:disabled .md3-menu-item-container.md3-state-layer,:host:disabled .md3-menu-item-container:after{display:none}\n"], dependencies: [{ kind: "directive", type: InputElement, selector: "[md3-input-element]" }, { kind: "directive", type: StateComponent, selector: "[md3-state-component]" }, { kind: "component", type: MaterialIcon, selector: "md3-icon", inputs: ["icon-version", "filled", "icon-style", "icon-size", "bi-directional"] }, { kind: "directive", type: TypeLabel, selector: "md3-type-label, [md3-type-label]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeBody, selector: "md3-type-body, [md3-type-body]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeTitle, selector: "md3-type-title, [md3-type-title]", inputs: ["size", "color", "emphasized"] }] });
6080
6092
  }
6081
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, decorators: [{
6093
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuItem, decorators: [{
6082
6094
  type: Component,
6083
- args: [{ selector: 'md3-dialog', imports: [
6084
- CdkPortalOutlet,
6085
- ], 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"] }]
6086
- }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
6095
+ args: [{ selector: 'button[md3-menu-item], a[md3-menu-item]', imports: [
6096
+ InputElement,
6097
+ StateComponent,
6098
+ MaterialIcon,
6099
+ TypeLabel,
6100
+ TypeBody,
6101
+ TypeTitle,
6102
+ ], host: {
6103
+ '(click)': 'onHostClick()',
6104
+ }, template: "@if (selected() !== null) {\n <input type=\"checkbox\" md3-input-element [checked]=\"selected()\">\n}\n\n<div class=\"md3-menu-item-container\" md3-state-component>\n <div class=\"md3-menu-item-leading\" [class.has-icon]=\"showLeadingIcon\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n @if (!leading) {\n <md3-icon>check</md3-icon>\n }\n </div>\n\n <div class=\"md3-menu-item-content\">\n <md3-type-label size=\"large\">{{ label() }}</md3-type-label>\n @if (supportingText()?.length) {\n <md3-type-body size=\"small\">{{ supportingText() }}</md3-type-body>\n }\n </div>\n\n <div class=\"md3-menu-item-trailing\">\n <ng-content select=\"md3-badge\"></ng-content>\n @if (trailingText()?.length) {\n <md3-type-title size=\"small\">{{ trailingText() }}</md3-type-title>\n }\n <ng-content select=\"[md3-icon-element=trailing]\"></ng-content>\n </div>\n</div>", styles: [":host{--state-color: var(--menu-item-state-color);--border-radius: var(--menu-item-border-radius);--outline-color: var(--menu-item-outline-color);--outline-width: var(--menu-item-outline-width);--outline-offset: var(--menu-item-outline-offset);position:relative;display:block;padding:0;border:0;background:transparent;color:var(--menu-item-label-color);font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;appearance:none;-webkit-user-select:none;user-select:none;z-index:0}:host:focus{z-index:1}:host:focus:not(:hover) .md3-menu-item-container:after{opacity:1}:host:active{z-index:2}:host:active .md3-menu-item-container:after{opacity:0}:host .md3-menu-item-container{display:flex;align-items:center;min-height:3em;padding:0 .75em;border-radius:var(--border-radius);transition:background-color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading{display:inline-flex;align-items:center;justify-content:center;font-size:inherit;opacity:0;transform:scale(1.2);width:0;height:1.25em;color:var(--menu-item-supporting-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-leading.has-icon{margin-inline-end:.5em;opacity:1;transform:scale(1);height:1.25em;width:1.25em}:host .md3-menu-item-container .md3-menu-item-trailing{flex:0 1 content;display:inline-flex;gap:.5em;align-items:center;justify-content:center;font-size:inherit;margin-inline-start:.5em;color:var(--menu-item-supporting-color)}:host .md3-menu-item-container .md3-menu-item-trailing:empty{margin:0}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep md3-badge{background-color:var(--menu-item-badge-background);color:var(--menu-item-badge-foreground)}:host .md3-menu-item-container .md3-menu-item-trailing .md3-text-title.md3-text-small{margin:0;padding:0;white-space:nowrap;letter-spacing:.007143em}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-content{flex:1 1 auto}:host .md3-menu-item-container .md3-menu-item-content .md3-text-label.md3-text-large{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.007143em;color:var(--menu-item-label-color)}:host .md3-menu-item-container .md3-menu-item-content .md3-text-body.md3-text-small{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.0333334em;color:var(--menu-item-supporting-color)}:host [md3-input-element]{position:absolute;height:0;width:0;opacity:0;pointer-events:none}:host [md3-input-element]+.md3-menu-item-container .md3-menu-item-leading{opacity:0;transform:scale(1.2);width:0}:host [md3-input-element]:checked+.md3-menu-item-container{--menu-item-label-color: var(--menu-item-selected-foreground);--menu-item-supporting-color: var(--menu-item-selected-foreground);--border-radius: var(--md-border-radius-medium);background-color:var(--menu-item-selected-background)}:host [md3-input-element]:checked+.md3-menu-item-container .md3-menu-item-leading{opacity:1;transform:scale(1);width:1.25em}:host:disabled{cursor:default}:host:disabled .md3-menu-item-container{--menu-item-label-color: var(--menu-item-label-color);--menu-item-supporting-color: var(--menu-item-label-color);--menu-item-selected-background: transparent;--menu-item-selected-foreground: var(--menu-item-label-color);pointer-events:none;opacity:.38}:host:disabled .md3-menu-item-container.md3-state-layer,:host:disabled .md3-menu-item-container:after{display:none}\n"] }]
6105
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], supportingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "supporting-text", required: false }] }], trailingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailing-text", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], iconElements: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { isSignal: true }] }] } });
6087
6106
 
6088
- /**
6089
- * Material 3 full screen dialog shell. It covers the viewport and holds the content.
6090
- *
6091
- * The content is an `md3-layout`. The layout places the regions — the bar rows for an app bar
6092
- * or a toolbar, the rail columns, and the panes where side sheets open — so the dialog itself
6093
- * places nothing but the content. A content root that is not a layout gets a warning in
6094
- * development mode, and the shell falls back to panes of its own, so a side sheet never opens
6095
- * behind the dialog where nobody can see it.
6096
- */
6097
- class FullScreenDialog extends CdkDialogContainer {
6098
- surface = viewChild('surface', /* @ts-ignore */
6099
- ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
6100
- mainPane = viewChild('mainPane', /* @ts-ignore */
6101
- ...(ngDevMode ? [{ debugName: "mainPane" }] : /* istanbul ignore next */ []));
6102
- startOutlet = viewChild('startOutlet', { ...(ngDevMode ? { debugName: "startOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
6103
- endOutlet = viewChild('endOutlet', { ...(ngDevMode ? { debugName: "endOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
6104
- sheets = inject(SheetsService);
6105
- /** True while the shell holds the side sheet outlets, which happens without a layout only. */
6106
- ownsSideSheetOutlets = false;
6107
- isActive = signal(false, /* @ts-ignore */
6108
- ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
6109
- config = inject(DIALOG_CONFIG, { optional: true }) ?? {};
6110
- get surfaceElement() {
6111
- return this.surface()?.nativeElement ?? null;
6112
- }
6113
- ngAfterViewInit() {
6114
- // The content is attached by now, so the layout it brings has already taken the
6115
- // outlets. Its panes sit under the bar regions, which is where a side sheet belongs.
6116
- const layout = this.findContentLayout();
6117
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
6118
- this.checkContentLayout(layout);
6119
- }
6120
- if (layout) {
6107
+ class SelectOptions {
6108
+ options = input.required(/* @ts-ignore */
6109
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
6110
+ multiple = input(false, /* @ts-ignore */
6111
+ ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
6112
+ /** Emits the values selected by the user. The field owns the selection state. */
6113
+ selectionChange = output();
6114
+ optionClick(index) {
6115
+ const options = this.options();
6116
+ const option = options.at(index);
6117
+ if (!option) {
6121
6118
  return;
6122
6119
  }
6123
- // No layout, so the shell keeps the dialog self-sufficient. Without this the next side
6124
- // sheet would open in the outlet underneath — the page scaffold, behind the dialog.
6125
- const startOutlet = this.startOutlet();
6126
- const endOutlet = this.endOutlet();
6127
- if (startOutlet) {
6128
- this.sheets.registerSideSheetOutlet('start', startOutlet);
6129
- }
6130
- if (endOutlet) {
6131
- this.sheets.registerSideSheetOutlet('end', endOutlet);
6120
+ if (this.multiple()) {
6121
+ option.selected = !(option.selected ?? false);
6132
6122
  }
6133
- this.ownsSideSheetOutlets = !!startOutlet || !!endOutlet;
6134
- }
6135
- ngOnDestroy() {
6136
- if (this.ownsSideSheetOutlets) {
6137
- const startOutlet = this.startOutlet();
6138
- const endOutlet = this.endOutlet();
6139
- if (startOutlet) {
6140
- this.sheets.unregisterSideSheetOutlet('start', startOutlet);
6141
- }
6142
- if (endOutlet) {
6143
- this.sheets.unregisterSideSheetOutlet('end', endOutlet);
6144
- }
6145
- this.ownsSideSheetOutlets = false;
6123
+ else {
6124
+ options.forEach((item, i) => {
6125
+ item.selected = i == index;
6126
+ });
6146
6127
  }
6147
- super.ngOnDestroy();
6128
+ this.selectionChange.emit(options.filter((item) => item.selected).map((item) => item.value));
6148
6129
  }
6130
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectOptions, deps: [], target: i0.ɵɵFactoryTarget.Component });
6131
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SelectOptions, isStandalone: true, selector: "md3-select-options", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, ngImport: i0, template: "<md3-menu-group class=\"md3-scrollable\">\n @for (item of options(); track `${$index}-${item.value}`) {\n <button\n md3-menu-item\n [selected]=\"item.selected ?? false\"\n [label]=\"item.label\"\n [supporting-text]=\"item.supportingText ?? null\"\n [trailing-text]=\"item.trailingText ?? null\"\n (click)=\"optionClick($index)\"\n >\n </button>\n }\n</md3-menu-group>", styles: [":host{max-height:inherit}:host md3-menu-group.md3-scrollable{padding:.5em .375em;max-height:inherit;overflow-y:auto}\n"], dependencies: [{ kind: "component", type: MenuGroup, selector: "md3-menu-group" }, { kind: "component", type: MenuItem, selector: "button[md3-menu-item], a[md3-menu-item]", inputs: ["label", "supporting-text", "trailing-text", "selected"], outputs: ["selectedChange"] }] });
6132
+ }
6133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectOptions, decorators: [{
6134
+ type: Component,
6135
+ args: [{ selector: 'md3-select-options', imports: [
6136
+ MenuGroup,
6137
+ MenuItem,
6138
+ ], template: "<md3-menu-group class=\"md3-scrollable\">\n @for (item of options(); track `${$index}-${item.value}`) {\n <button\n md3-menu-item\n [selected]=\"item.selected ?? false\"\n [label]=\"item.label\"\n [supporting-text]=\"item.supportingText ?? null\"\n [trailing-text]=\"item.trailingText ?? null\"\n (click)=\"optionClick($index)\"\n >\n </button>\n }\n</md3-menu-group>", styles: [":host{max-height:inherit}:host md3-menu-group.md3-scrollable{padding:.5em .375em;max-height:inherit;overflow-y:auto}\n"] }]
6139
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
6140
+
6141
+ const MENU_DATA = new InjectionToken('MD3_MENU_DATA');
6142
+ const MENU_CONFIG = new InjectionToken('MD3_MENU_CONFIG');
6143
+ const MENU_COMPONENT = new InjectionToken('MD3_MENU_COMPONENT');
6144
+ const MENU_EXIT_ANIMATION_FALLBACK_MS = 300;
6145
+ class MenuRef {
6146
+ overlayRef;
6147
+ previouslyFocusedElement;
6148
+ closed = new Subject();
6149
+ isClosed = false;
6150
+ menuInstance;
6149
6151
  /**
6150
- * The layout at the root of the content, if the content brought one.
6151
- *
6152
- * The root is either the layout itself, or the component that holds it — a dialog is
6153
- * normally opened with a component whose own template starts with `md3-layout`.
6152
+ * Filled by MenuService after the user component is attached. Keeping the
6153
+ * instance here lets callers imperatively update inputs when that is useful.
6154
6154
  */
6155
- findContentLayout() {
6156
- const content = this.mainPane()?.nativeElement.firstElementChild;
6157
- if (!content) {
6158
- return null;
6159
- }
6160
- if (content.tagName === 'MD3-LAYOUT') {
6161
- return content;
6162
- }
6163
- const root = content.firstElementChild;
6164
- return root?.tagName === 'MD3-LAYOUT' ? root : null;
6155
+ componentInstance;
6156
+ constructor(overlayRef, previouslyFocusedElement) {
6157
+ this.overlayRef = overlayRef;
6158
+ this.previouslyFocusedElement = previouslyFocusedElement;
6165
6159
  }
6166
- checkContentLayout(layout) {
6167
- if (layout) {
6160
+ close(result) {
6161
+ if (this.isClosed) {
6168
6162
  return;
6169
6163
  }
6170
- console.warn('[md3-fullscreen-dialog] the content of a full screen dialog should start with '
6171
- + 'md3-layout. Without it the dialog has no bar and no rail region, so an app bar or '
6172
- + 'a toolbar has nowhere to go, and the content does not scroll on its own.');
6173
- }
6174
- startEnterAnimation() {
6175
- requestAnimationFrame(() => {
6176
- this.isActive.set(true);
6164
+ this.isClosed = true;
6165
+ this.startCloseAnimation().then(() => {
6166
+ // Disposing the overlay removes the wrapper, the backdrop, and the
6167
+ // dynamically attached content component in one operation.
6168
+ this.overlayRef.dispose();
6169
+ // this.previouslyFocusedElement?.focus();
6170
+ this.closed.next(result);
6171
+ this.closed.complete();
6177
6172
  });
6178
6173
  }
6179
- setActive(value) {
6180
- this.isActive.set(value);
6174
+ startCloseAnimation() {
6175
+ let panel = this.overlayRef.overlayElement;
6176
+ let animatedElement = panel.querySelector('.md3-menu-container') ?? panel;
6177
+ panel.classList.add('md3-menu-closing');
6178
+ this.menuInstance?.showMenu(false);
6179
+ return new Promise((resolve) => {
6180
+ let isResolved = false;
6181
+ let timeoutId = setTimeout(done, MENU_EXIT_ANIMATION_FALLBACK_MS);
6182
+ function done() {
6183
+ if (isResolved) {
6184
+ return;
6185
+ }
6186
+ isResolved = true;
6187
+ clearTimeout(timeoutId);
6188
+ animatedElement.removeEventListener('transitionend', onTransitionEnd);
6189
+ resolve();
6190
+ }
6191
+ function onTransitionEnd(event) {
6192
+ if (event.target === animatedElement) {
6193
+ done();
6194
+ }
6195
+ }
6196
+ animatedElement.addEventListener('transitionend', onTransitionEnd);
6197
+ });
6181
6198
  }
6182
- recaptureFocus() {
6183
- this._recaptureFocus();
6199
+ afterClosed() {
6200
+ return this.closed.asObservable();
6184
6201
  }
6185
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
6186
- 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: "mainPane", first: true, predicate: ["mainPane"], 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\" #mainPane>\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);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}: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"] }] });
6187
6202
  }
6188
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, decorators: [{
6189
- type: Component,
6190
- args: [{ selector: 'md3-fullscreen-dialog', imports: [
6191
- CdkPortalOutlet,
6192
- ], 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\" #mainPane>\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);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
6193
- }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }], mainPane: [{ type: i0.ViewChild, args: ['mainPane', { isSignal: true }] }], startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }] } });
6194
6203
 
6195
- const PANEL_CLASS = 'md3-dialog-panel';
6196
- const FULL_SCREEN_PANEL_CLASS = 'md3-fullscreen-dialog-panel';
6197
- const OPENING_CLASS = 'md3-dialog-opening';
6198
- const SCRIM_KEPT_CLASS = 'md3-dialog-scrim-kept';
6199
- const SCRIM_INSTANT_CLASS = 'md3-dialog-scrim-instant';
6200
- /**
6201
- * Head start given to a dialog that leaves the screen before the dialog taking
6202
- * its place animates in. Long enough to read as one dialog replacing another,
6203
- * short enough to still feel like a single gesture.
6204
- */
6205
- const DIALOG_HANDOVER_DELAY_MS = 160;
6206
- class DialogService {
6207
- cdkDialog = inject(Dialog$1);
6208
- overlay = inject(Overlay);
6209
- overlayContainer = inject(OverlayContainer);
6210
- injector = inject(Injector);
6211
- document = inject(DOCUMENT);
6212
- /** Open dialogs, from the first one opened to the one currently on top. */
6213
- refs = [];
6214
- /**
6215
- * Elements the page was made of that the CDK hid from assistive technology,
6216
- * kept here while the dialogs are hidden and the page is given back.
6217
- */
6218
- pageAriaHidden = new Map();
6219
- /**
6220
- * Page scrolling is blocked here instead of per overlay, so stacked dialogs
6221
- * cannot unblock the page while another dialog is still open.
6222
- */
6223
- scrollBlock = this.overlay.scrollStrategies.block();
6224
- /** Element that was focused before the first dialog of the stack opened. */
6225
- rootTrigger = null;
6226
- pageStateQueued = false;
6227
- get openDialogs() {
6228
- return this.refs;
6229
- }
6230
- /** Open dialogs that are currently on screen, from the bottom one up. */
6231
- get visibleDialogs() {
6232
- return this.refs.filter((ref) => !ref.isHidden);
6233
- }
6234
- /** The full screen dialog that is open, if there is one. */
6235
- get fullScreenDialog() {
6236
- return this.refs.find((ref) => ref.isFullScreen && !ref.isClosing);
6204
+ class Menu {
6205
+ el;
6206
+ portalOutlet = viewChild(CdkPortalOutlet, /* @ts-ignore */
6207
+ ...(ngDevMode ? [{ debugName: "portalOutlet" }] : /* istanbul ignore next */ []));
6208
+ config = inject(MENU_CONFIG, { optional: true }) ?? {};
6209
+ menuColors = signal('standard', /* @ts-ignore */
6210
+ ...(ngDevMode ? [{ debugName: "menuColors" }] : /* istanbul ignore next */ []));
6211
+ isVisible = signal(false, /* @ts-ignore */
6212
+ ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
6213
+ scheme = signal('inherit', /* @ts-ignore */
6214
+ ...(ngDevMode ? [{ debugName: "scheme" }] : /* istanbul ignore next */ []));
6215
+ direction = signal(null, /* @ts-ignore */
6216
+ ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
6217
+ isActive = signal(true, /* @ts-ignore */
6218
+ ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
6219
+ get element() {
6220
+ return this.el.nativeElement;
6237
6221
  }
6238
- open(component, config = {}) {
6239
- const dialogConfig = this.mergeConfig(config);
6240
- if (this.refs.length === 0) {
6241
- this.rootTrigger = this.getFocusedElement();
6242
- }
6243
- // The dialog that is on screen starts leaving first, so the two dialogs
6244
- // never animate on top of each other. A full screen dialog is not part
6245
- // of this: regular dialogs open on top of it and leave it alone.
6246
- const previousRef = this.topRegularRef();
6247
- if (previousRef) {
6248
- this.dismissPrevious(previousRef, dialogConfig.previousDialog);
6249
- }
6250
- let dialogRef;
6251
- const cdkRef = this.cdkDialog.open(component, {
6252
- // The MD3 shell replaces the default CDK container, so the overlay,
6253
- // focus trap and focus restoration come from the CDK while the shell
6254
- // only renders the surface.
6255
- container: {
6256
- type: Dialog,
6257
- providers: () => [
6258
- { provide: DIALOG_CONFIG, useValue: dialogConfig },
6259
- ],
6260
- },
6261
- // These tokens make the dialog controllable from the dynamic
6262
- // component without coupling that component to the service.
6263
- providers: (cdkDialogRef) => {
6264
- dialogRef = new DialogRef(cdkDialogRef, dialogConfig.disableCloseEvents);
6265
- return [
6266
- { provide: DialogRef, useValue: dialogRef },
6267
- { provide: DIALOG_DATA, useValue: dialogConfig.data },
6268
- { provide: DIALOG_CONFIG, useValue: dialogConfig },
6269
- { provide: DIALOG_COMPONENT, useValue: component },
6270
- ];
6271
- },
6272
- data: dialogConfig.data,
6273
- role: dialogConfig.role,
6274
- ariaModal: true,
6275
- ariaLabel: dialogConfig.ariaLabel || null,
6276
- ariaLabelledBy: dialogConfig.ariaLabelledBy || null,
6277
- ariaDescribedBy: dialogConfig.ariaDescribedBy || null,
6278
- direction: dialogConfig.direction ?? undefined,
6279
- viewContainerRef: dialogConfig.viewContainerRef,
6280
- injector: dialogConfig.injector,
6281
- hasBackdrop: true,
6282
- backdropClass: ['md3-dialog-scrim', OPENING_CLASS],
6283
- panelClass: [PANEL_CLASS, OPENING_CLASS],
6284
- positionStrategy: this.overlay.position()
6285
- .global()
6286
- .centerHorizontally()
6287
- .centerVertically(),
6288
- // Scrolling is blocked by the service for the whole stack.
6289
- scrollStrategy: this.overlay.scrollStrategies.noop(),
6290
- // Focus goes back to whatever opened the stack, even when the dialog
6291
- // that was open underneath has been closed in the meantime.
6292
- restoreFocus: this.rootTrigger ?? true,
6293
- // Scrim and Escape handling lives in DialogRef so the dialog can
6294
- // play its exit animation before the overlay is disposed.
6295
- disableClose: true,
6222
+ constructor(el) {
6223
+ this.el = el;
6224
+ effect((onCleanup) => {
6225
+ const color = 'md3-' + this.menuColors();
6226
+ this.element.classList.add(color);
6227
+ onCleanup(() => {
6228
+ this.element.classList.remove(color);
6229
+ });
6296
6230
  });
6297
- this.registerDialog(dialogRef, cdkRef, dialogConfig, previousRef);
6298
- return dialogRef;
6231
+ this.menuColors.set(this.config.menuColors ?? 'standard');
6232
+ this.scheme.set(this.config.scheme ?? 'inherit');
6233
+ this.direction.set(this.config.direction ?? null);
6299
6234
  }
6300
- /**
6301
- * Opens a dialog that covers the whole screen. Only one can be open at a
6302
- * time, so it replaces whatever is open, and while it is up the side sheet
6303
- * outlets belong to it: side sheets open inside the dialog, not behind it.
6304
- * `previousDialog` decides what happens to the dialogs it replaces, the
6305
- * same way it does for a regular dialog.
6306
- */
6307
- openFullScreen(component, config = {}) {
6308
- const dialogConfig = this.mergeConfig(config);
6309
- if (this.refs.length === 0) {
6310
- this.rootTrigger = this.getFocusedElement();
6311
- }
6312
- // A full screen dialog is a context of its own: the dialog it replaces
6313
- // and anything stacked on that dialog goes with it.
6314
- const previousRef = this.topRef();
6315
- if (previousRef) {
6316
- // Everything open belongs to the context being replaced, including
6317
- // a full screen dialog that is already up.
6318
- this.dismissPreviousContext(dialogConfig.previousDialog);
6319
- }
6320
- let dialogRef;
6321
- const cdkRef = this.cdkDialog.open(component, {
6322
- container: {
6323
- type: FullScreenDialog,
6324
- providers: () => [
6325
- { provide: DIALOG_CONFIG, useValue: dialogConfig },
6326
- ],
6327
- },
6328
- providers: (cdkDialogRef) => {
6329
- dialogRef = new DialogRef(cdkDialogRef, dialogConfig.disableCloseEvents, true);
6330
- return [
6331
- { provide: DialogRef, useValue: dialogRef },
6332
- { provide: DIALOG_DATA, useValue: dialogConfig.data },
6333
- { provide: DIALOG_CONFIG, useValue: dialogConfig },
6334
- { provide: DIALOG_COMPONENT, useValue: component },
6335
- ];
6336
- },
6337
- data: dialogConfig.data,
6338
- role: dialogConfig.role,
6339
- ariaModal: true,
6340
- ariaLabel: dialogConfig.ariaLabel || null,
6341
- ariaLabelledBy: dialogConfig.ariaLabelledBy || null,
6342
- ariaDescribedBy: dialogConfig.ariaDescribedBy || null,
6343
- direction: dialogConfig.direction ?? undefined,
6344
- viewContainerRef: dialogConfig.viewContainerRef,
6345
- injector: dialogConfig.injector,
6346
- // The dialog covers the page on its own, so there is nothing left
6347
- // for a scrim to dim.
6348
- hasBackdrop: false,
6349
- panelClass: [FULL_SCREEN_PANEL_CLASS, OPENING_CLASS],
6350
- // The CDK writes the size on the panel and the global strategy then
6351
- // drops its centering margins, which is how the panel ends up
6352
- // covering the whole wrapper.
6353
- width: '100%',
6354
- height: '100%',
6355
- positionStrategy: this.overlay.position().global(),
6356
- scrollStrategy: this.overlay.scrollStrategies.noop(),
6357
- restoreFocus: this.rootTrigger ?? true,
6358
- disableClose: true,
6235
+ ngAfterContentInit() {
6236
+ requestAnimationFrame(() => {
6237
+ this.showMenu(true);
6359
6238
  });
6360
- this.registerDialog(dialogRef, cdkRef, dialogConfig, previousRef);
6361
- return dialogRef;
6362
- }
6363
- /** Wires a freshly created dialog into the stack and starts its animation. */
6364
- registerDialog(dialogRef, cdkRef, dialogConfig, previousRef) {
6365
- dialogRef.dialogInstance = cdkRef.containerInstance;
6366
- dialogRef.componentInstance = cdkRef.componentInstance ?? undefined;
6367
- if (cdkRef.componentRef) {
6368
- this.bindDataToInputs(cdkRef.componentRef, dialogConfig);
6369
- }
6370
- this.refs.push(dialogRef);
6371
- this.syncPageState();
6372
- if (previousRef) {
6373
- setTimeout(() => this.startReplacingAnimation(dialogRef, previousRef), DIALOG_HANDOVER_DELAY_MS);
6374
- }
6375
- else {
6376
- this.startOpenAnimation(dialogRef);
6377
- }
6378
- // Restoring starts with the exit animation, so the dialog underneath is
6379
- // already coming back while this one is fading out.
6380
- dialogRef.beforeClosed().subscribe(() => this.restorePreviousDialog(dialogRef));
6381
- dialogRef.afterClosed().subscribe(() => this.removeRef(dialogRef));
6382
- // Hiding and showing can also come straight from the reference, so the
6383
- // page state is driven by what the dialogs report rather than by the
6384
- // calls that went through this service.
6385
- dialogRef.hiddenChanged().subscribe(() => this.syncPageState());
6386
6239
  }
6387
- /**
6388
- * Hides every dialog that is on screen, the full screen one included, with
6389
- * the closing animation. They stay alive with their content and state, the
6390
- * page underneath becomes usable, and showAll() puts them back. The promise
6391
- * resolves once they are all out of sight.
6392
- */
6393
- hideAll() {
6394
- const visible = this.refs.filter((ref) => !ref.isHidden && !ref.isClosing);
6395
- return Promise.all(visible.map((ref) => ref.hide())).then(() => undefined);
6240
+ showMenu(value) {
6241
+ this.isVisible.set(value);
6396
6242
  }
6397
6243
  /**
6398
- * Brings the dialogs back on screen, whether they were hidden one by one or
6399
- * all at once: the dialog that was on top returns, along with the full
6400
- * screen dialog it sits in. Dialogs hidden behind another dialog stay
6401
- * hidden, since that is where they belong once the stack is back.
6244
+ * The service creates this wrapper first, then calls this method to mount
6245
+ * the user supplied component into the dialog container.
6402
6246
  */
6403
- showAll() {
6404
- const topRef = this.topRef();
6405
- if (!topRef) {
6406
- return;
6407
- }
6408
- const fullScreenRef = this.fullScreenDialog;
6409
- // The full screen dialog is the context the top one sits in, so it
6410
- // comes back first and the dialog on top ends up on top, with the focus.
6411
- if (fullScreenRef && fullScreenRef !== topRef && fullScreenRef.isHidden) {
6412
- fullScreenRef.show();
6413
- }
6414
- if (topRef.isHidden) {
6415
- topRef.show();
6416
- }
6247
+ attachContent(component, injector) {
6248
+ const portal = new ComponentPortal(component, null, injector);
6249
+ return this.portalOutlet().attachComponentPortal(portal);
6417
6250
  }
6418
- /** Closes every open dialog, including the hidden and the full screen ones. */
6419
- closeAll() {
6420
- // Closed from the bottom up so a closing dialog never brings back a
6421
- // hidden dialog that is about to close as well.
6422
- return Promise.all([...this.refs].map((ref) => ref.close())).then(() => undefined);
6251
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Menu, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
6252
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Menu, isStandalone: true, selector: "md3-menu", host: { attributes: { "role": "menu" }, properties: { "class.md3-visible": "isVisible()", "class.md3-inactive": "!isActive()", "class.md-scheme-dark": "scheme() == \"dark\"", "class.md-scheme-light": "scheme() == \"light\"", "dir": "direction()" }, classAttribute: "md3-menu-container" }, viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template cdkPortalOutlet></ng-template>", 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-menu-scrim{position:absolute;inset:0;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-overlay-connected-position-bounding-box{pointer-events:none}::ng-deep .cdk-overlay-container .md3-menu-panel{pointer-events:auto}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-select-menu>.md3-menu-container{--menu-min-width: 100%;--menu-max-width: 100%}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-menu-closing{pointer-events:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 0;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel{position:absolute;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel.md3-menu-closing{pointer-events:none}:host{--background-color: rgb(var(--md-scheme-surface-container-low));--foreground-color: rgb(var(--md-scheme-on-surface));--border-radius: var(--md-border-radius-large);--menu-min-width: 7em;--menu-max-width: 17.5em;--menu-group-radius: var(--md-border-radius-small);--menu-group-shadow: var(--md-shadow-3dp);--menu-group-label-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-label-color: rgb(var(--md-scheme-on-surface));--menu-item-supporting-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-selected-background: rgb(var(--md-scheme-tertiary-container));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary-container));--menu-item-state-color: var(--md-scheme-on-surface);--menu-item-border-radius: var(--md-border-radius-xsmall);--menu-item-outline-color: rgb(var(--md-scheme-secondary));--menu-item-outline-width: .1875em;--menu-item-outline-offset: -.1875em;--menu-item-badge-background: rgb(var(--md-scheme-primary-container));--menu-item-badge-foreground: rgb(var(--md-scheme-on-primary-container));position:relative;display:block;font-size:1rem;min-width:var(--menu-min-width);max-width:min(var(--menu-max-width),100vw - 2rem);max-height:min(32rem,100vh - 2rem);outline:none;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8)}:host.md3-visible{opacity:1;transform:scaleY(1)}:host.md3-vibrant{--background-color: rgb(var(--md-scheme-tertiary-container));--foreground-color: rgb(var(--md-scheme-on-tertiary-container));--menu-group-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-supporting-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-selected-background: rgb(var(--md-scheme-tertiary));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary));--menu-item-state-color: var(--md-scheme-on-tertiary-container)}:host.md3-inactive{--border-radius: var(--md-border-radius-small)}:host ::ng-deep md3-menu-group{margin-top:.125em}:host ::ng-deep md3-menu-group:first-child{margin-top:0}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
6253
+ }
6254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Menu, decorators: [{
6255
+ type: Component,
6256
+ args: [{ selector: 'md3-menu', imports: [
6257
+ CdkPortalOutlet,
6258
+ ], host: {
6259
+ 'class': 'md3-menu-container',
6260
+ 'role': 'menu',
6261
+ '[class.md3-visible]': 'isVisible()',
6262
+ '[class.md3-inactive]': '!isActive()',
6263
+ '[class.md-scheme-dark]': 'scheme() == "dark"',
6264
+ '[class.md-scheme-light]': 'scheme() == "light"',
6265
+ '[dir]': 'direction()',
6266
+ }, template: "<ng-template cdkPortalOutlet></ng-template>", 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-menu-scrim{position:absolute;inset:0;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-overlay-connected-position-bounding-box{pointer-events:none}::ng-deep .cdk-overlay-container .md3-menu-panel{pointer-events:auto}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-select-menu>.md3-menu-container{--menu-min-width: 100%;--menu-max-width: 100%}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-menu-closing{pointer-events:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 0;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel{position:absolute;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel.md3-menu-closing{pointer-events:none}:host{--background-color: rgb(var(--md-scheme-surface-container-low));--foreground-color: rgb(var(--md-scheme-on-surface));--border-radius: var(--md-border-radius-large);--menu-min-width: 7em;--menu-max-width: 17.5em;--menu-group-radius: var(--md-border-radius-small);--menu-group-shadow: var(--md-shadow-3dp);--menu-group-label-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-label-color: rgb(var(--md-scheme-on-surface));--menu-item-supporting-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-selected-background: rgb(var(--md-scheme-tertiary-container));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary-container));--menu-item-state-color: var(--md-scheme-on-surface);--menu-item-border-radius: var(--md-border-radius-xsmall);--menu-item-outline-color: rgb(var(--md-scheme-secondary));--menu-item-outline-width: .1875em;--menu-item-outline-offset: -.1875em;--menu-item-badge-background: rgb(var(--md-scheme-primary-container));--menu-item-badge-foreground: rgb(var(--md-scheme-on-primary-container));position:relative;display:block;font-size:1rem;min-width:var(--menu-min-width);max-width:min(var(--menu-max-width),100vw - 2rem);max-height:min(32rem,100vh - 2rem);outline:none;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8)}:host.md3-visible{opacity:1;transform:scaleY(1)}:host.md3-vibrant{--background-color: rgb(var(--md-scheme-tertiary-container));--foreground-color: rgb(var(--md-scheme-on-tertiary-container));--menu-group-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-supporting-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-selected-background: rgb(var(--md-scheme-tertiary));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary));--menu-item-state-color: var(--md-scheme-on-tertiary-container)}:host.md3-inactive{--border-radius: var(--md-border-radius-small)}:host ::ng-deep md3-menu-group{margin-top:.125em}:host ::ng-deep md3-menu-group:first-child{margin-top:0}\n"] }]
6267
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { portalOutlet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkPortalOutlet), { isSignal: true }] }] } });
6268
+
6269
+ class MenuService {
6270
+ overlay = inject(Overlay);
6271
+ injector = inject(Injector);
6272
+ document = inject(DOCUMENT);
6273
+ open(component, config = {}) {
6274
+ const menuConfig = this.mergeConfig(config);
6275
+ const previouslyFocusedElement = this.getFocusedElement();
6276
+ const triggerElement = this.resolveTriggerElement(menuConfig.origin, previouslyFocusedElement);
6277
+ const menuOverlay = this.createOverlay(menuConfig, previouslyFocusedElement);
6278
+ const overlayRef = menuOverlay.overlayRef;
6279
+ const menuRef = new MenuRef(overlayRef, previouslyFocusedElement);
6280
+ const injector = this.createInjector(component, menuConfig, menuRef);
6281
+ // The overlay hosts the MD3 menu shell. The shell is responsible for
6282
+ // the surface markup and receives the dynamic content through a portal.
6283
+ const menuPortal = new ComponentPortal(Menu, menuConfig.viewContainerRef ?? null, injector);
6284
+ const menuComponentRef = overlayRef.attach(menuPortal);
6285
+ const contentComponentRef = menuComponentRef.instance.attachContent(component, injector);
6286
+ this.bindDataToInputs(contentComponentRef, menuConfig);
6287
+ this.flipPositionIfPushBreaksAnchor(menuOverlay, menuConfig);
6288
+ menuRef.componentInstance = contentComponentRef.instance;
6289
+ menuRef.menuInstance = menuComponentRef.instance;
6290
+ this.bindTriggerActiveState(triggerElement, overlayRef, menuRef);
6291
+ this.startOpenAnimation(overlayRef);
6292
+ this.connectCloseEvents(overlayRef, menuRef, menuOverlay.origin);
6293
+ return menuRef;
6423
6294
  }
6424
- /** Closes the regular dialogs and leaves a full screen dialog alone. */
6425
- closeRegularDialogs() {
6426
- const closing = this.refs
6427
- .filter((ref) => !ref.isFullScreen)
6428
- .map((ref) => ref.close());
6429
- return Promise.all(closing).then(() => undefined);
6295
+ openSubMenu(component, config = {}) {
6296
+ const xPosition = this.getSubMenuXPosition(config.xPosition);
6297
+ const yPosition = config.yPosition ?? 'below';
6298
+ const offsetX = config.offsetX ?? 0;
6299
+ const offsetY = config.offsetY ?? 0;
6300
+ const subMenuConfig = {
6301
+ ...config,
6302
+ isSubMenu: true,
6303
+ xPosition,
6304
+ yPosition,
6305
+ overlapTrigger: config.overlapTrigger ?? true,
6306
+ offsetX,
6307
+ offsetY,
6308
+ scheme: config.scheme ?? 'inherit',
6309
+ direction: config.direction ?? null,
6310
+ };
6311
+ return this.open(component, subMenuConfig);
6430
6312
  }
6431
6313
  mergeConfig(config) {
6314
+ const viewportMargin = this.getViewportMargin(config.viewportMargin);
6432
6315
  return {
6433
6316
  data: config.data,
6434
6317
  bindDataToInputs: config.bindDataToInputs ?? false,
6435
- disableCloseEvents: config.disableCloseEvents ?? false,
6436
- previousDialog: config.previousDialog ?? 'close',
6437
- role: config.role ?? 'dialog',
6438
- ariaLabel: config.ariaLabel ?? '',
6439
- ariaLabelledBy: config.ariaLabelledBy ?? '',
6440
- ariaDescribedBy: config.ariaDescribedBy ?? '',
6318
+ isSubMenu: config.isSubMenu ?? false,
6319
+ menuColors: config.menuColors ?? 'standard',
6320
+ origin: config.origin,
6321
+ xPosition: config.xPosition ?? 'start',
6322
+ yPosition: config.yPosition ?? 'below',
6323
+ overlapTrigger: config.overlapTrigger ?? false,
6324
+ offsetX: config.offsetX ?? 0,
6325
+ offsetY: config.offsetY ?? 4,
6326
+ viewportMargin,
6327
+ positions: config.positions,
6328
+ scrollStrategy: config.scrollStrategy ?? 'reposition',
6441
6329
  scheme: config.scheme ?? 'inherit',
6442
6330
  direction: config.direction ?? null,
6443
6331
  viewContainerRef: config.viewContainerRef,
6444
6332
  injector: config.injector ?? this.injector,
6445
6333
  };
6446
6334
  }
6447
- /**
6448
- * Hides or closes the dialog that is on screen. Its scrim stays up until
6449
- * the dialog taking over is ready for it, so the page behind never
6450
- * brightens between the two dialogs.
6451
- */
6452
- dismissPrevious(previousRef, behavior) {
6453
- previousRef.overlayRef.backdropElement?.classList.add(SCRIM_KEPT_CLASS);
6454
- return behavior === 'hide' ? previousRef.hide() : this.closeRegularDialogs();
6455
- }
6456
- /**
6457
- * The same choice for a full screen dialog, applied to everything that is
6458
- * on screen: what it takes over from is a whole context, a full screen
6459
- * dialog of its own included. `hide` keeps that context alive, and it comes
6460
- * back as it was once this dialog closes.
6461
- */
6462
- dismissPreviousContext(behavior) {
6463
- return behavior === 'hide' ? this.hideAll() : this.closeAll();
6335
+ isSelectInput(origin) {
6336
+ return origin?.tagName.toLowerCase() == 'input' && origin?.classList.contains('md3-select-input');
6464
6337
  }
6465
- startOpenAnimation(dialogRef) {
6466
- const overlayRef = dialogRef.overlayRef;
6467
- const panel = overlayRef.overlayElement;
6468
- const backdrop = overlayRef.backdropElement;
6469
- // The overlay is inserted already rendered. Keep an initial class for
6470
- // one frame, force style calculation, then remove it so CSS transitions
6471
- // have a real from/to state.
6472
- requestAnimationFrame(() => {
6473
- setTimeout(() => {
6474
- panel.getBoundingClientRect();
6475
- panel.classList.remove(OPENING_CLASS);
6476
- backdrop?.classList.remove(OPENING_CLASS);
6477
- }, 100);
6338
+ createOverlay(config, fallbackOrigin) {
6339
+ const origin = this.resolveOrigin(config.origin, fallbackOrigin);
6340
+ const positionStrategy = this.overlay.position()
6341
+ .flexibleConnectedTo(origin)
6342
+ .withFlexibleDimensions(false)
6343
+ .withGrowAfterOpen(true)
6344
+ .withPush(true)
6345
+ .withViewportMargin(config.viewportMargin)
6346
+ .withPositions(config.positions ?? this.getInitialConnectedPositions(config))
6347
+ .withTransformOriginOn('.md3-menu-container');
6348
+ const isSelectInput = this.isSelectInput(origin);
6349
+ const originRect = this.getOriginClientRect(origin);
6350
+ const minWidth = !isSelectInput ? undefined : originRect.width;
6351
+ const overlayConfig = new OverlayConfig({
6352
+ hasBackdrop: !isSelectInput,
6353
+ backdropClass: ['md3-menu-scrim', 'md3-menu-opening'],
6354
+ panelClass: ['md3-menu-panel', 'md3-menu-opening', ...(isSelectInput ? ['md3-select-menu'] : [])],
6355
+ positionStrategy,
6356
+ scrollStrategy: this.getScrollStrategy(config.scrollStrategy),
6357
+ minWidth: minWidth,
6478
6358
  });
6479
- dialogRef.dialogInstance?.startEnterAnimation();
6359
+ return {
6360
+ overlayRef: this.overlay.create(overlayConfig),
6361
+ positionStrategy: config.positions ? undefined : positionStrategy,
6362
+ origin,
6363
+ };
6480
6364
  }
6481
- /** Opening animation for a dialog that took the place of another one. */
6482
- startReplacingAnimation(dialogRef, previousRef) {
6483
- if (dialogRef.isClosing) {
6365
+ bindTriggerActiveState(triggerElement, overlayRef, menuRef) {
6366
+ if (!triggerElement) {
6484
6367
  return;
6485
6368
  }
6486
- const panel = dialogRef.overlayRef.overlayElement;
6487
- const backdrop = dialogRef.overlayRef.backdropElement;
6488
- this.beginScrimHandover(previousRef, dialogRef);
6489
- panel.getBoundingClientRect();
6490
- panel.classList.remove(OPENING_CLASS);
6491
- backdrop?.classList.remove(OPENING_CLASS);
6492
- this.endScrimHandover(previousRef, dialogRef);
6493
- dialogRef.dialogInstance?.startEnterAnimation();
6369
+ const removeActiveClass = () => triggerElement.classList.remove('md3-menu-active');
6370
+ triggerElement.classList.add('md3-menu-active');
6371
+ menuRef.afterClosed().pipe(take(1)).subscribe(removeActiveClass);
6372
+ overlayRef.detachments().pipe(take(1)).subscribe(removeActiveClass);
6494
6373
  }
6495
- /** Opening animation for a dialog coming back from behind a closing one. */
6496
- startRestoringAnimation(closingRef, previousRef) {
6497
- if (previousRef.isClosing) {
6374
+ resolveOrigin(origin, fallbackOrigin) {
6375
+ const resolvedOrigin = origin ?? fallbackOrigin;
6376
+ if (resolvedOrigin) {
6377
+ if (this.isMouseEvent(resolvedOrigin)) {
6378
+ if (resolvedOrigin.currentTarget instanceof HTMLElement) {
6379
+ return resolvedOrigin.currentTarget;
6380
+ }
6381
+ return {
6382
+ x: resolvedOrigin.clientX,
6383
+ y: resolvedOrigin.clientY,
6384
+ };
6385
+ }
6386
+ if (this.isElementRef(resolvedOrigin)) {
6387
+ return resolvedOrigin.nativeElement;
6388
+ }
6389
+ return resolvedOrigin;
6390
+ }
6391
+ const viewport = this.document.defaultView;
6392
+ return {
6393
+ x: (viewport?.innerWidth ?? 0) / 2,
6394
+ y: (viewport?.innerHeight ?? 0) / 2,
6395
+ };
6396
+ }
6397
+ resolveTriggerElement(origin, fallbackOrigin) {
6398
+ const resolvedOrigin = origin ?? fallbackOrigin;
6399
+ if (!resolvedOrigin) {
6400
+ return null;
6401
+ }
6402
+ if (this.isMouseEvent(resolvedOrigin)) {
6403
+ return resolvedOrigin.currentTarget instanceof HTMLElement
6404
+ ? resolvedOrigin.currentTarget
6405
+ : null;
6406
+ }
6407
+ if (this.isElementRef(resolvedOrigin)) {
6408
+ return resolvedOrigin.nativeElement;
6409
+ }
6410
+ return resolvedOrigin instanceof HTMLElement ? resolvedOrigin : null;
6411
+ }
6412
+ flipPositionIfPushBreaksAnchor(menuOverlay, config) {
6413
+ if (!menuOverlay.positionStrategy) {
6414
+ return;
6415
+ }
6416
+ menuOverlay.overlayRef.updatePosition();
6417
+ const fallbackPosition = this.getFallbackPositionAfterPush(config, this.getOriginClientRect(menuOverlay.origin), menuOverlay.overlayRef.overlayElement.getBoundingClientRect());
6418
+ if (!fallbackPosition) {
6498
6419
  return;
6499
6420
  }
6500
- this.beginScrimHandover(closingRef, previousRef);
6501
- previousRef.show();
6502
- this.endScrimHandover(closingRef, previousRef);
6421
+ menuOverlay.positionStrategy.withPositions([fallbackPosition]);
6422
+ menuOverlay.overlayRef.updatePosition();
6423
+ }
6424
+ getInitialConnectedPositions(config) {
6425
+ return [this.getPreferredConnectedPosition(config)];
6426
+ }
6427
+ getPreferredConnectedPosition(config) {
6428
+ if (config.isSubMenu) {
6429
+ return this.createSubMenuConnectedPosition(this.getSubMenuXPosition(config.xPosition), this.getSubMenuVerticalAlignment(config.yPosition), config.offsetX, config.offsetY);
6430
+ }
6431
+ return this.createConnectedPosition(config.xPosition, config.yPosition, config);
6432
+ }
6433
+ getFallbackPositionAfterPush(config, originRect, overlayRect) {
6434
+ const xPosition = this.shouldFlipXPosition(config, originRect, overlayRect)
6435
+ ? this.getFallbackXPosition(config.xPosition)
6436
+ : config.xPosition;
6437
+ const yPosition = this.shouldFlipYPosition(config, originRect, overlayRect)
6438
+ ? this.getFallbackYPosition(config.yPosition)
6439
+ : config.yPosition;
6440
+ if (xPosition === config.xPosition && yPosition === config.yPosition) {
6441
+ return null;
6442
+ }
6443
+ return this.getPreferredConnectedPosition({
6444
+ ...config,
6445
+ xPosition,
6446
+ yPosition,
6447
+ });
6448
+ }
6449
+ shouldFlipXPosition(config, originRect, overlayRect) {
6450
+ const tolerance = config.viewportMargin;
6451
+ switch (config.xPosition) {
6452
+ case 'before':
6453
+ return overlayRect.right > originRect.left + tolerance;
6454
+ case 'after':
6455
+ return overlayRect.left < originRect.right - tolerance;
6456
+ case 'start':
6457
+ return originRect.left < overlayRect.left - tolerance
6458
+ || originRect.left > overlayRect.right + tolerance;
6459
+ case 'end':
6460
+ return originRect.right < overlayRect.left - tolerance
6461
+ || originRect.right > overlayRect.right + tolerance;
6462
+ case 'center':
6463
+ default:
6464
+ return false;
6465
+ }
6466
+ }
6467
+ shouldFlipYPosition(config, originRect, overlayRect) {
6468
+ const tolerance = config.viewportMargin;
6469
+ if (config.isSubMenu) {
6470
+ const anchorY = config.yPosition === 'above' ? originRect.bottom : originRect.top;
6471
+ return anchorY < overlayRect.top - tolerance
6472
+ || anchorY > overlayRect.bottom + tolerance;
6473
+ }
6474
+ if (config.overlapTrigger) {
6475
+ const anchorY = config.yPosition === 'above' ? originRect.bottom : originRect.top;
6476
+ return anchorY < overlayRect.top - tolerance
6477
+ || anchorY > overlayRect.bottom + tolerance;
6478
+ }
6479
+ switch (config.yPosition) {
6480
+ case 'above':
6481
+ return overlayRect.bottom > originRect.top + tolerance;
6482
+ case 'below':
6483
+ return overlayRect.top < originRect.bottom - tolerance;
6484
+ case 'center':
6485
+ default:
6486
+ return false;
6487
+ }
6488
+ }
6489
+ createConnectedPosition(xPosition, yPosition, config) {
6490
+ const horizontal = this.getHorizontalPosition(xPosition);
6491
+ const vertical = this.getVerticalPosition(yPosition, config.overlapTrigger);
6492
+ return {
6493
+ ...horizontal,
6494
+ ...vertical,
6495
+ offsetX: config.offsetX,
6496
+ offsetY: this.getOffsetY(yPosition, config),
6497
+ panelClass: [
6498
+ 'md3-menu-position-' + xPosition,
6499
+ 'md3-menu-position-' + yPosition,
6500
+ ],
6501
+ };
6502
+ }
6503
+ createSubMenuConnectedPosition(xPosition, yAlignment, offsetX, offsetY) {
6504
+ const horizontal = this.getHorizontalPosition(xPosition);
6505
+ const yPosition = yAlignment === 'top' ? 'below' : 'above';
6506
+ return {
6507
+ ...horizontal,
6508
+ originY: yAlignment,
6509
+ overlayY: yAlignment,
6510
+ offsetX: this.getSubMenuOffsetX(xPosition, offsetX),
6511
+ offsetY: this.getSubMenuOffsetY(yAlignment, offsetY),
6512
+ panelClass: [
6513
+ 'md3-menu-position-' + xPosition,
6514
+ 'md3-menu-position-' + yPosition,
6515
+ 'md3-menu-position-submenu',
6516
+ ],
6517
+ };
6518
+ }
6519
+ getHorizontalPosition(position) {
6520
+ switch (position) {
6521
+ case 'end':
6522
+ return {
6523
+ originX: 'end',
6524
+ overlayX: 'end',
6525
+ };
6526
+ case 'before':
6527
+ return {
6528
+ originX: 'start',
6529
+ overlayX: 'end',
6530
+ };
6531
+ case 'after':
6532
+ return {
6533
+ originX: 'end',
6534
+ overlayX: 'start',
6535
+ };
6536
+ case 'center':
6537
+ return {
6538
+ originX: 'center',
6539
+ overlayX: 'center',
6540
+ };
6541
+ case 'start':
6542
+ default:
6543
+ return {
6544
+ originX: 'start',
6545
+ overlayX: 'start',
6546
+ };
6547
+ }
6503
6548
  }
6504
- /**
6505
- * Moves both scrims to their new value in a single frame, without a
6506
- * transition on either side, so the dim behind the dialogs never changes.
6507
- */
6508
- beginScrimHandover(fromRef, toRef) {
6509
- const from = fromRef.overlayRef.backdropElement;
6510
- const to = toRef.overlayRef.backdropElement;
6511
- // Nothing to hand the scrim over to, e.g. a full screen dialog: the
6512
- // outgoing scrim fades out on its own instead.
6513
- if (!to) {
6514
- return;
6549
+ getVerticalPosition(position, overlapTrigger) {
6550
+ switch (position) {
6551
+ case 'above':
6552
+ return {
6553
+ originY: overlapTrigger ? 'bottom' : 'top',
6554
+ overlayY: 'bottom',
6555
+ };
6556
+ case 'center':
6557
+ return {
6558
+ originY: 'center',
6559
+ overlayY: 'center',
6560
+ };
6561
+ case 'below':
6562
+ default:
6563
+ return {
6564
+ originY: overlapTrigger ? 'top' : 'bottom',
6565
+ overlayY: 'top',
6566
+ };
6515
6567
  }
6516
- // Nothing to hand over either: the dialog leaving carries no scrim, so
6517
- // the one coming in fades its own in rather than switching it on in a
6518
- // single frame. This is a full screen dialog closing over a dialog that
6519
- // was hidden underneath it.
6520
- if (!from) {
6521
- return;
6568
+ }
6569
+ getFallbackXPosition(position) {
6570
+ switch (position) {
6571
+ case 'start':
6572
+ return 'end';
6573
+ case 'end':
6574
+ return 'start';
6575
+ case 'before':
6576
+ return 'after';
6577
+ case 'after':
6578
+ return 'before';
6579
+ case 'center':
6580
+ default:
6581
+ return 'center';
6522
6582
  }
6523
- from?.classList.add(SCRIM_INSTANT_CLASS);
6524
- from?.classList.remove(SCRIM_KEPT_CLASS);
6525
- to?.classList.add(SCRIM_INSTANT_CLASS);
6526
6583
  }
6527
- /** Gives the scrims their transitions back once the handover is painted. */
6528
- endScrimHandover(fromRef, toRef) {
6529
- const from = fromRef.overlayRef.backdropElement;
6530
- const to = toRef.overlayRef.backdropElement;
6531
- requestAnimationFrame(() => {
6532
- from?.classList.remove(SCRIM_INSTANT_CLASS);
6533
- to?.classList.remove(SCRIM_INSTANT_CLASS);
6534
- });
6584
+ getSubMenuXPosition(position) {
6585
+ return position === 'before' ? 'before' : 'after';
6535
6586
  }
6536
- bindDataToInputs(componentRef, config) {
6537
- if (!config.bindDataToInputs || !this.canBindDataToInputs(config.data)) {
6538
- return;
6587
+ getFallbackYPosition(position) {
6588
+ switch (position) {
6589
+ case 'above':
6590
+ return 'below';
6591
+ case 'below':
6592
+ return 'above';
6593
+ case 'center':
6594
+ default:
6595
+ return 'center';
6539
6596
  }
6540
- // setInput runs Angular's normal input pipeline, so input setters,
6541
- // transforms, signal inputs, and change detection are handled for us.
6542
- Object.entries(config.data).forEach(([inputName, inputValue]) => {
6543
- componentRef.setInput(inputName, inputValue);
6544
- });
6545
6597
  }
6546
- canBindDataToInputs(data) {
6547
- return typeof data === 'object' && data !== null && !Array.isArray(data);
6598
+ getSubMenuVerticalAlignment(position) {
6599
+ return position === 'above' ? 'bottom' : 'top';
6548
6600
  }
6549
- /** Last dialog of the stack that is not closing yet. */
6550
- topRef() {
6551
- for (let index = this.refs.length - 1; index >= 0; index--) {
6552
- if (!this.refs[index].isClosing) {
6553
- return this.refs[index];
6554
- }
6601
+ getOriginClientRect(origin) {
6602
+ if ('getBoundingClientRect' in origin) {
6603
+ return origin.getBoundingClientRect();
6555
6604
  }
6556
- return undefined;
6605
+ return {
6606
+ x: origin.x,
6607
+ y: origin.y,
6608
+ top: origin.y,
6609
+ right: origin.x,
6610
+ bottom: origin.y,
6611
+ left: origin.x,
6612
+ width: 0,
6613
+ height: 0,
6614
+ };
6557
6615
  }
6558
- /**
6559
- * Same, without the full screen dialog: it hosts the dialogs opened on top
6560
- * of it, so it is never the one that gets hidden or closed to make room.
6561
- */
6562
- topRegularRef() {
6563
- const ref = this.topRef();
6564
- return ref?.isFullScreen ? undefined : ref;
6616
+ getViewportMargin(configuredMargin) {
6617
+ const minimumMargin = this.getHalfEmInPixels();
6618
+ return Math.max(configuredMargin ?? minimumMargin, minimumMargin);
6565
6619
  }
6566
- restorePreviousDialog(ref) {
6567
- const index = this.refs.indexOf(ref);
6568
- if (index < 1) {
6569
- return;
6570
- }
6571
- for (let previousIndex = index - 1; previousIndex >= 0; previousIndex--) {
6572
- const previousRef = this.refs[previousIndex];
6573
- if (previousRef.isClosing) {
6574
- continue;
6575
- }
6576
- // The closing dialog gets the same head start it was given when it
6577
- // took the screen, and keeps the scrim until then. Nothing to keep
6578
- // when the dialog underneath has no scrim of its own.
6579
- if (previousRef.overlayRef.backdropElement) {
6580
- ref.overlayRef.backdropElement?.classList.add(SCRIM_KEPT_CLASS);
6581
- }
6582
- setTimeout(() => {
6583
- this.showHostFullScreenDialog(previousRef);
6584
- this.startRestoringAnimation(ref, previousRef);
6585
- }, DIALOG_HANDOVER_DELAY_MS);
6586
- return;
6587
- }
6620
+ getHalfEmInPixels() {
6621
+ const viewport = this.document.defaultView;
6622
+ const fontSize = viewport?.getComputedStyle(this.document.documentElement).fontSize;
6623
+ const pixels = fontSize ? Number.parseFloat(fontSize) * 0.5 : 8;
6624
+ return Number.isFinite(pixels) ? pixels : 8;
6588
6625
  }
6589
- /**
6590
- * Brings back the full screen dialog a restored dialog sits in. The two are
6591
- * hidden together when a full screen dialog takes over with
6592
- * `previousDialog: 'hide'`, so the context has to be on screen again before
6593
- * the dialog that sits on top of it, exactly as showAll() puts them back.
6594
- */
6595
- showHostFullScreenDialog(ref) {
6596
- if (ref.isFullScreen) {
6597
- return;
6598
- }
6599
- const hostRef = this.fullScreenDialog;
6600
- if (hostRef?.isHidden && this.refs.indexOf(hostRef) < this.refs.indexOf(ref)) {
6601
- hostRef.show();
6626
+ getOffsetY(position, config) {
6627
+ if (config.overlapTrigger || position === 'center') {
6628
+ return 0;
6602
6629
  }
6630
+ return position === 'above'
6631
+ ? config.offsetY * -1
6632
+ : config.offsetY;
6603
6633
  }
6604
- removeRef(ref) {
6605
- const index = this.refs.indexOf(ref);
6606
- if (index === -1) {
6607
- return;
6608
- }
6609
- this.refs.splice(index, 1);
6610
- if (this.refs.length === 0) {
6611
- this.rootTrigger = null;
6612
- }
6613
- this.syncPageState();
6634
+ getSubMenuOffsetX(position, offsetX) {
6635
+ return position === 'before' ? offsetX * -1 : offsetX;
6614
6636
  }
6615
- /**
6616
- * State that belongs to the dialogs as a whole rather than to one of them:
6617
- * page scrolling, the page being hidden from assistive technology, and
6618
- * where focus sits. Applied in a task of its own, so a dialog handing the
6619
- * screen over to another one does not give the page back and take it again
6620
- * within the same frame.
6621
- */
6622
- syncPageState() {
6623
- if (this.pageStateQueued) {
6624
- return;
6625
- }
6626
- this.pageStateQueued = true;
6627
- setTimeout(() => {
6628
- this.pageStateQueued = false;
6629
- this.applyPageState();
6630
- });
6637
+ getSubMenuOffsetY(alignment, offsetY) {
6638
+ return alignment === 'bottom' ? offsetY * -1 : offsetY;
6631
6639
  }
6632
- applyPageState() {
6633
- const hasVisibleDialog = this.refs.some((ref) => !ref.isHidden);
6634
- if (hasVisibleDialog) {
6635
- this.scrollBlock.enable();
6636
- }
6637
- else {
6638
- this.scrollBlock.disable();
6639
- }
6640
- if (this.refs.length === 0) {
6641
- // Nothing is open anymore: the CDK gives the page back to assistive
6642
- // technology on its own, so there is nothing left to restore here.
6643
- this.pageAriaHidden.clear();
6644
- return;
6645
- }
6646
- if (hasVisibleDialog) {
6647
- this.hidePageFromAssistiveTechnology();
6648
- return;
6640
+ getScrollStrategy(scrollStrategy) {
6641
+ switch (scrollStrategy) {
6642
+ case 'block':
6643
+ return this.overlay.scrollStrategies.block();
6644
+ case 'close':
6645
+ return this.overlay.scrollStrategies.close();
6646
+ case 'noop':
6647
+ return this.overlay.scrollStrategies.noop();
6648
+ case 'reposition':
6649
+ default:
6650
+ return this.overlay.scrollStrategies.reposition();
6649
6651
  }
6650
- this.exposePageToAssistiveTechnology();
6651
- this.releaseFocus();
6652
6652
  }
6653
- /**
6654
- * Gives the page back to assistive technology while every dialog is hidden.
6655
- * The CDK hides it for as long as a dialog is open, which would otherwise
6656
- * leave nothing to read at all once the dialogs are out of sight.
6657
- */
6658
- exposePageToAssistiveTechnology() {
6659
- if (this.pageAriaHidden.size > 0) {
6660
- return;
6661
- }
6662
- const container = this.overlayContainer.getContainerElement();
6663
- Array.from(container.parentElement?.children ?? []).forEach((sibling) => {
6664
- const value = sibling.getAttribute('aria-hidden');
6665
- if (sibling === container || value === null) {
6666
- return;
6667
- }
6668
- this.pageAriaHidden.set(sibling, value);
6669
- sibling.removeAttribute('aria-hidden');
6653
+ isMouseEvent(origin) {
6654
+ return typeof MouseEvent !== 'undefined' && origin instanceof MouseEvent;
6655
+ }
6656
+ isElementRef(origin) {
6657
+ return typeof origin === 'object'
6658
+ && origin !== null
6659
+ && 'nativeElement' in origin
6660
+ && origin.nativeElement instanceof HTMLElement;
6661
+ }
6662
+ startOpenAnimation(overlayRef) {
6663
+ const panel = overlayRef.overlayElement;
6664
+ const backdrop = overlayRef.backdropElement;
6665
+ // The overlay is inserted already rendered. Keep an initial class for
6666
+ // one frame, force style calculation, then remove it so CSS transitions
6667
+ // have a real from/to state.
6668
+ requestAnimationFrame(() => {
6669
+ setTimeout(() => {
6670
+ panel.getBoundingClientRect();
6671
+ panel.classList.remove('md3-menu-opening');
6672
+ backdrop?.classList.remove('md3-menu-opening');
6673
+ }, 100);
6674
+ });
6675
+ }
6676
+ createInjector(component, config, menuRef) {
6677
+ return Injector.create({
6678
+ parent: config.injector,
6679
+ providers: [
6680
+ // These tokens make the menu controllable from the dynamic
6681
+ // component without coupling that component to the service.
6682
+ { provide: MenuRef, useValue: menuRef },
6683
+ { provide: MENU_DATA, useValue: config.data },
6684
+ { provide: MENU_CONFIG, useValue: config },
6685
+ { provide: MENU_COMPONENT, useValue: component },
6686
+ ],
6670
6687
  });
6671
6688
  }
6672
- /** Hides the page again as soon as a dialog is back on screen. */
6673
- hidePageFromAssistiveTechnology() {
6674
- this.pageAriaHidden.forEach((value, element) => {
6675
- element.setAttribute('aria-hidden', value);
6689
+ bindDataToInputs(componentRef, config) {
6690
+ if (!config.bindDataToInputs || !this.canBindDataToInputs(config.data)) {
6691
+ return;
6692
+ }
6693
+ // setInput runs Angular's normal input pipeline, so input setters,
6694
+ // transforms, signal inputs, and change detection are handled for us.
6695
+ Object.entries(config.data).forEach(([inputName, inputValue]) => {
6696
+ componentRef.setInput(inputName, inputValue);
6676
6697
  });
6677
- this.pageAriaHidden.clear();
6678
6698
  }
6679
- /**
6680
- * Focus follows the dialogs off the screen: it goes back to whatever opened
6681
- * the stack, so the page stays usable with the keyboard while the dialogs
6682
- * wait behind it. Focus that already moved somewhere else is left alone.
6683
- */
6684
- releaseFocus() {
6685
- const activeElement = this.document.activeElement;
6686
- if (this.rootTrigger && (!activeElement || activeElement === this.document.body)) {
6687
- this.rootTrigger.focus();
6699
+ connectCloseEvents(overlayRef, menuRef, origin) {
6700
+ overlayRef.backdropClick().pipe(take(1)).subscribe(() => menuRef.close());
6701
+ overlayRef.keydownEvents().pipe(filter((event) => event.key === 'Escape'), take(1)).subscribe(() => menuRef.close());
6702
+ if (this.isSelectInput(origin)) {
6703
+ const originRect = this.getOriginClientRect(origin);
6704
+ overlayRef.outsidePointerEvents().pipe(filter((event) => {
6705
+ const clickedInsideOrigin = event.clientX >= originRect.left &&
6706
+ event.clientX <= originRect.right &&
6707
+ event.clientY >= originRect.top &&
6708
+ event.clientY <= originRect.bottom;
6709
+ return !clickedInsideOrigin;
6710
+ })).subscribe(() => menuRef.close());
6688
6711
  }
6689
6712
  }
6690
6713
  getFocusedElement() {
6691
6714
  const activeElement = this.document.activeElement;
6692
6715
  return activeElement instanceof HTMLElement ? activeElement : null;
6693
6716
  }
6694
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6695
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, providedIn: 'root' });
6717
+ canBindDataToInputs(data) {
6718
+ return typeof data === 'object' && data !== null && !Array.isArray(data);
6719
+ }
6720
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6721
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, providedIn: 'root' });
6696
6722
  }
6697
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, decorators: [{
6723
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, decorators: [{
6698
6724
  type: Injectable,
6699
6725
  args: [{
6700
6726
  providedIn: 'root',
6701
6727
  }]
6702
6728
  }] });
6703
6729
 
6704
- class DialogHeader {
6705
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
6706
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogHeader, isStandalone: true, selector: "md3-dialog-header", ngImport: i0, template: "<ng-content select=\"[md3-icon-element]\"></ng-content>\n<div class=\"md3-dialog-title\">\n <md3-type-headline size=\"small\">\n <ng-content></ng-content>\n </md3-type-headline>\n</div>", styles: [":host{display:block;margin:1.5em 1.5em 1em;text-align:center}:host .md3-dialog-title{text-align:start;color:rgb(var(--md-scheme-on-surface))}:host ::ng-deep [md3-icon-element]{color:rgb(var(--md-scheme-secondary))}:host ::ng-deep [md3-icon-element]+.md3-dialog-title{margin-top:1em;text-align:center}\n"], dependencies: [{ kind: "directive", type: TypeHeadline, selector: "md3-type-headline, [md3-type-headline]", inputs: ["size", "color", "emphasized"] }] });
6707
- }
6708
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogHeader, decorators: [{
6709
- type: Component,
6710
- args: [{ selector: 'md3-dialog-header', imports: [
6711
- TypeHeadline
6712
- ], template: "<ng-content select=\"[md3-icon-element]\"></ng-content>\n<div class=\"md3-dialog-title\">\n <md3-type-headline size=\"small\">\n <ng-content></ng-content>\n </md3-type-headline>\n</div>", styles: [":host{display:block;margin:1.5em 1.5em 1em;text-align:center}:host .md3-dialog-title{text-align:start;color:rgb(var(--md-scheme-on-surface))}:host ::ng-deep [md3-icon-element]{color:rgb(var(--md-scheme-secondary))}:host ::ng-deep [md3-icon-element]+.md3-dialog-title{margin-top:1em;text-align:center}\n"] }]
6713
- }] });
6714
-
6715
- class DialogBody {
6716
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogBody, deps: [], target: i0.ɵɵFactoryTarget.Component });
6717
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogBody, isStandalone: true, selector: "md3-dialog-body", host: { classAttribute: "md3-scrollable" }, ngImport: i0, template: "<ng-content></ng-content>", styles: [":host{display:block;margin:1em 1.5em 1.5em;color:rgb(var(--md-scheme-on-surface-variant))}:host .md3-text-body.md3-text-medium{letter-spacing:.017857em}\n"] });
6718
- }
6719
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogBody, decorators: [{
6720
- type: Component,
6721
- args: [{ selector: 'md3-dialog-body', imports: [], host: {
6722
- 'class': 'md3-scrollable',
6723
- }, template: "<ng-content></ng-content>", styles: [":host{display:block;margin:1em 1.5em 1.5em;color:rgb(var(--md-scheme-on-surface-variant))}:host .md3-text-body.md3-text-medium{letter-spacing:.017857em}\n"] }]
6724
- }] });
6725
-
6726
- class DialogActions {
6727
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
6728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogActions, isStandalone: true, selector: "md3-dialog-actions", ngImport: i0, template: "<div class=\"md3-actions\">\n <ng-content></ng-content>\n</div>", styles: [":host{display:block;margin:1.5em}:host .md3-actions{display:flex;gap:1em;flex-direction:row-reverse}\n"] });
6729
- }
6730
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogActions, decorators: [{
6731
- type: Component,
6732
- args: [{ selector: 'md3-dialog-actions', imports: [], template: "<div class=\"md3-actions\">\n <ng-content></ng-content>\n</div>", styles: [":host{display:block;margin:1.5em}:host .md3-actions{display:flex;gap:1em;flex-direction:row-reverse}\n"] }]
6733
- }] });
6734
-
6735
- const MENU_DATA = new InjectionToken('MD3_MENU_DATA');
6736
- const MENU_CONFIG = new InjectionToken('MD3_MENU_CONFIG');
6737
- const MENU_COMPONENT = new InjectionToken('MD3_MENU_COMPONENT');
6738
- const MENU_EXIT_ANIMATION_FALLBACK_MS = 300;
6739
- class MenuRef {
6740
- overlayRef;
6741
- previouslyFocusedElement;
6742
- closed = new Subject();
6743
- isClosed = false;
6744
- menuInstance;
6730
+ class SelectField {
6731
+ menuService;
6732
+ viewContainerRef;
6745
6733
  /**
6746
- * Filled by MenuService after the user component is attached. Keeping the
6747
- * instance here lets callers imperatively update inputs when that is useful.
6734
+ * Form directive placed on the host element: [formControl], formControlName or [(ngModel)].
6735
+ * The accessor is registered from the constructor instead of through an NG_VALUE_ACCESSOR
6736
+ * provider, which keeps the directive injectable here and gives access to the control
6737
+ * itself for the error state forwarded to md3-text-field.
6748
6738
  */
6749
- componentInstance;
6750
- constructor(overlayRef, previouslyFocusedElement) {
6751
- this.overlayRef = overlayRef;
6752
- this.previouslyFocusedElement = previouslyFocusedElement;
6753
- }
6754
- close(result) {
6755
- if (this.isClosed) {
6756
- return;
6739
+ ngControl = inject(NgControl, { self: true, optional: true });
6740
+ options = input.required(/* @ts-ignore */
6741
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
6742
+ multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6743
+ label = input(null, { ...(ngDevMode ? { debugName: "label" } : /* istanbul ignore next */ {}), alias: 'label' });
6744
+ /**
6745
+ * Formats the text shown in the field. The default joins the labels of the selected
6746
+ * options with a comma, so the field shows as many labels as its width allows.
6747
+ * The formatter is not called for an empty selection: the field stays empty, which keeps
6748
+ * the floating label in its place.
6749
+ */
6750
+ displayWith = input(null, { ...(ngDevMode ? { debugName: "displayWith" } : /* istanbul ignore next */ {}), alias: 'display-with' });
6751
+ /**
6752
+ * Disables the field outside of a form. With reactive forms prefer control.disable().
6753
+ */
6754
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6755
+ menuColors = input('standard', { ...(ngDevMode ? { debugName: "menuColors" } : /* istanbul ignore next */ {}), alias: 'menu-colors' });
6756
+ fieldType = input('filled', { ...(ngDevMode ? { debugName: "fieldType" } : /* istanbul ignore next */ {}), alias: 'field-type' });
6757
+ /**
6758
+ * Control passed explicitly, mirroring md3-text-field. Takes precedence over a form
6759
+ * directive on the host element.
6760
+ */
6761
+ control = input(undefined, { ...(ngDevMode ? { debugName: "control" } : /* istanbul ignore next */ {}), alias: 'control' });
6762
+ iconElements = contentChildren(IconElement, { ...(ngDevMode ? { debugName: "iconElements" } : /* istanbul ignore next */ {}), descendants: true });
6763
+ hasLeadingIcon = computed(() => this.iconElements().some(i => i.iconType() === 'leading') ?? false, /* @ts-ignore */
6764
+ ...(ngDevMode ? [{ debugName: "hasLeadingIcon" }] : /* istanbul ignore next */ []));
6765
+ hasArrowIcon = computed(() => this.iconElements().some(i => i.iconType() === 'arrow') ?? false, /* @ts-ignore */
6766
+ ...(ngDevMode ? [{ debugName: "hasArrowIcon" }] : /* istanbul ignore next */ []));
6767
+ isMenuOpen = signal(false, /* @ts-ignore */
6768
+ ...(ngDevMode ? [{ debugName: "isMenuOpen" }] : /* istanbul ignore next */ []));
6769
+ menuRef = null;
6770
+ inputElement = viewChild(InputElement, { ...(ngDevMode ? { debugName: "inputElement" } : /* istanbul ignore next */ {}), read: ElementRef });
6771
+ /** Control resolved from the host form directive, captured when the accessor is wired up. */
6772
+ hostControl = signal(undefined, /* @ts-ignore */
6773
+ ...(ngDevMode ? [{ debugName: "hostControl" }] : /* istanbul ignore next */ []));
6774
+ /** Disabled state pushed by the control, either through setDisabledState or control.disabled. */
6775
+ controlDisabled = signal(false, /* @ts-ignore */
6776
+ ...(ngDevMode ? [{ debugName: "controlDisabled" }] : /* istanbul ignore next */ []));
6777
+ /**
6778
+ * Set as soon as a control writes a value. From then on the control owns the selection and
6779
+ * SelectOption.selected no longer seeds it.
6780
+ */
6781
+ controlOwnsValue = false;
6782
+ onChange = () => { };
6783
+ onTouched = () => { };
6784
+ /** Selection is kept by value so it survives options arriving or being replaced later. */
6785
+ selectedValues = signal([], /* @ts-ignore */
6786
+ ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
6787
+ formControl = computed(() => this.control() ?? this.hostControl(), /* @ts-ignore */
6788
+ ...(ngDevMode ? [{ debugName: "formControl" }] : /* istanbul ignore next */ []));
6789
+ isDisabled = computed(() => this.disabled() || this.controlDisabled(), /* @ts-ignore */
6790
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
6791
+ selectedOptions = computed(() => {
6792
+ const values = this.selectedValues();
6793
+ return this.options().filter((option) => values.includes(option.value));
6794
+ }, /* @ts-ignore */
6795
+ ...(ngDevMode ? [{ debugName: "selectedOptions" }] : /* istanbul ignore next */ []));
6796
+ selectedText = computed(() => {
6797
+ const selected = this.selectedOptions();
6798
+ if (selected.length == 0) {
6799
+ return null;
6757
6800
  }
6758
- this.isClosed = true;
6759
- this.startCloseAnimation().then(() => {
6760
- // Disposing the overlay removes the wrapper, the backdrop, and the
6761
- // dynamically attached content component in one operation.
6762
- this.overlayRef.dispose();
6763
- this.previouslyFocusedElement?.focus();
6764
- this.closed.next(result);
6765
- this.closed.complete();
6766
- });
6767
- }
6768
- startCloseAnimation() {
6769
- let panel = this.overlayRef.overlayElement;
6770
- let animatedElement = panel.querySelector('.md3-menu-container') ?? panel;
6771
- panel.classList.add('md3-menu-closing');
6772
- this.menuInstance?.showMenu(false);
6773
- return new Promise((resolve) => {
6774
- let isResolved = false;
6775
- let timeoutId = setTimeout(done, MENU_EXIT_ANIMATION_FALLBACK_MS);
6776
- function done() {
6777
- if (isResolved) {
6801
+ const format = this.displayWith();
6802
+ if (format) {
6803
+ return format(selected);
6804
+ }
6805
+ return selected.map((option) => option.label).join(', ');
6806
+ }, /* @ts-ignore */
6807
+ ...(ngDevMode ? [{ debugName: "selectedText" }] : /* istanbul ignore next */ []));
6808
+ constructor(menuService, viewContainerRef) {
6809
+ this.menuService = menuService;
6810
+ this.viewContainerRef = viewContainerRef;
6811
+ if (this.ngControl) {
6812
+ this.ngControl.valueAccessor = this;
6813
+ }
6814
+ // Seeds the selection from SelectOption.selected while no control owns the value.
6815
+ effect(() => {
6816
+ const options = this.options();
6817
+ untracked(() => {
6818
+ if (this.controlOwnsValue) {
6778
6819
  return;
6779
6820
  }
6780
- isResolved = true;
6781
- clearTimeout(timeoutId);
6782
- animatedElement.removeEventListener('transitionend', onTransitionEnd);
6783
- resolve();
6784
- }
6785
- function onTransitionEnd(event) {
6786
- if (event.target === animatedElement) {
6787
- done();
6821
+ let selected = options.filter((option) => option.selected);
6822
+ if (!this.multiple() && selected.length > 1) {
6823
+ selected = [selected[0]];
6788
6824
  }
6825
+ this.setSelectedValues(selected.map((option) => option.value));
6826
+ });
6827
+ });
6828
+ // Mirrors the selection back onto SelectOption.selected so the menu renders it.
6829
+ effect(() => {
6830
+ const values = this.selectedValues();
6831
+ for (const option of this.options()) {
6832
+ option.selected = values.includes(option.value);
6789
6833
  }
6790
- animatedElement.addEventListener('transitionend', onTransitionEnd);
6834
+ });
6835
+ // [control] is bound manually; [formControl]/formControlName go through the accessor API.
6836
+ effect((onCleanup) => {
6837
+ const control = this.control();
6838
+ if (!control) {
6839
+ return;
6840
+ }
6841
+ this.syncFromControl(control);
6842
+ const controlEvents = control.events.subscribe(() => this.syncFromControl(control));
6843
+ onCleanup(() => controlEvents.unsubscribe());
6844
+ });
6845
+ effect(() => {
6846
+ const isOpen = this.isMenuOpen();
6847
+ untracked(() => {
6848
+ if (isOpen) {
6849
+ this.openSelectOptions();
6850
+ return;
6851
+ }
6852
+ this.menuRef?.close();
6853
+ this.menuRef = null;
6854
+ });
6791
6855
  });
6792
6856
  }
6793
- afterClosed() {
6794
- return this.closed.asObservable();
6857
+ // ControlValueAccessor
6858
+ writeValue(value) {
6859
+ this.captureHostControl();
6860
+ this.controlOwnsValue = true;
6861
+ this.setSelectedValues(this.normalizeValues(value));
6862
+ }
6863
+ registerOnChange(fn) {
6864
+ this.captureHostControl();
6865
+ this.onChange = fn;
6866
+ }
6867
+ registerOnTouched(fn) {
6868
+ this.onTouched = fn;
6869
+ }
6870
+ setDisabledState(isDisabled) {
6871
+ this.controlDisabled.set(isDisabled);
6872
+ }
6873
+ // Menu
6874
+ openMenu() {
6875
+ if (this.isDisabled()) {
6876
+ return;
6877
+ }
6878
+ this.isMenuOpen.set(true);
6879
+ }
6880
+ closeMenu() {
6881
+ this.isMenuOpen.set(false);
6882
+ }
6883
+ toggleMenu() {
6884
+ if (this.isDisabled()) {
6885
+ return;
6886
+ }
6887
+ this.isMenuOpen.update(current => !current);
6888
+ }
6889
+ openSelectOptions() {
6890
+ this.menuRef = this.menuService.open(SelectOptions, {
6891
+ data: {
6892
+ options: this.options(),
6893
+ multiple: this.multiple(),
6894
+ },
6895
+ bindDataToInputs: true,
6896
+ menuColors: this.menuColors(),
6897
+ origin: this.inputElement(),
6898
+ xPosition: 'start',
6899
+ yPosition: 'below',
6900
+ overlapTrigger: false,
6901
+ // scrollStrategy: 'close',
6902
+ viewContainerRef: this.viewContainerRef,
6903
+ });
6904
+ this.menuRef.componentInstance?.selectionChange.subscribe((values) => this.selectValues(values));
6905
+ this.menuRef.afterClosed().subscribe(() => {
6906
+ this.isMenuOpen.set(false);
6907
+ this.markAsTouched();
6908
+ });
6909
+ }
6910
+ // Selection
6911
+ selectValues(values) {
6912
+ this.setSelectedValues(this.normalizeValues(values));
6913
+ this.commitValue();
6914
+ }
6915
+ setSelectedValues(values) {
6916
+ const current = untracked(this.selectedValues);
6917
+ if (current.length === values.length && current.every((value, index) => value === values[index])) {
6918
+ return;
6919
+ }
6920
+ this.selectedValues.set(values);
6921
+ }
6922
+ commitValue() {
6923
+ const value = this.currentValue();
6924
+ // No-op unless a form directive registered an accessor callback.
6925
+ this.onChange(value);
6926
+ const control = this.control();
6927
+ if (control && !this.valuesAreEqual(control.value, value)) {
6928
+ control.markAsDirty();
6929
+ control.setValue(value);
6930
+ }
6931
+ }
6932
+ currentValue() {
6933
+ const values = untracked(this.selectedValues);
6934
+ if (this.multiple()) {
6935
+ return [...values];
6936
+ }
6937
+ return values.length > 0 ? values[0] : null;
6938
+ }
6939
+ markAsTouched() {
6940
+ this.onTouched();
6941
+ const control = this.control();
6942
+ if (control && !control.touched) {
6943
+ control.markAsTouched();
6944
+ }
6945
+ }
6946
+ syncFromControl(control) {
6947
+ this.controlOwnsValue = true;
6948
+ this.setSelectedValues(this.normalizeValues(control.value));
6949
+ this.controlDisabled.set(control.disabled);
6950
+ }
6951
+ captureHostControl() {
6952
+ const control = this.ngControl?.control ?? undefined;
6953
+ if (control && untracked(this.hostControl) !== control) {
6954
+ this.hostControl.set(control);
6955
+ }
6956
+ }
6957
+ /**
6958
+ * Accepts whatever a control holds and reduces it to the option values this field can show:
6959
+ * a single value for single selection, a de-duplicated list for multiple selection.
6960
+ */
6961
+ normalizeValues(value) {
6962
+ const values = (Array.isArray(value) ? value : [value])
6963
+ .filter((item) => typeof item === 'string' || typeof item === 'number');
6964
+ const unique = [...new Set(values)];
6965
+ return this.multiple() ? unique : unique.slice(0, 1);
6966
+ }
6967
+ valuesAreEqual(current, next) {
6968
+ if (Array.isArray(current) && Array.isArray(next)) {
6969
+ return current.length === next.length && current.every((value, index) => value === next[index]);
6970
+ }
6971
+ return current === next;
6795
6972
  }
6973
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectField, deps: [{ token: MenuService }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
6974
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SelectField, isStandalone: true, selector: "md3-select-field", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "display-with", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, menuColors: { classPropertyName: "menuColors", publicName: "menu-colors", isSignal: true, isRequired: false, transformFunction: null }, fieldType: { classPropertyName: "fieldType", publicName: "field-type", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "iconElements", predicate: IconElement, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "inputElement", first: true, predicate: InputElement, descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<md3-text-field [label]=\"label()\" [field-type]=\"fieldType()\" [control]=\"formControl()\">\n <!-- <md3-icon md3-icon-element=\"leading\">search</md3-icon> -->\n @if (hasLeadingIcon()) {\n <div md3-icon-element=\"leading\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n </div>\n }\n\n <input md3-input-element type=\"text\" [readonly]=\"true\" [disabled]=\"isDisabled()\" (click)=\"openMenu()\" class=\"md3-select-input\" [class.md3-menu-active]=\"isMenuOpen()\" [value]=\"selectedText()\">\n\n <button md3-icon-button button-type=\"standard\" [disabled]=\"isDisabled()\" (click)=\"toggleMenu()\" class=\"md3-select-arrow\">\n @if (hasArrowIcon()) {\n <ng-content select=\"[md3-icon-element=arrow]\"></ng-content>\n } @else {\n <md3-icon md3-icon-element>arrow_drop_down</md3-icon>\n }\n </button>\n\n <ng-content select=\"[md3-supporting-text]\" ngProjectAs=\"[md3-supporting-text]\"></ng-content>\n</md3-text-field>\n", styles: [".md3-select-input{text-overflow:ellipsis}.md3-select-input:read-only{cursor:default;-webkit-user-select:none;user-select:none}.md3-select-input~.md3-select-arrow{transition:transform var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}.md3-select-input.md3-menu-active:dir(ltr)~.md3-select-arrow{transform:rotate(180deg)}.md3-select-input.md3-menu-active:dir(rtl)~.md3-select-arrow{transform:rotate(-180deg)}\n"], dependencies: [{ kind: "component", type: TextField, selector: "md3-text-field", inputs: ["label", "field-type", "input-counter", "control"] }, { kind: "directive", type: IconElement, selector: "[md3-icon-element]", inputs: ["md3-icon-element"] }, { kind: "component", type: IconButton, selector: "button[md3-icon-button], a[md3-icon-button]", inputs: ["button-size", "button-type", "button-width", "button-squared", "selected"], outputs: ["selectedChange"] }, { kind: "directive", type: InputElement, selector: "[md3-input-element]" }, { kind: "component", type: MaterialIcon, selector: "md3-icon", inputs: ["icon-version", "filled", "icon-style", "icon-size", "bi-directional"] }] });
6796
6975
  }
6976
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectField, decorators: [{
6977
+ type: Component,
6978
+ args: [{ selector: 'md3-select-field', imports: [
6979
+ TextField,
6980
+ IconElement,
6981
+ IconButton,
6982
+ InputElement,
6983
+ MaterialIcon,
6984
+ ], template: "<md3-text-field [label]=\"label()\" [field-type]=\"fieldType()\" [control]=\"formControl()\">\n <!-- <md3-icon md3-icon-element=\"leading\">search</md3-icon> -->\n @if (hasLeadingIcon()) {\n <div md3-icon-element=\"leading\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n </div>\n }\n\n <input md3-input-element type=\"text\" [readonly]=\"true\" [disabled]=\"isDisabled()\" (click)=\"openMenu()\" class=\"md3-select-input\" [class.md3-menu-active]=\"isMenuOpen()\" [value]=\"selectedText()\">\n\n <button md3-icon-button button-type=\"standard\" [disabled]=\"isDisabled()\" (click)=\"toggleMenu()\" class=\"md3-select-arrow\">\n @if (hasArrowIcon()) {\n <ng-content select=\"[md3-icon-element=arrow]\"></ng-content>\n } @else {\n <md3-icon md3-icon-element>arrow_drop_down</md3-icon>\n }\n </button>\n\n <ng-content select=\"[md3-supporting-text]\" ngProjectAs=\"[md3-supporting-text]\"></ng-content>\n</md3-text-field>\n", styles: [".md3-select-input{text-overflow:ellipsis}.md3-select-input:read-only{cursor:default;-webkit-user-select:none;user-select:none}.md3-select-input~.md3-select-arrow{transition:transform var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}.md3-select-input.md3-menu-active:dir(ltr)~.md3-select-arrow{transform:rotate(180deg)}.md3-select-input.md3-menu-active:dir(rtl)~.md3-select-arrow{transform:rotate(-180deg)}\n"] }]
6985
+ }], ctorParameters: () => [{ type: MenuService }, { type: i0.ViewContainerRef }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "display-with", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], menuColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "menu-colors", required: false }] }], fieldType: [{ type: i0.Input, args: [{ isSignal: true, alias: "field-type", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], iconElements: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { ...{ descendants: true }, isSignal: true }] }], inputElement: [{ type: i0.ViewChild, args: [i0.forwardRef(() => InputElement), { ...{ read: ElementRef }, isSignal: true }] }] } });
6797
6986
 
6798
- class Menu {
6799
- el;
6800
- portalOutlet = viewChild(CdkPortalOutlet, /* @ts-ignore */
6801
- ...(ngDevMode ? [{ debugName: "portalOutlet" }] : /* istanbul ignore next */ []));
6802
- config = inject(MENU_CONFIG, { optional: true }) ?? {};
6803
- menuColors = signal('standard', /* @ts-ignore */
6804
- ...(ngDevMode ? [{ debugName: "menuColors" }] : /* istanbul ignore next */ []));
6805
- isVisible = signal(false, /* @ts-ignore */
6806
- ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
6807
- scheme = signal('inherit', /* @ts-ignore */
6808
- ...(ngDevMode ? [{ debugName: "scheme" }] : /* istanbul ignore next */ []));
6809
- direction = signal(null, /* @ts-ignore */
6810
- ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
6811
- isActive = signal(true, /* @ts-ignore */
6987
+ /**
6988
+ * Material 3 dialog shell. It extends the CDK dialog container, so focus
6989
+ * trapping, focus restoration and the ARIA attributes are handled by the CDK
6990
+ * while this component only owns the MD3 surface and its animation.
6991
+ */
6992
+ class Dialog extends CdkDialogContainer {
6993
+ surface = viewChild('surface', /* @ts-ignore */
6994
+ ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
6995
+ isActive = signal(false, /* @ts-ignore */
6812
6996
  ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
6813
- get element() {
6814
- return this.el.nativeElement;
6815
- }
6816
- constructor(el) {
6817
- this.el = el;
6818
- effect((onCleanup) => {
6819
- const color = 'md3-' + this.menuColors();
6820
- this.element.classList.add(color);
6821
- onCleanup(() => {
6822
- this.element.classList.remove(color);
6823
- });
6824
- });
6825
- this.menuColors.set(this.config.menuColors ?? 'standard');
6826
- this.scheme.set(this.config.scheme ?? 'inherit');
6827
- this.direction.set(this.config.direction ?? null);
6997
+ config = inject(DIALOG_CONFIG, { optional: true }) ?? {};
6998
+ get surfaceElement() {
6999
+ return this.surface()?.nativeElement ?? null;
6828
7000
  }
6829
- ngAfterContentInit() {
7001
+ /**
7002
+ * Started by DialogService, either right after the dialog is created or
7003
+ * once the dialog it replaces has had its head start. The animation runs on
7004
+ * the next frame so the surface has a real from/to state.
7005
+ */
7006
+ startEnterAnimation() {
6830
7007
  requestAnimationFrame(() => {
6831
- this.showMenu(true);
7008
+ this.isActive.set(true);
6832
7009
  });
6833
7010
  }
6834
- showMenu(value) {
6835
- this.isVisible.set(value);
7011
+ setActive(value) {
7012
+ this.isActive.set(value);
6836
7013
  }
6837
- /**
6838
- * The service creates this wrapper first, then calls this method to mount
6839
- * the user supplied component into the dialog container.
6840
- */
6841
- attachContent(component, injector) {
6842
- const portal = new ComponentPortal(component, null, injector);
6843
- return this.portalOutlet().attachComponentPortal(portal);
7014
+ recaptureFocus() {
7015
+ this._recaptureFocus();
6844
7016
  }
6845
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Menu, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
6846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Menu, isStandalone: true, selector: "md3-menu", host: { attributes: { "role": "menu" }, properties: { "class.md3-visible": "isVisible()", "class.md3-inactive": "!isActive()", "class.md-scheme-dark": "scheme() == \"dark\"", "class.md-scheme-light": "scheme() == \"light\"", "dir": "direction()" }, classAttribute: "md3-menu-container" }, viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template cdkPortalOutlet></ng-template>", 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-menu-scrim{position:absolute;inset:0;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-overlay-connected-position-bounding-box{pointer-events:none}::ng-deep .cdk-overlay-container .md3-menu-panel{pointer-events:auto}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-menu-closing{pointer-events:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 0;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel{position:absolute;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel.md3-menu-closing{pointer-events:none}:host{--background-color: rgb(var(--md-scheme-surface-container-low));--foreground-color: rgb(var(--md-scheme-on-surface));--border-radius: var(--md-border-radius-large);--menu-min-width: 7em;--menu-max-width: 17.5em;--menu-group-radius: var(--md-border-radius-small);--menu-group-shadow: var(--md-shadow-3dp);--menu-group-label-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-label-color: rgb(var(--md-scheme-on-surface));--menu-item-supporting-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-selected-background: rgb(var(--md-scheme-tertiary-container));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary-container));--menu-item-state-color: var(--md-scheme-on-surface);--menu-item-border-radius: var(--md-border-radius-xsmall);--menu-item-outline-color: rgb(var(--md-scheme-secondary));--menu-item-outline-width: .1875em;--menu-item-outline-offset: -.1875em;--menu-item-badge-background: rgb(var(--md-scheme-primary-container));--menu-item-badge-foreground: rgb(var(--md-scheme-on-primary-container));position:relative;display:block;font-size:1rem;min-width:var(--menu-min-width);max-width:min(var(--menu-max-width),100vw - 2rem);max-height:min(32rem,100vh - 2rem);outline:none;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8)}:host.md3-visible{opacity:1;transform:scaleY(1)}:host.md3-vibrant{--background-color: rgb(var(--md-scheme-tertiary-container));--foreground-color: rgb(var(--md-scheme-on-tertiary-container));--menu-group-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-supporting-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-selected-background: rgb(var(--md-scheme-tertiary));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary));--menu-item-state-color: var(--md-scheme-on-tertiary-container)}:host.md3-inactive{--border-radius: var(--md-border-radius-small)}:host ::ng-deep md3-menu-group{margin-top:.125em}:host ::ng-deep md3-menu-group:first-child{margin-top:0}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
7017
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
7018
+ 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"] }] });
6847
7019
  }
6848
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Menu, decorators: [{
7020
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dialog, decorators: [{
6849
7021
  type: Component,
6850
- args: [{ selector: 'md3-menu', imports: [
7022
+ args: [{ selector: 'md3-dialog', imports: [
6851
7023
  CdkPortalOutlet,
6852
- ], host: {
6853
- 'class': 'md3-menu-container',
6854
- 'role': 'menu',
6855
- '[class.md3-visible]': 'isVisible()',
6856
- '[class.md3-inactive]': '!isActive()',
6857
- '[class.md-scheme-dark]': 'scheme() == "dark"',
6858
- '[class.md-scheme-light]': 'scheme() == "light"',
6859
- '[dir]': 'direction()',
6860
- }, template: "<ng-template cdkPortalOutlet></ng-template>", 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-menu-scrim{position:absolute;inset:0;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-overlay-connected-position-bounding-box{pointer-events:none}::ng-deep .cdk-overlay-container .md3-menu-panel{pointer-events:auto}::ng-deep .cdk-overlay-container .md3-menu-panel.md3-menu-closing{pointer-events:none}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;padding:3.5rem 0;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel{position:absolute;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-menu-panel.md3-menu-closing{pointer-events:none}:host{--background-color: rgb(var(--md-scheme-surface-container-low));--foreground-color: rgb(var(--md-scheme-on-surface));--border-radius: var(--md-border-radius-large);--menu-min-width: 7em;--menu-max-width: 17.5em;--menu-group-radius: var(--md-border-radius-small);--menu-group-shadow: var(--md-shadow-3dp);--menu-group-label-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-label-color: rgb(var(--md-scheme-on-surface));--menu-item-supporting-color: rgb(var(--md-scheme-on-surface-variant));--menu-item-selected-background: rgb(var(--md-scheme-tertiary-container));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary-container));--menu-item-state-color: var(--md-scheme-on-surface);--menu-item-border-radius: var(--md-border-radius-xsmall);--menu-item-outline-color: rgb(var(--md-scheme-secondary));--menu-item-outline-width: .1875em;--menu-item-outline-offset: -.1875em;--menu-item-badge-background: rgb(var(--md-scheme-primary-container));--menu-item-badge-foreground: rgb(var(--md-scheme-on-primary-container));position:relative;display:block;font-size:1rem;min-width:var(--menu-min-width);max-width:min(var(--menu-max-width),100vw - 2rem);max-height:min(32rem,100vh - 2rem);outline:none;transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:scaleY(.8)}:host.md3-visible{opacity:1;transform:scaleY(1)}:host.md3-vibrant{--background-color: rgb(var(--md-scheme-tertiary-container));--foreground-color: rgb(var(--md-scheme-on-tertiary-container));--menu-group-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-label-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-supporting-color: rgb(var(--md-scheme-on-tertiary-container));--menu-item-selected-background: rgb(var(--md-scheme-tertiary));--menu-item-selected-foreground: rgb(var(--md-scheme-on-tertiary));--menu-item-state-color: var(--md-scheme-on-tertiary-container)}:host.md3-inactive{--border-radius: var(--md-border-radius-small)}:host ::ng-deep md3-menu-group{margin-top:.125em}:host ::ng-deep md3-menu-group:first-child{margin-top:0}\n"] }]
6861
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { portalOutlet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkPortalOutlet), { isSignal: true }] }] } });
7024
+ ], 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"] }]
7025
+ }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
6862
7026
 
6863
- class MenuService {
6864
- overlay = inject(Overlay);
6865
- injector = inject(Injector);
6866
- document = inject(DOCUMENT);
6867
- open(component, config = {}) {
6868
- const menuConfig = this.mergeConfig(config);
6869
- const previouslyFocusedElement = this.getFocusedElement();
6870
- const triggerElement = this.resolveTriggerElement(menuConfig.origin, previouslyFocusedElement);
6871
- const menuOverlay = this.createOverlay(menuConfig, previouslyFocusedElement);
6872
- const overlayRef = menuOverlay.overlayRef;
6873
- const menuRef = new MenuRef(overlayRef, previouslyFocusedElement);
6874
- const injector = this.createInjector(component, menuConfig, menuRef);
6875
- // The overlay hosts the MD3 menu shell. The shell is responsible for
6876
- // the surface markup and receives the dynamic content through a portal.
6877
- const menuPortal = new ComponentPortal(Menu, menuConfig.viewContainerRef ?? null, injector);
6878
- const menuComponentRef = overlayRef.attach(menuPortal);
6879
- const contentComponentRef = menuComponentRef.instance.attachContent(component, injector);
6880
- this.bindDataToInputs(contentComponentRef, menuConfig);
6881
- this.flipPositionIfPushBreaksAnchor(menuOverlay, menuConfig);
6882
- menuRef.componentInstance = contentComponentRef.instance;
6883
- menuRef.menuInstance = menuComponentRef.instance;
6884
- this.bindTriggerActiveState(triggerElement, overlayRef, menuRef);
6885
- this.startOpenAnimation(overlayRef);
6886
- this.connectCloseEvents(overlayRef, menuRef);
6887
- return menuRef;
6888
- }
6889
- openSubMenu(component, config = {}) {
6890
- const xPosition = this.getSubMenuXPosition(config.xPosition);
6891
- const yPosition = config.yPosition ?? 'below';
6892
- const offsetX = config.offsetX ?? 0;
6893
- const offsetY = config.offsetY ?? 0;
6894
- const subMenuConfig = {
6895
- ...config,
6896
- isSubMenu: true,
6897
- xPosition,
6898
- yPosition,
6899
- overlapTrigger: config.overlapTrigger ?? true,
6900
- offsetX,
6901
- offsetY,
6902
- scheme: config.scheme ?? 'inherit',
6903
- direction: config.direction ?? null,
6904
- };
6905
- return this.open(component, subMenuConfig);
6906
- }
6907
- mergeConfig(config) {
6908
- const viewportMargin = this.getViewportMargin(config.viewportMargin);
6909
- return {
6910
- data: config.data,
6911
- bindDataToInputs: config.bindDataToInputs ?? false,
6912
- isSubMenu: config.isSubMenu ?? false,
6913
- menuColors: config.menuColors ?? 'standard',
6914
- xPosition: config.xPosition ?? 'start',
6915
- yPosition: config.yPosition ?? 'below',
6916
- overlapTrigger: config.overlapTrigger ?? false,
6917
- offsetX: config.offsetX ?? 0,
6918
- offsetY: config.offsetY ?? 4,
6919
- viewportMargin,
6920
- positions: config.positions,
6921
- scrollStrategy: config.scrollStrategy ?? 'reposition',
6922
- scheme: config.scheme ?? 'inherit',
6923
- direction: config.direction ?? null,
6924
- viewContainerRef: config.viewContainerRef,
6925
- injector: config.injector ?? this.injector,
6926
- };
6927
- }
6928
- createOverlay(config, fallbackOrigin) {
6929
- const origin = this.resolveOrigin(config.origin, fallbackOrigin);
6930
- const positionStrategy = this.overlay.position()
6931
- .flexibleConnectedTo(origin)
6932
- .withFlexibleDimensions(false)
6933
- .withGrowAfterOpen(true)
6934
- .withPush(true)
6935
- .withViewportMargin(config.viewportMargin)
6936
- .withPositions(config.positions ?? this.getInitialConnectedPositions(config))
6937
- .withTransformOriginOn('.md3-menu-container');
6938
- const overlayConfig = new OverlayConfig({
6939
- hasBackdrop: true,
6940
- backdropClass: ['md3-menu-scrim', 'md3-menu-opening'],
6941
- panelClass: ['md3-menu-panel', 'md3-menu-opening'],
6942
- positionStrategy,
6943
- scrollStrategy: this.getScrollStrategy(config.scrollStrategy),
6944
- });
6945
- return {
6946
- overlayRef: this.overlay.create(overlayConfig),
6947
- positionStrategy: config.positions ? undefined : positionStrategy,
6948
- origin,
6949
- };
7027
+ /**
7028
+ * Material 3 full screen dialog shell. It covers the viewport and holds the content.
7029
+ *
7030
+ * The content is an `md3-layout`. The layout places the regions — the bar rows for an app bar
7031
+ * or a toolbar, the rail columns, and the panes where side sheets open — so the dialog itself
7032
+ * places nothing but the content. A content root that is not a layout gets a warning in
7033
+ * development mode, and the shell falls back to panes of its own, so a side sheet never opens
7034
+ * behind the dialog where nobody can see it.
7035
+ */
7036
+ class FullScreenDialog extends CdkDialogContainer {
7037
+ surface = viewChild('surface', /* @ts-ignore */
7038
+ ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
7039
+ mainPane = viewChild('mainPane', /* @ts-ignore */
7040
+ ...(ngDevMode ? [{ debugName: "mainPane" }] : /* istanbul ignore next */ []));
7041
+ startOutlet = viewChild('startOutlet', { ...(ngDevMode ? { debugName: "startOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
7042
+ endOutlet = viewChild('endOutlet', { ...(ngDevMode ? { debugName: "endOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
7043
+ sheets = inject(SheetsService);
7044
+ /** True while the shell holds the side sheet outlets, which happens without a layout only. */
7045
+ ownsSideSheetOutlets = false;
7046
+ isActive = signal(false, /* @ts-ignore */
7047
+ ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
7048
+ config = inject(DIALOG_CONFIG, { optional: true }) ?? {};
7049
+ get surfaceElement() {
7050
+ return this.surface()?.nativeElement ?? null;
6950
7051
  }
6951
- bindTriggerActiveState(triggerElement, overlayRef, menuRef) {
6952
- if (!triggerElement) {
7052
+ ngAfterViewInit() {
7053
+ // The content is attached by now, so the layout it brings has already taken the
7054
+ // outlets. Its panes sit under the bar regions, which is where a side sheet belongs.
7055
+ const layout = this.findContentLayout();
7056
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
7057
+ this.checkContentLayout(layout);
7058
+ }
7059
+ if (layout) {
6953
7060
  return;
6954
7061
  }
6955
- const removeActiveClass = () => triggerElement.classList.remove('md3-menu-active');
6956
- triggerElement.classList.add('md3-menu-active');
6957
- menuRef.afterClosed().pipe(take(1)).subscribe(removeActiveClass);
6958
- overlayRef.detachments().pipe(take(1)).subscribe(removeActiveClass);
7062
+ // No layout, so the shell keeps the dialog self-sufficient. Without this the next side
7063
+ // sheet would open in the outlet underneath — the page scaffold, behind the dialog.
7064
+ const startOutlet = this.startOutlet();
7065
+ const endOutlet = this.endOutlet();
7066
+ if (startOutlet) {
7067
+ this.sheets.registerSideSheetOutlet('start', startOutlet);
7068
+ }
7069
+ if (endOutlet) {
7070
+ this.sheets.registerSideSheetOutlet('end', endOutlet);
7071
+ }
7072
+ this.ownsSideSheetOutlets = !!startOutlet || !!endOutlet;
6959
7073
  }
6960
- resolveOrigin(origin, fallbackOrigin) {
6961
- const resolvedOrigin = origin ?? fallbackOrigin;
6962
- if (resolvedOrigin) {
6963
- if (this.isMouseEvent(resolvedOrigin)) {
6964
- if (resolvedOrigin.currentTarget instanceof HTMLElement) {
6965
- return resolvedOrigin.currentTarget;
6966
- }
6967
- return {
6968
- x: resolvedOrigin.clientX,
6969
- y: resolvedOrigin.clientY,
6970
- };
7074
+ ngOnDestroy() {
7075
+ if (this.ownsSideSheetOutlets) {
7076
+ const startOutlet = this.startOutlet();
7077
+ const endOutlet = this.endOutlet();
7078
+ if (startOutlet) {
7079
+ this.sheets.unregisterSideSheetOutlet('start', startOutlet);
6971
7080
  }
6972
- if (this.isElementRef(resolvedOrigin)) {
6973
- return resolvedOrigin.nativeElement;
7081
+ if (endOutlet) {
7082
+ this.sheets.unregisterSideSheetOutlet('end', endOutlet);
6974
7083
  }
6975
- return resolvedOrigin;
7084
+ this.ownsSideSheetOutlets = false;
6976
7085
  }
6977
- const viewport = this.document.defaultView;
6978
- return {
6979
- x: (viewport?.innerWidth ?? 0) / 2,
6980
- y: (viewport?.innerHeight ?? 0) / 2,
6981
- };
7086
+ super.ngOnDestroy();
6982
7087
  }
6983
- resolveTriggerElement(origin, fallbackOrigin) {
6984
- const resolvedOrigin = origin ?? fallbackOrigin;
6985
- if (!resolvedOrigin) {
7088
+ /**
7089
+ * The layout at the root of the content, if the content brought one.
7090
+ *
7091
+ * The root is either the layout itself, or the component that holds it — a dialog is
7092
+ * normally opened with a component whose own template starts with `md3-layout`.
7093
+ */
7094
+ findContentLayout() {
7095
+ const content = this.mainPane()?.nativeElement.firstElementChild;
7096
+ if (!content) {
6986
7097
  return null;
6987
7098
  }
6988
- if (this.isMouseEvent(resolvedOrigin)) {
6989
- return resolvedOrigin.currentTarget instanceof HTMLElement
6990
- ? resolvedOrigin.currentTarget
6991
- : null;
7099
+ if (content.tagName === 'MD3-LAYOUT') {
7100
+ return content;
6992
7101
  }
6993
- if (this.isElementRef(resolvedOrigin)) {
6994
- return resolvedOrigin.nativeElement;
7102
+ const root = content.firstElementChild;
7103
+ return root?.tagName === 'MD3-LAYOUT' ? root : null;
7104
+ }
7105
+ checkContentLayout(layout) {
7106
+ if (layout) {
7107
+ return;
6995
7108
  }
6996
- return resolvedOrigin instanceof HTMLElement ? resolvedOrigin : null;
7109
+ console.warn('[md3-fullscreen-dialog] the content of a full screen dialog should start with '
7110
+ + 'md3-layout. Without it the dialog has no bar and no rail region, so an app bar or '
7111
+ + 'a toolbar has nowhere to go, and the content does not scroll on its own.');
7112
+ }
7113
+ startEnterAnimation() {
7114
+ requestAnimationFrame(() => {
7115
+ this.isActive.set(true);
7116
+ });
7117
+ }
7118
+ setActive(value) {
7119
+ this.isActive.set(value);
7120
+ }
7121
+ recaptureFocus() {
7122
+ this._recaptureFocus();
7123
+ }
7124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
7125
+ 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: "mainPane", first: true, predicate: ["mainPane"], 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\" #mainPane>\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);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}: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"] }] });
7126
+ }
7127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, decorators: [{
7128
+ type: Component,
7129
+ args: [{ selector: 'md3-fullscreen-dialog', imports: [
7130
+ CdkPortalOutlet,
7131
+ ], 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\" #mainPane>\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);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
7132
+ }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }], mainPane: [{ type: i0.ViewChild, args: ['mainPane', { isSignal: true }] }], startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }] } });
7133
+
7134
+ const PANEL_CLASS = 'md3-dialog-panel';
7135
+ const FULL_SCREEN_PANEL_CLASS = 'md3-fullscreen-dialog-panel';
7136
+ const OPENING_CLASS = 'md3-dialog-opening';
7137
+ const SCRIM_KEPT_CLASS = 'md3-dialog-scrim-kept';
7138
+ const SCRIM_INSTANT_CLASS = 'md3-dialog-scrim-instant';
7139
+ /**
7140
+ * Head start given to a dialog that leaves the screen before the dialog taking
7141
+ * its place animates in. Long enough to read as one dialog replacing another,
7142
+ * short enough to still feel like a single gesture.
7143
+ */
7144
+ const DIALOG_HANDOVER_DELAY_MS = 160;
7145
+ class DialogService {
7146
+ cdkDialog = inject(Dialog$1);
7147
+ overlay = inject(Overlay);
7148
+ overlayContainer = inject(OverlayContainer);
7149
+ injector = inject(Injector);
7150
+ document = inject(DOCUMENT);
7151
+ /** Open dialogs, from the first one opened to the one currently on top. */
7152
+ refs = [];
7153
+ /**
7154
+ * Elements the page was made of that the CDK hid from assistive technology,
7155
+ * kept here while the dialogs are hidden and the page is given back.
7156
+ */
7157
+ pageAriaHidden = new Map();
7158
+ /**
7159
+ * Page scrolling is blocked here instead of per overlay, so stacked dialogs
7160
+ * cannot unblock the page while another dialog is still open.
7161
+ */
7162
+ scrollBlock = this.overlay.scrollStrategies.block();
7163
+ /** Element that was focused before the first dialog of the stack opened. */
7164
+ rootTrigger = null;
7165
+ pageStateQueued = false;
7166
+ get openDialogs() {
7167
+ return this.refs;
6997
7168
  }
6998
- flipPositionIfPushBreaksAnchor(menuOverlay, config) {
6999
- if (!menuOverlay.positionStrategy) {
7000
- return;
7001
- }
7002
- menuOverlay.overlayRef.updatePosition();
7003
- const fallbackPosition = this.getFallbackPositionAfterPush(config, this.getOriginClientRect(menuOverlay.origin), menuOverlay.overlayRef.overlayElement.getBoundingClientRect());
7004
- if (!fallbackPosition) {
7005
- return;
7006
- }
7007
- menuOverlay.positionStrategy.withPositions([fallbackPosition]);
7008
- menuOverlay.overlayRef.updatePosition();
7169
+ /** Open dialogs that are currently on screen, from the bottom one up. */
7170
+ get visibleDialogs() {
7171
+ return this.refs.filter((ref) => !ref.isHidden);
7009
7172
  }
7010
- getInitialConnectedPositions(config) {
7011
- return [this.getPreferredConnectedPosition(config)];
7173
+ /** The full screen dialog that is open, if there is one. */
7174
+ get fullScreenDialog() {
7175
+ return this.refs.find((ref) => ref.isFullScreen && !ref.isClosing);
7012
7176
  }
7013
- getPreferredConnectedPosition(config) {
7014
- if (config.isSubMenu) {
7015
- return this.createSubMenuConnectedPosition(this.getSubMenuXPosition(config.xPosition), this.getSubMenuVerticalAlignment(config.yPosition), config.offsetX, config.offsetY);
7177
+ open(component, config = {}) {
7178
+ const dialogConfig = this.mergeConfig(config);
7179
+ if (this.refs.length === 0) {
7180
+ this.rootTrigger = this.getFocusedElement();
7016
7181
  }
7017
- return this.createConnectedPosition(config.xPosition, config.yPosition, config);
7018
- }
7019
- getFallbackPositionAfterPush(config, originRect, overlayRect) {
7020
- const xPosition = this.shouldFlipXPosition(config, originRect, overlayRect)
7021
- ? this.getFallbackXPosition(config.xPosition)
7022
- : config.xPosition;
7023
- const yPosition = this.shouldFlipYPosition(config, originRect, overlayRect)
7024
- ? this.getFallbackYPosition(config.yPosition)
7025
- : config.yPosition;
7026
- if (xPosition === config.xPosition && yPosition === config.yPosition) {
7027
- return null;
7182
+ // The dialog that is on screen starts leaving first, so the two dialogs
7183
+ // never animate on top of each other. A full screen dialog is not part
7184
+ // of this: regular dialogs open on top of it and leave it alone.
7185
+ const previousRef = this.topRegularRef();
7186
+ if (previousRef) {
7187
+ this.dismissPrevious(previousRef, dialogConfig.previousDialog);
7028
7188
  }
7029
- return this.getPreferredConnectedPosition({
7030
- ...config,
7031
- xPosition,
7032
- yPosition,
7189
+ let dialogRef;
7190
+ const cdkRef = this.cdkDialog.open(component, {
7191
+ // The MD3 shell replaces the default CDK container, so the overlay,
7192
+ // focus trap and focus restoration come from the CDK while the shell
7193
+ // only renders the surface.
7194
+ container: {
7195
+ type: Dialog,
7196
+ providers: () => [
7197
+ { provide: DIALOG_CONFIG, useValue: dialogConfig },
7198
+ ],
7199
+ },
7200
+ // These tokens make the dialog controllable from the dynamic
7201
+ // component without coupling that component to the service.
7202
+ providers: (cdkDialogRef) => {
7203
+ dialogRef = new DialogRef(cdkDialogRef, dialogConfig.disableCloseEvents);
7204
+ return [
7205
+ { provide: DialogRef, useValue: dialogRef },
7206
+ { provide: DIALOG_DATA, useValue: dialogConfig.data },
7207
+ { provide: DIALOG_CONFIG, useValue: dialogConfig },
7208
+ { provide: DIALOG_COMPONENT, useValue: component },
7209
+ ];
7210
+ },
7211
+ data: dialogConfig.data,
7212
+ role: dialogConfig.role,
7213
+ ariaModal: true,
7214
+ ariaLabel: dialogConfig.ariaLabel || null,
7215
+ ariaLabelledBy: dialogConfig.ariaLabelledBy || null,
7216
+ ariaDescribedBy: dialogConfig.ariaDescribedBy || null,
7217
+ direction: dialogConfig.direction ?? undefined,
7218
+ viewContainerRef: dialogConfig.viewContainerRef,
7219
+ injector: dialogConfig.injector,
7220
+ hasBackdrop: true,
7221
+ backdropClass: ['md3-dialog-scrim', OPENING_CLASS],
7222
+ panelClass: [PANEL_CLASS, OPENING_CLASS],
7223
+ positionStrategy: this.overlay.position()
7224
+ .global()
7225
+ .centerHorizontally()
7226
+ .centerVertically(),
7227
+ // Scrolling is blocked by the service for the whole stack.
7228
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
7229
+ // Focus goes back to whatever opened the stack, even when the dialog
7230
+ // that was open underneath has been closed in the meantime.
7231
+ restoreFocus: this.rootTrigger ?? true,
7232
+ // Scrim and Escape handling lives in DialogRef so the dialog can
7233
+ // play its exit animation before the overlay is disposed.
7234
+ disableClose: true,
7033
7235
  });
7236
+ this.registerDialog(dialogRef, cdkRef, dialogConfig, previousRef);
7237
+ return dialogRef;
7034
7238
  }
7035
- shouldFlipXPosition(config, originRect, overlayRect) {
7036
- const tolerance = config.viewportMargin;
7037
- switch (config.xPosition) {
7038
- case 'before':
7039
- return overlayRect.right > originRect.left + tolerance;
7040
- case 'after':
7041
- return overlayRect.left < originRect.right - tolerance;
7042
- case 'start':
7043
- return originRect.left < overlayRect.left - tolerance
7044
- || originRect.left > overlayRect.right + tolerance;
7045
- case 'end':
7046
- return originRect.right < overlayRect.left - tolerance
7047
- || originRect.right > overlayRect.right + tolerance;
7048
- case 'center':
7049
- default:
7050
- return false;
7051
- }
7052
- }
7053
- shouldFlipYPosition(config, originRect, overlayRect) {
7054
- const tolerance = config.viewportMargin;
7055
- if (config.isSubMenu) {
7056
- const anchorY = config.yPosition === 'above' ? originRect.bottom : originRect.top;
7057
- return anchorY < overlayRect.top - tolerance
7058
- || anchorY > overlayRect.bottom + tolerance;
7059
- }
7060
- if (config.overlapTrigger) {
7061
- const anchorY = config.yPosition === 'above' ? originRect.bottom : originRect.top;
7062
- return anchorY < overlayRect.top - tolerance
7063
- || anchorY > overlayRect.bottom + tolerance;
7064
- }
7065
- switch (config.yPosition) {
7066
- case 'above':
7067
- return overlayRect.bottom > originRect.top + tolerance;
7068
- case 'below':
7069
- return overlayRect.top < originRect.bottom - tolerance;
7070
- case 'center':
7071
- default:
7072
- return false;
7239
+ /**
7240
+ * Opens a dialog that covers the whole screen. Only one can be open at a
7241
+ * time, so it replaces whatever is open, and while it is up the side sheet
7242
+ * outlets belong to it: side sheets open inside the dialog, not behind it.
7243
+ * `previousDialog` decides what happens to the dialogs it replaces, the
7244
+ * same way it does for a regular dialog.
7245
+ */
7246
+ openFullScreen(component, config = {}) {
7247
+ const dialogConfig = this.mergeConfig(config);
7248
+ if (this.refs.length === 0) {
7249
+ this.rootTrigger = this.getFocusedElement();
7073
7250
  }
7074
- }
7075
- createConnectedPosition(xPosition, yPosition, config) {
7076
- const horizontal = this.getHorizontalPosition(xPosition);
7077
- const vertical = this.getVerticalPosition(yPosition, config.overlapTrigger);
7078
- return {
7079
- ...horizontal,
7080
- ...vertical,
7081
- offsetX: config.offsetX,
7082
- offsetY: this.getOffsetY(yPosition, config),
7083
- panelClass: [
7084
- 'md3-menu-position-' + xPosition,
7085
- 'md3-menu-position-' + yPosition,
7086
- ],
7087
- };
7088
- }
7089
- createSubMenuConnectedPosition(xPosition, yAlignment, offsetX, offsetY) {
7090
- const horizontal = this.getHorizontalPosition(xPosition);
7091
- const yPosition = yAlignment === 'top' ? 'below' : 'above';
7092
- return {
7093
- ...horizontal,
7094
- originY: yAlignment,
7095
- overlayY: yAlignment,
7096
- offsetX: this.getSubMenuOffsetX(xPosition, offsetX),
7097
- offsetY: this.getSubMenuOffsetY(yAlignment, offsetY),
7098
- panelClass: [
7099
- 'md3-menu-position-' + xPosition,
7100
- 'md3-menu-position-' + yPosition,
7101
- 'md3-menu-position-submenu',
7102
- ],
7103
- };
7104
- }
7105
- getHorizontalPosition(position) {
7106
- switch (position) {
7107
- case 'end':
7108
- return {
7109
- originX: 'end',
7110
- overlayX: 'end',
7111
- };
7112
- case 'before':
7113
- return {
7114
- originX: 'start',
7115
- overlayX: 'end',
7116
- };
7117
- case 'after':
7118
- return {
7119
- originX: 'end',
7120
- overlayX: 'start',
7121
- };
7122
- case 'center':
7123
- return {
7124
- originX: 'center',
7125
- overlayX: 'center',
7126
- };
7127
- case 'start':
7128
- default:
7129
- return {
7130
- originX: 'start',
7131
- overlayX: 'start',
7132
- };
7251
+ // A full screen dialog is a context of its own: the dialog it replaces
7252
+ // and anything stacked on that dialog goes with it.
7253
+ const previousRef = this.topRef();
7254
+ if (previousRef) {
7255
+ // Everything open belongs to the context being replaced, including
7256
+ // a full screen dialog that is already up.
7257
+ this.dismissPreviousContext(dialogConfig.previousDialog);
7133
7258
  }
7259
+ let dialogRef;
7260
+ const cdkRef = this.cdkDialog.open(component, {
7261
+ container: {
7262
+ type: FullScreenDialog,
7263
+ providers: () => [
7264
+ { provide: DIALOG_CONFIG, useValue: dialogConfig },
7265
+ ],
7266
+ },
7267
+ providers: (cdkDialogRef) => {
7268
+ dialogRef = new DialogRef(cdkDialogRef, dialogConfig.disableCloseEvents, true);
7269
+ return [
7270
+ { provide: DialogRef, useValue: dialogRef },
7271
+ { provide: DIALOG_DATA, useValue: dialogConfig.data },
7272
+ { provide: DIALOG_CONFIG, useValue: dialogConfig },
7273
+ { provide: DIALOG_COMPONENT, useValue: component },
7274
+ ];
7275
+ },
7276
+ data: dialogConfig.data,
7277
+ role: dialogConfig.role,
7278
+ ariaModal: true,
7279
+ ariaLabel: dialogConfig.ariaLabel || null,
7280
+ ariaLabelledBy: dialogConfig.ariaLabelledBy || null,
7281
+ ariaDescribedBy: dialogConfig.ariaDescribedBy || null,
7282
+ direction: dialogConfig.direction ?? undefined,
7283
+ viewContainerRef: dialogConfig.viewContainerRef,
7284
+ injector: dialogConfig.injector,
7285
+ // The dialog covers the page on its own, so there is nothing left
7286
+ // for a scrim to dim.
7287
+ hasBackdrop: false,
7288
+ panelClass: [FULL_SCREEN_PANEL_CLASS, OPENING_CLASS],
7289
+ // The CDK writes the size on the panel and the global strategy then
7290
+ // drops its centering margins, which is how the panel ends up
7291
+ // covering the whole wrapper.
7292
+ width: '100%',
7293
+ height: '100%',
7294
+ positionStrategy: this.overlay.position().global(),
7295
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
7296
+ restoreFocus: this.rootTrigger ?? true,
7297
+ disableClose: true,
7298
+ });
7299
+ this.registerDialog(dialogRef, cdkRef, dialogConfig, previousRef);
7300
+ return dialogRef;
7134
7301
  }
7135
- getVerticalPosition(position, overlapTrigger) {
7136
- switch (position) {
7137
- case 'above':
7138
- return {
7139
- originY: overlapTrigger ? 'bottom' : 'top',
7140
- overlayY: 'bottom',
7141
- };
7142
- case 'center':
7143
- return {
7144
- originY: 'center',
7145
- overlayY: 'center',
7146
- };
7147
- case 'below':
7148
- default:
7149
- return {
7150
- originY: overlapTrigger ? 'top' : 'bottom',
7151
- overlayY: 'top',
7152
- };
7302
+ /** Wires a freshly created dialog into the stack and starts its animation. */
7303
+ registerDialog(dialogRef, cdkRef, dialogConfig, previousRef) {
7304
+ dialogRef.dialogInstance = cdkRef.containerInstance;
7305
+ dialogRef.componentInstance = cdkRef.componentInstance ?? undefined;
7306
+ if (cdkRef.componentRef) {
7307
+ this.bindDataToInputs(cdkRef.componentRef, dialogConfig);
7153
7308
  }
7154
- }
7155
- getFallbackXPosition(position) {
7156
- switch (position) {
7157
- case 'start':
7158
- return 'end';
7159
- case 'end':
7160
- return 'start';
7161
- case 'before':
7162
- return 'after';
7163
- case 'after':
7164
- return 'before';
7165
- case 'center':
7166
- default:
7167
- return 'center';
7309
+ this.refs.push(dialogRef);
7310
+ this.syncPageState();
7311
+ if (previousRef) {
7312
+ setTimeout(() => this.startReplacingAnimation(dialogRef, previousRef), DIALOG_HANDOVER_DELAY_MS);
7168
7313
  }
7169
- }
7170
- getSubMenuXPosition(position) {
7171
- return position === 'before' ? 'before' : 'after';
7172
- }
7173
- getFallbackYPosition(position) {
7174
- switch (position) {
7175
- case 'above':
7176
- return 'below';
7177
- case 'below':
7178
- return 'above';
7179
- case 'center':
7180
- default:
7181
- return 'center';
7314
+ else {
7315
+ this.startOpenAnimation(dialogRef);
7182
7316
  }
7317
+ // Restoring starts with the exit animation, so the dialog underneath is
7318
+ // already coming back while this one is fading out.
7319
+ dialogRef.beforeClosed().subscribe(() => this.restorePreviousDialog(dialogRef));
7320
+ dialogRef.afterClosed().subscribe(() => this.removeRef(dialogRef));
7321
+ // Hiding and showing can also come straight from the reference, so the
7322
+ // page state is driven by what the dialogs report rather than by the
7323
+ // calls that went through this service.
7324
+ dialogRef.hiddenChanged().subscribe(() => this.syncPageState());
7183
7325
  }
7184
- getSubMenuVerticalAlignment(position) {
7185
- return position === 'above' ? 'bottom' : 'top';
7326
+ /**
7327
+ * Hides every dialog that is on screen, the full screen one included, with
7328
+ * the closing animation. They stay alive with their content and state, the
7329
+ * page underneath becomes usable, and showAll() puts them back. The promise
7330
+ * resolves once they are all out of sight.
7331
+ */
7332
+ hideAll() {
7333
+ const visible = this.refs.filter((ref) => !ref.isHidden && !ref.isClosing);
7334
+ return Promise.all(visible.map((ref) => ref.hide())).then(() => undefined);
7186
7335
  }
7187
- getOriginClientRect(origin) {
7188
- if ('getBoundingClientRect' in origin) {
7189
- return origin.getBoundingClientRect();
7336
+ /**
7337
+ * Brings the dialogs back on screen, whether they were hidden one by one or
7338
+ * all at once: the dialog that was on top returns, along with the full
7339
+ * screen dialog it sits in. Dialogs hidden behind another dialog stay
7340
+ * hidden, since that is where they belong once the stack is back.
7341
+ */
7342
+ showAll() {
7343
+ const topRef = this.topRef();
7344
+ if (!topRef) {
7345
+ return;
7190
7346
  }
7191
- return {
7192
- x: origin.x,
7193
- y: origin.y,
7194
- top: origin.y,
7195
- right: origin.x,
7196
- bottom: origin.y,
7197
- left: origin.x,
7198
- width: 0,
7199
- height: 0,
7200
- };
7201
- }
7202
- getViewportMargin(configuredMargin) {
7203
- const minimumMargin = this.getHalfEmInPixels();
7204
- return Math.max(configuredMargin ?? minimumMargin, minimumMargin);
7205
- }
7206
- getHalfEmInPixels() {
7207
- const viewport = this.document.defaultView;
7208
- const fontSize = viewport?.getComputedStyle(this.document.documentElement).fontSize;
7209
- const pixels = fontSize ? Number.parseFloat(fontSize) * 0.5 : 8;
7210
- return Number.isFinite(pixels) ? pixels : 8;
7211
- }
7212
- getOffsetY(position, config) {
7213
- if (config.overlapTrigger || position === 'center') {
7214
- return 0;
7347
+ const fullScreenRef = this.fullScreenDialog;
7348
+ // The full screen dialog is the context the top one sits in, so it
7349
+ // comes back first and the dialog on top ends up on top, with the focus.
7350
+ if (fullScreenRef && fullScreenRef !== topRef && fullScreenRef.isHidden) {
7351
+ fullScreenRef.show();
7352
+ }
7353
+ if (topRef.isHidden) {
7354
+ topRef.show();
7215
7355
  }
7216
- return position === 'above'
7217
- ? config.offsetY * -1
7218
- : config.offsetY;
7219
7356
  }
7220
- getSubMenuOffsetX(position, offsetX) {
7221
- return position === 'before' ? offsetX * -1 : offsetX;
7357
+ /** Closes every open dialog, including the hidden and the full screen ones. */
7358
+ closeAll() {
7359
+ // Closed from the bottom up so a closing dialog never brings back a
7360
+ // hidden dialog that is about to close as well.
7361
+ return Promise.all([...this.refs].map((ref) => ref.close())).then(() => undefined);
7222
7362
  }
7223
- getSubMenuOffsetY(alignment, offsetY) {
7224
- return alignment === 'bottom' ? offsetY * -1 : offsetY;
7363
+ /** Closes the regular dialogs and leaves a full screen dialog alone. */
7364
+ closeRegularDialogs() {
7365
+ const closing = this.refs
7366
+ .filter((ref) => !ref.isFullScreen)
7367
+ .map((ref) => ref.close());
7368
+ return Promise.all(closing).then(() => undefined);
7225
7369
  }
7226
- getScrollStrategy(scrollStrategy) {
7227
- switch (scrollStrategy) {
7228
- case 'block':
7229
- return this.overlay.scrollStrategies.block();
7230
- case 'close':
7231
- return this.overlay.scrollStrategies.close();
7232
- case 'noop':
7233
- return this.overlay.scrollStrategies.noop();
7234
- case 'reposition':
7235
- default:
7236
- return this.overlay.scrollStrategies.reposition();
7237
- }
7370
+ mergeConfig(config) {
7371
+ return {
7372
+ data: config.data,
7373
+ bindDataToInputs: config.bindDataToInputs ?? false,
7374
+ disableCloseEvents: config.disableCloseEvents ?? false,
7375
+ previousDialog: config.previousDialog ?? 'close',
7376
+ role: config.role ?? 'dialog',
7377
+ ariaLabel: config.ariaLabel ?? '',
7378
+ ariaLabelledBy: config.ariaLabelledBy ?? '',
7379
+ ariaDescribedBy: config.ariaDescribedBy ?? '',
7380
+ scheme: config.scheme ?? 'inherit',
7381
+ direction: config.direction ?? null,
7382
+ viewContainerRef: config.viewContainerRef,
7383
+ injector: config.injector ?? this.injector,
7384
+ };
7238
7385
  }
7239
- isMouseEvent(origin) {
7240
- return typeof MouseEvent !== 'undefined' && origin instanceof MouseEvent;
7386
+ /**
7387
+ * Hides or closes the dialog that is on screen. Its scrim stays up until
7388
+ * the dialog taking over is ready for it, so the page behind never
7389
+ * brightens between the two dialogs.
7390
+ */
7391
+ dismissPrevious(previousRef, behavior) {
7392
+ previousRef.overlayRef.backdropElement?.classList.add(SCRIM_KEPT_CLASS);
7393
+ return behavior === 'hide' ? previousRef.hide() : this.closeRegularDialogs();
7241
7394
  }
7242
- isElementRef(origin) {
7243
- return typeof origin === 'object'
7244
- && origin !== null
7245
- && 'nativeElement' in origin
7246
- && origin.nativeElement instanceof HTMLElement;
7395
+ /**
7396
+ * The same choice for a full screen dialog, applied to everything that is
7397
+ * on screen: what it takes over from is a whole context, a full screen
7398
+ * dialog of its own included. `hide` keeps that context alive, and it comes
7399
+ * back as it was once this dialog closes.
7400
+ */
7401
+ dismissPreviousContext(behavior) {
7402
+ return behavior === 'hide' ? this.hideAll() : this.closeAll();
7247
7403
  }
7248
- startOpenAnimation(overlayRef) {
7404
+ startOpenAnimation(dialogRef) {
7405
+ const overlayRef = dialogRef.overlayRef;
7249
7406
  const panel = overlayRef.overlayElement;
7250
7407
  const backdrop = overlayRef.backdropElement;
7251
7408
  // The overlay is inserted already rendered. Keep an initial class for
@@ -7254,22 +7411,65 @@ class MenuService {
7254
7411
  requestAnimationFrame(() => {
7255
7412
  setTimeout(() => {
7256
7413
  panel.getBoundingClientRect();
7257
- panel.classList.remove('md3-menu-opening');
7258
- backdrop?.classList.remove('md3-menu-opening');
7414
+ panel.classList.remove(OPENING_CLASS);
7415
+ backdrop?.classList.remove(OPENING_CLASS);
7259
7416
  }, 100);
7260
7417
  });
7418
+ dialogRef.dialogInstance?.startEnterAnimation();
7419
+ }
7420
+ /** Opening animation for a dialog that took the place of another one. */
7421
+ startReplacingAnimation(dialogRef, previousRef) {
7422
+ if (dialogRef.isClosing) {
7423
+ return;
7424
+ }
7425
+ const panel = dialogRef.overlayRef.overlayElement;
7426
+ const backdrop = dialogRef.overlayRef.backdropElement;
7427
+ this.beginScrimHandover(previousRef, dialogRef);
7428
+ panel.getBoundingClientRect();
7429
+ panel.classList.remove(OPENING_CLASS);
7430
+ backdrop?.classList.remove(OPENING_CLASS);
7431
+ this.endScrimHandover(previousRef, dialogRef);
7432
+ dialogRef.dialogInstance?.startEnterAnimation();
7433
+ }
7434
+ /** Opening animation for a dialog coming back from behind a closing one. */
7435
+ startRestoringAnimation(closingRef, previousRef) {
7436
+ if (previousRef.isClosing) {
7437
+ return;
7438
+ }
7439
+ this.beginScrimHandover(closingRef, previousRef);
7440
+ previousRef.show();
7441
+ this.endScrimHandover(closingRef, previousRef);
7442
+ }
7443
+ /**
7444
+ * Moves both scrims to their new value in a single frame, without a
7445
+ * transition on either side, so the dim behind the dialogs never changes.
7446
+ */
7447
+ beginScrimHandover(fromRef, toRef) {
7448
+ const from = fromRef.overlayRef.backdropElement;
7449
+ const to = toRef.overlayRef.backdropElement;
7450
+ // Nothing to hand the scrim over to, e.g. a full screen dialog: the
7451
+ // outgoing scrim fades out on its own instead.
7452
+ if (!to) {
7453
+ return;
7454
+ }
7455
+ // Nothing to hand over either: the dialog leaving carries no scrim, so
7456
+ // the one coming in fades its own in rather than switching it on in a
7457
+ // single frame. This is a full screen dialog closing over a dialog that
7458
+ // was hidden underneath it.
7459
+ if (!from) {
7460
+ return;
7461
+ }
7462
+ from?.classList.add(SCRIM_INSTANT_CLASS);
7463
+ from?.classList.remove(SCRIM_KEPT_CLASS);
7464
+ to?.classList.add(SCRIM_INSTANT_CLASS);
7261
7465
  }
7262
- createInjector(component, config, menuRef) {
7263
- return Injector.create({
7264
- parent: config.injector,
7265
- providers: [
7266
- // These tokens make the menu controllable from the dynamic
7267
- // component without coupling that component to the service.
7268
- { provide: MenuRef, useValue: menuRef },
7269
- { provide: MENU_DATA, useValue: config.data },
7270
- { provide: MENU_CONFIG, useValue: config },
7271
- { provide: MENU_COMPONENT, useValue: component },
7272
- ],
7466
+ /** Gives the scrims their transitions back once the handover is painted. */
7467
+ endScrimHandover(fromRef, toRef) {
7468
+ const from = fromRef.overlayRef.backdropElement;
7469
+ const to = toRef.overlayRef.backdropElement;
7470
+ requestAnimationFrame(() => {
7471
+ from?.classList.remove(SCRIM_INSTANT_CLASS);
7472
+ to?.classList.remove(SCRIM_INSTANT_CLASS);
7273
7473
  });
7274
7474
  }
7275
7475
  bindDataToInputs(componentRef, config) {
@@ -7282,84 +7482,194 @@ class MenuService {
7282
7482
  componentRef.setInput(inputName, inputValue);
7283
7483
  });
7284
7484
  }
7285
- connectCloseEvents(overlayRef, menuRef) {
7286
- overlayRef.backdropClick().pipe(take(1)).subscribe(() => menuRef.close());
7287
- overlayRef.keydownEvents().pipe(filter((event) => event.key === 'Escape'), take(1)).subscribe(() => menuRef.close());
7485
+ canBindDataToInputs(data) {
7486
+ return typeof data === 'object' && data !== null && !Array.isArray(data);
7487
+ }
7488
+ /** Last dialog of the stack that is not closing yet. */
7489
+ topRef() {
7490
+ for (let index = this.refs.length - 1; index >= 0; index--) {
7491
+ if (!this.refs[index].isClosing) {
7492
+ return this.refs[index];
7493
+ }
7494
+ }
7495
+ return undefined;
7496
+ }
7497
+ /**
7498
+ * Same, without the full screen dialog: it hosts the dialogs opened on top
7499
+ * of it, so it is never the one that gets hidden or closed to make room.
7500
+ */
7501
+ topRegularRef() {
7502
+ const ref = this.topRef();
7503
+ return ref?.isFullScreen ? undefined : ref;
7504
+ }
7505
+ restorePreviousDialog(ref) {
7506
+ const index = this.refs.indexOf(ref);
7507
+ if (index < 1) {
7508
+ return;
7509
+ }
7510
+ for (let previousIndex = index - 1; previousIndex >= 0; previousIndex--) {
7511
+ const previousRef = this.refs[previousIndex];
7512
+ if (previousRef.isClosing) {
7513
+ continue;
7514
+ }
7515
+ // The closing dialog gets the same head start it was given when it
7516
+ // took the screen, and keeps the scrim until then. Nothing to keep
7517
+ // when the dialog underneath has no scrim of its own.
7518
+ if (previousRef.overlayRef.backdropElement) {
7519
+ ref.overlayRef.backdropElement?.classList.add(SCRIM_KEPT_CLASS);
7520
+ }
7521
+ setTimeout(() => {
7522
+ this.showHostFullScreenDialog(previousRef);
7523
+ this.startRestoringAnimation(ref, previousRef);
7524
+ }, DIALOG_HANDOVER_DELAY_MS);
7525
+ return;
7526
+ }
7527
+ }
7528
+ /**
7529
+ * Brings back the full screen dialog a restored dialog sits in. The two are
7530
+ * hidden together when a full screen dialog takes over with
7531
+ * `previousDialog: 'hide'`, so the context has to be on screen again before
7532
+ * the dialog that sits on top of it, exactly as showAll() puts them back.
7533
+ */
7534
+ showHostFullScreenDialog(ref) {
7535
+ if (ref.isFullScreen) {
7536
+ return;
7537
+ }
7538
+ const hostRef = this.fullScreenDialog;
7539
+ if (hostRef?.isHidden && this.refs.indexOf(hostRef) < this.refs.indexOf(ref)) {
7540
+ hostRef.show();
7541
+ }
7542
+ }
7543
+ removeRef(ref) {
7544
+ const index = this.refs.indexOf(ref);
7545
+ if (index === -1) {
7546
+ return;
7547
+ }
7548
+ this.refs.splice(index, 1);
7549
+ if (this.refs.length === 0) {
7550
+ this.rootTrigger = null;
7551
+ }
7552
+ this.syncPageState();
7553
+ }
7554
+ /**
7555
+ * State that belongs to the dialogs as a whole rather than to one of them:
7556
+ * page scrolling, the page being hidden from assistive technology, and
7557
+ * where focus sits. Applied in a task of its own, so a dialog handing the
7558
+ * screen over to another one does not give the page back and take it again
7559
+ * within the same frame.
7560
+ */
7561
+ syncPageState() {
7562
+ if (this.pageStateQueued) {
7563
+ return;
7564
+ }
7565
+ this.pageStateQueued = true;
7566
+ setTimeout(() => {
7567
+ this.pageStateQueued = false;
7568
+ this.applyPageState();
7569
+ });
7570
+ }
7571
+ applyPageState() {
7572
+ const hasVisibleDialog = this.refs.some((ref) => !ref.isHidden);
7573
+ if (hasVisibleDialog) {
7574
+ this.scrollBlock.enable();
7575
+ }
7576
+ else {
7577
+ this.scrollBlock.disable();
7578
+ }
7579
+ if (this.refs.length === 0) {
7580
+ // Nothing is open anymore: the CDK gives the page back to assistive
7581
+ // technology on its own, so there is nothing left to restore here.
7582
+ this.pageAriaHidden.clear();
7583
+ return;
7584
+ }
7585
+ if (hasVisibleDialog) {
7586
+ this.hidePageFromAssistiveTechnology();
7587
+ return;
7588
+ }
7589
+ this.exposePageToAssistiveTechnology();
7590
+ this.releaseFocus();
7591
+ }
7592
+ /**
7593
+ * Gives the page back to assistive technology while every dialog is hidden.
7594
+ * The CDK hides it for as long as a dialog is open, which would otherwise
7595
+ * leave nothing to read at all once the dialogs are out of sight.
7596
+ */
7597
+ exposePageToAssistiveTechnology() {
7598
+ if (this.pageAriaHidden.size > 0) {
7599
+ return;
7600
+ }
7601
+ const container = this.overlayContainer.getContainerElement();
7602
+ Array.from(container.parentElement?.children ?? []).forEach((sibling) => {
7603
+ const value = sibling.getAttribute('aria-hidden');
7604
+ if (sibling === container || value === null) {
7605
+ return;
7606
+ }
7607
+ this.pageAriaHidden.set(sibling, value);
7608
+ sibling.removeAttribute('aria-hidden');
7609
+ });
7610
+ }
7611
+ /** Hides the page again as soon as a dialog is back on screen. */
7612
+ hidePageFromAssistiveTechnology() {
7613
+ this.pageAriaHidden.forEach((value, element) => {
7614
+ element.setAttribute('aria-hidden', value);
7615
+ });
7616
+ this.pageAriaHidden.clear();
7617
+ }
7618
+ /**
7619
+ * Focus follows the dialogs off the screen: it goes back to whatever opened
7620
+ * the stack, so the page stays usable with the keyboard while the dialogs
7621
+ * wait behind it. Focus that already moved somewhere else is left alone.
7622
+ */
7623
+ releaseFocus() {
7624
+ const activeElement = this.document.activeElement;
7625
+ if (this.rootTrigger && (!activeElement || activeElement === this.document.body)) {
7626
+ this.rootTrigger.focus();
7627
+ }
7288
7628
  }
7289
7629
  getFocusedElement() {
7290
7630
  const activeElement = this.document.activeElement;
7291
7631
  return activeElement instanceof HTMLElement ? activeElement : null;
7292
7632
  }
7293
- canBindDataToInputs(data) {
7294
- return typeof data === 'object' && data !== null && !Array.isArray(data);
7295
- }
7296
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7297
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, providedIn: 'root' });
7633
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7634
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, providedIn: 'root' });
7298
7635
  }
7299
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuService, decorators: [{
7636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogService, decorators: [{
7300
7637
  type: Injectable,
7301
7638
  args: [{
7302
7639
  providedIn: 'root',
7303
7640
  }]
7304
7641
  }] });
7305
7642
 
7306
- class MenuGroup {
7307
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
7308
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: MenuGroup, isStandalone: true, selector: "md3-menu-group", host: { attributes: { "role": "group" } }, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [":host{display:flex;flex-direction:column;gap:.125em;padding:.25em;background-color:var(--background-color);color:var(--foreground-color);border-radius:var(--menu-group-radius);box-shadow:var(--menu-group-shadow)}:host:first-child{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius)}:host:last-child{border-end-start-radius:var(--border-radius);border-end-end-radius:var(--border-radius)}:host ::ng-deep md3-divider{margin:.125em .5em}:host ::ng-deep [md3-menu-item]:first-child .md3-menu-item-container{--border-top-start-r: var(--md-border-radius-medium);--border-top-end-r: var(--md-border-radius-medium);border-start-start-radius:var(--border-top-start-r);border-start-end-radius:var(--border-top-end-r)}:host ::ng-deep [md3-menu-item]:last-child .md3-menu-item-container{--border-bottom-start-r: var(--md-border-radius-medium);--border-bottom-end-r: var(--md-border-radius-medium);border-end-start-radius:var(--border-bottom-start-r);border-end-end-radius:var(--border-bottom-end-r)}.md3-menu-group-label{padding:.5rem var(--menu-item-inline-padding, .75rem) .25rem;color:rgb(var(--md-scheme-on-surface-variant));font-size:.75rem;font-weight:500;line-height:1rem;letter-spacing:.03125rem}\n"] });
7643
+ class DialogHeader {
7644
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
7645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogHeader, isStandalone: true, selector: "md3-dialog-header", ngImport: i0, template: "<ng-content select=\"[md3-icon-element]\"></ng-content>\n<div class=\"md3-dialog-title\">\n <md3-type-headline size=\"small\">\n <ng-content></ng-content>\n </md3-type-headline>\n</div>", styles: [":host{display:block;margin:1.5em 1.5em 1em;text-align:center}:host .md3-dialog-title{text-align:start;color:rgb(var(--md-scheme-on-surface))}:host ::ng-deep [md3-icon-element]{color:rgb(var(--md-scheme-secondary))}:host ::ng-deep [md3-icon-element]+.md3-dialog-title{margin-top:1em;text-align:center}\n"], dependencies: [{ kind: "directive", type: TypeHeadline, selector: "md3-type-headline, [md3-type-headline]", inputs: ["size", "color", "emphasized"] }] });
7309
7646
  }
7310
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuGroup, decorators: [{
7647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogHeader, decorators: [{
7311
7648
  type: Component,
7312
- args: [{ selector: 'md3-menu-group', imports: [], host: {
7313
- 'role': 'group',
7314
- }, template: "<ng-content></ng-content>\n", styles: [":host{display:flex;flex-direction:column;gap:.125em;padding:.25em;background-color:var(--background-color);color:var(--foreground-color);border-radius:var(--menu-group-radius);box-shadow:var(--menu-group-shadow)}:host:first-child{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius)}:host:last-child{border-end-start-radius:var(--border-radius);border-end-end-radius:var(--border-radius)}:host ::ng-deep md3-divider{margin:.125em .5em}:host ::ng-deep [md3-menu-item]:first-child .md3-menu-item-container{--border-top-start-r: var(--md-border-radius-medium);--border-top-end-r: var(--md-border-radius-medium);border-start-start-radius:var(--border-top-start-r);border-start-end-radius:var(--border-top-end-r)}:host ::ng-deep [md3-menu-item]:last-child .md3-menu-item-container{--border-bottom-start-r: var(--md-border-radius-medium);--border-bottom-end-r: var(--md-border-radius-medium);border-end-start-radius:var(--border-bottom-start-r);border-end-end-radius:var(--border-bottom-end-r)}.md3-menu-group-label{padding:.5rem var(--menu-item-inline-padding, .75rem) .25rem;color:rgb(var(--md-scheme-on-surface-variant));font-size:.75rem;font-weight:500;line-height:1rem;letter-spacing:.03125rem}\n"] }]
7649
+ args: [{ selector: 'md3-dialog-header', imports: [
7650
+ TypeHeadline
7651
+ ], template: "<ng-content select=\"[md3-icon-element]\"></ng-content>\n<div class=\"md3-dialog-title\">\n <md3-type-headline size=\"small\">\n <ng-content></ng-content>\n </md3-type-headline>\n</div>", styles: [":host{display:block;margin:1.5em 1.5em 1em;text-align:center}:host .md3-dialog-title{text-align:start;color:rgb(var(--md-scheme-on-surface))}:host ::ng-deep [md3-icon-element]{color:rgb(var(--md-scheme-secondary))}:host ::ng-deep [md3-icon-element]+.md3-dialog-title{margin-top:1em;text-align:center}\n"] }]
7315
7652
  }] });
7316
7653
 
7317
- class MenuItem {
7318
- el;
7319
- label = input('', { ...(ngDevMode ? { debugName: "label" } : /* istanbul ignore next */ {}), alias: 'label' });
7320
- supportingText = input(null, { ...(ngDevMode ? { debugName: "supportingText" } : /* istanbul ignore next */ {}), alias: 'supporting-text' });
7321
- trailingText = input(null, { ...(ngDevMode ? { debugName: "trailingText" } : /* istanbul ignore next */ {}), alias: 'trailing-text' });
7322
- selected = model(null, { ...(ngDevMode ? { debugName: "selected" } : /* istanbul ignore next */ {}), alias: 'selected' });
7323
- iconElements = contentChildren(IconElement, /* @ts-ignore */
7324
- ...(ngDevMode ? [{ debugName: "iconElements" }] : /* istanbul ignore next */ []));
7325
- get leading() {
7326
- return this.iconElements().find((icon) => icon.iconType() === 'leading');
7327
- }
7328
- get trailing() {
7329
- return this.iconElements().find((icon) => icon.iconType() === 'trailing');
7330
- }
7331
- get showLeadingIcon() {
7332
- return (!!this.leading && !this.selected()) || this.selected() == true;
7333
- }
7334
- onHostClick() {
7335
- const selected = this.selected();
7336
- if (selected === null) {
7337
- return;
7338
- }
7339
- this.selected.set(!selected);
7340
- }
7341
- constructor(el) {
7342
- this.el = el;
7343
- }
7344
- get element() {
7345
- return this.el.nativeElement;
7346
- }
7347
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuItem, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
7348
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: MenuItem, isStandalone: true, selector: "button[md3-menu-item], a[md3-menu-item]", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, supportingText: { classPropertyName: "supportingText", publicName: "supporting-text", isSignal: true, isRequired: false, transformFunction: null }, trailingText: { classPropertyName: "trailingText", publicName: "trailing-text", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange" }, host: { listeners: { "click": "onHostClick()" } }, queries: [{ propertyName: "iconElements", predicate: IconElement, isSignal: true }], ngImport: i0, template: "@if (selected() !== null) {\n <input type=\"checkbox\" md3-input-element [checked]=\"selected()\">\n}\n\n<div class=\"md3-menu-item-container\" md3-state-component>\n <div class=\"md3-menu-item-leading\" [class.has-icon]=\"showLeadingIcon\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n @if (!leading) {\n <md3-icon>check</md3-icon>\n }\n </div>\n\n <div class=\"md3-menu-item-content\">\n <md3-type-label size=\"large\">{{ label() }}</md3-type-label>\n @if (supportingText()?.length) {\n <md3-type-body size=\"small\">{{ supportingText() }}</md3-type-body>\n }\n </div>\n\n <div class=\"md3-menu-item-trailing\">\n <ng-content select=\"md3-badge\"></ng-content>\n @if (trailingText()?.length) {\n <md3-type-title size=\"small\">{{ trailingText() }}</md3-type-title>\n }\n <ng-content select=\"[md3-icon-element=trailing]\"></ng-content>\n </div>\n</div>", styles: [":host{--state-color: var(--menu-item-state-color);--border-radius: var(--menu-item-border-radius);--outline-color: var(--menu-item-outline-color);--outline-width: var(--menu-item-outline-width);--outline-offset: var(--menu-item-outline-offset);position:relative;display:block;padding:0;border:0;background:transparent;color:var(--menu-item-label-color);font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;appearance:none;-webkit-user-select:none;user-select:none;z-index:0}:host:focus{z-index:1}:host:focus:not(:hover) .md3-menu-item-container:after{opacity:1}:host:active{z-index:2}:host:active .md3-menu-item-container:after{opacity:0}:host .md3-menu-item-container{display:flex;align-items:center;min-height:3em;padding:0 .75em;border-radius:var(--border-radius);transition:background-color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading{display:inline-flex;align-items:center;justify-content:center;font-size:inherit;opacity:0;transform:scale(1.2);width:0;height:1.25em;color:var(--menu-item-supporting-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-leading.has-icon{margin-inline-end:.5em;opacity:1;transform:scale(1);height:1.25em;width:1.25em}:host .md3-menu-item-container .md3-menu-item-trailing{flex:0 1 content;display:inline-flex;gap:.5em;align-items:center;justify-content:center;font-size:inherit;margin-inline-start:.5em;color:var(--menu-item-supporting-color)}:host .md3-menu-item-container .md3-menu-item-trailing:empty{margin:0}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep md3-badge{background-color:var(--menu-item-badge-background);color:var(--menu-item-badge-foreground)}:host .md3-menu-item-container .md3-menu-item-trailing .md3-text-title.md3-text-small{margin:0;padding:0;white-space:nowrap;letter-spacing:.007143em}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-content{flex:1 1 auto}:host .md3-menu-item-container .md3-menu-item-content .md3-text-label.md3-text-large{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.007143em;color:var(--menu-item-label-color)}:host .md3-menu-item-container .md3-menu-item-content .md3-text-body.md3-text-small{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.0333334em;color:var(--menu-item-supporting-color)}:host [md3-input-element]{position:absolute;height:0;width:0;opacity:0;pointer-events:none}:host [md3-input-element]+.md3-menu-item-container .md3-menu-item-leading{opacity:0;transform:scale(1.2);width:0}:host [md3-input-element]:checked+.md3-menu-item-container{--menu-item-label-color: var(--menu-item-selected-foreground);--menu-item-supporting-color: var(--menu-item-selected-foreground);--border-radius: var(--md-border-radius-medium);background-color:var(--menu-item-selected-background)}:host [md3-input-element]:checked+.md3-menu-item-container .md3-menu-item-leading{opacity:1;transform:scale(1);width:1.25em}:host:disabled{cursor:default}:host:disabled .md3-menu-item-container{--menu-item-label-color: var(--menu-item-label-color);--menu-item-supporting-color: var(--menu-item-label-color);--menu-item-selected-background: transparent;--menu-item-selected-foreground: var(--menu-item-label-color);pointer-events:none;opacity:.38}:host:disabled .md3-menu-item-container.md3-state-layer,:host:disabled .md3-menu-item-container:after{display:none}\n"], dependencies: [{ kind: "directive", type: InputElement, selector: "[md3-input-element]" }, { kind: "directive", type: StateComponent, selector: "[md3-state-component]" }, { kind: "component", type: MaterialIcon, selector: "md3-icon", inputs: ["icon-version", "filled", "icon-style", "icon-size", "bi-directional"] }, { kind: "directive", type: TypeLabel, selector: "md3-type-label, [md3-type-label]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeBody, selector: "md3-type-body, [md3-type-body]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeTitle, selector: "md3-type-title, [md3-type-title]", inputs: ["size", "color", "emphasized"] }] });
7654
+ class DialogBody {
7655
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogBody, deps: [], target: i0.ɵɵFactoryTarget.Component });
7656
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogBody, isStandalone: true, selector: "md3-dialog-body", host: { classAttribute: "md3-scrollable" }, ngImport: i0, template: "<ng-content></ng-content>", styles: [":host{display:block;margin:1em 1.5em 1.5em;color:rgb(var(--md-scheme-on-surface-variant))}:host .md3-text-body.md3-text-medium{letter-spacing:.017857em}\n"] });
7349
7657
  }
7350
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuItem, decorators: [{
7658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogBody, decorators: [{
7351
7659
  type: Component,
7352
- args: [{ selector: 'button[md3-menu-item], a[md3-menu-item]', imports: [
7353
- InputElement,
7354
- StateComponent,
7355
- MaterialIcon,
7356
- TypeLabel,
7357
- TypeBody,
7358
- TypeTitle,
7359
- ], host: {
7360
- '(click)': 'onHostClick()',
7361
- }, template: "@if (selected() !== null) {\n <input type=\"checkbox\" md3-input-element [checked]=\"selected()\">\n}\n\n<div class=\"md3-menu-item-container\" md3-state-component>\n <div class=\"md3-menu-item-leading\" [class.has-icon]=\"showLeadingIcon\">\n <ng-content select=\"[md3-icon-element=leading]\"></ng-content>\n @if (!leading) {\n <md3-icon>check</md3-icon>\n }\n </div>\n\n <div class=\"md3-menu-item-content\">\n <md3-type-label size=\"large\">{{ label() }}</md3-type-label>\n @if (supportingText()?.length) {\n <md3-type-body size=\"small\">{{ supportingText() }}</md3-type-body>\n }\n </div>\n\n <div class=\"md3-menu-item-trailing\">\n <ng-content select=\"md3-badge\"></ng-content>\n @if (trailingText()?.length) {\n <md3-type-title size=\"small\">{{ trailingText() }}</md3-type-title>\n }\n <ng-content select=\"[md3-icon-element=trailing]\"></ng-content>\n </div>\n</div>", styles: [":host{--state-color: var(--menu-item-state-color);--border-radius: var(--menu-item-border-radius);--outline-color: var(--menu-item-outline-color);--outline-width: var(--menu-item-outline-width);--outline-offset: var(--menu-item-outline-offset);position:relative;display:block;padding:0;border:0;background:transparent;color:var(--menu-item-label-color);font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;appearance:none;-webkit-user-select:none;user-select:none;z-index:0}:host:focus{z-index:1}:host:focus:not(:hover) .md3-menu-item-container:after{opacity:1}:host:active{z-index:2}:host:active .md3-menu-item-container:after{opacity:0}:host .md3-menu-item-container{display:flex;align-items:center;min-height:3em;padding:0 .75em;border-radius:var(--border-radius);transition:background-color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing),color var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading{display:inline-flex;align-items:center;justify-content:center;font-size:inherit;opacity:0;transform:scale(1.2);width:0;height:1.25em;color:var(--menu-item-supporting-color);transition:all var(--md-motion-standard-fast-spatial-duration) var(--md-motion-standard-fast-spatial-easing)}:host .md3-menu-item-container .md3-menu-item-leading ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-leading.has-icon{margin-inline-end:.5em;opacity:1;transform:scale(1);height:1.25em;width:1.25em}:host .md3-menu-item-container .md3-menu-item-trailing{flex:0 1 content;display:inline-flex;gap:.5em;align-items:center;justify-content:center;font-size:inherit;margin-inline-start:.5em;color:var(--menu-item-supporting-color)}:host .md3-menu-item-container .md3-menu-item-trailing:empty{margin:0}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep md3-badge{background-color:var(--menu-item-badge-background);color:var(--menu-item-badge-foreground)}:host .md3-menu-item-container .md3-menu-item-trailing .md3-text-title.md3-text-small{margin:0;padding:0;white-space:nowrap;letter-spacing:.007143em}:host .md3-menu-item-container .md3-menu-item-trailing ::ng-deep [md3-icon-element]{font-size:1.25em!important;height:1em!important;width:1em!important;line-height:1em!important}:host .md3-menu-item-container .md3-menu-item-content{flex:1 1 auto}:host .md3-menu-item-container .md3-menu-item-content .md3-text-label.md3-text-large{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.007143em;color:var(--menu-item-label-color)}:host .md3-menu-item-container .md3-menu-item-content .md3-text-body.md3-text-small{display:block;margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:.0333334em;color:var(--menu-item-supporting-color)}:host [md3-input-element]{position:absolute;height:0;width:0;opacity:0;pointer-events:none}:host [md3-input-element]+.md3-menu-item-container .md3-menu-item-leading{opacity:0;transform:scale(1.2);width:0}:host [md3-input-element]:checked+.md3-menu-item-container{--menu-item-label-color: var(--menu-item-selected-foreground);--menu-item-supporting-color: var(--menu-item-selected-foreground);--border-radius: var(--md-border-radius-medium);background-color:var(--menu-item-selected-background)}:host [md3-input-element]:checked+.md3-menu-item-container .md3-menu-item-leading{opacity:1;transform:scale(1);width:1.25em}:host:disabled{cursor:default}:host:disabled .md3-menu-item-container{--menu-item-label-color: var(--menu-item-label-color);--menu-item-supporting-color: var(--menu-item-label-color);--menu-item-selected-background: transparent;--menu-item-selected-foreground: var(--menu-item-label-color);pointer-events:none;opacity:.38}:host:disabled .md3-menu-item-container.md3-state-layer,:host:disabled .md3-menu-item-container:after{display:none}\n"] }]
7362
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], supportingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "supporting-text", required: false }] }], trailingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailing-text", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], iconElements: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => IconElement), { isSignal: true }] }] } });
7660
+ args: [{ selector: 'md3-dialog-body', imports: [], host: {
7661
+ 'class': 'md3-scrollable',
7662
+ }, template: "<ng-content></ng-content>", styles: [":host{display:block;margin:1em 1.5em 1.5em;color:rgb(var(--md-scheme-on-surface-variant))}:host .md3-text-body.md3-text-medium{letter-spacing:.017857em}\n"] }]
7663
+ }] });
7664
+
7665
+ class DialogActions {
7666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
7667
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: DialogActions, isStandalone: true, selector: "md3-dialog-actions", ngImport: i0, template: "<div class=\"md3-actions\">\n <ng-content></ng-content>\n</div>", styles: [":host{display:block;margin:1.5em}:host .md3-actions{display:flex;gap:1em;flex-direction:row-reverse}\n"] });
7668
+ }
7669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DialogActions, decorators: [{
7670
+ type: Component,
7671
+ args: [{ selector: 'md3-dialog-actions', imports: [], template: "<div class=\"md3-actions\">\n <ng-content></ng-content>\n</div>", styles: [":host{display:block;margin:1.5em}:host .md3-actions{display:flex;gap:1em;flex-direction:row-reverse}\n"] }]
7672
+ }] });
7363
7673
 
7364
7674
  class SideSheetHeader {
7365
7675
  title = input('', { ...(ngDevMode ? { debugName: "title" } : /* istanbul ignore next */ {}), alias: 'title' });
@@ -7762,5 +8072,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
7762
8072
  * Generated bundle index. Do not edit.
7763
8073
  */
7764
8074
 
7765
- 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, Grid, GridItem, IconButton, IconElement, InputElement, Layout, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, ModalBottomSheetRef, 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, StandardBottomSheetRef, StateComponent, SupportingText, Switch, TextField, Toolbar, ToolbarItem, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, ViewportService, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
8075
+ 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, Grid, GridItem, IconButton, IconElement, InputElement, Layout, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, ModalBottomSheetRef, 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, SelectField, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StandardBottomSheetRef, StateComponent, SupportingText, Switch, TextField, Toolbar, ToolbarItem, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, ViewportService, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
7766
8076
  //# sourceMappingURL=almoamendev-ngx-md3.mjs.map