shadow editor now can display shadow information
This commit is contained in:
parent
b4a1bcd070
commit
ef795becf6
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue