1- import { AfterContentInit , Component , ContentChild , ElementRef , HostBinding , Input } from '@angular/core' ;
2- import { NgClass , NgTemplateOutlet } from '@angular/common' ;
1+ import {
2+ AfterContentInit ,
3+ afterRender ,
4+ Component ,
5+ computed ,
6+ contentChild ,
7+ ElementRef ,
8+ inject ,
9+ input ,
10+ OnDestroy ,
11+ signal
12+ } from '@angular/core' ;
13+ import { DOCUMENT , NgClass , NgTemplateOutlet } from '@angular/common' ;
314import { BreakpointObserver } from '@angular/cdk/layout' ;
415
516import { CollapseDirective } from '../collapse' ;
617import { Colors } from '../coreui.types' ;
718import { ThemeDirective } from '../shared' ;
19+ import { Subscription } from 'rxjs' ;
820
921// todo: fix container prop issue not rendering children
1022// todo: workaround - use <c-container> component directly in template
@@ -15,79 +27,106 @@ import { ThemeDirective } from '../shared';
1527 standalone : true ,
1628 imports : [ NgClass , NgTemplateOutlet ] ,
1729 hostDirectives : [ { directive : ThemeDirective , inputs : [ 'colorScheme' ] } ] ,
18- host : { class : 'navbar ' }
30+ host : { '[ class]' : 'hostClasses()' , '[attr.role]' : 'role() ' }
1931} )
20- export class NavbarComponent implements AfterContentInit {
32+ export class NavbarComponent implements AfterContentInit , OnDestroy {
33+ readonly #breakpointObserver = inject ( BreakpointObserver ) ;
34+ readonly #document = inject ( DOCUMENT ) ;
35+ readonly #hostElement = inject ( ElementRef ) ;
36+
2137 /**
2238 * Sets the color context of the component to one of CoreUI’s themed colors.
2339 * @type Colors
2440 */
25- @Input ( ) color ?: Colors ;
41+ readonly color = input < Colors > ( ) ;
42+
2643 /**
2744 * Defines optional container wrapping children elements.
2845 */
29- @Input ( ) container ?: boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'fluid' ;
46+ readonly container = input < boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'fluid' > ( ) ;
47+
3048 /**
3149 * Defines the responsive breakpoint to determine when content collapses.
3250 */
33- @Input ( ) expand ?: boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' ;
51+ readonly expand = input < boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' > ( ) ;
52+
3453 /**
3554 * Place component in non-static positions.
3655 */
37- @ Input ( ) placement ?: 'fixed-top' | 'fixed-bottom' | 'sticky-top' ;
56+ readonly placement = input < 'fixed-top' | 'fixed-bottom' | 'sticky-top' > ( ) ;
3857
39- @ ContentChild ( CollapseDirective ) collapse ! : CollapseDirective ;
58+ readonly role = input ( 'navigation' ) ;
4059
41- @HostBinding ( 'attr.role' )
42- @Input ( )
43- role = 'navigation' ;
60+ readonly collapse = contentChild ( CollapseDirective ) ;
4461
45- constructor (
46- private hostElement : ElementRef ,
47- private breakpointObserver : BreakpointObserver
48- ) { }
49-
50- @HostBinding ( 'class' )
51- get hostClasses ( ) : any {
52- const expandClassSuffix : string = this . expand === true ? '' : `-${ this . expand } ` ;
62+ readonly hostClasses = computed ( ( ) => {
63+ const color = this . color ( ) ;
64+ const expand = this . expand ( ) ;
65+ const expandClassSuffix : string = expand === true ? '' : `-${ expand } ` ;
66+ const placement = this . placement ( ) ;
5367 return {
5468 navbar : true ,
55- [ `navbar-expand${ expandClassSuffix } ` ] : ! ! this . expand ,
56- [ `bg-${ this . color } ` ] : ! ! this . color ,
57- [ `${ this . placement } ` ] : ! ! this . placement
58- } ;
59- }
69+ [ `navbar-expand${ expandClassSuffix } ` ] : ! ! expand ,
70+ [ `bg-${ color } ` ] : ! ! color ,
71+ [ `${ placement } ` ] : ! ! placement
72+ } as Record < string , boolean > ;
73+ } ) ;
6074
61- get containerClass ( ) : string {
62- return `container${ this . container !== true ? '-' + this . container : '' } ` ;
63- }
75+ readonly containerClass = computed ( ( ) => {
76+ const container = this . container ( ) ;
77+ return `container${ container !== true ? '-' + container : '' } ` ;
78+ } ) ;
6479
65- get breakpoint ( ) : string | boolean {
66- if ( typeof this . expand === 'string' ) {
67- return (
68- getComputedStyle ( this . hostElement . nativeElement ) ?. getPropertyValue ( `--cui-breakpoint-${ this . expand } ` ) ?? false
69- ) ;
80+ readonly computedStyle = signal < string > ( '' ) ;
81+
82+ readonly afterNextRenderFn = afterRender ( {
83+ read : ( ) => {
84+ const expand = this . expand ( ) ;
85+ if ( typeof expand === 'string' ) {
86+ const computedStyle =
87+ this . #document. defaultView
88+ ?. getComputedStyle ( this . #hostElement. nativeElement )
89+ ?. getPropertyValue ( `--cui-breakpoint-${ expand } ` ) ?? false ;
90+ computedStyle && this . computedStyle . set ( computedStyle ) ;
91+ }
92+ }
93+ } ) ;
94+
95+ readonly breakpoint = computed ( ( ) => {
96+ const expand = this . expand ( ) ;
97+ if ( typeof expand === 'string' ) {
98+ return this . computedStyle ( ) ;
7099 }
71100 return false ;
72- }
101+ } ) ;
102+
103+ #observer! : Subscription ;
73104
74105 ngAfterContentInit ( ) : void {
75- if ( this . breakpoint ) {
76- const onBreakpoint = `(min-width: ${ this . breakpoint } )` ;
77- this . breakpointObserver . observe ( [ onBreakpoint ] ) . subscribe ( ( result ) => {
78- if ( this . collapse ) {
79- const animate = this . collapse . animate ;
80- // todo: collapse animate input signal setter
81- this . collapse . animate = false ;
82- this . collapse . toggle ( false ) ;
83- setTimeout ( ( ) => {
84- this . collapse . toggle ( result . matches ) ;
106+ const breakpoint = this . breakpoint ( ) ;
107+ if ( breakpoint ) {
108+ const onBreakpoint = `(min-width: ${ breakpoint } )` ;
109+ this . #observer = this . #breakpointObserver
110+ . observe ( [ onBreakpoint ] )
111+ . pipe ( )
112+ . subscribe ( ( result ) => {
113+ const collapse = this . collapse ( ) ;
114+ if ( collapse ) {
115+ const animate = collapse . animate ( ) ;
116+ collapse . animate . set ( false ) ;
117+ collapse . toggle ( false ) ;
85118 setTimeout ( ( ) => {
86- this . collapse . animate = animate ;
119+ collapse . toggle ( result . matches ) ;
120+ setTimeout ( ( ) => {
121+ collapse . animate . set ( animate ) ;
122+ } ) ;
87123 } ) ;
88- } ) ;
89- }
90- } ) ;
124+ }
125+ } ) ;
91126 }
92127 }
128+
129+ ngOnDestroy ( ) : void {
130+ this . #observer?. unsubscribe ( ) ;
131+ }
93132}
0 commit comments