@almoamendev/ngx-md3 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almoamendev/ngx-md3",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "MD3-style Angular components & style library",
5
5
  "author": "Murtadha (Hussain) Almoamen",
6
6
  "license": "MIT",
@@ -510,6 +510,14 @@ md3-badge {
510
510
  height: 100%;
511
511
  overflow-x: hidden;
512
512
  overflow-y: auto;
513
+
514
+ // A floating toolbar in a scaffold bar covers content that it does not reserve. The
515
+ // scaffold publishes how much, and the fallback is 0, so a layout without one is
516
+ // unchanged. Set these to 0 on a page that needs full-bleed content.
517
+ padding-block-start: var(--md-scaffold-floating-inset-block-start, 0em);
518
+ padding-block-end: var(--md-scaffold-floating-inset-block-end, 0em);
519
+ scroll-padding-block-start: var(--md-scaffold-floating-inset-block-start, 0em);
520
+ scroll-padding-block-end: var(--md-scaffold-floating-inset-block-end, 0em);
513
521
  }
514
522
  }
515
523
 
@@ -53,6 +53,62 @@ type ListLeadingSize = 'image' | 'small-video' | 'large-video';
53
53
  */
54
54
  type CarouselLayout = 'multi-browse';
55
55
 
56
+ /**
57
+ * The toolbar container style.
58
+ *
59
+ * `floating` draws a rounded, elevated container with an outside margin. In a scaffold bar
60
+ * region it leaves the layout flow, so the content passes behind it. In a scaffold rail
61
+ * region it stays in the flow and reserves its own space.
62
+ *
63
+ * `docked` fills its region, has square corners and no elevation. The Material 3
64
+ * specification allows it in a bar region only, because it spans the full window width.
65
+ */
66
+ type ToolbarType = 'floating' | 'docked';
67
+
68
+ /**
69
+ * The toolbar color configuration.
70
+ *
71
+ * `standard` uses a surface container. `vibrant` uses a primary container, and remaps the
72
+ * colors of the buttons inside it, as the Material 3 specification describes.
73
+ */
74
+ type ToolbarColor = 'standard' | 'vibrant';
75
+
76
+ /**
77
+ * The axis the toolbar items follow.
78
+ *
79
+ * The value is optional on the component. When it is not set, a toolbar in a scaffold rail
80
+ * region becomes `vertical`, and every other toolbar becomes `horizontal`.
81
+ */
82
+ type ToolbarOrientation = 'horizontal' | 'vertical';
83
+
84
+ /**
85
+ * Where the toolbar sits along its main axis.
86
+ *
87
+ * A docked toolbar fills its region, so the value moves the item row inside the container. A
88
+ * floating toolbar is as wide as its content, so the value moves the container itself, and the
89
+ * FAB with it, inside the region.
90
+ */
91
+ type ToolbarAlignment = 'start' | 'center' | 'end';
92
+
93
+ /**
94
+ * What the toolbar does when the scaffold main pane scrolls down.
95
+ *
96
+ * `none` does nothing. `hide` moves the toolbar out of the region. `collapse` hides every
97
+ * item that does not carry the `md3-toolbar-persistent` attribute, and keeps the FAB.
98
+ *
99
+ * A vertical toolbar ignores this input.
100
+ */
101
+ type ToolbarScrollAction = 'none' | 'hide' | 'collapse';
102
+
103
+ /**
104
+ * The scaffold region a toolbar sits in, named by its logical side.
105
+ *
106
+ * `blockStart` and `blockEnd` are the top and bottom scaffold bars. `inlineStart` and
107
+ * `inlineEnd` are the leading and trailing scaffold rails. The names are logical, so they
108
+ * follow the document direction.
109
+ */
110
+ type ToolbarRegion = 'blockStart' | 'blockEnd' | 'inlineStart' | 'inlineEnd';
111
+
56
112
  /**
57
113
  * Where the focal (large) items sit within the carousel container.
58
114
  */
@@ -568,6 +624,11 @@ type ViewportWidth = 'compact' | 'medium' | 'expanded' | 'large' | 'extra-large'
568
624
 
