Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2024-10-28 21:23:14 +02:00
commit a023c44bee
9 changed files with 435 additions and 368 deletions

View file

@ -5,6 +5,10 @@
flex: 1 1 auto;
}
.opt {
margin-right: 0.5em;
}
&-field.input {
display: inline-flex;
flex: 0 0 0;

View file

@ -103,6 +103,7 @@
>
</div>
<ColorInput
v-if="!noColorControl"
class="input-color-input"
v-model="colorOverride"
fallback="#606060"
@ -128,19 +129,19 @@ export default {
'previewStyle',
'previewCss',
'disabled',
'invalid'
'invalid',
'noColorControl'
],
emits: ['update:shadow'],
data () {
return {
colorOverride: null,
colorOverride: undefined,
lightGrid: false,
zoom: 100
}
},
computed: {
style () {
console.log(this.previewStyle)
const result = [
this.previewStyle,
`zoom: ${this.zoom / 100}`

View file

@ -72,6 +72,7 @@ const moveUp = () => {
const moveDnValid = computed(() => {
return props.selectedId < props.modelValue.length - 1
})
const moveDn = () => {
const newModel = [...props.modelValue]
const movable = newModel.splice(props.selectedId.value, 1)[0]

View file

@ -1,5 +1,6 @@
import { ref, reactive, computed, watch } from 'vue'
import { get, set } from 'lodash'
import { ref, reactive, computed, watch, provide } from 'vue'
import { useStore } from 'vuex'
import { get, set, unset } from 'lodash'
import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
@ -15,12 +16,14 @@ import Tooltip from 'src/components/tooltip/tooltip.vue'
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
import Preview from '../theme_tab/theme_preview.vue'
import VirtualDirectivesTab from './virtual_directives_tab.vue'
import { init, findColor } from 'src/services/theme_data/theme_data_3.service.js'
import {
getCssRules,
getScopedVersion
} from 'src/services/theme_data/css_utils.js'
import { serializeShadow, serialize } from 'src/services/theme_data/iss_serializer.js'
import { serialize } from 'src/services/theme_data/iss_serializer.js'
import { deserializeShadow, deserialize } from 'src/services/theme_data/iss_deserializer.js'
import {
rgb2hex,
@ -70,10 +73,12 @@ export default {
PaletteEditor,
OpacityInput,
ContrastRatio,
Preview
Preview,
VirtualDirectivesTab
},
setup () {
setup (props, context) {
const exports = {}
const store = useStore()
// All rules that are made by editor
const allEditedRules = reactive({})
@ -97,7 +102,7 @@ export default {
// ## Palette stuff
const palettes = reactive([
{
name: 'dark',
name: 'default',
bg: '#121a24',
fg: '#182230',
text: '#b9b9ba',
@ -147,6 +152,7 @@ export default {
})
exports.selectedPaletteId = selectedPaletteId
exports.selectedPalette = selectedPalette
provide('selectedPalette', selectedPalette)
exports.getNewPalette = () => ({
name: 'new palette',
@ -186,19 +192,20 @@ export default {
const componentKeys = [...componentsMap.keys()]
exports.componentKeys = componentKeys
// selection basis
// Component list and selection
const selectedComponentKey = ref(componentsMap.keys().next().value)
exports.selectedComponentKey = selectedComponentKey
const selectedComponent = computed(() => componentsMap.get(selectedComponentKey.value))
const selectedComponentName = computed(() => selectedComponent.value.name)
// Selection basis
exports.selectedComponentVariants = computed(() => {
return Object.keys({ normal: null, ...(selectedComponent.value.variants || {}) })
})
const selectedComponentStatesAll = computed(() => {
return Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
})
exports.selectedComponentStates = computed(() => {
return selectedComponentStatesAll.value.filter(x => x !== 'normal')
const all = Object.keys({ normal: null, ...(selectedComponent.value.states || {}) })
return all.filter(x => x !== 'normal')
})
// selection
@ -214,6 +221,17 @@ export default {
}
}
// Reset variant and state on component change
const updateSelectedComponent = () => {
selectedVariant.value = 'normal'
selectedState.clear()
}
watch(
selectedComponentName,
updateSelectedComponent
)
// ### 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
@ -270,13 +288,13 @@ export default {
return root
})
// Checkging whether component can support some "directives" which
// Checking whether component can support some "directives" which
// are actually virtual subcomponents, i.e. Text, Link etc
exports.componentHas = (subComponent) => {
return !!selectedComponent.value.validInnerComponents?.find(x => x === subComponent)
}
// Path is path for lodash's get and set
// Path for lodash's get and set
const getPath = (component, directive) => {
const pathSuffix = component ? `._children.${component}.normal.normal` : ''
const path = `${selectedComponentName.value}.${selectedVariant.value}.${normalizeStates([...selectedState])}${pathSuffix}.directives.${directive}`
@ -296,7 +314,7 @@ export default {
)
set(allEditedRules, getPath(component, directive), fallback ?? defaultValue)
} else {
set(allEditedRules, getPath(component, directive), null)
unset(allEditedRules, getPath(component, directive))
}
}
})
@ -313,14 +331,14 @@ export default {
usedRule = get(fallback, path)
}
if (directive === 'shadow') {
console.log('EDITED', usedRule)
console.log('PP', postProcess(usedRule))
}
return postProcess(usedRule)
},
set (value) {
set(allEditedRules, getPath(component, directive), value)
if (value) {
set(allEditedRules, getPath(component, directive), value)
} else {
unset(allEditedRules, getPath(component, directive))
}
}
})
@ -378,6 +396,7 @@ export default {
return null
})
}
provide('normalizeShadows', normalizeShadows)
// Shadow is partially edited outside the ShadowControl
// for better space utilization
@ -428,57 +447,6 @@ export default {
}
return styles.join('; ')
})
// Apart from "hover" we can't really show how component looks like in
// certain states, so we have to fake them.
const simulatePseudoSelectors = css => css
.replace(selectedComponent.value.selector, '.ComponentPreview .preview-block')
.replace(':active', '.preview-active')
.replace(':hover', '.preview-hover')
.replace(':active', '.preview-active')
.replace(':focus', '.preview-focus')
.replace(':focus-within', '.preview-focus-within')
.replace(':disabled', '.preview-disabled')
exports.previewClass = computed(() => {
const selectors = []
if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
selectors.push(selectedComponent.value.variants[selectedVariant.value])
}
if (selectedState.size > 0) {
selectedState.forEach(state => {
const original = selectedComponent.value.states[state]
selectors.push(simulatePseudoSelectors(original))
})
}
return selectors.map(x => x.substring(1)).join('')
})
const previewRules = reactive([])
exports.previewRules = previewRules
exports.previewCss = computed(() => {
try {
const scoped = getCssRules(previewRules).map(simulatePseudoSelectors)
return scoped.join('\n')
} catch (e) {
console.error('Invalid ruleset', e)
return null
}
})
const applicablePreviewRules = computed(() => {
return previewRules.filter(rule => {
const filterable = rule.parent ? rule.parent : rule
const variantMatches = filterable.variant === selectedVariant.value
const stateMatches = filterable.state.filter(x => x !== 'normal').every(x => selectedState.has(x))
return variantMatches && stateMatches
})
})
const previewColors = computed(() => ({
text: applicablePreviewRules.value.find(r => r.component === 'Text')?.virtualDirectives['--text'],
link: applicablePreviewRules.value.find(r => r.component === 'Link')?.virtualDirectives['--link'],
border: applicablePreviewRules.value.find(r => r.component === 'Border')?.virtualDirectives['--border'],
icon: applicablePreviewRules.value.find(r => r.component === 'Icon')?.virtualDirectives['--icon'],
background: applicablePreviewRules.value.find(r => r.parent == null)?.dynamicVars.stacked
}))
exports.previewColors = previewColors
const editorFriendlyToOriginal = computed(() => {
const resultRules = []
@ -514,64 +482,13 @@ export default {
})
}
convert(selectedComponentName.value, allEditedRules[selectedComponentName.value])
componentsMap.values().forEach(({ name }) => {
convert(name, allEditedRules[name])
})
return resultRules
})
const updatePreview = () => {
try {
const { name, ...paletteData } = selectedPalette.value
// This normally would be handled by Root but since we pass something
// else we have to make do ourselves
paletteData.accent = paletteData.accent || paletteData.link
paletteData.link = paletteData.link || paletteData.accent
const rules = init({
inputRuleset: editorFriendlyToOriginal.value,
initialStaticVars: {
...paletteData
},
ultimateBackgroundColor: '#000000',
rootComponentName: selectedComponentName.value,
editMode: true,
debug: true
}).eager
previewRules.splice(0, previewRules.length)
previewRules.push(...rules)
} catch (e) {
console.error('Could not compile preview theme', e)
}
}
const updateSelectedComponent = () => {
selectedVariant.value = 'normal'
selectedState.clear()
updatePreview()
}
updateSelectedComponent()
// export and import
watch(
allEditedRules,
updatePreview
)
watch(
palettes,
updatePreview
)
watch(
selectedPalette,
updatePreview
)
watch(
selectedComponentName,
updateSelectedComponent
)
// ## Variables
const allCustomVirtualDirectives = [...componentsMap.values()]
.map(c => {
return c
@ -590,124 +507,29 @@ export default {
value: valVal.trim()
}
})
const virtualDirectives = reactive(allCustomVirtualDirectives)
const virtualDirectives = ref(allCustomVirtualDirectives)
exports.virtualDirectives = virtualDirectives
exports.onVirtualDirectivesUpdate = (e) => {
virtualDirectives.splice(0, virtualDirectives.length)
virtualDirectives.push(...e)
exports.updateVirtualDirectives = (value) => {
virtualDirectives.value = value
}
const selectedVirtualDirectiveId = ref(0)
exports.selectedVirtualDirectiveId = selectedVirtualDirectiveId
const selectedVirtualDirective = computed({
get () {
return virtualDirectives[selectedVirtualDirectiveId.value]
},
set (value) {
virtualDirectives[selectedVirtualDirectiveId.value].value = value
}
})
exports.selectedVirtualDirective = selectedVirtualDirective
exports.selectedVirtualDirectiveValType = computed({
get () {
return virtualDirectives[selectedVirtualDirectiveId.value].valType
},
set (value) {
const newValType = value
let newValue
switch (value) {
case 'shadow':
newValue = '0 0 0 #000000 / 1'
break
case 'color':
newValue = '#000000'
break
default:
newValue = 'none'
}
const newName = virtualDirectives[selectedVirtualDirectiveId.value].name
virtualDirectives[selectedVirtualDirectiveId.value] = {
name: newName,
value: newValue,
valType: newValType
}
}
})
const draftVirtualDirectiveValid = ref(true)
const draftVirtualDirective = ref({})
exports.draftVirtualDirective = draftVirtualDirective
watch(
selectedVirtualDirective,
(directive) => {
switch (directive.valType) {
case 'shadow': {
if (Array.isArray(directive.value)) {
draftVirtualDirective.value = normalizeShadows(directive.value)
} else {
const splitShadow = directive.value.split(/,/g).map(x => x.trim())
draftVirtualDirective.value = normalizeShadows(splitShadow)
}
break
}
case 'color':
draftVirtualDirective.value = directive.value
break
default:
draftVirtualDirective.value = directive.value
break
}
},
{ immediate: true }
)
watch(
draftVirtualDirective,
(directive) => {
try {
switch (selectedVirtualDirective.value.valType) {
case 'shadow': {
virtualDirectives[selectedVirtualDirectiveId.value].value =
directive.map(x => serializeShadow(x)).join(', ')
break
}
default:
virtualDirectives[selectedVirtualDirectiveId.value].value = directive
}
draftVirtualDirectiveValid.value = true
} catch (e) {
console.error('Invalid virtual directive value', e)
draftVirtualDirectiveValid.value = false
}
},
{ immediate: true }
)
const virtualDirectivesOut = computed(() => {
return [
'Root {',
...virtualDirectives.map(vd => ` --${vd.name}: ${vd.valType} | ${vd.value};`),
...virtualDirectives.value.map(vd => ` --${vd.name}: ${vd.valType} | ${vd.value};`),
'}'
].join('\n')
})
exports.getNewVirtualDirective = () => ({
name: 'newDirective',
valType: 'generic',
value: 'foobar'
})
exports.computeColor = (color) => {
const computedColor = findColor(color, { dynamicVars: {}, staticVars: selectedPalette.value })
const computedColor = findColor(color, { dynamicVars: dynamicVars.value, staticVars: selectedPalette.value })
if (computedColor) {
return rgb2hex(computedColor)
}
return null
}
provide('computeColor', exports.computeColor)
exports.contrast = computed(() => {
return getContrast(
@ -716,48 +538,24 @@ export default {
)
})
const overallPreviewRules = ref()
exports.overallPreviewRules = overallPreviewRules
exports.updateOverallPreview = () => {
try {
// This normally would be handled by Root but since we pass something
// else we have to make do ourselves
const { name, ...rest } = selectedPalette.value
const paletteRule = {
component: 'Root',
directives: Object
.entries(rest)
.map(([k, v]) => ['--' + k, v])
.reduce((acc, [k, v]) => ({ ...acc, [k]: `color | ${v}` }), {})
}
const virtualDirectivesRule = {
component: 'Root',
directives: Object.fromEntries(
virtualDirectives.map(vd => [`--${vd.name}`, `${vd.valType} | ${vd.value}`])
)
}
const rules = init({
inputRuleset: [
paletteRule,
virtualDirectivesRule,
...editorFriendlyToOriginal.value
],
ultimateBackgroundColor: '#000000',
liteMode: true,
debug: true
}).eager
overallPreviewRules.value = getScopedVersion(
getCssRules(rules),
'#edited-style-preview'
).join('\n')
} catch (e) {
console.error('Could not compile preview theme', e)
const paletteRule = computed(() => {
const { name, ...rest } = selectedPalette.value
return {
component: 'Root',
directives: Object
.entries(rest)
.filter(([k, v]) => v)
.map(([k, v]) => ['--' + k, v])
.reduce((acc, [k, v]) => ({ ...acc, [k]: `color | ${v}` }), {})
}
}
})
const virtualDirectivesRule = computed(() => ({
component: 'Root',
directives: Object.fromEntries(
virtualDirectives.value.map(vd => [`--${vd.name}`, `${vd.valType} | ${vd.value}`])
)
}))
// ## Export and Import
const styleExporter = newExporter({
@ -782,14 +580,13 @@ export default {
exports.author.value = metaIn.author
exports.website.value = metaIn.website
virtualDirectives.splice(0, virtualDirectives.length)
const newVirtualDirectives = Object
.entries(rootComponent.directives)
.map(([name, value]) => {
const [valType, valVal] = value.split('|').map(x => x.trim())
return { name: name.substring(2), valType, value: valVal }
})
virtualDirectives.push(...newVirtualDirectives)
virtualDirectives.value = newVirtualDirectives
onPalettesUpdate(palettesIn.map(x => ({ name: x.variant, ...x.directives })))
@ -801,6 +598,8 @@ export default {
allEditedRules
)
})
exports.updateOverallPreview()
}
})
@ -821,6 +620,133 @@ export default {
styleImporter.importData()
}
const exportRules = computed(() => [
paletteRule.value,
virtualDirectivesRule.value,
...editorFriendlyToOriginal.value
])
exports.applyStyle = () => {
store.dispatch('setStyleCustom', exportRules.value)
}
const overallPreviewRules = ref([])
exports.overallPreviewRules = overallPreviewRules
const overallPreviewCssRules = computed(() => getScopedVersion(
getCssRules(overallPreviewRules.value),
'#edited-style-preview'
).join('\n'))
exports.overallPreviewCssRules = overallPreviewCssRules
const updateOverallPreview = () => {
try {
overallPreviewRules.value = init({
inputRuleset: exportRules.value,
ultimateBackgroundColor: '#000000',
liteMode: true,
debug: true
}).eager
} catch (e) {
console.error('Could not compile preview theme', e)
return null
}
}
//
// Apart from "hover" we can't really show how component looks like in
// certain states, so we have to fake them.
const simulatePseudoSelectors = (css, prefix) => css
.replace(prefix, '.component-preview .preview-block')
.replace(':active', '.preview-active')
.replace(':hover', '.preview-hover')
.replace(':active', '.preview-active')
.replace(':focus', '.preview-focus')
.replace(':focus-within', '.preview-focus-within')
.replace(':disabled', '.preview-disabled')
const previewRules = computed(() => {
const filtered = overallPreviewRules.value.filter(r => {
const componentMatch = r.component === selectedComponentName.value
const parentComponentMatch = r.parent?.component === selectedComponentName.value
if (!componentMatch && !parentComponentMatch) return false
const rule = parentComponentMatch ? r.parent : r
if (rule.component !== selectedComponentName.value) return false
if (rule.variant !== selectedVariant.value) return false
const ruleState = new Set(rule.state.filter(x => x !== 'normal'))
const differenceA = [...ruleState].filter(x => !selectedState.has(x))
const differenceB = [...selectedState].filter(x => !ruleState.has(x))
return (differenceA.length + differenceB.length) === 0
})
const sorted = [...filtered]
.filter(x => x.component === selectedComponentName.value)
.sort((a, b) => {
const aSelectorLength = a.selector.split(/ /g).length
const bSelectorLength = b.selector.split(/ /g).length
return aSelectorLength - bSelectorLength
})
const prefix = sorted[0].selector
return filtered.filter(x => x.selector.startsWith(prefix))
})
exports.previewClass = computed(() => {
const selectors = []
if (!!selectedComponent.value.variants?.normal || selectedVariant.value !== 'normal') {
selectors.push(selectedComponent.value.variants[selectedVariant.value])
}
if (selectedState.size > 0) {
selectedState.forEach(state => {
const original = selectedComponent.value.states[state]
console.log('ORIG', original)
selectors.push(simulatePseudoSelectors(original))
})
}
return selectors.map(x => x.substring(1)).join('')
})
exports.previewCss = computed(() => {
try {
const prefix = previewRules.value[0].selector
const scoped = getCssRules(previewRules.value).map(x => simulatePseudoSelectors(x, prefix))
return scoped.join('\n')
} catch (e) {
console.error('Invalid ruleset', e)
return null
}
})
const dynamicVars = computed(() => {
return previewRules.value[0].dynamicVars
})
const previewColors = computed(() => {
const stacked = dynamicVars.value.stacked
const background = typeof stacked === 'string' ? stacked : rgb2hex(stacked)
return {
text: previewRules.value.find(r => r.component === 'Text')?.virtualDirectives['--text'],
link: previewRules.value.find(r => r.component === 'Link')?.virtualDirectives['--link'],
border: previewRules.value.find(r => r.component === 'Border')?.virtualDirectives['--border'],
icon: previewRules.value.find(r => r.component === 'Icon')?.virtualDirectives['--icon'],
background
}
})
exports.previewColors = previewColors
exports.updateOverallPreview = updateOverallPreview
updateOverallPreview()
watch(
[
allEditedRules,
palettes,
selectedPalette,
selectedState,
selectedVariant
],
updateOverallPreview
)
return exports
}
}

