@almoamendev/ngx-md3 0.5.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, booleanAttribute, effect, Directive, inject, signal, computed, Injectable, InjectionToken, viewChild, 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, Injectable, untracked, 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';
6
+ import { fromEvent, startWith, map, filter, Subscription, Subject, take, takeUntil, merge } from 'rxjs';
6
7
  import * as i1 from '@angular/router';
7
8
  import { Router, NavigationEnd, RouterLinkActive } from '@angular/router';
8
- import { fromEvent, startWith, map, filter, Subscription, Subject, take, takeUntil, merge } from 'rxjs';
9
9
  import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
10
10
  import { CdkDialogContainer, Dialog as Dialog$1 } from '@angular/cdk/dialog';
11
11
  import { Overlay, OverlayContainer, OverlayConfig } from '@angular/cdk/overlay';
@@ -220,12 +220,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
220
220
  }]
221
221
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], emphasized: [{ type: i0.Input, args: [{ isSignal: true, alias: "emphasized", required: false }] }] } });
222
222
 
223
- class LayoutService {
223
+ /**
224
+ * The state of the window and of the document, for the whole application.
225
+ *
226
+ * This service is a singleton on purpose. A layout region can appear more than once — a page
227
+ * scaffold, and a contained layout inside a full screen dialog — and each one keeps its own
228
+ * scroll and inset state in its own {@link LayoutService}. The window size, the breakpoints,
229
+ * the reading direction and the color scheme belong to the document, so they live here and
230
+ * every layout reads the same values.
231
+ */
232
+ class ViewportService {
224
233
  document = inject(DOCUMENT);
225
234
  breakpointObserver = inject(BreakpointObserver);
226
- // Optional — LayoutService (and anything built on Scaffold) shouldn't
227
- // hard-require the Router, only benefit from it when it's present.
228
- router = inject(Router, { optional: true });
229
235
  widthQueries = {
230
236
  'compact': '(max-width: 37.499em)', // < 600
231
237
  'medium': '(min-width: 37.5em) and (max-width: 52.499em)', // 600-839
@@ -238,23 +244,6 @@ class LayoutService {
238
244
  'medium': '(min-height: 30em) and (max-height: 56.249em)',
239
245
  'expanded': '(min-height: 56.25em)'
240
246
  };
241
- mainPaneSub;
242
- mainPaneEl;
243
- panesContainerResizeObserver;
244
- panesContainerResizeListener;
245
- mainScrollTop = signal(0, /* @ts-ignore */
246
- ...(ngDevMode ? [{ debugName: "mainScrollTop" }] : /* istanbul ignore next */ []));
247
- mainIsScrolled = computed(() => this.mainScrollTop() > 0, /* @ts-ignore */
248
- ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
249
- /**
250
- * Distance, in pixels, between the viewport bottom and the bottom edge of
251
- * the scaffold's .md3-panes-container — i.e. whatever the bottom scaffold
252
- * bar (nav bar) currently reserves, or 0 when there is none. Overlay-based
253
- * components anchored to the viewport bottom (like Snackbar) read this so
254
- * they never render lower than the panes container.
255
- */
256
- bottomInset = signal(0, /* @ts-ignore */
257
- ...(ngDevMode ? [{ debugName: "bottomInset" }] : /* istanbul ignore next */ []));
258
247
  viewport = toSignal(fromEvent(window, 'resize').pipe(startWith(null), map(() => ({
259
248
  width: window.innerWidth,
260
249
  height: window.innerHeight
@@ -328,21 +317,120 @@ class LayoutService {
328
317
  this.document.body.classList.toggle('md-scheme-dark', darkMode);
329
318
  this.document.body.classList.toggle('md-scheme-light', !darkMode);
330
319
  });
331
- // Reset the scaffold's main pane to the top after every completed
332
- // navigation — otherwise a scrolled-down list page leaves the next
333
- // page's content scrolled down too, since the pane itself never
334
- // remounts on route change.
320
+ }
321
+ setDirection(direction) {
322
+ this.document.documentElement.dir = direction;
323
+ this.direction.set(direction);
324
+ }
325
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ViewportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
326
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ViewportService, providedIn: 'root' });
327
+ }
328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ViewportService, decorators: [{
329
+ type: Injectable,
330
+ args: [{
331
+ providedIn: 'root'
332
+ }]
333
+ }], ctorParameters: () => [] });
334
+
335
+ /**
336
+ * The state of one layout container: what its main pane scrolls, and what its floating bars
337
+ * cover.
338
+ *
339
+ * The service is provided at the root, and the page scaffold uses that root instance. A
340
+ * contained layout — `md3-layout`, the one a full screen dialog holds — provides its own
341
+ * instance instead, so a toolbar inside it reads the scroll and the insets of that layout and
342
+ * never of the page behind it.
343
+ *
344
+ * The window size, the breakpoints, the reading direction and the color scheme belong to the
345
+ * document, not to a container. They live in {@link ViewportService}, and every instance of
346
+ * this service exposes the same signals, so an instance stays a complete view of the layout.
347
+ */
348
+ class LayoutService {
349
+ viewportService = inject(ViewportService);
350
+ // Optional — LayoutService (and anything built on Scaffold) shouldn't
351
+ // hard-require the Router, only benefit from it when it's present.
352
+ router = inject(Router, { optional: true });
353
+ mainPaneSub;
354
+ mainPaneEl;
355
+ panesContainerResizeObserver;
356
+ panesContainerResizeListener;
357
+ /** Floating bars currently registered, keyed by the measured element. */
358
+ floatingBars = new Map();
359
+ /** How far the main pane must move before the scroll direction flips. Stops jitter. */
360
+ static scrollDirectionThreshold = 64;
361
+ scrollPosition = 0;
362
+ mainScrollTop = signal(0, /* @ts-ignore */
363
+ ...(ngDevMode ? [{ debugName: "mainScrollTop" }] : /* istanbul ignore next */ []));
364
+ mainIsScrolled = computed(() => this.mainScrollTop() > 0, /* @ts-ignore */
365
+ ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
366
+ /**
367
+ * True while the main pane moves down, false while it moves up. A small threshold keeps
368
+ * a jitter from flipping the value. Components that react to scrolling — the app bar and
369
+ * the toolbar — read this, so they can never disagree.
370
+ */
371
+ isScrollingDown = signal(false, /* @ts-ignore */
372
+ ...(ngDevMode ? [{ debugName: "isScrollingDown" }] : /* istanbul ignore next */ []));
373
+ /**
374
+ * Distance, in pixels, between the bottom of the container and the bottom edge of
375
+ * the .md3-panes-container — i.e. whatever the bottom bar currently reserves, or 0 when
376
+ * there is none. Overlay-based components anchored to the bottom (like Snackbar) read
377
+ * this so they never render lower than the panes container.
378
+ */
379
+ bottomInset = signal(0, /* @ts-ignore */
380
+ ...(ngDevMode ? [{ debugName: "bottomInset" }] : /* istanbul ignore next */ []));
381
+ /**
382
+ * Space a floating bar covers but does not reserve, per logical block side.
383
+ *
384
+ * A floating toolbar in a bar region leaves the layout flow, so its grid track collapses
385
+ * and the content flows under it. This signal reports what it covers, so the layout can
386
+ * pad the main pane and overlays can stay clear of it.
387
+ *
388
+ * A floating toolbar in a *rail* region stays in the flow and reserves its own space, so
389
+ * it never appears here.
390
+ */
391
+ floatingInset = signal({ blockStart: 0, blockEnd: 0 }, /* @ts-ignore */
392
+ ...(ngDevMode ? [{ debugName: "floatingInset" }] : /* istanbul ignore next */ []));
393
+ /**
394
+ * The distance from the bottom that an anchored overlay must keep clear. It covers both
395
+ * the reserved bottom bar and any floating bottom bar over it.
396
+ */
397
+ bottomSafeInset = computed(() => this.bottomInset() + this.floatingInset().blockEnd, /* @ts-ignore */
398
+ ...(ngDevMode ? [{ debugName: "bottomSafeInset" }] : /* istanbul ignore next */ []));
399
+ // The state of the window and of the document. It is shared by every layout, so these are
400
+ // the same signals on every instance of this service.
401
+ viewport = this.viewportService.viewport;
402
+ widthClass = this.viewportService.widthClass;
403
+ heightClass = this.viewportService.heightClass;
404
+ direction = this.viewportService.direction;
405
+ isCompact = this.viewportService.isCompact;
406
+ isMedium = this.viewportService.isMedium;
407
+ isExpanded = this.viewportService.isExpanded;
408
+ isLarge = this.viewportService.isLarge;
409
+ isExtraLarge = this.viewportService.isExtraLarge;
410
+ isPortrait = this.viewportService.isPortrait;
411
+ isLandscape = this.viewportService.isLandscape;
412
+ preferredNavigationMode = this.viewportService.preferredNavigationMode;
413
+ darkMode = this.viewportService.darkMode;
414
+ constructor() {
415
+ // Keep the scroll direction in step with the position. Anything that writes
416
+ // mainScrollTop drives it, so the app bar and the toolbar always agree.
417
+ effect(() => {
418
+ this.updateScrollDirection(this.mainScrollTop());
419
+ });
420
+ // Reset the main pane to the top after every completed navigation — otherwise a
421
+ // scrolled-down list page leaves the next page's content scrolled down too, since the
422
+ // pane itself never remounts on route change.
335
423
  this.router?.events
336
424
  .pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed())
337
425
  .subscribe(() => this.scrollMainPaneToTop());
338
426
  }
339
427
  setDirection(direction) {
340
- this.document.documentElement.dir = direction;
341
- this.direction.set(direction);
428
+ this.viewportService.setDirection(direction);
342
429
  }
343
430
  scrollMainPaneToTop() {
344
431
  this.mainPaneEl?.scrollTo({ top: 0 });
345
432
  this.mainScrollTop.set(0);
433
+ this.resetScrollDirection();
346
434
  }
347
435
  registerMainPane(element) {
348
436
  this.mainPaneSub?.unsubscribe();
@@ -365,12 +453,29 @@ class LayoutService {
365
453
  this.mainPaneEl = undefined;
366
454
  }
367
455
  this.mainScrollTop.set(0);
456
+ this.resetScrollDirection();
457
+ }
458
+ resetScrollDirection() {
459
+ this.scrollPosition = 0;
460
+ this.isScrollingDown.set(false);
461
+ }
462
+ updateScrollDirection(scrollTop) {
463
+ if (scrollTop === this.scrollPosition) {
464
+ return;
465
+ }
466
+ const offset = scrollTop - this.scrollPosition;
467
+ if (Math.abs(offset) <= LayoutService.scrollDirectionThreshold) {
468
+ return;
469
+ }
470
+ this.isScrollingDown.set(offset > 0);
471
+ this.scrollPosition = scrollTop;
368
472
  }
369
473
  registerPanesContainer(element) {
370
474
  this.unregisterPanesContainer();
371
475
  const update = () => {
372
476
  const rect = element.getBoundingClientRect();
373
- this.bottomInset.set(Math.max(0, Math.round(window.innerHeight - rect.bottom)));
477
+ const bottom = element.ownerDocument.defaultView?.innerHeight ?? 0;
478
+ this.bottomInset.set(Math.max(0, Math.round(bottom - rect.bottom)));
374
479
  };
375
480
  update();
376
481
  this.panesContainerResizeObserver = new ResizeObserver(update);
@@ -378,6 +483,67 @@ class LayoutService {
378
483
  this.panesContainerResizeListener = update;
379
484
  window.addEventListener('resize', update, { passive: true });
380
485
  }
486
+ /**
487
+ * Register a floating bar so the layout and the overlays know what it covers.
488
+ *
489
+ * Call this for a floating toolbar in a *bar* region only. A rail region keeps the toolbar
490
+ * in the layout flow, so it reserves its space and needs no inset.
491
+ */
492
+ registerFloatingBar(element, side) {
493
+ this.unregisterFloatingBar(element);
494
+ const observer = new ResizeObserver(() => this.measureFloatingBars());
495
+ observer.observe(element);
496
+ this.floatingBars.set(element, { side, observer });
497
+ this.measureFloatingBars();
498
+ }
499
+ unregisterFloatingBar(element) {
500
+ const entry = this.floatingBars.get(element);
501
+ if (!entry) {
502
+ return;
503
+ }
504
+ entry.observer.disconnect();
505
+ this.floatingBars.delete(element);
506
+ this.measureFloatingBars();
507
+ }
508
+ measureFloatingBars() {
509
+ let blockStart = 0;
510
+ let blockEnd = 0;
511
+ for (const [element, entry] of this.floatingBars) {
512
+ const size = this.measureBlockSize(element);
513
+ if (entry.side === 'blockStart') {
514
+ blockStart = Math.max(blockStart, size);
515
+ }
516
+ else {
517
+ blockEnd = Math.max(blockEnd, size);
518
+ }
519
+ }
520
+ // Read the current value untracked. A component registers its floating bar from an
521
+ // effect, so a tracked read would make that effect depend on the signal that the same
522
+ // run writes. The cleanup measures an empty map and writes 0, the body measures the bar
523
+ // and writes its size, and the effect dirties itself again on every run. That loop never
524
+ // settles, and change detection never finishes.
525
+ const current = untracked(this.floatingInset);
526
+ // Only write on a real change. The main pane padding reads this value, and padding
527
+ // changes the panes container size, which fires the observer again.
528
+ if (current.blockStart === blockStart && current.blockEnd === blockEnd) {
529
+ return;
530
+ }
531
+ this.floatingInset.set({ blockStart, blockEnd });
532
+ }
533
+ /**
534
+ * `offsetHeight` ignores transforms. So a toolbar that scrolling has hidden or collapsed
535
+ * still reports its expanded size, and the content padding never moves while the user
536
+ * scrolls.
537
+ */
538
+ measureBlockSize(element) {
539
+ if (typeof getComputedStyle === 'undefined') {
540
+ return element.offsetHeight || 0;
541
+ }
542
+ const styles = getComputedStyle(element);
543
+ const start = Number.parseFloat(styles.marginBlockStart) || 0;
544
+ const end = Number.parseFloat(styles.marginBlockEnd) || 0;
545
+ return Math.max(0, Math.round(element.offsetHeight + start + end));
546
+ }
381
547
  unregisterPanesContainer() {
382
548
  this.panesContainerResizeObserver?.disconnect();
383
549
  this.panesContainerResizeObserver = undefined;
@@ -1847,6 +2013,18 @@ class Scaffold {
1847
2013
  sheets = inject(SheetsService);
1848
2014
  bottomSheets = inject(BottomSheetService);
1849
2015
  layout = inject(LayoutService);
2016
+ el = inject(ElementRef);
2017
+ constructor() {
2018
+ // Publish what a floating bar covers but does not reserve. The main pane pads itself
2019
+ // by these values, and the fallback is 0, so a layout without a floating bar is
2020
+ // unchanged. A page that needs full-bleed content sets them back to 0 on itself.
2021
+ effect(() => {
2022
+ const inset = this.layout.floatingInset();
2023
+ const host = this.el.nativeElement;
2024
+ host.style.setProperty('--md-scaffold-floating-inset-block-start', `${inset.blockStart}px`);
2025
+ host.style.setProperty('--md-scaffold-floating-inset-block-end', `${inset.blockEnd}px`);
2026
+ });
2027
+ }
1850
2028
  ngAfterViewInit() {
1851
2029
  const startOutlet = this.startOutlet();
1852
2030
  const endOutlet = this.endOutlet();
@@ -1881,14 +2059,53 @@ class Scaffold {
1881
2059
  this.layout.unregisterPanesContainer();
1882
2060
  }
1883
2061
  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"] }] });
2062
+ 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{width:100%;height:100dvh;display:grid;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
2063
  }
1886
2064
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Scaffold, decorators: [{
1887
2065
  type: Component,
1888
2066
  args: [{ selector: 'md3-scaffold', imports: [
1889
2067
  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 }] }] } });
2068
+ ], 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{width:100%;height:100dvh;display:grid;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"] }]
2069
+ }], 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 }] }] } });
2070
+
2071
+ /**
2072
+ * A layout region shell that fills its parent instead of the window.
2073
+ *
2074
+ * It places the same regions as `md3-scaffold` — the bar rows, the rail columns and the three
2075
+ * panes — so the same region attributes work inside it:
2076
+ *
2077
+ * ```html
2078
+ * <md3-layout>
2079
+ * <md3-toolbar md3-scaffold-bar="bottom" toolbar-type="floating">...</md3-toolbar>
2080
+ *
2081
+ * <div md3-scaffold-pane="main">...</div>
2082
+ * </md3-layout>
2083
+ * ```
2084
+ *
2085
+ * Use it wherever a page-sized scaffold does not fit: the content of a full screen dialog, a
2086
+ * card, a preview pane. A full screen dialog is the common one, because a toolbar needs a bar
2087
+ * or a rail region and the dialog shell has none of its own.
2088
+ *
2089
+ * The layout provides its own {@link LayoutService}, so everything inside it reads the scroll
2090
+ * position and the floating insets of *this* container. A floating toolbar therefore pads the
2091
+ * main pane of the layout, and `scroll-action` follows the pane of the layout — never the page
2092
+ * behind it. The window size, the breakpoints, the reading direction and the color scheme stay
2093
+ * shared with the rest of the application.
2094
+ */
2095
+ class Layout extends Scaffold {
2096
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Layout, deps: null, target: i0.ɵɵFactoryTarget.Component });
2097
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: Layout, isStandalone: true, selector: "md3-layout", providers: [
2098
+ LayoutService,
2099
+ ], usesInheritance: 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{width:100%;height:100%;display:grid;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"] }] });
2100
+ }
2101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Layout, decorators: [{
2102
+ type: Component,
2103
+ args: [{ selector: 'md3-layout', imports: [
2104
+ CdkPortalOutlet,
2105
+ ], providers: [
2106
+ LayoutService,
2107
+ ], 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{width:100%;height:100%;display:grid;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"] }]
2108
+ }] });
1892
2109
 
1893
2110
  class ScaffoldBar {
1894
2111
  region = input.required({ ...(ngDevMode ? { debugName: "region" } : /* istanbul ignore next */ {}), alias: 'md3-scaffold-bar' });
@@ -4707,125 +4924,316 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
4707
4924
  args: [{ selector: 'md3-circular-progress-indicator', imports: [], template: "<div class=\"md3-indicator-container\" [class.md3-thickness-8dp]=\"thickness() == 8\" [class.md3-indeterminate]=\"indeterminate()\" [style.--progress]=\"progressValue()\">\n <svg class=\"md3-circlar-indicator\">\n <circle class=\"md3-track\" pathLength=\"100\"></circle>\n <circle class=\"md3-active-indicator\" pathLength=\"100\"></circle>\n </svg>\n</div>", styles: [":host{display:inline-flex}:host .md3-indicator-container{font-size:.25rem;--gap: 7;--progress: 0}:host .md3-indicator-container.md3-thickness-8dp{font-size:.5rem;--gap: 10}:host .md3-indicator-container{--indicator-color: rgb(var(--md-scheme-primary));--track-color: rgb(var(--md-scheme-primary-container));--size: calc(2.25rem + 1em) ;--stroke: 1em;--center: calc(var(--size) / 2);--radius: calc(var(--size) / 2 - var(--stroke) / 2);--track-arc: calc(100 - var(--progress));display:inline-block;width:var(--size);height:var(--size)}:host .md3-indicator-container .md3-circlar-indicator{display:block;width:var(--size);height:var(--size);shape-rendering:geometricprecision}:host .md3-indicator-container .md3-track,:host .md3-indicator-container .md3-active-indicator{fill:none;stroke-width:var(--stroke);stroke-linecap:round;cx:var(--center);cy:var(--center);r:var(--radius);transform-origin:center;transform:rotate(-90deg);transition:stroke-dasharray var(--md-motion-standard-fast-effects-duration) var(--md-motion-standard-fast-effects-easing),stroke-dashoffset var(--md-motion-standard-fast-effects-duration) var(--md-motion-standard-fast-effects-easing)}:host .md3-indicator-container .md3-track{--track-length: calc(var(--track-arc) - var(--gap) * 2);stroke:var(--track-color);stroke-dasharray:var(--track-length) calc(100 - var(--track-length));stroke-dashoffset:calc(var(--track-arc) - var(--gap))}:host .md3-indicator-container .md3-active-indicator{stroke:var(--indicator-color);stroke-dasharray:var(--progress) calc(100 - var(--progress))}:host .md3-indicator-container.md3-indeterminate{animation:container-rotate calc(var(--md-motion-standard-slow-effects-duration) * 5) linear infinite}:host .md3-indicator-container.md3-indeterminate .md3-circlar-indicator{animation:indicator-track-rotate calc(var(--md-motion-standard-slow-effects-duration) * 8) var(--md-motion-standard-slow-effects-easing) infinite}:host .md3-indicator-container.md3-indeterminate .md3-circlar-indicator .md3-track{stroke-dashoffset:92;animation:track-fill calc(var(--md-motion-standard-slow-effects-duration) * 8) var(--md-motion-standard-slow-effects-easing) infinite}:host .md3-indicator-container.md3-indeterminate .md3-circlar-indicator .md3-active-indicator{stroke-dashoffset:0;animation:indicator-fill calc(var(--md-motion-standard-slow-effects-duration) * 8) var(--md-motion-standard-slow-effects-easing) infinite}:host .md3-indicator-container.md3-indeterminate.md3-thickness-8dp .md3-circlar-indicator .md3-track{stroke-dashoffset:90;animation:track-fill-8dp calc(var(--md-motion-standard-slow-effects-duration) * 8) var(--md-motion-standard-slow-effects-easing) infinite}@keyframes container-rotate{to{transform:rotate(360deg)}}@keyframes indicator-track-rotate{0%{transform:rotate(0)}30%{transform:rotate(0)}50%{transform:rotate(180deg)}80%{transform:rotate(180deg)}to{transform:rotate(360deg)}}@keyframes track-fill{0%{stroke-dasharray:84 16;stroke-dashoffset:92}30%{stroke-dasharray:34 66;stroke-dashoffset:42}50%{stroke-dasharray:84 24;stroke-dashoffset:100}80%{stroke-dasharray:34 66;stroke-dashoffset:42}to{stroke-dasharray:84 16;stroke-dashoffset:92}}@keyframes track-fill-8dp{0%{stroke-dasharray:80 20;stroke-dashoffset:90}30%{stroke-dasharray:30 70;stroke-dashoffset:40}50%{stroke-dasharray:80 20;stroke-dashoffset:90}80%{stroke-dasharray:30 70;stroke-dashoffset:40}to{stroke-dasharray:80 20;stroke-dashoffset:90}}@keyframes indicator-fill{0%{stroke-dasharray:0 100}30%{stroke-dasharray:50 50}50%{stroke-dasharray:0 100}80%{stroke-dasharray:50 50}to{stroke-dasharray:0 100}}\n"] }]
4708
4925
  }], ctorParameters: () => [], propDecorators: { indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], thickness: [{ type: i0.Input, args: [{ isSignal: true, alias: "thickness", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }] } });
