moved the select motion stuff into its own component

This commit is contained in:
Henry Jameson 2024-10-04 02:49:20 +03:00
parent c937736fea
commit 3d77860e57
4 changed files with 356 additions and 291 deletions

View file

@ -0,0 +1,115 @@
<template>
<div
class="SelectMotion btn-group"
>
<button
class="btn button-default"
:disabled="disabled || shadowsAreNull"
@click="add"
>
<FAIcon
fixed-width
icon="plus"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !moveUpValid"
:class="{ disabled: disabled || !moveUpValid }"
@click="moveUp"
>
<FAIcon
fixed-width
icon="chevron-up"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !moveDnValid"
:class="{ disabled: disabled || !moveDnValid }"
@click="moveDn"
>
<FAIcon
fixed-width
icon="chevron-down"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !present"
:class="{ disabled: disabled || !present }"
@click="del"
>
<FAIcon
fixed-width
icon="times"
/>
</button>
</div>
</template>
<script setup>
import { computed, defineEmits, defineProps } from 'vue'
const props = defineProps(['modelValue', 'selectedId', 'disabled', 'getAddValue'])
const emit = defineEmits(['update:modelValue', 'update:selectedId'])
const moveUpValid = computed(() => {
return props.selectedId > 0
})
const present = computed(() => props.modelValue[props.selectedId] != null)
const moveUp = () => {
const newModel = [...props.modelValue]
const movable = newModel.splice(props.selectedId, 1)[0]
newModel.splice(props.selectedId - 1, 0, movable)
emit('update:modelValue', newModel)
emit('update:selectedId', props.selectedId - 1)
}
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]
newModel.splice(props.selectedId + 1, 0, movable)
emit('update:modelValue', newModel)
emit('update:selectedId', props.selectedId + 1)
}
const add = () => {
const newModel = [...props.modelValue]
newModel.push(props.getAddValue())
console.log(newModel)
emit('update:modelValue', newModel)
emit('update:selectedId', Math.max(newModel.length - 1, 0))
}
const del = () => {
const newModel = [...props.modelValue]
newModel.splice(props.selectedId, 1)
emit('update:modelValue', newModel)
emit('update:selectedId', newModel.length === 0 ? undefined : Math.max(props.selectedId - 1, 0))
}
</script>
<style lang="scss">
.SelectMotion {
flex: 0 0 auto;
display: grid;
grid-auto-columns: 1fr;
grid-auto-flow: column;
margin-top: 0.25em;
.button-default {
margin: 0;
padding: 0;
}
}
</style>

View file

