@@ -133,13 +133,10 @@ function detectDisabledThemes($mdThemingProvider) {
133
133
* {{primary-color-0.7}} - Apply 0.7 opacity to each of the above rules
134
134
* {{primary-contrast}} - Generates .md-hue-1, .md-hue-2, .md-hue-3 with configured contrast (ie. text) color shades set for each hue
135
135
* {{primary-contrast-0.7}} - Apply 0.7 opacity to each of the above rules
136
+ * {{primary-contrast-divider}} - Apply divider opacity to contrast color
137
+ * {{background-default-contrast}} - Apply primary text color for contrasting with default background
138
+ * {{background-50-contrast-icon}} - Apply contrast color for icon on background's shade 50 hue
136
139
*
137
- * Foreground expansion: Applies rgba to black/white foreground text
138
- *
139
- * {{foreground-1}} - used for primary text
140
- * {{foreground-2}} - used for secondary text/divider
141
- * {{foreground-3}} - used for disabled text
142
- * {{foreground-4}} - used for dividers
143
140
*/
144
141
145
142
// In memory generated CSS rules; registered by theme.name
@@ -148,21 +145,14 @@ var GENERATED = { };
148
145
// In memory storage of defined themes and color palettes (both loaded by CSS, and user specified)
149
146
var PALETTES ;
150
147
151
- // Text Colors on light and dark backgrounds
148
+ // Text colors are automatically generated based on background color when not specified
149
+ // Custom palettes can provide override colors
152
150
// @see https://material.io/archive/guidelines/style/color.html#color-usability
153
151
var DARK_FOREGROUND = {
154
152
name : 'dark' ,
155
- '1' : 'rgba(0,0,0,0.87)' ,
156
- '2' : 'rgba(0,0,0,0.54)' ,
157
- '3' : 'rgba(0,0,0,0.38)' ,
158
- '4' : 'rgba(0,0,0,0.12)'
159
153
} ;
160
154
var LIGHT_FOREGROUND = {
161
155
name : 'light' ,
162
- '1' : 'rgba(255,255,255,1.0)' ,
163
- '2' : 'rgba(255,255,255,0.7)' ,
164
- '3' : 'rgba(255,255,255,0.5)' ,
165
- '4' : 'rgba(255,255,255,0.12)'
166
156
} ;
167
157
168
158
var DARK_SHADOW = '1px 1px 0px rgba(0,0,0,0.4), -1px -1px 0px rgba(0,0,0,0.4)' ;
@@ -199,6 +189,34 @@ var DARK_DEFAULT_HUES = {
199
189
'hue-3' : 'A200'
200
190
}
201
191
} ;
192
+
193
+ // use inactive icon opacity from https://material.google.com/style/color.html#color-text-background-colors
194
+ // not inactive icon opacity from https://material.google.com/style/icons.html#icons-system-icons
195
+
196
+ var DARK_CONTRAST_OPACITY = {
197
+ 'icon' : 0.54 ,
198
+ 'secondary' : 0.54 ,
199
+ 'disabled' : 0.38 ,
200
+ 'hint' : 0.38 ,
201
+ 'divider' : 0.12 ,
202
+ } ;
203
+
204
+ var LIGHT_CONTRAST_OPACITY = {
205
+ 'icon' : 0.87 ,
206
+ 'secondary' : 0.7 ,
207
+ 'disabled' : 0.5 ,
208
+ 'hint' : 0.5 ,
209
+ 'divider' : 0.12
210
+ } ;
211
+
212
+ var STRONG_LIGHT_CONTRAST_OPACITY = {
213
+ 'icon' : 1.0 ,
214
+ 'secondary' : 0.7 ,
215
+ 'disabled' : 0.5 ,
216
+ 'hint' : 0.5 ,
217
+ 'divider' : 0.12
218
+ } ;
219
+
202
220
THEME_COLOR_TYPES . forEach ( function ( colorType ) {
203
221
// Color types with unspecified default hues will use these default hue values
204
222
var defaultDefaultHues = {
@@ -974,18 +992,45 @@ function parseRules(theme, colorType, rules) {
974
992
975
993
rules = rules . replace ( / T H E M E _ N A M E / g, theme . name ) ;
976
994
var themeNameRegex = new RegExp ( '\\.md-' + theme . name + '-theme' , 'g' ) ;
977
- var simpleVariableRegex = / ' ? " ? \{ \{ \s * ( [ a - z A - Z ] + ) - ( A ? \d + | h u e - [ 0 - 3 ] | s h a d o w | d e f a u l t ) - ? ( \d \. ? \d * ) ? ( c o n t r a s t ) ? \s * \} \} ' ? " ? / g;
995
+ // Matches '{{ primary-color }}', etc
996
+ var hueRegex = new RegExp ( '(?:\'|")?{{\\s*(' + colorType + ')-?(color|default)?-?(contrast)?-?((?:\\d\\.?\\d*)|(?:[a-zA-Z]+))?\\s*}}(\"|\')?' , 'g' ) ;
997
+ var simpleVariableRegex = / ' ? " ? \{ \{ \s * ( [ a - z A - Z ] + ) - ( A ? \d + | h u e - [ 0 - 3 ] | s h a d o w | d e f a u l t ) - ? ( c o n t r a s t ) ? - ? ( (?: \d \. ? \d * ) | (?: [ a - z A - Z ] + ) ) ? \s * \} \} ' ? " ? / g;
998
+ var palette = PALETTES [ color . name ] ;
999
+ var defaultBgHue = theme . colors [ 'background' ] . hues [ 'default' ] ;
1000
+ var defaultBgContrastType = PALETTES [ theme . colors [ 'background' ] . name ] [ defaultBgHue ] . contrastType ;
978
1001
979
1002
// find and replace simple variables where we use a specific hue, not an entire palette
980
1003
// eg. "{{primary-100}}"
981
1004
// \(' + THEME_COLOR_TYPES.join('\|') + '\)'
982
- rules = rules . replace ( simpleVariableRegex , function ( match , colorType , hue , opacity , contrast ) {
1005
+ rules = rules . replace ( simpleVariableRegex , function ( match , colorType , hue , contrast , opacity ) {
1006
+ var regexColorType = colorType ;
983
1007
if ( colorType === 'foreground' ) {
984
1008
if ( hue == 'shadow' ) {
985
1009
return theme . foregroundShadow ;
986
- } else {
987
- return theme . foregroundPalette [ hue ] || theme . foregroundPalette [ '1' ] ;
1010
+ } else if ( theme . foregroundPalette [ hue ] ) {
1011
+ // Use user defined palette number (ie: foreground-2)
1012
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ hue ] ) ) ;
1013
+ } else if ( theme . foregroundPalette [ '1' ] ) {
1014
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ '1' ] ) ) ;
1015
+ }
1016
+ // Default to background-default-contrast-{opacity}
1017
+ colorType = 'background' ;
1018
+ contrast = 'contrast' ;
1019
+ if ( ! opacity && hue ) {
1020
+ // Convert references to legacy hues to opacities (ie: foreground-4 to *-divider)
1021
+ switch ( hue ) {
1022
+ // hue-1 uses default opacity
1023
+ case '2' :
1024
+ opacity = 'secondary' ;
1025
+ break ;
1026
+ case '3' :
1027
+ opacity = 'disabled' ;
1028
+ break ;
1029
+ case '4' :
1030
+ opacity = 'divider' ;
1031
+ }
988
1032
}
1033
+ hue = 'default' ;
989
1034
}
990
1035
991
1036
// `default` is also accepted as a hue-value, because the background palettes are
@@ -994,7 +1039,42 @@ function parseRules(theme, colorType, rules) {
994
1039
hue = theme . colors [ colorType ] . hues [ hue ] ;
995
1040
}
996
1041
997
- return rgba ( ( PALETTES [ theme . colors [ colorType ] . name ] [ hue ] || '' ) [ contrast ? 'contrast' : 'value' ] , opacity ) ;
1042
+ var colorDetails = ( PALETTES [ theme . colors [ colorType ] . name ] [ hue ] || '' ) ;
1043
+
1044
+ // If user has specified a foreground color, use those
1045
+ if ( colorType === 'background' && contrast && regexColorType !== 'foreground' && colorDetails . contrastType == defaultBgContrastType ) {
1046
+ // Don't process if colorType was changed
1047
+ switch ( opacity ) {
1048
+ case 'secondary' :
1049
+ case 'icon' :
1050
+ if ( theme . foregroundPalette [ '2' ] ) {
1051
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ '2' ] ) ) ;
1052
+ }
1053
+ break ;
1054
+ case 'disabled' :
1055
+ case 'hint' :
1056
+ if ( theme . foregroundPalette [ '3' ] ) {
1057
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ '3' ] ) ) ;
1058
+ }
1059
+ break ;
1060
+ case 'divider' :
1061
+ if ( theme . foregroundPalette [ '4' ] ) {
1062
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ '4' ] ) ) ;
1063
+ }
1064
+ break ;
1065
+ default :
1066
+ if ( theme . foregroundPalette [ '1' ] ) {
1067
+ return rgba ( colorToRgbaArray ( theme . foregroundPalette [ '1' ] ) ) ;
1068
+ }
1069
+ break ;
1070
+ }
1071
+ }
1072
+
1073
+ if ( contrast && opacity ) {
1074
+ opacity = colorDetails . opacity [ opacity ] || opacity ;
1075
+ }
1076
+
1077
+ return rgba ( colorDetails [ contrast ? 'contrast' : 'value' ] , opacity ) ;
998
1078
} ) ;
999
1079
1000
1080
// Matches '{{ primary-color }}', etc
@@ -1004,10 +1084,13 @@ function parseRules(theme, colorType, rules) {
1004
1084
// For each type, generate rules for each hue (ie. default, md-hue-1, md-hue-2, md-hue-3)
1005
1085
angular . forEach ( [ 'default' , 'hue-1' , 'hue-2' , 'hue-3' ] , function ( hueName ) {
1006
1086
var newRule = rules
1007
- . replace ( hueRegex , function ( match , _ , matchedColorType , hueType , opacity ) {
1087
+ . replace ( hueRegex , function ( match , _ , matchedColorType , hueType , contrast , opacity ) {
1008
1088
var color = theme . colors [ matchedColorType ] ;
1009
1089
var palette = PALETTES [ color . name ] ;
1010
1090
var hueValue = color . hues [ hueName ] ;
1091
+ if ( contrast && opacity ) {
1092
+ opacity = palette [ hueValue ] . opacity [ opacity ] || opacity ;
1093
+ }
1011
1094
return rgba ( palette [ hueValue ] [ hueType === 'color' ? 'value' : 'contrast' ] , opacity ) ;
1012
1095
} ) ;
1013
1096
if ( hueName !== 'default' ) {
@@ -1114,6 +1197,37 @@ function generateAllThemes($injector, $mdTheming) {
1114
1197
delete palette . contrastStrongLightColors ;
1115
1198
delete palette . contrastDarkColors ;
1116
1199
1200
+ function getContrastType ( hueName ) {
1201
+ if ( defaultContrast === 'light' ? darkColors . indexOf ( hueName ) !== - 1 : lightColors . indexOf ( hueName ) === - 1 ) {
1202
+ return 'dark' ;
1203
+ }
1204
+ if ( strongLightColors . indexOf ( hueName ) !== - 1 ) {
1205
+ return 'strongLight' ;
1206
+ }
1207
+ return 'light' ;
1208
+ }
1209
+ function getContrastColor ( contrastType ) {
1210
+ switch ( contrastType ) {
1211
+ default :
1212
+ case 'strongLight' :
1213
+ return STRONG_LIGHT_CONTRAST_COLOR ;
1214
+ case 'light' :
1215
+ return LIGHT_CONTRAST_COLOR ;
1216
+ case 'dark' :
1217
+ return DARK_CONTRAST_COLOR ;
1218
+ }
1219
+ }
1220
+ function getOpacityValues ( contrastType ) {
1221
+ switch ( contrastType ) {
1222
+ default :
1223
+ case 'strongLight' :
1224
+ return STRONG_LIGHT_CONTRAST_OPACITY ;
1225
+ case 'light' :
1226
+ return LIGHT_CONTRAST_OPACITY ;
1227
+ case 'dark' :
1228
+ return DARK_CONTRAST_OPACITY ;
1229
+ }
1230
+ }
1117
1231
// Change { 'A100': '#fffeee' } to { 'A100': { value: '#fffeee', contrast:DARK_CONTRAST_COLOR }
1118
1232
angular . forEach ( palette , function ( hueValue , hueName ) {
1119
1233
if ( angular . isObject ( hueValue ) ) return ; // Already converted
@@ -1126,28 +1240,14 @@ function generateAllThemes($injector, $mdTheming) {
1126
1240
. replace ( '%3' , hueName ) ) ;
1127
1241
}
1128
1242
1243
+ var contrastType = getContrastType ( hueName ) ;
1129
1244
palette [ hueName ] = {
1130
1245
hex : palette [ hueName ] ,
1131
1246
value : rgbValue ,
1132
- contrast : getContrastColor ( )
1247
+ contrastType : contrastType ,
1248
+ contrast : getContrastColor ( contrastType ) ,
1249
+ opacity : getOpacityValues ( contrastType )
1133
1250
} ;
1134
- function getContrastColor ( ) {
1135
- if ( defaultContrast === 'light' ) {
1136
- if ( darkColors . indexOf ( hueName ) > - 1 ) {
1137
- return DARK_CONTRAST_COLOR ;
1138
- } else {
1139
- return strongLightColors . indexOf ( hueName ) > - 1 ? STRONG_LIGHT_CONTRAST_COLOR
1140
- : LIGHT_CONTRAST_COLOR ;
1141
- }
1142
- } else {
1143
- if ( lightColors . indexOf ( hueName ) > - 1 ) {
1144
- return strongLightColors . indexOf ( hueName ) > - 1 ? STRONG_LIGHT_CONTRAST_COLOR
1145
- : LIGHT_CONTRAST_COLOR ;
1146
- } else {
1147
- return DARK_CONTRAST_COLOR ;
1148
- }
1149
- }
1150
- }
1151
1251
} ) ;
1152
1252
}
1153
1253
}
0 commit comments