diff --git a/src/components/button.style.js b/src/components/button.style.js index 51f781e1..49147c8d 100644 --- a/src/components/button.style.js +++ b/src/components/button.style.js @@ -15,5 +15,20 @@ export default { validInnerComponents: [ 'Text', 'Icon' + ], + defaultRules: [ + { + component: 'Button', + directives: { + background: '--fg' + } + }, + { + component: 'Button', + state: ['hover'], + directives: { + background: '#FFFFFF' + } + } ] } diff --git a/src/components/link.style.js b/src/components/link.style.js index 0128fd91..d13cef33 100644 --- a/src/components/link.style.js +++ b/src/components/link.style.js @@ -16,7 +16,6 @@ export default { component: 'Link', state: ['faint'], directives: { - textColor: '--link', textOpacity: 0.5, textOpacityMode: 'fake' } diff --git a/src/components/panel.style.js b/src/components/panel.style.js index 870f5099..a9de7e56 100644 --- a/src/components/panel.style.js +++ b/src/components/panel.style.js @@ -7,5 +7,13 @@ export default { 'Icon', 'Button', 'PanelHeader' + ], + defaultRules: [ + { + component: 'Panel', + directives: { + background: '--fg' + } + } ] } diff --git a/src/components/panel_header.style.js b/src/components/panel_header.style.js index e83e1f15..01f8a67f 100644 --- a/src/components/panel_header.style.js +++ b/src/components/panel_header.style.js @@ -6,5 +6,14 @@ export default { 'Link', 'Icon', 'Button' + ], + defaultRules: [ + { + component: 'PanelHeader', + directives: { + background: '--fg' + // opacity: 0.9 + } + } ] } diff --git a/src/components/text.style.js b/src/components/text.style.js index e52b6f68..18472032 100644 --- a/src/components/text.style.js +++ b/src/components/text.style.js @@ -19,7 +19,6 @@ export default { component: 'Text', state: ['faint'], directives: { - textColor: '--text', textOpacity: 0.5 } }, @@ -29,15 +28,6 @@ export default { directives: { textColor: '--cGreen' } - }, - { - component: 'Text', - variant: 'greentext', - state: ['faint'], - directives: { - textColor: '--cGreen', - textOpacity: 0.5 - } } ] } diff --git a/src/components/underlay.style.js b/src/components/underlay.style.js index c35fbada..380ea26e 100644 --- a/src/components/underlay.style.js +++ b/src/components/underlay.style.js @@ -4,5 +4,16 @@ export default { outOfTreeSelector: '.underlay', validInnerComponents: [ 'Panel' + ], + defaultRules: [ + { + component: 'Underlay', + // variant: 'normal', + // state: 'normal' + directives: { + background: '#000000', + opacity: 0.2 + } + } ] } diff --git a/src/services/theme_data/pleromafe.t3.js b/src/services/theme_data/pleromafe.t3.js index 9fadf0ee..db612a5b 100644 --- a/src/services/theme_data/pleromafe.t3.js +++ b/src/services/theme_data/pleromafe.t3.js @@ -1,40 +1,2 @@ export const sampleRules = [ - { - component: 'Underlay', - // variant: 'normal', - // state: 'normal' - directives: { - background: '#000000', - opacity: 0.2 - } - }, - { - component: 'Panel', - directives: { - background: '--fg' - // opacity: 0.9 - } - }, - { - component: 'PanelHeader', - directives: { - background: '--fg' - // opacity: 0.9 - } - }, - { - component: 'Button', - directives: { - background: '--fg' - // opacity: 0.8 - } - }, - { - component: 'Button', - state: ['hover'], - directives: { - background: '#FFFFFF' - // opacity: 0.9 - } - } ] diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js index c9468d07..b7679021 100644 --- a/src/services/theme_data/theme_data_3.service.js +++ b/src/services/theme_data/theme_data_3.service.js @@ -1,5 +1,6 @@ -import { convert } from 'chromatism' -import { alphaBlend, getTextColor, rgba2css, mixrgb } from '../color_convert/color_convert.js' +import { convert, brightness } from 'chromatism' +import merge from 'lodash.merge' +import { alphaBlend, getTextColor, rgba2css, mixrgb, relativeLuminance } from '../color_convert/color_convert.js' import Underlay from 'src/components/underlay.style.js' import Panel from 'src/components/panel.style.js' @@ -87,27 +88,35 @@ export const init = (extraRuleset, palette) => { rulesByComponent[rule.component].push(rule) } - const findRules = (combination, parent) => rule => { + const findRules = (searchCombination, parent) => rule => { // inexact search const doesCombinationMatch = () => { - if (combination.component !== rule.component) return false - if (Object.prototype.hasOwnProperty.call(rule, 'variant')) { - if (combination.variant !== rule.variant) return false - } else { - if (combination.variant !== 'normal') return false + if (searchCombination.component !== rule.component) return false + const ruleVariant = Object.prototype.hasOwnProperty.call(rule, 'variant') ? rule.variant : 'normal' + + if (ruleVariant !== 'normal') { + if (searchCombination.variant !== rule.variant) return false } - if (Object.prototype.hasOwnProperty.call(rule, 'state')) { - const ruleStatesSet = new Set(['normal', ...(rule.state || [])]) - const combinationSet = new Set(['normal', ...combination.state]) - const setsAreEqual = combination.state.every(state => ruleStatesSet.has(state)) && + const ruleHasStateDefined = Object.prototype.hasOwnProperty.call(rule, 'state') + let ruleStateSet + if (ruleHasStateDefined) { + ruleStateSet = new Set(['normal', ...rule.state]) + } else { + ruleStateSet = new Set(['normal']) + } + + if (ruleStateSet.size > 1) { + const ruleStatesSet = ruleStateSet + const combinationSet = new Set(['normal', ...searchCombination.state]) + const setsAreEqual = searchCombination.state.every(state => ruleStatesSet.has(state)) && [...ruleStatesSet].every(state => combinationSet.has(state)) return setsAreEqual } else { - if (combination.state.length !== 1 || combination.state[0] !== 'normal') return false return true } } + const combinationMatches = doesCombinationMatch() if (!parent || !combinationMatches) return combinationMatches @@ -154,21 +163,31 @@ export const init = (extraRuleset, palette) => { return filter(lowerLevelComponent) ? lowerLevelComponent : null } - const findColor = (color) => { - if (typeof color === 'string' && color.startsWith('--')) { - const name = color.substring(2) - return palette[name] + const findColor = (color, background) => { + if (typeof color !== 'string' || !color.startsWith('--')) return color + let targetColor = null + // Color references other color + const [variable, modifier] = color.split(/,/g).map(str => str.trim()) + const variableSlot = variable.substring(2) + targetColor = palette[variableSlot] + + if (modifier) { + const effectiveBackground = background ?? targetColor + const isLightOnDark = relativeLuminance(convert(effectiveBackground).rgb) < 0.5 + const mod = isLightOnDark ? 1 : -1 + targetColor = brightness(Number.parseFloat(modifier) * mod, targetColor).rgb } - return color + + return targetColor } const getTextColorAlpha = (rule, lowerRule, value) => { const opacity = rule.directives.textOpacity - const textColor = convert(findColor(value)).rgb + const backgroundColor = convert(lowerRule.cache.background).rgb + const textColor = convert(findColor(value, backgroundColor)).rgb if (opacity === null || opacity === undefined || opacity >= 1) { return convert(textColor).hex } - const backgroundColor = convert(lowerRule.cache.background).rgb if (opacity === 0) { return convert(backgroundColor).hex } @@ -217,6 +236,7 @@ export const init = (extraRuleset, palette) => { ].join('') const lowerLevel = findLowerLevelRule(parent, (r) => { + if (!r) return false if (components[r.component].validInnerComponents.indexOf(component.name) < 0) return false if (r.cache.background === undefined) return false if (r.cache.textDefined) { @@ -234,15 +254,15 @@ export const init = (extraRuleset, palette) => { if (!inheritedTextColorRule) { const generalTextColorRules = ruleset.filter(findRules({ component: component.name, ...combination }, null, true)) - inheritedTextColorRule = generalTextColorRules[generalTextColorRules.length - 1] + inheritedTextColorRule = generalTextColorRules.reduce((acc, rule) => merge(acc, rule), {}) } else { - inheritedTextColorRule = inheritedTextColorRules[inheritedTextColorRules.length - 1] + inheritedTextColorRule = inheritedTextColorRules.reduce((acc, rule) => merge(acc, rule), {}) } let inheritedTextColor let inheritedTextOpacity = {} if (inheritedTextColorRule) { - inheritedTextColor = findColor(inheritedTextColorRule.directives.textColor) + inheritedTextColor = findColor(inheritedTextColorRule.directives.textColor, convert(lowerLevel.cache.background).rgb) // also inherit opacity settings const { textOpacity, textOpacityMode } = inheritedTextColorRule.directives inheritedTextOpacity = { textOpacity, textOpacityMode } @@ -284,8 +304,11 @@ export const init = (extraRuleset, palette) => { // Global (general) rules if (existingGlobalRules.length !== 0) { + const totalRule = existingGlobalRules.reduce((acc, rule) => merge(acc, rule), {}) + const { directives } = totalRule + + // last rule is used as a cache const lastRule = existingGlobalRules[existingGlobalRules.length - 1] - const { directives } = lastRule lastRule.cache = lastRule.cache || {} if (directives.background) {