fix shadow control misbehaving in style tab

This commit is contained in:
Henry Jameson 2024-10-19 17:19:54 +03:00
parent f4d29b5d5e
commit d772f6cfeb
7 changed files with 83 additions and 31 deletions

View file

@ -3,6 +3,12 @@
class="ComponentPreview"
:class="{ '-shadow-controls': shadowControl }"
>
<!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->
<component
:is="'style'"
v-html="previewCss"
/>
<!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->
<label
v-show="shadowControl"
class="header"
@ -11,7 +17,7 @@
{{ $t('settings.style.shadows.offset') }}
</label>
<input
v-show="shadowControl"
v-show="shadowControl && !hideControls"
:value="shadow?.y"
:disabled="disabled"
:class="{ disabled }"
@ -20,7 +26,7 @@
@input="e => updateProperty('y', e.target.value)"
>
<input
v-show="shadowControl"
v-show="shadowControl && !hideControls"
:value="shadow?.y"
:disabled="disabled"
:class="{ disabled }"
@ -41,9 +47,14 @@
>
{{ $t('settings.style.themes3.editor.test_string') }}
</div>
<div v-if="invalid" class="invalid-container">
<div class="alert error invalid-label">
{{ $t('settings.style.themes3.editor.invalid') }}
</div>
</div>
</div>
<input
v-show="shadowControl"
v-show="shadowControl && !hideControls"
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
@ -52,7 +63,7 @@
@input="e => updateProperty('x', e.target.value)"
>
<input
v-show="shadowControl"
v-show="shadowControl && !hideControls"
:value="shadow?.x"
:disabled="disabled"
:class="{ disabled }"
@ -85,7 +96,9 @@ export default {
'shadowControl',
'previewClass',
'previewStyle',
'disabled'
'previewCss',
'disabled',
'invalid'
],
emits: ['update:shadow'],
data () {
@ -93,9 +106,14 @@ export default {
lightGrid: false
}
},
computed: {
hideControls () {
return typeof this.shadow === 'string'
}
},
methods: {
updateProperty (axis, value) {
this.$emit('update:shadow', { axis, value })
this.$emit('update:shadow', { axis, value: Number(value) })
}
}
}
@ -121,6 +139,22 @@ export default {
line-height: 2;
}
.invalid-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: grid;
align-items: center;
justify-items: center;
background-color: rgba(100 0 0 / 50%);
.alert {
padding: 0.5em 1em;
}
}
.input-light-grid {
grid-area: options;
justify-self: center;
@ -170,6 +204,7 @@ export default {
--__grid-color2-disabled: rgba(255 255 255 / 20%);
}
position: relative;
grid-area: preview;
aspect-ratio: 1;
display: flex;

View file

@ -148,6 +148,7 @@
:shadow-control="isShadowTabOpen"
:preview-class="previewClass"
:preview-style="editorHintStyle"
:preview-css="previewCss"
:disabled="!editedSubShadow && typeof editedShadow !== 'string'"
:shadow="editedSubShadow"
@update:shadow="({ axis, value }) => updateSubShadow(axis, value)"
@ -285,7 +286,7 @@
:disabled="!isShadowPresent"
:no-preview="true"
:compact="true"
:compute-color="computeColor"
:static-vars="selectedPalette"
@subShadowSelected="onSubShadow"
/>
</div>
@ -409,7 +410,7 @@
<ShadowControl
v-if="selectedVirtualDirectiveValType === 'shadow'"
v-model="draftVirtualDirective"
:compute-color="computeColor"
:static-vars="selectedPalette"
:compact="true"
/>
<ColorInput

View file

@ -5,9 +5,13 @@ import SelectMotion from 'src/components/select/select_motion.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue'
import ComponentPreview from 'src/components/component_preview/component_preview.vue'
import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js'
import { rgb2hex } from 'src/services/color_convert/color_convert.js'
import { serializeShadow } from 'src/services/theme_data/iss_serializer.js'
import { deserializeShadow } from 'src/services/theme_data/iss_deserializer.js'
import { getCssShadow, getCssShadowFilter } from 'src/services/theme_data/css_utils.js'
import { findShadow, findColor } from 'src/services/theme_data/theme_data_3.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { throttle } from 'lodash'
import { throttle, flattenDeep } from 'lodash'
import {
faTimes,
faChevronDown,
@ -46,13 +50,14 @@ export default {
'separateInset',
'noPreview',
'disabled',
'computeColor',
'staticVars',
'compact'
],
emits: ['update:modelValue', 'subShadowSelected'],
data () {
return {
selectedId: 0
selectedId: 0,
invalid: false
}
},
components: {
@ -97,7 +102,7 @@ export default {
}
},
present () {
return this.selected != null && !this.usingFallback
return this.selected != null && this.modelValue != null
},
shadowsAreNull () {
return this.modelValue == null
@ -105,31 +110,38 @@ export default {
currentFallback () {
return this.fallback?.[this.selectedId]
},
usingFallback () {
return this.modelValue == null
},
getFallback () {
if (typeof this.computeColor === 'function' && this.selected?.color) {
return this.computeColor(this.selected.color)
getColorFallback () {
if (this.staticVars && this.selected?.color) {
const computedColor = findColor(this.selected.color, { dynamicVars: {}, staticVars: this.staticVars }, true)
if (computedColor) return rgb2hex(computedColor)
return null
} else {
return this.currentFallback?.color
}
},
style () {
try {
let result
const serialized = this.cValue.map(x => serializeShadow(x)).join(',')
deserializeShadow(serialized) // validate
const expandedShadow = flattenDeep(findShadow(this.cValue, { dynamicVars: {}, staticVars: this.staticVars }))
const fixedShadows = expandedShadow.map(x => ({ ...x, color: console.log(x) || rgb2hex(x.color) }))
if (this.separateInset) {
return {
filter: getCssShadowFilter(this.cValue),
boxShadow: getCssShadow(this.cValue, true)
result = {
filter: getCssShadowFilter(fixedShadows),
boxShadow: getCssShadow(fixedShadows, true)
}
} else {
result = {
boxShadow: getCssShadow(fixedShadows)
}
}
return {
boxShadow: getCssShadow(this.cValue)
}
this.invalid = false
return result
} catch (e) {
return {
border: '1px solid red'
}
console.error('Invalid shadow', e)
this.invalid = true
}
}
},

View file

@ -5,9 +5,11 @@
>
<ComponentPreview
v-if="!noPreview"
:invalid="invalid"
class="shadow-preview"
:shadow-control="true"
:shadow="selected"
:preview-style="style"
:disabled="disabled || !present"
@update:shadow="({ axis, value }) => updateProperty(axis, value)"
/>
@ -165,7 +167,7 @@
:model-value="selected?.color"
:disabled="disabled || !present"
:label="$t('settings.style.common.color')"
:fallback="getFallback"
:fallback="getColorFallback"
:show-optional-tickbox="false"
name="shadow"
@update:modelValue="e => updateProperty('color', e)"

View file

@ -793,8 +793,10 @@
"text_color": "Text color",
"icon_color": "Icon color",
"link_color": "Link color",
"border_color": "Border color",
"include_in_rule": "Add to rule",
"test_string": "TEST",
"invalid": "Invalid",
"refresh_preview": "Refresh preview",
"apply_preview": "Apply",
"text_auto": {

View file

@ -28,7 +28,7 @@ export const deserializeShadow = string => {
if (string.startsWith('$') || string.startsWith('--')) {
return string
} else {
throw new Error(`Invalid shadow definition: ${string}`)
throw new Error(`Invalid shadow definition: '${string}'`)
}
} else {
const numeric = new Set(['x', 'y', 'blur', 'spread', 'alpha'])

View file

@ -37,7 +37,7 @@ const components = {
ChatMessage: null
}
const findShadow = (shadows, { dynamicVars, staticVars }) => {
export const findShadow = (shadows, { dynamicVars, staticVars }) => {
return (shadows || []).map(shadow => {
let targetShadow
if (typeof shadow === 'string') {