4709
4926
 
4710
- class AppBarLogo {
4711
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBarLogo, deps: [], target: i0.ɵɵFactoryTarget.Directive });
4712
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: AppBarLogo, isStandalone: true, selector: "[md3-app-bar-logo]", ngImport: i0 });
4713
- }
4714
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBarLogo, decorators: [{
4715
- type: Directive,
4716
- args: [{
4717
- selector: '[md3-app-bar-logo]',
4718
- }]
4719
- }] });
4720
-
4721
- class AppBar {
4722
- el;
4723
- layoutService;
4724
- title = input(null, { ...(ngDevMode ? { debugName: "title" } : /* istanbul ignore next */ {}), alias: 'bar-title' });
4725
- subtitle = input(null, { ...(ngDevMode ? { debugName: "subtitle" } : /* istanbul ignore next */ {}), alias: 'bar-subtitle' });
4726
- appBarType = input('small', { ...(ngDevMode ? { debugName: "appBarType" } : /* istanbul ignore next */ {}), alias: 'bar-type' });
4727
- appBarScrollingStyle = input('elevate', { ...(ngDevMode ? { debugName: "appBarScrollingStyle" } : /* istanbul ignore next */ {}), alias: 'scroll-style' });
4728
- autoHide = input(false, { ...(ngDevMode ? { debugName: "autoHide" } : /* istanbul ignore next */ {}), alias: 'auto-hide',
4729
- transform: booleanAttribute });
4730
- centerAligned = input(false, { ...(ngDevMode ? { debugName: "centerAligned" } : /* istanbul ignore next */ {}), alias: 'center-aligned',
4731
- transform: booleanAttribute });
4732
- logo = contentChild(AppBarLogo, /* @ts-ignore */
4733
- ...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
4734
- avatar = contentChild(Avatar, /* @ts-ignore */
4735
- ...(ngDevMode ? [{ debugName: "avatar" }] : /* istanbul ignore next */ []));
4736
- hasLogo = computed(() => !!this.logo(), /* @ts-ignore */
4737
- ...(ngDevMode ? [{ debugName: "hasLogo" }] : /* istanbul ignore next */ []));
4738
- hasAvatar = computed(() => !!this.avatar(), /* @ts-ignore */
4739
- ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
4740
- mainIsScrolled = computed(() => this.layoutService.mainIsScrolled(), /* @ts-ignore */
4741
- ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
4742
- isScrollingDown = signal(false, /* @ts-ignore */
4743
- ...(ngDevMode ? [{ debugName: "isScrollingDown" }] : /* istanbul ignore next */ []));
4744
- scrollPosition = 0;
4745
- bottomExpandedHeight = computed(() => {
4746
- const type = this.appBarType();
4747
- if (!this.hasCollapsibleBottom(type)) {
4748
- return 0;
4749
- }
4750
- this.layoutService.viewport();
4751
- const fontSize = this.getHostFontSize();
4752
- const hasSubtitle = !!this.subtitle()?.length;
4753
- if (type === 'medium') {
4754
- return (hasSubtitle ? 4.5 : 3) * fontSize;
4755
- }
4756
- return (hasSubtitle ? 5.5 : 3.5) * fontSize;
4757
- }, /* @ts-ignore */
4758
- ...(ngDevMode ? [{ debugName: "bottomExpandedHeight" }] : /* istanbul ignore next */ []));
4759
- bottomCollapse = computed(() => {
4760
- const expandedHeight = this.bottomExpandedHeight();
4761
- if (!expandedHeight) {
4762
- return 0;
4763
- }
4764
- return Math.min(expandedHeight, Math.max(0, this.layoutService.mainScrollTop()));
4765
- }, /* @ts-ignore */
4766
- ...(ngDevMode ? [{ debugName: "bottomCollapse" }] : /* istanbul ignore next */ []));
4767
- // button context
4768
- buttonContextSize = signal('small', /* @ts-ignore */
4769
- ...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
4770
- constructor(el, layoutService) {
4771
- this.el = el;
4772
- this.layoutService = layoutService;
4773
- this.scrollPosition = this.layoutService.mainScrollTop();
4774
- effect((onCleanup) => {
4775
- const type = 'md3-' + this.appBarType();
4776
- this.element.classList.add(type);
4777
- onCleanup(() => {
4778
- this.element.classList.remove(type);
4779
- });
4780
- });
4781
- effect((onCleanup) => {
4782
- const scrollingStyle = 'md3-scroll-style-' + this.appBarScrollingStyle();
4783
- this.element.classList.add(scrollingStyle);
4784
- onCleanup(() => {
4785
- this.element.classList.remove(scrollingStyle);
4786
- });
4787
- });
4788
- effect((onCleanup) => {
4789
- const width = 'md3-layout-' + this.layoutService.widthClass();
4790
- this.element.classList.add(width);
4791
- onCleanup(() => {
4792
- this.element.classList.remove(width);
4793
- });
4794
- });
4795
- effect(() => {
4796
- this.updateScrollDirection(this.layoutService.mainScrollTop());
4797
- });
4798
- effect(() => {
4799
- const collapse = this.bottomCollapse();
4800
- const expandedHeight = this.bottomExpandedHeight();
4801
- this.element.style.setProperty('--app-bar-bottom-collapse', `${collapse}px`);
4802
- this.element.style.setProperty('--app-bar-bottom-opacity', this.getBottomOpacity(collapse, expandedHeight).toString());
4803
- this.element.classList.toggle('md3-collapsed', this.isBottomCollapsed(collapse, expandedHeight));
4804
- });
4805
- }
4806
- get element() {
4807
- return this.el.nativeElement;
4927
+ const DIALOG_DATA = new InjectionToken('MD3_DIALOG_DATA');
4928
+ const DIALOG_CONFIG = new InjectionToken('MD3_DIALOG_CONFIG');
4929
+ const DIALOG_COMPONENT = new InjectionToken('MD3_DIALOG_COMPONENT');
4930
+ const DIALOG_EXIT_ANIMATION_FALLBACK_MS = 300;
4931
+ const HIDDEN_CLASS = 'md3-dialog-hidden';
4932
+ class DialogRef {
4933
+ cdkRef;
4934
+ isFullScreen;
4935
+ closed = new Subject();
4936
+ closing = new Subject();
4937
+ hiddenChanges = new Subject();
4938
+ closePromise = null;
4939
+ closeStarted = false;
4940
+ closeSettled = false;
4941
+ hidden = false;
4942
+ /** Shell hosting the dialog: the regular dialog or the full screen one. */
4943
+ dialogInstance;
4944
+ /**
4945
+ * Filled by DialogService after the user component is attached. Keeping the
4946
+ * instance here lets callers imperatively update inputs when that is useful.
4947
+ */
4948
+ componentInstance;
4949
+ /** Overlay hosting the dialog, useful to reach the panel and the scrim. */
4950
+ get overlayRef() {
4951
+ return this.cdkRef.overlayRef;
4808
4952
  }
4809
- getBottomOpacity(collapse, expandedHeight) {
4810
- if (!expandedHeight) {
4811
- return 1;
4812
- }
4813
- return Math.max(0, Math.min(1, 1 - (collapse / expandedHeight)));
4953
+ /** Whether the dialog started closing. Such a dialog cannot be hidden or shown anymore. */
4954
+ get isClosing() {
4955
+ return this.closeStarted;
4814
4956
  }
4815
- isBottomCollapsed(collapse, expandedHeight) {
4816
- return expandedHeight > 0 && collapse >= expandedHeight;
4957
+ /** Whether the dialog is currently hidden, on request or behind another dialog. */
4958
+ get isHidden() {
4959
+ return this.hidden;
4817
4960
  }
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;
4961
+ constructor(cdkRef, disableCloseEvents,
4962
+ /** Whether this reference belongs to a full screen dialog. */
4963
+ isFullScreen = false) {
4964
+ this.cdkRef = cdkRef;
4965
+ this.isFullScreen = isFullScreen;
4966
+ // Closing always goes through this reference so the exit animation can
4967
+ // run before the CDK disposes the overlay. Detachments triggered from
4968
+ // the outside (navigation, scroll strategy) still settle this ref.
4969
+ this.cdkRef.closed.pipe(take(1)).subscribe((result) => this.settle(result));
4970
+ if (!disableCloseEvents) {
4971
+ this.connectCloseEvents();
4972
+ }
4973
+ }
4974
+ /** Closes the dialog. The promise resolves once the exit animation is done. */
4975
+ close(result) {
4976
+ if (this.closePromise) {
4977
+ return this.closePromise;
4978
+ }
4979
+ this.startClosing();
4980
+ this.closePromise = this.startCloseAnimation().then(() => this.cdkRef.close(result));
4981
+ return this.closePromise;
4982
+ }
4983
+ /**
4984
+ * Hides the dialog with the closing animation while keeping it alive, so
4985
+ * its content, form state and subscriptions survive until show() is called.
4986
+ * The page underneath becomes usable again while the dialog waits behind it.
4987
+ * The promise resolves once the dialog is out of sight.
4988
+ */
4989
+ hide() {
4990
+ if (this.hidden || this.closeStarted) {
4991
+ return Promise.resolve();
4992
+ }
4993
+ this.hidden = true;
4994
+ this.toggleHiddenState(true);
4995
+ this.dialogInstance?.setActive(false);
4996
+ this.hiddenChanges.next(true);
4997
+ return this.waitForSurfaceAnimation();
4998
+ }
4999
+ /**
5000
+ * Brings a hidden dialog back with the opening animation. Focus moves back
5001
+ * into the dialog even when it was never hidden, which is what makes it
5002
+ * usable again once the dialog above it closes.
5003
+ */
5004
+ show() {
5005
+ if (this.closeStarted) {
5006
+ return;
5007
+ }
5008
+ if (this.hidden) {
5009
+ this.hidden = false;
5010
+ this.toggleHiddenState(false);
5011
+ this.dialogInstance?.setActive(true);
5012
+ this.hiddenChanges.next(false);
5013
+ }
5014
+ this.dialogInstance?.recaptureFocus();
5015
+ }
5016
+ /** Emits when the dialog starts closing, before the exit animation runs. */
5017
+ beforeClosed() {
5018
+ return this.closing.asObservable();
5019
+ }
5020
+ /** Emits the new value of `isHidden` every time the dialog is hidden or shown. */
5021
+ hiddenChanged() {
5022
+ return this.hiddenChanges.asObservable();
5023
+ }
5024
+ afterClosed() {
5025
+ return this.closed.asObservable();
5026
+ }
5027
+ connectCloseEvents() {
5028
+ // The CDK config keeps `disableClose` on, so the scrim and Escape key
5029
+ // are handled here instead and the dialog can animate out.
5030
+ this.cdkRef.backdropClick.pipe(take(1)).subscribe(() => {
5031
+ this.cdkRef.containerInstance._closeInteractionType = 'mouse';
5032
+ this.close();
5033
+ });
5034
+ // A hidden dialog is not the one the Escape key is meant for, even
5035
+ // though the overlay it sits in is still the one receiving the event.
5036
+ this.cdkRef.keydownEvents.pipe(filter((event) => !this.hidden && event.key === 'Escape' && !hasModifierKey(event)), take(1)).subscribe((event) => {
5037
+ event.preventDefault();
5038
+ this.cdkRef.containerInstance._closeInteractionType = 'keyboard';
5039
+ this.close();
5040
+ });
5041
+ }
5042
+ toggleHiddenState(isHidden) {
5043
+ const overlayRef = this.cdkRef.overlayRef;
5044
+ const panel = overlayRef.overlayElement;
5045
+ const backdrop = overlayRef.backdropElement;
5046
+ panel.classList.toggle(HIDDEN_CLASS, isHidden);
5047
+ backdrop?.classList.toggle(HIDDEN_CLASS, isHidden);
5048
+ // `inert` keeps a hidden dialog out of the tab order and away from
5049
+ // assistive technology without removing it from the DOM.
5050
+ if (isHidden) {
5051
+ panel.setAttribute('inert', '');
5052
+ }
5053
+ else {
5054
+ panel.removeAttribute('inert');
5055
+ }
5056
+ }
5057
+ startClosing() {
5058
+ if (this.closeStarted) {
5059
+ return;
5060
+ }
5061
+ this.closeStarted = true;
5062
+ this.closing.next();
5063
+ this.closing.complete();
5064
+ }
5065
+ startCloseAnimation() {
5066
+ const overlayRef = this.cdkRef.overlayRef;
5067
+ const wasVisible = !this.hidden;
5068
+ overlayRef.overlayElement.classList.add('md3-dialog-closing');
5069
+ overlayRef.backdropElement?.classList.add('md3-dialog-closing');
5070
+ this.dialogInstance?.setActive(false);
5071
+ // A hidden dialog already played the exit animation, so there is
5072
+ // nothing left to transition and it can be disposed right away.
5073
+ return wasVisible ? this.waitForSurfaceAnimation() : Promise.resolve();
5074
+ }
5075
+ /** Resolves when the surface finished animating, with a timeout as a safety net. */
5076
+ waitForSurfaceAnimation() {
5077
+ const panel = this.cdkRef.overlayRef.overlayElement;
5078
+ const surface = this.dialogInstance?.surfaceElement ?? panel;
5079
+ return new Promise((resolve) => {
5080
+ let isResolved = false;
5081
+ let timeoutId = setTimeout(done, DIALOG_EXIT_ANIMATION_FALLBACK_MS);
5082
+ function done() {
5083
+ if (isResolved) {
5084
+ return;
5085
+ }
5086
+ isResolved = true;
5087
+ clearTimeout(timeoutId);
5088
+ surface.removeEventListener('transitionend', onTransitionEnd);
5089
+ resolve();
5090
+ }
5091
+ function onTransitionEnd(event) {
5092
+ if (event.target === surface) {
5093
+ done();
5094
+ }
5095
+ }
5096
+ surface.addEventListener('transitionend', onTransitionEnd);
5097
+ });
5098
+ }
5099
+ /** Emits the result once the CDK reference is closed. Focus is restored by the container. */
5100
+ settle(result) {
5101
+ if (this.closeSettled) {
5102
+ return;
5103
+ }
5104
+ // Covers detachments that did not go through close(), so anything
5105
+ // waiting on beforeClosed() is still notified.
5106
+ this.startClosing();
5107
+ this.closeSettled = true;
5108
+ this.hiddenChanges.complete();
5109
+ this.closed.next(result);
5110
+ this.closed.complete();
5111
+ }
5112
+ }
5113
+
5114
+ class AppBarLogo {
5115
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBarLogo, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5116
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: AppBarLogo, isStandalone: true, selector: "[md3-app-bar-logo]", ngImport: i0 });
5117
+ }
5118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBarLogo, decorators: [{
5119
+ type: Directive,
5120
+ args: [{
5121
+ selector: '[md3-app-bar-logo]',
5122
+ }]
5123
+ }] });
5124
+
5125
+ class AppBar {
5126
+ el;
5127
+ layoutService;
5128
+ // A dialog provides its configuration to everything it holds, so this is how the bar knows
5129
+ // it is not the banner of the document.
5130
+ inDialog = !!inject(DIALOG_CONFIG, { optional: true });
5131
+ /**
5132
+ * The landmark role of the bar.
5133
+ *
5134
+ * A page has one banner, and the app bar of the page is it. A bar inside a dialog is not
5135
+ * the banner of the document — a banner nested in a dialog misleads a screen reader — so a
5136
+ * bar that finds itself in one carries no role. Set this input to force either value.
5137
+ */
5138
+ barRole = input(null, { ...(ngDevMode ? { debugName: "barRole" } : /* istanbul ignore next */ {}), alias: 'bar-role' });
5139
+ resolvedRole = computed(() => {
5140
+ const role = this.barRole();
5141
+ if (role !== null) {
5142
+ return role === 'none' ? null : role;
5143
+ }
5144
+ return this.inDialog ? null : 'banner';
5145
+ }, /* @ts-ignore */
5146
+ ...(ngDevMode ? [{ debugName: "resolvedRole" }] : /* istanbul ignore next */ []));
5147
+ title = input(null, { ...(ngDevMode ? { debugName: "title" } : /* istanbul ignore next */ {}), alias: 'bar-title' });
5148
+ subtitle = input(null, { ...(ngDevMode ? { debugName: "subtitle" } : /* istanbul ignore next */ {}), alias: 'bar-subtitle' });
5149
+ appBarType = input('small', { ...(ngDevMode ? { debugName: "appBarType" } : /* istanbul ignore next */ {}), alias: 'bar-type' });
5150
+ appBarScrollingStyle = input('elevate', { ...(ngDevMode ? { debugName: "appBarScrollingStyle" } : /* istanbul ignore next */ {}), alias: 'scroll-style' });
5151
+ autoHide = input(false, { ...(ngDevMode ? { debugName: "autoHide" } : /* istanbul ignore next */ {}), alias: 'auto-hide',
5152
+ transform: booleanAttribute });
5153
+ centerAligned = input(false, { ...(ngDevMode ? { debugName: "centerAligned" } : /* istanbul ignore next */ {}), alias: 'center-aligned',
5154
+ transform: booleanAttribute });
5155
+ logo = contentChild(AppBarLogo, /* @ts-ignore */
5156
+ ...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
5157
+ avatar = contentChild(Avatar, /* @ts-ignore */
5158
+ ...(ngDevMode ? [{ debugName: "avatar" }] : /* istanbul ignore next */ []));
5159
+ hasLogo = computed(() => !!this.logo(), /* @ts-ignore */
5160
+ ...(ngDevMode ? [{ debugName: "hasLogo" }] : /* istanbul ignore next */ []));
5161
+ hasAvatar = computed(() => !!this.avatar(), /* @ts-ignore */
5162
+ ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
5163
+ mainIsScrolled = computed(() => this.layoutService.mainIsScrolled(), /* @ts-ignore */
5164
+ ...(ngDevMode ? [{ debugName: "mainIsScrolled" }] : /* istanbul ignore next */ []));
5165
+ // One source of truth. The toolbar reads the same signal, so the two bars can never
5166
+ // disagree about which way the main pane is moving.
5167
+ isScrollingDown = computed(() => this.layoutService.isScrollingDown(), /* @ts-ignore */
5168
+ ...(ngDevMode ? [{ debugName: "isScrollingDown" }] : /* istanbul ignore next */ []));
5169
+ bottomExpandedHeight = computed(() => {
5170
+ const type = this.appBarType();
5171
+ if (!this.hasCollapsibleBottom(type)) {
5172
+ return 0;
5173
+ }
5174
+ this.layoutService.viewport();
5175
+ const fontSize = this.getHostFontSize();
5176
+ const hasSubtitle = !!this.subtitle()?.length;
5177
+ if (type === 'medium') {
5178
+ return (hasSubtitle ? 4.5 : 3) * fontSize;
5179
+ }
5180
+ return (hasSubtitle ? 5.5 : 3.5) * fontSize;
5181
+ }, /* @ts-ignore */
5182
+ ...(ngDevMode ? [{ debugName: "bottomExpandedHeight" }] : /* istanbul ignore next */ []));
5183
+ bottomCollapse = computed(() => {
5184
+ const expandedHeight = this.bottomExpandedHeight();
5185
+ if (!expandedHeight) {
5186
+ return 0;
5187
+ }
5188
+ return Math.min(expandedHeight, Math.max(0, this.layoutService.mainScrollTop()));
5189
+ }, /* @ts-ignore */
5190
+ ...(ngDevMode ? [{ debugName: "bottomCollapse" }] : /* istanbul ignore next */ []));
5191
+ // button context
5192
+ buttonContextSize = signal('small', /* @ts-ignore */
5193
+ ...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
5194
+ constructor(el, layoutService) {
5195
+ this.el = el;
5196
+ this.layoutService = layoutService;
5197
+ effect((onCleanup) => {
5198
+ const type = 'md3-' + this.appBarType();
5199
+ this.element.classList.add(type);
5200
+ onCleanup(() => {
5201
+ this.element.classList.remove(type);
5202
+ });
5203
+ });
5204
+ effect((onCleanup) => {
5205
+ const scrollingStyle = 'md3-scroll-style-' + this.appBarScrollingStyle();
5206
+ this.element.classList.add(scrollingStyle);
5207
+ onCleanup(() => {
5208
+ this.element.classList.remove(scrollingStyle);
5209
+ });
5210
+ });
5211
+ effect((onCleanup) => {
5212
+ const width = 'md3-layout-' + this.layoutService.widthClass();
5213
+ this.element.classList.add(width);
5214
+ onCleanup(() => {
5215
+ this.element.classList.remove(width);
5216
+ });
5217
+ });
5218
+ effect(() => {
5219
+ const collapse = this.bottomCollapse();
5220
+ const expandedHeight = this.bottomExpandedHeight();
5221
+ this.element.style.setProperty('--app-bar-bottom-collapse', `${collapse}px`);
5222
+ this.element.style.setProperty('--app-bar-bottom-opacity', this.getBottomOpacity(collapse, expandedHeight).toString());
5223
+ this.element.classList.toggle('md3-collapsed', this.isBottomCollapsed(collapse, expandedHeight));
5224
+ });
5225
+ }
5226
+ get element() {
5227
+ return this.el.nativeElement;
5228
+ }
5229
+ getBottomOpacity(collapse, expandedHeight) {
5230
+ if (!expandedHeight) {
5231
+ return 1;
5232
+ }
5233
+ return Math.max(0, Math.min(1, 1 - (collapse / expandedHeight)));
5234
+ }
5235
+ isBottomCollapsed(collapse, expandedHeight) {
5236
+ return expandedHeight > 0 && collapse >= expandedHeight;
4829
5237
  }
4830
5238
  hasCollapsibleBottom(type) {
4831
5239
  return (type === 'medium' || type === 'large') &&
@@ -4835,34 +5243,435 @@ class AppBar {
4835
5243
  if (typeof getComputedStyle === 'undefined') {
4836
5244
  return 16;
4837
5245
  }
4838
- return Number.parseFloat(getComputedStyle(this.element).fontSize) || 16;
5246
+ return Number.parseFloat(getComputedStyle(this.element).fontSize) || 16;
5247
+ }
5248
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBar, deps: [{ token: i0.ElementRef }, { token: LayoutService }], target: i0.ɵɵFactoryTarget.Component });
5249
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: AppBar, isStandalone: true, selector: "md3-app-bar", inputs: { barRole: { classPropertyName: "barRole", publicName: "bar-role", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "bar-title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "bar-subtitle", isSignal: true, isRequired: false, transformFunction: null }, appBarType: { classPropertyName: "appBarType", publicName: "bar-type", isSignal: true, isRequired: false, transformFunction: null }, appBarScrollingStyle: { classPropertyName: "appBarScrollingStyle", publicName: "scroll-style", isSignal: true, isRequired: false, transformFunction: null }, autoHide: { classPropertyName: "autoHide", publicName: "auto-hide", isSignal: true, isRequired: false, transformFunction: null }, centerAligned: { classPropertyName: "centerAligned", publicName: "center-aligned", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "resolvedRole()", "class.md3-scrolled": "mainIsScrolled()", "class.md3-auto-hide": "autoHide()", "class.md3-scrolling-down": "isScrollingDown()" } }, providers: [
5250
+ {
5251
+ provide: MD3_BUTTON_CONTEXT,
5252
+ useExisting: AppBar,
5253
+ },
5254
+ ], queries: [{ propertyName: "logo", first: true, predicate: AppBarLogo, descendants: true, isSignal: true }, { propertyName: "avatar", first: true, predicate: Avatar, descendants: true, isSignal: true }], ngImport: i0, 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"], dependencies: [{ kind: "directive", type: TypeHeadline, selector: "md3-type-headline, [md3-type-headline]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeTitle, selector: "md3-type-title, [md3-type-title]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeDisplay, selector: "md3-type-display, [md3-type-display]", inputs: ["size", "color", "emphasized"] }] });
5255
+ }
5256
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBar, decorators: [{
5257
+ type: Component,
5258
+ args: [{ selector: 'md3-app-bar', imports: [
5259
+ TypeHeadline,
5260
+ TypeTitle,
5261
+ TypeDisplay,
5262
+ ], providers: [
5263
+ {
5264
+ provide: MD3_BUTTON_CONTEXT,
5265
+ useExisting: AppBar,
5266
+ },
5267
+ ], host: {
5268
+ '[attr.role]': 'resolvedRole()',
5269
+ '[class.md3-scrolled]': 'mainIsScrolled()',
5270
+ '[class.md3-auto-hide]': 'autoHide()',
5271
+ '[class.md3-scrolling-down]': 'isScrollingDown()',
5272
+ }, 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"] }]
5273
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: LayoutService }], propDecorators: { barRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar-role", required: false }] }], 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 }] }] } });
5274
+
5275
+ /**
5276
+ * Material 3 toolbar.
5277
+ *
5278
+ * The toolbar holds the actions of the current page. Put it in a scaffold region, and the
5279
+ * region decides where it goes:
5280
+ *
5281
+ * ```html
5282
+ * <md3-toolbar md3-scaffold-bar="bottom" toolbar-type="floating" scroll-action="collapse">
5283
+ * <md3-toolbar-item><button md3-icon-button>...</button></md3-toolbar-item>
5284
+ * <md3-toolbar-item md3-toolbar-persistent><button md3-icon-button>...</button></md3-toolbar-item>
5285
+ * <button md3-fab>...</button>
5286
+ * </md3-toolbar>
5287
+ * ```
5288
+ *
5289
+ * Every action goes inside an `md3-toolbar-item`. The toolbar projects that element only. A FAB is
5290
+ * the one exception: it sits beside the container, and a floating toolbar takes it.
5291
+ *
5292
+ * A **floating** toolbar in a *bar* region leaves the layout flow, so the content passes
5293
+ * behind it. The scaffold pads the main pane by the height it covers. In a *rail* region it
5294
+ * stays in the flow and reserves its own space, so no padding is necessary.
5295
+ *
5296
+ * A **docked** toolbar fills its region. The specification allows it in a bar region only.
5297
+ *
5298
+ * Group actions with `md3-button-group`. The toolbar has one slots region, and it keeps the
5299
+ * authored order. The space between the items follows the free space of the container, between
5300
+ * `--md-toolbar-gap-min` and `--md-toolbar-gap-max`.
5301
+ */
5302
+ class Toolbar {
5303
+ el = inject(ElementRef);
5304
+ layout = inject(LayoutService);
5305
+ // The scaffold region directives sit on this same host element, so `self` is correct.
5306
+ scaffoldBar = inject(ScaffoldBar, { optional: true, self: true });
5307
+ scaffoldRail = inject(ScaffoldRail, { optional: true, self: true });
5308
+ toolbarType = input('floating', { ...(ngDevMode ? { debugName: "toolbarType" } : /* istanbul ignore next */ {}), alias: 'toolbar-type' });
5309
+ toolbarColor = input('standard', { ...(ngDevMode ? { debugName: "toolbarColor" } : /* istanbul ignore next */ {}), alias: 'toolbar-color' });
5310
+ /**
5311
+ * Leave this unset to follow the region. A rail region gives `vertical`, and every other
5312
+ * placement gives `horizontal`. Read `effectiveOrientation` for the resolved value.
5313
+ */
5314
+ orientation = input(null, { ...(ngDevMode ? { debugName: "orientation" } : /* istanbul ignore next */ {}), alias: 'orientation' });
5315
+ alignment = input('center', { ...(ngDevMode ? { debugName: "alignment" } : /* istanbul ignore next */ {}), alias: 'alignment' });
5316
+ scrollAction = input('none', { ...(ngDevMode ? { debugName: "scrollAction" } : /* istanbul ignore next */ {}), alias: 'scroll-action' });
5317
+ fabPosition = input('end', { ...(ngDevMode ? { debugName: "fabPosition" } : /* istanbul ignore next */ {}), alias: 'fab-position' });
5318
+ /** The collapse state. Scrolling writes to it, and you can read or set it yourself. */
5319
+ expanded = model(true, /* @ts-ignore */
5320
+ ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
5321
+ layoutElement = viewChild('layout', /* @ts-ignore */
5322
+ ...(ngDevMode ? [{ debugName: "layoutElement" }] : /* istanbul ignore next */ []));
5323
+ containerElement = viewChild('container', /* @ts-ignore */
5324
+ ...(ngDevMode ? [{ debugName: "containerElement" }] : /* istanbul ignore next */ []));
5325
+ slotsElement = viewChild('slots', /* @ts-ignore */
5326
+ ...(ngDevMode ? [{ debugName: "slotsElement" }] : /* istanbul ignore next */ []));
5327
+ fab = contentChild(FloatingActionButton, /* @ts-ignore */
5328
+ ...(ngDevMode ? [{ debugName: "fab" }] : /* istanbul ignore next */ []));
5329
+ /** Set from the DOM, because `md3-toolbar-persistent` is a plain attribute, not a directive. */
5330
+ hasPersistentItem = signal(false, /* @ts-ignore */
5331
+ ...(ngDevMode ? [{ debugName: "hasPersistentItem" }] : /* istanbul ignore next */ []));
5332
+ hasFocusWithin = signal(false, /* @ts-ignore */
5333
+ ...(ngDevMode ? [{ debugName: "hasFocusWithin" }] : /* istanbul ignore next */ []));
5334
+ persistentObserver;
5335
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
5336
+ /** The last published free space, to keep an unchanged measurement from writing to the DOM. */
5337
+ lastGap = -1;
5338
+ isFloating = computed(() => this.toolbarType() === 'floating', /* @ts-ignore */
5339
+ ...(ngDevMode ? [{ debugName: "isFloating" }] : /* istanbul ignore next */ []));
5340
+ effectiveOrientation = computed(() => {
5341
+ return this.orientation() ?? (this.scaffoldRail ? 'vertical' : 'horizontal');
5342
+ }, /* @ts-ignore */
5343
+ ...(ngDevMode ? [{ debugName: "effectiveOrientation" }] : /* istanbul ignore next */ []));
5344
+ /** The logical side of the scaffold region, or null outside a scaffold. */
5345
+ region = computed(() => {
5346
+ if (this.scaffoldBar) {
5347
+ return this.scaffoldBar.region() === 'top' ? 'blockStart' : 'blockEnd';
5348
+ }
5349
+ if (this.scaffoldRail) {
5350
+ return this.scaffoldRail.region() === 'leading' ? 'inlineStart' : 'inlineEnd';
5351
+ }
5352
+ return null;
5353
+ }, /* @ts-ignore */
5354
+ ...(ngDevMode ? [{ debugName: "region" }] : /* istanbul ignore next */ []));
5355
+ isBarRegion = computed(() => !!this.scaffoldBar, /* @ts-ignore */
5356
+ ...(ngDevMode ? [{ debugName: "isBarRegion" }] : /* istanbul ignore next */ []));
5357
+ isRailRegion = computed(() => !!this.scaffoldRail, /* @ts-ignore */
5358
+ ...(ngDevMode ? [{ debugName: "isRailRegion" }] : /* istanbul ignore next */ []));
5359
+ /** A floating toolbar inside a scaffold region needs the region to stop clipping it. */
5360
+ isFloatingRegion = computed(() => {
5361
+ return this.isFloating() && (this.isBarRegion() || this.isRailRegion());
5362
+ }, /* @ts-ignore */
5363
+ ...(ngDevMode ? [{ debugName: "isFloatingRegion" }] : /* istanbul ignore next */ []));
5364
+ /** Only a floating bar covers content it does not reserve. Everything else reserves its space. */
5365
+ coversContent = computed(() => this.isFloating() && this.isBarRegion(), /* @ts-ignore */
5366
+ ...(ngDevMode ? [{ debugName: "coversContent" }] : /* istanbul ignore next */ []));
5367
+ /** Something must survive a collapse, or a collapse is just a hide. */
5368
+ canCollapse = computed(() => (!!this.fab() && this.isFloating()) || this.hasPersistentItem(), /* @ts-ignore */
5369
+ ...(ngDevMode ? [{ debugName: "canCollapse" }] : /* istanbul ignore next */ []));
5370
+ /** With a FAB and no marked item, a collapse takes the container away and the FAB stays alone. */
5371
+ collapsesToFab = computed(() => !!this.fab() && this.isFloating() && !this.hasPersistentItem(), /* @ts-ignore */
5372
+ ...(ngDevMode ? [{ debugName: "collapsesToFab" }] : /* istanbul ignore next */ []));
5373
+ /** A vertical toolbar never reacts to scrolling, and a docked one never collapses. */
5374
+ resolvedScrollAction = computed(() => {
5375
+ const action = this.scrollAction();
5376
+ if (action === 'none' || this.effectiveOrientation() === 'vertical') {
5377
+ return 'none';
5378
+ }
5379
+ if (action === 'collapse' && (!this.isFloating() || !this.canCollapse())) {
5380
+ return 'hide';
5381
+ }
5382
+ return action;
5383
+ }, /* @ts-ignore */
5384
+ ...(ngDevMode ? [{ debugName: "resolvedScrollAction" }] : /* istanbul ignore next */ []));
5385
+ isHidden = signal(false, /* @ts-ignore */
5386
+ ...(ngDevMode ? [{ debugName: "isHidden" }] : /* istanbul ignore next */ []));
5387
+ isCollapsed = computed(() => {
5388
+ return this.resolvedScrollAction() === 'collapse' && !this.expanded();
5389
+ }, /* @ts-ignore */
5390
+ ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
5391
+ /**
5392
+ * The collapsed state in which the FAB stays alone.
5393
+ *
5394
+ * This is the state, not the capability. A FAB by itself must never take the container
5395
+ * away, because a toolbar that does not collapse keeps its items at all times.
5396
+ */
5397
+ isCollapsedToFab = computed(() => this.isCollapsed() && this.collapsesToFab(), /* @ts-ignore */
5398
+ ...(ngDevMode ? [{ debugName: "isCollapsedToFab" }] : /* istanbul ignore next */ []));
5399
+ // button context — the container is 4em high, so the buttons inside it are small.
5400
+ buttonContextSize = signal('small', /* @ts-ignore */
5401
+ ...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
5402
+ constructor() {
5403
+ effect(() => {
5404
+ if (this.isFloating()) {
5405
+ this.element.classList.add('md3-floating');
5406
+ this.element.classList.remove('md3-docked');
5407
+ }
5408
+ else {
5409
+ this.element.classList.add('md3-docked');
5410
+ this.element.classList.remove('md3-floating');
5411
+ }
5412
+ });
5413
+ effect((onCleanup) => {
5414
+ const orientation = 'md3-' + this.effectiveOrientation();
5415
+ this.element.classList.add(orientation);
5416
+ onCleanup(() => this.element.classList.remove(orientation));
5417
+ });
5418
+ effect((onCleanup) => {
5419
+ const color = 'md3-color-' + this.toolbarColor();
5420
+ this.element.classList.add(color);
5421
+ onCleanup(() => this.element.classList.remove(color));
5422
+ });
5423
+ effect((onCleanup) => {
5424
+ const alignment = 'md3-align-' + this.alignment();
5425
+ this.element.classList.add(alignment);
5426
+ onCleanup(() => this.element.classList.remove(alignment));
5427
+ });
5428
+ effect((onCleanup) => {
5429
+ const position = 'md3-fab-' + this.fabPosition();
5430
+ this.element.classList.add(position);
5431
+ onCleanup(() => this.element.classList.remove(position));
5432
+ });
5433
+ effect((onCleanup) => {
5434
+ const region = this.region();
5435
+ if (!region) {
5436
+ return;
5437
+ }
5438
+ const name = 'md3-region-' + region.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase());
5439
+ this.element.classList.add(name);
5440
+ onCleanup(() => this.element.classList.remove(name));
5441
+ });
5442
+ // Report what a floating bar covers, so the scaffold can pad the main pane and the
5443
+ // overlays can stay above it.
5444
+ effect((onCleanup) => {
5445
+ if (!this.coversContent()) {
5446
+ return;
5447
+ }
5448
+ const region = this.region();
5449
+ if (region !== 'blockStart' && region !== 'blockEnd') {
5450
+ return;
5451
+ }
5452
+ const element = this.layoutElement()?.nativeElement;
5453
+ if (!element) {
5454
+ return;
5455
+ }
5456
+ this.layout.registerFloatingBar(element, region);
5457
+ onCleanup(() => this.layout.unregisterFloatingBar(element));
5458
+ });
5459
+ effect(() => {
5460
+ this.updateScrollState();
5461
+ });
5462
+ effect(() => {
5463
+ const element = this.layoutElement()?.nativeElement;
5464
+ if (element) {
5465
+ this.watchPersistentItems(element);
5466
+ }
5467
+ });
5468
+ // Measure again when the region gives the toolbar a different amount of space, and when
5469
+ // the items themselves change size or number.
5470
+ effect((onCleanup) => {
5471
+ if (!this.isBrowser) {
5472
+ return;
5473
+ }
5474
+ // Read the state that changes the geometry, so a new orientation or a collapse
5475
+ // measures again without a resize.
5476
+ this.effectiveOrientation();
5477
+ this.isCollapsed();
5478
+ this.isCollapsedToFab();
5479
+ const layout = this.layoutElement()?.nativeElement;
5480
+ const slots = this.slotsElement()?.nativeElement;
5481
+ if (!layout || !slots) {
5482
+ return;
5483
+ }
5484
+ // The observer reports the first size as soon as it starts, so no separate initial
5485
+ // measurement is necessary.
5486
+ const observer = new ResizeObserver(() => this.measureGap());
5487
+ observer.observe(this.element);
5488
+ observer.observe(layout);
5489
+ observer.observe(slots);
5490
+ onCleanup(() => observer.disconnect());
5491
+ });
5492
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
5493
+ effect(() => this.checkConfiguration());
5494
+ }
5495
+ }
5496
+ ngOnDestroy() {
5497
+ // The registration effect owns its own cleanup, so it unregisters the exact element
5498
+ // it measured.
5499
+ this.persistentObserver?.disconnect();
5500
+ this.persistentObserver = undefined;
5501
+ }
5502
+ get element() {
5503
+ return this.el.nativeElement;
5504
+ }
5505
+ onFocusIn() {
5506
+ this.hasFocusWithin.set(true);
5507
+ }
5508
+ onFocusOut(event) {
5509
+ const next = event.relatedTarget;
5510
+ if (next && this.element.contains(next)) {
5511
+ return;
5512
+ }
5513
+ this.hasFocusWithin.set(false);
5514
+ }
5515
+ updateScrollState() {
5516
+ const action = this.resolvedScrollAction();
5517
+ if (action === 'none') {
5518
+ this.isHidden.set(false);
5519
+ this.expanded.set(true);
5520
+ return;
5521
+ }
5522
+ // Keep the toolbar reachable while it holds the focus. A keyboard or screen-reader
5523
+ // user must never lose the control they are on.
5524
+ if (this.hasFocusWithin()) {
5525
+ this.isHidden.set(false);
5526
+ this.expanded.set(true);
5527
+ return;
5528
+ }
5529
+ const away = this.layout.mainIsScrolled() && this.layout.isScrollingDown();
5530
+ this.isHidden.set(action === 'hide' && away);
5531
+ this.expanded.set(action === 'hide' ? true : !away);
5532
+ }
5533
+ /**
5534
+ * Divide the free space of the container between the gaps.
5535
+ *
5536
+ * The measurement starts from the host, because the host holds the space the region gives
5537
+ * the toolbar. A floating container is only as wide as its content, so reading the container
5538
+ * itself would feed the gap back into the measurement and the value would never settle.
5539
+ */
5540
+ measureGap() {
5541
+ const layout = this.layoutElement()?.nativeElement;
5542
+ const container = this.containerElement()?.nativeElement;
5543
+ const slots = this.slotsElement()?.nativeElement;
5544
+ if (!layout || !container || !slots) {
5545
+ return;
5546
+ }
5547
+ const vertical = this.effectiveOrientation() === 'vertical';
5548
+ const items = Array.from(slots.children);
5549
+ const extents = items.map((item) => this.extent(item, vertical));
5550
+ // A collapsed item keeps its box but loses its size, and it must not keep a gap either.
5551
+ const visible = extents.filter((extent) => extent > 0.5).length;
5552
+ if (visible < 2) {
5553
+ this.publishGap(0);
5554
+ return;
5555
+ }
5556
+ const content = extents.reduce((sum, extent) => sum + extent, 0);
5557
+ const free = this.contentExtent(this.element, vertical)
5558
+ - this.paddingExtent(layout, vertical)
5559
+ - this.siblingExtent(layout, container, vertical)
5560
+ - this.paddingExtent(container, vertical)
5561
+ - content;
5562
+ this.publishGap(free / (visible - 1));
5563
+ }
5564
+ publishGap(gap) {
5565
+ // Round down, so a fraction of a pixel never pushes the last item past the container.
5566
+ const value = Math.max(0, Math.floor(gap * 100) / 100);
5567
+ if (value === this.lastGap) {
5568
+ return;
5569
+ }
5570
+ this.lastGap = value;
5571
+ this.element.style.setProperty('--md-toolbar-gap-free', `${value}px`);
5572
+ }
5573
+ extent(element, vertical) {
5574
+ const rect = element.getBoundingClientRect();
5575
+ return vertical ? rect.height : rect.width;
5576
+ }
5577
+ contentExtent(element, vertical) {
5578
+ const size = vertical ? element.clientHeight : element.clientWidth;
5579
+ return Math.max(0, size - this.paddingExtent(element, vertical));
5580
+ }
5581
+ paddingExtent(element, vertical) {
5582
+ const style = getComputedStyle(element);
5583
+ const start = parseFloat(vertical ? style.paddingTop : style.paddingLeft) || 0;
5584
+ const end = parseFloat(vertical ? style.paddingBottom : style.paddingRight) || 0;
5585
+ return start + end;
5586
+ }
5587
+ /** What the other children of the layout take, the flex gap that separates them included. */
5588
+ siblingExtent(layout, container, vertical) {
5589
+ const style = getComputedStyle(layout);
5590
+ const gap = parseFloat(vertical ? style.rowGap : style.columnGap) || 0;
5591
+ return Array.from(layout.children)
5592
+ .filter((child) => child !== container)
5593
+ .reduce((sum, child) => sum + this.extent(child, vertical) + gap, 0);
5594
+ }
5595
+ watchPersistentItems(element) {
5596
+ this.persistentObserver?.disconnect();
5597
+ const update = () => {
5598
+ this.hasPersistentItem.set(!!element.querySelector('.md3-toolbar-slots [md3-toolbar-persistent]'));
5599
+ };
5600
+ update();
5601
+ if (typeof MutationObserver === 'undefined') {
5602
+ return;
5603
+ }
5604
+ this.persistentObserver = new MutationObserver(update);
5605
+ this.persistentObserver.observe(element, {
5606
+ childList: true,
5607
+ subtree: true,
5608
+ attributeFilter: ['md3-toolbar-persistent'],
5609
+ });
5610
+ }
5611
+ checkConfiguration() {
5612
+ const explicit = this.orientation();
5613
+ const orientation = this.effectiveOrientation();
5614
+ if (this.isRailRegion() && !this.isFloating()) {
5615
+ this.warn('a docked toolbar needs the full window width, so it belongs in a scaffold bar region, not a rail.');
5616
+ }
5617
+ if (explicit === 'horizontal' && this.isRailRegion()) {
5618
+ this.warn('a horizontal toolbar does not fit a scaffold rail region. Move it to a bar region, or drop the orientation input.');
5619
+ }
5620
+ if (explicit === 'vertical' && this.isBarRegion()) {
5621
+ this.warn('a vertical toolbar does not fit a scaffold bar region. Move it to a rail region, or drop the orientation input.');
5622
+ }
5623
+ if (this.scrollAction() !== 'none' && orientation === 'vertical') {
5624
+ this.warn('a vertical toolbar ignores scroll-action.');
5625
+ }
5626
+ if (this.scrollAction() === 'collapse' && this.isFloating() && !this.canCollapse()) {
5627
+ this.warn('scroll-action="collapse" needs a FAB, or one item with the md3-toolbar-persistent attribute. The toolbar will hide instead.');
5628
+ }
5629
+ if (this.scrollAction() === 'collapse' && !this.isFloating()) {
5630
+ this.warn('a docked toolbar cannot collapse to a FAB. The toolbar will hide instead.');
5631
+ }
4839
5632
  }
4840
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBar, deps: [{ token: i0.ElementRef }, { token: LayoutService }], target: i0.ɵɵFactoryTarget.Component });
4841
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: AppBar, isStandalone: true, selector: "md3-app-bar", inputs: { title: { classPropertyName: "title", publicName: "bar-title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "bar-subtitle", isSignal: true, isRequired: false, transformFunction: null }, appBarType: { classPropertyName: "appBarType", publicName: "bar-type", isSignal: true, isRequired: false, transformFunction: null }, appBarScrollingStyle: { classPropertyName: "appBarScrollingStyle", publicName: "scroll-style", isSignal: true, isRequired: false, transformFunction: null }, autoHide: { classPropertyName: "autoHide", publicName: "auto-hide", isSignal: true, isRequired: false, transformFunction: null }, centerAligned: { classPropertyName: "centerAligned", publicName: "center-aligned", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "banner" }, properties: { "class.md3-scrolled": "mainIsScrolled()", "class.md3-auto-hide": "autoHide()", "class.md3-scrolling-down": "isScrollingDown()" } }, providers: [
5633
+ warn(message) {
5634
+ console.warn(`[md3-toolbar] ${message}`);
5635
+ }
5636
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Toolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
5637
+ 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: [
4842
5638
  {
4843
5639
  provide: MD3_BUTTON_CONTEXT,
4844
- useExisting: AppBar,
5640
+ useExisting: Toolbar,
4845
5641
  },
4846
- ], queries: [{ propertyName: "logo", first: true, predicate: AppBarLogo, descendants: true, isSignal: true }, { propertyName: "avatar", first: true, predicate: Avatar, descendants: true, isSignal: true }], ngImport: i0, 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"], dependencies: [{ kind: "directive", type: TypeHeadline, selector: "md3-type-headline, [md3-type-headline]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeTitle, selector: "md3-type-title, [md3-type-title]", inputs: ["size", "color", "emphasized"] }, { kind: "directive", type: TypeDisplay, selector: "md3-type-display, [md3-type-display]", inputs: ["size", "color", "emphasized"] }] });
5642
+ ], 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"] });
4847
5643
  }
4848
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: AppBar, decorators: [{
5644
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Toolbar, decorators: [{
4849
5645
  type: Component,
4850
- args: [{ selector: 'md3-app-bar', imports: [
4851
- TypeHeadline,
4852
- TypeTitle,
4853
- TypeDisplay,
4854
- ], providers: [
5646
+ args: [{ selector: 'md3-toolbar', providers: [
4855
5647
  {
4856
5648
  provide: MD3_BUTTON_CONTEXT,
4857
- useExisting: AppBar,
5649
+ useExisting: Toolbar,
4858
5650
  },
4859
5651
  ], host: {
4860
- role: 'banner',
4861
- '[class.md3-scrolled]': 'mainIsScrolled()',
4862
- '[class.md3-auto-hide]': 'autoHide()',
4863
- '[class.md3-scrolling-down]': 'isScrollingDown()',
4864
- }, 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
- }], 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 }] }] } });
5652
+ 'role': 'toolbar',
5653
+ '[attr.aria-orientation]': 'effectiveOrientation()',
5654
+ '[class.md3-floating-region]': 'isFloatingRegion()',
5655
+ '[class.md3-bar-region]': 'isBarRegion()',
5656
+ '[class.md3-rail-region]': 'isRailRegion()',
5657
+ '[class.md3-hidden]': 'isHidden()',
5658
+ '[class.md3-collapsed]': 'isCollapsed()',
5659
+ '[class.md3-collapse-to-fab]': 'isCollapsedToFab()',
5660
+ '(focusin)': 'onFocusIn()',
5661
+ '(focusout)': 'onFocusOut($event)',
5662
+ }, 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"] }]
5663
+ }], 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 }] }] } });
5664
+
5665
+ class ToolbarItem {
5666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5667
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: ToolbarItem, isStandalone: true, selector: "md3-toolbar-item", ngImport: i0 });
5668
+ }
5669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ToolbarItem, decorators: [{
5670
+ type: Directive,
5671
+ args: [{
5672
+ selector: 'md3-toolbar-item',
5673
+ }]
5674
+ }] });
4866
5675
 
