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 Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import ComponentPreview from 'src/components/component_preview/component_preview.vue'
|
import ComponentPreview from 'src/components/component_preview/component_preview.vue'
|
||||||
import StringSetting from '../../helpers/string_setting.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 { init } from 'src/services/theme_data/theme_data_3.service.js'
|
||||||
import { getCssRules } from 'src/services/theme_data/css_utils.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 { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faFloppyDisk, faFolderOpen, faFile } from '@fortawesome/free-solid-svg-icons'
|
import { faFloppyDisk, faFolderOpen, faFile } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? '"lol"' : x))
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFile,
|
faFile,
|
||||||
faFloppyDisk,
|
faFloppyDisk,
|
||||||
|
@ -22,14 +26,18 @@ export default {
|
||||||
Select,
|
Select,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
StringSetting,
|
StringSetting,
|
||||||
ComponentPreview
|
ComponentPreview,
|
||||||
|
TabSwitcher,
|
||||||
|
ShadowControl
|
||||||
},
|
},
|
||||||
setup () {
|
setup () {
|
||||||
|
// Meta stuff
|
||||||
const name = ref('')
|
const name = ref('')
|
||||||
const author = ref('')
|
const author = ref('')
|
||||||
const license = ref('')
|
const license = ref('')
|
||||||
const website = ref('')
|
const website = ref('')
|
||||||
|
|
||||||
|
// Initialization stuff
|
||||||
const palette = {
|
const palette = {
|
||||||
// These are here just to establish order,
|
// These are here just to establish order,
|
||||||
// themes should override those
|
// themes should override those
|
||||||
|
@ -61,43 +69,54 @@ export default {
|
||||||
|
|
||||||
// Getting existing components
|
// Getting existing components
|
||||||
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
|
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
|
||||||
const componentKeysRaw = componentsContext.keys()
|
const componentKeysAll = componentsContext.keys()
|
||||||
|
|
||||||
const componentsMap = new Map(
|
const componentsMap = new Map(
|
||||||
componentKeysRaw
|
componentKeysAll
|
||||||
.map(
|
.map(
|
||||||
key => [key, componentsContext(key).default]
|
key => [key, componentsContext(key).default]
|
||||||
).filter(([key, component]) => !component.virtual && !component.notEditable)
|
).filter(([key, component]) => !component.virtual && !component.notEditable)
|
||||||
)
|
)
|
||||||
const componentKeys = [...componentsMap.keys()]
|
const componentKeys = [...componentsMap.keys()]
|
||||||
|
|
||||||
// const componentValues = componentsMap.values()
|
|
||||||
|
|
||||||
// Initializing selected component and its computed descendants
|
// Initializing selected component and its computed descendants
|
||||||
const selectedComponentKey = ref(componentKeys[0])
|
const selectedComponentKey = ref(componentsMap.keys().next().value)
|
||||||
const selectedComponentValue = computed(() => componentsMap.get(selectedComponentKey.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 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) => {
|
const selectedStates = reactive(new Set())
|
||||||
if (v) {
|
const selectedComponentStatesAll = computed(() => {
|
||||||
selectedStates.add(state)
|
return Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
|
||||||
} else {
|
})
|
||||||
selectedStates.delete(state)
|
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
|
const simulatePseudoSelectors = css => css
|
||||||
.replace(selectedComponentValue.value.selector, '.ComponentPreview .preview-block')
|
.replace(selectedComponent.value.selector, '.ComponentPreview .preview-block')
|
||||||
.replace(':active', '.preview-active')
|
.replace(':active', '.preview-active')
|
||||||
.replace(':hover', '.preview-hover')
|
.replace(':hover', '.preview-hover')
|
||||||
.replace(':active', '.preview-active')
|
.replace(':active', '.preview-active')
|
||||||
|
@ -108,44 +127,70 @@ export default {
|
||||||
const previewRules = reactive([])
|
const previewRules = reactive([])
|
||||||
const previewClass = computed(() => {
|
const previewClass = computed(() => {
|
||||||
const selectors = []
|
const selectors = []
|
||||||
if (!!selectedComponentValue.value.variants?.normal || selectedVariant.value !== 'normal') {
|
if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
|
||||||
selectors.push(selectedComponentValue.value.variants[selectedVariant.value])
|
selectors.push(selectedComponent.value.variants[selectedVariant.value])
|
||||||
}
|
}
|
||||||
if (selectedStates.size > 0) {
|
if (selectedStates.size > 0) {
|
||||||
selectedStates.forEach(state => {
|
selectedStates.forEach(state => {
|
||||||
const original = selectedComponentValue.value.states[state]
|
const original = selectedComponent.value.states[state]
|
||||||
selectors.push(simulatePseudoSelectors(original))
|
selectors.push(simulatePseudoSelectors(original))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return selectors.map(x => x.substring(1)).join('')
|
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 previewCss = computed(() => {
|
||||||
const scoped = getCssRules(previewRules)
|
const scoped = getCssRules(previewRules)
|
||||||
.map(simulatePseudoSelectors)
|
.map(simulatePseudoSelectors)
|
||||||
return scoped.join('\n')
|
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 = () => {
|
const updateSelectedComponent = () => {
|
||||||
selectedVariant.value = 'normal'
|
selectedVariant.value = 'normal'
|
||||||
selectedStates.clear()
|
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.splice(0, previewRules.length)
|
||||||
previewRules.push(...init({
|
previewRules.push(...init({
|
||||||
inputRuleset: [{
|
inputRuleset: [{
|
||||||
|
@ -175,21 +220,29 @@ export default {
|
||||||
website,
|
website,
|
||||||
componentKeys,
|
componentKeys,
|
||||||
componentsMap,
|
componentsMap,
|
||||||
|
selectedComponent,
|
||||||
selectedComponentValue,
|
|
||||||
selectedComponentName,
|
selectedComponentName,
|
||||||
selectedComponentKey,
|
selectedComponentKey,
|
||||||
selectedComponentVariants,
|
selectedComponentVariantsAll,
|
||||||
selectedComponentStates,
|
selectedComponentStates,
|
||||||
updateSelectedStates,
|
selectedComponentRulesObject,
|
||||||
selectedVariant,
|
selectedVariant,
|
||||||
selectedStates,
|
selectedStates,
|
||||||
getFriendlyNamePath,
|
updateSelectedStates (state, v) {
|
||||||
getStatePath,
|
if (v) {
|
||||||
getVariantPath,
|
selectedStates.add(state)
|
||||||
editorHintStyle,
|
} else {
|
||||||
|
selectedStates.delete(state)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editedRuleFallback,
|
||||||
|
editedShadow,
|
||||||
previewCss,
|
previewCss,
|
||||||
previewClass,
|
previewClass,
|
||||||
|
editorHintStyle,
|
||||||
|
getFriendlyNamePath,
|
||||||
|
getVariantPath,
|
||||||
|
getStatePath,
|
||||||
fallbackI18n (translated, fallback) {
|
fallbackI18n (translated, fallback) {
|
||||||
if (translated.startsWith('settings.style.themes3')) {
|
if (translated.startsWith('settings.style.themes3')) {
|
||||||
return fallback
|
return fallback
|
||||||
|
|
|
@ -1,4 +1,48 @@
|
||||||
.StyleTab {
|
.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 {
|
.setting-item {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
@ -74,6 +118,8 @@
|
||||||
|
|
||||||
.state-selector {
|
.state-selector {
|
||||||
grid-area: state;
|
grid-area: state;
|
||||||
|
align-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variant-selector {
|
.variant-selector {
|
||||||
|
@ -96,5 +142,12 @@
|
||||||
.component-settings {
|
.component-settings {
|
||||||
grid-area: 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') }}
|
{{ $t('settings.style.themes3.editor.variant_selector') }}
|
||||||
</label>
|
</label>
|
||||||
<Select
|
<Select
|
||||||
v-if="selectedComponentVariants.size > 1"
|
v-if="selectedComponentVariantsAll.length > 1"
|
||||||
v-model="selectedVariant"
|
v-model="selectedVariant"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="variant in selectedComponentVariants"
|
v-for="variant in selectedComponentVariantsAll"
|
||||||
:value="variant"
|
:value="variant"
|
||||||
:key="'component-variant-' + variant"
|
:key="'component-variant-' + variant"
|
||||||
>
|
>
|
||||||
{{ fallbackI18n($t(getVariantPath(selectedComponentName, variant)), variant) }}
|
{{ fallbackI18n($t(getVariantPath(selectedComponentName, variant)), variant) }}
|
||||||
</option>
|
</option>
|
||||||
</Select>
|
</Select>
|
||||||
<p v-else>
|
<div v-else>
|
||||||
{{ $t('settings.style.themes3.editor.only_variant') }}
|
{{ $t('settings.style.themes3.editor.only_variant') }}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="state-selector">
|
<div class="state-selector">
|
||||||
<label for="variant-selector">
|
<label for="variant-selector">
|
||||||
{{ $t('settings.style.themes3.editor.states_selector') }}
|
{{ $t('settings.style.themes3.editor.states_selector') }}
|
||||||
</label>
|
</label>
|
||||||
<ul
|
<ul
|
||||||
v-if="selectedComponentStates.size > 0"
|
v-if="selectedComponentStates.length > 0"
|
||||||
class="state-selector-list"
|
class="state-selector-list"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
v-for="state in selectedComponentStates"
|
v-for="state in selectedComponentStates"
|
||||||
:key="'component-variant-' + state"
|
:key="'component-variant-' + state"
|
||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
:value="selectedStates.has(state)"
|
:value="selectedStates.has(state)"
|
||||||
@update:modelValue="(v) => updateSelectedStates(state, v)"
|
@update:modelValue="(v) => updateSelectedStates(state, v)"
|
||||||
>
|
>
|
||||||
{{ fallbackI18n($t(getStatePath(selectedComponentName, state)), state) }}
|
{{ fallbackI18n($t(getStatePath(selectedComponentName, state)), state) }}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p v-else>
|
<div v-else>
|
||||||
{{ $t('settings.style.themes3.editor.only_state') }}
|
{{ $t('settings.style.themes3.editor.only_state') }}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-container">
|
<div class="preview-container">
|
||||||
<!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->
|
<!-- 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)"
|
@update:shadow="({ axis, value }) => updateProperty(axis, value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="component-setting">
|
<tab-switcher
|
||||||
</div>
|
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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -767,6 +767,8 @@
|
||||||
"states_selector": "States",
|
"states_selector": "States",
|
||||||
"only_variant": "Component doesn't have any variants",
|
"only_variant": "Component doesn't have any variants",
|
||||||
"only_state": "Component only has default state",
|
"only_state": "Component only has default state",
|
||||||
|
"main_tab": "Main",
|
||||||
|
"shadows_tab": "Shadows",
|
||||||
"components": {
|
"components": {
|
||||||
"normal": {
|
"normal": {
|
||||||
"state": "Normal",
|
"state": "Normal",
|
||||||
|
|
Loading…
Reference in a new issue