vuetify
Version:
Vue Material Component Framework
167 lines (146 loc) • 4.41 kB
text/typescript
// Styles
import './VToolbar.sass'
// Extensions
import VSheet from '../VSheet/VSheet'
// Components
import VImg, { srcObject } from '../VImg/VImg'
// Utilities
import { convertToUnit, getSlot } from '../../util/helpers'
import { breaking } from '../../util/console'
// Types
import { VNode, PropType } from 'vue'
/* @vue/component */
export default VSheet.extend({
name: 'v-toolbar',
props: {
absolute: Boolean,
bottom: Boolean,
collapse: Boolean,
dense: Boolean,
extended: Boolean,
extensionHeight: {
default: 48,
type: [Number, String],
},
flat: Boolean,
floating: Boolean,
prominent: Boolean,
short: Boolean,
src: {
type: [String, Object] as PropType<string | srcObject>,
default: '',
},
tag: {
type: String,
default: 'header',
},
},
data: () => ({
isExtended: false,
}),
computed: {
computedHeight (): number {
const height = this.computedContentHeight
if (!this.isExtended) return height
const extensionHeight = parseInt(this.extensionHeight)
return this.isCollapsed
? height
: height + (!isNaN(extensionHeight) ? extensionHeight : 0)
},
computedContentHeight (): number {
if (this.height) return parseInt(this.height)
if (this.isProminent && this.dense) return 96
if (this.isProminent && this.short) return 112
if (this.isProminent) return 128
if (this.dense) return 48
if (this.short || this.$vuetify.breakpoint.smAndDown) return 56
return 64
},
classes (): object {
return {
...VSheet.options.computed.classes.call(this),
'v-toolbar': true,
'v-toolbar--absolute': this.absolute,
'v-toolbar--bottom': this.bottom,
'v-toolbar--collapse': this.collapse,
'v-toolbar--collapsed': this.isCollapsed,
'v-toolbar--dense': this.dense,
'v-toolbar--extended': this.isExtended,
'v-toolbar--flat': this.flat,
'v-toolbar--floating': this.floating,
'v-toolbar--prominent': this.isProminent,
}
},
isCollapsed (): boolean {
return this.collapse
},
isProminent (): boolean {
return this.prominent
},
styles (): object {
return {
...this.measurableStyles,
height: convertToUnit(this.computedHeight),
}
},
},
created () {
const breakingProps = [
['app', '<v-app-bar app>'],
['manual-scroll', '<v-app-bar :value="false">'],
['clipped-left', '<v-app-bar clipped-left>'],
['clipped-right', '<v-app-bar clipped-right>'],
['inverted-scroll', '<v-app-bar inverted-scroll>'],
['scroll-off-screen', '<v-app-bar scroll-off-screen>'],
['scroll-target', '<v-app-bar scroll-target>'],
['scroll-threshold', '<v-app-bar scroll-threshold>'],
['card', '<v-app-bar flat>'],
]
/* istanbul ignore next */
breakingProps.forEach(([original, replacement]) => {
if (this.$attrs.hasOwnProperty(original)) breaking(original, replacement, this)
})
},
methods: {
genBackground () {
const props = {
height: convertToUnit(this.computedHeight),
src: this.src,
}
const image = this.$scopedSlots.img
? this.$scopedSlots.img({ props })
: this.$createElement(VImg, { props })
return this.$createElement('div', {
staticClass: 'v-toolbar__image',
}, [image])
},
genContent () {
return this.$createElement('div', {
staticClass: 'v-toolbar__content',
style: {
height: convertToUnit(this.computedContentHeight),
},
}, getSlot(this))
},
genExtension () {
return this.$createElement('div', {
staticClass: 'v-toolbar__extension',
style: {
height: convertToUnit(this.extensionHeight),
},
}, getSlot(this, 'extension'))
},
},
render (h): VNode {
this.isExtended = this.extended || !!this.$scopedSlots.extension
const children = [this.genContent()]
const data = this.setBackgroundColor(this.color, {
class: this.classes,
style: this.styles,
on: this.$listeners,
})
if (this.isExtended) children.push(this.genExtension())
if (this.src || this.$scopedSlots.img) children.unshift(this.genBackground())
return h(this.tag, data, children)
},
})