// Styles import "../../../src/components/VTabs/VTabs.sass"; // Components import VTabsBar from './VTabsBar'; import VTabsItems from './VTabsItems'; import VTabsSlider from './VTabsSlider'; // Mixins import Colorable from '../../mixins/colorable'; import Proxyable from '../../mixins/proxyable'; import Themeable from '../../mixins/themeable'; // Directives import Resize from '../../directives/resize'; // Utilities import { convertToUnit } from '../../util/helpers'; import mixins from '../../util/mixins'; const baseMixins = mixins(Colorable, Proxyable, Themeable); export default baseMixins.extend().extend({ name: 'v-tabs', directives: { Resize }, props: { activeClass: { type: String, default: '' }, alignWithTitle: Boolean, backgroundColor: String, centerActive: Boolean, centered: Boolean, fixedTabs: Boolean, grow: Boolean, height: { type: [Number, String], default: undefined }, hideSlider: Boolean, iconsAndText: Boolean, mobileBreakPoint: { type: [Number, String], default: 1264 }, nextIcon: { type: String, default: '$vuetify.icons.next' }, optional: Boolean, prevIcon: { type: String, default: '$vuetify.icons.prev' }, right: Boolean, showArrows: Boolean, sliderColor: String, sliderSize: { type: [Number, String], default: 2 }, vertical: Boolean }, data() { return { resizeTimeout: 0, slider: { height: null, left: null, right: null, top: null, width: null }, transitionTime: 300 }; }, computed: { classes() { return { 'v-tabs--align-with-title': this.alignWithTitle, 'v-tabs--centered': this.centered, 'v-tabs--fixed-tabs': this.fixedTabs, 'v-tabs--grow': this.grow, 'v-tabs--icons-and-text': this.iconsAndText, 'v-tabs--right': this.right, 'v-tabs--vertical': this.vertical, ...this.themeClasses }; }, isReversed() { return this.$vuetify.rtl && this.vertical; }, sliderStyles() { return { height: convertToUnit(this.slider.height), left: this.isReversed ? undefined : convertToUnit(this.slider.left), right: this.isReversed ? convertToUnit(this.slider.right) : undefined, top: this.vertical ? convertToUnit(this.slider.top) : undefined, transition: this.slider.left != null ? null : 'none', width: convertToUnit(this.slider.width) }; }, computedColor() { if (this.color) return this.color;else if (this.isDark && !this.appIsDark) return 'white';else return 'primary'; } }, watch: { alignWithTitle: 'callSlider', centered: 'callSlider', centerActive: 'callSlider', fixedTabs: 'callSlider', grow: 'callSlider', right: 'callSlider', showArrows: 'callSlider', vertical: 'callSlider', '$vuetify.application.left': 'onResize', '$vuetify.application.right': 'onResize', '$vuetify.rtl': 'onResize' }, mounted() { this.$nextTick(() => { window.setTimeout(this.callSlider, 30); }); }, methods: { callSlider() { if (this.hideSlider || !this.$refs.items || !this.$refs.items.selectedItems.length) { this.slider.width = 0; return false; } this.$nextTick(() => { // Give screen time to paint const activeTab = this.$refs.items.selectedItems[0]; /* istanbul ignore if */ if (!activeTab || !activeTab.$el) { this.slider.width = 0; this.slider.left = 0; return; } const el = activeTab.$el; this.slider = { height: !this.vertical ? Number(this.sliderSize) : el.scrollHeight, left: this.vertical ? 0 : el.offsetLeft, right: this.vertical ? 0 : el.offsetLeft + el.offsetWidth, top: el.offsetTop, width: this.vertical ? Number(this.sliderSize) : el.scrollWidth }; }); return true; }, genBar(items, slider) { const data = { style: { height: convertToUnit(this.height) }, props: { activeClass: this.activeClass, centerActive: this.centerActive, dark: this.dark, light: this.light, mandatory: !this.optional, mobileBreakPoint: this.mobileBreakPoint, nextIcon: this.nextIcon, prevIcon: this.prevIcon, showArrows: this.showArrows, value: this.internalValue }, on: { 'call:slider': this.callSlider, change: val => { this.internalValue = val; } }, ref: 'items' }; this.setTextColor(this.computedColor, data); this.setBackgroundColor(this.backgroundColor, data); return this.$createElement(VTabsBar, data, [this.genSlider(slider), items]); }, genItems(items, item) { // If user provides items // opt to use theirs if (items) return items; // If no tabs are provided // render nothing if (!item.length) return null; return this.$createElement(VTabsItems, { props: { value: this.internalValue }, on: { change: val => { this.internalValue = val; } } }, item); }, genSlider(slider) { if (this.hideSlider) return null; if (!slider) { slider = this.$createElement(VTabsSlider, { props: { color: this.sliderColor } }); } return this.$createElement('div', { staticClass: 'v-tabs-slider-wrapper', style: this.sliderStyles }, [slider]); }, onResize() { if (this._isDestroyed) return; clearTimeout(this.resizeTimeout); this.resizeTimeout = window.setTimeout(this.callSlider, 0); }, parseNodes() { let items = null; let slider = null; const item = []; const tab = []; const slot = this.$slots.default || []; const length = slot.length; for (let i = 0; i < length; i++) { const vnode = slot[i]; if (vnode.componentOptions) { switch (vnode.componentOptions.Ctor.options.name) { case 'v-tabs-slider': slider = vnode; break; case 'v-tabs-items': items = vnode; break; case 'v-tab-item': item.push(vnode); break; // case 'v-tab' - intentionally omitted default: tab.push(vnode); } } else { tab.push(vnode); } } /** * tab: array of `v-tab` * slider: single `v-tabs-slider` * items: single `v-tabs-items` * item: array of `v-tab-item` */ return { tab, slider, items, item }; } }, render(h) { const { tab, slider, items, item } = this.parseNodes(); return h('div', { staticClass: 'v-tabs', class: this.classes, directives: [{ name: 'resize', modifiers: { quiet: true }, value: this.onResize }] }, [this.genBar(tab, slider), this.genItems(items, item)]); } }); //# sourceMappingURL=VTabs.js.map