UNPKG

vuetify

Version:

Vue.js 2 Semantic Component Framework

180 lines (177 loc) 6.45 kB
import '../../../src/stylus/components/_menus.styl'; import Vue from 'vue'; // Mixins import Delayable from '../../mixins/delayable'; import Dependent from '../../mixins/dependent'; import Detachable from '../../mixins/detachable'; import Menuable from '../../mixins/menuable.js'; import Returnable from '../../mixins/returnable'; import Toggleable from '../../mixins/toggleable'; import Themeable from '../../mixins/themeable'; // Component level mixins import Activator from './mixins/menu-activator'; import Generators from './mixins/menu-generators'; import Keyable from './mixins/menu-keyable'; import Position from './mixins/menu-position'; // Directives import ClickOutside from '../../directives/click-outside'; import Resize from '../../directives/resize'; // Helpers import { convertToUnit } from '../../util/helpers'; import ThemeProvider from '../../util/ThemeProvider'; /* @vue/component */ export default Vue.extend({ name: 'v-menu', provide: function provide() { return { // Pass theme through to default slot theme: this.theme }; }, directives: { ClickOutside: ClickOutside, Resize: Resize }, mixins: [Activator, Dependent, Delayable, Detachable, Generators, Keyable, Menuable, Position, Returnable, Toggleable, Themeable], props: { auto: Boolean, closeOnClick: { type: Boolean, default: true }, closeOnContentClick: { type: Boolean, default: true }, disabled: Boolean, fullWidth: Boolean, maxHeight: { default: 'auto' }, offsetX: Boolean, offsetY: Boolean, openOnClick: { type: Boolean, default: true }, openOnHover: Boolean, origin: { type: String, default: 'top left' }, transition: { type: [Boolean, String], default: 'v-menu-transition' } }, data: function data() { return { defaultOffset: 8, hasJustFocused: false, resizeTimeout: null }; }, computed: { calculatedLeft: function calculatedLeft() { if (!this.auto) return this.calcLeft(); return this.calcXOverflow(this.calcLeftAuto()) + 'px'; }, calculatedMaxHeight: function calculatedMaxHeight() { return this.auto ? '200px' : convertToUnit(this.maxHeight); }, calculatedMaxWidth: function calculatedMaxWidth() { return isNaN(this.maxWidth) ? this.maxWidth : this.maxWidth + 'px'; }, calculatedMinWidth: function calculatedMinWidth() { if (this.minWidth) { return isNaN(this.minWidth) ? this.minWidth : this.minWidth + 'px'; } var minWidth = this.dimensions.activator.width + this.nudgeWidth + (this.auto ? 16 : 0); var calculatedMaxWidth = isNaN(parseInt(this.calculatedMaxWidth)) ? minWidth : parseInt(this.calculatedMaxWidth); return Math.min(calculatedMaxWidth, minWidth) + 'px'; }, calculatedTop: function calculatedTop() { if (!this.auto || this.isAttached) return this.calcTop(); return this.calcYOverflow(this.calculatedTopAuto) + 'px'; }, styles: function styles() { return { maxHeight: this.calculatedMaxHeight, minWidth: this.calculatedMinWidth, maxWidth: this.calculatedMaxWidth, top: this.calculatedTop, left: this.calculatedLeft, transformOrigin: this.origin, zIndex: this.zIndex || this.activeZIndex }; } }, watch: { activator: function activator(newActivator, oldActivator) { this.removeActivatorEvents(oldActivator); this.addActivatorEvents(newActivator); }, isContentActive: function isContentActive(val) { this.hasJustFocused = val; } }, methods: { activate: function activate() { var _this = this; // This exists primarily for v-select // helps determine which tiles to activate this.getTiles(); // Update coordinates and dimensions of menu // and its activator this.updateDimensions(); // Start the transition requestAnimationFrame(function () { // Once transitioning, calculate scroll and top position _this.startTransition().then(function () { if (_this.$refs.content) { _this.calculatedTopAuto = _this.calcTopAuto(); _this.auto && (_this.$refs.content.scrollTop = _this.calcScrollPosition()); } }); }); }, closeConditional: function closeConditional() { return this.isActive && this.closeOnClick; }, onResize: function onResize() { if (!this.isActive) return; // Account for screen resize // and orientation change // eslint-disable-next-line no-unused-expressions this.$refs.content.offsetWidth; this.updateDimensions(); // When resizing to a smaller width // content width is evaluated before // the new activator width has been // set, causing it to not size properly // hacky but will revisit in the future clearTimeout(this.resizeTimeout); this.resizeTimeout = setTimeout(this.updateDimensions, 100); } }, render: function render(h) { var data = { staticClass: 'v-menu', class: { 'v-menu--inline': !this.fullWidth && this.$slots.activator }, directives: [{ arg: 500, name: 'resize', value: this.onResize }], on: { keydown: this.onKeyDown } }; return h('div', data, [this.genActivator(), this.$createElement(ThemeProvider, { props: { root: true, light: this.light, dark: this.dark } }, [this.genTransition()])]); } }); //# sourceMappingURL=VMenu.js.map