<template> <div v-if="elementMode === 'editing' || isVisible" class="element__wrapper" :class="{ 'element__wrapper--full-width': element.style_width === WIDTH_TYPES.FULL.value, 'element__wrapper--medium-width': element.style_width === WIDTH_TYPES.MEDIUM.value, 'element__wrapper--small-width': element.style_width === WIDTH_TYPES.SMALL.value, }" :style="wrapperStyles" > <div class="element__inner-wrapper" :style="innerWrapperStyles"> <component :is="component" :element="element" :children="children" class="element" /> </div> </div> </template> <script> import _ from 'lodash' import { resolveColor } from '@baserow/modules/core/utils/colors' import { themeToColorVariables } from '@baserow/modules/builder/utils/theme' import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums' export default { name: 'PageElement', inject: ['builder', 'page', 'mode', 'applicationContext'], provide() { return { mode: this.elementMode, applicationContext: { ...this.applicationContext, element: this.element, ...this.applicationContextAdditions, }, } }, props: { element: { type: Object, required: true, }, forceMode: { type: String, required: false, default: null, }, applicationContextAdditions: { type: Object, required: false, default: null, }, }, computed: { BACKGROUND_TYPES: () => BACKGROUND_TYPES, WIDTH_TYPES: () => WIDTH_TYPES, colorVariables() { return themeToColorVariables(this.builder.theme) }, elementMode() { return this.forceMode !== null ? this.forceMode : this.mode }, component() { const elementType = this.$registry.get('element', this.element.type) const componentName = this.elementMode === 'editing' ? 'editComponent' : 'component' return elementType[componentName] }, children() { return this.$store.getters['element/getChildren'](this.page, this.element) }, isVisible() { switch (this.element.visibility) { case 'logged-in': return this.$store.getters['userSourceUser/isAuthenticated']( this.builder ) case 'not-logged': return !this.$store.getters['userSourceUser/isAuthenticated']( this.builder ) default: return true } }, allowedStyles() { const parentElement = this.$store.getters['element/getElementById']( this.page, this.element.parent_element_id ) const elementType = this.$registry.get('element', this.element.type) const parentElementType = this.parentElement ? this.$registry.get('element', parentElement?.type) : null return !parentElementType ? elementType.styles : _.difference( elementType.styles, parentElementType.childStylesForbidden ) }, /** * Computes an object containing all the style properties that must be set on * the element wrapper. */ wrapperStyles() { const styles = { style_background_color: { '--background-color': this.element.style_background === BACKGROUND_TYPES.COLOR.value ? this.resolveColor( this.element.style_background_color, this.colorVariables ) : 'transparent', }, style_border_top: { '--border-top': this.border( this.element.style_border_top_size, this.element.style_border_top_color ), }, style_border_bottom: { '--border-bottom': this.border( this.element.style_border_bottom_size, this.element.style_border_bottom_color ), }, style_border_left: { '--border-left': this.border( this.element.style_border_left_size, this.element.style_border_left_color ), }, style_border_right: { '--border-right': this.border( this.element.style_border_right_size, this.element.style_border_right_color ), }, } return Object.keys(styles).reduce((acc, key) => { if (this.allowedStyles.includes(key)) { acc = { ...acc, ...styles[key] } } return acc }, {}) }, /** * Computes an object containing all the style properties that must be set on * the element inner wrapper. */ innerWrapperStyles() { const styles = { style_padding_top: { '--padding-top': `${this.element.style_padding_top || 0}px`, }, style_padding_bottom: { '--padding-bottom': `${this.element.style_padding_bottom || 0}px`, }, style_padding_left: { '--padding-left': `${this.element.style_padding_left || 0}px`, }, style_padding_right: { '--padding-right': `${this.element.style_padding_right || 0}px`, }, } return Object.keys(styles).reduce((acc, key) => { if (this.allowedStyles.includes(key)) { acc = { ...acc, ...styles[key] } } return acc }, {}) }, }, methods: { resolveColor, border(size, color) { return `solid ${size || 0}px ${this.resolveColor( color, this.colorVariables )}` }, }, } </script>