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

This commit is contained in:
Henry Jameson 2024-10-25 16:58:48 +03:00
commit 0562fe1c44
13 changed files with 534 additions and 343 deletions

View file

@ -11,7 +11,7 @@
{{ label }} {{ label }}
</label> </label>
<Checkbox <Checkbox
v-if="typeof fallback !== 'undefined' && showOptionalTickbox" v-if="typeof fallback !== 'undefined' && showOptionalCheckbox && !hideOptionalCheckbox"
:model-value="present" :model-value="present"
:disabled="disabled" :disabled="disabled"
class="opt" class="opt"
@ -112,10 +112,16 @@ export default {
default: false default: false
}, },
// Show "optional" tickbox, for when value might become mandatory // Show "optional" tickbox, for when value might become mandatory
showOptionalTickbox: { showOptionalCheckbox: {
required: false, required: false,
type: Boolean, type: Boolean,
default: true default: true
},
// Force "optional" tickbox to hide
hideOptionalCheckbox: {
required: false,
type: Boolean,
default: false
} }
}, },
emits: ['update:modelValue'], emits: ['update:modelValue'],

View file

@ -11,20 +11,51 @@
<!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component --> <!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->
<label <label
v-show="shadowControl" v-show="shadowControl"
role="heading"
class="header" class="header"
:class="{ faint: disabled }" :class="{ faint: disabled }"
> >
{{ $t('settings.style.shadows.offset') }} {{ $t('settings.style.shadows.offset') }}
</label> </label>
<input <label
v-show="shadowControl && !hideControls" v-show="shadowControl && !hideControls"
class="x-shift-number"
>
{{ $t('settings.style.shadows.offset-x') }}
<input
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
class="input input-number"
type="number"
@input="e => updateProperty('x', e.target.value)"
>
</label>
<label
class="y-shift-number"
v-show="shadowControl && !hideControls"
>
{{ $t('settings.style.shadows.offset-y') }}
<input
:value="shadow?.y" :value="shadow?.y"
:disabled="disabled" :disabled="disabled"
:class="{ disabled }" :class="{ disabled }"
class="input input-number y-shift-number" class="input input-number"
type="number" type="number"
@input="e => updateProperty('y', e.target.value)" @input="e => updateProperty('y', e.target.value)"
> >
</label>
<input
v-show="shadowControl && !hideControls"
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
class="input input-range x-shift-slider"
type="range"
max="20"
min="-20"
@input="e => updateProperty('x', e.target.value)"
>
<input <input
v-show="shadowControl && !hideControls" v-show="shadowControl && !hideControls"
:value="shadow?.y" :value="shadow?.y"
@ -43,7 +74,7 @@
<div <div
class="preview-block" class="preview-block"
:class="previewClass" :class="previewClass"
:style="previewStyle" :style="style"
> >
{{ $t('settings.style.themes3.editor.test_string') }} {{ $t('settings.style.themes3.editor.test_string') }}
</div> </div>
@ -53,43 +84,42 @@
</div> </div>
</div> </div>
</div> </div>
<input <div class="assists">
v-show="shadowControl && !hideControls"
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
class="input input-number x-shift-number"
type="number"
@input="e => updateProperty('x', e.target.value)"
>
<input
v-show="shadowControl && !hideControls"
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
class="input input-range x-shift-slider"
type="range"
max="20"
min="-20"
@input="e => updateProperty('x', e.target.value)"
>
<Checkbox <Checkbox
id="lightGrid"
v-model="lightGrid" v-model="lightGrid"
name="lightGrid" name="lightGrid"
class="input-light-grid" class="input-light-grid"
> >
{{ $t('settings.style.shadows.light_grid') }} {{ $t('settings.style.shadows.light_grid') }}
</Checkbox> </Checkbox>
<div class="style-control">
<label class="label">
{{ $t('settings.style.shadows.zoom') }}
</label>
<input
v-model="zoom"
class="input input-number y-shift-number"
type="number"
>
</div>
<ColorInput
class="input-color-input"
v-model="colorOverride"
fallback="#606060"
:label="$t('settings.style.shadows.color_override')"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import ColorInput from 'src/components/color_input/color_input.vue'
export default { export default {
components: { components: {
Checkbox Checkbox,
ColorInput
}, },
props: [ props: [
'shadow', 'shadow',
@ -103,10 +133,21 @@ export default {
emits: ['update:shadow'], emits: ['update:shadow'],
data () { data () {
return { return {
lightGrid: false colorOverride: null,
lightGrid: false,
zoom: 100
} }
}, },
computed: { computed: {
style () {
console.log(this.previewStyle)
const result = [
this.previewStyle,
`zoom: ${this.zoom / 100}`
]
if (this.colorOverride) result.push(`--background: ${this.colorOverride}`)
return result
},
hideControls () { hideControls () {
return typeof this.shadow === 'string' return typeof this.shadow === 'string'
} }
@ -121,16 +162,27 @@ export default {
<style lang="scss"> <style lang="scss">
.ComponentPreview { .ComponentPreview {
display: grid; display: grid;
grid-template-columns: 3em 1fr 3em; grid-template-columns: 1em 1fr 1fr 1em;
grid-template-rows: 2em 1fr 2em; grid-template-rows: 2em 1fr 1fr 1fr 1em 2em max-content;
grid-template-areas: grid-template-areas:
". header y-num " "header header header header "
". preview y-slide" "preview preview preview y-slide"
"x-num x-slide . " "preview preview preview y-slide"
"options options options"; "preview preview preview y-slide"
"x-slide x-slide x-slide . "
"x-num x-num y-num y-num "
"assists assists assists assists";
grid-gap: 0.5em; grid-gap: 0.5em;
max-width: 25em;
max-height: 25em; &:not(.-shadow-controls) {
grid-template-areas:
"header header header header "
"preview preview preview y-slide"
"preview preview preview y-slide"
"preview preview preview y-slide"
"assists assists assists assists";
grid-template-rows: 2em 1fr 1fr 1fr max-content;
}
.header { .header {
grid-area: header; grid-area: header;
@ -155,8 +207,15 @@ export default {
} }
} }
.assists {
grid-area: assists;
display: grid;
grid-auto-flow: rows;
grid-auto-rows: 2em;
grid-gap: 0.5em;
}
.input-light-grid { .input-light-grid {
grid-area: options;
justify-self: center; justify-self: center;
} }
@ -166,6 +225,19 @@ export default {
.x-shift-number { .x-shift-number {
grid-area: x-num; grid-area: x-num;
justify-self: right;
}
.y-shift-number {
grid-area: y-num;
justify-self: left;
}
.x-shift-number,
.y-shift-number {
input {
max-width: 4em;
}
} }
.x-shift-slider { .x-shift-slider {
@ -175,10 +247,6 @@ export default {
min-width: 10em; min-width: 10em;
} }
.y-shift-number {
grid-area: y-num;
}
.y-shift-slider { .y-shift-slider {
grid-area: y-slide; grid-area: y-slide;
writing-mode: vertical-lr; writing-mode: vertical-lr;

View file

@ -3,39 +3,44 @@
v-if="contrast" v-if="contrast"
class="contrast-ratio" class="contrast-ratio"
> >
<span <span v-if="showRatio">
:title="hint" {{ contrast.text }}
</span>
<Tooltip
:text="hint"
class="rating" class="rating"
> >
<span v-if="contrast.aaa"> <span v-if="contrast.aaa">
<FAIcon icon="thumbs-up" /> <FAIcon icon="thumbs-up" :size="showRatio ? 'lg' : ''" />
</span> </span>
<span v-if="!contrast.aaa && contrast.aa"> <span v-if="!contrast.aaa && contrast.aa">
<FAIcon icon="adjust" /> <FAIcon icon="adjust" :size="showRatio ? 'lg' : ''" />
</span> </span>
<span v-if="!contrast.aaa && !contrast.aa"> <span v-if="!contrast.aaa && !contrast.aa">
<FAIcon icon="exclamation-triangle" /> <FAIcon icon="exclamation-triangle" :size="showRatio ? 'lg' : ''" />
</span> </span>
</span> </Tooltip>
<span <Tooltip
v-if="contrast && large" v-if="contrast && large"
:text="hint_18pt"
class="rating" class="rating"
:title="hint_18pt"
> >
<span v-if="contrast.laaa"> <span v-if="contrast.laaa">
<FAIcon icon="thumbs-up" /> <FAIcon icon="thumbs-up" :size="showRatio ? 'large' : ''" />
</span> </span>
<span v-if="!contrast.laaa && contrast.laa"> <span v-if="!contrast.laaa && contrast.laa">
<FAIcon icon="adjust" /> <FAIcon icon="adjust" :size="showRatio ? 'lg' : ''" />
</span> </span>
<span v-if="!contrast.laaa && !contrast.laa"> <span v-if="!contrast.laaa && !contrast.laa">
<FAIcon icon="exclamation-triangle" /> <FAIcon icon="exclamation-triangle" :size="showRatio ? 'lg' : ''" />
</span>
</span> </span>
</Tooltip>
</span> </span>
</template> </template>
<script> <script>
import Tooltip from 'src/components/tooltip/tooltip.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faAdjust, faAdjust,
@ -62,8 +67,16 @@ export default {
required: false, required: false,
type: Object, type: Object,
default: () => ({}) default: () => ({})
},
showRatio: {
required: false,
type: Boolean,
default: false
} }
}, },
components: {
Tooltip
},
computed: { computed: {
hint () { hint () {
const levelVal = this.contrast.aaa ? 'aaa' : (this.contrast.aa ? 'aa' : 'bad') const levelVal = this.contrast.aaa ? 'aaa' : (this.contrast.aa ? 'aa' : 'bad')
@ -87,8 +100,7 @@ export default {
.contrast-ratio { .contrast-ratio {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-top: -4px; align-items: baseline;
margin-bottom: 5px;
.label { .label {
margin-right: 1em; margin-right: 1em;
@ -96,7 +108,6 @@ export default {
.rating { .rating {
display: inline-block; display: inline-block;
text-align: center;
margin-left: 0.5em; margin-left: 0.5em;
} }
} }

View file

@ -75,9 +75,17 @@ const paletteKeys = [
'cBlue', 'cBlue',
'cGreen', 'cGreen',
'cOrange', 'cOrange',
'wallpaper',
'extra1', 'extra1',
'extra2', 'extra2',
'extra3' 'extra3',
'extra4',
'extra5',
'extra6',
'extra7',
'extra8',
'extra9',
'extra10'
] ]
const fallback = (key) => { const fallback = (key) => {
@ -88,6 +96,9 @@ const fallback = (key) => {
return props.modelValue.accent return props.modelValue.accent
} }
if (key.startsWith('extra')) { if (key.startsWith('extra')) {
return '#FF00FF'
}
if (key.startsWith('wallpaper')) {
return '#008080' return '#008080'
} }
} }
@ -105,7 +116,7 @@ const updatePalette = (paletteKey, value) => {
display: grid; display: grid;
justify-content: space-around; justify-content: space-around;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr) auto; grid-template-rows: repeat(5, 1fr) auto;
grid-gap: 0.5em; grid-gap: 0.5em;
align-items: baseline; align-items: baseline;

View file

@ -340,9 +340,7 @@ export default {
exports.editedBorderColor = getEditedElement('Border', 'textColor') exports.editedBorderColor = getEditedElement('Border', 'textColor')
exports.isBorderColorPresent = isElementPresent('Border', 'textColor', '#909090') exports.isBorderColorPresent = isElementPresent('Border', 'textColor', '#909090')
// TODO this is VERY primitive right now, need to make it const getContrast = (bg, text) => {
// support variables, fallbacks etc.
exports.getContrast = (bg, text) => {
try { try {
const bgRgb = hex2rgb(bg) const bgRgb = hex2rgb(bg)
const textRgb = hex2rgb(text) const textRgb = hex2rgb(text)
@ -464,6 +462,24 @@ export default {
return null 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 editorFriendlyToOriginal = computed(() => {
const resultRules = [] const resultRules = []
@ -600,16 +616,23 @@ export default {
return virtualDirectives[selectedVirtualDirectiveId.value].valType return virtualDirectives[selectedVirtualDirectiveId.value].valType
}, },
set (value) { set (value) {
virtualDirectives[selectedVirtualDirectiveId.value].valType = value const newValType = value
let newValue
switch (value) { switch (value) {
case 'shadow': case 'shadow':
virtualDirectives[selectedVirtualDirectiveId.value].value = '0 0 0 #000000' newValue = '0 0 0 #000000 / 1'
break break
case 'color': case 'color':
virtualDirectives[selectedVirtualDirectiveId.value].value = '#000000' newValue = '#000000'
break break
default: default:
virtualDirectives[selectedVirtualDirectiveId.value].value = 'none' newValue = 'none'
}
const newName = virtualDirectives[selectedVirtualDirectiveId.value].name
virtualDirectives[selectedVirtualDirectiveId.value] = {
name: newName,
value: newValue,
valType: newValType
} }
} }
}) })
@ -664,6 +687,14 @@ export default {
{ immediate: true } { immediate: true }
) )
const virtualDirectivesOut = computed(() => {
return [
'Root {',
...virtualDirectives.map(vd => ` --${vd.name}: ${vd.valType} | ${vd.value};`),
'}'
].join('\n')
})
exports.getNewVirtualDirective = () => ({ exports.getNewVirtualDirective = () => ({
name: 'newDirective', name: 'newDirective',
valType: 'generic', valType: 'generic',
@ -678,6 +709,13 @@ export default {
return null return null
} }
exports.contrast = computed(() => {
return getContrast(
exports.computeColor(previewColors.value.background),
exports.computeColor(previewColors.value.text)
)
})
const overallPreviewRules = ref() const overallPreviewRules = ref()
exports.overallPreviewRules = overallPreviewRules exports.overallPreviewRules = overallPreviewRules
exports.updateOverallPreview = () => { exports.updateOverallPreview = () => {
@ -694,10 +732,18 @@ export default {
.reduce((acc, [k, v]) => ({ ...acc, [k]: `color | ${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({ const rules = init({
inputRuleset: [ inputRuleset: [
...editorFriendlyToOriginal.value, paletteRule,
paletteRule virtualDirectivesRule,
...editorFriendlyToOriginal.value
], ],
ultimateBackgroundColor: '#000000', ultimateBackgroundColor: '#000000',
liteMode: true, liteMode: true,
@ -726,7 +772,8 @@ export default {
parser: (string) => deserialize(string), parser: (string) => deserialize(string),
onImport (parsed, filename) { onImport (parsed, filename) {
const editorComponents = parsed.filter(x => x.component.startsWith('@')) const editorComponents = parsed.filter(x => x.component.startsWith('@'))
const rules = parsed.filter(x => !x.component.startsWith('@')) const rootComponent = parsed.find(x => x.component === 'Root')
const rules = parsed.filter(x => !x.component.startsWith('@') && x.component !== 'Root')
const metaIn = editorComponents.find(x => x.component === '@meta').directives const metaIn = editorComponents.find(x => x.component === '@meta').directives
const palettesIn = editorComponents.filter(x => x.component === '@palette') const palettesIn = editorComponents.filter(x => x.component === '@palette')
@ -735,8 +782,16 @@ export default {
exports.author.value = metaIn.author exports.author.value = metaIn.author
exports.website.value = metaIn.website 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)
onPalettesUpdate(palettesIn.map(x => ({ name: x.variant, ...x.directives }))) onPalettesUpdate(palettesIn.map(x => ({ name: x.variant, ...x.directives })))
console.log('PALETTES', palettesIn)
Object.keys(allEditedRules).forEach((k) => delete allEditedRules[k]) Object.keys(allEditedRules).forEach((k) => delete allEditedRules[k])
@ -753,6 +808,7 @@ export default {
return [ return [
metaOut.value, metaOut.value,
palettesOut.value, palettesOut.value,
virtualDirectivesOut.value,
serialize(editorFriendlyToOriginal.value) serialize(editorFriendlyToOriginal.value)
].join('\n\n') ].join('\n\n')
}) })

View file

@ -166,27 +166,21 @@
> >
<ColorInput <ColorInput
v-model="editedBackgroundColor" v-model="editedBackgroundColor"
:fallback="computeColor(editedBackgroundColor)" :fallback="computeColor(editedBackgroundColor) ?? previewColors.background"
:disabled="!isBackgroundColorPresent" :disabled="!isBackgroundColorPresent"
:label="$t('settings.style.themes3.editor.background')" :label="$t('settings.style.themes3.editor.background')"
:hide-optional-checkbox="true"
/> />
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')"> <Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isBackgroundColorPresent" /> <Checkbox v-model="isBackgroundColorPresent" />
</Tooltip> </Tooltip>
<OpacityInput
v-model="editedOpacity"
:disabled="!isOpacityPresent"
:label="$t('settings.style.themes3.editor.opacity')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isOpacityPresent" />
</Tooltip>
<ColorInput <ColorInput
v-if="componentHas('Text')" v-if="componentHas('Text')"
v-model="editedTextColor" v-model="editedTextColor"
:fallback="computeColor(editedTextColor)" :fallback="computeColor(editedTextColor) ?? previewColors.text"
:label="$t('settings.style.themes3.editor.text_color')" :label="$t('settings.style.themes3.editor.text_color')"
:disabled="!isTextColorPresent" :disabled="!isTextColorPresent"
:hide-optional-checkbox="true"
/> />
<Tooltip <Tooltip
v-if="componentHas('Text')" v-if="componentHas('Text')"
@ -194,7 +188,10 @@
> >
<Checkbox v-model="isTextColorPresent" /> <Checkbox v-model="isTextColorPresent" />
</Tooltip> </Tooltip>
<div class="style-control suboption"> <div
v-if="componentHas('Text')"
class="style-control suboption"
>
<label <label
for="textAuto" for="textAuto"
class="label" class="label"
@ -224,18 +221,27 @@
> >
<Checkbox v-model="isTextAutoPresent" /> <Checkbox v-model="isTextAutoPresent" />
</Tooltip> </Tooltip>
<div> <div
<ContrastRatio :contrast="getContrast(editedBackgroundColor, editedTextColor)" /> class="style-control suboption"
v-if="componentHas('Text')"
>
<label class="label">
{{$t('settings.style.themes3.editor.contrast') }}
</label>
<ContrastRatio
:show-ratio="true"
:contrast="contrast"
/>
</div> </div>
<div> <div v-if="componentHas('Text')">
<!-- spacer for missing checkbox -->
</div> </div>
<ColorInput <ColorInput
v-if="componentHas('Link')" v-if="componentHas('Link')"
v-model="editedLinkColor" v-model="editedLinkColor"
:fallback="computeColor(editedLinkColor)" :fallback="computeColor(editedLinkColor) ?? previewColors.link"
:label="$t('settings.style.themes3.editor.link_color')" :label="$t('settings.style.themes3.editor.link_color')"
:disabled="!isLinkColorPresent" :disabled="!isLinkColorPresent"
:hide-optional-checkbox="true"
/> />
<Tooltip <Tooltip
v-if="componentHas('Link')" v-if="componentHas('Link')"
@ -246,9 +252,10 @@
<ColorInput <ColorInput
v-if="componentHas('Icon')" v-if="componentHas('Icon')"
v-model="editedIconColor" v-model="editedIconColor"
:fallback="computeColor(editedIconColor)" :fallback="computeColor(editedIconColor) ?? previewColors.icon"
:label="$t('settings.style.themes3.editor.icon_color')" :label="$t('settings.style.themes3.editor.icon_color')"
:disabled="!isIconColorPresent" :disabled="!isIconColorPresent"
:hide-optional-checkbox="true"
/> />
<Tooltip <Tooltip
v-if="componentHas('Icon')" v-if="componentHas('Icon')"
@ -259,9 +266,10 @@
<ColorInput <ColorInput
v-if="componentHas('Border')" v-if="componentHas('Border')"
v-model="editedBorderColor" v-model="editedBorderColor"
:fallback="computeColor(editedBorderColor)" :fallback="computeColor(editedBorderColor) ?? previewColors.border"
:label="$t('settings.style.themes3.editor.Border_color')" :label="$t('settings.style.themes3.editor.border_color')"
:disabled="!isBorderColorPresent" :disabled="!isBorderColorPresent"
:hide-optional-checkbox="true"
/> />
<Tooltip <Tooltip
v-if="componentHas('Border')" v-if="componentHas('Border')"
@ -269,6 +277,14 @@
> >
<Checkbox v-model="isBorderColorPresent" /> <Checkbox v-model="isBorderColorPresent" />
</Tooltip> </Tooltip>
<OpacityInput
v-model="editedOpacity"
:disabled="!isOpacityPresent"
:label="$t('settings.style.themes3.editor.opacity')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isOpacityPresent" />
</Tooltip>
</div> </div>
<div <div
key="shadow" key="shadow"
@ -418,6 +434,7 @@
v-model="draftVirtualDirective" v-model="draftVirtualDirective"
:fallback="computeColor(draftVirtualDirective)" :fallback="computeColor(draftVirtualDirective)"
:label="$t('settings.style.themes3.editor.variables.virtual_color')" :label="$t('settings.style.themes3.editor.variables.virtual_color')"
:hide-optional-checkbox="true"
/> />
</div> </div>
</div> </div>

View file

@ -187,14 +187,14 @@
name="accentColor" name="accentColor"
:fallback="previewTheme.colors?.link" :fallback="previewTheme.colors?.link"
:label="$t('settings.accent')" :label="$t('settings.accent')"
:show-optional-tickbox="typeof linkColorLocal !== 'undefined'" :show-optional-checkbox="typeof linkColorLocal !== 'undefined'"
/> />
<ColorInput <ColorInput
v-model="linkColorLocal" v-model="linkColorLocal"
name="linkColor" name="linkColor"
:fallback="previewTheme.colors?.accent" :fallback="previewTheme.colors?.accent"
:label="$t('settings.links')" :label="$t('settings.links')"
:show-optional-tickbox="typeof accentColorLocal !== 'undefined'" :show-optional-checkbox="typeof accentColorLocal !== 'undefined'"
/> />
<ContrastRatio :contrast="previewContrast.bgLink" /> <ContrastRatio :contrast="previewContrast.bgLink" />
</div> </div>

View file

@ -123,7 +123,7 @@ export default {
try { try {
let result let result
const serialized = this.cValue.map(x => serializeShadow(x)).join(',') const serialized = this.cValue.map(x => serializeShadow(x)).join(',')
deserializeShadow(serialized) // validate serialized.split(/,/).map(deserializeShadow) // validate
const expandedShadow = flattenDeep(findShadow(this.cValue, { dynamicVars: {}, staticVars: this.staticVars })) const expandedShadow = flattenDeep(findShadow(this.cValue, { dynamicVars: {}, staticVars: this.staticVars }))
const fixedShadows = expandedShadow.map(x => ({ ...x, color: console.log(x) || rgb2hex(x.color) })) const fixedShadows = expandedShadow.map(x => ({ ...x, color: console.log(x) || rgb2hex(x.color) }))

View file

@ -168,7 +168,7 @@
:disabled="disabled || !present" :disabled="disabled || !present"
:label="$t('settings.style.common.color')" :label="$t('settings.style.common.color')"
:fallback="getColorFallback" :fallback="getColorFallback"
:show-optional-tickbox="false" :show-optional-checkbox="false"
name="shadow" name="shadow"
@update:modelValue="e => updateProperty('color', e)" @update:modelValue="e => updateProperty('color', e)"
/> />

View file

@ -770,9 +770,17 @@
"cBlue": "Blue color", "cBlue": "Blue color",
"cGreen": "Green color", "cGreen": "Green color",
"cOrange": "Orange color", "cOrange": "Orange color",
"wallpaper": "Wallpaper",
"extra1": "Extra 1", "extra1": "Extra 1",
"extra2": "Extra 2", "extra2": "Extra 2",
"extra3": "Extra 3", "extra3": "Extra 3",
"extra4": "Extra 4",
"extra5": "Extra 5",
"extra6": "Extra 6",
"extra7": "Extra 7",
"extra8": "Extra 8",
"extra9": "Extra 9",
"extra10": "Extra 10",
"v2_unsupported": "Older v2 themes don't support palettes. Switch to v3 theme to make use of palettes" "v2_unsupported": "Older v2 themes don't support palettes. Switch to v3 theme to make use of palettes"
}, },
"editor": { "editor": {
@ -793,6 +801,7 @@
"text_color": "Text color", "text_color": "Text color",
"icon_color": "Icon color", "icon_color": "Icon color",
"link_color": "Link color", "link_color": "Link color",
"contrast": "Text contrast",
"border_color": "Border color", "border_color": "Border color",
"include_in_rule": "Add to rule", "include_in_rule": "Add to rule",
"test_string": "TEST", "test_string": "TEST",
@ -940,7 +949,11 @@
"override": "Override", "override": "Override",
"shadow_id": "Shadow #{value}", "shadow_id": "Shadow #{value}",
"offset": "Shadow offset", "offset": "Shadow offset",
"zoom": "Zoom",
"offset-x": "x:",
"offset-y": "y:",
"light_grid": "Use light checkerboard", "light_grid": "Use light checkerboard",
"color_override": "Use different color",
"name": "Name", "name": "Name",
"blur": "Blur", "blur": "Blur",
"spread": "Spread", "spread": "Spread",

View file

@ -15,7 +15,7 @@ export const deserializeShadow = string => {
// spread (optional) // spread (optional)
'(?:(-?[0-9]+(?:\\.[0-9]+)?)\\s+)?', '(?:(-?[0-9]+(?:\\.[0-9]+)?)\\s+)?',
// either hex, variable or function // either hex, variable or function
'(#[0-9a-f]{6}|--[a-z\\-_]+|\\$[a-z\\-()_]+)', '(#[0-9a-f]{6}|--[a-z0-9\\-_]+|\\$[a-z0-9\\-()_]+)',
// opacity (optional) // opacity (optional)
'(?:\\s+\\/\\s+([0-9]+(?:\\.[0-9]+)?)\\s*)?', '(?:\\s+\\/\\s+([0-9]+(?:\\.[0-9]+)?)\\s*)?',
// name // name

View file

@ -354,10 +354,6 @@ export const convertTheme2To3 = (data) => {
newRules.push({ ...rule, state: ['toggled'] }) newRules.push({ ...rule, state: ['toggled'] })
newRules.push({ ...rule, state: ['toggled', 'focus'] }) newRules.push({ ...rule, state: ['toggled', 'focus'] })
newRules.push({ ...rule, state: ['pressed', 'focus'] }) newRules.push({ ...rule, state: ['pressed', 'focus'] })
}
if (key === 'buttonHover') {
newRules.push({ ...rule, state: ['toggled', 'hover'] })
newRules.push({ ...rule, state: ['pressed', 'hover'] })
newRules.push({ ...rule, state: ['toggled', 'focus', 'hover'] }) newRules.push({ ...rule, state: ['toggled', 'focus', 'hover'] })
newRules.push({ ...rule, state: ['pressed', 'focus', 'hover'] }) newRules.push({ ...rule, state: ['pressed', 'focus', 'hover'] })
} }

View file

@ -63,6 +63,7 @@ export const findShadow = (shadows, { dynamicVars, staticVars }) => {
} }
export const findColor = (color, { dynamicVars, staticVars }) => { export const findColor = (color, { dynamicVars, staticVars }) => {
try {
if (typeof color !== 'string' || (!color.startsWith('--') && !color.startsWith('$'))) return color if (typeof color !== 'string' || (!color.startsWith('--') && !color.startsWith('$'))) return color
let targetColor = null let targetColor = null
if (color.startsWith('--')) { if (color.startsWith('--')) {
@ -111,6 +112,13 @@ export const findColor = (color, { dynamicVars, staticVars }) => {
} }
// Color references other color // Color references other color
return targetColor return targetColor
} catch (e) {
throw new Error(`Couldn't find color "${color}", variables are:
Static:
${JSON.stringify(staticVars, null, 2)}
Dynamic:
${JSON.stringify(dynamicVars, null, 2)}`)
}
} }
const getTextColorAlpha = (directives, intendedTextColor, dynamicVars, staticVars) => { const getTextColorAlpha = (directives, intendedTextColor, dynamicVars, staticVars) => {
@ -241,6 +249,7 @@ export const init = ({
const nonEditableComponents = new Set(Object.values(components).filter(c => c.notEditable).map(c => c.name)) const nonEditableComponents = new Set(Object.values(components).filter(c => c.notEditable).map(c => c.name))
const processCombination = (combination) => { const processCombination = (combination) => {
try {
const selector = ruleToSelector(combination, true) const selector = ruleToSelector(combination, true)
const cssSelector = ruleToSelector(combination) const cssSelector = ruleToSelector(combination)
@ -448,6 +457,10 @@ export const init = ({
return rule return rule
} }
} catch (e) {
const { component, variant, state } = combination
throw new Error(`Error processing combination ${component}.${variant}:${state.join(':')}: ${e}`)
}
} }
const processInnerComponent = (component, parent) => { const processInnerComponent = (component, parent) => {