165 lines
3.5 KiB
TypeScript
165 lines
3.5 KiB
TypeScript
// Styles
|
|
import './VBanner.sass'
|
|
|
|
// Extensions
|
|
import VSheet from '../VSheet'
|
|
|
|
// Components
|
|
import VAvatar from '../VAvatar'
|
|
import VIcon from '../VIcon'
|
|
import { VExpandTransition } from '../transitions'
|
|
|
|
// Mixins
|
|
import Mobile from '../../mixins/mobile'
|
|
import Toggleable from '../../mixins/toggleable'
|
|
|
|
// Utilities
|
|
import mixins from '../../util/mixins'
|
|
import {
|
|
convertToUnit,
|
|
getSlot,
|
|
} from '../../util/helpers'
|
|
|
|
// Typeslint
|
|
import { VNode } from 'vue'
|
|
|
|
/* @vue/component */
|
|
export default mixins(
|
|
VSheet,
|
|
Mobile,
|
|
Toggleable
|
|
).extend({
|
|
name: 'v-banner',
|
|
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
app: Boolean,
|
|
icon: String,
|
|
iconColor: String,
|
|
singleLine: Boolean,
|
|
sticky: Boolean,
|
|
value: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
},
|
|
|
|
computed: {
|
|
classes (): object {
|
|
return {
|
|
...VSheet.options.computed.classes.call(this),
|
|
'v-banner--has-icon': this.hasIcon,
|
|
'v-banner--is-mobile': this.isMobile,
|
|
'v-banner--single-line': this.singleLine,
|
|
'v-banner--sticky': this.isSticky,
|
|
}
|
|
},
|
|
hasIcon (): boolean {
|
|
return Boolean(this.icon || this.$slots.icon)
|
|
},
|
|
isSticky (): boolean {
|
|
return this.sticky || this.app
|
|
},
|
|
styles (): object {
|
|
const styles: Record<string, any> = { ...VSheet.options.computed.styles.call(this) }
|
|
|
|
if (this.isSticky) {
|
|
const top = !this.app
|
|
? 0
|
|
: (this.$vuetify.application.bar + this.$vuetify.application.top)
|
|
|
|
styles.top = convertToUnit(top)
|
|
styles.position = 'sticky'
|
|
styles.zIndex = 1
|
|
}
|
|
|
|
return styles
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
/** @public */
|
|
toggle () {
|
|
this.isActive = !this.isActive
|
|
},
|
|
iconClick (e: MouseEvent) {
|
|
this.$emit('click:icon', e)
|
|
},
|
|
genIcon () {
|
|
if (!this.hasIcon) return undefined
|
|
|
|
let content
|
|
|
|
if (this.icon) {
|
|
content = this.$createElement(VIcon, {
|
|
props: {
|
|
color: this.iconColor,
|
|
size: 28,
|
|
},
|
|
}, [this.icon])
|
|
} else {
|
|
content = this.$slots.icon
|
|
}
|
|
|
|
return this.$createElement(VAvatar, {
|
|
staticClass: 'v-banner__icon',
|
|
props: {
|
|
color: this.color,
|
|
size: 40,
|
|
},
|
|
on: {
|
|
click: this.iconClick,
|
|
},
|
|
}, [content])
|
|
},
|
|
genText () {
|
|
return this.$createElement('div', {
|
|
staticClass: 'v-banner__text',
|
|
}, this.$slots.default)
|
|
},
|
|
genActions () {
|
|
const children = getSlot(this, 'actions', {
|
|
dismiss: () => this.isActive = false,
|
|
})
|
|
|
|
if (!children) return undefined
|
|
|
|
return this.$createElement('div', {
|
|
staticClass: 'v-banner__actions',
|
|
}, children)
|
|
},
|
|
genContent () {
|
|
return this.$createElement('div', {
|
|
staticClass: 'v-banner__content',
|
|
}, [
|
|
this.genIcon(),
|
|
this.genText(),
|
|
])
|
|
},
|
|
genWrapper () {
|
|
return this.$createElement('div', {
|
|
staticClass: 'v-banner__wrapper',
|
|
}, [
|
|
this.genContent(),
|
|
this.genActions(),
|
|
])
|
|
},
|
|
},
|
|
|
|
render (h): VNode {
|
|
return h(VExpandTransition, [
|
|
h('div', this.setBackgroundColor(this.color, {
|
|
staticClass: 'v-banner',
|
|
attrs: this.attrs$,
|
|
class: this.classes,
|
|
style: this.styles,
|
|
directives: [{
|
|
name: 'show',
|
|
value: this.isActive,
|
|
}],
|
|
}), [this.genWrapper()]),
|
|
])
|
|
},
|
|
})
|