<template> <form @submit.prevent @keydown.enter.prevent> <ThemeConfigBlockSection v-if="showBody" :title="$t('typographyThemeConfigBlock.bodyLabel')" > <template #default> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.fontFamily')" > <FontFamilySelector v-model="values.body_font_family" /> <template #after-input> <ResetButton v-model="values.body_font_family" :default-value="theme?.body_font_family" /> </template> </FormGroup> <FormGroup v-if="!extraArgs?.noAlignment" horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.textAlignment')" > <HorizontalAlignmentsSelector v-model="values.body_text_alignment" /> <template #after-input> <ResetButton v-model="values.body_text_alignment" :default-value="theme?.body_text_alignment" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.size')" :error-message=" $v.values[`body_font_size`].$invalid ? $t('error.minMaxValueField', { min: fontSizeMin, max: bodyFontSizeMax, }) : '' " > <PixelValueSelector v-model="values.body_font_size" class="typography-theme-config-block__input-number" @blur="$v.values[`body_font_size`].$touch()" /> <template #after-input> <ResetButton v-model="values.body_font_size" :default-value="theme?.body_font_size" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.color')" > <ColorInput v-model="values['body_text_color']" :color-variables="colorVariables" :default-value="theme ? theme['body_text_color'] : null" small /> <template #after-input> <ResetButton v-model="values.body_text_color" :default-value="theme?.body_text_color" /> </template> </FormGroup> </template> <template #preview> <ABParagraph> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </ABParagraph> </template> </ThemeConfigBlockSection> <template v-if="showHeadings"> <ThemeConfigBlockSection v-for="level in headings" :key="level" :title="$t('typographyThemeConfigBlock.headingLabel', { i: level })" > <template #default> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.fontFamily')" > <FontFamilySelector v-model="values[`heading_${level}_font_family`]" /> <template #after-input> <ResetButton v-model="values[`heading_${level}_font_family`]" :default-value="theme?.[`heading_${level}_font_family`]" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.textAlignment')" > <HorizontalAlignmentsSelector v-model="values[`heading_${level}_text_alignment`]" /> <template #after-input> <ResetButton v-model="values[`heading_${level}_text_alignment`]" :default-value="theme?.[`heading_${level}_text_alignment`]" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.size')" :error-message=" $v.values[`heading_${level}_font_size`].$invalid ? $t('error.minMaxValueField', { min: fontSizeMin, max: fontSizeMax, }) : '' " > <PixelValueSelector v-model="values[`heading_${level}_font_size`]" class="typography-theme-config-block__input-number" @blur="$v.values[`heading_${level}_font_size`].$touch()" /> <template #after-input> <ResetButton v-model="values[`heading_${level}_font_size`]" :default-value="theme?.[`heading_${level}_font_size`]" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.color')" > <ColorInput v-model="values[`heading_${level}_text_color`]" :color-variables="colorVariables" :default-value=" theme ? theme[`heading_${level}_text_color`] : null " small /> <template #after-input> <ResetButton v-model="values[`heading_${level}_text_color`]" :default-value="theme?.[`heading_${level}_text_color`]" /> </template> </FormGroup> </template> <template #preview> <ABHeading class="typography-theme-config-block__heading-preview" :level="level" > {{ $t('typographyThemeConfigBlock.headingValue', { i: level }) }} </ABHeading> </template> </ThemeConfigBlockSection> </template> </form> </template> <script> import { required, integer, minValue, maxValue } from 'vuelidate/lib/validators' import themeConfigBlock from '@baserow/modules/builder/mixins/themeConfigBlock' import ThemeConfigBlockSection from '@baserow/modules/builder/components/theme/ThemeConfigBlockSection' import ResetButton from '@baserow/modules/builder/components/theme/ResetButton' import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/HorizontalAlignmentsSelector' import FontFamilySelector from '@baserow/modules/builder/components/FontFamilySelector' import PixelValueSelector from '@baserow/modules/builder/components/PixelValueSelector' const fontSizeMin = 1 const fontSizeMax = 100 const bodyFontSizeMax = 30 const headings = [1, 2, 3, 4, 5, 6] export default { name: 'TypographyThemeConfigBlock', components: { ThemeConfigBlockSection, ResetButton, HorizontalAlignmentsSelector, FontFamilySelector, PixelValueSelector, }, mixins: [themeConfigBlock], data() { return { values: {}, } }, computed: { headings() { if (this.extraArgs?.headingLevel) { return [this.extraArgs.headingLevel] } else { return headings } }, showBody() { return !this.extraArgs?.headingLevel }, showHeadings() { return !this.extraArgs?.onlyBody }, fontSizeMin() { return fontSizeMin }, fontSizeMax() { return fontSizeMax }, bodyFontSizeMax() { return bodyFontSizeMax }, }, methods: { isAllowedKey(key) { return key.startsWith('heading_') || key.startsWith('body_') }, }, validations: { values: { ...headings.reduce((o, i) => { o[`heading_${i}_font_size`] = { required, integer, minValue: minValue(fontSizeMin), maxValue: maxValue(fontSizeMax), } return o }, {}), body_font_size: { required, integer, minValue: minValue(fontSizeMin), maxValue: maxValue(bodyFontSizeMax), }, }, }, } </script>