akkoma-fe/src/services/theme_data/pleromafe.js

710 lines
16 KiB
JavaScript

import { invertLightness, brightness } from 'chromatism'
import { alphaBlend, mixrgb } from '../color_convert/color_convert.js'
/* This is a definition of all layer combinations
* each key is a topmost layer, each value represents layer underneath
* this is essentially a simplified tree
*/
export const LAYERS = {
undelay: null, // root
topBar: null, // no transparency support
badge: null, // no transparency support
profileTint: null, // doesn't matter
fg: null,
bg: 'underlay',
highlight: 'bg',
panel: 'bg',
popover: 'bg',
selectedMenu: 'popover',
btn: 'bg',
btnPanel: 'panel',
btnTopBar: 'topBar',
input: 'bg',
inputPanel: 'panel',
inputTopBar: 'topBar',
alert: 'bg',
alertPanel: 'panel',
poll: 'bg'
}
/* By default opacity slots have 1 as default opacity
* this allows redefining it to something else
*/
export const DEFAULT_OPACITY = {
profileTint: 0.5,
alert: 0.5,
input: 0.5,
faint: 0.5,
underlay: 0.15,
alertPopup: 0.95
}
/** SUBJECT TO CHANGE IN THE FUTURE, this is all beta
* Color and opacity slots definitions. Each key represents a slot.
*
* Short-hands:
* String beginning with `--` - value after dashes treated as sole
* dependency - i.e. `--value` equivalent to { depends: ['value']}
* String beginning with `#` - value would be treated as solid color
* defined in hexadecimal representation (i.e. #FFFFFF) and will be
* used as default. `#FFFFFF` is equivalent to { default: '#FFFFFF'}
*
* Full definition:
* @property {String[]} depends - color slot names this color depends ones.
* cyclic dependencies are supported to some extent but not recommended.
* @property {String} [opacity] - opacity slot used by this color slot.
* opacity is inherited from parents. To break inheritance graph use null
* @property {Number} [priority] - EXPERIMENTAL. used to pre-sort slots so
* that slots with higher priority come earlier
* @property {Function(mod, ...colors)} [color] - function that will be
* used to determine the color. By default it just copies first color in
* dependency list.
* @argument {Number} mod - `1` (light-on-dark) or `-1` (dark-on-light)
* depending on background color (for textColor)/given color.
* @argument {...Object} deps - each argument after mod represents each
* color from `depends` array. All colors take user customizations into
* account and represented by { r, g, b } objects.
* @returns {Object} resulting color, should be in { r, g, b } form
*
* @property {Boolean|String} [textColor] - true to mark color slot as text
* color. This enables automatic text color generation for the slot. Use
* 'preserve' string if you don't want text color to fall back to
* black/white. Use 'bw' to only ever use black or white. This also makes
* following properties required:
* @property {String} [layer] - which layer the text sit on top on - used
* to account for transparency in text color calculation
* layer is inherited from parents. To break inheritance graph use null
* @property {String} [variant] - which color slot is background (same as
* above, used to account for transparency)
*/
export const SLOT_INHERITANCE = {
bg: {
depends: [],
opacity: 'bg',
priority: 1
},
wallpaper: {
depends: ['bg'],
color: (mod, bg) => brightness(-2 * mod, bg).rgb
},
fg: {
depends: [],
priority: 1
},
text: {
depends: [],
layer: 'bg',
opacity: null,
priority: 1
},
underlay: {
default: '#000000',
opacity: 'underlay'
},
link: {
depends: ['accent'],
priority: 1
},
accent: {
depends: ['link'],
priority: 1
},
faint: {
depends: ['text'],
opacity: 'faint'
},
faintLink: {
depends: ['link'],
opacity: 'faint'
},
postFaintLink: {
depends: ['postLink'],
opacity: 'faint'
},
cBlue: '#0000ff',
cRed: '#FF0000',
cGreen: '#00FF00',
cOrange: '#E3FF00',
profileBg: {
depends: ['bg'],
color: (mod, bg) => ({
r: Math.floor(bg.r * 0.53),
g: Math.floor(bg.g * 0.56),
b: Math.floor(bg.b * 0.59)
})
},
profileTint: {
depends: ['bg'],
layer: 'profileTint',
opacity: 'profileTint'
},
highlight: {
depends: ['bg'],
color: (mod, bg) => brightness(5 * mod, bg).rgb
},
highlightLightText: {
depends: ['lightText'],
layer: 'highlight',
textColor: true
},
highlightPostLink: {
depends: ['postLink'],
layer: 'highlight',
textColor: 'preserve'
},
highlightFaintText: {
depends: ['faint'],
layer: 'highlight',
textColor: true
},
highlightFaintLink: {
depends: ['faintLink'],
layer: 'highlight',
textColor: 'preserve'
},
highlightPostFaintLink: {
depends: ['postFaintLink'],
layer: 'highlight',
textColor: 'preserve'
},
highlightText: {
depends: ['text'],
layer: 'highlight',
textColor: true
},
highlightLink: {
depends: ['link'],
layer: 'highlight',
textColor: 'preserve'
},
highlightIcon: {
depends: ['highlight', 'highlightText'],
color: (mod, bg, text) => mixrgb(bg, text)
},
popover: {
depends: ['bg'],
opacity: 'popover'
},
popoverLightText: {
depends: ['lightText'],
layer: 'popover',
textColor: true
},
popoverPostLink: {
depends: ['postLink'],
layer: 'popover',
textColor: 'preserve'
},
popoverFaintText: {
depends: ['faint'],
layer: 'popover',
textColor: true
},
popoverFaintLink: {
depends: ['faintLink'],
layer: 'popover',
textColor: 'preserve'
},
popoverPostFaintLink: {
depends: ['postFaintLink'],
layer: 'popover',
textColor: 'preserve'
},
popoverText: {
depends: ['text'],
layer: 'popover',
textColor: true
},
popoverLink: {
depends: ['link'],
layer: 'popover',
textColor: 'preserve'
},
popoverIcon: {
depends: ['popover', 'popoverText'],
color: (mod, bg, text) => mixrgb(bg, text)
},
selectedPost: '--highlight',
selectedPostFaintText: {
depends: ['highlightFaintText'],
layer: 'highlight',
variant: 'selectedPost',
textColor: true
},
selectedPostLightText: {
depends: ['highlightLightText'],
layer: 'highlight',
variant: 'selectedPost',
textColor: true
},
selectedPostPostLink: {
depends: ['highlightPostLink'],
layer: 'highlight',
variant: 'selectedPost',
textColor: 'preserve'
},
selectedPostFaintLink: {
depends: ['highlightFaintLink'],
layer: 'highlight',
variant: 'selectedPost',
textColor: 'preserve'
},
selectedPostText: {
depends: ['highlightText'],
layer: 'highlight',
variant: 'selectedPost',
textColor: true
},
selectedPostLink: {
depends: ['highlightLink'],
layer: 'highlight',
variant: 'selectedPost',
textColor: 'preserve'
},
selectedPostIcon: {
depends: ['selectedPost', 'selectedPostText'],
color: (mod, bg, text) => mixrgb(bg, text)
},
selectedMenu: {
depends: ['bg'],
color: (mod, bg) => brightness(5 * mod, bg).rgb
},
selectedMenuLightText: {
depends: ['highlightLightText'],
layer: 'selectedMenu',
variant: 'selectedMenu',
textColor: true
},
selectedMenuFaintText: {
depends: ['highlightFaintText'],
layer: 'selectedMenu',
variant: 'selectedMenu',
textColor: true
},
selectedMenuFaintLink: {
depends: ['highlightFaintLink'],
layer: 'selectedMenu',
variant: 'selectedMenu',
textColor: 'preserve'
},
selectedMenuText: {
depends: ['highlightText'],
layer: 'selectedMenu',
variant: 'selectedMenu',
textColor: true
},
selectedMenuLink: {
depends: ['highlightLink'],
layer: 'selectedMenu',
variant: 'selectedMenu',
textColor: 'preserve'
},
selectedMenuIcon: {
depends: ['selectedMenu', 'selectedMenuText'],
color: (mod, bg, text) => mixrgb(bg, text)
},
selectedMenuPopover: {
depends: ['popover'],
color: (mod, bg) => brightness(5 * mod, bg).rgb
},
selectedMenuPopoverLightText: {
depends: ['selectedMenuLightText'],
layer: 'selectedMenuPopover',
variant: 'selectedMenuPopover',
textColor: true
},
selectedMenuPopoverFaintText: {
depends: ['selectedMenuFaintText'],
layer: 'selectedMenuPopover',
variant: 'selectedMenuPopover',
textColor: true
},
selectedMenuPopoverFaintLink: {
depends: ['selectedMenuFaintLink'],
layer: 'selectedMenuPopover',
variant: 'selectedMenuPopover',
textColor: 'preserve'
},
selectedMenuPopoverText: {
depends: ['selectedMenuText'],
layer: 'selectedMenuPopover',
variant: 'selectedMenuPopover',
textColor: true
},
selectedMenuPopoverLink: {
depends: ['selectedMenuLink'],
layer: 'selectedMenuPopover',
variant: 'selectedMenuPopover',
textColor: 'preserve'
},
selectedMenuPopoverIcon: {
depends: ['selectedMenuPopover', 'selectedMenuText'],
color: (mod, bg, text) => mixrgb(bg, text)
},
lightText: {
depends: ['text'],
layer: 'bg',
textColor: 'preserve',
color: (mod, text) => brightness(20 * mod, text).rgb
},
postLink: {
depends: ['link'],
layer: 'bg',
textColor: 'preserve'
},
postGreentext: {
depends: ['cGreen'],
layer: 'bg',
textColor: 'preserve'
},
postCyantext: {
depends: ['cBlue'],
layer: 'bg',
textColor: 'preserve'
},
border: {
depends: ['fg'],
opacity: 'border',
color: (mod, fg) => brightness(2 * mod, fg).rgb
},
poll: {
depends: ['accent', 'bg'],
copacity: 'poll',
color: (mod, accent, bg) => alphaBlend(accent, 0.4, bg)
},
pollText: {
depends: ['text'],
layer: 'poll',
textColor: true
},
icon: {
depends: ['bg', 'text'],
inheritsOpacity: false,
color: (mod, bg, text) => mixrgb(bg, text)
},
// Foreground
fgText: {
depends: ['text'],
layer: 'fg',
textColor: true
},
fgLink: {
depends: ['link'],
layer: 'fg',
textColor: 'preserve'
},
// Panel header
panel: {
depends: ['fg'],
opacity: 'panel'
},
panelText: {
depends: ['text'],
layer: 'panel',
textColor: true
},
panelFaint: {
depends: ['fgText'],
layer: 'panel',
opacity: 'faint',
textColor: true
},
panelLink: {
depends: ['fgLink'],
layer: 'panel',
textColor: 'preserve'
},
// Top bar
topBar: '--fg',
topBarText: {
depends: ['fgText'],
layer: 'topBar',
textColor: true
},
topBarLink: {
depends: ['fgLink'],
layer: 'topBar',
textColor: 'preserve'
},
// Tabs
tab: {
depends: ['btn']
},
tabText: {
depends: ['btnText'],
layer: 'btn',
textColor: true
},
tabActiveText: {
depends: ['text'],
layer: 'bg',
textColor: true
},
// Buttons
btn: {
depends: ['fg'],
variant: 'btn',
opacity: 'btn'
},
btnText: {
depends: ['fgText'],
layer: 'btn',
textColor: true
},
btnPanelText: {
depends: ['btnText'],
layer: 'btnPanel',
variant: 'btn',
textColor: true
},
btnTopBarText: {
depends: ['btnText'],
layer: 'btnTopBar',
variant: 'btn',
textColor: true
},
// Buttons: pressed
btnPressed: {
depends: ['btn'],
layer: 'btn'
},
btnPressedText: {
depends: ['btnText'],
layer: 'btn',
variant: 'btnPressed',
textColor: true
},
btnPressedPanel: {
depends: ['btnPressed'],
layer: 'btn'
},
btnPressedPanelText: {
depends: ['btnPanelText'],
layer: 'btnPanel',
variant: 'btnPressed',
textColor: true
},
btnPressedTopBar: {
depends: ['btnPressed'],
layer: 'btn'
},
btnPressedTopBarText: {
depends: ['btnTopBarText'],
layer: 'btnTopBar',
variant: 'btnPressed',
textColor: true
},
// Buttons: toggled
btnToggled: {
depends: ['btn'],
layer: 'btn',
color: (mod, btn) => brightness(mod * 20, btn).rgb
},
btnToggledText: {
depends: ['btnText'],
layer: 'btn',
variant: 'btnToggled',
textColor: true
},
btnToggledPanelText: {
depends: ['btnPanelText'],
layer: 'btnPanel',
variant: 'btnToggled',
textColor: true
},
btnToggledTopBarText: {
depends: ['btnTopBarText'],
layer: 'btnTopBar',
variant: 'btnToggled',
textColor: true
},
// Buttons: disabled
btnDisabled: {
depends: ['btn', 'bg'],
color: (mod, btn, bg) => alphaBlend(btn, 0.25, bg)
},
btnDisabledText: {
depends: ['btnText', 'btnDisabled'],
layer: 'btn',
variant: 'btnDisabled',
color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
},
btnDisabledPanelText: {
depends: ['btnPanelText', 'btnDisabled'],
layer: 'btnPanel',
variant: 'btnDisabled',
color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
},
btnDisabledTopBarText: {
depends: ['btnTopBarText', 'btnDisabled'],
layer: 'btnTopBar',
variant: 'btnDisabled',
color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
},
// Input fields
input: {
depends: ['fg'],
opacity: 'input'
},
inputText: {
depends: ['text'],
layer: 'input',
textColor: true
},
inputPanelText: {
depends: ['panelText'],
layer: 'inputPanel',
variant: 'input',
textColor: true
},
inputTopbarText: {
depends: ['topBarText'],
layer: 'inputTopBar',
variant: 'input',
textColor: true
},
alertError: {
depends: ['cRed'],
opacity: 'alert'
},
alertErrorText: {
depends: ['text'],
layer: 'alert',
variant: 'alertError',
textColor: true
},
alertErrorPanelText: {
depends: ['panelText'],
layer: 'alertPanel',
variant: 'alertError',
textColor: true
},
alertWarning: {
depends: ['cOrange'],
opacity: 'alert'
},
alertWarningText: {
depends: ['text'],
layer: 'alert',
variant: 'alertWarning',
textColor: true
},
alertWarningPanelText: {
depends: ['panelText'],
layer: 'alertPanel',
variant: 'alertWarning',
textColor: true
},
alertSuccess: {
depends: ['cGreen'],
opacity: 'alert'
},
alertSuccessText: {
depends: ['text'],
layer: 'alert',
variant: 'alertSuccess',
textColor: true
},
alertSuccessPanelText: {
depends: ['panelText'],
layer: 'alertPanel',
variant: 'alertSuccess',
textColor: true
},
alertNeutral: {
depends: ['text'],
opacity: 'alert'
},
alertNeutralText: {
depends: ['text'],
layer: 'alert',
variant: 'alertNeutral',
color: (mod, text) => invertLightness(text).rgb,
textColor: true
},
alertNeutralPanelText: {
depends: ['panelText'],
layer: 'alertPanel',
variant: 'alertNeutral',
textColor: true
},
alertPopupError: {
depends: ['alertError'],
opacity: 'alertPopup'
},
alertPopupErrorText: {
depends: ['alertErrorText'],
layer: 'popover',
variant: 'alertPopupError',
textColor: true
},
alertPopupWarning: {
depends: ['alertWarning'],
opacity: 'alertPopup'
},
alertPopupWarningText: {
depends: ['alertWarningText'],
layer: 'popover',
variant: 'alertPopupWarning',
textColor: true
},
alertPopupSuccess: {
depends: ['alertSuccess'],
opacity: 'alertPopup'
},
alertPopupSuccessText: {
depends: ['alertSuccessText'],
layer: 'popover',
variant: 'alertPopupSuccess',
textColor: true
},
alertPopupNeutral: {
depends: ['alertNeutral'],
opacity: 'alertPopup'
},
alertPopupNeutralText: {
depends: ['alertNeutralText'],
layer: 'popover',
variant: 'alertPopupNeutral',
textColor: true
},
badgeNotification: '--cRed',
badgeNotificationText: {
depends: ['text', 'badgeNotification'],
layer: 'badge',
variant: 'badgeNotification',
textColor: 'bw'
}
}