mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
11 KiB
332 lines
11 KiB
<template>
|
|
<div
|
|
class="modal modal-open items-start !animate-none overflow-y-auto"
|
|
>
|
|
<div
|
|
class="absolute top-0 bottom-0 right-0 left-0"
|
|
@click.prevent="$emit('close')"
|
|
/>
|
|
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none w-full max-w-xl">
|
|
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
|
|
<span class="modal-title">
|
|
{{ t('font') }} - {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || buildDefaultName(field, template.fields) }}
|
|
</span>
|
|
<a
|
|
href="#"
|
|
class="text-xl modal-close-button"
|
|
@click.prevent="$emit('close')"
|
|
>×</a>
|
|
</div>
|
|
<div class="mt-4">
|
|
<div>
|
|
<div class="flex items-center space-x-1.5">
|
|
<span>
|
|
<div class="dropdown modal-field-font-dropdown">
|
|
<label
|
|
tabindex="0"
|
|
class="base-input flex items-center justify-between"
|
|
style="height: 32px; padding-right: 0; width: 120px"
|
|
:class="fonts.find((f) => f.value === preferences.font)?.class"
|
|
>
|
|
<span style="margin-top: 1px">
|
|
{{ preferences.font || 'Default' }}
|
|
</span>
|
|
<IconChevronDown
|
|
class="ml-2 mr-2 mt-0.5"
|
|
width="18"
|
|
height="18"
|
|
/>
|
|
</label>
|
|
<div
|
|
tabindex="0"
|
|
class="dropdown-content p-0 mt-1 block z-10 menu shadow bg-white border border-base-300 rounded-md w-52"
|
|
>
|
|
<div
|
|
v-for="(font, index) in fonts"
|
|
:key="index"
|
|
:value="font.value"
|
|
:class="{ 'bg-base-300': preferences.font == font.value, [font.class]: true }"
|
|
class="hover:bg-base-300 px-2 py-1.5 cursor-pointer"
|
|
@click="[font.value ? preferences.font = font.value : delete preferences.font, closeDropdown()]"
|
|
>
|
|
{{ font.label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</span>
|
|
<span class="relative">
|
|
<select
|
|
class="select input-bordered bg-white select-sm text-center pl-2"
|
|
style="font-size: 16px; line-height: 12px; width: 86px; text-align-last: center;"
|
|
@change="$event.target.value ? preferences.font_size = parseInt($event.target.value) : delete preferences.font_size"
|
|
>
|
|
<option
|
|
:selected="!preferences.font_size"
|
|
value=""
|
|
>
|
|
Auto
|
|
</option>
|
|
<option
|
|
v-for="size in sizes"
|
|
:key="size"
|
|
:value="size"
|
|
:selected="size === preferences.font_size"
|
|
>
|
|
{{ size }}
|
|
</option>
|
|
</select>
|
|
<span
|
|
class="border-l pl-1.5 absolute bg-white bottom-0 pointer-events-none text-sm h-5"
|
|
style="right: 13px; top: 6px"
|
|
>
|
|
pt
|
|
</span>
|
|
</span>
|
|
<span class="flex">
|
|
<div
|
|
class="join"
|
|
style="height: 32px"
|
|
>
|
|
<button
|
|
v-for="(type, index) in types"
|
|
:key="index"
|
|
class="btn btn-sm join-item bg-white input-bordered hover:border-base-content/20 hover:bg-base-200/50 px-2"
|
|
:class="{ '!bg-base-300': preferences.font_type?.includes(type.value) }"
|
|
@click="setFontType(type.value)"
|
|
>
|
|
<component :is="type.icon" />
|
|
</button>
|
|
</div>
|
|
</span>
|
|
<span class="flex">
|
|
<div
|
|
class="join"
|
|
style="height: 32px"
|
|
>
|
|
<button
|
|
v-for="(align, index) in aligns"
|
|
:key="index"
|
|
class="btn btn-sm join-item bg-white input-bordered hover:border-base-content/20 hover:bg-base-200/50 px-2"
|
|
:class="{ '!bg-base-300': preferences.align === align.value }"
|
|
@click="align.value && preferences.align != align.value ? preferences.align = align.value : delete preferences.align"
|
|
>
|
|
<component :is="align.icon" />
|
|
</button>
|
|
</div>
|
|
</span>
|
|
<span class="flex">
|
|
<div class="dropdown modal-field-font-dropdown">
|
|
<label
|
|
tabindex="0"
|
|
class="cursor-pointer flex bg-white border input-bordered rounded-md h-8 items-center justify-center px-1"
|
|
style="-webkit-appearance: none; -moz-appearance: none;"
|
|
>
|
|
<component :is="valigns.find((v) => v.value === (preferences.valign || 'center'))?.icon" />
|
|
</label>
|
|
<div
|
|
tabindex="0"
|
|
class="dropdown-content p-0 mt-1 block z-10 menu shadow bg-white border border-base-300 rounded-md"
|
|
>
|
|
<div
|
|
v-for="(valign, index) in valigns"
|
|
:key="index"
|
|
:value="valign.value"
|
|
:class="{ 'bg-base-300': preferences.valign == valign.value }"
|
|
class="hover:bg-base-300 px-2 py-1.5 cursor-pointer"
|
|
@click="[valign.value ? preferences.valign = valign.value : delete preferences.valign, closeDropdown()]"
|
|
>
|
|
<component :is="valign.icon" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</span>
|
|
<span>
|
|
<select
|
|
class="input input-bordered bg-white input-sm text-lg rounded-md"
|
|
style="-webkit-appearance: none; -moz-appearance: none; text-indent: 0px; text-overflow: ''; padding: 0px 6px; height: 32px"
|
|
@change="$event.target.value ? preferences.color = $event.target.value : delete preferences.color"
|
|
>
|
|
<option
|
|
v-for="(color, index) in colors"
|
|
:key="index"
|
|
:value="color.value"
|
|
:selected="color.value == preferences.color"
|
|
>
|
|
{{ color.label }}
|
|
</option>
|
|
</select>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="mt-4">
|
|
<div
|
|
class="flex border border-base-content/20 rounded-xl bg-white px-4 h-16 modal-field-font-preview"
|
|
:style="{
|
|
color: preferences.color || 'black',
|
|
fontSize: (preferences.font_size || 11) + 'pt',
|
|
}"
|
|
:class="textClasses"
|
|
>
|
|
<span
|
|
contenteditable="true"
|
|
class="outline-none whitespace-nowrap truncate"
|
|
>
|
|
{{ field.default_value || field.name || buildDefaultName(field, template.fields) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="mt-4">
|
|
<button
|
|
class="base-button w-full modal-save-button"
|
|
@click.prevent="saveAndClose"
|
|
>
|
|
{{ t('save') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { IconChevronDown, IconBold, IconItalic, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignBoxCenterTop, IconAlignBoxCenterBottom, IconAlignBoxCenterMiddle } from '@tabler/icons-vue'
|
|
|
|
export default {
|
|
name: 'FontModal',
|
|
components: {
|
|
IconChevronDown
|
|
},
|
|
inject: ['t', 'save', 'template'],
|
|
props: {
|
|
field: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
defaultField: {
|
|
type: Object,
|
|
required: false,
|
|
default: null
|
|
},
|
|
editable: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: true
|
|
},
|
|
buildDefaultName: {
|
|
type: Function,
|
|
required: true
|
|
}
|
|
},
|
|
emits: ['close'],
|
|
data () {
|
|
return {
|
|
preferences: {}
|
|
}
|
|
},
|
|
computed: {
|
|
fonts () {
|
|
return [
|
|
{ value: null, label: 'Default' },
|
|
{ value: 'Times', label: 'Times', class: 'font-times' },
|
|
{ value: 'Courier', label: 'Courier', class: 'font-courier' }
|
|
]
|
|
},
|
|
types () {
|
|
return [
|
|
{ icon: IconBold, value: 'bold' },
|
|
{ icon: IconItalic, value: 'italic' }
|
|
]
|
|
},
|
|
aligns () {
|
|
return [
|
|
{ icon: IconAlignLeft, value: 'left' },
|
|
{ icon: IconAlignCenter, value: 'center' },
|
|
{ icon: IconAlignRight, value: 'right' }
|
|
]
|
|
},
|
|
valigns () {
|
|
return [
|
|
{ icon: IconAlignBoxCenterTop, value: 'top' },
|
|
{ icon: IconAlignBoxCenterMiddle, value: 'center' },
|
|
{ icon: IconAlignBoxCenterBottom, value: 'bottom' }
|
|
]
|
|
},
|
|
sizes () {
|
|
return [...Array(23).keys()].map(i => i + 6)
|
|
},
|
|
colors () {
|
|
return [
|
|
{ label: '⬛', value: 'black' },
|
|
{ label: '🟦', value: 'blue' },
|
|
{ label: '🟥', value: 'red' }
|
|
]
|
|
},
|
|
textClasses () {
|
|
return {
|
|
'font-courier': this.preferences.font === 'Courier',
|
|
'font-times': this.preferences.font === 'Times',
|
|
'justify-center': this.preferences.align === 'center',
|
|
'justify-start': this.preferences.align === 'left',
|
|
'justify-end': this.preferences.align === 'right',
|
|
'items-center': !this.preferences.valign || this.preferences.valign === 'center',
|
|
'items-start': this.preferences.valign === 'top',
|
|
'items-end': this.preferences.valign === 'bottom',
|
|
'font-bold': ['bold_italic', 'bold'].includes(this.preferences.font_type),
|
|
italic: ['bold_italic', 'italic'].includes(this.preferences.font_type)
|
|
}
|
|
},
|
|
keys () {
|
|
return ['font_type', 'font_size', 'color', 'align', 'valign', 'font']
|
|
}
|
|
},
|
|
created () {
|
|
this.preferences = this.keys.reduce((acc, key) => {
|
|
acc[key] = this.field.preferences?.[key]
|
|
|
|
return acc
|
|
}, {})
|
|
},
|
|
methods: {
|
|
closeDropdown () {
|
|
this.$el.getRootNode().activeElement.blur()
|
|
},
|
|
setFontType (value) {
|
|
if (value === 'bold') {
|
|
if (this.preferences.font_type === 'bold') {
|
|
delete this.preferences.font_type
|
|
} else if (this.preferences.font_type === 'italic') {
|
|
this.preferences.font_type = 'bold_italic'
|
|
} else if (this.preferences.font_type === 'bold_italic') {
|
|
this.preferences.font_type = 'italic'
|
|
} else {
|
|
this.preferences.font_type = value
|
|
}
|
|
}
|
|
|
|
if (value === 'italic') {
|
|
if (this.preferences.font_type === 'italic') {
|
|
delete this.preferences.font_type
|
|
} else if (this.preferences.font_type === 'bold') {
|
|
this.preferences.font_type = 'bold_italic'
|
|
} else if (this.preferences.font_type === 'bold_italic') {
|
|
this.preferences.font_type = 'bold'
|
|
} else {
|
|
this.preferences.font_type = value
|
|
}
|
|
}
|
|
},
|
|
saveAndClose () {
|
|
this.field.preferences ||= {}
|
|
|
|
this.keys.forEach((key) => delete this.field.preferences[key])
|
|
|
|
Object.assign(this.field.preferences, this.preferences)
|
|
|
|
this.save()
|
|
|
|
this.$emit('close')
|
|
}
|
|
}
|
|
}
|
|
</script>
|