Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3
This commit is contained in:
commit
a023c44bee
9 changed files with 435 additions and 368 deletions
|
@ -5,6 +5,10 @@
|
|||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.opt {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
&-field.input {
|
||||
display: inline-flex;
|
||||
flex: 0 0 0;
|
||||
|
|
|
@ -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}`
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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) {
|
||||
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 paletteRule = computed(() => {
|
||||
const { name, ...rest } = selectedPalette.value
|
||||
const paletteRule = {
|
||||
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 = {
|
||||
const virtualDirectivesRule = computed(() => ({
|
||||
component: 'Root',
|
||||
directives: Object.fromEntries(
|
||||
virtualDirectives.map(vd => [`--${vd.name}`, `${vd.valType} | ${vd.value}`])
|
||||
virtualDirectives.value.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)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
// ## 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
:model-value="virtualDirectives"
|
||||
@update:modelValue="updateVirtualDirectives"
|
||||
:normalize-shadows="normalizeShadows"
|
||||
/>
|
||||
<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>
|
||||
</tab-switcher>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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 })
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
Loading…
Add table
Reference in a new issue