View file

@ -7,7 +7,7 @@
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
<component
:is="'style'"
v-html="overallPreviewRules"
v-html="overallPreviewCssRules"
/>
<!-- eslint-enable vue/no-v-text-v-html-on-component -->
<Preview id="edited-style-preview" />
@ -41,7 +41,7 @@
</button>
<button
class="btn button-default button-apply"
@click="applyTheme"
@click="applyStyle"
>
<FAIcon icon="check" />
{{ $t('settings.style.themes3.editor.apply_preview') }}
@ -151,6 +151,7 @@
:preview-css="previewCss"
:disabled="!editedSubShadow && typeof editedShadow !== 'string'"
:shadow="editedSubShadow"
:no-color-control="true"
@update:shadow="({ axis, value }) => updateSubShadow(axis, value)"
/>
</div>
@ -355,89 +356,13 @@
/>
</div>
</div>
<div
<VirtualDirectivesTab
key="variables"
:label="$t('settings.style.themes3.editor.variables_tab')"
class="setting-item list-editor variables-editor"
>
<label
class="list-select-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.label') }}
{{ ' ' }}
</label>
<Select
id="variables-selector"
v-model="selectedVirtualDirectiveId"
class="list-select"
size="20"
>
<option
v-for="(p, index) in virtualDirectives"
:key="p.name"
:value="index"
>
{{ p.name }}
</option>
</Select>
<SelectMotion
class="list-select-movement"
:modelValue="virtualDirectives"
@update:modelValue="onVirtualDirectivesUpdate"
:selected-id="selectedVirtualDirectiveId"
:get-add-value="getNewVirtualDirective"
@update:selectedId="e => selectedVirtualDirectiveId = e"
/>
<div class="list-edit-area">
<div class="variable-selector">
<label
class="variable-name-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.name_label') }}
{{ ' ' }}
</label>
<input
class="input"
v-model="selectedVirtualDirective.name"
>
<label
class="variable-type-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.type_label') }}
{{ ' ' }}
</label>
<Select
v-model="selectedVirtualDirectiveValType"
>
<option value='shadow'>
{{ $t('settings.style.themes3.editor.variables.type_shadow') }}
</option>
<option value='color'>
{{ $t('settings.style.themes3.editor.variables.type_color') }}
</option>
<option value='generic'>
{{ $t('settings.style.themes3.editor.variables.type_generic') }}
</option>
</Select>
</div>
<ShadowControl
v-if="selectedVirtualDirectiveValType === 'shadow'"
v-model="draftVirtualDirective"
:static-vars="selectedPalette"
:compact="true"
/>
<ColorInput
v-if="selectedVirtualDirectiveValType === 'color'"
v-model="draftVirtualDirective"
:fallback="computeColor(draftVirtualDirective)"
:label="$t('settings.style.themes3.editor.variables.virtual_color')"
:hide-optional-checkbox="true"
/>
</div>
</div>
:model-value="virtualDirectives"
@update:modelValue="updateVirtualDirectives"
:normalize-shadows="normalizeShadows"
/>
</tab-switcher>
</div>
</template>

