From 9753db1c6798c0a581e9eebcdb3f46c4e075b780 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 29 Sep 2024 03:20:14 +0300 Subject: [PATCH] it works! --- .../tabs/style_tab/style_tab.js | 115 +++++++++++++++--- .../tabs/style_tab/style_tab.scss | 4 + .../tabs/style_tab/style_tab.vue | 41 +++++++ src/i18n/en.json | 6 + 4 files changed, 152 insertions(+), 14 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 index 3b1b16ca..6589dc4d 100644 --- a/src/components/settings_modal/tabs/style_tab/style_tab.js +++ b/src/components/settings_modal/tabs/style_tab/style_tab.js @@ -10,9 +10,15 @@ import ColorInput from 'src/components/color_input/color_input.vue' import OpacityInput from 'src/components/opacity_input/opacity_input.vue' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx' import Popover from 'src/components/popover/popover.vue' +import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue' import { init } from 'src/services/theme_data/theme_data_3.service.js' import { getCssRules } from 'src/services/theme_data/css_utils.js' +import { + // rgb2hex, + hex2rgb, + getContrastRatio +} from 'src/services/color_convert/color_convert.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faFloppyDisk, faFolderOpen, faFile } from '@fortawesome/free-solid-svg-icons' @@ -40,7 +46,8 @@ export default { TabSwitcher, ShadowControl, ColorInput, - OpacityInput + OpacityInput, + ContrastRatio }, setup () { // Meta stuff @@ -153,7 +160,10 @@ export default { return scoped.join('\n') }) - // Rules stuff aka meat and potatoes + // ### 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 + // and child -> parent structure with map and parent -> child structure const editorFriendlyFallbackStructure = computed(() => { const root = {} @@ -251,27 +261,66 @@ export default { const editedBackgroundColor = getEditedElement(null, 'background') const editedOpacity = getEditedElement(null, 'opacity') - const editedTextColor = getEditedElement('Text', 'color') - const editedLinkColor = getEditedElement('Link', 'color') - const editedIconColor = getEditedElement('Icon', 'color') + const editedTextColor = getEditedElement('Text', 'textColor') + const editedTextAuto = getEditedElement('Text', 'textAuto') + const editedLinkColor = getEditedElement('Link', 'textColor') + const editedIconColor = getEditedElement('Icon', 'textColor') const editedShadow = getEditedElement(null, 'shadow') const isBackgroundColorPresent = isElementPresent(null, 'background', '#FFFFFF') const isOpacityPresent = isElementPresent(null, 'opacity', 1) - const isTextColorPresent = isElementPresent('Text', 'color', '#000000') - const isLinkColorPresent = isElementPresent('Link', 'color', '#000080') - const isIconColorPresent = isElementPresent('Icon', 'color', '#909090') + 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 updateSelectedComponent = () => { - selectedVariant.value = 'normal' - selectedState.clear() + 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 || {} + } + + console.log('PARENT', parent) + 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)) + } + }) + }) + } + + convert(selectedComponentName.value, allEditedRules[selectedComponentName.value]) + console.log(toValue(allEditedRules)) + console.log(toValue(resultRules)) + + return resultRules + }) + + const updatePreview = () => { previewRules.splice(0, previewRules.length) previewRules.push(...init({ - inputRuleset: [{ - component: selectedComponentName.value - }], + inputRuleset: editorFriendlyToOriginal.value, initialStaticVars: { ...palette }, @@ -282,13 +331,48 @@ export default { }).eager) } + const updateSelectedComponent = () => { + selectedVariant.value = 'normal' + selectedState.clear() + updatePreview() + } updateSelectedComponent() + watch( + allEditedRules, + updatePreview + ) + watch( selectedComponentName, updateSelectedComponent ) + // TODO this is VERY primitive right now, need to make it + // support variables, fallbacks etc. + const getContrast = (bg, text) => { + console.log('CONTRAST', bg, text) + try { + const bgRgb = hex2rgb(bg) + const textRgb = hex2rgb(text) + + const ratio = getContrastRatio(bgRgb, textRgb) + return { + 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 isShadowTabOpen = ref(false) const onTabSwitch = (tab) => { isShadowTabOpen.value = tab === 'shadow' @@ -318,12 +402,15 @@ export default { editedBackgroundColor, editedOpacity, editedTextColor, + editedTextAuto, editedLinkColor, editedIconColor, editedShadow, + getContrast, isBackgroundColorPresent, isOpacityPresent, isTextColorPresent, + isTextAutoPresent, isLinkColorPresent, isIconColorPresent, isShadowPresent, diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.scss b/src/components/settings_modal/tabs/style_tab/style_tab.scss index 9c85cc0b..4c439cf2 100644 --- a/src/components/settings_modal/tabs/style_tab/style_tab.scss +++ b/src/components/settings_modal/tabs/style_tab/style_tab.scss @@ -11,6 +11,10 @@ line-height: 2; } + &.suboption { + margin-left: 1em; + } + .opt { margin: 0.5em; } diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.vue b/src/components/settings_modal/tabs/style_tab/style_tab.vue index bc26a031..bfe809f4 100644 --- a/src/components/settings_modal/tabs/style_tab/style_tab.vue +++ b/src/components/settings_modal/tabs/style_tab/style_tab.vue @@ -183,6 +183,47 @@ {{ $t('settings.style.themes3.editor.include_in_rule') }} +
+ + +
+ + + + +
+ +
+
+ +