font selector with proper styles and functionality + local font selector

This commit is contained in:
Henry Jameson 2024-06-26 17:05:59 +03:00
commit d5d37849ea
6 changed files with 186 additions and 51 deletions

View file

@ -1,13 +1,19 @@
import { set } from 'lodash'
import { set, clone } from 'lodash'
import Select from '../select/select.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'
import {
faExclamationTriangle,
faKeyboard,
faFont
} from '@fortawesome/free-solid-svg-icons'
library.add(
faExclamationTriangle
faExclamationTriangle,
faKeyboard,
faFont
)
const PRESET_FONTS = new Set(['serif', 'sans-serif', 'monospace', 'inherit'])
@ -24,20 +30,38 @@ export default {
emits: ['update:modelValue'],
data () {
return {
localValue: this.modelValue,
customFamily: '',
manualEntry: true,
localValue: clone(this.modelValue),
familyCustomLocal: null,
availableOptions: [
this.noInherit ? '' : 'inherit',
'local',
...(this.options || []),
'serif',
'sans-serif',
'monospace',
'sans-serif'
'local',
...(this.options || [])
].filter(_ => _)
}
},
beforeUpdate () {
this.localValue = this.modelValue
this.localValue = clone(this.modelValue)
if (this.familyCustomLocal === null && !this.isInvalidFamily(this.modelValue?.family)) {
this.familyCustomLocal = this.modelValue?.family
}
},
methods: {
lookupLocalFonts () {
if (!this.fontsList) {
this.$store.dispatch('queryLocalFonts')
}
this.toggleManualEntry()
},
isInvalidFamily (value) {
return PRESET_FONTS.has(value) || (value === '')
},
toggleManualEntry () {
this.manualEntry = !this.manualEntry
}
},
computed: {
present () {
@ -46,32 +70,39 @@ export default {
defaultValue () {
return this.localValue || this.fallback || {}
},
fontsListCapable () {
return this.$store.state.interface.browserSupport.localFonts
},
fontsList () {
return this.$store.state.interface.localFonts
},
family: {
get () {
return this.defaultValue.family
},
set (v) {
this.familyCustomLocal = ''
set(this.localValue, 'family', v)
this.$emit('update:modelValue', this.localValue)
}
},
familyCustom: {
get () {
return this.customFamily
return this.familyCustomLocal
},
set (v) {
this.customFamily = v
if (!PRESET_FONTS.has(this.customFamily)) {
this.familyCustomLocal = v
if (!this.isInvalidFamily(v)) {
set(this.localValue, 'family', v)
this.$emit('update:modelValue', this.customFamily)
this.$emit('update:modelValue', this.localValue)
}
}
},
invalidCustom () {
return PRESET_FONTS.has(this.customFamily)
return this.isInvalidFamily(this.familyCustomLocal)
},
isCustom () {
return !PRESET_FONTS.has(this.family)
return !PRESET_FONTS.has(this.defaultValue.family)
},
preset: {
get () {

View file

@ -10,15 +10,6 @@
>
{{ label }}
</label>
{{ ' ' }}
<Checkbox
v-if="typeof fallback !== 'undefined'"
:id="name + '-o'"
:modelValue="present"
@change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
>
{{ $t('settings.style.themes3.define') }}
</Checkbox>
<p>
<Select
:id="name + '-font-switcher'"
@ -34,15 +25,89 @@
{{ $t('settings.style.themes3.font.' + option) }}
</option>
</Select>
</p>
<p>
<input
v-if="isCustom"
:id="name"
v-model="familyCustom"
class="input custom-font"
type="text"
{{ ' ' }}
<Checkbox
v-if="typeof fallback !== 'undefined'"
:id="name + '-o'"
:modelValue="present"
@change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
>
{{ $t('settings.style.themes3.define') }}
</Checkbox>
</p>
<p v-if="isCustom">
<label
v-if="fontsList !== null && !manualEntry"
:id="name + '-label'"
:for="preset === 'custom' ? name : name + '-font-switcher'"
class="label"
>
{{ $t('settings.style.themes3.font.select') }}
</label>
<label
v-else
:id="name + '-label'"
:for="preset === 'custom' ? name : name + '-font-switcher'"
class="label"
>
<i18n-t
keypath="settings.style.themes3.font.entry"
tag="span"
>
<template #fontFamily>
<code>font-family</code>
</template>
</i18n-t>
</label>
{{ ' ' }}
<span class="btn-group">
<button
v-if="fontsListCapable && (fontsList === null || manualEntry)"
class="btn button-default"
@click="lookupLocalFonts"
:title="$t('settings.style.themes3.font.lookup_local_fonts')"
>
<FAIcon
fixed-width
icon="font"
/>
</button>
<input
v-if="fontsLists === null || manualEntry"
:id="name"
v-model="familyCustom"
class="input custom-font"
type="text"
>
</span>
<span class="btn-group">
<button
v-if="fontsList !== null && !manualEntry"
class="btn button-default"
@click="toggleManualEntry"
:title="$t('settings.style.themes3.font.enter_manually')"
>
<FAIcon
fixed-width
icon="keyboard"
/>
</button>
<Select
v-if="fontsList !== null && !manualEntry"
:id="name + '-local-font-switcher'"
v-model="familyCustom"
class="custom-font"
>
<option
v-for="option in fontsList.values()"
:key="option"
:value="option"
:style="{ fontFamily: option }"
>
{{ option }}
</option>
</Select>
</span>
<span
v-if="invalidCustom"
class="InvalidIndicator"
@ -70,8 +135,9 @@
<style lang="scss">
.font-control {
input.custom-font {
min-width: 12em;
.custom-font {
min-width: 20em;
max-width: 20em;
}
}

View file

@ -10,6 +10,10 @@
margin-right: 0.25em;
}
.btn-group .btn {
margin: 0;
}
.style-control {
display: flex;
align-items: baseline;