2018-08-27 12:22:25 -07:00
|
|
|
import Vue from 'vue'
|
|
|
|
|
|
|
|
import './tab_switcher.scss'
|
|
|
|
|
|
|
|
export default Vue.component('tab-switcher', {
|
|
|
|
name: 'TabSwitcher',
|
2019-08-12 10:01:38 -07:00
|
|
|
props: {
|
|
|
|
renderOnlyFocused: {
|
|
|
|
required: false,
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
onSwitch: {
|
|
|
|
required: false,
|
2019-11-08 08:14:01 -08:00
|
|
|
type: Function,
|
|
|
|
default: undefined
|
2019-08-12 10:01:38 -07:00
|
|
|
},
|
2019-09-08 03:44:29 -07:00
|
|
|
activeTab: {
|
2019-08-12 10:01:38 -07:00
|
|
|
required: false,
|
2019-11-08 08:14:01 -08:00
|
|
|
type: String,
|
|
|
|
default: undefined
|
2019-08-12 10:01:38 -07:00
|
|
|
},
|
|
|
|
scrollableTabs: {
|
|
|
|
required: false,
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2020-05-03 07:36:12 -07:00
|
|
|
},
|
|
|
|
sideTabBar: {
|
|
|
|
required: false,
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2019-08-12 10:01:38 -07:00
|
|
|
}
|
|
|
|
},
|
2018-08-27 12:22:25 -07:00
|
|
|
data () {
|
|
|
|
return {
|
2019-01-17 11:25:50 -08:00
|
|
|
active: this.$slots.default.findIndex(_ => _.tag)
|
2018-08-27 12:22:25 -07:00
|
|
|
}
|
|
|
|
},
|
2019-08-10 11:48:05 -07:00
|
|
|
computed: {
|
|
|
|
activeIndex () {
|
|
|
|
// In case of controlled component
|
|
|
|
if (this.activeTab) {
|
|
|
|
return this.$slots.default.findIndex(slot => this.activeTab === slot.key)
|
|
|
|
} else {
|
|
|
|
return this.active
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2019-07-05 00:02:14 -07:00
|
|
|
beforeUpdate () {
|
|
|
|
const currentSlot = this.$slots.default[this.active]
|
|
|
|
if (!currentSlot.tag) {
|
|
|
|
this.active = this.$slots.default.findIndex(_ => _.tag)
|
|
|
|
}
|
|
|
|
},
|
2018-08-27 12:22:25 -07:00
|
|
|
methods: {
|
2019-08-09 20:48:33 -07:00
|
|
|
activateTab (index) {
|
2019-08-12 10:01:38 -07:00
|
|
|
return (e) => {
|
|
|
|
e.preventDefault()
|
2019-05-14 12:38:16 -07:00
|
|
|
if (typeof this.onSwitch === 'function') {
|
2019-08-09 20:48:08 -07:00
|
|
|
this.onSwitch.call(null, this.$slots.default[index].key)
|
2019-05-14 12:38:16 -07:00
|
|
|
}
|
2019-01-17 11:25:50 -08:00
|
|
|
this.active = index
|
2020-05-25 04:16:03 -07:00
|
|
|
if (this.scrollableTabs) {
|
|
|
|
this.$refs.contents.scrollTop = 0
|
|
|
|
}
|
2019-01-17 11:25:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
render (h) {
|
2018-08-27 12:22:25 -07:00
|
|
|
const tabs = this.$slots.default
|
2019-07-05 00:02:14 -07:00
|
|
|
.map((slot, index) => {
|
|
|
|
if (!slot.tag) return
|
|
|
|
const classesTab = ['tab']
|
|
|
|
const classesWrapper = ['tab-wrapper']
|
2019-08-10 11:48:05 -07:00
|
|
|
if (this.activeIndex === index) {
|
2019-07-05 00:02:14 -07:00
|
|
|
classesTab.push('active')
|
|
|
|
classesWrapper.push('active')
|
|
|
|
}
|
2019-07-24 12:35:52 -07:00
|
|
|
if (slot.data.attrs.image) {
|
|
|
|
return (
|
2019-08-09 21:26:29 -07:00
|
|
|
<div class={classesWrapper.join(' ')}>
|
2019-07-24 12:35:52 -07:00
|
|
|
<button
|
|
|
|
disabled={slot.data.attrs.disabled}
|
|
|
|
onClick={this.activateTab(index)}
|
|
|
|
class={classesTab.join(' ')}>
|
|
|
|
<img src={slot.data.attrs.image} title={slot.data.attrs['image-tooltip']}/>
|
|
|
|
{slot.data.attrs.label ? '' : slot.data.attrs.label}
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
2019-07-05 00:02:14 -07:00
|
|
|
return (
|
2019-08-09 21:26:29 -07:00
|
|
|
<div class={classesWrapper.join(' ')}>
|
2019-07-05 00:02:14 -07:00
|
|
|
<button
|
|
|
|
disabled={slot.data.attrs.disabled}
|
|
|
|
onClick={this.activateTab(index)}
|
2020-05-25 06:10:14 -07:00
|
|
|
class={classesTab.join(' ')}
|
2020-05-26 17:32:57 -07:00
|
|
|
type="button"
|
2020-05-25 06:10:14 -07:00
|
|
|
>
|
|
|
|
{!slot.data.attrs.icon ? '' : (<i class={'tab-icon icon-' + slot.data.attrs.icon}/>)}
|
2020-05-26 17:32:57 -07:00
|
|
|
<span class="text">
|
|
|
|
{slot.data.attrs.label}
|
|
|
|
</span>
|
2020-05-25 06:10:14 -07:00
|
|
|
</button>
|
2019-07-05 00:02:14 -07:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
})
|
2019-01-17 11:25:50 -08:00
|
|
|
|
|
|
|
const contents = this.$slots.default.map((slot, index) => {
|
|
|
|
if (!slot.tag) return
|
2019-08-10 11:48:05 -07:00
|
|
|
const active = this.activeIndex === index
|
2020-05-23 16:06:55 -07:00
|
|
|
const classes = [ active ? 'active' : 'hidden' ]
|
|
|
|
if (slot.data.attrs.fullHeight) {
|
|
|
|
classes.push('full-height')
|
|
|
|
}
|
2020-05-28 11:26:33 -07:00
|
|
|
const renderSlot = (!this.renderOnlyFocused || active)
|
|
|
|
? slot
|
|
|
|
: ''
|
|
|
|
|
|
|
|
return (
|
2020-05-26 17:32:57 -07:00
|
|
|
<div class={classes}>
|
|
|
|
{
|
|
|
|
this.sideTabBar
|
|
|
|
? <h1 class="mobile-label">{slot.data.attrs.label}</h1>
|
|
|
|
: ''
|
|
|
|
}
|
2020-05-28 11:26:33 -07:00
|
|
|
{renderSlot}
|
2020-05-26 17:32:57 -07:00
|
|
|
</div>
|
|
|
|
)
|
2019-01-17 11:25:50 -08:00
|
|
|
})
|
|
|
|
|
2018-08-27 12:22:25 -07:00
|
|
|
return (
|
2020-05-03 07:36:12 -07:00
|
|
|
<div class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}>
|
2019-01-17 12:05:58 -08:00
|
|
|
<div class="tabs">
|
|
|
|
{tabs}
|
|
|
|
</div>
|
2020-05-25 04:16:03 -07:00
|
|
|
<div ref="contents" class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}>
|
2019-01-17 12:05:58 -08:00
|
|
|
{contents}
|
|
|
|
</div>
|
2018-11-21 11:08:27 -08:00
|
|
|
</div>
|
|
|
|
)
|
2018-08-27 12:22:25 -07:00
|
|
|
}
|
|
|
|
})
|