// Styles import "../../../src/components/VNavigationDrawer/VNavigationDrawer.sass"; // Components import VImg from '../VImg/VImg'; // Mixins import Applicationable from '../../mixins/applicationable'; import Colorable from '../../mixins/colorable'; import Dependent from '../../mixins/dependent'; import Overlayable from '../../mixins/overlayable'; import SSRBootable from '../../mixins/ssr-bootable'; import Themeable from '../../mixins/themeable'; // Directives import ClickOutside from '../../directives/click-outside'; import Resize from '../../directives/resize'; import Touch from '../../directives/touch'; // Utilities import { convertToUnit, getSlot } from '../../util/helpers'; import mixins from '../../util/mixins'; const baseMixins = mixins(Applicationable('left', ['isActive', 'isMobile', 'miniVariant', 'expandOnHover', 'permanent', 'right', 'temporary', 'width']), Colorable, Dependent, Overlayable, SSRBootable, Themeable); /* @vue/component */ export default baseMixins.extend({ name: 'v-navigation-drawer', provide() { return { isInNav: this.tag === 'nav' }; }, directives: { ClickOutside, Resize, Touch }, props: { bottom: Boolean, clipped: Boolean, disableResizeWatcher: Boolean, disableRouteWatcher: Boolean, expandOnHover: Boolean, floating: Boolean, height: { type: [Number, String], default() { return this.app ? '100vh' : '100%'; } }, miniVariant: Boolean, miniVariantWidth: { type: [Number, String], default: 80 }, mobileBreakPoint: { type: [Number, String], default: 1264 }, permanent: Boolean, right: Boolean, src: { type: [String, Object], default: '' }, stateless: Boolean, tag: { type: String, default() { return this.app ? 'nav' : 'aside'; } }, temporary: Boolean, touchless: Boolean, width: { type: [Number, String], default: 256 }, value: { required: false } }, data: () => ({ isMouseover: false, touchArea: { left: 0, right: 0 } }), computed: { /** * Used for setting an app value from a dynamic * property. Called from applicationable.js */ applicationProperty() { return this.right ? 'right' : 'left'; }, classes() { return { 'v-navigation-drawer': true, 'v-navigation-drawer--absolute': this.absolute, 'v-navigation-drawer--bottom': this.bottom, 'v-navigation-drawer--clipped': this.clipped, 'v-navigation-drawer--close': !this.isActive, 'v-navigation-drawer--fixed': !this.absolute && (this.app || this.fixed), 'v-navigation-drawer--floating': this.floating, 'v-navigation-drawer--is-mobile': this.isMobile, 'v-navigation-drawer--is-mouseover': this.isMouseover, 'v-navigation-drawer--mini-variant': this.miniVariant || this.expandOnHover && !this.isMouseover, 'v-navigation-drawer--open': this.isActive, 'v-navigation-drawer--open-on-hover': this.expandOnHover, 'v-navigation-drawer--right': this.right, 'v-navigation-drawer--temporary': this.temporary, ...this.themeClasses }; }, computedMaxHeight() { if (!this.hasApp) return null; const computedMaxHeight = this.$vuetify.application.bottom + this.$vuetify.application.footer + this.$vuetify.application.bar; if (!this.clipped) return computedMaxHeight; return computedMaxHeight + this.$vuetify.application.top; }, computedTop() { if (!this.hasApp) return 0; let computedTop = this.$vuetify.application.bar; computedTop += this.clipped ? this.$vuetify.application.top : 0; return computedTop; }, computedTransform() { if (this.isActive) return 0; if (this.isBottom) return 100; return this.right ? 100 : -100; }, computedWidth() { if (this.expandOnHover && !this.isMouseover || this.miniVariant) return this.miniVariantWidth; return this.width; }, hasApp() { return this.app && !this.isMobile && !this.temporary; }, isBottom() { return this.bottom && this.isMobile; }, isMobile() { return !this.stateless && !this.permanent && this.$vuetify.breakpoint.width < parseInt(this.mobileBreakPoint, 10); }, reactsToClick() { return !this.stateless && !this.permanent && (this.isMobile || this.temporary); }, reactsToMobile() { return this.app && !this.disableResizeWatcher && !this.permanent && !this.stateless && !this.temporary; }, reactsToResize() { return !this.disableResizeWatcher && !this.stateless; }, reactsToRoute() { return !this.disableRouteWatcher && !this.stateless && (this.temporary || this.isMobile); }, showOverlay() { return this.isActive && (this.isMobile || this.temporary); }, styles() { const translate = this.isBottom ? 'translateY' : 'translateX'; const styles = { height: convertToUnit(this.height), top: !this.isBottom ? convertToUnit(this.computedTop) : 'auto', maxHeight: this.computedMaxHeight != null ? `calc(100% - ${convertToUnit(this.computedMaxHeight)})` : undefined, transform: `${translate}(${convertToUnit(this.computedTransform, '%')})`, width: convertToUnit(this.computedWidth) }; return styles; } }, watch: { $route: 'onRouteChange', isActive(val) { this.$emit('input', val); }, /** * When mobile changes, adjust the active state * only when there has been a previous value */ isMobile(val, prev) { !val && this.isActive && !this.temporary && this.removeOverlay(); if (prev == null || !this.reactsToResize || !this.reactsToMobile) return; this.isActive = !val; }, permanent(val) { // If enabling prop enable the drawer if (val) this.isActive = true; }, showOverlay(val) { if (val) this.genOverlay();else this.removeOverlay(); }, value(val) { if (this.permanent) return; if (val == null) { this.init(); return; } if (val !== this.isActive) this.isActive = val; } }, beforeMount() { this.init(); }, methods: { calculateTouchArea() { const parent = this.$el.parentNode; if (!parent) return; const parentRect = parent.getBoundingClientRect(); this.touchArea = { left: parentRect.left + 50, right: parentRect.right - 50 }; }, closeConditional() { return this.isActive && this.reactsToClick; }, genAppend() { return this.genPosition('append'); }, genBackground() { const props = { height: '100%', width: '100%', src: this.src }; const image = this.$scopedSlots.img ? this.$scopedSlots.img(props) : this.$createElement(VImg, { props }); return this.$createElement('div', { staticClass: 'v-navigation-drawer__image' }, [image]); }, genDirectives() { const directives = [{ name: 'click-outside', value: () => this.isActive = false, args: { closeConditional: this.closeConditional, include: this.getOpenDependentElements } }]; if (!this.touchless && !this.stateless) { directives.push({ name: 'touch', value: { parent: true, left: this.swipeLeft, right: this.swipeRight } }); } return directives; }, genListeners() { const on = { transitionend: e => { if (e.target !== e.currentTarget) return; this.$emit('transitionend', e); // IE11 does not support new Event('resize') const resizeEvent = document.createEvent('UIEvents'); resizeEvent.initUIEvent('resize', true, false, window, 0); window.dispatchEvent(resizeEvent); } }; if (this.miniVariant) { on.click = () => this.$emit('update:mini-variant', false); } if (this.expandOnHover) { on.mouseenter = () => this.isMouseover = true; on.mouseleave = () => this.isMouseover = false; } return on; }, genPosition(name) { const slot = getSlot(this, name); if (!slot) return slot; return this.$createElement('div', { staticClass: `v-navigation-drawer__${name}` }, slot); }, genPrepend() { return this.genPosition('prepend'); }, genContent() { return this.$createElement('div', { staticClass: 'v-navigation-drawer__content' }, this.$slots.default); }, genBorder() { return this.$createElement('div', { staticClass: 'v-navigation-drawer__border' }); }, init() { if (this.permanent) { this.isActive = true; } else if (this.stateless || this.value != null) { this.isActive = this.value; } else if (!this.temporary) { this.isActive = !this.isMobile; } }, onRouteChange() { if (this.reactsToRoute && this.closeConditional()) { this.isActive = false; } }, swipeLeft(e) { if (this.isActive && this.right) return; this.calculateTouchArea(); if (Math.abs(e.touchendX - e.touchstartX) < 100) return; if (this.right && e.touchstartX >= this.touchArea.right) this.isActive = true;else if (!this.right && this.isActive) this.isActive = false; }, swipeRight(e) { if (this.isActive && !this.right) return; this.calculateTouchArea(); if (Math.abs(e.touchendX - e.touchstartX) < 100) return; if (!this.right && e.touchstartX <= this.touchArea.left) this.isActive = true;else if (this.right && this.isActive) this.isActive = false; }, /** * Update the application layout */ updateApplication() { if (!this.isActive || this.isMobile || this.temporary || !this.$el) return 0; const width = Number(this.computedWidth); return isNaN(width) ? this.$el.clientWidth : width; } }, render(h) { const children = [this.genPrepend(), this.genContent(), this.genAppend(), this.genBorder()]; if (this.src || getSlot(this, 'img')) children.unshift(this.genBackground()); return h(this.tag, this.setBackgroundColor(this.color, { class: this.classes, style: this.styles, directives: this.genDirectives(), on: this.genListeners() }), children); } }); //# sourceMappingURL=VNavigationDrawer.js.map