@almoamendev/ngx-md3 0.2.1 → 0.3.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almoamendev/ngx-md3",
3
- "version": "0.2.1",
3
+ "version": "0.3.4",
4
4
  "description": "MD3-style Angular components & style library",
5
5
  "author": "Murtadha (Hussain) Almoamen",
6
6
  "license": "MIT",
@@ -44,6 +44,37 @@ type ListLeadingType = 'icon' | 'avatar' | 'media' | 'selection-input';
44
44
 
45
45
  type ListLeadingSize = 'image' | 'small-video' | 'large-video';
46
46
 
47
+ /**
48
+ * The arrangement strategy used to size and position carousel items.
49
+ *
50
+ * Material Design 3 defines four layouts. Only `multi-browse` is implemented today; the
51
+ * remaining values will be added to this union as their strategies land, which is a
52
+ * non-breaking change for consumers.
53
+ */
54
+ type CarouselLayout = 'multi-browse';
55
+
56
+ /**
57
+ * Where the focal (large) items sit within the carousel container.
58
+ */
59
+ type CarouselAlignment = 'start' | 'center';
60
+
61
+ /**
62
+ * The axis the carousel scrolls along.
63
+ *
64
+ * Only `horizontal` is implemented today. The type exists so vertical layouts can be added
65
+ * without changing the public API shape.
66
+ */
67
+ type CarouselOrientation = 'horizontal';
68
+
69
+ /**
70
+ * Size band a carousel item currently renders at.
71
+ *
72
+ * Item sizes are continuous, so this is the nearest of the arrangement's three sizes rather than
73
+ * the keyline the item happens to be resting on. It changes as the item is scrolled, and is
74
+ * mirrored onto the element as `md3-large`, `md3-medium` or `md3-small`.
75
+ */
76
+ type CarouselItemSize = 'large' | 'medium' | 'small';
77
+
47
78
  /**
48
79
  * What happens to a dialog that is already open when a new dialog opens.
49
80
  * - close: the open dialogs are closed before the new one opens.
@@ -263,6 +294,147 @@ interface SnackbarConfig<D = unknown> {
263
294
  injector?: Injector;
264
295
  }
265
296
 
297
+ /**
298
+ * A solved distribution of large, medium and small items that exactly fills the carousel
299
+ * container. Produced by a {@link CarouselStrategy}, consumed by the keyline builder.
300
+ *
301
+ * All sizes are in pixels and already include the item gap.
302
+ */
303
+ interface CarouselArrangement {
304
+ /** Size of a fully unmasked item. Also the size each item occupies in scroll space. */
305
+ largeSize: number;
306
+ largeCount: number;
307
+ mediumSize: number;
308
+ mediumCount: number;
309
+ smallSize: number;
310
+ smallCount: number;
311
+ }
312
+
313
+ /**
314
+ * A single slot in the carousel container.
315
+ *
316
+ * An item does not have a fixed size: it adopts the size of whichever keyline it is currently
317
+ * passing through, interpolating continuously between neighbours as it scrolls.
318
+ *
319
+ * Two coordinate systems are in play, both measured along the scroll axis from the container's
320
+ * logical start edge:
321
+ *
322
+ * - **screen space** (`screenLoc`) — where the keyline actually renders, the running sum of
323
+ * masked sizes.
324
+ * - **scroll space** (`scrollLoc`) — where the keyline sits if every item were fully unmasked.
325
+ * Keylines are always `largeSize` apart here, which is what makes item positions a simple
326
+ * function of `scrollLeft`.
327
+ */
328
+ interface CarouselKeyline {
329
+ /** Centre of the keyline in scroll space. Used to look an item up by its scroll position. */
330
+ scrollLoc: number;
331
+ /** Centre of the keyline in screen space. Used to position the item. */
332
+ screenLoc: number;
333
+ /** Rendered size of an item resting exactly on this keyline. */
334
+ maskedSize: number;
335
+ /** True for the large keylines — the "selected" region of the carousel. */
336
+ isFocal: boolean;
337
+ /** True for the off-screen keylines items shrink into as they leave the container. */
338
+ isAnchor: boolean;
339
+ }
340
+ /**
341
+ * A complete keyline arrangement for one discrete shift step.
342
+ *
343
+ * Every state in a carousel holds the same number of keylines, so states can be interpolated
344
+ * index by index.
345
+ */
346
+ interface CarouselKeylineState {
347
+ keylines: CarouselKeyline[];
348
+ /** Offset of the focal region's leading edge, in screen space. */
349
+ focalStart: number;
350
+ firstFocalIndex: number;
351
+ lastFocalIndex: number;
352
+ }
353
+ /**
354
+ * Everything needed to place items for a given container size, resolved once per layout pass.
355
+ */
356
+ interface CarouselGeometry {
357
+ /** The solved arrangement this geometry was built from. */
358
+ arrangement: CarouselArrangement;
359
+ /** Shift steps ordered by ascending `focalStart`, from the start state to the end state. */
360
+ steps: CarouselKeylineState[];
361
+ /** Index within `steps` of the arrangement's resting state. */
362
+ defaultStep: number;
363
+ /** Size of a fully unmasked item, and the scroll distance between consecutive items. */
364
+ itemSize: number;
365
+ /** Scroll distance over which keylines shift while approaching the start of the list. */
366
+ startShiftRange: number;
367
+ /** Scroll distance over which keylines shift while approaching the end of the list. */
368
+ endShiftRange: number;
369
+ /** Largest valid scroll offset. */
370
+ maxScroll: number;
371
+ /**
372
+ * Highest index the carousel can come to rest on.
373
+ *
374
+ * The final `largeCount` items share the focal range at `maxScroll`, so they are all visible
375
+ * at once and none of them has a resting position of its own. Scrolling past this index is
376
+ * impossible, which is why it is the point where the carousel counts as being at the end.
377
+ */
378
+ lastIndex: number;
379
+ /** Total inline size of the scrollable content. */
380
+ scrollSize: number;
381
+ }
382
+ /**
383
+ * Resolved placement for a single item at a given scroll offset.
384
+ */
385
+ interface CarouselItemGeometry {
386
+ /** Distance from the container's logical start edge to the item's leading edge. */
387
+ offset: number;
388
+ /** Current rendered size of the item. */
389
+ maskedSize: number;
390
+ /** Which of the arrangement's three sizes the item currently renders closest to. */
391
+ size: CarouselItemSize;
392
+ /** 0 when fully unmasked, approaching 1 as the item crops away. */
393
+ maskRatio: number;
394
+ /** True while the item rests within the focal region. */
395
+ isFocal: boolean;
396
+ /** False when the item is outside the container and should not be rendered. */
397
+ isVisible: boolean;
398
+ }
399
+
400
+ /**
401
+ * Everything a strategy needs to solve an arrangement. All sizes are in pixels.
402
+ */
403
+ interface CarouselStrategyContext {
404
+ /** Size of the carousel along the scroll axis. */
405
+ containerSize: number;
406
+ /** Requested size of a fully unmasked item, gap included. */
407
+ itemSize: number;
408
+ /** Smallest a small item is allowed to be, gap included. */
409
+ smallSizeMin: number;
410
+ /** Largest a small item is allowed to be, gap included. */
411
+ smallSizeMax: number;
412
+ /** Number of items projected into the carousel. */
413
+ itemCount: number;
414
+ alignment: CarouselAlignment;
415
+ }
416
+ /**
417
+ * Sizes and counts the items of a carousel so they fill the container in a visually balanced way.
418
+ *
419
+ * Implement this to add a new carousel layout, then register it in `CAROUSEL_STRATEGIES`.
420
+ * Strategies must be pure: same context in, same arrangement out.
421
+ */
422
+ interface CarouselStrategy {
423
+ /**
424
+ * Whether items must come to rest exactly on keylines.
425
+ *
426
+ * Layouts that resize items need this: their arrangement only reads correctly when every
427
+ * item is sitting on a keyline, and settling part-way through leaves items at sizes that
428
+ * belong to no keyline at all. Layouts that keep items at a fixed size, such as uncontained,
429
+ * can scroll freely.
430
+ *
431
+ * This is a property of the layout rather than something consumers choose, so that a
432
+ * carousel can never be configured into a state that contradicts its own arrangement.
433
+ */
434
+ readonly snap: boolean;
435
+ arrange(context: CarouselStrategyContext): CarouselArrangement;
436
+ }
437
+
266
438
  declare class TypeDisplay {
267
439
  el: ElementRef;
268
440
  size: _angular_core.InputSignal<TextSize | "default">;
@@ -598,6 +770,234 @@ declare class Card implements AfterViewInit {
598
770
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Card, "md3-card, button[md3-card], a[md3-card]", never, { "cardType": { "alias": "card-type"; "required": false; "isSignal": true; }; "isInteractive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, [{ directive: typeof StateComponent; inputs: {}; outputs: {}; }]>;
599
771
  }
600
772
 
773
+ /**
774
+ * A single item within an `md3-carousel`.
775
+ *
776
+ * The item is a clipping box whose content stays at full size, so scrolling crops the item
777
+ * towards its centre rather than squashing it. Content should be full-bleed — an image or a
778
+ * background that reaches the edges — or the crop will reveal empty space.
779
+ *
780
+ * Position and size are written straight to CSS custom properties by the parent carousel, so
781
+ * styling never waits on change detection. The same values are mirrored onto signals and onto
782
+ * `md3-large` / `md3-medium` / `md3-small` classes, so content can react to the item's size
783
+ * either declaratively or from a stylesheet.
784
+ */
785
+ declare class CarouselItem {
786
+ private el;
787
+ /** 0 while the item is fully unmasked, approaching 1 as it crops away. */
788
+ readonly maskRatio: _angular_core.WritableSignal<number>;
789
+ /** Current rendered size of the item, in pixels. */
790
+ readonly maskedSize: _angular_core.WritableSignal<number>;
791
+ /** True while the item rests in the carousel's focal range. */
792
+ readonly isFocal: _angular_core.WritableSignal<boolean>;
793
+ /**
794
+ * Which of the arrangement's three sizes the item currently reads as.
795
+ *
796
+ * Mirrored onto the element as `md3-large`, `md3-medium` or `md3-small`.
797
+ */
798
+ readonly size: _angular_core.WritableSignal<CarouselItemSize>;
799
+ constructor(el: ElementRef<HTMLElement>);
800
+ get element(): HTMLElement;
801
+ /**
802
+ * Applies a resolved placement.
803
+ *
804
+ * Called from the carousel's scroll handler on every frame, so this writes to the DOM
805
+ * directly and only touches signals when a value actually changes.
806
+ */
807
+ applyGeometry(geometry: CarouselItemGeometry, itemSize: number): void;
808
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CarouselItem, never>;
809
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CarouselItem, "md3-carousel-item", never, {}, {}, never, ["*"], true, never>;
810
+ }
811
+
812
+ /**
813
+ * A Material Design 3 carousel.
814
+ *
815
+ * Items are laid out against a set of keylines — large, medium, small and an off-screen anchor —
816
+ * and adopt the size of whichever keyline they are passing through, so they grow into the focal
817
+ * range and crop away as they leave it.
818
+ *
819
+ * Scrolling is native, which keeps momentum, touch, snapping and the scrollbar intact. Only the
820
+ * visual sizing is derived in TypeScript, and it is written straight to CSS custom properties so
821
+ * scrolling never triggers change detection.
822
+ *
823
+ * All size inputs are in pixels.
824
+ *
825
+ * ```html
826
+ * <md3-carousel [(index)]="selected" [item-size]="200">
827
+ * @for (photo of photos(); track photo.id) {
828
+ * <md3-carousel-item>
829
+ * <img [src]="photo.url" [alt]="photo.alt" />
830
+ * </md3-carousel-item>
831
+ * }
832
+ * </md3-carousel>
833
+ * ```
834
+ */
835
+ declare class Carousel {
836
+ private el;
837
+ /** Arrangement strategy. Additional Material Design layouts will widen this type. */
838
+ carouselLayout: _angular_core.InputSignal<"multi-browse">;
839
+ /** Where the focal (large) items sit within the container. */
840
+ alignment: _angular_core.InputSignal<CarouselAlignment>;
841
+ /** Scroll axis. Only `horizontal` is implemented today. */
842
+ orientation: _angular_core.InputSignal<"horizontal">;
843
+ /** Preferred size of a fully unmasked item, in pixels. */
844
+ itemSize: _angular_core.InputSignalWithTransform<number, unknown>;
845
+ /** Smallest a small item may shrink to, in pixels. */
846
+ smallItemSizeMin: _angular_core.InputSignalWithTransform<number, unknown>;
847
+ /** Largest a small item may grow to, in pixels. */
848
+ smallItemSizeMax: _angular_core.InputSignalWithTransform<number, unknown>;
849
+ /** Space between items, in pixels. */
850
+ gap: _angular_core.InputSignalWithTransform<number, unknown>;
851
+ /**
852
+ * Index of the item leading the focal range. Two-way bindable.
853
+ *
854
+ * Clamped to {@link lastIndex}: the final items share the focal range and are all visible at
855
+ * once, so there is no scroll position where any of them leads on its own. Setting a higher
856
+ * value scrolls to the end and reads back as `lastIndex`.
857
+ */
858
+ index: _angular_core.ModelSignal<number>;
859
+ /** Items projected into the carousel, in document order. */
860
+ readonly items: _angular_core.Signal<readonly CarouselItem[]>;
861
+ /**
862
+ * Whether the current layout brings items to rest on keylines.
863
+ *
864
+ * Decided by the layout, not by the consumer: an arrangement that resizes items only reads
865
+ * correctly when they are sitting on keylines.
866
+ */
867
+ readonly snap: _angular_core.Signal<boolean>;
868
+ private scroller;
869
+ private containerSize;
870
+ private readonly directionality;
871
+ /**
872
+ * Sizes handed to the solver.
873
+ *
874
+ * Gaps are folded into item sizes so the solver only has one quantity to balance, then
875
+ * removed again visually by insetting each item half a gap on both sides.
876
+ */
877
+ private readonly metrics;
878
+ /** The solved distribution of large, medium and small items for the current container. */
879
+ readonly arrangement: _angular_core.Signal<CarouselArrangement | undefined>;
880
+ /** Keyline geometry derived from the arrangement. */
881
+ readonly geometry: _angular_core.Signal<CarouselGeometry | undefined>;
882
+ /** Scroll offsets that items snap to, one per item. */
883
+ protected readonly snapPoints: _angular_core.Signal<number[]>;
884
+ /**
885
+ * Highest index the carousel can rest on.
886
+ *
887
+ * Lower than the last item's index, because the trailing items share the focal range once
888
+ * the carousel is scrolled to the end. It moves as the container is resized, since a wider
889
+ * container fits more items in the focal range.
890
+ */
891
+ readonly lastIndex: _angular_core.Signal<number>;
892
+ readonly atStart: _angular_core.Signal<boolean>;
893
+ /** True when the carousel cannot scroll any further towards the end. */
894
+ readonly atEnd: _angular_core.Signal<boolean>;
895
+ private readonly isBrowser;
896
+ private scrollEndTimer;
897
+ private frame;
898
+ /**
899
+ * Target of an in-flight programmatic scroll.
900
+ *
901
+ * Smooth scrolling reports intermediate offsets, and reading the index back from those would
902
+ * fight the animation, so index syncing pauses until the target is reached or the user takes
903
+ * over.
904
+ */
905
+ private pendingScroll;
906
+ constructor(el: ElementRef<HTMLElement>);
907
+ get element(): HTMLElement;
908
+ /** True when laid out right-to-left. */
909
+ protected get isRtl(): boolean;
910
+ protected onKeydown(event: KeyboardEvent): void;
911
+ /**
912
+ * Keeps a focused item in view.
913
+ *
914
+ * Items are absolutely positioned, so the browser cannot scroll them into view on its own.
915
+ * Without this, tabbing to a link inside a cropped item would leave it invisible.
916
+ */
917
+ protected onFocusIn(event: FocusEvent): void;
918
+ /** Scrolls until `index` leads the focal range, clamping to {@link lastIndex}. */
919
+ scrollToIndex(index: number, behavior?: ScrollBehavior): void;
920
+ next(): void;
921
+ previous(): void;
922
+ private measure;
923
+ /**
924
+ * Current scroll position as a positive offset from the logical start edge.
925
+ *
926
+ * Right-to-left scroll containers report `scrollLeft` as zero at the start and negative
927
+ * moving away from it, so the magnitude is the logical offset in both directions.
928
+ */
929
+ private scrollOffset;
930
+ private scrollTo;
931
+ private scheduleGeometry;
932
+ /** `scrollend` is not universally supported, so back it with a timer. */
933
+ private scheduleIndexSync;
934
+ private syncIndexFromScroll;
935
+ /**
936
+ * Writes the current placement of every item.
937
+ *
938
+ * Runs on every scroll frame, so it touches the DOM directly and allocates nothing beyond
939
+ * the resolved state.
940
+ */
941
+ private applyGeometry;
942
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<Carousel, never>;
943
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Carousel, "md3-carousel", never, { "carouselLayout": { "alias": "carousel-layout"; "required": false; "isSignal": true; }; "alignment": { "alias": "alignment"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "itemSize": { "alias": "item-size"; "required": false; "isSignal": true; }; "smallItemSizeMin": { "alias": "small-item-size-min"; "required": false; "isSignal": true; }; "smallItemSizeMax": { "alias": "small-item-size-max"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; "index": { "alias": "index"; "required": false; "isSignal": true; }; }, { "index": "indexChange"; }, ["items"], ["*"], true, never>;
944
+ }
945
+
946
+ /**
947
+ * The Material Design 3 multi-browse layout: a run of large items followed by a medium and a
948
+ * small item, sized so the whole arrangement fills the container exactly.
949
+ *
950
+ * Ported from `MultiBrowseCarouselStrategy` and `Arrangement` in Material Components for
951
+ * Android so the two implementations agree on sizing.
952
+ */
953
+ declare const multiBrowseStrategy: CarouselStrategy;
954
+ /**
955
+ * Registry of the available carousel layouts.
956
+ *
957
+ * Adding a layout means implementing {@link CarouselStrategy}, widening `CarouselLayout` and
958
+ * adding the entry here — no changes to the component itself.
959
+ */
960
+ declare const CAROUSEL_STRATEGIES: Record<CarouselLayout, CarouselStrategy>;
961
+
962
+ /**
963
+ * Turns a solved arrangement into everything the component needs to place items.
964
+ */
965
+ declare function buildGeometry(arrangement: CarouselArrangement, alignment: CarouselAlignment, itemCount: number, containerSize: number): CarouselGeometry;
966
+ /**
967
+ * Resolves the keyline arrangement in effect at a given scroll offset.
968
+ */
969
+ declare function resolveState(geometry: CarouselGeometry, scrollOffset: number): CarouselKeylineState;
970
+ /**
971
+ * Classifies a rendered size against the arrangement's three sizes.
972
+ *
973
+ * Items resize continuously, so this snaps to whichever size the item currently reads as,
974
+ * flipping at the midpoint between one size and the next.
975
+ */
976
+ declare function sizeBandFor(maskedSize: number, geometry: CarouselGeometry): CarouselItemSize;
977
+ /**
978
+ * Places one item.
979
+ *
980
+ * The item's centre is a plain linear function of the scroll offset in scroll space; looking
981
+ * that position up against the current keylines is what converts it into a rendered size and
982
+ * an on-screen position.
983
+ */
984
+ declare function resolveItemGeometry(geometry: CarouselGeometry, state: CarouselKeylineState, index: number, scrollOffset: number): CarouselItemGeometry;
985
+ /**
986
+ * Clamps an index to one the carousel can actually come to rest on.
987
+ */
988
+ declare function clampIndex(geometry: CarouselGeometry, index: number): number;
989
+ /**
990
+ * Scroll offset at which `index` leads the focal range.
991
+ *
992
+ * The shifting focal range cancels out here, so this stays a simple multiple regardless of
993
+ * alignment or how close to either end of the list the item is.
994
+ */
995
+ declare function scrollOffsetForIndex(geometry: CarouselGeometry, index: number): number;
996
+ /**
997
+ * The item leading the focal range at a given scroll offset.
998
+ */
999
+ declare function indexForScrollOffset(geometry: CarouselGeometry, scrollOffset: number): number;
1000
+
601
1001
  declare class ChipAvatar {
602
1002
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChipAvatar, never>;
603
1003
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ChipAvatar, "[md3-chip-avatar]", never, {}, {}, never, never, true, never>;
@@ -760,7 +1160,7 @@ declare class ListItemPrimaryAction {
760
1160
  declare class ListItem implements AfterViewInit {
761
1161
  private el;
762
1162
  private state;
763
- slotsAlignment: _angular_core.InputSignal<"start" | "end" | "center">;
1163
+ slotsAlignment: _angular_core.InputSignal<"start" | "center" | "end">;
764
1164
  selected: _angular_core.InputSignalWithTransform<boolean, unknown>;
765
1165
  isActionTag: boolean;
766
1166
  private isLabelTag;
@@ -998,6 +1398,7 @@ declare class DialogRef<T = unknown, R = unknown> {
998
1398
  readonly isFullScreen: boolean;
999
1399
  private readonly closed;
1000
1400
  private readonly closing;
1401
+ private readonly hiddenChanges;
1001
1402
  private closePromise;
1002
1403
  private closeStarted;
1003
1404
  private closeSettled;
@@ -1013,7 +1414,7 @@ declare class DialogRef<T = unknown, R = unknown> {
1013
1414
  get overlayRef(): OverlayRef;
1014
1415
  /** Whether the dialog started closing. Such a dialog cannot be hidden or shown anymore. */
1015
1416
  get isClosing(): boolean;
1016
- /** Whether the dialog is currently hidden behind another dialog. */
1417
+ /** Whether the dialog is currently hidden, on request or behind another dialog. */
1017
1418
  get isHidden(): boolean;
1018
1419
  constructor(cdkRef: DialogRef$1<R, T>, disableCloseEvents: boolean,
1019
1420
  /** Whether this reference belongs to a full screen dialog. */
@@ -1023,6 +1424,7 @@ declare class DialogRef<T = unknown, R = unknown> {
1023
1424
  /**
1024
1425
  * Hides the dialog with the closing animation while keeping it alive, so
1025
1426
  * its content, form state and subscriptions survive until show() is called.
1427
+ * The page underneath becomes usable again while the dialog waits behind it.
1026
1428
  * The promise resolves once the dialog is out of sight.
1027
1429
  */
1028
1430
  hide(): Promise<void>;
@@ -1034,6 +1436,8 @@ declare class DialogRef<T = unknown, R = unknown> {
1034
1436
  show(): void;
1035
1437
  /** Emits when the dialog starts closing, before the exit animation runs. */
1036
1438
  beforeClosed(): Observable<void>;
1439
+ /** Emits the new value of `isHidden` every time the dialog is hidden or shown. */
1440
+ hiddenChanged(): Observable<boolean>;
1037
1441
  afterClosed(): Observable<R | undefined>;
1038
1442
  private connectCloseEvents;
1039
1443
  private toggleHiddenState;
@@ -1048,10 +1452,16 @@ declare class DialogRef<T = unknown, R = unknown> {
1048
1452
  declare class DialogService {
1049
1453
  private readonly cdkDialog;
1050
1454
  private readonly overlay;
1455
+ private readonly overlayContainer;
1051
1456
  private readonly injector;
1052
1457
  private readonly document;
1053
1458
  /** Open dialogs, from the first one opened to the one currently on top. */
1054
1459
  private readonly refs;
1460
+ /**
1461
+ * Elements the page was made of that the CDK hid from assistive technology,
1462
+ * kept here while the dialogs are hidden and the page is given back.
1463
+ */
1464
+ private readonly pageAriaHidden;
1055
1465
  /**
1056
1466
  * Page scrolling is blocked here instead of per overlay, so stacked dialogs
1057
1467
  * cannot unblock the page while another dialog is still open.
@@ -1059,7 +1469,10 @@ declare class DialogService {
1059
1469
  private readonly scrollBlock;
1060
1470
  /** Element that was focused before the first dialog of the stack opened. */
1061
1471
  private rootTrigger;
1472
+ private pageStateQueued;
1062
1473
  get openDialogs(): readonly DialogRef<any, any>[];
1474
+ /** Open dialogs that are currently on screen, from the bottom one up. */
1475
+ get visibleDialogs(): readonly DialogRef<any, any>[];
1063
1476
  /** The full screen dialog that is open, if there is one. */
1064
1477
  get fullScreenDialog(): DialogRef<any, any> | undefined;
1065
1478
  open<T, D = unknown, R = unknown>(component: Type<T>, config?: DialogConfig<D>): DialogRef<T, R>;
@@ -1071,6 +1484,20 @@ declare class DialogService {
1071
1484
  openFullScreen<T, D = unknown, R = unknown>(component: Type<T>, config?: FullScreenDialogConfig<D>): DialogRef<T, R>;
1072
1485
  /** Wires a freshly created dialog into the stack and starts its animation. */
1073
1486
  private registerDialog;
1487
+ /**
1488
+ * Hides every dialog that is on screen, the full screen one included, with
1489
+ * the closing animation. They stay alive with their content and state, the
1490
+ * page underneath becomes usable, and showAll() puts them back. The promise
1491
+ * resolves once they are all out of sight.
1492
+ */
1493
+ hideAll(): Promise<void>;
1494
+ /**
1495
+ * Brings the dialogs back on screen, whether they were hidden one by one or
1496
+ * all at once: the dialog that was on top returns, along with the full
1497
+ * screen dialog it sits in. Dialogs hidden behind another dialog stay
1498
+ * hidden, since that is where they belong once the stack is back.
1499
+ */
1500
+ showAll(): void;
1074
1501
  /** Closes every open dialog, including the hidden and the full screen ones. */
1075
1502
  closeAll(): Promise<void>;
1076
1503
  /** Closes the regular dialogs and leaves a full screen dialog alone. */
@@ -1105,7 +1532,29 @@ declare class DialogService {
1105
1532
  private topRegularRef;
1106
1533
  private restorePreviousDialog;
1107
1534
  private removeRef;
1108
- private updateScrollBlock;
1535
+ /**
1536
+ * State that belongs to the dialogs as a whole rather than to one of them:
1537
+ * page scrolling, the page being hidden from assistive technology, and
1538
+ * where focus sits. Applied in a task of its own, so a dialog handing the
1539
+ * screen over to another one does not give the page back and take it again
1540
+ * within the same frame.
1541
+ */
1542
+ private syncPageState;
1543
+ private applyPageState;
1544
+ /**
1545
+ * Gives the page back to assistive technology while every dialog is hidden.
1546
+ * The CDK hides it for as long as a dialog is open, which would otherwise
1547
+ * leave nothing to read at all once the dialogs are out of sight.
1548
+ */
1549
+ private exposePageToAssistiveTechnology;
1550
+ /** Hides the page again as soon as a dialog is back on screen. */
1551
+ private hidePageFromAssistiveTechnology;
1552
+ /**
1553
+ * Focus follows the dialogs off the screen: it goes back to whatever opened
1554
+ * the stack, so the page stays usable with the keyboard while the dialogs
1555
+ * wait behind it. Focus that already moved somewhere else is left alone.
1556
+ */
1557
+ private releaseFocus;
1109
1558
  private getFocusedElement;
1110
1559
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DialogService, never>;
1111
1560
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<DialogService>;
@@ -1461,5 +1910,5 @@ declare class SnackbarService {
1461
1910
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SnackbarService>;
1462
1911
  }
1463
1912
 
1464
- export { AppBar, AppBarLogo, Avatar, Badge, Button, ButtonGroup, Card, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StateComponent, SupportingText, Switch, TextField, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle };
1465
- export type { AppBarScrollingStyle, AppBarType, ButtonGroupSelection, ButtonGroupType, ButtonSize, ButtonType, CardType, ChipStyle, ChipType, DialogConfig, DialogContainer, DialogRole, FabSize, FabType, FullScreenDialogConfig, IconButtonType, IconButtonWidth, ListLeadingSize, ListLeadingType, Md3NavigationMode, MenuConfig, MenuPositionOrigin, MenuPositionX, MenuPositionY, MenuScrollStrategy, PreviousDialog, SideSheetConfig, SideSheetContainer, SideSheetSide, SideSheetType, SliderSize, SnackbarConfig, SnackbarDismiss, SnackbarDismissReason, SnackbarPoliteness, SplitButtonType, TextColor, TextSize };
1913
+ export { AppBar, AppBarLogo, Avatar, Badge, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StateComponent, SupportingText, Switch, TextField, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
1914
+ export type { AppBarScrollingStyle, AppBarType, ButtonGroupSelection, ButtonGroupType, ButtonSize, ButtonType, CardType, CarouselAlignment, CarouselArrangement, CarouselGeometry, CarouselItemGeometry, CarouselItemSize, CarouselKeyline, CarouselKeylineState, CarouselLayout, CarouselOrientation, CarouselStrategy, CarouselStrategyContext, ChipStyle, ChipType, DialogConfig, DialogContainer, DialogRole, FabSize, FabType, FullScreenDialogConfig, IconButtonType, IconButtonWidth, ListLeadingSize, ListLeadingType, Md3NavigationMode, MenuConfig, MenuPositionOrigin, MenuPositionX, MenuPositionY, MenuScrollStrategy, PreviousDialog, SideSheetConfig, SideSheetContainer, SideSheetSide, SideSheetType, SliderSize, SnackbarConfig, SnackbarDismiss, SnackbarDismissReason, SnackbarPoliteness, SplitButtonType, TextColor, TextSize };