<template> <div> <ThemeConfigBlockSection> <template #default> <FormGroup horizontal-narrow small-label required :label="$t('imageThemeConfigBlock.alignment')" class="margin-bottom-2" > <HorizontalAlignmentsSelector v-model="values.image_alignment" /> <template #after-input> <ResetButton v-model="values.image_alignment" :default-value="theme?.image_alignment" /> </template> </FormGroup> <FormGroup horizontal-narrow :label="$t('imageThemeConfigBlock.maxWidthLabel')" small-label required class="margin-bottom-2" :error-message=" $v.values.image_max_width.$dirty && !$v.values.image_max_width.integer ? $t('error.integerField') : !$v.values.image_max_width.minValue ? $t('error.minValueField', { min: 0 }) : !$v.values.image_max_width.maxValue ? $t('error.maxValueField', { max: 100 }) : !$v.values.image_max_width.required ? $t('error.requiredField') : '' " > <FormInput v-model="values.image_max_width" type="number" :min="0" :max="100" remove-number-input-controls :placeholder="$t('imageThemeConfigBlock.maxWidthPlaceholder')" :to-value="(value) => (value ? parseInt(value) : null)" > <template #suffix> <i class="iconoir-percentage"></i> </template> </FormInput> <template #after-input> <ResetButton v-model="values.image_max_width" :default-value="theme?.image_max_width" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label required :label="$t('imageThemeConfigBlock.maxHeightLabel')" class="margin-bottom-2" :error-message=" $v.values.image_max_height.$dirty && !$v.values.image_max_height.integer ? $t('error.integerField') : !$v.values.image_max_height.minValue ? $t('error.minValueField', { min: 5 }) : !$v.values.image_max_height.maxValue ? $t('error.maxValueField', { max: 3000 }) : '' " > <FormInput v-model="imageMaxHeight" type="number" remove-number-input-controls :placeholder="$t('imageThemeConfigBlock.maxHeightPlaceholder')" :to-value="(value) => (value ? parseInt(value) : null)" > <template #suffix>px</template> </FormInput> <template #after-input> <ResetButton v-model="imageMaxHeight" :default-value="theme?.image_max_height" /> </template> </FormGroup> <FormGroup horizontal-narrow small-label required class="margin-bottom-2" :label="$t('imageThemeConfigBlock.imageConstraintsLabel')" > <Dropdown v-model="values.image_constraint" small fixed-items :show-search="true" class="flex-grow-1" > <DropdownItem v-for="{ name, label } in imageConstraintChoices" :key="name" :disabled="constraintDisabled(name)" :description=" constraintDisabled(name) ? $t(`imageThemeConfigBlock.imageConstraint${label}Disabled`) : '' " :name="label" :value="name" > </DropdownItem> </Dropdown> <template #after-input> <ResetButton v-model="imageConstraintForReset" :default-value="theme?.image_constraint" /> </template> </FormGroup> </template> <template #preview> <ABImage src="/img/favicon_192.png" /> </template> </ThemeConfigBlockSection> </div> </template> <script> 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 { IMAGE_SOURCE_TYPES } from '@baserow/modules/builder/enums' import { integer, maxValue, minValue, required } from 'vuelidate/lib/validators' export default { name: 'ImageThemeConfigBlock', components: { ThemeConfigBlockSection, ResetButton, HorizontalAlignmentsSelector, }, mixins: [themeConfigBlock], data() { return { values: {}, allowedValues: [ 'image_alignment', 'image_max_width', 'image_max_height', 'image_constraint', ], } }, computed: { imageMaxHeight: { get() { return this.values.image_max_height }, set(newValue) { // If the `image_max_height` is emptied, and the // constraint is 'cover', then reset back to 'contain'. if (!newValue && this.values.image_constraint === 'cover') { this.values.image_constraint = 'contain' } // If the `image_max_height` is set, and the // constraint is 'contain', then reset back to 'cover'. if (newValue && this.values.image_constraint === 'contain') { this.values.image_constraint = 'cover' } this.values.image_max_height = newValue }, }, imageMaxHeightForReset: { get() { return { image_max_height: this.imageMaxHeight } }, set(value) { this.imageMaxHeight = value.imageMaxHeight }, }, imageConstraintForReset: { get() { return this.values.image_constraint }, set(value) { if (value === 'contain') { // Reset the height as we can't have a max height with contain this.values.image_max_height = null } if (value === 'cover') { // Set the height to what is defined in theme this.values.image_max_height = this.theme.image_max_height } this.values.image_constraint = value }, }, IMAGE_SOURCE_TYPES() { return IMAGE_SOURCE_TYPES }, imageConstraintChoices() { return [ { name: 'contain', label: this.$t('imageThemeConfigBlock.imageConstraintContain'), }, { name: 'cover', label: this.$t('imageThemeConfigBlock.imageConstraintCover'), }, { name: 'full-width', label: this.$t('imageThemeConfigBlock.imageConstraintFullWidth'), }, ] }, }, methods: { constraintDisabled(name) { if (name === 'cover') { return !this.values.image_max_height } else if (name === 'contain') { return !!( this.values.image_max_height && this.values.image_max_height > 0 ) } }, isAllowedKey(key) { return key.startsWith('image_') }, }, validations: { values: { image_max_width: { required, integer, minValue: minValue(0), maxValue: maxValue(100), }, image_max_height: { integer, minValue: minValue(5), maxValue: maxValue(3000), }, }, }, } </script>