@ -51,231 +51,241 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="setting-item component-editor"> <tab-switcher>
<div class="component-selector">
<label for="component-selector">
{{ $t('settings.style.themes3.editor.component_selector') }}
{{ ' ' }}
</label>
<Select
id="component-selector"
v-model="selectedComponentKey"
>
<option
v-for="key in componentKeys"
:key="'component-' + key"
:value="key"
>
{{ fallbackI18n($t(getFriendlyNamePath(componentsMap.get(key).name)), componentsMap.get(key).name) }}
</option>
</Select>
</div>
<div <div
v-if="selectedComponentVariantsAll.length > 1" class="setting-item component-editor"
class="variant-selector" key="component"
:label="$t('settings.style.themes3.editor.component_tab')"
> >
<label for="variant-selector"> <div class="component-selector">
{{ $t('settings.style.themes3.editor.variant_selector') }} <label for="component-selector">
</label> {{ $t('settings.style.themes3.editor.component_selector') }}
<Select {{ ' ' }}
v-model="selectedVariant" </label>
> <Select
<option id="component-selector"
v-for="variant in selectedComponentVariantsAll" v-model="selectedComponentKey"
:key="'component-variant-' + variant"
:value="variant"
> >
{{ fallbackI18n($t(getVariantPath(selectedComponentName, variant)), variant) }} <option
</option> v-for="key in componentKeys"
</Select> :key="'component-' + key"
</div> :value="key"
<div >
v-if="selectedComponentStates.length > 0" {{ fallbackI18n($t(getFriendlyNamePath(componentsMap.get(key).name)), componentsMap.get(key).name) }}
class="state-selector" </option>
> </Select>
<label> </div>
{{ $t('settings.style.themes3.editor.states_selector') }} <div
</label> v-if="selectedComponentVariantsAll.length > 1"
<ul class="variant-selector"
class="state-selector-list"
> >
<li <label for="variant-selector">
v-for="state in selectedComponentStates" {{ $t('settings.style.themes3.editor.variant_selector') }}
:key="'component-state-' + state" </label>
<Select
v-model="selectedVariant"
>
<option
v-for="variant in selectedComponentVariantsAll"
:key="'component-variant-' + variant"
:value="variant"
>
{{ fallbackI18n($t(getVariantPath(selectedComponentName, variant)), variant) }}
</option>
</Select>
</div>
<div
v-if="selectedComponentStates.length > 0"
class="state-selector"
>
<label>
{{ $t('settings.style.themes3.editor.states_selector') }}
</label>
<ul
class="state-selector-list"
>
<li
v-for="state in selectedComponentStates"
:key="'component-state-' + state"
>
<Checkbox
:value="selectedState.has(state)"
@update:modelValue="(v) => updateSelectedStates(state, v)"
>
{{ fallbackI18n($t(getStatePath(selectedComponentName, state)), state) }}
</Checkbox>
</li>
</ul>
</div>
<div class="preview-container">
<!-- 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 -->
<ComponentPreview
class="component-preview"
:show-text="componentHas('Text')"
:shadow-control="isShadowTabOpen"
:preview-class="previewClass"
:preview-style="editorHintStyle"
:disabled="!editedSubShadow && typeof editedShadow !== 'string'"
:shadow="editedSubShadow"
@update:shadow="({ axis, value }) => updateSubShadow(axis, value)"
/>
</div>
<tab-switcher
ref="tabSwitcher"
class="component-settings"
:on-switch="onTabSwitch"
>
<div
key="main"
class="editor-tab"
:label="$t('settings.style.themes3.editor.main_tab')"
>
<ColorInput
v-model="editedBackgroundColor"
:disabled="!isBackgroundColorPresent"
:label="$t('settings.style.themes3.editor.background')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isBackgroundColorPresent" />
</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
v-if="componentHas('Text')"
v-model="editedTextColor"
:label="$t('settings.style.themes3.editor.text_color')"
:disabled="!isTextColorPresent"
/>
<Tooltip
v-if="componentHas('Text')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isTextColorPresent" />
</Tooltip>
<div class="style-control suboption">
<label
for="textAuto"
class="label"
:class="{ faint: !isTextAutoPresent }"
>
{{ $t('settings.style.themes3.editor.text_auto.label') }}
</label>
<Select
id="textAuto"
v-model="editedTextAuto"
:disabled="!isTextAutoPresent"
>
<option value="no-preserve">
{{ $t('settings.style.themes3.editor.text_auto.no-preserve') }}
</option>
<option value="no-auto">
{{ $t('settings.style.themes3.editor.text_auto.no-auto') }}
</option>
<option value="preserve">
{{ $t('settings.style.themes3.editor.text_auto.preserve') }}
</option>
</Select>
</div>
<Tooltip
v-if="componentHas('Text')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isTextAutoPresent" />
</Tooltip>
<div>
<ContrastRatio :contrast="getContrast(editedBackgroundColor, editedTextColor)" />
</div>
<div>
<!-- spacer for missing checkbox -->
</div>
<ColorInput
v-if="componentHas('Link')"
v-model="editedLinkColor"
:label="$t('settings.style.themes3.editor.link_color')"
:disabled="!isLinkColorPresent"
/>
<Tooltip
v-if="componentHas('Link')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isLinkColorPresent" />
</Tooltip>
<ColorInput
v-if="componentHas('Icon')"
v-model="editedIconColor"
:label="$t('settings.style.themes3.editor.icon_color')"
:disabled="!isIconColorPresent"
/>
<Tooltip
v-if="componentHas('Icon')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isIconColorPresent" />
</Tooltip>
</div>
<div
key="shadow"
class="editor-tab shadow-tab"
:label="$t('settings.style.themes3.editor.shadows_tab')"
> >
<Checkbox <Checkbox
:value="selectedState.has(state)" v-model="isShadowPresent"
@update:modelValue="(v) => updateSelectedStates(state, v)" class="style-control"
> >
{{ fallbackI18n($t(getStatePath(selectedComponentName, state)), state) }} {{ $t('settings.style.themes3.editor.include_in_rule') }}
</Checkbox> </checkbox>
</li> <ShadowControl
</ul> v-model="editedShadow"
:disabled="!isShadowPresent"
:no-preview="true"
:separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
@subShadowSelected="onSubShadow"
/>
</div>
</tab-switcher>
</div> </div>
<div class="preview-container"> <div
<!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component --> key="palette"
<component :label="$t('settings.style.themes3.editor.palette_tab')"
:is="'style'" class="setting-item palette-editor"
v-html="previewCss"
/>
<!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->
<ComponentPreview
class="component-preview"
:show-text="componentHas('Text')"
:shadow-control="isShadowTabOpen"
:preview-class="previewClass"
:preview-style="editorHintStyle"
:disabled="!editedSubShadow && typeof editedShadow !== 'string'"
:shadow="editedSubShadow"
@update:shadow="({ axis, value }) => updateSubShadow(axis, value)"
/>
</div>
<tab-switcher
ref="tabSwitcher"
class="component-settings"
:on-switch="onTabSwitch"
> >
<div <div class="label">
key="main" <label for="palette-selector">
class="editor-tab" {{ $t('settings.style.themes3.palette.label') }}
:label="$t('settings.style.themes3.editor.main_tab')" {{ ' ' }}
> </label>
<ColorInput <Select
v-model="editedBackgroundColor" id="palette-selector"
:disabled="!isBackgroundColorPresent" v-model="editedPalette"
:label="$t('settings.style.themes3.editor.background')"
/>
<Tooltip :text="$t('settings.style.themes3.editor.include_in_rule')">
<Checkbox v-model="isBackgroundColorPresent" />
</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
v-if="componentHas('Text')"
v-model="editedTextColor"
:label="$t('settings.style.themes3.editor.text_color')"
:disabled="!isTextColorPresent"
/>
<Tooltip
v-if="componentHas('Text')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
> >
<Checkbox v-model="isTextColorPresent" /> <option
</Tooltip> key="dark"
<div class="style-control suboption"> value="dark"
<label
for="textAuto"
class="label"
:class="{ faint: !isTextAutoPresent }"
> >
{{ $t('settings.style.themes3.editor.text_auto.label') }} {{ $t('settings.style.themes3.palette.dark') }}
</label> </option>
<Select <option
id="textAuto" key="light"
v-model="editedTextAuto" value="light"
:disabled="!isTextAutoPresent"
> >
<option value="no-preserve"> {{ $t('settings.style.themes3.palette.light') }}
{{ $t('settings.style.themes3.editor.text_auto.no-preserve') }} </option>
</option> </Select>
<option value="no-auto">
{{ $t('settings.style.themes3.editor.text_auto.no-auto') }}
</option>
<option value="preserve">
{{ $t('settings.style.themes3.editor.text_auto.preserve') }}
</option>
</Select>
</div>
<Tooltip
v-if="componentHas('Text')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isTextAutoPresent" />
</Tooltip>
<div>
<ContrastRatio :contrast="getContrast(editedBackgroundColor, editedTextColor)" />
</div>
<div>
<!-- spacer for missing checkbox -->
</div>
<ColorInput
v-if="componentHas('Link')"
v-model="editedLinkColor"
:label="$t('settings.style.themes3.editor.link_color')"
:disabled="!isLinkColorPresent"
/>
<Tooltip
v-if="componentHas('Link')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isLinkColorPresent" />
</Tooltip>
<ColorInput
v-if="componentHas('Icon')"
v-model="editedIconColor"
:label="$t('settings.style.themes3.editor.icon_color')"
:disabled="!isIconColorPresent"
/>
<Tooltip
v-if="componentHas('Icon')"
:text="$t('settings.style.themes3.editor.include_in_rule')"
>
<Checkbox v-model="isIconColorPresent" />
</Tooltip>
</div> </div>
<div <PaletteEditor v-model="palette" />
key="shadow"
class="editor-tab shadow-tab"
:label="$t('settings.style.themes3.editor.shadows_tab')"
>
<Checkbox
v-model="isShadowPresent"
class="style-control"
>
{{ $t('settings.style.themes3.editor.include_in_rule') }}
</checkbox>
<ShadowControl
v-model="editedShadow"
:disabled="!isShadowPresent"
:no-preview="true"
:separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
@subShadowSelected="onSubShadow"
/>
</div>
</tab-switcher>
</div>
<div class="setting-item palette-editor">
<div class="label">
<label for="palette-selector">
{{ $t('settings.style.themes3.palette.label') }}
{{ ' ' }}
</label>
<Select
id="palette-selector"
v-model="editedPalette"
>
<option
key="dark"
value="dark"
>
{{ $t('settings.style.themes3.palette.dark') }}
</option>
<option
key="light"
value="light"
>
{{ $t('settings.style.themes3.palette.light') }}
</option>
</Select>
</div> </div>
<PaletteEditor v-model="palette" /> </tab-switcher>
</div>
</div> </div>
</template> </template>