4867
5676
  class NavigationItem {
4868
5677
  el = inject((ElementRef));
@@ -5235,193 +6044,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
5235
6044
  }]
5236
6045
  }] });
5237
6046
 
5238
- const DIALOG_DATA = new InjectionToken('MD3_DIALOG_DATA');
5239
- const DIALOG_CONFIG = new InjectionToken('MD3_DIALOG_CONFIG');
5240
- const DIALOG_COMPONENT = new InjectionToken('MD3_DIALOG_COMPONENT');
5241
- const DIALOG_EXIT_ANIMATION_FALLBACK_MS = 300;
5242
- const HIDDEN_CLASS = 'md3-dialog-hidden';
5243
- class DialogRef {
5244
- cdkRef;
5245
- isFullScreen;
5246
- closed = new Subject();
5247
- closing = new Subject();
5248
- hiddenChanges = new Subject();
5249
- closePromise = null;
5250
- closeStarted = false;
5251
- closeSettled = false;
5252
- hidden = false;
5253
- /** Shell hosting the dialog: the regular dialog or the full screen one. */
5254
- dialogInstance;
5255
- /**
5256
- * Filled by DialogService after the user component is attached. Keeping the
5257
- * instance here lets callers imperatively update inputs when that is useful.
5258
- */
5259
- componentInstance;
5260
- /** Overlay hosting the dialog, useful to reach the panel and the scrim. */
5261
- get overlayRef() {
5262
- return this.cdkRef.overlayRef;
5263
- }
5264
- /** Whether the dialog started closing. Such a dialog cannot be hidden or shown anymore. */
5265
- get isClosing() {
5266
- return this.closeStarted;
5267
- }
5268
- /** Whether the dialog is currently hidden, on request or behind another dialog. */
5269
- get isHidden() {
5270
- return this.hidden;
5271
- }
5272
- constructor(cdkRef, disableCloseEvents,
5273
- /** Whether this reference belongs to a full screen dialog. */
5274
- isFullScreen = false) {
5275
- this.cdkRef = cdkRef;
5276
- this.isFullScreen = isFullScreen;
5277
- // Closing always goes through this reference so the exit animation can
5278
- // run before the CDK disposes the overlay. Detachments triggered from
5279
- // the outside (navigation, scroll strategy) still settle this ref.
5280
- this.cdkRef.closed.pipe(take(1)).subscribe((result) => this.settle(result));
5281
- if (!disableCloseEvents) {
5282
- this.connectCloseEvents();
5283
- }
5284
- }
5285
- /** Closes the dialog. The promise resolves once the exit animation is done. */
5286
- close(result) {
5287
- if (this.closePromise) {
5288
- return this.closePromise;
5289
- }
5290
- this.startClosing();
5291
- this.closePromise = this.startCloseAnimation().then(() => this.cdkRef.close(result));
5292
- return this.closePromise;
5293
- }
5294
- /**
5295
- * Hides the dialog with the closing animation while keeping it alive, so
5296
- * its content, form state and subscriptions survive until show() is called.
5297
- * The page underneath becomes usable again while the dialog waits behind it.
5298
- * The promise resolves once the dialog is out of sight.
5299
- */
5300
- hide() {
5301
- if (this.hidden || this.closeStarted) {
5302
- return Promise.resolve();
5303
- }
5304
- this.hidden = true;
5305
- this.toggleHiddenState(true);
5306
- this.dialogInstance?.setActive(false);
5307
- this.hiddenChanges.next(true);
5308
- return this.waitForSurfaceAnimation();
5309
- }
5310
- /**
5311
- * Brings a hidden dialog back with the opening animation. Focus moves back
5312
- * into the dialog even when it was never hidden, which is what makes it
5313
- * usable again once the dialog above it closes.
5314
- */
5315
- show() {
5316
- if (this.closeStarted) {
5317
- return;
5318
- }
5319
- if (this.hidden) {
5320
- this.hidden = false;
5321
- this.toggleHiddenState(false);
5322
- this.dialogInstance?.setActive(true);
5323
- this.hiddenChanges.next(false);
5324
- }
5325
- this.dialogInstance?.recaptureFocus();
5326
- }
5327
- /** Emits when the dialog starts closing, before the exit animation runs. */
5328
- beforeClosed() {
5329
- return this.closing.asObservable();
5330
- }
5331
- /** Emits the new value of `isHidden` every time the dialog is hidden or shown. */
5332
- hiddenChanged() {
5333
- return this.hiddenChanges.asObservable();
5334
- }
5335
- afterClosed() {
5336
- return this.closed.asObservable();
5337
- }
5338
- connectCloseEvents() {
5339
- // The CDK config keeps `disableClose` on, so the scrim and Escape key
5340
- // are handled here instead and the dialog can animate out.
5341
- this.cdkRef.backdropClick.pipe(take(1)).subscribe(() => {
5342
- this.cdkRef.containerInstance._closeInteractionType = 'mouse';
5343
- this.close();
5344
- });
5345
- // A hidden dialog is not the one the Escape key is meant for, even
5346
- // though the overlay it sits in is still the one receiving the event.
5347
- this.cdkRef.keydownEvents.pipe(filter((event) => !this.hidden && event.key === 'Escape' && !hasModifierKey(event)), take(1)).subscribe((event) => {
5348
- event.preventDefault();
5349
- this.cdkRef.containerInstance._closeInteractionType = 'keyboard';
5350
- this.close();
5351
- });
5352
- }
5353
- toggleHiddenState(isHidden) {
5354
- const overlayRef = this.cdkRef.overlayRef;
5355
- const panel = overlayRef.overlayElement;
5356
- const backdrop = overlayRef.backdropElement;
5357
- panel.classList.toggle(HIDDEN_CLASS, isHidden);
5358
- backdrop?.classList.toggle(HIDDEN_CLASS, isHidden);
5359
- // `inert` keeps a hidden dialog out of the tab order and away from
5360
- // assistive technology without removing it from the DOM.
5361
- if (isHidden) {
5362
- panel.setAttribute('inert', '');
5363
- }
5364
- else {
5365
- panel.removeAttribute('inert');
5366
- }
5367
- }
5368
- startClosing() {
5369
- if (this.closeStarted) {
5370
- return;
5371
- }
5372
- this.closeStarted = true;
5373
- this.closing.next();
5374
- this.closing.complete();
5375
- }
5376
- startCloseAnimation() {
5377
- const overlayRef = this.cdkRef.overlayRef;
5378
- const wasVisible = !this.hidden;
5379
- overlayRef.overlayElement.classList.add('md3-dialog-closing');
5380
- overlayRef.backdropElement?.classList.add('md3-dialog-closing');
5381
- this.dialogInstance?.setActive(false);
5382
- // A hidden dialog already played the exit animation, so there is
5383
- // nothing left to transition and it can be disposed right away.
5384
- return wasVisible ? this.waitForSurfaceAnimation() : Promise.resolve();
5385
- }
5386
- /** Resolves when the surface finished animating, with a timeout as a safety net. */
5387
- waitForSurfaceAnimation() {
5388
- const panel = this.cdkRef.overlayRef.overlayElement;
5389
- const surface = this.dialogInstance?.surfaceElement ?? panel;
5390
- return new Promise((resolve) => {
5391
- let isResolved = false;
5392
- let timeoutId = setTimeout(done, DIALOG_EXIT_ANIMATION_FALLBACK_MS);
5393
- function done() {
5394
- if (isResolved) {
5395
- return;
5396
- }
5397
- isResolved = true;
5398
- clearTimeout(timeoutId);
5399
- surface.removeEventListener('transitionend', onTransitionEnd);
5400
- resolve();
5401
- }
5402
- function onTransitionEnd(event) {
5403
- if (event.target === surface) {
5404
- done();
5405
- }
5406
- }
5407
- surface.addEventListener('transitionend', onTransitionEnd);
5408
- });
5409
- }
5410
- /** Emits the result once the CDK reference is closed. Focus is restored by the container. */
5411
- settle(result) {
5412
- if (this.closeSettled) {
5413
- return;
5414
- }
5415
- // Covers detachments that did not go through close(), so anything
5416
- // waiting on beforeClosed() is still notified.
5417
- this.startClosing();
5418
- this.closeSettled = true;
5419
- this.hiddenChanges.complete();
5420
- this.closed.next(result);
5421
- this.closed.complete();
5422
- }
5423
- }
5424
-
5425
6047
  /**
5426
6048
  * Material 3 dialog shell. It extends the CDK dialog container, so focus
5427
6049
  * trapping, focus restoration and the ARIA attributes are handled by the CDK
@@ -5463,17 +6085,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
5463
6085
  }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }] } });
5464
6086
 
5465
6087
  /**
5466
- * Material 3 full screen dialog shell. It covers the viewport and lays its
5467
- * content out like the scaffold does, with a main pane and a side sheet outlet
5468
- * on each side, so side sheets opened while it is up land inside the dialog
5469
- * instead of behind it.
6088
+ * Material 3 full screen dialog shell. It covers the viewport and holds the content.
6089
+ *
6090
+ * The content is an `md3-layout`. The layout places the regions the bar rows for an app bar
6091
+ * or a toolbar, the rail columns, and the panes where side sheets open — so the dialog itself
6092
+ * places nothing but the content. A content root that is not a layout gets a warning in
6093
+ * development mode, and the shell falls back to panes of its own, so a side sheet never opens
6094
+ * behind the dialog where nobody can see it.
5470
6095
  */
