commit: 22b32f149d7753592fddcfb1cd2679b3fbac33d6
parent 0729b529d7da2002f25039e1dad2732302009cf3
Author: Henry Jameson <me@hjkos.com>
Date: Tue, 23 Jan 2024 19:18:55 +0200
shit more or less works for the very basic stuff
Diffstat:
9 files changed, 132 insertions(+), 22 deletions(-)
diff --git a/src/components/button.style.js b/src/components/button.style.js
@@ -2,10 +2,10 @@ export default {
name: 'Button',
selector: '.btn',
states: {
- hover: ':hover',
disabled: ':disabled',
+ toggled: '.toggled',
pressed: ':active',
- toggled: '.toggled'
+ hover: ':hover'
},
variants: {
danger: '.danger',
diff --git a/src/components/panel.style.js b/src/components/panel.style.js
@@ -4,6 +4,7 @@ export default {
validInnerComponents: [
'Text',
'Icon',
- 'Button'
+ 'Button',
+ 'PanelHeader'
]
}
diff --git a/src/components/panel_header.style.js b/src/components/panel_header.style.js
@@ -0,0 +1,9 @@
+export default {
+ name: 'PanelHeader',
+ selector: '.panel-heading',
+ validInnerComponents: [
+ 'Text',
+ 'Icon',
+ 'Button'
+ ]
+}
diff --git a/src/components/text.style.js b/src/components/text.style.js
@@ -1,6 +1,6 @@
export default {
name: 'Text',
- selector: '',
+ selector: '/*text*/',
states: {
faint: '.faint'
}
diff --git a/src/components/underlay.style.js b/src/components/underlay.style.js
@@ -1,6 +1,6 @@
export default {
name: 'Underlay',
- selector: '.underlay',
+ selector: '#app',
validInnerComponents: [
'Panel'
]
diff --git a/src/services/color_convert/color_convert.js b/src/services/color_convert/color_convert.js
@@ -188,6 +188,7 @@ export const rgba2css = function (rgba) {
*/
export const getTextColor = function (bg, text, preserve) {
const contrast = getContrastRatio(bg, text)
+ console.log(contrast)
if (contrast < 4.5) {
const base = typeof text.a !== 'undefined' ? { a: text.a } : {}
diff --git a/src/services/theme_data/pleromafe.t3.js b/src/services/theme_data/pleromafe.t3.js
@@ -4,7 +4,7 @@ export const sampleRules = [
// variant: 'normal',
// state: 'normal'
directives: {
- background: '#000',
+ background: '#000000',
opacity: 0.2
}
},
@@ -16,10 +16,16 @@ export const sampleRules = [
}
},
{
+ component: 'PanelHeader',
+ directives: {
+ background: '#000000',
+ opacity: 0.9
+ }
+ },
+ {
component: 'Button',
directives: {
background: '#808080',
- text: '#FFFFFF',
opacity: 0.5
}
}
diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js
@@ -1,5 +1,9 @@
+import { convert } from 'chromatism'
+import { alphaBlend, getTextColor, rgba2css } from '../color_convert/color_convert.js'
+
import Underlay from 'src/components/underlay.style.js'
import Panel from 'src/components/panel.style.js'
+import PanelHeader from 'src/components/panel_header.style.js'
import Button from 'src/components/button.style.js'
import Text from 'src/components/text.style.js'
import Icon from 'src/components/icon.style.js'
@@ -8,6 +12,7 @@ const root = Underlay
const components = {
Underlay,
Panel,
+ PanelHeader,
Button,
Text,
Icon
@@ -34,7 +39,7 @@ export const ruleToSelector = (rule) => {
const component = components[rule.component]
const { states, variants, selector } = component
- const applicableStates = (rule.state.filter(x => x !== 'normal') || []).map(state => states[state])
+ const applicableStates = ((rule.state || []).filter(x => x !== 'normal')).map(state => states[state])
const applicableVariantName = (rule.variant || 'normal')
let applicableVariant = ''
@@ -63,12 +68,37 @@ export const init = (ruleset) => {
const addRule = (rule) => {
rules.push(rule)
rulesByComponent[rule.component] = rulesByComponent[rule.component] || []
- rulesByComponent.push(rule)
+ rulesByComponent[rule.component].push(rule)
}
- ruleset.forEach(rule => {
+ const findRules = (combination) => rule => {
+ 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 (Object.prototype.hasOwnProperty.call(rule, 'state')) {
+ const ruleStatesSet = new Set(['normal', ...(rule.state || [])])
+ return combination.state.every(state => ruleStatesSet.has(state))
+ } else {
+ if (combination.state.length !== 1 || combination.state[0] !== 'normal') return false
+ return true
+ }
+ }
- })
+ const findLowerLevelRule = (parent, filter = () => true) => {
+ let lowerLevelComponent = null
+ let currentParent = parent
+ while (currentParent) {
+ const rulesParent = ruleset.filter(findRules(currentParent, true))
+ lowerLevelComponent = rulesParent[rulesParent.length - 1]
+ currentParent = currentParent.parent
+ if (lowerLevelComponent && filter(lowerLevelComponent)) currentParent = null
+ }
+ return filter(lowerLevelComponent) ? lowerLevelComponent : null
+ }
const processInnerComponent = (component, parent) => {
const {
@@ -87,18 +117,82 @@ export const init = (ruleset) => {
return stateCombinations.map(state => ({ variant, state }))
}).reduce((acc, x) => [...acc, ...x], [])
+ const VIRTUAL_COMPONENTS = new Set(['Text', 'Link', 'Icon'])
+
stateVariantCombination.forEach(combination => {
- // addRule(({
- // parent,
- // component: component.name,
- // state: combination.state,
- // variant: combination.variant
- // }))
+ const existingRules = ruleset.filter(findRules({ component: component.name, ...combination }))
+ const lastRule = existingRules[existingRules.length - 1]
+
+ if (existingRules.length !== 0) {
+ const { directives } = lastRule
+ const rgb = convert(directives.background).rgb
+
+ // TODO: DEFAULT TEXT COLOR
+ const bg = findLowerLevelRule(parent)?.cache.background || convert('#FFFFFF').rgb
+
+ if (!lastRule.cache?.background) {
+ const blend = directives.opacity < 1 ? alphaBlend(rgb, directives.opacity, bg) : rgb
+ lastRule.cache = lastRule.cache || {}
+ lastRule.cache.background = blend
+
+ addRule(lastRule)
+ }
+ } else {
+ if (VIRTUAL_COMPONENTS.has(component.name)) {
+ const selector = component.name + ruleToSelector({ component: component.name, ...combination })
+
+ const lowerLevel = findLowerLevelRule(parent, (r) => {
+ if (components[r.component].validInnerComponents.indexOf(component.name) < 0) return false
+ if (r.cache?.background === undefined) return false
+ if (r.cache.textDefined) {
+ return !r.cache.textDefined[selector]
+ }
+ return true
+ })
+ if (!lowerLevel) return
+ lowerLevel.cache.textDefined = lowerLevel.cache.textDefined || {}
+ lowerLevel.cache.textDefined[selector] = true
+ addRule({
+ parent,
+ component: component.name,
+ ...combination,
+ directives: {
+ // TODO: DEFAULT TEXT COLOR
+ textColor: getTextColor(convert(lowerLevel.cache.background).rgb, convert('#FFFFFF').rgb, component.name === 'Link'),
+ // Debug: lets you see what it think background color should be
+ background: convert(lowerLevel.cache.background).hex
+ }
+ })
+ }
+ }
innerComponents.forEach(innerComponent => processInnerComponent(innerComponent, { parent, component: name, ...combination }))
})
}
processInnerComponent(components[rootName])
- return rules
+
+ // console.info(rules.map(x => [
+ // (parent?.component || 'root') + ' -> ' + x.component,
+ // // 'Cached background:' + convert(bg).hex,
+ // // 'Color: ' + convert(x.directives.background).hex + ' A:' + x.directives.opacity,
+ // JSON.stringify(x.directives)
+ // // '=> Blend: ' + convert(x.cache.background).hex
+ // ].join(' ')))
+
+ return {
+ raw: rules,
+ css: rules.map(rule => {
+ const header = ruleToSelector(rule) + ' {'
+ const footer = '}'
+ const directives = Object.entries(rule.directives).map(([k, v]) => {
+ switch (k) {
+ case 'background': return 'background-color: ' + rgba2css({ ...convert(v).rgb, a: rule.directives.opacity ?? 1 })
+ case 'textColor': return 'color: ' + rgba2css({ ...convert(v).rgb, a: rule.directives.opacity ?? 1 })
+ default: return ''
+ }
+ }).filter(x => x).map(x => ' ' + x).join(';\n')
+ return [header, directives, footer].join('\n')
+ })
+ }
}
diff --git a/test/unit/specs/services/theme_data/theme_data3.spec.js b/test/unit/specs/services/theme_data/theme_data3.spec.js
@@ -1,8 +1,7 @@
// import { topoSort } from 'src/services/theme_data/theme_data.service.js'
import {
getAllPossibleCombinations,
- init,
- ruleToSelector
+ init
} from 'src/services/theme_data/theme_data_3.service.js'
import {
sampleRules
@@ -19,8 +18,8 @@ describe.only('Theme Data 3', () => {
describe('init', () => {
it('test simple case', () => {
const out = init(sampleRules)
- console.log(JSON.stringify(out, null, 2))
- out.forEach(r => console.log(ruleToSelector(r)))
+ // console.log(JSON.stringify(out, null, 2))
+ console.log('\n' + out.css.join('\n') + '\n')
})
})
})