569
625
  type ViewportHeight = 'compact' | 'medium' | 'expanded';
570
626
 
627
+ type FloatingBarSide = 'blockStart' | 'blockEnd';
628
+ interface FloatingInset {
629
+ blockStart: number;
630
+ blockEnd: number;
631
+ }
571
632
  type Md3NavigationMode = 'none' | 'navigation-bar' | 'navigation-rail' | 'standard-drawer' | 'modal-drawer';
572
633
  declare class LayoutService {
573
634
  private readonly document;
@@ -579,8 +640,19 @@ declare class LayoutService {
579
640
  private mainPaneEl?;
580
641
  private panesContainerResizeObserver?;
581
642
  private panesContainerResizeListener?;
643
+ /** Floating bars currently registered, keyed by the measured element. */
644
+ private readonly floatingBars;
645
+ /** How far the main pane must move before the scroll direction flips. Stops jitter. */
646
+ private static readonly scrollDirectionThreshold;
647
+ private scrollPosition;
582
648
  readonly mainScrollTop: _angular_core.WritableSignal<number>;
583
649
  readonly mainIsScrolled: _angular_core.Signal<boolean>;
650
+ /**
651
+ * True while the main pane moves down, false while it moves up. A small threshold keeps
652
+ * a jitter from flipping the value. Components that react to scrolling — the app bar and
653
+ * the toolbar — read this, so they can never disagree.
654
+ */
655
+ readonly isScrollingDown: _angular_core.WritableSignal<boolean>;
584
656
  /**
585
657
  * Distance, in pixels, between the viewport bottom and the bottom edge of
586
658
  * the scaffold's .md3-panes-container — i.e. whatever the bottom scaffold
@@ -589,6 +661,22 @@ declare class LayoutService {
589
661
  * they never render lower than the panes container.
590
662
  */
591
663
  readonly bottomInset: _angular_core.WritableSignal<number>;
664
+ /**
665
+ * Space a floating scaffold bar covers but does not reserve, per logical block side.
666
+ *
667
+ * A floating toolbar in a bar region leaves the layout flow, so its grid track collapses
668
+ * and the content flows under it. This signal reports what it covers, so the scaffold can
669
+ * pad the main pane and overlays can stay clear of it.
670
+ *
671
+ * A floating toolbar in a *rail* region stays in the flow and reserves its own space, so
672
+ * it never appears here.
673
+ */
674
+ readonly floatingInset: _angular_core.WritableSignal<FloatingInset>;
675
+ /**
676
+ * The distance from the viewport bottom that a viewport-anchored overlay must keep clear.
677
+ * It covers both the reserved bottom bar and any floating bottom bar over it.
678
+ */
679
+ readonly bottomSafeInset: _angular_core.Signal<number>;
592
680
  readonly viewport: _angular_core.Signal<{
593
681
  width: number;
594
682
  height: number;
@@ -613,7 +701,24 @@ declare class LayoutService {
613
701
  private scrollMainPaneToTop;
614
702
  registerMainPane(element: HTMLElement): void;
615
703
  unregisterMainPane(element: HTMLElement): void;
704
+ private resetScrollDirection;
705
+ private updateScrollDirection;
616
706
  registerPanesContainer(element: HTMLElement): void;
707
+ /**
708
+ * Register a floating bar so the scaffold and the overlays know what it covers.
709
+ *
710
+ * Call this for a floating toolbar in a scaffold *bar* region only. A rail region keeps
711
+ * the toolbar in the layout flow, so it reserves its own space and needs no inset.
712
+ */
713
+ registerFloatingBar(element: HTMLElement, side: FloatingBarSide): void;
714
+ unregisterFloatingBar(element: HTMLElement): void;
715
+ private measureFloatingBars;
716
+ /**
717
+ * `offsetHeight` ignores transforms. So a toolbar that scrolling has hidden or collapsed
718
+ * still reports its expanded size, and the content padding never moves while the user
719
+ * scrolls.
720
+ */
721
+ private measureBlockSize;
617
722
  unregisterPanesContainer(): void;
618
723
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LayoutService, never>;
619
724
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<LayoutService>;
@@ -627,6 +732,8 @@ declare class Scaffold implements AfterViewInit, OnDestroy {
627
732
  private sheets;
628
733
  private bottomSheets;
629
734
  private layout;
735
+ private el;
736
+ constructor();
630
737
  ngAfterViewInit(): void;
631
738
  ngOnDestroy(): void;
632
739
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Scaffold, never>;
@@ -1354,8 +1461,7 @@ declare class AppBar implements ButtonContext {
1354
1461
  hasLogo: Signal<boolean>;
1355
1462
  hasAvatar: Signal<boolean>;
1356
1463
  mainIsScrolled: Signal<boolean>;
1357
- isScrollingDown: _angular_core.WritableSignal<boolean>;
1358
- private scrollPosition;
1464
+ isScrollingDown: Signal<boolean>;
1359
1465
  private bottomExpandedHeight;
1360
1466
  private bottomCollapse;
1361
1467
  buttonContextSize: Signal<ButtonSize>;
@@ -1363,7 +1469,6 @@ declare class AppBar implements ButtonContext {
1363
1469
  get element(): HTMLElement;
1364
1470
  private getBottomOpacity;
1365
1471
  private isBottomCollapsed;
1366
- private updateScrollDirection;
1367
1472
  private hasCollapsibleBottom;
1368
1473
  private getHostFontSize;
1369
1474
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AppBar, never>;
@@ -1375,6 +1480,119 @@ declare class AppBarLogo {
1375
1480
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AppBarLogo, "[md3-app-bar-logo]", never, {}, {}, never, never, true, never>;
1376
1481
  }
1377
1482
 
1483
+ /**
1484
+ * Material 3 toolbar.
1485
+ *
1486
+ * The toolbar holds the actions of the current page. Put it in a scaffold region, and the
1487
+ * region decides where it goes:
1488
+ *
1489
+ * ```html
1490
+ * <md3-toolbar md3-scaffold-bar="bottom" toolbar-type="floating" scroll-action="collapse">
1491
+ * <md3-toolbar-item><button md3-icon-button>...</button></md3-toolbar-item>
1492
+ * <md3-toolbar-item md3-toolbar-persistent><button md3-icon-button>...</button></md3-toolbar-item>
1493
+ * <button md3-fab>...</button>
1494
+ * </md3-toolbar>
1495
+ * ```
1496
+ *
1497
+ * Every action goes inside an `md3-toolbar-item`. The toolbar projects that element only. A FAB is
1498
+ * the one exception: it sits beside the container, and a floating toolbar takes it.
1499
+ *
1500
+ * A **floating** toolbar in a *bar* region leaves the layout flow, so the content passes
1501
+ * behind it. The scaffold pads the main pane by the height it covers. In a *rail* region it
1502
+ * stays in the flow and reserves its own space, so no padding is necessary.
1503
+ *
1504
+ * A **docked** toolbar fills its region. The specification allows it in a bar region only.
1505
+ *
1506
+ * Group actions with `md3-button-group`. The toolbar has one slots region, and it keeps the
1507
+ * authored order. The space between the items follows the free space of the container, between
1508
+ * `--md-toolbar-gap-min` and `--md-toolbar-gap-max`.
1509
+ */
1510
+ declare class Toolbar implements ButtonContext, OnDestroy {
1511
+ private readonly el;
1512
+ private readonly layout;
1513
+ private readonly scaffoldBar;
1514
+ private readonly scaffoldRail;
1515
+ toolbarType: _angular_core.InputSignal<ToolbarType>;
1516
+ toolbarColor: _angular_core.InputSignal<ToolbarColor>;
1517
+ /**
1518
+ * Leave this unset to follow the region. A rail region gives `vertical`, and every other
1519
+ * placement gives `horizontal`. Read `effectiveOrientation` for the resolved value.
1520
+ */
1521
+ orientation: _angular_core.InputSignal<ToolbarOrientation | null>;
1522
+ alignment: _angular_core.InputSignal<ToolbarAlignment>;
1523
+ scrollAction: _angular_core.InputSignal<ToolbarScrollAction>;
1524
+ fabPosition: _angular_core.InputSignal<"start" | "end">;
1525
+ /** The collapse state. Scrolling writes to it, and you can read or set it yourself. */
1526
+ expanded: _angular_core.ModelSignal<boolean>;
1527
+ private readonly layoutElement;
1528
+ private readonly containerElement;
1529
+ private readonly slotsElement;
1530
+ private readonly fab;
1531
+ /** Set from the DOM, because `md3-toolbar-persistent` is a plain attribute, not a directive. */
1532
+ private readonly hasPersistentItem;
1533
+ private readonly hasFocusWithin;
1534
+ private persistentObserver?;
1535
+ private readonly isBrowser;
1536
+ /** The last published free space, to keep an unchanged measurement from writing to the DOM. */
1537
+ private lastGap;
1538
+ readonly isFloating: Signal<boolean>;
1539
+ readonly effectiveOrientation: Signal<ToolbarOrientation>;
1540
+ /** The logical side of the scaffold region, or null outside a scaffold. */
1541
+ readonly region: Signal<ToolbarRegion | null>;
1542
+ protected readonly isBarRegion: Signal<boolean>;
1543
+ protected readonly isRailRegion: Signal<boolean>;
1544
+ /** A floating toolbar inside a scaffold region needs the region to stop clipping it. */
1545
+ protected readonly isFloatingRegion: Signal<boolean>;
1546
+ /** Only a floating bar covers content it does not reserve. Everything else reserves its space. */
1547
+ private readonly coversContent;
1548
+ /** Something must survive a collapse, or a collapse is just a hide. */
1549
+ private readonly canCollapse;
1550
+ /** With a FAB and no marked item, a collapse takes the container away and the FAB stays alone. */
1551
+ protected readonly collapsesToFab: Signal<boolean>;
1552
+ /** A vertical toolbar never reacts to scrolling, and a docked one never collapses. */
1553
+ readonly resolvedScrollAction: Signal<ToolbarScrollAction>;
1554
+ readonly isHidden: _angular_core.WritableSignal<boolean>;
1555
+ readonly isCollapsed: Signal<boolean>;
1556
+ /**
1557
+ * The collapsed state in which the FAB stays alone.
1558
+ *
1559
+ * This is the state, not the capability. A FAB by itself must never take the container
1560
+ * away, because a toolbar that does not collapse keeps its items at all times.
1561
+ */
1562
+ protected readonly isCollapsedToFab: Signal<boolean>;
1563
+ buttonContextSize: Signal<ButtonSize>;
1564
+ constructor();
1565
+ ngOnDestroy(): void;
1566
+ get element(): HTMLElement;
1567
+ protected onFocusIn(): void;
1568
+ protected onFocusOut(event: FocusEvent): void;
1569
+ private updateScrollState;
1570
+ /**
1571
+ * Divide the free space of the container between the gaps.
1572
+ *
1573
+ * The measurement starts from the host, because the host holds the space the region gives
1574
+ * the toolbar. A floating container is only as wide as its content, so reading the container
1575
+ * itself would feed the gap back into the measurement and the value would never settle.
1576
+ */
1577
+ private measureGap;
1578
+ private publishGap;
1579
+ private extent;
1580
+ private contentExtent;
1581
+ private paddingExtent;
1582
+ /** What the other children of the layout take, the flex gap that separates them included. */
1583
+ private siblingExtent;
1584
+ private watchPersistentItems;
1585
+ private checkConfiguration;
1586
+ private warn;
1587
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<Toolbar, never>;
1588
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Toolbar, "md3-toolbar", never, { "toolbarType": { "alias": "toolbar-type"; "required": false; "isSignal": true; }; "toolbarColor": { "alias": "toolbar-color"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "alignment": { "alias": "alignment"; "required": false; "isSignal": true; }; "scrollAction": { "alias": "scroll-action"; "required": false; "isSignal": true; }; "fabPosition": { "alias": "fab-position"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; }, ["fab"], ["[md3-fab]", "md3-toolbar-item"], true, never>;
1589
+ }
1590
+
1591
+ declare class ToolbarItem {
1592
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ToolbarItem, never>;
1593
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ToolbarItem, "md3-toolbar-item", never, {}, {}, never, never, true, never>;
1594
+ }
1595
+
1378
1596
  declare class NavigationItem {
1379
1597
  private readonly el;
1380
1598
  private routerLinkActive;
@@ -2148,5 +2366,5 @@ declare class SnackbarService {
2148
2366
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<SnackbarService>;
2149
2367
  }
2150
2368
 
2151
- 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 };
2152
- export type { AppBarScrollingStyle, AppBarType, BottomSheetConfig, BottomSheetContainer, BottomSheetState, BottomSheetSurfaceHost, BottomSheetType, 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, StandardBottomSheetHost, TextColor, TextSize };
2369
+ export { AppBar, AppBarLogo, Avatar, BOTTOM_SHEET_COMPONENT, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, Badge, BottomSheetRef, BottomSheetService, Button, ButtonGroup, CAROUSEL_STRATEGIES, Card, Carousel, CarouselItem, Checkbox, ChipAvatar, Chips, CircularProgressIndicator, DIALOG_COMPONENT, DIALOG_CONFIG, DIALOG_DATA, Dialog, DialogActions, DialogBody, DialogHeader, DialogRef, DialogService, Divider, FloatingActionButton, FullScreenDialog, FullScreenDialogHeader, Grid, GridItem, IconButton, IconElement, InputElement, LayoutService, LinearProgressIndicator, List, ListItem, ListItemPrimaryAction, ListLeading, ListSlot, LoadingIndicator, MENU_COMPONENT, MENU_CONFIG, MENU_DATA, MaterialIcon, Menu, MenuGroup, MenuItem, MenuRef, MenuService, ModalBottomSheetRef, NavigationBar, NavigationGroup, NavigationItem, NavigationRail, RadioButton, SIDE_SHEET_COMPONENT, SIDE_SHEET_CONFIG, SIDE_SHEET_DATA, SNACKBAR_ACTION_LABEL, SNACKBAR_CONFIG, SNACKBAR_MESSAGE, Scaffold, ScaffoldBar, ScaffoldPane, ScaffoldRail, SheetsService, SideSheetActions, SideSheetBody, SideSheetHeader, SideSheetRef, Slider, Snackbar, SnackbarRef, SnackbarService, SplitButton, StandardBottomSheetRef, StateComponent, SupportingText, Switch, TextField, Toolbar, ToolbarItem, TypeBody, TypeDisplay, TypeHeadline, TypeLabel, TypeTitle, buildGeometry, clampIndex, indexForScrollOffset, multiBrowseStrategy, parseCarouselAspectRatio, resolveItemGeometry, resolveState, scrollOffsetForIndex, sizeBandFor };
2370
+ export type { AppBarScrollingStyle, AppBarType, BottomSheetConfig, BottomSheetContainer, BottomSheetState, BottomSheetSurfaceHost, BottomSheetType, ButtonGroupSelection, ButtonGroupType, ButtonSize, ButtonType, CardType, CarouselAlignment, CarouselArrangement, CarouselGeometry, CarouselItemGeometry, CarouselItemSize, CarouselKeyline, CarouselKeylineState, CarouselLayout, CarouselOrientation, CarouselStrategy, CarouselStrategyContext, ChipStyle, ChipType, DialogConfig, DialogContainer, DialogRole, FabSize, FabType, FloatingBarSide, FloatingInset, FullScreenDialogConfig, IconButtonType, IconButtonWidth, ListLeadingSize, ListLeadingType, Md3NavigationMode, MenuConfig, MenuPositionOrigin, MenuPositionX, MenuPositionY, MenuScrollStrategy, PreviousDialog, SideSheetConfig, SideSheetContainer, SideSheetSide, SideSheetType, SliderSize, SnackbarConfig, SnackbarDismiss, SnackbarDismissReason, SnackbarPoliteness, SplitButtonType, StandardBottomSheetHost, TextColor, TextSize, ToolbarAlignment, ToolbarColor, ToolbarOrientation, ToolbarRegion, ToolbarScrollAction, ToolbarType };