pleroma-fe/src/services/theme_data/theme2_to_theme3.js

463 lines
12 KiB
JavaScript
Raw Normal View History

import allKeys from './theme2_keys'
// keys that are meant to be used globally, i.e. what's the rest of the theme is based upon.
export const basePaletteKeys = new Set([
'bg',
'fg',
'text',
'link',
'accent',
'cBlue',
'cRed',
'cGreen',
'cOrange'
])
2024-02-22 12:36:56 +00:00
export const opacityKeys = new Set([
'alert',
'alertPopup',
'bg',
'border',
'btn',
'faint',
'input',
'panel',
'popover',
'profileTint',
'underlay'
])
export const shadowsKeys = new Set([
'panel',
'topBar',
'popup',
'avatar',
'avatarStatus',
'panelHeader',
'button',
'buttonHover',
'buttonPressed',
'input'
])
2024-02-19 23:05:17 +00:00
export const radiiKeys = new Set([
'btn',
'input',
2024-02-21 11:10:11 +00:00
'checkbox',
2024-02-19 23:05:17 +00:00
'panel',
'avatar',
'avatarAlt',
'tooltip',
'attachment',
'chatMessage'
])
// Keys that are not available in editor and never meant to be edited
export const hiddenKeys = new Set([
'profileBg',
'profileTint'
])
export const extendedBasePrefixes = [
'border',
'icon',
'highlight',
'lightText',
'popover',
'panel',
'topBar',
2024-02-21 22:02:24 +00:00
'tab',
'btn',
'input',
'selectedMenu',
'alert',
2024-02-19 23:05:17 +00:00
'alertPopup',
'badge',
'post',
'selectedPost', // wrong nomenclature
'poll',
'chatBg',
2024-02-19 23:05:17 +00:00
'chatMessage'
]
2024-02-19 23:05:17 +00:00
export const nonComponentPrefixes = new Set([
'border',
'icon',
'highlight',
'lightText',
'chatBg'
])
2024-02-19 23:05:17 +00:00
export const extendedBaseKeys = Object.fromEntries(
extendedBasePrefixes.map(prefix => [
prefix,
allKeys.filter(k => {
if (prefix === 'alert') {
return k.startsWith(prefix) && !k.startsWith('alertPopup')
}
return k.startsWith(prefix)
})
])
)
// Keysets that are only really used intermideately, i.e. to generate other colors
export const temporary = new Set([
2024-02-19 23:05:17 +00:00
'',
'highlight'
])
export const temporaryColors = {}
export const convertTheme2To3 = (data) => {
2024-02-21 20:18:56 +00:00
data.colors.accent = data.colors.accent || data.colors.link
data.colors.link = data.colors.link || data.colors.accent
const generateRoot = () => {
const directives = {}
basePaletteKeys.forEach(key => { directives['--' + key] = 'color | ' + data.colors[key] })
return {
component: 'Root',
directives
}
}
2024-02-22 12:36:56 +00:00
const convertOpacity = () => {
const newRules = []
Object.keys(data.opacity).forEach(key => {
if (!opacityKeys.has(key) || data.opacity[key] === undefined) return null
const originalOpacity = data.opacity[key]
const rule = {}
switch (key) {
case 'alert':
rule.component = 'Alert'
break
case 'alertPopup':
rule.component = 'Alert'
rule.parent = { component: 'Popover' }
break
case 'bg':
rule.component = 'Panel'
break
case 'border':
rule.component = 'Border'
break
case 'btn':
rule.component = 'Button'
break
case 'faint':
rule.component = 'Text'
rule.state = ['faint']
break
case 'input':
rule.component = 'Input'
break
case 'panel':
rule.component = 'PanelHeader'
break
case 'popover':
rule.component = 'Popover'
break
case 'profileTint':
return null
case 'underlay':
rule.component = 'Underlay'
break
}
switch (key) {
case 'alert':
case 'alertPopup':
case 'bg':
case 'btn':
case 'input':
case 'panel':
case 'popover':
case 'underlay':
rule.directives = { opacity: originalOpacity }
break
case 'faint':
case 'border':
rule.directives = { textOpacity: originalOpacity }
break
}
newRules.push(rule)
if (rule.component === 'Button') {
newRules.push({ ...rule, component: 'ScrollbarElement' })
newRules.push({ ...rule, component: 'Tab' })
}
})
console.log(newRules)
return newRules
}
2024-02-19 23:05:17 +00:00
const convertRadii = () => {
const newRules = []
2024-02-21 20:18:56 +00:00
Object.keys(data.radii).forEach(key => {
if (!radiiKeys.has(key) || data.radii[key] === undefined) return null
2024-02-19 23:05:17 +00:00
const originalRadius = data.radii[key]
const rule = {}
switch (key) {
case 'btn':
rule.component = 'Button'
break
2024-02-21 22:02:24 +00:00
case 'tab':
rule.component = 'Tab'
break
2024-02-19 23:05:17 +00:00
case 'input':
rule.component = 'Input'
break
2024-02-21 11:10:11 +00:00
case 'checkbox':
rule.component = 'Input'
rule.variant = 'checkbox'
break
2024-02-19 23:05:17 +00:00
case 'panel':
rule.component = 'Panel'
break
case 'avatar':
rule.component = 'Avatar'
break
case 'avatarAlt':
rule.component = 'Avatar'
rule.variant = 'compact'
break
case 'tooltip':
rule.component = 'Popover'
break
case 'attachment':
rule.component = 'Attachment'
break
case 'ChatMessage':
rule.component = 'Button'
break
}
rule.directives = {
roundness: originalRadius
}
newRules.push(rule)
2024-02-21 20:18:56 +00:00
if (rule.component === 'Button') {
newRules.push({ ...rule, component: 'ScrollbarElement' })
2024-02-21 22:02:24 +00:00
newRules.push({ ...rule, component: 'Tab' })
2024-02-21 20:18:56 +00:00
}
2024-02-19 23:05:17 +00:00
})
return newRules
}
const convertShadows = () => {
const newRules = []
2024-02-21 20:18:56 +00:00
Object.keys(data.shadows).forEach(key => {
if (!shadowsKeys.has(key)) return
const originalShadow = data.shadows[key]
const rule = {}
switch (key) {
case 'panel':
rule.component = 'Panel'
break
case 'topBar':
rule.component = 'TopBar'
break
case 'popup':
rule.component = 'Popover'
break
case 'avatar':
rule.component = 'Avatar'
break
case 'avatarStatus':
rule.component = 'Avatar'
rule.parent = { component: 'Post' }
break
case 'panelHeader':
rule.component = 'PanelHeader'
break
case 'button':
rule.component = 'Button'
break
case 'buttonHover':
rule.component = 'Button'
rule.state = ['hover']
break
case 'buttonPressed':
rule.component = 'Button'
rule.state = ['pressed']
break
case 'input':
rule.component = 'Input'
break
}
rule.directives = {
shadow: originalShadow
}
newRules.push(rule)
2024-02-21 23:10:24 +00:00
if (key === 'topBar') {
newRules.push({ ...rule, component: 'PanelHeader', parent: { component: 'MobileDrawer' } })
}
if (key === 'avatarStatus') {
newRules.push({ ...rule, parent: { component: 'Notification' } })
}
if (key === 'buttonPressed') {
newRules.push({ ...rule, state: ['toggled'] })
}
2024-02-21 20:18:56 +00:00
if (rule.component === 'Button') {
newRules.push({ ...rule, component: 'ScrollbarElement' })
2024-02-21 22:02:24 +00:00
newRules.push({ ...rule, component: 'Tab' })
2024-02-21 20:18:56 +00:00
}
})
return newRules
}
2024-02-19 23:05:17 +00:00
const extendedRules = Object.entries(extendedBaseKeys).map(([prefix, keys]) => {
if (nonComponentPrefixes.has(prefix)) return null
const rule = {}
if (prefix === 'alertPopup') {
rule.component = 'Alert'
rule.parent = { component: 'Popover' }
} else if (prefix === 'selectedPost') {
rule.component = 'Post'
rule.state = ['selected']
} else if (prefix === 'selectedMenu') {
rule.component = 'MenuItem'
rule.state = ['hover']
} else if (prefix === 'chatMessageIncoming') {
rule.component = 'ChatMessage'
} else if (prefix === 'chatMessageOutgoing') {
rule.component = 'ChatMessage'
rule.variant = 'outgoing'
} else if (prefix === 'panel') {
rule.component = 'PanelHeader'
} else if (prefix === 'topBar') {
2024-02-19 23:05:17 +00:00
rule.component = 'TopBar'
} else if (prefix === 'chatMessage') {
rule.component = 'ChatMessage'
} else if (prefix === 'poll') {
rule.component = 'PollGraph'
2024-02-21 20:18:56 +00:00
} else if (prefix === 'btn') {
rule.component = 'Button'
2024-02-19 23:05:17 +00:00
} else {
rule.component = prefix[0].toUpperCase() + prefix.slice(1).toLowerCase()
}
return keys.map((key) => {
2024-02-21 20:18:56 +00:00
if (!data.colors[key]) return null
2024-02-19 23:05:17 +00:00
const leftoverKey = key.replace(prefix, '')
const parts = (leftoverKey || 'Bg').match(/[A-Z][a-z]*/g)
const last = parts.slice(-1)[0]
let newRule = { directives: {} }
let variantArray = []
switch (last) {
case 'Text':
case 'Faint': // typo
case 'Link':
case 'Icon':
case 'Greentext':
case 'Cyantext':
case 'Border':
newRule.parent = rule
newRule.directives.textColor = data.colors[key]
newRule.directives.textAuto = 'no-auto'
2024-02-19 23:05:17 +00:00
variantArray = parts.slice(0, -1)
break
default:
newRule = { ...rule, directives: {} }
newRule.directives.background = data.colors[key]
variantArray = parts
break
}
if (last === 'Text' || last === 'Link') {
const secondLast = parts.slice(-2)[0]
if (secondLast === 'Light') {
return null // unsupported
} else if (secondLast === 'Faint') {
newRule.state = ['faint']
variantArray = parts.slice(0, -2)
}
}
switch (last) {
case 'Text':
case 'Link':
case 'Icon':
case 'Border':
newRule.component = last
break
case 'Greentext':
case 'Cyantext':
newRule.component = 'FunText'
newRule.variant = last.toLowerCase()
break
case 'Faint':
newRule.component = 'Text'
newRule.state = ['faint']
break
}
variantArray = variantArray.filter(x => x !== 'Bg')
if (last === 'Link' && prefix === 'selectedPost') {
// selectedPost has typo - duplicate 'Post'
variantArray = variantArray.filter(x => x !== 'Post')
}
if (prefix === 'popover' && variantArray[0] === 'Post') {
newRule.component = 'Post'
newRule.parent = { component: 'Popover' }
variantArray = variantArray.filter(x => x !== 'Post')
}
if (prefix === 'selectedMenu' && variantArray[0] === 'Popover') {
newRule.parent = { component: 'Popover' }
variantArray = variantArray.filter(x => x !== 'Popover')
}
switch (prefix) {
case 'btn':
case 'input':
case 'alert': {
const hasPanel = variantArray.find(x => x === 'Panel')
if (hasPanel) {
rule.parent = { component: 'PanelHeader' }
variantArray = variantArray.filter(x => x !== 'Panel')
}
const hasTop = variantArray.find(x => x === 'Top') // TopBar
if (hasTop) {
rule.parent = { component: 'TopBar' }
variantArray = variantArray.filter(x => x !== 'Top' && x !== 'Bar')
}
break
}
}
if (variantArray.length > 0) {
if (prefix === 'btn') {
newRule.state = variantArray.map(x => x.toLowerCase())
} else {
newRule.variant = variantArray[0].toLowerCase()
}
}
2024-02-21 20:18:56 +00:00
2024-02-21 23:10:24 +00:00
if (newRule.component === 'Panel') {
return [newRule, { ...newRule, component: 'MobileDrawer' }]
} else if (newRule.component === 'Button') {
2024-02-21 22:02:24 +00:00
return [newRule, { ...newRule, component: 'Tab' }, { ...newRule, component: 'ScrollbarElement' }]
2024-02-21 23:10:24 +00:00
} else if (newRule.component === 'TopBar') {
return [newRule, { ...newRule, parent: { component: 'MobileDrawer' }, component: 'PanelHeader' }]
2024-02-21 20:18:56 +00:00
} else {
return [newRule]
}
2024-02-19 23:05:17 +00:00
})
})
2024-02-21 20:18:56 +00:00
const flatExtRules = extendedRules.filter(x => x).reduce((acc, x) => [...acc, ...x], []).filter(x => x).reduce((acc, x) => [...acc, ...x], [])
2024-02-19 23:05:17 +00:00
2024-02-22 12:36:56 +00:00
return [generateRoot(), ...convertShadows(), ...convertRadii(), ...convertOpacity(), ...flatExtRules]
}