66 * found in the LICENSE file at https://angular.io/license
77 */
88
9- import { Directionality } from '@angular/cdk/bidi' ;
109import { ChangeDetectorRef , Component , ElementRef , Inject , ViewEncapsulation } from '@angular/core' ;
11-
12- import { DevAppDirectionality } from './dev-app-directionality' ;
13- import { DevAppRippleOptions } from './ripple-options' ;
1410import { CommonModule , DOCUMENT } from '@angular/common' ;
11+ import { Direction , Directionality } from '@angular/cdk/bidi' ;
1512import { MatSidenavModule } from '@angular/material/sidenav' ;
1613import { MatListModule } from '@angular/material/list' ;
1714import { MatButtonModule } from '@angular/material/button' ;
1815import { RouterModule } from '@angular/router' ;
1916import { MatIconModule } from '@angular/material/icon' ;
2017import { MatToolbarModule } from '@angular/material/toolbar' ;
21-
22- const isDarkThemeKey = 'ANGULAR_COMPONENTS_DEV_APP_DARK_THEME ';
23-
24- export const ANIMATIONS_STORAGE_KEY = 'ANGULAR_COMPONENTS_ANIMATIONS_DISABLED ';
18+ import { MatTooltipModule } from '@angular/material/tooltip' ;
19+ import { DevAppDirectionality } from './dev-app-directionality ';
20+ import { DevAppRippleOptions } from './ripple-options' ;
21+ import { getAppState , setAppState } from './dev-app-state ';
2522
2623/** Root component for the dev-app demos. */
2724@Component ( {
@@ -37,13 +34,12 @@ export const ANIMATIONS_STORAGE_KEY = 'ANGULAR_COMPONENTS_ANIMATIONS_DISABLED';
3734 MatListModule ,
3835 MatSidenavModule ,
3936 MatToolbarModule ,
37+ MatTooltipModule ,
4038 RouterModule ,
4139 ] ,
4240} )
4341export class DevAppLayout {
44- readonly darkThemeClass = 'demo-unicorn-dark-theme' ;
45- _isDark = false ;
46- strongFocus = false ;
42+ state = getAppState ( ) ;
4743 navItems = [
4844 { name : 'Examples' , route : '/examples' } ,
4945 { name : 'CDK Dialog' , route : '/cdk-dialog' } ,
@@ -126,108 +122,79 @@ export class DevAppLayout {
126122 { name : 'Legacy Tooltip' , route : '/legacy-tooltip' } ,
127123 ] ;
128124
129- /** Currently selected density scale based on the index. */
130- currentDensityIndex = 0 ;
131-
132125 /** List of possible global density scale values. */
133- densityScales = [ 0 , - 1 , - 2 , - 3 , 'minimum' , 'maximum' ] ;
134-
135- /** Whether animations are disabled. */
136- animationsDisabled = localStorage . getItem ( ANIMATIONS_STORAGE_KEY ) === 'true' ;
126+ private _densityScales = [ 0 , - 1 , - 2 , - 3 , 'minimum' , 'maximum' ] ;
137127
138128 constructor (
139129 private _element : ElementRef < HTMLElement > ,
140- public rippleOptions : DevAppRippleOptions ,
141- @Inject ( Directionality ) public dir : DevAppDirectionality ,
142- cdr : ChangeDetectorRef ,
130+ private _rippleOptions : DevAppRippleOptions ,
131+ @Inject ( Directionality ) private _dir : DevAppDirectionality ,
132+ private _changeDetectorRef : ChangeDetectorRef ,
143133 @Inject ( DOCUMENT ) private _document : Document ,
144134 ) {
145- dir . change . subscribe ( ( ) => cdr . markForCheck ( ) ) ;
146- try {
147- const isDark = localStorage . getItem ( isDarkThemeKey ) ;
148- if ( isDark != null ) {
149- // We avoid calling the setter and apply the themes directly here.
150- // This avoids writing the same value, that we just read, back to localStorage.
151- this . _isDark = isDark === 'true' ;
152- this . updateThemeClass ( this . _isDark ) ;
153- }
154- } catch ( error ) {
155- console . error ( `Failed to read ${ isDarkThemeKey } from localStorage: ` , error ) ;
156- }
135+ this . toggleTheme ( this . state . darkTheme ) ;
136+ this . toggleStrongFocus ( this . state . strongFocusEnabled ) ;
137+ this . toggleDensity ( Math . max ( this . _densityScales . indexOf ( this . state . density ) , 0 ) ) ;
138+ this . toggleRippleDisabled ( this . state . rippleDisabled ) ;
139+ this . toggleDirection ( this . state . direction ) ;
157140 }
158141
159- get isDark ( ) : boolean {
160- return this . _isDark ;
161- }
162-
163- set isDark ( value : boolean ) {
164- // Noop if the value is the same as is already set.
165- if ( value !== this . _isDark ) {
166- this . _isDark = value ;
167- this . updateThemeClass ( this . _isDark ) ;
168-
169- try {
170- localStorage . setItem ( isDarkThemeKey , String ( value ) ) ;
171- } catch ( error ) {
172- console . error ( `Failed to write ${ isDarkThemeKey } to localStorage: ` , error ) ;
173- }
174- }
142+ toggleTheme ( value = ! this . state . darkTheme ) {
143+ this . state . darkTheme = value ;
144+ this . _document . body . classList . toggle ( 'demo-unicorn-dark-theme' , value ) ;
145+ setAppState ( this . state ) ;
175146 }
176147
177148 toggleFullscreen ( ) {
178- // Cast to `any`, because the typings don't include the browser-prefixed methods.
179- const elem = this . _element . nativeElement . querySelector ( '.demo-content' ) as any ;
180- if ( elem . requestFullscreen ) {
181- elem . requestFullscreen ( ) ;
182- } else if ( elem . webkitRequestFullScreen ) {
183- elem . webkitRequestFullScreen ( ) ;
184- } else if ( elem . mozRequestFullScreen ) {
185- elem . mozRequestFullScreen ( ) ;
186- } else if ( elem . msRequestFullScreen ) {
187- elem . msRequestFullScreen ( ) ;
188- }
149+ this . _element . nativeElement . querySelector ( '.demo-content' ) ?. requestFullscreen ( ) ;
189150 }
190151
191- updateThemeClass ( isDark ?: boolean ) {
192- if ( isDark ) {
193- this . _document . body . classList . add ( this . darkThemeClass ) ;
194- } else {
195- this . _document . body . classList . remove ( this . darkThemeClass ) ;
196- }
152+ toggleStrongFocus ( value = ! this . state . strongFocusEnabled ) {
153+ this . state . strongFocusEnabled = value ;
154+ this . _document . body . classList . toggle ( 'demo-strong-focus' , value ) ;
155+ setAppState ( this . state ) ;
197156 }
198157
199- toggleStrongFocus ( ) {
200- const strongFocusClass = 'demo-strong-focus' ;
201-
202- this . strongFocus = ! this . strongFocus ;
158+ toggleAnimations ( ) {
159+ this . state . animations = ! this . state . animations ;
160+ setAppState ( this . state ) ;
161+ location . reload ( ) ;
162+ }
203163
204- if ( this . strongFocus ) {
205- this . _document . body . classList . add ( strongFocusClass ) ;
206- } else {
207- this . _document . body . classList . remove ( strongFocusClass ) ;
164+ toggleDensity ( index ?: number ) {
165+ if ( index == null ) {
166+ index = ( this . _densityScales . indexOf ( this . state . density ) + 1 ) % this . _densityScales . length ;
208167 }
168+
169+ this . state . density = this . _densityScales [ index ] ;
170+ setAppState ( this . state ) ;
209171 }
210172
211- toggleAnimations ( ) {
212- localStorage . setItem ( ANIMATIONS_STORAGE_KEY , ! this . animationsDisabled + '' ) ;
213- location . reload ( ) ;
173+ toggleRippleDisabled ( value = ! this . state . rippleDisabled ) {
174+ this . _rippleOptions . disabled = this . state . rippleDisabled = value ;
175+ setAppState ( this . state ) ;
214176 }
215177
216- /** Gets the index of the next density scale that can be selected. */
217- getNextDensityIndex ( ) {
218- return ( this . currentDensityIndex + 1 ) % this . densityScales . length ;
178+ toggleDirection ( value : Direction = this . state . direction === 'ltr' ? 'rtl' : 'ltr' ) {
179+ if ( value !== this . _dir . value ) {
180+ this . _dir . value = this . state . direction = value ;
181+ this . _changeDetectorRef . markForCheck ( ) ;
182+ setAppState ( this . state ) ;
183+ }
219184 }
220185
221- /** Selects the next possible density scale. */
222- selectNextDensity ( ) {
223- this . currentDensityIndex = this . getNextDensityIndex ( ) ;
186+ toggleTokens ( value = ! this . state . tokensEnabled ) {
187+ // We need to diff this one since it's a bit more expensive to toggle.
188+ if ( value !== this . state . tokensEnabled ) {
189+ ( document . getElementById ( 'theme-styles' ) as HTMLLinkElement ) . href = value
190+ ? 'theme-token-api.css'
191+ : 'theme.css' ;
192+ this . state . tokensEnabled = value ;
193+ setAppState ( this . state ) ;
194+ }
224195 }
225196
226- /**
227- * Updates the density classes on the host element. Applies a unique class for
228- * a given density scale, so that the density styles are conditionally applied.
229- */
230197 getDensityClass ( ) {
231- return `demo-density-${ this . densityScales [ this . currentDensityIndex ] } ` ;
198+ return `demo-density-${ this . state . density } ` ;
232199 }
233200}
0 commit comments