@almoamendev/ngx-md3 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, booleanAttribute, effect, Directive, inject, signal, computed, Injectable, InjectionToken, viewChild, NgZone, ElementRef, Component, ViewChild, isDevMode, ViewContainerRef, Injector, numberAttribute, HostListener, model, contentChild, contentChildren, PLATFORM_ID, afterNextRender, output, HostBinding, TemplateRef } from '@angular/core';
2
+ import { input, booleanAttribute, effect, Directive, inject, signal, computed, untracked, Injectable, InjectionToken, viewChild, NgZone, ElementRef, Component, ViewChild, isDevMode, ViewContainerRef, Injector, numberAttribute, HostListener, model, contentChild, contentChildren, PLATFORM_ID, afterNextRender, output, HostBinding, TemplateRef } from '@angular/core';
3
3
  import { DOCUMENT, isPlatformBrowser, NgClass, NgTemplateOutlet } from '@angular/common';
4
4
  import { BreakpointObserver } from '@angular/cdk/layout';
5
5
  import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -242,10 +242,22 @@ class LayoutService {
242
242
  mainPaneEl;
243
243
  panesContainerResizeObserver;
244
244
  panesContainerResizeListener;
245
+ /** Floating bars currently registered, keyed by the measured element. */
246
+ floatingBars = new Map();
247
+ /** How far the main pane must move before the scroll direction flips. Stops jitter. */
248
+ static scrollDirectionThreshold = 64;
249
+ scrollPosition = 0;
245
250
  mainScrollTop = signal(0, /* @ts-ignore */
246
251
  ...(ngDevMode ? [{ debugName: "mainScrollTop" }] : /* istanbul ignore next */ []));
247
252
  mainIsScrolled = computed(() => this.mainScrollTop() > 0, /* @ts-ignore */
248
253
  ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
254
+ /**
255
+ * True while the main pane moves down, false while it moves up. A small threshold keeps
256
+ * a jitter from flipping the value. Components that react to scrolling — the app bar and
257
+ * the toolbar — read this, so they can never disagree.
258
+ */
259
+ isScrollingDown = signal(false, /* @ts-ignore */
260
+ ...(ngDevMode ? [{ debugName: "isScrollingDown" }] : /* istanbul ignore next */ []));
249
261
  /**
250
262
  * Distance, in pixels, between the viewport bottom and the bottom edge of
251
263
  * the scaffold's .md3-panes-container — i.e. whatever the bottom scaffold
@@ -255,6 +267,24 @@ class LayoutService {
255
267
  */
256
268
  bottomInset = signal(0, /* @ts-ignore */
257
269
  ...(ngDevMode ? [{ debugName: "bottomInset" }] : /* istanbul ignore next */ []));
270
+ /**
271
+ * Space a floating scaffold bar covers but does not reserve, per logical block side.
272
+ *
273
+ * A floating toolbar in a bar region leaves the layout flow, so its grid track collapses
274
+ * and the content flows under it. This signal reports what it covers, so the scaffold can
275
+ * pad the main pane and overlays can stay clear of it.
276
+ *
277
+ * A floating toolbar in a *rail* region stays in the flow and reserves its own space, so
278
+ * it never appears here.
279
+ */
280
+ floatingInset = signal({ blockStart: 0, blockEnd: 0 }, /* @ts-ignore */
281
+ ...(ngDevMode ? [{ debugName: "floatingInset" }] : /* istanbul ignore next */ []));
282
+ /**
283
+ * The distance from the viewport bottom that a viewport-anchored overlay must keep clear.
284
+ * It covers both the reserved bottom bar and any floating bottom bar over it.
285
+ */
286
+ bottomSafeInset = computed(() => this.bottomInset() + this.floatingInset().blockEnd, /* @ts-ignore */
287
+ ...(ngDevMode ? [{ debugName: "bottomSafeInset" }] : /* istanbul ignore next */ []));
258
288
  viewport = toSignal(fromEvent(window, 'resize').pipe(startWith(null), map(() => ({
259
289
  width: window.innerWidth,
260
290
  height: window.innerHeight
@@ -323,6 +353,11 @@ class LayoutService {
323
353
  darkMode = signal(true, /* @ts-ignore */
324
354
  ...(ngDevMode ? [{ debugName: "darkMode" }] : /* istanbul ignore next */ []));
325
355
  constructor() {
356
+ // Keep the scroll direction in step with the position. Anything that writes
357
+ // mainScrollTop drives it, so the app bar and the toolbar always agree.
358
+ effect(() => {
359
+ this.updateScrollDirection(this.mainScrollTop());
360
+ });
326
361
  effect(() => {
327
362
  const darkMode = this.darkMode();
328
363
  this.document.body.classList.toggle('md-scheme-dark', darkMode);
@@ -343,6 +378,7 @@ class LayoutService {
343
378
  scrollMainPaneToTop() {
344
379
  this.mainPaneEl?.scrollTo({ top: 0 });
345
380
  this.mainScrollTop.set(0);
381
+ this.resetScrollDirection();
346
382
  }
347
383
  registerMainPane(element) {
348
384
  this.mainPaneSub?.unsubscribe();
@@ -365,6 +401,22 @@ class LayoutService {
365
401
  this.mainPaneEl = undefined;
366
402
  }
367
403
  this.mainScrollTop.set(0);
404
+ this.resetScrollDirection();
405
+ }
406
+ resetScrollDirection() {
407
+ this.scrollPosition = 0;
408
+ this.isScrollingDown.set(false);
409
+ }
410
+ updateScrollDirection(scrollTop) {
411
+ if (scrollTop === this.scrollPosition) {
412
+ return;
413
+ }
414
+ const offset = scrollTop - this.scrollPosition;
415
+ if (Math.abs(offset) <= LayoutService.scrollDirectionThreshold) {
416
+ return;
417
+ }
418
+ this.isScrollingDown.set(offset > 0);
419
+ this.scrollPosition = scrollTop;
368
420
  }
369
421
  registerPanesContainer(element) {
370
422
  this.unregisterPanesContainer();
@@ -378,6 +430,67 @@ class LayoutService {
378
430
  this.panesContainerResizeListener = update;
379
431
  window.addEventListener('resize', update, { passive: true });
380
432
  }
433
+ /**
434
+ * Register a floating bar so the scaffold and the overlays know what it covers.
435
+ *
436
+ * Call this for a floating toolbar in a scaffold *bar* region only. A rail region keeps
437
+ * the toolbar in the layout flow, so it reserves its own space and needs no inset.
438
+ */
439
+ registerFloatingBar(element, side) {
440
+ this.unregisterFloatingBar(element);
441
+ const observer = new ResizeObserver(() => this.measureFloatingBars());
442
+ observer.observe(element);
443
+ this.floatingBars.set(element, { side, observer });
444
+ this.measureFloatingBars();
445
+ }
446
+ unregisterFloatingBar(element) {
447
+ const entry = this.floatingBars.get(element);
448
+ if (!entry) {
449
+ return;
450
+ }
451
+ entry.observer.disconnect();
452
+ this.floatingBars.delete(element);
453
+ this.measureFloatingBars();
454
+ }
455
+ measureFloatingBars() {
456
+ let blockStart = 0;
457
+ let blockEnd = 0;
458
+ for (const [element, entry] of this.floatingBars) {
459
+ const size = this.measureBlockSize(element);
460
+ if (entry.side === 'blockStart') {
461
+ blockStart = Math.max(blockStart, size);
462
+ }
463
+ else {
464
+ blockEnd = Math.max(blockEnd, size);
465
+ }
466
+ }
467
+ // Read the current value untracked. A component registers its floating bar from an
468
+ // effect, so a tracked read would make that effect depend on the signal that the same
469
+ // run writes. The cleanup measures an empty map and writes 0, the body measures the bar
470
+ // and writes its size, and the effect dirties itself again on every run. That loop never
471
+ // settles, and change detection never finishes.
472
+ const current = untracked(this.floatingInset);
473
+ // Only write on a real change. The main pane padding reads this value, and padding
474
+ // changes the panes container size, which fires the observer again.
475
+ if (current.blockStart === blockStart && current.blockEnd === blockEnd) {
476
+ return;
477
+ }
478
+ this.floatingInset.set({ blockStart, blockEnd });
479
+ }
480
+ /**
481
+ * `offsetHeight` ignores transforms. So a toolbar that scrolling has hidden or collapsed
482
+ * still reports its expanded size, and the content padding never moves while the user
483
+ * scrolls.
484
+ */
485
+ measureBlockSize(element) {
486
+ if (typeof getComputedStyle === 'undefined') {
487
+ return element.offsetHeight || 0;
488
+ }
489
+ const styles = getComputedStyle(element);
490
+ const start = Number.parseFloat(styles.marginBlockStart) || 0;
491
+ const end = Number.parseFloat(styles.marginBlockEnd) || 0;
492
+ return Math.max(0, Math.round(element.offsetHeight + start + end));
493
+ }
381
494
  unregisterPanesContainer() {
382
495
  this.panesContainerResizeObserver?.disconnect();
383
496
  this.panesContainerResizeObserver = undefined;
@@ -1847,6 +1960,18 @@ class Scaffold {
1847
1960
  sheets = inject(SheetsService);
1848
1961
  bottomSheets = inject(BottomSheetService);
1849
1962
  layout = inject(LayoutService);
1963
+ el = inject(ElementRef);
1964
+ constructor() {
1965
+ // Publish what a floating bar covers but does not reserve. The main pane pads itself
1966
+ // by these values, and the fallback is 0, so a layout without a floating bar is
1967
+ // unchanged. A page that needs full-bleed content sets them back to 0 on itself.
1968
+ effect(() => {
1969
+ const inset = this.layout.floatingInset();
1970
+ const host = this.el.nativeElement;
1971
+ host.style.setProperty('--md-scaffold-floating-inset-block-start', `${inset.blockStart}px`);
1972
+ host.style.setProperty('--md-scaffold-floating-inset-block-end', `${inset.blockEnd}px`);
1973
+ });
1974
+ }
1850
1975
  ngAfterViewInit() {
1851
1976
  const startOutlet = this.startOutlet();
1852
1977
  const endOutlet = this.endOutlet();
@@ -1881,14 +2006,14 @@ class Scaffold {
1881
2006
  this.layout.unregisterPanesContainer();
1882
2007
  }
1883
2008
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Scaffold, deps: [], target: i0.ɵɵFactoryTarget.Component });
1884
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Scaffold, isStandalone: true, selector: "md3-scaffold", viewQueries: [{ propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "bottomOutlet", first: true, predicate: ["bottomOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "panesContainer", first: true, predicate: ["panesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content select=\"[md3-scaffold-bar=top]\"></ng-content>\n<ng-content select=\"[md3-scaffold-rail=leading]\"></ng-content>\n\n<div class=\"md3-panes-container\" #panesContainer>\n <div class=\"md3-pane md3-pane-start\">\n <ng-content select=\"[md3-scaffold-pane=start]\"></ng-content>\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-main\">\n <ng-content select=\"[md3-scaffold-pane=main]\"></ng-content>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-content select=\"[md3-scaffold-pane=end]\"></ng-content>\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n</div>\n\n<!-- Standard bottom sheets dock here, between the content and the bottom bar. The region\n measures zero until one opens, so it reserves nothing the rest of the time. -->\n<div class=\"md3-bottom-sheet-region\">\n <ng-template #bottomOutlet cdkPortalOutlet></ng-template>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=trailing]\"></ng-content>\n<ng-content select=\"[md3-scaffold-bar=bottom]\"></ng-content>", styles: [":host{display:grid;width:100%;height:100dvh;min-height:0em;overflow:hidden;grid-template-areas:\"top top top\" \"start content end\" \"start sheet end\" \"bottom bottom bottom\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:auto minmax(0,1fr) auto auto}:host ::ng-deep [md3-scaffold-bar=top]{grid-area:top;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:2}:host ::ng-deep [md3-scaffold-rail=leading]{grid-area:start;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-rail=trailing]{grid-area:end;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-bar=bottom]{grid-area:bottom;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:2}:host .md3-bottom-sheet-region{grid-area:sheet;justify-self:stretch;min-width:0em;height:0em;position:relative;overflow:visible;z-index:4}:host .md3-panes-container{--background-color: rgb(var(--md-scheme-surface));--foreground-color: rgb(var(--md-scheme-on-surface));grid-area:content;min-width:0em;min-height:0em;overflow:hidden;background-color:var(--background-color);color:var(--foreground-color);display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;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}: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"] }] });
2009
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Scaffold, isStandalone: true, selector: "md3-scaffold", viewQueries: [{ propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "bottomOutlet", first: true, predicate: ["bottomOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "panesContainer", first: true, predicate: ["panesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"md3-bar-region md3-bar-region-top\">\n <ng-content select=\"[md3-scaffold-bar=top]\"></ng-content>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=leading]\"></ng-content>\n\n<div class=\"md3-panes-container\" #panesContainer>\n <div class=\"md3-pane md3-pane-start\">\n <ng-content select=\"[md3-scaffold-pane=start]\"></ng-content>\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-main\">\n <ng-content select=\"[md3-scaffold-pane=main]\"></ng-content>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-content select=\"[md3-scaffold-pane=end]\"></ng-content>\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n</div>\n\n<!-- Standard bottom sheets dock here, between the content and the bottom bar. The region\n measures zero until one opens, so it reserves nothing the rest of the time. -->\n<div class=\"md3-bottom-sheet-region\">\n <ng-template #bottomOutlet cdkPortalOutlet></ng-template>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=trailing]\"></ng-content>\n\n<div class=\"md3-bar-region md3-bar-region-bottom\">\n <ng-content select=\"[md3-scaffold-bar=bottom]\"></ng-content>\n</div>", styles: [":host{display:grid;width:100%;height:100dvh;min-height:0em;overflow:hidden;grid-template-areas:\"top top top\" \"start content end\" \"start sheet end\" \"bottom bottom bottom\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:auto minmax(0,1fr) auto auto}:host .md3-bar-region{display:flex;flex-direction:column;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:visible;z-index:2}:host .md3-bar-region.md3-bar-region-top{grid-area:top}:host .md3-bar-region.md3-bar-region-bottom{grid-area:bottom}:host ::ng-deep [md3-scaffold-bar=top],:host ::ng-deep [md3-scaffold-bar=bottom]{min-width:0em;min-height:0em;overflow:hidden}:host ::ng-deep [md3-scaffold-rail=leading]{grid-area:start;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-rail=trailing]{grid-area:end;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-bar].md3-floating-region,:host ::ng-deep [md3-scaffold-rail].md3-floating-region{overflow:visible}:host .md3-bottom-sheet-region{grid-area:sheet;justify-self:stretch;min-width:0em;height:0em;position:relative;overflow:visible;z-index:4}:host .md3-panes-container{--background-color: rgb(var(--md-scheme-surface));--foreground-color: rgb(var(--md-scheme-on-surface));grid-area:content;min-width:0em;min-height:0em;overflow:hidden;background-color:var(--background-color);color:var(--foreground-color);display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;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}: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"] }] });
1885
2010
  }
1886
2011
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Scaffold, decorators: [{
1887
2012
  type: Component,
1888
2013
  args: [{ selector: 'md3-scaffold', imports: [
1889
2014
  CdkPortalOutlet,
1890
- ], template: "<ng-content select=\"[md3-scaffold-bar=top]\"></ng-content>\n<ng-content select=\"[md3-scaffold-rail=leading]\"></ng-content>\n\n<div class=\"md3-panes-container\" #panesContainer>\n <div class=\"md3-pane md3-pane-start\">\n <ng-content select=\"[md3-scaffold-pane=start]\"></ng-content>\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-main\">\n <ng-content select=\"[md3-scaffold-pane=main]\"></ng-content>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-content select=\"[md3-scaffold-pane=end]\"></ng-content>\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n</div>\n\n<!-- Standard bottom sheets dock here, between the content and the bottom bar. The region\n measures zero until one opens, so it reserves nothing the rest of the time. -->\n<div class=\"md3-bottom-sheet-region\">\n <ng-template #bottomOutlet cdkPortalOutlet></ng-template>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=trailing]\"></ng-content>\n<ng-content select=\"[md3-scaffold-bar=bottom]\"></ng-content>", styles: [":host{display:grid;width:100%;height:100dvh;min-height:0em;overflow:hidden;grid-template-areas:\"top top top\" \"start content end\" \"start sheet end\" \"bottom bottom bottom\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:auto minmax(0,1fr) auto auto}:host ::ng-deep [md3-scaffold-bar=top]{grid-area:top;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:2}:host ::ng-deep [md3-scaffold-rail=leading]{grid-area:start;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-rail=trailing]{grid-area:end;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-bar=bottom]{grid-area:bottom;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:2}:host .md3-bottom-sheet-region{grid-area:sheet;justify-self:stretch;min-width:0em;height:0em;position:relative;overflow:visible;z-index:4}:host .md3-panes-container{--background-color: rgb(var(--md-scheme-surface));--foreground-color: rgb(var(--md-scheme-on-surface));grid-area:content;min-width:0em;min-height:0em;overflow:hidden;background-color:var(--background-color);color:var(--foreground-color);display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;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}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
1891
- }], propDecorators: { startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], bottomOutlet: [{ type: i0.ViewChild, args: ['bottomOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], panesContainer: [{ type: i0.ViewChild, args: ['panesContainer', { isSignal: true }] }] } });
2015
+ ], template: "<div class=\"md3-bar-region md3-bar-region-top\">\n <ng-content select=\"[md3-scaffold-bar=top]\"></ng-content>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=leading]\"></ng-content>\n\n<div class=\"md3-panes-container\" #panesContainer>\n <div class=\"md3-pane md3-pane-start\">\n <ng-content select=\"[md3-scaffold-pane=start]\"></ng-content>\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-main\">\n <ng-content select=\"[md3-scaffold-pane=main]\"></ng-content>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-content select=\"[md3-scaffold-pane=end]\"></ng-content>\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n</div>\n\n<!-- Standard bottom sheets dock here, between the content and the bottom bar. The region\n measures zero until one opens, so it reserves nothing the rest of the time. -->\n<div class=\"md3-bottom-sheet-region\">\n <ng-template #bottomOutlet cdkPortalOutlet></ng-template>\n</div>\n\n<ng-content select=\"[md3-scaffold-rail=trailing]\"></ng-content>\n\n<div class=\"md3-bar-region md3-bar-region-bottom\">\n <ng-content select=\"[md3-scaffold-bar=bottom]\"></ng-content>\n</div>", styles: [":host{display:grid;width:100%;height:100dvh;min-height:0em;overflow:hidden;grid-template-areas:\"top top top\" \"start content end\" \"start sheet end\" \"bottom bottom bottom\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:auto minmax(0,1fr) auto auto}:host .md3-bar-region{display:flex;flex-direction:column;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:visible;z-index:2}:host .md3-bar-region.md3-bar-region-top{grid-area:top}:host .md3-bar-region.md3-bar-region-bottom{grid-area:bottom}:host ::ng-deep [md3-scaffold-bar=top],:host ::ng-deep [md3-scaffold-bar=bottom]{min-width:0em;min-height:0em;overflow:hidden}:host ::ng-deep [md3-scaffold-rail=leading]{grid-area:start;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-rail=trailing]{grid-area:end;justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;overflow:hidden;z-index:3}:host ::ng-deep [md3-scaffold-bar].md3-floating-region,:host ::ng-deep [md3-scaffold-rail].md3-floating-region{overflow:visible}:host .md3-bottom-sheet-region{grid-area:sheet;justify-self:stretch;min-width:0em;height:0em;position:relative;overflow:visible;z-index:4}:host .md3-panes-container{--background-color: rgb(var(--md-scheme-surface));--foreground-color: rgb(var(--md-scheme-on-surface));grid-area:content;min-width:0em;min-height:0em;overflow:hidden;background-color:var(--background-color);color:var(--foreground-color);display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0em;min-height:0em;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}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
2016
+ }], ctorParameters: () => [], propDecorators: { startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], bottomOutlet: [{ type: i0.ViewChild, args: ['bottomOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], panesContainer: [{ type: i0.ViewChild, args: ['panesContainer', { isSignal: true }] }] } });
1892
2017
 
1893
2018
  class ScaffoldBar {
1894
2019
  region = input.required({ ...(ngDevMode ? { debugName: "region" } : /* istanbul ignore next */ {}), alias: 'md3-scaffold-bar' });
@@ -4739,9 +4864,10 @@ class AppBar {
4739
4864
  ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
4740
4865
  mainIsScrolled = computed(() => this.layoutService.mainIsScrolled(), /* @ts-ignore */
4741
4866
  ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
4742
- isScrollingDown = signal(false, /* @ts-ignore */
4867
+ // One source of truth. The toolbar reads the same signal, so the two bars can never
4868
+ // disagree about which way the main pane is moving.
4869
+ isScrollingDown = computed(() => this.layoutService.isScrollingDown(), /* @ts-ignore */
4743
4870
  ...(ngDevMode ? [{ debugName: "isScrollingDown" }] : /* istanbul ignore next */ []));
4744
- scrollPosition = 0;
4745
4871
  bottomExpandedHeight = computed(() => {
4746
4872
  const type = this.appBarType();
4747
4873
  if (!this.hasCollapsibleBottom(type)) {
@@ -4770,7 +4896,6 @@ class AppBar {
4770
4896
  constructor(el, layoutService) {
4771
4897
  this.el = el;
4772
4898
  this.layoutService = layoutService;
4773
- this.scrollPosition = this.layoutService.mainScrollTop();
4774
4899
  effect((onCleanup) => {
4775
4900
  const type = 'md3-' + this.appBarType();
4776
4901
  this.element.classList.add(type);
@@ -4792,9 +4917,6 @@ class AppBar {
4792
4917
  this.element.classList.remove(width);
4793
4918
  });
4794
4919
  });
4795
- effect(() => {
4796
- this.updateScrollDirection(this.layoutService.mainScrollTop());
4797
- });
4798
4920
  effect(() => {
4799
4921
  const collapse = this.bottomCollapse();
4800
4922
  const expandedHeight = this.bottomExpandedHeight();
@@ -4815,18 +4937,6 @@ class AppBar {
4815
4937
  isBottomCollapsed(collapse, expandedHeight) {
4816
4938
  return expandedHeight > 0 && collapse >= expandedHeight;
4817
4939
  }
4818
- updateScrollDirection(scrollTop) {
4819
- if (scrollTop === this.scrollPosition) {
4820
- return;
4821
- }
4822
- const defaultBarHeight = this.getHostFontSize() * 4;
4823
- const scrollOffset = scrollTop - this.scrollPosition;
4824
- if (Math.abs(scrollOffset) <= defaultBarHeight) {
4825
- return;
4826
- }
4827
- this.isScrollingDown.set(scrollOffset > 0);
4828
- this.scrollPosition = scrollTop;
4829
- }
4830
4940
  hasCollapsibleBottom(type) {
4831
4941
  return (type === 'medium' || type === 'large') &&
4832
4942
  (!!this.title()?.length || !!this.subtitle()?.length);
@@ -4864,6 +4974,407 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
4864
4974
  }, template: "<div class=\"md3-app-bar-container\">\n <div class=\"md3-app-bar-leading\">\n <ng-content select=\"[md3-app-bar-leading]\"></ng-content>\n </div>\n\n @if (appBarType() == 'search') {\n <div class=\"md3-app-bar-search\" [class.md3-center]=\"centerAligned()\">\n <div class=\"md3-search-container\">\n <div class=\"md3-leading-buttons\">\n <ng-content select=\"[md3-search-leading]\"></ng-content>\n </div>\n <ng-content select=\"[md3-input-element]\"></ng-content>\n <div class=\"md3-trailing-buttons\">\n <ng-content select=\"[md3-search-trailing]\"></ng-content>\n </div>\n </div>\n </div>\n } @else if (hasLogo()) {\n <div class=\"md3-app-bar-logo\" [class.md3-center]=\"centerAligned()\">\n <ng-content select=\"[md3-app-bar-logo]\"></ng-content>\n </div>\n } @else if (title() || subtitle()) {\n <div class=\"md3-app-bar-title\" [class.md3-center]=\"centerAligned()\">\n @if (title()?.length) {\n <div md3-type-title size=\"large\">{{ title() }}</div>\n }\n @if (subtitle()?.length) {\n <div md3-type-body size=\"small\" emphasized>{{ subtitle() }}</div>\n }\n </div>\n }\n\n <div class=\"md3-app-bar-trailing\">\n <ng-content select=\"[md3-app-bar-trailing]\"></ng-content>\n @if (hasAvatar()) {\n <div class=\"md3-app-bar-avatar\">\n <ng-content select=\"[md3-avatar]\"></ng-content>\n </div>\n }\n </div>\n\n @if ((appBarType() == 'medium' || appBarType() == 'large') && (title() || subtitle())) {\n <div class=\"md3-app-bar-bottom\" [class.md3-center]=\"centerAligned()\">\n <div class=\"md3-app-bar-bottom-content\">\n @if (appBarType() == 'medium') {\n @if (title()?.length) {\n <div md3-type-headline size=\"medium\">{{ title() }}</div>\n }\n @if (subtitle()?.length) {\n <div md3-type-title size=\"small\">{{ subtitle() }}</div>\n }\n }\n @if (appBarType() == 'large') {\n @if (title()?.length) {\n <div md3-type-display size=\"small\">{{ title() }}</div>\n }\n @if (subtitle()?.length) {\n <div md3-type-title size=\"medium\">{{ subtitle() }}</div>\n }\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{--background-color: rgb(var(--md-scheme-surface));--foreground-color: rgb(var(--md-scheme-on-surface));--search-background-color: rgb(var(--md-scheme-surface-container));--search-foreground-color: rgb(var(--md-scheme-on-surface));--foreground-secondary: rgb(var(--md-scheme-on-surface-variant));--elevation: var(--md-shadow-0dp);--app-bar-bottom-collapse: 0px;--app-bar-bottom-opacity: 1;display:block;min-height:0em;max-height:9.5em;overflow:hidden;background-color:var(--background-color);color:var(--foreground-color);box-shadow:var(--elevation);transition:all var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing)}:host .md3-app-bar-container{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:4em auto auto;min-height:4em;width:100%;background-color:inherit;color:inherit;transition:opacity var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing)}:host .md3-app-bar-container .md3-app-bar-leading,:host .md3-app-bar-container .md3-app-bar-trailing{grid-row:1;z-index:1;display:inline-flex;align-items:center;gap:.25em;min-inline-size:0;block-size:4em}:host .md3-app-bar-container .md3-app-bar-leading:empty,:host .md3-app-bar-container .md3-app-bar-trailing:empty{display:none}:host .md3-app-bar-container .md3-app-bar-leading .md3-app-bar-avatar,:host .md3-app-bar-container .md3-app-bar-leading ::ng-deep [md3-app-bar-leading],:host .md3-app-bar-container .md3-app-bar-leading ::ng-deep [md3-app-bar-trailing],:host .md3-app-bar-container .md3-app-bar-trailing .md3-app-bar-avatar,:host .md3-app-bar-container .md3-app-bar-trailing ::ng-deep [md3-app-bar-leading],:host .md3-app-bar-container .md3-app-bar-trailing ::ng-deep [md3-app-bar-trailing]{flex:0 0 auto;height:3em;min-width:3em;display:inline-flex;align-items:center;justify-content:center}:host .md3-app-bar-container .md3-app-bar-leading{grid-column:1;justify-self:start;padding-inline-start:.25em;padding-inline-end:.5em;min-width:1em}:host .md3-app-bar-container .md3-app-bar-leading:empty{display:inline-flex}:host .md3-app-bar-container .md3-app-bar-leading ::ng-deep [md3-app-bar-leading]{color:var(--foreground-color)}:host .md3-app-bar-container .md3-app-bar-leading ::ng-deep [md3-app-bar-leading] .md3-standard[md3-icon-button]{--foreground-color: var(--foreground-color)}:host .md3-app-bar-container .md3-app-bar-trailing{grid-column:3;justify-self:end;padding-inline-end:.25em}:host .md3-app-bar-container .md3-app-bar-trailing ::ng-deep [md3-app-bar-trailing]{color:var(--foreground-secondary)}:host .md3-app-bar-container .md3-app-bar-trailing ::ng-deep [md3-app-bar-trailing] .md3-standard[md3-icon-button]{--foreground-color: var(--foreground-secondary)}:host .md3-app-bar-container .md3-app-bar-trailing ::ng-deep .md3-avatar{flex:0 0 2em}:host .md3-app-bar-container .md3-app-bar-search{grid-column:1/-1;grid-row:1;align-self:center;display:flex;justify-content:center;min-inline-size:0;height:3em;padding:0 .5em}:host .md3-app-bar-container .md3-app-bar-search .md3-search-container{display:inline-flex;align-items:center;justify-content:center;width:50%;max-width:100%;border-radius:1.5em;background-color:var(--search-background-color);color:var(--search-foreground-color);transition:all var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing)}:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-leading-buttons,:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-trailing-buttons{flex:0 0 1.5em;pointer-events:none;display:inline-flex;gap:.25em;padding:0 .25em}:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-leading-buttons:empty,:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-trailing-buttons:empty{padding:0}:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-leading-buttons ::ng-deep [md3-search-leading],:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-leading-buttons ::ng-deep [md3-search-trailing],:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-trailing-buttons ::ng-deep [md3-search-leading],:host .md3-app-bar-container .md3-app-bar-search .md3-search-container .md3-trailing-buttons ::ng-deep [md3-search-trailing]{pointer-events:all}:host .md3-app-bar-container .md3-app-bar-search .md3-search-container ::ng-deep [md3-input-element]{flex:1 1 auto;background-color:transparent;color:var(--search-foreground-color);font-size:1em;height:100%;min-width:0em;border:none;padding:0 1.5em;margin:0 -1.5em}:host .md3-app-bar-container .md3-app-bar-search.md3-center .md3-search-container ::ng-deep [md3-input-element]{text-align:center}:host .md3-app-bar-container .md3-app-bar-logo{grid-column:2;grid-row:1;align-self:center;display:flex;justify-content:start;min-inline-size:0;overflow:hidden;height:3em}:host .md3-app-bar-container .md3-app-bar-logo.md3-center{grid-column:1/-1;justify-self:stretch;text-align:center;justify-content:center}:host .md3-app-bar-container .md3-app-bar-logo ::ng-deep a[md3-app-bar-logo],:host .md3-app-bar-container .md3-app-bar-logo ::ng-deep button[md3-app-bar-logo]{cursor:pointer}:host .md3-app-bar-container .md3-app-bar-logo ::ng-deep [md3-app-bar-logo]{flex:0 1 auto;max-height:100%;max-width:100%;display:block;border:none;background:transparent;font-size:1em;text-decoration:none;padding:0;margin:0}:host .md3-app-bar-container .md3-app-bar-logo ::ng-deep [md3-app-bar-logo]>*{display:inline-block;max-height:100%;max-width:100%;width:100%;height:100%;object-fit:contain}:host .md3-app-bar-container .md3-app-bar-title{grid-column:2;grid-row:1;align-self:center;min-inline-size:0;color:inherit;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;pointer-events:none;transition:all var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing);transform:scale(0);opacity:0}:host .md3-app-bar-container .md3-app-bar-title:dir(ltr){transform-origin:bottom left}:host .md3-app-bar-container .md3-app-bar-title:dir(rtl){transform-origin:bottom right}:host .md3-app-bar-container .md3-app-bar-title.md3-center{grid-column:1/-1;justify-self:stretch;text-align:center;transform-origin:bottom center}:host .md3-app-bar-container .md3-app-bar-title ::ng-deep [md3-app-bar-title]{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;pointer-events:all}:host .md3-app-bar-container .md3-app-bar-bottom{--app-bar-bottom-expanded-block-size: auto;grid-column:1/-1;grid-row:2;min-inline-size:0;min-block-size:0;overflow:hidden;transition:all var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing)}:host .md3-app-bar-container .md3-app-bar-bottom:empty{display:none}:host .md3-app-bar-container .md3-app-bar-bottom .md3-app-bar-bottom-content{padding-bottom:.75em;padding-inline-start:1em;padding-inline-end:.25em;opacity:var(--app-bar-bottom-opacity);transition:all var(--md-motion-standard-default-effects-duration) var(--md-motion-standard-default-effects-easing)}:host .md3-app-bar-container .md3-app-bar-bottom.md3-center .md3-app-bar-bottom-content{text-align:center;padding-inline:1em}:host.md3-scrolled.md3-scroll-style-elevate{--background-color: rgb(var(--md-scheme-surface-container));--search-background-color: rgb(var(--md-scheme-surface-container-highest));--elevation: var(--md-shadow-3dp)}:host.md3-scrolled.md3-scroll-style-transparent{--background-color: transparent}:host.md3-layout-medium .md3-app-bar-container .md3-app-bar-search{grid-column:2}:host.md3-layout-medium .md3-app-bar-container .md3-app-bar-search .md3-search-container{width:19.5em}:host.md3-layout-compact .md3-app-bar-container .md3-app-bar-search{grid-column:2}:host.md3-layout-compact .md3-app-bar-container .md3-app-bar-search .md3-search-container{width:100%}:host.md3-small .md3-app-bar-container .md3-app-bar-title,:host.md3-collapsed .md3-app-bar-container .md3-app-bar-title{transform:scale(1);opacity:1}:host.md3-medium .md3-app-bar-container .md3-app-bar-bottom{--app-bar-bottom-expanded-block-size: 3em;block-size:max(0px,var(--app-bar-bottom-expanded-block-size) - var(--app-bar-bottom-collapse))}:host.md3-medium .md3-app-bar-container .md3-app-bar-bottom:has(.md3-text-title.md3-text-small){--app-bar-bottom-expanded-block-size: 4.5em}:host.md3-medium .md3-app-bar-container .md3-app-bar-bottom .md3-app-bar-bottom-content .md3-text-title.md3-text-small{margin-top:.285715em}:host.md3-large .md3-app-bar-container .md3-app-bar-bottom{--app-bar-bottom-expanded-block-size: 3.5em;block-size:max(0px,var(--app-bar-bottom-expanded-block-size) - var(--app-bar-bottom-collapse))}:host.md3-large .md3-app-bar-container .md3-app-bar-bottom:has(.md3-text-title.md3-text-medium){--app-bar-bottom-expanded-block-size: 5.5em}:host.md3-large .md3-app-bar-container .md3-app-bar-bottom .md3-app-bar-bottom-content .md3-text-title.md3-text-medium{margin-top:.5em}:host.md3-scrolling-down.md3-auto-hide{max-height:0}:host.md3-scrolling-down.md3-auto-hide .md3-app-bar-container{opacity:0}\n"] }]
4865
4975
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: LayoutService }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar-title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar-subtitle", required: false }] }], appBarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar-type", required: false }] }], appBarScrollingStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "scroll-style", required: false }] }], autoHide: [{ type: i0.Input, args: [{ isSignal: true, alias: "auto-hide", required: false }] }], centerAligned: [{ type: i0.Input, args: [{ isSignal: true, alias: "center-aligned", required: false }] }], logo: [{ type: i0.ContentChild, args: [i0.forwardRef(() => AppBarLogo), { isSignal: true }] }], avatar: [{ type: i0.ContentChild, args: [i0.forwardRef(() => Avatar), { isSignal: true }] }] } });
4866
4976
 
4977
+ /**
4978
+ * Material 3 toolbar.
4979
+ *
4980
+ * The toolbar holds the actions of the current page. Put it in a scaffold region, and the
4981
+ * region decides where it goes:
4982
+ *
4983
+ * ```html
4984
+ * <md3-toolbar md3-scaffold-bar="bottom" toolbar-type="floating" scroll-action="collapse">
4985
+ * <md3-toolbar-item><button md3-icon-button>...</button></md3-toolbar-item>
4986
+ * <md3-toolbar-item md3-toolbar-persistent><button md3-icon-button>...</button></md3-toolbar-item>
4987
+ * <button md3-fab>...</button>
4988
+ * </md3-toolbar>
4989
+ * ```
4990
+ *
4991
+ * Every action goes inside an `md3-toolbar-item`. The toolbar projects that element only. A FAB is
4992
+ * the one exception: it sits beside the container, and a floating toolbar takes it.
4993
+ *
4994
+ * A **floating** toolbar in a *bar* region leaves the layout flow, so the content passes
4995
+ * behind it. The scaffold pads the main pane by the height it covers. In a *rail* region it
4996
+ * stays in the flow and reserves its own space, so no padding is necessary.
4997
+ *
4998
+ * A **docked** toolbar fills its region. The specification allows it in a bar region only.
4999
+ *
5000
+ * Group actions with `md3-button-group`. The toolbar has one slots region, and it keeps the
5001
+ * authored order. The space between the items follows the free space of the container, between
5002
+ * `--md-toolbar-gap-min` and `--md-toolbar-gap-max`.
5003
+ */
5004
+ class Toolbar {
5005
+ el = inject(ElementRef);
5006
+ layout = inject(LayoutService);
5007
+ // The scaffold region directives sit on this same host element, so `self` is correct.
5008
+ scaffoldBar = inject(ScaffoldBar, { optional: true, self: true });
5009
+ scaffoldRail = inject(ScaffoldRail, { optional: true, self: true });
5010
+ toolbarType = input('floating', { ...(ngDevMode ? { debugName: "toolbarType" } : /* istanbul ignore next */ {}), alias: 'toolbar-type' });
5011
+ toolbarColor = input('standard', { ...(ngDevMode ? { debugName: "toolbarColor" } : /* istanbul ignore next */ {}), alias: 'toolbar-color' });
5012
+ /**
5013
+ * Leave this unset to follow the region. A rail region gives `vertical`, and every other
5014
+ * placement gives `horizontal`. Read `effectiveOrientation` for the resolved value.
5015
+ */
5016
+ orientation = input(null, { ...(ngDevMode ? { debugName: "orientation" } : /* istanbul ignore next */ {}), alias: 'orientation' });
5017
+ alignment = input('center', { ...(ngDevMode ? { debugName: "alignment" } : /* istanbul ignore next */ {}), alias: 'alignment' });
5018
+ scrollAction = input('none', { ...(ngDevMode ? { debugName: "scrollAction" } : /* istanbul ignore next */ {}), alias: 'scroll-action' });
5019
+ fabPosition = input('end', { ...(ngDevMode ? { debugName: "fabPosition" } : /* istanbul ignore next */ {}), alias: 'fab-position' });
5020
+ /** The collapse state. Scrolling writes to it, and you can read or set it yourself. */
5021
+ expanded = model(true, /* @ts-ignore */
5022
+ ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
5023
+ layoutElement = viewChild('layout', /* @ts-ignore */
5024
+ ...(ngDevMode ? [{ debugName: "layoutElement" }] : /* istanbul ignore next */ []));
5025
+ containerElement = viewChild('container', /* @ts-ignore */
5026
+ ...(ngDevMode ? [{ debugName: "containerElement" }] : /* istanbul ignore next */ []));
5027
+ slotsElement = viewChild('slots', /* @ts-ignore */
5028
+ ...(ngDevMode ? [{ debugName: "slotsElement" }] : /* istanbul ignore next */ []));
5029
+ fab = contentChild(FloatingActionButton, /* @ts-ignore */
5030
+ ...(ngDevMode ? [{ debugName: "fab" }] : /* istanbul ignore next */ []));
5031
+ /** Set from the DOM, because `md3-toolbar-persistent` is a plain attribute, not a directive. */
5032
+ hasPersistentItem = signal(false, /* @ts-ignore */
5033
+ ...(ngDevMode ? [{ debugName: "hasPersistentItem" }] : /* istanbul ignore next */ []));
5034
+ hasFocusWithin = signal(false, /* @ts-ignore */
5035
+ ...(ngDevMode ? [{ debugName: "hasFocusWithin" }] : /* istanbul ignore next */ []));
5036
+ persistentObserver;
5037
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
5038
+ /** The last published free space, to keep an unchanged measurement from writing to the DOM. */
5039
+ lastGap = -1;
5040
+ isFloating = computed(() => this.toolbarType() === 'floating', /* @ts-ignore */
5041
+ ...(ngDevMode ? [{ debugName: "isFloating" }] : /* istanbul ignore next */ []));
5042
+ effectiveOrientation = computed(() => {
5043
+ return this.orientation() ?? (this.scaffoldRail ? 'vertical' : 'horizontal');
5044
+ }, /* @ts-ignore */
5045
+ ...(ngDevMode ? [{ debugName: "effectiveOrientation" }] : /* istanbul ignore next */ []));
5046
+ /** The logical side of the scaffold region, or null outside a scaffold. */
5047
+ region = computed(() => {
5048
+ if (this.scaffoldBar) {
5049
+ return this.scaffoldBar.region() === 'top' ? 'blockStart' : 'blockEnd';
5050
+ }
5051
+ if (this.scaffoldRail) {
5052
+ return this.scaffoldRail.region() === 'leading' ? 'inlineStart' : 'inlineEnd';
5053
+ }
5054
+ return null;
5055
+ }, /* @ts-ignore */
5056
+ ...(ngDevMode ? [{ debugName: "region" }] : /* istanbul ignore next */ []));
5057
+ isBarRegion = computed(() => !!this.scaffoldBar, /* @ts-ignore */
5058
+ ...(ngDevMode ? [{ debugName: "isBarRegion" }] : /* istanbul ignore next */ []));
5059
+ isRailRegion = computed(() => !!this.scaffoldRail, /* @ts-ignore */
5060
+ ...(ngDevMode ? [{ debugName: "isRailRegion" }] : /* istanbul ignore next */ []));
5061
+ /** A floating toolbar inside a scaffold region needs the region to stop clipping it. */
5062
+ isFloatingRegion = computed(() => {
5063
+ return this.isFloating() && (this.isBarRegion() || this.isRailRegion());
5064
+ }, /* @ts-ignore */
5065
+ ...(ngDevMode ? [{ debugName: "isFloatingRegion" }] : /* istanbul ignore next */ []));
5066
+ /** Only a floating bar covers content it does not reserve. Everything else reserves its space. */
5067
+ coversContent = computed(() => this.isFloating() && this.isBarRegion(), /* @ts-ignore */
5068
+ ...(ngDevMode ? [{ debugName: "coversContent" }] : /* istanbul ignore next */ []));
5069
+ /** Something must survive a collapse, or a collapse is just a hide. */
5070
+ canCollapse = computed(() => (!!this.fab() && this.isFloating()) || this.hasPersistentItem(), /* @ts-ignore */
5071
+ ...(ngDevMode ? [{ debugName: "canCollapse" }] : /* istanbul ignore next */ []));
5072
+ /** With a FAB and no marked item, a collapse takes the container away and the FAB stays alone. */
5073
+ collapsesToFab = computed(() => !!this.fab() && this.isFloating() && !this.hasPersistentItem(), /* @ts-ignore */
5074
+ ...(ngDevMode ? [{ debugName: "collapsesToFab" }] : /* istanbul ignore next */ []));
5075
+ /** A vertical toolbar never reacts to scrolling, and a docked one never collapses. */
5076
+ resolvedScrollAction = computed(() => {
5077
+ const action = this.scrollAction();
5078
+ if (action === 'none' || this.effectiveOrientation() === 'vertical') {
5079
+ return 'none';
5080
+ }
5081
+ if (action === 'collapse' && (!this.isFloating() || !this.canCollapse())) {
5082
+ return 'hide';
5083
+ }
5084
+ return action;
5085
+ }, /* @ts-ignore */
5086
+ ...(ngDevMode ? [{ debugName: "resolvedScrollAction" }] : /* istanbul ignore next */ []));
5087
+ isHidden = signal(false, /* @ts-ignore */
5088
+ ...(ngDevMode ? [{ debugName: "isHidden" }] : /* istanbul ignore next */ []));
5089
+ isCollapsed = computed(() => {
5090
+ return this.resolvedScrollAction() === 'collapse' && !this.expanded();
5091
+ }, /* @ts-ignore */
5092
+ ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
5093
+ /**
5094
+ * The collapsed state in which the FAB stays alone.
5095
+ *
5096
+ * This is the state, not the capability. A FAB by itself must never take the container
5097
+ * away, because a toolbar that does not collapse keeps its items at all times.
5098
+ */
5099
+ isCollapsedToFab = computed(() => this.isCollapsed() && this.collapsesToFab(), /* @ts-ignore */
5100
+ ...(ngDevMode ? [{ debugName: "isCollapsedToFab" }] : /* istanbul ignore next */ []));
5101
+ // button context — the container is 4em high, so the buttons inside it are small.
5102
+ buttonContextSize = signal('small', /* @ts-ignore */
5103
+ ...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
5104
+ constructor() {
5105
+ effect(() => {
5106
+ if (this.isFloating()) {
5107
+ this.element.classList.add('md3-floating');
5108
+ this.element.classList.remove('md3-docked');
5109
+ }
5110
+ else {
5111
+ this.element.classList.add('md3-docked');
5112
+ this.element.classList.remove('md3-floating');
5113
+ }
5114
+ });
5115
+ effect((onCleanup) => {
5116
+ const orientation = 'md3-' + this.effectiveOrientation();
5117
+ this.element.classList.add(orientation);
5118
+ onCleanup(() => this.element.classList.remove(orientation));
5119
+ });
5120
+ effect((onCleanup) => {
5121
+ const color = 'md3-color-' + this.toolbarColor();
5122
+ this.element.classList.add(color);
5123
+ onCleanup(() => this.element.classList.remove(color));
5124
+ });
5125
+ effect((onCleanup) => {
5126
+ const alignment = 'md3-align-' + this.alignment();
5127
+ this.element.classList.add(alignment);
5128
+ onCleanup(() => this.element.classList.remove(alignment));
5129
+ });
5130
+ effect((onCleanup) => {
5131
+ const position = 'md3-fab-' + this.fabPosition();
5132
+ this.element.classList.add(position);
5133
+ onCleanup(() => this.element.classList.remove(position));
5134
+ });
5135
+ effect((onCleanup) => {
5136
+ const region = this.region();
5137
+ if (!region) {
5138
+ return;
5139
+ }
5140
+ const name = 'md3-region-' + region.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase());
5141
+ this.element.classList.add(name);
5142
+ onCleanup(() => this.element.classList.remove(name));
5143
+ });
5144
+ // Report what a floating bar covers, so the scaffold can pad the main pane and the
5145
+ // overlays can stay above it.
5146
+ effect((onCleanup) => {
5147
+ if (!this.coversContent()) {
5148
+ return;
5149
+ }
5150
+ const region = this.region();
5151
+ if (region !== 'blockStart' && region !== 'blockEnd') {
5152
+ return;
5153
+ }
5154
+ const element = this.layoutElement()?.nativeElement;
5155
+ if (!element) {
5156
+ return;
5157
+ }
5158
+ this.layout.registerFloatingBar(element, region);
5159
+ onCleanup(() => this.layout.unregisterFloatingBar(element));
5160
+ });
5161
+ effect(() => {
5162
+ this.updateScrollState();
5163
+ });
5164
+ effect(() => {
5165
+ const element = this.layoutElement()?.nativeElement;
5166
+ if (element) {
5167
+ this.watchPersistentItems(element);
5168
+ }
5169
+ });
5170
+ // Measure again when the region gives the toolbar a different amount of space, and when
5171
+ // the items themselves change size or number.
5172
+ effect((onCleanup) => {
5173
+ if (!this.isBrowser) {
5174
+ return;
5175
+ }
5176
+ // Read the state that changes the geometry, so a new orientation or a collapse
5177
+ // measures again without a resize.
5178
+ this.effectiveOrientation();
5179
+ this.isCollapsed();
5180
+ this.isCollapsedToFab();
5181
+ const layout = this.layoutElement()?.nativeElement;
5182
+ const slots = this.slotsElement()?.nativeElement;
5183
+ if (!layout || !slots) {
5184
+ return;
5185
+ }
5186
+ // The observer reports the first size as soon as it starts, so no separate initial
5187
+ // measurement is necessary.
5188
+ const observer = new ResizeObserver(() => this.measureGap());
5189
+ observer.observe(this.element);
5190
+ observer.observe(layout);
5191
+ observer.observe(slots);
5192
+ onCleanup(() => observer.disconnect());
5193
+ });
5194
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
5195
+ effect(() => this.checkConfiguration());
5196
+ }
5197
+ }
5198
+ ngOnDestroy() {
5199
+ // The registration effect owns its own cleanup, so it unregisters the exact element
5200
+ // it measured.
5201
+ this.persistentObserver?.disconnect();
5202
+ this.persistentObserver = undefined;
5203
+ }
5204
+ get element() {
5205
+ return this.el.nativeElement;
5206
+ }
5207
+ onFocusIn() {
5208
+ this.hasFocusWithin.set(true);
5209
+ }
5210
+ onFocusOut(event) {
5211
+ const next = event.relatedTarget;
5212
+ if (next && this.element.contains(next)) {
5213
+ return;
5214
+ }
5215
+ this.hasFocusWithin.set(false);
5216
+ }
5217
+ updateScrollState() {
5218
+ const action = this.resolvedScrollAction();
5219
+ if (action === 'none') {
5220
+ this.isHidden.set(false);
5221
+ this.expanded.set(true);
5222
+ return;
5223
+ }
5224
+ // Keep the toolbar reachable while it holds the focus. A keyboard or screen-reader
5225
+ // user must never lose the control they are on.
5226
+ if (this.hasFocusWithin()) {
5227
+ this.isHidden.set(false);
5228
+ this.expanded.set(true);
5229
+ return;
5230
+ }
5231
+ const away = this.layout.mainIsScrolled() && this.layout.isScrollingDown();
5232
+ this.isHidden.set(action === 'hide' && away);
5233
+ this.expanded.set(action === 'hide' ? true : !away);
5234
+ }
5235
+ /**
5236
+ * Divide the free space of the container between the gaps.
5237
+ *
5238
+ * The measurement starts from the host, because the host holds the space the region gives
5239
+ * the toolbar. A floating container is only as wide as its content, so reading the container
5240
+ * itself would feed the gap back into the measurement and the value would never settle.
5241
+ */
5242
+ measureGap() {
5243
+ const layout = this.layoutElement()?.nativeElement;
5244
+ const container = this.containerElement()?.nativeElement;
5245
+ const slots = this.slotsElement()?.nativeElement;
5246
+ if (!layout || !container || !slots) {
5247
+ return;
5248
+ }
5249
+ const vertical = this.effectiveOrientation() === 'vertical';
5250
+ const items = Array.from(slots.children);
5251
+ const extents = items.map((item) => this.extent(item, vertical));
5252
+ // A collapsed item keeps its box but loses its size, and it must not keep a gap either.
5253
+ const visible = extents.filter((extent) => extent > 0.5).length;
5254
+ if (visible < 2) {
5255
+ this.publishGap(0);
5256
+ return;
5257
+ }
5258
+ const content = extents.reduce((sum, extent) => sum + extent, 0);
5259
+ const free = this.contentExtent(this.element, vertical)
5260
+ - this.paddingExtent(layout, vertical)
5261
+ - this.siblingExtent(layout, container, vertical)
5262
+ - this.paddingExtent(container, vertical)
5263
+ - content;
5264
+ this.publishGap(free / (visible - 1));
5265
+ }
5266
+ publishGap(gap) {
5267
+ // Round down, so a fraction of a pixel never pushes the last item past the container.
5268
+ const value = Math.max(0, Math.floor(gap * 100) / 100);
5269
+ if (value === this.lastGap) {
5270
+ return;
5271
+ }
5272
+ this.lastGap = value;
5273
+ this.element.style.setProperty('--md-toolbar-gap-free', `${value}px`);
5274
+ }
5275
+ extent(element, vertical) {
5276
+ const rect = element.getBoundingClientRect();
5277
+ return vertical ? rect.height : rect.width;
5278
+ }
5279
+ contentExtent(element, vertical) {
5280
+ const size = vertical ? element.clientHeight : element.clientWidth;
5281
+ return Math.max(0, size - this.paddingExtent(element, vertical));
5282
+ }
5283
+ paddingExtent(element, vertical) {
5284
+ const style = getComputedStyle(element);
5285
+ const start = parseFloat(vertical ? style.paddingTop : style.paddingLeft) || 0;
5286
+ const end = parseFloat(vertical ? style.paddingBottom : style.paddingRight) || 0;
5287
+ return start + end;
5288
+ }
5289
+ /** What the other children of the layout take, the flex gap that separates them included. */
5290
+ siblingExtent(layout, container, vertical) {
5291
+ const style = getComputedStyle(layout);
5292
+ const gap = parseFloat(vertical ? style.rowGap : style.columnGap) || 0;
5293
+ return Array.from(layout.children)
5294
+ .filter((child) => child !== container)
5295
+ .reduce((sum, child) => sum + this.extent(child, vertical) + gap, 0);
5296
+ }
5297
+ watchPersistentItems(element) {
5298
+ this.persistentObserver?.disconnect();
5299
+ const update = () => {
5300
+ this.hasPersistentItem.set(!!element.querySelector('.md3-toolbar-slots [md3-toolbar-persistent]'));
5301
+ };
5302
+ update();
5303
+ if (typeof MutationObserver === 'undefined') {
5304
+ return;
5305
+ }
5306
+ this.persistentObserver = new MutationObserver(update);
5307
+ this.persistentObserver.observe(element, {
5308
+ childList: true,
5309
+ subtree: true,
5310
+ attributeFilter: ['md3-toolbar-persistent'],
5311
+ });
5312
+ }
5313
+ checkConfiguration() {
5314
+ const explicit = this.orientation();
5315
+ const orientation = this.effectiveOrientation();
5316
+ if (this.isRailRegion() && !this.isFloating()) {
5317
+ this.warn('a docked toolbar needs the full window width, so it belongs in a scaffold bar region, not a rail.');
5318
+ }
5319
+ if (explicit === 'horizontal' && this.isRailRegion()) {
5320
+ this.warn('a horizontal toolbar does not fit a scaffold rail region. Move it to a bar region, or drop the orientation input.');
5321
+ }
5322
+ if (explicit === 'vertical' && this.isBarRegion()) {
5323
+ this.warn('a vertical toolbar does not fit a scaffold bar region. Move it to a rail region, or drop the orientation input.');
5324
+ }
5325
+ if (this.scrollAction() !== 'none' && orientation === 'vertical') {
5326
+ this.warn('a vertical toolbar ignores scroll-action.');
5327
+ }
5328
+ if (this.scrollAction() === 'collapse' && this.isFloating() && !this.canCollapse()) {
5329
+ this.warn('scroll-action="collapse" needs a FAB, or one item with the md3-toolbar-persistent attribute. The toolbar will hide instead.');
5330
+ }
5331
+ if (this.scrollAction() === 'collapse' && !this.isFloating()) {
5332
+ this.warn('a docked toolbar cannot collapse to a FAB. The toolbar will hide instead.');
5333
+ }
5334
+ }
5335
+ warn(message) {
5336
+ console.warn(`[md3-toolbar] ${message}`);
5337
+ }
5338
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Toolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
5339
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Toolbar, isStandalone: true, selector: "md3-toolbar", inputs: { toolbarType: { classPropertyName: "toolbarType", publicName: "toolbar-type", isSignal: true, isRequired: false, transformFunction: null }, toolbarColor: { classPropertyName: "toolbarColor", publicName: "toolbar-color", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, alignment: { classPropertyName: "alignment", publicName: "alignment", isSignal: true, isRequired: false, transformFunction: null }, scrollAction: { classPropertyName: "scrollAction", publicName: "scroll-action", isSignal: true, isRequired: false, transformFunction: null }, fabPosition: { classPropertyName: "fabPosition", publicName: "fab-position", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { attributes: { "role": "toolbar" }, listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut($event)" }, properties: { "attr.aria-orientation": "effectiveOrientation()", "class.md3-floating-region": "isFloatingRegion()", "class.md3-bar-region": "isBarRegion()", "class.md3-rail-region": "isRailRegion()", "class.md3-hidden": "isHidden()", "class.md3-collapsed": "isCollapsed()", "class.md3-collapse-to-fab": "isCollapsedToFab()" } }, providers: [
5340
+ {
5341
+ provide: MD3_BUTTON_CONTEXT,
5342
+ useExisting: Toolbar,
5343
+ },
5344
+ ], queries: [{ propertyName: "fab", first: true, predicate: FloatingActionButton, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "layoutElement", first: true, predicate: ["layout"], descendants: true, isSignal: true }, { propertyName: "containerElement", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "slotsElement", first: true, predicate: ["slots"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"md3-toolbar-layout\" #layout>\n @if (isFloating()) {\n <ng-content select=\"[md3-fab]\"></ng-content>\n }\n \n <div class=\"md3-toolbar-container\" #container>\n <div class=\"md3-toolbar-slots\" #slots>\n <ng-content select=\"md3-toolbar-item\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{--md-toolbar-size: 4em;--md-toolbar-padding: .5em;--md-toolbar-radius: var(--md-toolbar-size);--md-toolbar-shadow: var(--md-shadow-3dp);--md-toolbar-item-max-size: 20em;--md-toolbar-gap-min: .25em;--md-toolbar-gap-max: 2em;--md-toolbar-gap: clamp(var(--md-toolbar-gap-min), var(--md-toolbar-gap-free, 0px), var(--md-toolbar-gap-max));--md-toolbar-duration: var(--md-motion-expressive-default-spatial-duration);--md-toolbar-easing: var(--md-motion-expressive-default-spatial-easing);--md-toolbar-effect-duration: var(--md-motion-expressive-fast-effects-duration);--background-color: rgb(var(--md-scheme-surface-container));--foreground-color: rgb(var(--md-scheme-on-surface));display:block;position:relative;min-width:0em;min-height:0em;transition:max-height var(--md-toolbar-duration) var(--md-toolbar-easing),max-width var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-duration) var(--md-toolbar-easing)}:host .md3-toolbar-layout{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:var(--md-toolbar-padding);width:100%;height:100%;min-width:0em;min-height:0em;transition:transform var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-duration) var(--md-toolbar-easing)}:host .md3-toolbar-layout .md3-toolbar-container{display:flex;flex-direction:row;align-items:center;min-width:0em;min-height:0em;max-width:100%;max-height:100%;border-radius:var(--md-toolbar-radius);background-color:var(--background-color);color:var(--foreground-color);box-shadow:var(--md-toolbar-shadow);overflow:hidden;pointer-events:auto;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),box-shadow var(--md-toolbar-effect-duration) linear,opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear}:host .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots{display:flex;flex:0 1 auto;flex-direction:row;align-items:center;min-width:0em;min-height:0em}:host .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),margin var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear}:host.md3-fab-start ::ng-deep [md3-fab]{order:-1}:host.md3-fab-end ::ng-deep [md3-fab]{order:1}:host.md3-docked{--md-toolbar-radius: var(--md-border-radius-none);--md-toolbar-shadow: var(--md-shadow-0dp);background-color:var(--background-color)}:host.md3-docked.md3-align-start .md3-toolbar-layout .md3-toolbar-container{justify-content:start}:host.md3-docked.md3-align-center .md3-toolbar-layout .md3-toolbar-container{justify-content:center}:host.md3-docked.md3-align-end .md3-toolbar-layout .md3-toolbar-container{justify-content:end}:host.md3-docked .md3-toolbar-layout{width:100%;height:100%}:host.md3-docked .md3-toolbar-layout .md3-toolbar-container{background-color:transparent}:host.md3-floating.md3-align-start .md3-toolbar-layout{justify-content:start}:host.md3-floating.md3-align-center .md3-toolbar-layout{justify-content:center}:host.md3-floating.md3-align-end .md3-toolbar-layout{justify-content:end}:host.md3-floating .md3-toolbar-layout{position:absolute;inset:0;pointer-events:none}:host.md3-floating .md3-toolbar-layout .md3-toolbar-container{pointer-events:auto}:host.md3-floating .md3-toolbar-layout ::ng-deep [md3-fab]{pointer-events:auto}:host.md3-horizontal{max-height:var(--md-toolbar-size)}:host.md3-horizontal .md3-toolbar-layout{height:var(--md-toolbar-size);padding:0 1em}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container{height:var(--md-toolbar-size)}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{max-width:var(--md-toolbar-item-max-size);min-width:3em}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item+md3-toolbar-item{margin-inline-start:var(--md-toolbar-gap)}:host.md3-horizontal.md3-docked .md3-toolbar-layout .md3-toolbar-container{width:100%}:host.md3-horizontal.md3-floating{height:0}:host.md3-horizontal.md3-floating .md3-toolbar-layout .md3-toolbar-container{padding:0 var(--md-toolbar-padding)}:host.md3-horizontal.md3-floating.md3-region-block-end .md3-toolbar-layout{inset-block-start:auto;inset-block-end:1em}:host.md3-horizontal.md3-floating.md3-region-block-start .md3-toolbar-layout{inset-block-end:auto;inset-block-start:1em}:host.md3-vertical{max-width:var(--md-toolbar-size)}:host.md3-vertical .md3-toolbar-layout{flex-direction:column;width:var(--md-toolbar-size);padding:1em 0}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container{flex-direction:column;width:var(--md-toolbar-size)}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots{flex-direction:column;width:100%;height:auto}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{max-height:var(--md-toolbar-item-max-size);min-height:3em}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item+md3-toolbar-item{margin-block-start:var(--md-toolbar-gap)}:host.md3-vertical.md3-docked .md3-toolbar-layout .md3-toolbar-container{height:100%}:host.md3-vertical.md3-floating{width:0}:host.md3-vertical.md3-floating .md3-toolbar-layout .md3-toolbar-container{padding:var(--md-toolbar-padding) 0}:host.md3-vertical.md3-floating.md3-region-inline-end .md3-toolbar-layout{inset-inline-start:auto;inset-inline-end:1em}:host.md3-vertical.md3-floating.md3-region-inline-start .md3-toolbar-layout{inset-inline-end:auto;inset-inline-start:1em}:host.md3-hidden{opacity:0;pointer-events:none}:host.md3-hidden.md3-horizontal{max-height:0em}:host.md3-hidden.md3-vertical{max-width:0em}:host.md3-hidden .md3-toolbar-layout{transform:scaleY(0)}:host.md3-collapsed{--md-toolbar-gap: 0em}:host.md3-collapsed .md3-toolbar-container .md3-toolbar-slots>::ng-deep md3-toolbar-item:not([md3-toolbar-persistent]){max-width:0em!important;max-height:0em!important;min-width:0em!important;min-height:0em!important;margin:0;padding-inline:0em;border-width:0em;opacity:0;visibility:hidden;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),max-height var(--md-toolbar-duration) var(--md-toolbar-easing),margin var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear var(--md-toolbar-duration)}:host.md3-collapsed.md3-collapse-to-fab{--md-toolbar-padding: 0}:host.md3-collapsed.md3-collapse-to-fab .md3-toolbar-container{max-width:0em;opacity:0;visibility:hidden;pointer-events:none;box-shadow:var(--md-shadow-0dp);transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),box-shadow var(--md-toolbar-effect-duration) linear,opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear var(--md-toolbar-duration)}:host.md3-color-vibrant{--background-color: rgb(var(--md-scheme-primary-container));--foreground-color: rgb(var(--md-scheme-on-primary-container))}:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-standard,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-outlined,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-text,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-outlined{--foreground-color: rgb(var(--md-scheme-on-primary-container))}:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-tonal,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-tonal{--background-color: rgb(var(--md-scheme-surface-container));--foreground-color: rgb(var(--md-scheme-on-surface))}\n"] });
5345
+ }
5346
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Toolbar, decorators: [{
5347
+ type: Component,
5348
+ args: [{ selector: 'md3-toolbar', providers: [
5349
+ {
5350
+ provide: MD3_BUTTON_CONTEXT,
5351
+ useExisting: Toolbar,
5352
+ },
5353
+ ], host: {
5354
+ 'role': 'toolbar',
5355
+ '[attr.aria-orientation]': 'effectiveOrientation()',
5356
+ '[class.md3-floating-region]': 'isFloatingRegion()',
5357
+ '[class.md3-bar-region]': 'isBarRegion()',
5358
+ '[class.md3-rail-region]': 'isRailRegion()',
5359
+ '[class.md3-hidden]': 'isHidden()',
5360
+ '[class.md3-collapsed]': 'isCollapsed()',
5361
+ '[class.md3-collapse-to-fab]': 'isCollapsedToFab()',
5362
+ '(focusin)': 'onFocusIn()',
5363
+ '(focusout)': 'onFocusOut($event)',
5364
+ }, template: "<div class=\"md3-toolbar-layout\" #layout>\n @if (isFloating()) {\n <ng-content select=\"[md3-fab]\"></ng-content>\n }\n \n <div class=\"md3-toolbar-container\" #container>\n <div class=\"md3-toolbar-slots\" #slots>\n <ng-content select=\"md3-toolbar-item\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{--md-toolbar-size: 4em;--md-toolbar-padding: .5em;--md-toolbar-radius: var(--md-toolbar-size);--md-toolbar-shadow: var(--md-shadow-3dp);--md-toolbar-item-max-size: 20em;--md-toolbar-gap-min: .25em;--md-toolbar-gap-max: 2em;--md-toolbar-gap: clamp(var(--md-toolbar-gap-min), var(--md-toolbar-gap-free, 0px), var(--md-toolbar-gap-max));--md-toolbar-duration: var(--md-motion-expressive-default-spatial-duration);--md-toolbar-easing: var(--md-motion-expressive-default-spatial-easing);--md-toolbar-effect-duration: var(--md-motion-expressive-fast-effects-duration);--background-color: rgb(var(--md-scheme-surface-container));--foreground-color: rgb(var(--md-scheme-on-surface));display:block;position:relative;min-width:0em;min-height:0em;transition:max-height var(--md-toolbar-duration) var(--md-toolbar-easing),max-width var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-duration) var(--md-toolbar-easing)}:host .md3-toolbar-layout{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:var(--md-toolbar-padding);width:100%;height:100%;min-width:0em;min-height:0em;transition:transform var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-duration) var(--md-toolbar-easing)}:host .md3-toolbar-layout .md3-toolbar-container{display:flex;flex-direction:row;align-items:center;min-width:0em;min-height:0em;max-width:100%;max-height:100%;border-radius:var(--md-toolbar-radius);background-color:var(--background-color);color:var(--foreground-color);box-shadow:var(--md-toolbar-shadow);overflow:hidden;pointer-events:auto;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),box-shadow var(--md-toolbar-effect-duration) linear,opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear}:host .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots{display:flex;flex:0 1 auto;flex-direction:row;align-items:center;min-width:0em;min-height:0em}:host .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),margin var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear}:host.md3-fab-start ::ng-deep [md3-fab]{order:-1}:host.md3-fab-end ::ng-deep [md3-fab]{order:1}:host.md3-docked{--md-toolbar-radius: var(--md-border-radius-none);--md-toolbar-shadow: var(--md-shadow-0dp);background-color:var(--background-color)}:host.md3-docked.md3-align-start .md3-toolbar-layout .md3-toolbar-container{justify-content:start}:host.md3-docked.md3-align-center .md3-toolbar-layout .md3-toolbar-container{justify-content:center}:host.md3-docked.md3-align-end .md3-toolbar-layout .md3-toolbar-container{justify-content:end}:host.md3-docked .md3-toolbar-layout{width:100%;height:100%}:host.md3-docked .md3-toolbar-layout .md3-toolbar-container{background-color:transparent}:host.md3-floating.md3-align-start .md3-toolbar-layout{justify-content:start}:host.md3-floating.md3-align-center .md3-toolbar-layout{justify-content:center}:host.md3-floating.md3-align-end .md3-toolbar-layout{justify-content:end}:host.md3-floating .md3-toolbar-layout{position:absolute;inset:0;pointer-events:none}:host.md3-floating .md3-toolbar-layout .md3-toolbar-container{pointer-events:auto}:host.md3-floating .md3-toolbar-layout ::ng-deep [md3-fab]{pointer-events:auto}:host.md3-horizontal{max-height:var(--md-toolbar-size)}:host.md3-horizontal .md3-toolbar-layout{height:var(--md-toolbar-size);padding:0 1em}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container{height:var(--md-toolbar-size)}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{max-width:var(--md-toolbar-item-max-size);min-width:3em}:host.md3-horizontal .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item+md3-toolbar-item{margin-inline-start:var(--md-toolbar-gap)}:host.md3-horizontal.md3-docked .md3-toolbar-layout .md3-toolbar-container{width:100%}:host.md3-horizontal.md3-floating{height:0}:host.md3-horizontal.md3-floating .md3-toolbar-layout .md3-toolbar-container{padding:0 var(--md-toolbar-padding)}:host.md3-horizontal.md3-floating.md3-region-block-end .md3-toolbar-layout{inset-block-start:auto;inset-block-end:1em}:host.md3-horizontal.md3-floating.md3-region-block-start .md3-toolbar-layout{inset-block-end:auto;inset-block-start:1em}:host.md3-vertical{max-width:var(--md-toolbar-size)}:host.md3-vertical .md3-toolbar-layout{flex-direction:column;width:var(--md-toolbar-size);padding:1em 0}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container{flex-direction:column;width:var(--md-toolbar-size)}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots{flex-direction:column;width:100%;height:auto}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item{max-height:var(--md-toolbar-item-max-size);min-height:3em}:host.md3-vertical .md3-toolbar-layout .md3-toolbar-container .md3-toolbar-slots ::ng-deep>md3-toolbar-item+md3-toolbar-item{margin-block-start:var(--md-toolbar-gap)}:host.md3-vertical.md3-docked .md3-toolbar-layout .md3-toolbar-container{height:100%}:host.md3-vertical.md3-floating{width:0}:host.md3-vertical.md3-floating .md3-toolbar-layout .md3-toolbar-container{padding:var(--md-toolbar-padding) 0}:host.md3-vertical.md3-floating.md3-region-inline-end .md3-toolbar-layout{inset-inline-start:auto;inset-inline-end:1em}:host.md3-vertical.md3-floating.md3-region-inline-start .md3-toolbar-layout{inset-inline-end:auto;inset-inline-start:1em}:host.md3-hidden{opacity:0;pointer-events:none}:host.md3-hidden.md3-horizontal{max-height:0em}:host.md3-hidden.md3-vertical{max-width:0em}:host.md3-hidden .md3-toolbar-layout{transform:scaleY(0)}:host.md3-collapsed{--md-toolbar-gap: 0em}:host.md3-collapsed .md3-toolbar-container .md3-toolbar-slots>::ng-deep md3-toolbar-item:not([md3-toolbar-persistent]){max-width:0em!important;max-height:0em!important;min-width:0em!important;min-height:0em!important;margin:0;padding-inline:0em;border-width:0em;opacity:0;visibility:hidden;transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),max-height var(--md-toolbar-duration) var(--md-toolbar-easing),margin var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear var(--md-toolbar-duration)}:host.md3-collapsed.md3-collapse-to-fab{--md-toolbar-padding: 0}:host.md3-collapsed.md3-collapse-to-fab .md3-toolbar-container{max-width:0em;opacity:0;visibility:hidden;pointer-events:none;box-shadow:var(--md-shadow-0dp);transition:max-width var(--md-toolbar-duration) var(--md-toolbar-easing),padding var(--md-toolbar-duration) var(--md-toolbar-easing),box-shadow var(--md-toolbar-effect-duration) linear,opacity var(--md-toolbar-effect-duration) linear,visibility 0s linear var(--md-toolbar-duration)}:host.md3-color-vibrant{--background-color: rgb(var(--md-scheme-primary-container));--foreground-color: rgb(var(--md-scheme-on-primary-container))}:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-standard,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-outlined,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-text,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-outlined{--foreground-color: rgb(var(--md-scheme-on-primary-container))}:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-icon-button].md3-tonal,:host.md3-color-vibrant ::ng-deep .md3-toolbar-slots md3-toolbar-item [md3-button].md3-tonal{--background-color: rgb(var(--md-scheme-surface-container));--foreground-color: rgb(var(--md-scheme-on-surface))}\n"] }]
5365
+ }], ctorParameters: () => [], propDecorators: { toolbarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar-type", required: false }] }], toolbarColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar-color", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], alignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignment", required: false }] }], scrollAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "scroll-action", required: false }] }], fabPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "fab-position", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], layoutElement: [{ type: i0.ViewChild, args: ['layout', { isSignal: true }] }], containerElement: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }], slotsElement: [{ type: i0.ViewChild, args: ['slots', { isSignal: true }] }], fab: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FloatingActionButton), { isSignal: true }] }] } });
5366
+
5367
+ class ToolbarItem {
5368
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5369
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: ToolbarItem, isStandalone: true, selector: "md3-toolbar-item", ngImport: i0 });
5370
+ }
5371
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ToolbarItem, decorators: [{
5372
+ type: Directive,
5373
+ args: [{
5374
+ selector: 'md3-toolbar-item',
5375
+ }]
5376
+ }] });
5377
+
4867
5378
  class NavigationItem {
4868
5379
  el = inject((ElementRef));
4869
5380
  routerLinkActive = inject(RouterLinkActive);
@@ -5515,13 +6026,13 @@ class FullScreenDialog extends CdkDialogContainer {
5515
6026
  this._recaptureFocus();
5516
6027
  }
5517
6028
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, deps: null, target: i0.ɵɵFactoryTarget.Component });
5518
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: FullScreenDialog, isStandalone: true, selector: "md3-fullscreen-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }, { propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;overflow-y:visible;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
6029
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: FullScreenDialog, isStandalone: true, selector: "md3-fullscreen-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }, { propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;max-height:100dvh;max-width:100dvw;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;max-width:inherit;overflow-y:auto;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
5519
6030
  }
5520
6031
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, decorators: [{
5521
6032
  type: Component,
5522
6033
  args: [{ selector: 'md3-fullscreen-dialog', imports: [
5523
6034
  CdkPortalOutlet,
5524
- ], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;overflow-y:visible;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
6035
+ ], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{display:grid;grid-template-areas:\"header\" \"body\";grid-template-rows:auto minmax(0,1fr) auto;min-height:0;height:100%;max-height:100dvh;max-width:100dvw;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgb(var(--md-scheme-outline-variant)) transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar{width:.5rem;height:.5rem}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *::-webkit-scrollbar-track{background:transparent}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *>md3-dialog-body{grid-area:body;margin:0;padding:1em 1.5em;max-width:inherit;overflow-y:auto;height:auto}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
5525
6036
  }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }], startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }] } });
5526
6037
 
5527
6038
  const PANEL_CLASS = 'md3-dialog-panel';
@@ -6880,7 +7391,7 @@ class Snackbar {
6880
7391
  constructor(el) {
6881
7392
  this.el = el;
6882
7393
  effect(() => {
6883
- const inset = this.layout.bottomInset() + (this.config.bottomOffset ?? 0);
7394
+ const inset = this.layout.bottomSafeInset() + (this.config.bottomOffset ?? 0);
6884
7395
  this.el.nativeElement.style.setProperty('--md3-snackbar-bottom-inset', `${inset}px`);
6885
7396
  });
6886
7397
  effect(() => {
@@ -7087,5 +7598,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
7087
7598
  * Generated bundle index. Do not edit.
7088
7599
  */
7089
7600
 
7090
- export { AppBar, AppBarLogo, Avatar, BOTTOM_SHEET_COMPONENT, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, Badge, BottomSheetRef, BottomSheetService, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, 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, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
7601
+ export { AppBar, AppBarLogo, Avatar, BOTTOM_SHEET_COMPONENT, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, Badge, BottomSheetRef, BottomSheetService, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, 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, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
7091
7602
  //# sourceMappingURL=almoamendev-ngx-md3.mjs.map