View file

@ -0,0 +1,132 @@
import { ref, computed, watch, inject } from 'vue'
import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
import ColorInput from 'src/components/color_input/color_input.vue'
import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
// helper for debugging
// eslint-disable-next-line no-unused-vars
const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
export default {
components: {
Select,
SelectMotion,
ShadowControl,
ColorInput
},
props: ['modelValue'],
emits: ['update:modelValue'],
setup (props, context) {
const exports = {}
const emit = context.emit
exports.emit = emit
exports.computeColor = inject('computeColor')
exports.selectedPalette = inject('selectedPalette')
const selectedVirtualDirectiveId = ref(0)
exports.selectedVirtualDirectiveId = selectedVirtualDirectiveId
const selectedVirtualDirective = computed({
get () {
return props.modelValue[selectedVirtualDirectiveId.value]
},
set (value) {
const newVD = [...props.modelValue]
newVD[selectedVirtualDirectiveId.value] = value
emit('update:modelValue', newVD)
}
})
exports.selectedVirtualDirective = selectedVirtualDirective
exports.selectedVirtualDirectiveValType = computed({
get () {
return props.modelValue[selectedVirtualDirectiveId.value].valType
},
set (value) {
const newValType = value
let newValue
switch (value) {
case 'shadow':
newValue = '0 0 0 #000000 / 1'
break
case 'color':
newValue = '#000000'
break
default:
newValue = 'none'
}
const newName = props.modelValue[selectedVirtualDirectiveId.value].name
props.modelValue[selectedVirtualDirectiveId.value] = {
name: newName,
value: newValue,
valType: newValType
}
}
})
const draftVirtualDirectiveValid = ref(true)
const draftVirtualDirective = ref({})
exports.draftVirtualDirective = draftVirtualDirective
const normalizeShadows = inject('normalizeShadows')
watch(
selectedVirtualDirective,
(directive) => {
switch (directive.valType) {
case 'shadow': {
if (Array.isArray(directive.value)) {
draftVirtualDirective.value = normalizeShadows(directive.value)
} else {
const splitShadow = directive.value.split(/,/g).map(x => x.trim())
draftVirtualDirective.value = normalizeShadows(splitShadow)
}
break
}
case 'color':
draftVirtualDirective.value = directive.value
break
default:
draftVirtualDirective.value = directive.value
break
}
},
{ immediate: true }
)
watch(
draftVirtualDirective,
(directive) => {
try {
switch (selectedVirtualDirective.value.valType) {
case 'shadow': {
props.modelValue[selectedVirtualDirectiveId.value].value =
directive.map(x => serializeShadow(x)).join(', ')
break
}
default:
props.modelValue[selectedVirtualDirectiveId.value].value = directive
}
draftVirtualDirectiveValid.value = true
} catch (e) {
console.error('Invalid virtual directive value', e)
draftVirtualDirectiveValid.value = false
}
},
{ immediate: true }
)
exports.getNewVirtualDirective = () => ({
name: 'newDirective',
valType: 'generic',
value: 'foobar'
})
return exports
}
}