5471
6096
  class FullScreenDialog extends CdkDialogContainer {
5472
6097
  surface = viewChild('surface', /* @ts-ignore */
5473
6098
  ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
6099
+ mainPane = viewChild('mainPane', /* @ts-ignore */
6100
+ ...(ngDevMode ? [{ debugName: "mainPane" }] : /* istanbul ignore next */ []));
5474
6101
  startOutlet = viewChild('startOutlet', { ...(ngDevMode ? { debugName: "startOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
5475
6102
  endOutlet = viewChild('endOutlet', { ...(ngDevMode ? { debugName: "endOutlet" } : /* istanbul ignore next */ {}), read: CdkPortalOutlet });
5476
6103
  sheets = inject(SheetsService);
6104
+ /** True while the shell holds the side sheet outlets, which happens without a layout only. */
6105
+ ownsSideSheetOutlets = false;
5477
6106
  isActive = signal(false, /* @ts-ignore */
5478
6107
  ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
5479
6108
  config = inject(DIALOG_CONFIG, { optional: true }) ?? {};
@@ -5481,28 +6110,66 @@ class FullScreenDialog extends CdkDialogContainer {
5481
6110
  return this.surface()?.nativeElement ?? null;
5482
6111
  }
5483
6112
  ngAfterViewInit() {
6113
+ // The content is attached by now, so the layout it brings has already taken the
6114
+ // outlets. Its panes sit under the bar regions, which is where a side sheet belongs.
6115
+ const layout = this.findContentLayout();
6116
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
6117
+ this.checkContentLayout(layout);
6118
+ }
6119
+ if (layout) {
6120
+ return;
6121
+ }
6122
+ // No layout, so the shell keeps the dialog self-sufficient. Without this the next side
6123
+ // sheet would open in the outlet underneath — the page scaffold, behind the dialog.
5484
6124
  const startOutlet = this.startOutlet();
5485
6125
  const endOutlet = this.endOutlet();
5486
- // Taking the outlets over is what sends the next side sheet inside the
5487
- // dialog. The scaffold gets them back when this dialog is destroyed.
5488
6126
  if (startOutlet) {
5489
6127
  this.sheets.registerSideSheetOutlet('start', startOutlet);
5490
6128
  }
5491
6129
  if (endOutlet) {
5492
6130
  this.sheets.registerSideSheetOutlet('end', endOutlet);
5493
6131
  }
6132
+ this.ownsSideSheetOutlets = !!startOutlet || !!endOutlet;
5494
6133
  }
5495
6134
  ngOnDestroy() {
5496
- const startOutlet = this.startOutlet();
5497
- const endOutlet = this.endOutlet();
5498
- if (startOutlet) {
5499
- this.sheets.unregisterSideSheetOutlet('start', startOutlet);
5500
- }
5501
- if (endOutlet) {
5502
- this.sheets.unregisterSideSheetOutlet('end', endOutlet);
6135
+ if (this.ownsSideSheetOutlets) {
6136
+ const startOutlet = this.startOutlet();
6137
+ const endOutlet = this.endOutlet();
6138
+ if (startOutlet) {
6139
+ this.sheets.unregisterSideSheetOutlet('start', startOutlet);
6140
+ }
6141
+ if (endOutlet) {
6142
+ this.sheets.unregisterSideSheetOutlet('end', endOutlet);
6143
+ }
6144
+ this.ownsSideSheetOutlets = false;
5503
6145
  }
5504
6146
  super.ngOnDestroy();
5505
6147
  }
6148
+ /**
6149
+ * The layout at the root of the content, if the content brought one.
6150
+ *
6151
+ * The root is either the layout itself, or the component that holds it — a dialog is
6152
+ * normally opened with a component whose own template starts with `md3-layout`.
6153
+ */
6154
+ findContentLayout() {
6155
+ const content = this.mainPane()?.nativeElement.firstElementChild;
6156
+ if (!content) {
6157
+ return null;
6158
+ }
6159
+ if (content.tagName === 'MD3-LAYOUT') {
6160
+ return content;
6161
+ }
6162
+ const root = content.firstElementChild;
6163
+ return root?.tagName === 'MD3-LAYOUT' ? root : null;
6164
+ }
6165
+ checkContentLayout(layout) {
6166
+ if (layout) {
6167
+ return;
6168
+ }
6169
+ console.warn('[md3-fullscreen-dialog] the content of a full screen dialog should start with '
6170
+ + 'md3-layout. Without it the dialog has no bar and no rail region, so an app bar or '
6171
+ + 'a toolbar has nowhere to go, and the content does not scroll on its own.');
6172
+ }
5506
6173
  startEnterAnimation() {
5507
6174
  requestAnimationFrame(() => {
5508
6175
  this.isActive.set(true);
@@ -5515,14 +6182,14 @@ class FullScreenDialog extends CdkDialogContainer {
5515
6182
  this._recaptureFocus();
5516
6183
  }
5517
6184
  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%;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"] }] });
6185
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: FullScreenDialog, isStandalone: true, selector: "md3-fullscreen-dialog", viewQueries: [{ propertyName: "surface", first: true, predicate: ["surface"], descendants: true, isSignal: true }, { propertyName: "mainPane", first: true, predicate: ["mainPane"], descendants: true, isSignal: true }, { propertyName: "startOutlet", first: true, predicate: ["startOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }, { propertyName: "endOutlet", first: true, predicate: ["endOutlet"], descendants: true, read: CdkPortalOutlet, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\" #mainPane>\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
5519
6186
  }
5520
6187
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialog, decorators: [{
5521
6188
  type: Component,
5522
6189
  args: [{ selector: 'md3-fullscreen-dialog', imports: [
5523
6190
  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%;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
- }], 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 }] }] } });
6191
+ ], template: "<!-- The role and aria attributes live on the host element, applied by the CDK dialog container. -->\n<div\n #surface\n class=\"md3-fullscreen-dialog-container\"\n [class.md3-active]=\"isActive()\"\n [class.md-scheme-dark]=\"config.scheme == 'dark'\"\n [class.md-scheme-light]=\"config.scheme == 'light'\"\n [attr.dir]=\"config.direction ?? null\">\n <div class=\"md3-panes-container md3-scrollable\">\n <!--\n The CDK attaches the dialog content to the first portal outlet of\n this template, so the main pane has to come first. The panes are\n placed by grid area, which makes the DOM order irrelevant visually.\n -->\n <div class=\"md3-pane md3-pane-main\" #mainPane>\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-start\">\n <ng-template #startOutlet cdkPortalOutlet></ng-template>\n </div>\n <div class=\"md3-pane md3-pane-end\">\n <ng-template #endOutlet cdkPortalOutlet></ng-template>\n </div>\n </div>\n</div>\n", styles: ["::ng-deep .cdk-overlay-container{position:fixed;z-index:1000;inset:0;pointer-events:none;font-size:1rem}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper{position:absolute;display:flex;inset:0;pointer-events:none;overflow:hidden}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper:has(>.md3-fullscreen-dialog-panel){padding:0}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel{width:100%;height:100%;max-width:none;pointer-events:auto}::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-closing,::ng-deep .cdk-overlay-container .cdk-global-overlay-wrapper .md3-fullscreen-dialog-panel.md3-dialog-hidden{pointer-events:none}:host{display:block;height:100%;width:100%;outline:0}:host .md3-fullscreen-dialog-container{display:grid;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;color:rgb(var(--md-scheme-on-surface));background-color:rgb(var(--md-scheme-surface));transition:all var(--md-motion-expressive-default-spatial-duration) var(--md-motion-expressive-default-spatial-easing);opacity:0;transform:translateY(1.5em)}:host .md3-fullscreen-dialog-container.md3-active{opacity:1;transform:none}:host .md3-panes-container{display:grid;grid-template-areas:\"start main end\";grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}:host .md3-panes-container .md3-pane{justify-self:stretch;align-self:stretch;min-width:0;min-height:0;height:100%;overflow:hidden}:host .md3-panes-container .md3-pane.md3-pane-start{grid-area:start}:host .md3-panes-container .md3-pane.md3-pane-main{position:relative;grid-area:main;z-index:1;display:grid;grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr)}:host .md3-panes-container .md3-pane.md3-pane-main>::ng-deep *{min-width:0;min-height:0;height:100%;max-height:100dvh;max-width:100dvw}:host .md3-panes-container .md3-pane.md3-pane-end{grid-area:end}\n"] }]
6192
+ }], propDecorators: { surface: [{ type: i0.ViewChild, args: ['surface', { isSignal: true }] }], mainPane: [{ type: i0.ViewChild, args: ['mainPane', { isSignal: true }] }], startOutlet: [{ type: i0.ViewChild, args: ['startOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }], endOutlet: [{ type: i0.ViewChild, args: ['endOutlet', { ...{ read: CdkPortalOutlet }, isSignal: true }] }] } });
5526
6193
 
5527
6194
  const PANEL_CLASS = 'md3-dialog-panel';
5528
6195
  const FULL_SCREEN_PANEL_CLASS = 'md3-fullscreen-dialog-panel';
@@ -6028,35 +6695,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
6028
6695
  args: [{ selector: 'md3-dialog-actions', imports: [], template: "<div class=\"md3-actions\">\n <ng-content></ng-content>\n</div>", styles: [":host{display:block;margin:1.5em}:host .md3-actions{display:flex;gap:1em;flex-direction:row-reverse}\n"] }]
6029
6696
  }] });
6030
6697
 
6031
- /**
6032
- * Header of a full screen dialog: a leading icon button to leave the dialog,
6033
- * the headline, and a trailing action. It sticks to the top of the dialog while
6034
- * the content scrolls underneath.
6035
- */
6036
- class FullScreenDialogHeader {
6037
- // context values
6038
- buttonContextSize = signal('small', /* @ts-ignore */
6039
- ...(ngDevMode ? [{ debugName: "buttonContextSize" }] : /* istanbul ignore next */ []));
6040
- buttonContextWidth = signal('default', /* @ts-ignore */
6041
- ...(ngDevMode ? [{ debugName: "buttonContextWidth" }] : /* istanbul ignore next */ []));
6042
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialogHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
6043
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: FullScreenDialogHeader, isStandalone: true, selector: "md3-fullscreen-dialog-header", providers: [
6044
- {
6045
- provide: MD3_BUTTON_CONTEXT,
6046
- useExisting: FullScreenDialogHeader,
6047
- },
6048
- ], ngImport: i0, template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <ng-content></ng-content>\n</div>\n<div class=\"md3-actions-container\">\n <ng-content select=\"[md3-header-trailing]\"></ng-content>\n</div>\n", styles: [":host{--foreground-color: rgb(var(--md-scheme-on-surface));position:sticky;top:0;z-index:3;grid-area:header;display:flex;align-items:center;gap:.5em;height:4em;padding:0 1em;color:var(--foreground-color);background-color:rgb(var(--md-scheme-surface))}:host ::ng-deep [md3-header-leading]:first-child{margin-inline-start:-.5em}:host .md3-title-container{flex:1 1 auto;min-width:0;color:inherit}:host .md3-title-container:first-child{padding-inline-start:.5em}:host .md3-actions-container{display:flex;flex:0 0 auto;align-items:center;gap:.5em}\n"] });
6049
- }
6050
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: FullScreenDialogHeader, decorators: [{
6051
- type: Component,
6052
- args: [{ selector: 'md3-fullscreen-dialog-header', imports: [], providers: [
6053
- {
6054
- provide: MD3_BUTTON_CONTEXT,
6055
- useExisting: FullScreenDialogHeader,
6056
- },
6057
- ], template: "<ng-content select=\"[md3-icon-button][md3-header-leading]\"></ng-content>\n<div class=\"md3-title-container\">\n <ng-content></ng-content>\n</div>\n<div class=\"md3-actions-container\">\n <ng-content select=\"[md3-header-trailing]\"></ng-content>\n</div>\n", styles: [":host{--foreground-color: rgb(var(--md-scheme-on-surface));position:sticky;top:0;z-index:3;grid-area:header;display:flex;align-items:center;gap:.5em;height:4em;padding:0 1em;color:var(--foreground-color);background-color:rgb(var(--md-scheme-surface))}:host ::ng-deep [md3-header-leading]:first-child{margin-inline-start:-.5em}:host .md3-title-container{flex:1 1 auto;min-width:0;color:inherit}:host .md3-title-container:first-child{padding-inline-start:.5em}:host .md3-actions-container{display:flex;flex:0 0 auto;align-items:center;gap:.5em}\n"] }]
6058
- }] });
6059
-
6060
6698
  const MENU_DATA = new InjectionToken('MD3_MENU_DATA');
