commit: a6863248bbffac9d8efddb00903ec631113df33f
parent da2c016ab42f2cfbc8926e816fb842ce2293d1a0
Author: Henry Jameson <me@hjkos.com>
Date: Sun, 6 Oct 2024 15:00:52 +0300
variables + consistency in code
Diffstat:
2 files changed, 220 insertions(+), 180 deletions(-)
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.js b/src/components/settings_modal/tabs/style_tab/style_tab.js
@@ -60,7 +60,7 @@ export default {
ContrastRatio
},
setup () {
- // ### Meta stuff
+ // ## Meta stuff
const name = ref('')
const author = ref('')
const license = ref('')
@@ -77,7 +77,7 @@ export default {
].join('\n')
})
- // ### Palette stuff
+ // ## Palette stuff
const palettes = reactive([
{
name: 'light',
@@ -105,29 +105,15 @@ export default {
cOrange: '#ffa500'
}
])
-
- const palettesOut = computed(() => {
- return palettes.map(({ name, ...palette }) => {
- const entries = Object
- .entries(palette)
- .map(([slot, data]) => ` ${slot}: ${data};`)
- .join('\n')
-
- return `@palette.${name} {\n${entries}\n}`
- }).join('\n\n')
- })
-
- const editedPalette = ref(0)
- const palette = computed({
+ const selectedPaletteId = ref(0)
+ const selectedPalette = computed({
get () {
- console.log(palettes, editedPalette.value)
- return palettes[editedPalette.value]
+ return palettes[selectedPaletteId.value]
},
set (newPalette) {
- palettes[editedPalette.value] = newPalette
+ palettes[selectedPaletteId.value] = newPalette
}
})
-
const getNewPalette = () => ({
name: 'new palette',
bg: '#121a24',
@@ -141,11 +127,21 @@ export default {
cOrange: '#ffa500'
})
- // ### Initialization stuff
+ const palettesOut = computed(() => {
+ return palettes.map(({ name, ...palette }) => {
+ const entries = Object
+ .entries(palette)
+ .map(([slot, data]) => ` ${slot}: ${data};`)
+ .join('\n')
+
+ return `@palette.${name} {\n${entries}\n}`
+ }).join('\n\n')
+ })
+
+ // ## Components stuff
// Getting existing components
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
const componentKeysAll = componentsContext.keys()
-
const componentsMap = new Map(
componentKeysAll
.map(
@@ -154,23 +150,23 @@ export default {
)
const componentKeys = [...componentsMap.keys()]
- // Initializing selected component and its computed descendants
+ // selection basis
const selectedComponentKey = ref(componentsMap.keys().next().value)
const selectedComponent = computed(() => componentsMap.get(selectedComponentKey.value))
const selectedComponentName = computed(() => selectedComponent.value.name)
-
- const selectedVariant = ref('normal')
- const selectedComponentVariantsAll = computed(() => {
+ const selectedComponentVariants = computed(() => {
return Object.keys({ normal: null, ...(selectedComponent.value.variants || {}) })
})
-
- const selectedState = reactive(new Set())
const selectedComponentStatesAll = computed(() => {
return Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
})
const selectedComponentStates = computed(() => {
return selectedComponentStatesAll.value.filter(x => x !== 'normal')
})
+
+ // selection
+ const selectedVariant = ref('normal')
+ const selectedState = reactive(new Set())
const updateSelectedStates = (state, v) => {
if (v) {
selectedState.add(state)
@@ -179,56 +175,6 @@ export default {
}
}
- // ### Preview stuff
- const editorHintStyle = computed(() => {
- const editorHint = selectedComponent.value.editor
- const styles = []
- if (editorHint && Object.keys(editorHint).length > 0) {
- if (editorHint.aspect != null) {
- styles.push(`aspect-ratio: ${editorHint.aspect} !important;`)
- }
- if (editorHint.border != null) {
- styles.push(`border-width: ${editorHint.border}px !important;`)
- }
- }
- return styles.join('; ')
- })
-
- // Apart from "hover" we can't really show how component looks like in
- // certain states, so we have to fake them.
- const simulatePseudoSelectors = css => css
- .replace(selectedComponent.value.selector, '.ComponentPreview .preview-block')
- .replace(':active', '.preview-active')
- .replace(':hover', '.preview-hover')
- .replace(':active', '.preview-active')
- .replace(':focus', '.preview-focus')
- .replace(':focus-within', '.preview-focus-within')
- .replace(':disabled', '.preview-disabled')
-
- const previewRules = reactive([])
- const previewClass = computed(() => {
- const selectors = []
- if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
- selectors.push(selectedComponent.value.variants[selectedVariant.value])
- }
- if (selectedState.size > 0) {
- selectedState.forEach(state => {
- const original = selectedComponent.value.states[state]
- selectors.push(simulatePseudoSelectors(original))
- })
- }
- return selectors.map(x => x.substring(1)).join('')
- })
- const previewCss = computed(() => {
- try {
- const scoped = getCssRules(previewRules).map(simulatePseudoSelectors)
- return scoped.join('\n')
- } catch (e) {
- console.error('Invalid ruleset', e)
- return null
- }
- })
-
// ### Rules stuff aka meat and potatoes
// The native structure of separate rules and the child -> parent
// relation isn't very convenient for editor, we replace the array
@@ -334,21 +280,58 @@ export default {
// All the editable stuff for the component
const editedBackgroundColor = getEditedElement(null, 'background')
+ const isBackgroundColorPresent = isElementPresent(null, 'background', '#FFFFFF')
const editedOpacity = getEditedElement(null, 'opacity')
+ const isOpacityPresent = isElementPresent(null, 'opacity', 1)
const editedTextColor = getEditedElement('Text', 'textColor')
+ const isTextColorPresent = isElementPresent('Text', 'textColor', '#000000')
const editedTextAuto = getEditedElement('Text', 'textAuto')
+ const isTextAutoPresent = isElementPresent('Text', 'textAuto', '#000000')
const editedLinkColor = getEditedElement('Link', 'textColor')
+ const isLinkColorPresent = isElementPresent('Link', 'textColor', '#000080')
const editedIconColor = getEditedElement('Icon', 'textColor')
- const editedShadow = getEditedElement(null, 'shadow')
+ const isIconColorPresent = isElementPresent('Icon', 'textColor', '#909090')
+ // TODO this is VERY primitive right now, need to make it
+ // support variables, fallbacks etc.
+ const getContrast = (bg, text) => {
+ try {
+ const bgRgb = hex2rgb(bg)
+ const textRgb = hex2rgb(text)
+
+ const ratio = getContrastRatio(bgRgb, textRgb)
+ return {
+ // TODO this ideally should be part of <ContractRatio />
+ ratio,
+ text: ratio.toPrecision(3) + ':1',
+ // AA level, AAA level
+ aa: ratio >= 4.5,
+ aaa: ratio >= 7,
+ // same but for 18pt+ texts
+ laa: ratio >= 3,
+ laaa: ratio >= 4.5
+ }
+ } catch (e) {
+ console.warn('Failure computing contrast', e)
+ return { error: e }
+ }
+ }
// Shadow is partially edited outside the ShadowControl
// for better space utilization
+ const editedShadow = getEditedElement(null, 'shadow')
const editedSubShadowId = ref(null)
const editedSubShadow = computed(() => {
if (editedShadow.value == null || editedSubShadowId.value == null) return null
return editedShadow.value[editedSubShadowId.value]
})
-
+ const isShadowPresent = isElementPresent(null, 'shadow', [])
+ const onSubShadow = (id) => {
+ if (id != null) {
+ editedSubShadowId.value = id
+ } else {
+ editedSubShadow.value = null
+ }
+ }
const updateSubShadow = (axis, value) => {
if (!editedSubShadow.value || editedSubShadowId.value == null) return
const newEditedShadow = [...editedShadow.value]
@@ -360,68 +343,61 @@ export default {
editedShadow.value = newEditedShadow
}
-
- const onSubShadow = (id) => {
- if (id != null) {
- editedSubShadowId.value = id
- } else {
- editedSubShadow.value = null
- }
+ const isShadowTabOpen = ref(false)
+ const onTabSwitch = (tab) => {
+ isShadowTabOpen.value = tab === 'shadow'
}
- // Whether specific directives present in the edited rule or not
- // Somewhat serves double-duty as it creates/removes the directive
- // when set
- const isBackgroundColorPresent = isElementPresent(null, 'background', '#FFFFFF')
- const isOpacityPresent = isElementPresent(null, 'opacity', 1)
- const isTextColorPresent = isElementPresent('Text', 'textColor', '#000000')
- const isTextAutoPresent = isElementPresent('Text', 'textAuto', '#000000')
- const isLinkColorPresent = isElementPresent('Link', 'textColor', '#000080')
- const isIconColorPresent = isElementPresent('Icon', 'textColor', '#909090')
- const isShadowPresent = isElementPresent(null, 'shadow', [])
-
- const editorFriendlyToOriginal = computed(() => {
- const resultRules = []
-
- const convert = (component, data = {}, parent) => {
- const variants = Object.entries(data || {})
-
- variants.forEach(([variant, variantData]) => {
- const states = Object.entries(variantData)
-
- states.forEach(([jointState, stateData]) => {
- const state = jointState.split(/:/g)
- const result = {
- component,
- variant,
- state,
- directives: stateData.directives || {}
- }
-
- if (parent) {
- result.parent = {
- component: parent
- }
- }
-
- resultRules.push(result)
-
- // Currently we only support single depth for simplicity's sake
- if (!parent) {
- Object.entries(stateData._children || {}).forEach(([cName, child]) => convert(cName, child, component))
- }
- })
+ // component preview
+ const editorHintStyle = computed(() => {
+ const editorHint = selectedComponent.value.editor
+ const styles = []
+ if (editorHint && Object.keys(editorHint).length > 0) {
+ if (editorHint.aspect != null) {
+ styles.push(`aspect-ratio: ${editorHint.aspect} !important;`)
+ }
+ if (editorHint.border != null) {
+ styles.push(`border-width: ${editorHint.border}px !important;`)
+ }
+ }
+ return styles.join('; ')
+ })
+ // Apart from "hover" we can't really show how component looks like in
+ // certain states, so we have to fake them.
+ const simulatePseudoSelectors = css => css
+ .replace(selectedComponent.value.selector, '.ComponentPreview .preview-block')
+ .replace(':active', '.preview-active')
+ .replace(':hover', '.preview-hover')
+ .replace(':active', '.preview-active')
+ .replace(':focus', '.preview-focus')
+ .replace(':focus-within', '.preview-focus-within')
+ .replace(':disabled', '.preview-disabled')
+ const previewClass = computed(() => {
+ const selectors = []
+ if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
+ selectors.push(selectedComponent.value.variants[selectedVariant.value])
+ }
+ if (selectedState.size > 0) {
+ selectedState.forEach(state => {
+ const original = selectedComponent.value.states[state]
+ selectors.push(simulatePseudoSelectors(original))
})
}
-
- convert(selectedComponentName.value, allEditedRules[selectedComponentName.value])
-
- return resultRules
+ return selectors.map(x => x.substring(1)).join('')
+ })
+ const previewRules = reactive([])
+ const previewCss = computed(() => {
+ try {
+ const scoped = getCssRules(previewRules).map(simulatePseudoSelectors)
+ return scoped.join('\n')
+ } catch (e) {
+ console.error('Invalid ruleset', e)
+ return null
+ }
})
-
const updatePreview = () => {
try {
- const { name, ...paletteData } = palette.value
+ const { name, ...paletteData } = selectedPalette.value
const rules = init({
inputRuleset: editorFriendlyToOriginal.value,
initialStaticVars: {
@@ -438,7 +414,6 @@ export default {
console.error('Could not compile preview theme', e)
}
}
-
const updateSelectedComponent = () => {
selectedVariant.value = 'normal'
selectedState.clear()
@@ -457,7 +432,7 @@ export default {
)
watch(
- editedPalette,
+ selectedPalette,
updatePreview
)
@@ -466,36 +441,76 @@ export default {
updateSelectedComponent
)
- // TODO this is VERY primitive right now, need to make it
- // support variables, fallbacks etc.
- const getContrast = (bg, text) => {
- try {
- const bgRgb = hex2rgb(bg)
- const textRgb = hex2rgb(text)
+ // export and import
+ const editorFriendlyToOriginal = computed(() => {
+ const resultRules = []
- const ratio = getContrastRatio(bgRgb, textRgb)
- return {
- // TODO this ideally should be part of <ContractRatio />
- ratio,
- text: ratio.toPrecision(3) + ':1',
- // AA level, AAA level
- aa: ratio >= 4.5,
- aaa: ratio >= 7,
- // same but for 18pt+ texts
- laa: ratio >= 3,
- laaa: ratio >= 4.5
- }
- } catch (e) {
- console.warn('Failure computing contrast', e)
- return { error: e }
+ const convert = (component, data = {}, parent) => {
+ const variants = Object.entries(data || {})
+
+ variants.forEach(([variant, variantData]) => {
+ const states = Object.entries(variantData)
+
+ states.forEach(([jointState, stateData]) => {
+ const state = jointState.split(/:/g)
+ const result = {
+ component,
+ variant,
+ state,
+ directives: stateData.directives || {}
+ }
+
+ if (parent) {
+ result.parent = {
+ component: parent
+ }
+ }
+
+ resultRules.push(result)
+
+ // Currently we only support single depth for simplicity's sake
+ if (!parent) {
+ Object.entries(stateData._children || {}).forEach(([cName, child]) => convert(cName, child, component))
+ }
+ })
+ })
}
- }
- const isShadowTabOpen = ref(false)
- const onTabSwitch = (tab) => {
- isShadowTabOpen.value = tab === 'shadow'
- }
+ convert(selectedComponentName.value, allEditedRules[selectedComponentName.value])
+
+ return resultRules
+ })
+ // ## Variables
+ const allCustomVirtualDirectives = [...componentsMap.values()]
+ .map(c => {
+ console.log(c.defaultRules.filter(c => c.component === 'Root'))
+ return c
+ .defaultRules
+ .filter(c => c.component === 'Root')
+ .map(x => Object.entries(x.directives))
+ .flat()
+ })
+ .filter(x => x)
+ .flat()
+ .map(([name, value]) => {
+ const [valType, valVal] = value.split('|')
+ return {
+ name: name.substring(2),
+ valType: valType.trim(),
+ value: valVal.trim()
+ }
+ })
+ const virtualDirectives = reactive(allCustomVirtualDirectives)
+ const selectedVirtualDirectiveId = ref(0)
+ const selectedVirtualDirective = computed(() => virtualDirectives[selectedVirtualDirectiveId.value])
+ const getNewDirective = () => ({
+ name: 'newDirective',
+ valType: 'generic',
+ value: 'foobar'
+ })
+
+ // ## Export and Import
const styleExporter = newExporter({
filename: 'pleroma.palette.json',
getExportedObject: () => exportStyleData
@@ -512,48 +527,73 @@ export default {
}
return {
+ // ## Meta
name,
author,
license,
website,
- palette,
+
+ // ## Palette
palettes,
- editedPalette,
+ selectedPalette,
+ selectedPaletteId,
getNewPalette,
+
+ // ## Components
componentKeys,
componentsMap,
+
+ // selection basis
selectedComponent,
selectedComponentName,
selectedComponentKey,
- selectedComponentVariantsAll,
+ selectedComponentVariants,
selectedComponentStates,
+
+ // selection
selectedVariant,
selectedState,
updateSelectedStates,
+
+ // component directives
+ componentHas,
+
+ // component colors
editedBackgroundColor,
+ isBackgroundColorPresent,
editedOpacity,
+ isOpacityPresent,
editedTextColor,
+ isTextColorPresent,
editedTextAuto,
+ isTextAutoPresent,
editedLinkColor,
+ isLinkColorPresent,
editedIconColor,
+ isIconColorPresent,
+ getContrast,
+
+ // component shadow
editedShadow,
editedSubShadow,
+ isShadowPresent,
onSubShadow,
updateSubShadow,
- getContrast,
- isBackgroundColorPresent,
- isOpacityPresent,
- isTextColorPresent,
- isTextAutoPresent,
- isLinkColorPresent,
- isIconColorPresent,
- isShadowPresent,
- previewCss,
- previewClass,
- editorHintStyle,
- componentHas,
isShadowTabOpen,
onTabSwitch,
+
+ // component preview
+ editorHintStyle,
+ previewCss,
+ previewClass,
+
+ // ## Variables
+ virtualDirectives,
+ selectedVirtualDirective,
+ selectedVirtualDirectiveId,
+ getNewDirective,
+
+ // ## Export and Import
exportStyle
}
}
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.vue b/src/components/settings_modal/tabs/style_tab/style_tab.vue
@@ -76,7 +76,7 @@
</Select>
</div>
<div
- v-if="selectedComponentVariantsAll.length > 1"
+ v-if="selectedComponentVariants.length > 1"
class="variant-selector"
>
<label for="variant-selector">
@@ -86,7 +86,7 @@
v-model="selectedVariant"
>
<option
- v-for="variant in selectedComponentVariantsAll"
+ v-for="variant in selectedComponentVariants"
:key="'component-variant-' + variant"
:value="variant"
>