View file

@ -0,0 +1,83 @@
<script src="./virtual_directives_tab.js"></script>
<template>
<div class="setting-item list-editor variables-editor">
<label
class="list-select-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.label') }}
{{ ' ' }}
</label>
<Select
id="variables-selector"
v-model="selectedVirtualDirectiveId"
class="list-select"
size="20"
>
<option
v-for="(p, index) in modelValue"
:key="p.name"
:value="index"
>
{{ p.name }}
</option>
</Select>
<SelectMotion
class="list-select-movement"
:model-value="modelValue"
@update:modelValue="e => emit('update:modelValue', e)"
:selected-id="selectedVirtualDirectiveId"
@update:selectedId="e => selectedVirtualDirectiveId = e"
:get-add-value="getNewVirtualDirective"
/>
<div class="list-edit-area">
<div class="variable-selector">
<label
class="variable-name-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.name_label') }}
{{ ' ' }}
</label>
<input
class="input"
v-model="selectedVirtualDirective.name"
>
<label
class="variable-type-label"
for="variables-selector"
>
{{ $t('settings.style.themes3.editor.variables.type_label') }}
{{ ' ' }}
</label>
<Select
v-model="selectedVirtualDirectiveValType"
>
<option value='shadow'>
{{ $t('settings.style.themes3.editor.variables.type_shadow') }}
</option>
<option value='color'>
{{ $t('settings.style.themes3.editor.variables.type_color') }}
</option>
<option value='generic'>
{{ $t('settings.style.themes3.editor.variables.type_generic') }}
</option>
</Select>
</div>
<ShadowControl
v-if="selectedVirtualDirectiveValType === 'shadow'"
v-model="draftVirtualDirective"
:static-vars="selectedPalette"
:compact="true"
/>
<ColorInput
v-if="selectedVirtualDirectiveValType === 'color'"
v-model="draftVirtualDirective"
:fallback="computeColor(draftVirtualDirective)"
:label="$t('settings.style.themes3.editor.variables.virtual_color')"
:hide-optional-checkbox="true"
/>
</div>
</div>
</template>

