6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import { Directionality } from '@angular/cdk/bidi' ;
10
9
import { ChangeDetectorRef , Component , ElementRef , Inject , ViewEncapsulation } from '@angular/core' ;
11
-
12
- import { DevAppDirectionality } from './dev-app-directionality' ;
13
- import { DevAppRippleOptions } from './ripple-options' ;
14
10
import { CommonModule , DOCUMENT } from '@angular/common' ;
11
+ import { Direction , Directionality } from '@angular/cdk/bidi' ;
15
12
import { MatSidenavModule } from '@angular/material/sidenav' ;
16
13
import { MatListModule } from '@angular/material/list' ;
17
14
import { MatButtonModule } from '@angular/material/button' ;
18
15
import { RouterModule } from '@angular/router' ;
19
16
import { MatIconModule } from '@angular/material/icon' ;
20
17
import { 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 ';
25
22
26
23
/** Root component for the dev-app demos. */
27
24
@Component ( {
@@ -37,13 +34,12 @@ export const ANIMATIONS_STORAGE_KEY = 'ANGULAR_COMPONENTS_ANIMATIONS_DISABLED';
37
34
MatListModule ,
38
35
MatSidenavModule ,
39
36
MatToolbarModule ,
37
+ MatTooltipModule ,
40
38
RouterModule ,
41
39
] ,
42
40
} )
43
41
export class DevAppLayout {
44
- readonly darkThemeClass = 'demo-unicorn-dark-theme' ;
45
- _isDark = false ;
46
- strongFocus = false ;
42
+ state = getAppState ( ) ;
47
43
navItems = [
48
44
{ name : 'Examples' , route : '/examples' } ,
49
45
{ name : 'CDK Dialog' , route : '/cdk-dialog' } ,
@@ -126,108 +122,79 @@ export class DevAppLayout {
126
122
{ name : 'Legacy Tooltip' , route : '/legacy-tooltip' } ,
127
123
] ;
128
124
129
- /** Currently selected density scale based on the index. */
130
- currentDensityIndex = 0 ;
131
-
132
125
/** 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' ] ;
137
127
138
128
constructor (
139
129
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 ,
143
133
@Inject ( DOCUMENT ) private _document : Document ,
144
134
) {
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 ) ;
157
140
}
158
141
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 ) ;
175
146
}
176
147
177
148
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 ( ) ;
189
150
}
190
151
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 ) ;
197
156
}
198
157
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
+ }
203
163
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 ;
208
167
}
168
+
169
+ this . state . density = this . _densityScales [ index ] ;
170
+ setAppState ( this . state ) ;
209
171
}
210
172
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 ) ;
214
176
}
215
177
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
+ }
219
184
}
220
185
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
+ }
224
195
}
225
196
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
- */
230
197
getDensityClass ( ) {
231
- return `demo-density-${ this . densityScales [ this . currentDensityIndex ] } ` ;
198
+ return `demo-density-${ this . state . density } ` ;
232
199
}
233
200
}
0 commit comments