View file

@ -1,6 +1,7 @@
import ColorInput from 'src/components/color_input/color_input.vue' import ColorInput from 'src/components/color_input/color_input.vue'
import OpacityInput from 'src/components/opacity_input/opacity_input.vue' import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
import Select from 'src/components/select/select.vue' import Select from 'src/components/select/select.vue'
import SelectMotion from 'src/components/select/select_motion.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue' import Popover from 'src/components/popover/popover.vue'
import ComponentPreview from 'src/components/component_preview/component_preview.vue' import ComponentPreview from 'src/components/component_preview/component_preview.vue'
@ -54,13 +55,11 @@ export default {
ColorInput, ColorInput,
OpacityInput, OpacityInput,
Select, Select,
SelectMotion,
Checkbox, Checkbox,
Popover, Popover,
ComponentPreview ComponentPreview
}, },
beforeUpdate () {
this.cValue = (this.modelValue ?? this.fallback ?? []).map(toModel)
},
computed: { computed: {
selectedType: { selectedType: {
get () { get () {
@ -73,7 +72,6 @@ export default {
selected: { selected: {
get () { get () {
const selected = this.cValue[this.selectedId] const selected = this.cValue[this.selectedId]
console.log('SELECTED', selected)
if (selected && typeof selected === 'object') { if (selected && typeof selected === 'object') {
return { ...selected } return { ...selected }
} else if (typeof selected === 'string') { } else if (typeof selected === 'string') {
@ -95,12 +93,6 @@ export default {
currentFallback () { currentFallback () {
return this.fallback?.[this.selectedId] return this.fallback?.[this.selectedId]
}, },
moveUpValid () {
return this.selectedId > 0
},
moveDnValid () {
return this.selectedId < this.cValue.length - 1
},
usingFallback () { usingFallback () {
return this.modelValue == null return this.modelValue == null
}, },
@ -123,11 +115,20 @@ export default {
} }
}, },
watch: { watch: {
modelValue (value) {
if (!value) this.cValue = (this.modelValue ?? this.fallback ?? []).map(toModel)
},
selected (value) { selected (value) {
this.$emit('subShadowSelected', this.selectedId) this.$emit('subShadowSelected', this.selectedId)
} }
}, },
methods: { methods: {
getNewSubshadow () {
return toModel(this.selected)
},
onSelectChange (id) {
this.selectedId = id
},
getSubshadowLabel (shadow, index) { getSubshadowLabel (shadow, index) {
if (typeof shadow === 'object') { if (typeof shadow === 'object') {
return shadow?.name ?? this.$t('settings.style.shadows.shadow_id', { value: index }) return shadow?.name ?? this.$t('settings.style.shadows.shadow_id', { value: index })
@ -141,28 +142,6 @@ export default {
this.cValue[this.selectedId].spread = 0 this.cValue[this.selectedId].spread = 0
} }
this.$emit('update:modelValue', this.cValue) this.$emit('update:modelValue', this.cValue)
}, 100), }, 100)
add () {
this.cValue.push(toModel(this.selected))
this.selectedId = Math.max(this.cValue.length - 1, 0)
this.$emit('update:modelValue', this.cValue)
},
del () {
this.cValue.splice(this.selectedId, 1)
this.selectedId = this.cValue.length === 0 ? undefined : Math.max(this.selectedId - 1, 0)
this.$emit('update:modelValue', this.cValue)
},
moveUp () {
const movable = this.cValue.splice(this.selectedId, 1)[0]
this.cValue.splice(this.selectedId - 1, 0, movable)
this.selectedId -= 1
this.$emit('update:modelValue', this.cValue)
},
moveDn () {
const movable = this.cValue.splice(this.selectedId, 1)[0]
this.cValue.splice(this.selectedId + 1, 0, movable)
this.selectedId += 1
this.$emit('update:modelValue', this.cValue)
}
} }
} }

View file

@ -28,53 +28,14 @@
{{ getSubshadowLabel(shadow, index) }} {{ getSubshadowLabel(shadow, index) }}
</option> </option>
</Select> </Select>
<div <SelectMotion
class="id-control btn-group arrange-buttons" class="arrange-buttons"
> v-model="cValue"
<button :selectedId="selectedId"
class="btn button-default" :get-add-value="getNewSubshadow"
:disabled="disabled || shadowsAreNull" :disabled="disabled"
@click="add" @update:selectedId="onSelectChange"
> />
<FAIcon
fixed-width
icon="plus"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !moveUpValid"
:class="{ disabled: disabled || !moveUpValid }"
@click="moveUp"
>
<FAIcon
fixed-width
icon="chevron-up"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !moveDnValid"
:class="{ disabled: disabled || !moveDnValid }"
@click="moveDn"
>
<FAIcon
fixed-width
icon="chevron-down"
/>
</button>
<button
class="btn button-default"
:disabled="disabled || !present"
:class="{ disabled: disabled || !present }"
@click="del"
>
<FAIcon
fixed-width
icon="times"
/>
</button>
</div>
</div> </div>
<div class="shadow-tweak"> <div class="shadow-tweak">
<Select <Select