View file

@ -351,10 +351,10 @@ const interfaceMod = {
let majorVersionUsed
console.log(
`USER V3 palette: ${userPaletteName}, style: ${userStyleName} `
`USER V3 palette: ${userPaletteName}, style: ${userStyleName} , custom: ${!!userStyleCustomData}`
)
console.log(
`USER V2 name: ${userThemeV2Name}, source: ${userThemeV2Source}, snapshot: ${userThemeV2Snapshot}`
`USER V2 name: ${userThemeV2Name}, source: ${!!userThemeV2Source}, snapshot: ${!!userThemeV2Snapshot}`
)
console.log(`INST V3 palette: ${instancePaletteName}, style: ${instanceStyleName}`)
@ -411,8 +411,8 @@ const interfaceMod = {
let styleDataUsed = null
let styleNameUsed = null
let paletteDataUsed = null
let paletteNameUsed = null
let themeNameUsed = null
// let paletteNameUsed = null
// let themeNameUsed = null
let themeDataUsed = null
const getData = async (resource, index, customData, name) => {
@ -455,7 +455,7 @@ const interfaceMod = {
userPaletteCustomData,
userPaletteName || instancePaletteName
)
paletteNameUsed = palette.nameUsed
// paletteNameUsed = palette.nameUsed
paletteDataUsed = palette.dataUsed
if (Array.isArray(paletteDataUsed)) {
const [
@ -471,9 +471,8 @@ const interfaceMod = {
] = paletteDataUsed
paletteDataUsed = { name, background, foreground, text, link, cRed, cBlue, cGreen, cOrange }
}
console.log('PAL', userPaletteName, paletteNameUsed)
console.log('PAL', paletteDataUsed)
console.log('USCD', userStyleCustomData)
const style = await getData(
'style',
stylesIndex,
@ -489,15 +488,13 @@ const interfaceMod = {
userThemeV2Source || userThemeV2Snapshot,
userThemeV2Name || instanceThemeV2Name
)
themeNameUsed = theme.nameUsed
// themeNameUsed = theme.nameUsed
themeDataUsed = theme.dataUsed
// Themes v2 editor support
commit('setInstanceOption', { name: 'themeData', value: themeDataUsed })
}
console.log('STYLE', styleNameUsed, paletteNameUsed, themeNameUsed)
// commit('setOption', { name: 'palette', value: paletteNameUsed })
// commit('setOption', { name: 'style', value: styleNameUsed })
// commit('setOption', { name: 'theme', value: themeNameUsed })

View file

@ -173,8 +173,6 @@ export const getEngineChecksum = () => engineChecksum
* @param {boolean} onlyNormalState - only use components 'normal' states, meant for generating theme
* previews since states are the biggest factor for compilation time and are completely unnecessary
* when previewing multiple themes at same time
* @param {string} rootComponentName - [UNTESTED] which component to start from, meant for previewing a
* part of the theme (i.e. just the button) for themes 3 editor.
*/
export const init = ({
inputRuleset,
@ -183,9 +181,9 @@ export const init = ({
liteMode = false,
editMode = false,
onlyNormalState = false,
rootComponentName = 'Root',
initialStaticVars = {}
}) => {
const rootComponentName = 'Root'
if (!inputRuleset) throw new Error('Ruleset is null or undefined!')
const staticVars = { ...initialStaticVars }
const stacked = {}