better virtual components and stuff

This commit is contained in:
Henry Jameson 2024-01-31 17:39:51 +02:00
parent ff2db7a247
commit 53a4b1f9a6
17 changed files with 354 additions and 137 deletions

View File

@ -24,8 +24,7 @@ body {
font-family: sans-serif; font-family: sans-serif;
font-family: var(--interfaceFont, sans-serif); font-family: var(--interfaceFont, sans-serif);
margin: 0; margin: 0;
color: $fallback--text; color: var(--text);
color: var(--text, $fallback--text);
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
overscroll-behavior-y: none; overscroll-behavior-y: none;
@ -111,8 +110,7 @@ body {
a { a {
text-decoration: none; text-decoration: none;
color: $fallback--link; color: var(--link);
color: var(--link, $fallback--link);
} }
h4 { h4 {
@ -128,8 +126,7 @@ h4 {
i[class*="icon-"], i[class*="icon-"],
.svg-inline--fa, .svg-inline--fa,
.iconLetter { .iconLetter {
color: $fallback--icon; color: var(--icon);
color: var(--icon, $fallback--icon);
} }
.button-unstyled:hover, .button-unstyled:hover,
@ -763,17 +760,11 @@ option {
} }
.faint { .faint {
color: $fallback--faint; --text: var(--textFaint);
color: var(--faint, $fallback--faint); --textGreentext: var(--textGreentextFaint);
} --link: var(--linkFaint);
.faint-link { color: var(--text);
color: $fallback--faint;
color: var(--faint, $fallback--faint);
&:hover {
text-decoration: underline;
}
} }
.visibility-notice { .visibility-notice {
@ -816,6 +807,11 @@ option {
opacity: 0.25; opacity: 0.25;
} }
.timeago {
--link: var(--text);
--linkFaint: var(--textFaint);
}
.login-hint { .login-hint {
text-align: center; text-align: center;

View File

@ -1,4 +1,15 @@
export default { export default {
name: 'Icon', name: 'Icon',
selector: '.icon' virtual: true,
selector: '.svg-inline--fa',
defaultRules: [
{
component: 'Icon',
directives: {
textColor: '--text',
textOpacity: 0.5,
textOpacityMode: 'mixrgb'
}
}
]
} }

View File

@ -0,0 +1,25 @@
export default {
name: 'Link',
selector: 'a',
virtual: true,
states: {
faint: '.faint'
},
defaultRules: [
{
component: 'Link',
directives: {
textColor: '--link'
}
},
{
component: 'Link',
state: ['faint'],
directives: {
textColor: '--link',
textOpacity: 0.5,
textOpacityMode: 'fake'
}
}
]
}

View File

@ -155,7 +155,7 @@
<router-link <router-link
v-if="notification.status" v-if="notification.status"
:to="{ name: 'conversation', params: { id: notification.status.id } }" :to="{ name: 'conversation', params: { id: notification.status.id } }"
class="timeago-link faint-link" class="timeago-link faint"
> >
<Timeago <Timeago
:time="notification.created_at" :time="notification.created_at"

View File

@ -7,8 +7,7 @@
} }
.loadmore-error { .loadmore-error {
color: $fallback--text; color: var(--text);
color: var(--text, $fallback--text);
} }
.notification { .notification {
@ -25,7 +24,7 @@
&.unseen { &.unseen {
.notification-overlay { .notification-overlay {
background-image: linear-gradient(135deg, var(--badgeNotification, $fallback--cRed) 4px, transparent 10px); background-image: linear-gradient(135deg, var(--badgeNotification) 4px, transparent 10px);
} }
} }
} }
@ -60,24 +59,17 @@
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
.faint {
--link: var(--faintLink);
--text: var(--faint);
}
} }
.follow-request-accept { .follow-request-accept {
&:hover { &:hover {
color: $fallback--text; color: var(--text);
color: var(--text, $fallback--text);
} }
} }
.follow-request-reject { .follow-request-reject {
&:hover { &:hover {
color: $fallback--cRed; color: var(--cRed);
color: var(--cRed, $fallback--cRed);
} }
} }

View File

@ -3,6 +3,7 @@ export default {
selector: '.panel', selector: '.panel',
validInnerComponents: [ validInnerComponents: [
'Text', 'Text',
'Link',
'Icon', 'Icon',
'Button', 'Button',
'PanelHeader' 'PanelHeader'

View File

@ -3,6 +3,7 @@ export default {
selector: '.panel-heading', selector: '.panel-heading',
validInnerComponents: [ validInnerComponents: [
'Text', 'Text',
'Link',
'Icon', 'Icon',
'Button' 'Button'
] ]

View File

@ -180,7 +180,7 @@
<span class="heading-right"> <span class="heading-right">
<router-link <router-link
class="timeago faint-link" class="timeago faint"
:to="{ name: 'conversation', params: { id: status.id } }" :to="{ name: 'conversation', params: { id: status.id } }"
> >
<Timeago <Timeago

View File

@ -113,12 +113,11 @@
} }
.greentext { .greentext {
color: $fallback--cGreen; color: var(--textGreentext);
color: var(--postGreentext, $fallback--cGreen);
} }
.cyantext { .cyantext {
color: var(--postCyantext, $fallback--cBlue); color: var(--textCyantext);
} }
&.-compact { &.-compact {

View File

@ -1,7 +1,43 @@
export default { export default {
name: 'Text', name: 'Text',
selector: '/*text*/', selector: '/*text*/',
virtual: true,
variants: {
greentext: '.greentext'
},
states: { states: {
faint: '.faint' faint: '.faint'
},
defaultRules: [
{
component: 'Text',
directives: {
textColor: '--text'
}
},
{
component: 'Text',
state: ['faint'],
directives: {
textColor: '--text',
textOpacity: 0.5
}
},
{
component: 'Text',
variant: 'greentext',
directives: {
textColor: '--cGreen'
}
},
{
component: 'Text',
variant: 'greentext',
state: ['faint'],
directives: {
textColor: '--cGreen',
textOpacity: 0.5
} }
} }
]
}

View File

@ -1,6 +1,7 @@
export default { export default {
name: 'Underlay', name: 'Underlay',
selector: '#app', selector: '#content',
outOfTreeSelector: '.underlay',
validInnerComponents: [ validInnerComponents: [
'Panel' 'Panel'
] ]

View File

@ -143,12 +143,6 @@
box-shadow: var(--panelHeaderShadow); box-shadow: var(--panelHeaderShadow);
} }
a,
.-link {
color: $fallback--link;
color: var(--panelLink, $fallback--link);
}
.button-unstyled:hover, .button-unstyled:hover,
a:hover { a:hover {
i[class*="icon-"], i[class*="icon-"],
@ -164,11 +158,6 @@
color: var(--panelFaint, $fallback--faint); color: var(--panelFaint, $fallback--faint);
} }
.faint-link {
color: $fallback--faint;
color: var(--faintLink, $fallback--faint);
}
&:not(.-flexible-height) { &:not(.-flexible-height) {
> .button-default { > .button-default {
flex-shrink: 0; flex-shrink: 0;

View File

@ -173,7 +173,7 @@ export const mixrgb = (a, b) => {
* @returns {String} CSS rgba() color * @returns {String} CSS rgba() color
*/ */
export const rgba2css = function (rgba) { export const rgba2css = function (rgba) {
return `rgba(${Math.floor(rgba.r)}, ${Math.floor(rgba.g)}, ${Math.floor(rgba.b)}, ${rgba.a})` return `rgba(${Math.floor(rgba.r)}, ${Math.floor(rgba.g)}, ${Math.floor(rgba.b)}, ${rgba.a ?? 1})`
} }
/** /**
@ -188,7 +188,6 @@ export const rgba2css = function (rgba) {
*/ */
export const getTextColor = function (bg, text, preserve) { export const getTextColor = function (bg, text, preserve) {
const contrast = getContrastRatio(bg, text) const contrast = getContrastRatio(bg, text)
console.log(contrast)
if (contrast < 4.5) { if (contrast < 4.5) {
const base = typeof text.a !== 'undefined' ? { a: text.a } : {} const base = typeof text.a !== 'undefined' ? { a: text.a } : {}

View File

@ -1,10 +1,15 @@
import { convert } from 'chromatism' import { convert } from 'chromatism'
import { rgb2hex, hex2rgb, rgba2css, getCssColor, relativeLuminance } from '../color_convert/color_convert.js' import { rgb2hex, hex2rgb, rgba2css, getCssColor, relativeLuminance } from '../color_convert/color_convert.js'
import { getColors, computeDynamicColor, getOpacitySlot } from '../theme_data/theme_data.service.js' import { getColors, computeDynamicColor, getOpacitySlot } from '../theme_data/theme_data.service.js'
import { init } from '../theme_data/theme_data_3.service.js'
import {
sampleRules
} from 'src/services/theme_data/pleromafe.t3.js'
import { defaultState } from '../../modules/config.js' import { defaultState } from '../../modules/config.js'
export const applyTheme = (input) => { export const applyTheme = (input) => {
const { rules } = generatePreset(input) const { rules, t3b } = generatePreset(input)
const themes3 = init(sampleRules, t3b)
const head = document.head const head = document.head
const body = document.body const body = document.body
body.classList.add('hidden') body.classList.add('hidden')
@ -18,6 +23,10 @@ export const applyTheme = (input) => {
styleSheet.insertRule(`:root { ${rules.colors} }`, 'index-max') styleSheet.insertRule(`:root { ${rules.colors} }`, 'index-max')
styleSheet.insertRule(`:root { ${rules.shadows} }`, 'index-max') styleSheet.insertRule(`:root { ${rules.shadows} }`, 'index-max')
styleSheet.insertRule(`:root { ${rules.fonts} }`, 'index-max') styleSheet.insertRule(`:root { ${rules.fonts} }`, 'index-max')
themes3.css.forEach(rule => {
console.log(rule)
styleSheet.insertRule(rule, 'index-max')
})
body.classList.remove('hidden') body.classList.remove('hidden')
} }
@ -326,7 +335,7 @@ export const generateShadows = (input, colors) => {
} }
} }
export const composePreset = (colors, radii, shadows, fonts) => { export const composePreset = (colors, radii, shadows, fonts, t3b) => {
return { return {
rules: { rules: {
...shadows.rules, ...shadows.rules,
@ -339,7 +348,8 @@ export const composePreset = (colors, radii, shadows, fonts) => {
...colors.theme, ...colors.theme,
...radii.theme, ...radii.theme,
...fonts.theme ...fonts.theme
} },
t3b
} }
} }
@ -349,7 +359,8 @@ export const generatePreset = (input) => {
colors, colors,
generateRadii(input), generateRadii(input),
generateShadows(input, colors.theme.colors, colors.mod), generateShadows(input, colors.theme.colors, colors.mod),
generateFonts(input) generateFonts(input),
colors.theme.colors
) )
} }

View File

@ -11,30 +11,30 @@ export const sampleRules = [
{ {
component: 'Panel', component: 'Panel',
directives: { directives: {
background: '#FFFFFF', background: '--fg'
opacity: 0.9 // opacity: 0.9
} }
}, },
{ {
component: 'PanelHeader', component: 'PanelHeader',
directives: { directives: {
background: '#000000', background: '--fg'
opacity: 0.9 // opacity: 0.9
} }
}, },
{ {
component: 'Button', component: 'Button',
directives: { directives: {
background: '#000000', background: '--fg'
opacity: 0.8 // opacity: 0.8
} }
}, },
{ {
component: 'Button', component: 'Button',
state: ['hover'], state: ['hover'],
directives: { directives: {
background: '#FF00FF', background: '#FFFFFF'
opacity: 0.9 // opacity: 0.9
} }
} }
] ]

View File

@ -1,11 +1,12 @@
import { convert } from 'chromatism' import { convert } from 'chromatism'
import { alphaBlend, getTextColor, rgba2css } from '../color_convert/color_convert.js' import { alphaBlend, getTextColor, rgba2css, mixrgb } from '../color_convert/color_convert.js'
import Underlay from 'src/components/underlay.style.js' import Underlay from 'src/components/underlay.style.js'
import Panel from 'src/components/panel.style.js' import Panel from 'src/components/panel.style.js'
import PanelHeader from 'src/components/panel_header.style.js' import PanelHeader from 'src/components/panel_header.style.js'
import Button from 'src/components/button.style.js' import Button from 'src/components/button.style.js'
import Text from 'src/components/text.style.js' import Text from 'src/components/text.style.js'
import Link from 'src/components/link.style.js'
import Icon from 'src/components/icon.style.js' import Icon from 'src/components/icon.style.js'
const root = Underlay const root = Underlay
@ -15,6 +16,7 @@ const components = {
PanelHeader, PanelHeader,
Button, Button,
Text, Text,
Link,
Icon Icon
} }
@ -35,9 +37,9 @@ export const getAllPossibleCombinations = (array) => {
return combos.reduce((acc, x) => [...acc, ...x], []) return combos.reduce((acc, x) => [...acc, ...x], [])
} }
export const ruleToSelector = (rule) => { export const ruleToSelector = (rule, isParent) => {
const component = components[rule.component] const component = components[rule.component]
const { states, variants, selector } = component const { states, variants, selector, outOfTreeSelector } = 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])
@ -47,31 +49,47 @@ export const ruleToSelector = (rule) => {
applicableVariant = variants[applicableVariantName] applicableVariant = variants[applicableVariantName]
} }
const selectors = [selector, applicableVariant, ...applicableStates] let realSelector
if (isParent) {
realSelector = selector
} else {
if (outOfTreeSelector) realSelector = outOfTreeSelector
else realSelector = selector
}
const selectors = [realSelector, applicableVariant, ...applicableStates]
.toSorted((a, b) => { .toSorted((a, b) => {
if (a.startsWith(':')) return 1 if (a.startsWith(':')) return 1
else return -1 if (!a.startsWith('.')) return -1
else return 0
}) })
.join('') .join('')
if (rule.parent) { if (rule.parent) {
return ruleToSelector(rule.parent) + ' ' + selectors return ruleToSelector(rule.parent, true) + ' ' + selectors
} }
return selectors return selectors
} }
export const init = (ruleset) => { export const init = (extraRuleset, palette) => {
const rootName = root.name const rootName = root.name
const rules = [] const rules = []
const rulesByComponent = {} const rulesByComponent = {}
const ruleset = [
...Object.values(components).map(c => c.defaultRules || []).reduce((acc, arr) => [...acc, ...arr], []),
...extraRuleset
]
const addRule = (rule) => { const addRule = (rule) => {
rules.push(rule) rules.push(rule)
rulesByComponent[rule.component] = rulesByComponent[rule.component] || [] rulesByComponent[rule.component] = rulesByComponent[rule.component] || []
rulesByComponent[rule.component].push(rule) rulesByComponent[rule.component].push(rule)
} }
const findRules = (combination) => rule => { const findRules = (combination, parent) => rule => {
// inexact search
const doesCombinationMatch = () => {
if (combination.component !== rule.component) return false if (combination.component !== rule.component) return false
if (Object.prototype.hasOwnProperty.call(rule, 'variant')) { if (Object.prototype.hasOwnProperty.call(rule, 'variant')) {
if (combination.variant !== rule.variant) return false if (combination.variant !== rule.variant) return false
@ -90,13 +108,45 @@ export const init = (ruleset) => {
return true return true
} }
} }
const combinationMatches = doesCombinationMatch()
if (!parent || !combinationMatches) return combinationMatches
// exact search
// unroll parents into array
const unroll = (item) => {
const out = []
let currentParent = item.parent
while (currentParent) {
const { parent: newParent, ...rest } = currentParent
out.push(rest)
currentParent = newParent
}
return out
}
const { parent: _, ...rest } = parent
const pathSearch = [rest, ...unroll(parent)]
const pathRule = unroll(rule)
if (pathSearch.length !== pathRule.length) return false
const pathsMatch = pathSearch.every((searchRule, i) => {
const existingRule = pathRule[i]
if (existingRule.component !== searchRule.component) return false
if (existingRule.variant !== searchRule.variant) return false
const existingRuleStatesSet = new Set(['normal', ...(existingRule.state || [])])
const searchStatesSet = new Set(['normal', ...(searchRule.state || [])])
const setsAreEqual = existingRule.state.every(state => searchStatesSet.has(state)) &&
[...searchStatesSet].every(state => existingRuleStatesSet.has(state))
return setsAreEqual
})
return pathsMatch
}
const findLowerLevelRule = (parent, filter = () => true) => { const findLowerLevelRule = (parent, filter = () => true) => {
let lowerLevelComponent = null let lowerLevelComponent = null
let currentParent = parent let currentParent = parent
while (currentParent) { while (currentParent) {
const rulesParent = ruleset.filter(findRules(currentParent, true)) const rulesParent = ruleset.filter(findRules(currentParent))
rulesParent > 1 && console.log('OOPS') rulesParent > 1 && console.warn('OOPS')
lowerLevelComponent = rulesParent[rulesParent.length - 1] lowerLevelComponent = rulesParent[rulesParent.length - 1]
currentParent = currentParent.parent currentParent = currentParent.parent
if (lowerLevelComponent && filter(lowerLevelComponent)) currentParent = null if (lowerLevelComponent && filter(lowerLevelComponent)) currentParent = null
@ -104,6 +154,35 @@ export const init = (ruleset) => {
return filter(lowerLevelComponent) ? lowerLevelComponent : null return filter(lowerLevelComponent) ? lowerLevelComponent : null
} }
const findColor = (color) => {
if (typeof color === 'string' && color.startsWith('--')) {
const name = color.substring(2)
return palette[name]
}
return color
}
const getTextColorAlpha = (rule, lowerRule, value) => {
const opacity = rule.directives.textOpacity
const textColor = convert(findColor(value)).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
}
const opacityMode = rule.directives.textOpacityMode
switch (opacityMode) {
case 'fake':
return convert(alphaBlend(textColor, opacity, backgroundColor)).hex
case 'mixrgb':
return convert(mixrgb(backgroundColor, textColor)).hex
default:
return rgba2css({ a: opacity, ...textColor })
}
}
const processInnerComponent = (component, parent) => { const processInnerComponent = (component, parent) => {
const { const {
validInnerComponents = [], validInnerComponents = [],
@ -124,79 +203,156 @@ export const init = (ruleset) => {
const VIRTUAL_COMPONENTS = new Set(['Text', 'Link', 'Icon']) const VIRTUAL_COMPONENTS = new Set(['Text', 'Link', 'Icon'])
stateVariantCombination.forEach(combination => { stateVariantCombination.forEach(combination => {
const existingRules = ruleset.filter(findRules({ component: component.name, ...combination })) let needRuleAdd = false
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)) { if (VIRTUAL_COMPONENTS.has(component.name)) {
const selector = component.name + ruleToSelector({ component: component.name, ...combination }) const selector = component.name + ruleToSelector({ component: component.name, ...combination })
const virtualName = [
'--',
component.name.toLowerCase(),
combination.variant === 'normal'
? ''
: combination.variant[0].toUpperCase() + combination.variant.slice(1).toLowerCase(),
...combination.state.filter(x => x !== 'normal').toSorted().map(state => state[0].toUpperCase() + state.slice(1).toLowerCase())
].join('')
const lowerLevel = findLowerLevelRule(parent, (r) => { const lowerLevel = findLowerLevelRule(parent, (r) => {
if (components[r.component].validInnerComponents.indexOf(component.name) < 0) return false if (components[r.component].validInnerComponents.indexOf(component.name) < 0) return false
if (r.cache?.background === undefined) return false if (r.cache.background === undefined) return false
if (r.cache.textDefined) { if (r.cache.textDefined) {
return !r.cache.textDefined[selector] return !r.cache.textDefined[selector]
} }
return true return true
}) })
if (!lowerLevel) return if (!lowerLevel) return
let inheritedTextColorRule
const inheritedTextColorRules = findLowerLevelRule(parent, (r) => {
return r.cache?.textDefined?.[selector]
})
if (!inheritedTextColorRule) {
const generalTextColorRules = ruleset.filter(findRules({ component: component.name, ...combination }, null, true))
inheritedTextColorRule = generalTextColorRules[generalTextColorRules.length - 1]
} else {
inheritedTextColorRule = inheritedTextColorRules[inheritedTextColorRules.length - 1]
}
let inheritedTextColor
let inheritedTextOpacity = {}
if (inheritedTextColorRule) {
inheritedTextColor = findColor(inheritedTextColorRule.directives.textColor)
// also inherit opacity settings
const { textOpacity, textOpacityMode } = inheritedTextColorRule.directives
inheritedTextOpacity = { textOpacity, textOpacityMode }
} else {
// Emergency fallback
inheritedTextColor = '#000000'
}
const textColor = getTextColor(
convert(lowerLevel.cache.background).rgb,
convert(inheritedTextColor).rgb,
component.name === 'Link' // make it configurable?
)
lowerLevel.cache.textDefined = lowerLevel.cache.textDefined || {} lowerLevel.cache.textDefined = lowerLevel.cache.textDefined || {}
lowerLevel.cache.textDefined[selector] = true lowerLevel.cache.textDefined[selector] = textColor
lowerLevel.virtualDirectives = lowerLevel.virtualDirectives || {}
lowerLevel.virtualDirectives[virtualName] = getTextColorAlpha(inheritedTextColorRule, lowerLevel, textColor)
const directives = {
textColor,
...inheritedTextOpacity
}
// Debug: lets you see what it think background color should be
directives.background = convert(lowerLevel.cache.background).hex
addRule({ addRule({
parent, parent,
virtual: true,
component: component.name, component: component.name,
...combination, ...combination,
directives: { cache: { background: lowerLevel.cache.background },
// TODO: DEFAULT TEXT COLOR directives
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
}
}) })
} else {
const existingGlobalRules = ruleset.filter(findRules({ component: component.name, ...combination }, null))
const existingRules = ruleset.filter(findRules({ component: component.name, ...combination }, parent))
// Global (general) rules
if (existingGlobalRules.length !== 0) {
const lastRule = existingGlobalRules[existingGlobalRules.length - 1]
const { directives } = lastRule
lastRule.cache = lastRule.cache || {}
if (directives.background) {
const rgb = convert(findColor(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.background = blend
needRuleAdd = true
} }
} }
if (needRuleAdd) {
addRule(lastRule)
}
}
if (existingRules.length !== 0) {
console.warn('MORE EXISTING RULES', existingRules)
}
}
innerComponents.forEach(innerComponent => processInnerComponent(innerComponent, { parent, component: name, ...combination })) innerComponents.forEach(innerComponent => processInnerComponent(innerComponent, { parent, component: name, ...combination }))
}) })
} }
processInnerComponent(components[rootName]) processInnerComponent(components[rootName])
// 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 { return {
raw: rules, raw: rules,
css: rules.map(rule => { css: rules.map(rule => {
const header = ruleToSelector(rule) + ' {' if (rule.virtual) return ''
let selector = ruleToSelector(rule).replace(/\/\*.*\*\//g, '')
if (!selector) {
selector = 'body'
}
const header = selector + ' {'
const footer = '}' const footer = '}'
const virtualDirectives = Object.entries(rule.virtualDirectives || {}).map(([k, v]) => {
return ' ' + k + ': ' + v
}).join(';\n')
const directives = Object.entries(rule.directives).map(([k, v]) => { const directives = Object.entries(rule.directives).map(([k, v]) => {
switch (k) { switch (k) {
case 'background': return 'background-color: ' + rgba2css({ ...convert(v).rgb, a: rule.directives.opacity ?? 1 }) case 'background': {
case 'textColor': return 'color: ' + rgba2css({ ...convert(v).rgb, a: rule.directives.opacity ?? 1 }) return 'background-color: ' + rgba2css({ ...convert(findColor(v)).rgb, a: rule.directives.opacity ?? 1 })
}
case 'textColor': {
return 'color: ' + v
}
default: return '' default: return ''
} }
}).filter(x => x).map(x => ' ' + x).join(';\n') }).filter(x => x).map(x => ' ' + x).join(';\n')
return [header, directives, footer].join('\n')
}) return [
header,
directives + ';',
' color: var(--text);',
'',
virtualDirectives,
footer
].join('\n')
}).filter(x => x)
} }
} }

View File

@ -17,7 +17,7 @@ describe.only('Theme Data 3', () => {
describe('init', () => { describe('init', () => {
it('test simple case', () => { it('test simple case', () => {
const out = init(sampleRules) const out = init(sampleRules, palette)
// console.log(JSON.stringify(out, null, 2)) // console.log(JSON.stringify(out, null, 2))
console.log('\n' + out.css.join('\n') + '\n') console.log('\n' + out.css.join('\n') + '\n')
}) })