commit: ef795becf6b2d6b0fa0aeeb5c1ad80c74e63e85b
parent b4a1bcd0707ba26c72411289b0a2e78a4396d142
Author: Henry Jameson <me@hjkos.com>
Date: Thu, 26 Sep 2024 01:06:14 +0300
shadow editor now can display shadow information
Diffstat:
4 files changed, 193 insertions(+), 62 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
@@ -4,6 +4,8 @@ import Select from 'src/components/select/select.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ComponentPreview from 'src/components/component_preview/component_preview.vue'
import StringSetting from '../../helpers/string_setting.vue'
+import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
+import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { init } from 'src/services/theme_data/theme_data_3.service.js'
import { getCssRules } from 'src/services/theme_data/css_utils.js'
@@ -11,6 +13,8 @@ import { getCssRules } from 'src/services/theme_data/css_utils.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faFloppyDisk, faFolderOpen, faFile } from '@fortawesome/free-solid-svg-icons'
+const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? '"lol"' : x))
+
library.add(
faFile,
faFloppyDisk,
@@ -22,14 +26,18 @@ export default {
Select,
Checkbox,
StringSetting,
- ComponentPreview
+ ComponentPreview,
+ TabSwitcher,
+ ShadowControl
},
setup () {
+ // Meta stuff
const name = ref('')
const author = ref('')
const license = ref('')
const website = ref('')
+ // Initialization stuff
const palette = {
// These are here just to establish order,
// themes should override those
@@ -61,43 +69,54 @@ export default {
// Getting existing components
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
- const componentKeysRaw = componentsContext.keys()
+ const componentKeysAll = componentsContext.keys()
const componentsMap = new Map(
- componentKeysRaw
+ componentKeysAll
.map(
key => [key, componentsContext(key).default]
).filter(([key, component]) => !component.virtual && !component.notEditable)
)
const componentKeys = [...componentsMap.keys()]
- // const componentValues = componentsMap.values()
-
// Initializing selected component and its computed descendants
- const selectedComponentKey = ref(componentKeys[0])
- const selectedComponentValue = computed(() => componentsMap.get(selectedComponentKey.value))
+ const selectedComponentKey = ref(componentsMap.keys().next().value)
+ const selectedComponent = computed(() => componentsMap.get(selectedComponentKey.value))
+ const selectedComponentName = computed(() => selectedComponent.value.name)
- const selectedComponentName = computed(() => selectedComponentValue.value.name)
- const selectedComponentVariants = computed(() => {
- return new Set(['normal', ...(Object.keys(selectedComponentValue.value.variants || {}))])
- })
- const selectedComponentStates = computed(() => {
- return new Set([...(Object.keys(selectedComponentValue.value.states || {}).filter(x => x !== 'normal'))])
+ const selectedVariant = ref('normal')
+ const selectedComponentVariantsAll = computed(() => {
+ return Object.keys({ normal: null, ...(selectedComponent.value.variants || {}) })
})
+ // const selectedComponentVariants = computed(() => {
+ // return selectedComponentVariantsAll.value.filter(x => x !== 'normal')
+ // })
- const selectedVariant = ref('normal')
const selectedStates = reactive(new Set())
+ const selectedComponentStatesAll = computed(() => {
+ return Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
+ })
+ const selectedComponentStates = computed(() => {
+ return selectedComponentStatesAll.value.filter(x => x !== 'normal')
+ })
- const updateSelectedStates = (state, v) => {
- if (v) {
- selectedStates.add(state)
- } else {
- selectedStates.delete(state)
+ // 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('; ')
+ })
const simulatePseudoSelectors = css => css
- .replace(selectedComponentValue.value.selector, '.ComponentPreview .preview-block')
+ .replace(selectedComponent.value.selector, '.ComponentPreview .preview-block')
.replace(':active', '.preview-active')
.replace(':hover', '.preview-hover')
.replace(':active', '.preview-active')
@@ -108,44 +127,70 @@ export default {
const previewRules = reactive([])
const previewClass = computed(() => {
const selectors = []
- if (!!selectedComponentValue.value.variants?.normal || selectedVariant.value !== 'normal') {
- selectors.push(selectedComponentValue.value.variants[selectedVariant.value])
+ if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
+ selectors.push(selectedComponent.value.variants[selectedVariant.value])
}
if (selectedStates.size > 0) {
selectedStates.forEach(state => {
- const original = selectedComponentValue.value.states[state]
+ const original = selectedComponent.value.states[state]
selectors.push(simulatePseudoSelectors(original))
})
}
return selectors.map(x => x.substring(1)).join('')
})
-
- const editorHintStyle = computed(() => {
- const editorHint = selectedComponentValue.value.editor
- const styles = []
- if (editorHint && Object.keys(editorHint).length > 0) {
- console.log('EH', editorHint)
- if (editorHint.aspect != null) {
- styles.push(`aspect-ratio: ${editorHint.aspect} !important;`)
- }
- if (editorHint.border != null) {
- styles.push(`border-width: ${editorHint.border}px !important;`)
- }
- }
- console.log('EH', styles)
- return styles.join('; ')
- })
-
const previewCss = computed(() => {
const scoped = getCssRules(previewRules)
.map(simulatePseudoSelectors)
return scoped.join('\n')
})
+ // Rules stuff
+ const selectedComponentRulesList = reactive([])
+ const selectedComponentRulesObject = computed(() => {
+ const result = {}
+ selectedComponentRulesList.forEach(
+ (rule) => {
+ const component = rule.component
+ const { variant = 'normal', state = [] } = rule
+ result[component] = result[component] || {}
+ result[component][variant] = result[component][variant] || {}
+ result[component][variant][state.join(':')] = rule
+ }
+ )
+ return result
+ })
+
+ // Edited rule
+ const editedRuleFallback = computed(() => {
+ const component = selectedComponentName.value
+ const variant = selectedVariant.value
+ const states = ['normal', ...selectedStates.keys()].join(':')
+ return selectedComponentRulesObject.value[component]?.[variant]?.[states]
+ })
+
+ const editedShadow = computed(() => {
+ return editedRuleFallback.value?.directives.shadow
+ })
+
const updateSelectedComponent = () => {
selectedVariant.value = 'normal'
selectedStates.clear()
+ const processedRulesList = selectedComponent.value.defaultRules.map(r => {
+ const rule = {
+ component: selectedComponentName.value,
+ variant: 'normal',
+ ...r,
+ state: ['normal', ...(r.state || []).filter(x => x !== 'normal')]
+ }
+ return rule
+ })
+
+ selectedComponentRulesList.splice(0, selectedComponentRulesList.length)
+ selectedComponentRulesList.push(...processedRulesList)
+
+ console.log('FALLBACK', toValue(editedRuleFallback.value))
+
previewRules.splice(0, previewRules.length)
previewRules.push(...init({
inputRuleset: [{
@@ -175,21 +220,29 @@ export default {
website,
componentKeys,
componentsMap,
-
- selectedComponentValue,
+ selectedComponent,
selectedComponentName,
selectedComponentKey,
- selectedComponentVariants,
+ selectedComponentVariantsAll,
selectedComponentStates,
- updateSelectedStates,
+ selectedComponentRulesObject,
selectedVariant,
selectedStates,
- getFriendlyNamePath,
- getStatePath,
- getVariantPath,
- editorHintStyle,
+ updateSelectedStates (state, v) {
+ if (v) {
+ selectedStates.add(state)
+ } else {
+ selectedStates.delete(state)
+ }
+ },
+ editedRuleFallback,
+ editedShadow,
previewCss,
previewClass,
+ editorHintStyle,
+ getFriendlyNamePath,
+ getVariantPath,
+ getStatePath,
fallbackI18n (translated, fallback) {
if (translated.startsWith('settings.style.themes3')) {
return fallback
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.scss b/src/components/settings_modal/tabs/style_tab/style_tab.scss
@@ -1,4 +1,48 @@
.StyleTab {
+ .style-control {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+ margin-bottom: 0.5em;
+
+ .label {
+ margin-right: 1em;
+ flex: 1 1 10em;
+ line-height: 2;
+ }
+
+ .opt {
+ margin: 0.5em;
+ }
+
+ .color-input {
+ flex: 0 0 0;
+ }
+
+ input,
+ select {
+ min-width: 3em;
+ margin: 0;
+ flex: 0;
+
+ &[type="number"] {
+ min-width: 5em;
+ }
+
+ &[type="range"] {
+ flex: 1;
+ min-width: 2em;
+ align-self: center;
+ margin: 0 0.5em;
+ }
+
+ &[type="checkbox"] + i {
+ height: 1.1em;
+ align-self: center;
+ }
+ }
+ }
+
.setting-item {
padding-bottom: 0;
@@ -74,6 +118,8 @@
.state-selector {
grid-area: state;
+ align-content: flex-start;
+ align-items: flex-start;
}
.variant-selector {
@@ -96,5 +142,12 @@
.component-settings {
grid-area: settings;
}
+
+ .editor-tab {
+ border-left: 1px solid var(--border);
+ border-right: 1px solid var(--border);
+ border-bottom: 1px solid var(--border);
+ padding: 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
@@ -83,44 +83,44 @@
{{ $t('settings.style.themes3.editor.variant_selector') }}
</label>
<Select
- v-if="selectedComponentVariants.size > 1"
+ v-if="selectedComponentVariantsAll.length > 1"
v-model="selectedVariant"
>
<option
- v-for="variant in selectedComponentVariants"
+ v-for="variant in selectedComponentVariantsAll"
:value="variant"
:key="'component-variant-' + variant"
>
{{ fallbackI18n($t(getVariantPath(selectedComponentName, variant)), variant) }}
</option>
</Select>
- <p v-else>
+ <div v-else>
{{ $t('settings.style.themes3.editor.only_variant') }}
- </p>
+ </div>
</div>
<div class="state-selector">
<label for="variant-selector">
{{ $t('settings.style.themes3.editor.states_selector') }}
</label>
<ul
- v-if="selectedComponentStates.size > 0"
+ v-if="selectedComponentStates.length > 0"
class="state-selector-list"
- >
+ >
<li
v-for="state in selectedComponentStates"
:key="'component-variant-' + state"
- >
+ >
<Checkbox
:value="selectedStates.has(state)"
- @update:modelValue="(v) => updateSelectedStates(state, v)"
- >
+ @update:modelValue="(v) => updateSelectedStates(state, v)"
+ >
{{ fallbackI18n($t(getStatePath(selectedComponentName, state)), state) }}
</Checkbox>
</li>
</ul>
- <p v-else>
+ <div v-else>
{{ $t('settings.style.themes3.editor.only_state') }}
- </p>
+ </div>
</div>
<div class="preview-container">
<!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->
@@ -136,8 +136,31 @@
@update:shadow="({ axis, value }) => updateProperty(axis, value)"
/>
</div>
- <div class="component-setting">
- </div>
+ <tab-switcher
+ ref="tabSwitcher"
+ class="component-settings"
+ :on-switch="onTabSwitch"
+ >
+ <div
+ class="editor-tab"
+ :label="$t('settings.style.themes3.editor.main_tab')"
+ :data-tab-name="main"
+ >
+ lol
+ </div>
+ <div
+ class="editor-tab"
+ :label="$t('settings.style.themes3.editor.shadows_tab')"
+ :data-tab-name="shadow"
+ >
+ <ShadowControl
+ v-model="editedShadow"
+ :no-preview="true"
+ :separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
+ :fallback="currentShadowFallback"
+ />
+ </div>
+ </tab-switcher>
</div>
</div>
</template>
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -767,6 +767,8 @@
"states_selector": "States",
"only_variant": "Component doesn't have any variants",
"only_state": "Component only has default state",
+ "main_tab": "Main",
+ "shadows_tab": "Shadows",
"components": {
"normal": {
"state": "Normal",