shadow editor now can display shadow information

This commit is contained in:
Henry Jameson 2024-09-26 01:06:14 +03:00
parent b4a1bcd070
commit ef795becf6
4 changed files with 195 additions and 64 deletions

View file

@ -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 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 selectedComponentKey = ref(componentsMap.keys().next().value)
const selectedComponent = computed(() => componentsMap.get(selectedComponentKey.value))
const selectedComponentName = computed(() => selectedComponent.value.name)
const selectedVariant = ref('normal')
const selectedStates = reactive(new Set())
const selectedComponentVariantsAll = computed(() => {
return Object.keys({ normal: null, ...(selectedComponent.value.variants || {}) })
})
// const selectedComponentVariants = computed(() => {
// return selectedComponentVariantsAll.value.filter(x => x !== 'normal')
// })
const updateSelectedStates = (state, v) => {
if (v) {
selectedStates.add(state)
} else {
selectedStates.delete(state)
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')
})
// 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

View file

@ -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;
}
}
}

View file

@ -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>

View file

@ -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",