-
-
Save BoLaMN/5d3543dc522b35f631de to your computer and use it in GitHub Desktop.
do -> | |
angular.module 'material.core.colors', ['material.core.theming'] | |
.provider '$mdColors', ($mdColorPalette) -> | |
style = angular.element '<style></style>' | |
document.head.appendChild style[0] | |
stylesheet = style[0].sheet | |
index = 0 | |
DARK_CONTRAST_COLOR = [ 0, 0, 0, 0.87 ] | |
LIGHT_CONTRAST_COLOR = [ 255, 255, 255, 0.87 ] | |
STRONG_LIGHT_CONTRAST_COLOR = [ 255, 255, 255 ] | |
addCustomStyle = (cssname, name, color, contrast = '') -> | |
if contrast | |
contrast = "color: #{contrast}" | |
stylesheet.insertRule ".md-#{cssname}-#{name}.text { #{contrast} !important }", index | |
stylesheet.insertRule ".md-#{cssname}-#{name}.background { background-color: #{color}; #{contrast} }", index + 1 | |
index += 2 | |
return | |
clearStyleSheet = -> | |
while stylesheet.cssRules.length > 0 | |
stylesheet.deleteRule 0 | |
colorNames: [] | |
colorStore: {} | |
colorSelected: null | |
themeNames: [] | |
themeStore: {} | |
getContrastColor: (palette, hueName) -> | |
{ contrastDefaultColor, contrastLightColors, contrastStrongLightColors, contrastDarkColors } = palette | |
if angular.isString contrastLightColors | |
contrastLightColors = contrastLightColors.split ' ' | |
if angular.isString contrastStrongLightColors | |
contrastStrongLightColors = contrastStrongLightColors.split ' ' | |
if angular.isString contrastDarkColors | |
contrastDarkColors = contrastDarkColors.split ' ' | |
if contrastDefaultColor is 'light' | |
if contrastDarkColors?.indexOf(hueName) > -1 | |
DARK_CONTRAST_COLOR | |
else | |
if contrastStrongLightColors?.indexOf(hueName) > -1 | |
STRONG_LIGHT_CONTRAST_COLOR | |
else | |
LIGHT_CONTRAST_COLOR | |
else | |
if contrastLightColors?.indexOf(hueName) > -1 | |
if contrastStrongLightColors?.indexOf(hueName) > -1 | |
STRONG_LIGHT_CONTRAST_COLOR | |
else | |
LIGHT_CONTRAST_COLOR | |
else | |
DARK_CONTRAST_COLOR | |
storeAndLoadPalettes: (colors, themes, primaryPalette) -> | |
@colorStore = colors | |
@themeStore = themes | |
@colorNames = Object.keys colors | |
@themeNames = Object.keys themes | |
@loadPalette primaryPalette | |
return | |
loadPalette: (newPalette) -> | |
if @colorSelected | |
clearStyleSheet() | |
@colorSelected = newPalette | |
for name, color of @colorStore[newPalette] | |
addCustomStyle 'fg', name, color.value, color.contrast | |
addCustomStyle 'bg', name, color.value, color.contrast | |
for themeName, theme of @themeStore | |
cleanedThemeName = if themeName is 'default' then '' else themeName + '-' | |
for groupName, group of theme | |
for name, color of group | |
addCustomStyle cleanedThemeName + groupName, name, color.value, color.contrast | |
return | |
$get: -> | |
colorNames: @colorNames | |
colorStore: @colorStore | |
colorSelected: @colorSelected | |
themeNames: @themeNames | |
themeStore: @themeStore | |
loadPalette: @loadPalette | |
.config ($mdThemingProvider, $mdColorsProvider) -> | |
colorStore = {} | |
parsePalette = (paletteName, palette) -> | |
paletteContrast = palette | |
hueColors = $mdThemingProvider._THEMES['default'].colors['primary'].hues | |
colors = {} | |
addHue = (hueName) -> | |
contrastColor = $mdThemingProvider._rgba $mdColorsProvider.getContrastColor(palette, hueColors[hueName]) | |
colors[hueName] = value: palette[hueColors[hueName]], contrast: contrastColor | |
copyColors = (colorName) -> | |
if /#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})\b/.test(palette[colorName]) | |
contrastColor = $mdThemingProvider._rgba $mdColorsProvider.getContrastColor(palette, colorName) | |
colors[colorName] = value: palette[colorName], contrast: contrastColor | |
return | |
colorStore[paletteName] = colors | |
Object.keys(palette).forEach copyColors | |
Object.keys(hueColors).forEach addHue | |
return | |
for paletteName, palette of $mdThemingProvider._PALETTES | |
parsePalette paletteName, palette | |
themeStore = {} | |
parseTheme = (themeName) -> | |
themeColorGroups = $mdThemingProvider._THEMES[themeName].colors | |
colors = {} | |
defineColors = (themeGroup) -> | |
themeStore[themeName][themeGroup] ?= {} | |
definedColors = colorStore[themeColorGroups[themeGroup].name] | |
for item, value of themeColorGroups[themeGroup].hues | |
themeStore[themeName][themeGroup][item] = definedColors[value] | |
return | |
themeStore[themeName] ?= {} | |
Object.keys(themeColorGroups).forEach defineColors | |
return | |
Object.keys($mdThemingProvider._THEMES).forEach parseTheme | |
primaryPalette = $mdThemingProvider._THEMES['default'].colors.primary.name | |
$mdColorsProvider.storeAndLoadPalettes colorStore, themeStore, primaryPalette | |
return | |
.directive 'mdStyle', ($mdColors, $parse) -> | |
restrict: 'A' | |
link: (scope, element, attrs) -> | |
{ colorSelected, colorStore, colorNames, themeStore, themeNames } = $mdColors | |
parsedStyles = $parse attrs.mdStyle | |
styles = parsedStyles() | |
for cssName, cssValue of styles | |
[color, hue, hue2] = cssValue.split '.' | |
if color in ['primary', 'accent', 'background', 'foreground', 'warn'] | |
color = themeStore['default'][color] | |
else if color not in colorNames | |
color = colorSelected | |
if themeStore[color] | |
color = themeStore[color] | |
if hue2 | |
color = color[hue][hue2] | |
else | |
color = color[hue]['default'] | |
color = colorStore[color] or color | |
colorObject = color[hue] or color.default | |
if colorObject | |
if cssName is 'background-color' | |
element.css 'color', colorObject.contrast | |
if angular.isString attrs.mdContrast | |
element.css cssName, colorObject.contrast | |
else | |
element.css cssName, colorObject.value |
BoLaMN
commented
Sep 12, 2015
This looks really interesting and I've been trying to understand/adapt it, but I'm wondering about some stuff:
- Does the
getContrastColor
function work correctly? It looks forhueName
in each color set, yethueName
does not appear to be a variable in scope. - What is the point of
colorToRgbaArray
? It looks like it only gets used with the constants, which could just as easily be arrays in the first place, and it has all that handling for formats that never get used. copyColors
takes two arguments, but the second one does not seem to be used.
So I now understand that the parts I was confused by came from material's own code, hence some of it not being applicable here. Still, it was very instructive. Here's what I came up based on this if you're curuous (just for generating classes, not the directive; and it's es6+):
module.run(($mdColorPalette, $mdTheming) => {
const { THEMES } = $mdTheming;
const rules = [];
for (const themeName in THEMES) {
const { colors } = THEMES[themeName];
const themeCls = themeName == 'default' ? '' : `.md-${ themeName }-theme`;
for (const intention in colors) {
const intentCls = `.md-${ intention }`;
const {
name: color,
hues: {
'default': h0,
'hue-1': h1,
'hue-2': h2,
'hue-3': h3
}
} = colors[intention];
const palette = $mdColorPalette[color];
[ h0, h1, h2, h3 ]
.map(hue => {
const { contrast, value } = palette[hue];
return [ value, contrast ].map(([ ...rgb ]) =>
`rgb${ rgb.length == 4 ? 'a' : '' }(${ rgb.join(',') })`
);
})
.forEach(([ color, contrast ], i) => {
const hueCls = i ? `.md-hue-${ i }` : '';
const selector = [ themeCls, intentCls, hueCls ]
.filter(n => n)
.join('');
const textRule = `${ selector }.text{color:${ color }}`;
const bgRule = selector +
`.background{background-color:${ color };color:${ contrast }}`;
rules.push(textRule, bgRule);
});
}
}
const style = document.createElement('style');
document.head.appendChild(style);
const { sheet } = style;
rules.forEach(::sheet.insertRule);
});
Hey, sorry i did some extra work on this but forgot to update. fixes all the things you pointed out, it now checks the contrast colour correctly and nice pickup with the colorToRgbaArray ive ripped that out and replaced the them with arrays to reduce the code.
I added checking for "md-contrast" in the md-style directive eg <md-button md-contrast class="md-accent-default background">My Button</md-button>
Cheers
i should also point out that this md-style directive actually uses $parse instead of isolated or child scopes avoiding the multiple directives scope error.