6061
6699
  const MENU_CONFIG = new InjectionToken('MD3_MENU_CONFIG');
6062
6700
  const MENU_COMPONENT = new InjectionToken('MD3_MENU_COMPONENT');
@@ -6880,7 +7518,7 @@ class Snackbar {
6880
7518
  constructor(el) {
6881
7519
  this.el = el;
6882
7520
  effect(() => {
6883
- const inset = this.layout.bottomInset() + (this.config.bottomOffset ?? 0);
7521
+ const inset = this.layout.bottomSafeInset() + (this.config.bottomOffset ?? 0);
6884
7522
  this.el.nativeElement.style.setProperty('--md3-snackbar-bottom-inset', `${inset}px`);
6885
7523
  });
6886
7524
  effect(() => {
@@ -7087,5 +7725,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
7087
7725
  * Generated bundle index. Do not edit.
7088
7726
  */
7089
7727
 
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 };
7728
+ export { AppBar, AppBarLogo, Avatar, BOTTOM_SHEET_COMPONENT, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, Badge, BottomSheetRef, BottomSheetService, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, Grid, GridItem, IconButton, IconElement, InputElement, Layout, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, ModalBottomSheetRef, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StandardBottomSheetRef, StateComponent, SupportingText, Switch, TextField, Toolbar, ToolbarItem, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, ViewportService, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
7091
7729
  //# sourceMappingURL=almoamendev-ngx-md3.mjs.map