123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
- import Vue from 'vue';
- import Positionable from './positionable';
- import Stackable from './stackable';
- /* eslint-disable object-property-newline */
- var dimensions = {
- activator: {
- top: 0, left: 0,
- bottom: 0, right: 0,
- width: 0, height: 0,
- offsetTop: 0, scrollHeight: 0
- },
- content: {
- top: 0, left: 0,
- bottom: 0, right: 0,
- width: 0, height: 0,
- offsetTop: 0, scrollHeight: 0
- },
- hasWindow: false
- };
- /* eslint-enable object-property-newline */
- /**
- * Menuable
- *
- * @mixin
- *
- * Used for fixed or absolutely positioning
- * elements within the DOM
- * Can calculate X and Y axis overflows
- * As well as be manually positioned
- */
- /* @vue/component */
- export default Vue.extend({
- name: 'menuable',
- mixins: [Positionable, Stackable],
- props: {
- activator: {
- default: null,
- validator: function validator(val) {
- return ['string', 'object'].includes(typeof val === 'undefined' ? 'undefined' : _typeof(val));
- }
- },
- allowOverflow: Boolean,
- inputActivator: Boolean,
- light: Boolean,
- dark: Boolean,
- maxWidth: {
- type: [Number, String],
- default: 'auto'
- },
- minWidth: [Number, String],
- nudgeBottom: {
- type: [Number, String],
- default: 0
- },
- nudgeLeft: {
- type: [Number, String],
- default: 0
- },
- nudgeRight: {
- type: [Number, String],
- default: 0
- },
- nudgeTop: {
- type: [Number, String],
- default: 0
- },
- nudgeWidth: {
- type: [Number, String],
- default: 0
- },
- offsetOverflow: Boolean,
- positionX: {
- type: Number,
- default: null
- },
- positionY: {
- type: Number,
- default: null
- },
- zIndex: {
- type: [Number, String],
- default: null
- }
- },
- data: function data() {
- return {
- absoluteX: 0,
- absoluteY: 0,
- activatorFixed: false,
- dimensions: Object.assign({}, dimensions),
- isContentActive: false,
- pageWidth: 0,
- pageYOffset: 0,
- stackClass: 'v-menu__content--active',
- stackMinZIndex: 6
- };
- },
- computed: {
- computedLeft: function computedLeft() {
- var a = this.dimensions.activator;
- var c = this.dimensions.content;
- var activatorLeft = (this.isAttached ? a.offsetLeft : a.left) || 0;
- var minWidth = Math.max(a.width, c.width);
- var left = 0;
- left += this.left ? activatorLeft - (minWidth - a.width) : activatorLeft;
- if (this.offsetX) {
- var maxWidth = isNaN(this.maxWidth) ? a.width : Math.min(a.width, this.maxWidth);
- left += this.left ? -maxWidth : a.width;
- }
- if (this.nudgeLeft) left -= parseInt(this.nudgeLeft);
- if (this.nudgeRight) left += parseInt(this.nudgeRight);
- return left;
- },
- computedTop: function computedTop() {
- var a = this.dimensions.activator;
- var c = this.dimensions.content;
- var top = 0;
- if (this.top) top += a.height - c.height;
- if (this.isAttached) top += a.offsetTop;else top += a.top + this.pageYOffset;
- if (this.offsetY) top += this.top ? -a.height : a.height;
- if (this.nudgeTop) top -= parseInt(this.nudgeTop);
- if (this.nudgeBottom) top += parseInt(this.nudgeBottom);
- return top;
- },
- hasActivator: function hasActivator() {
- return !!this.$slots.activator || !!this.$scopedSlots.activator || this.activator || this.inputActivator;
- },
- isAttached: function isAttached() {
- return this.attach !== false;
- }
- },
- watch: {
- disabled: function disabled(val) {
- val && this.callDeactivate();
- },
- isActive: function isActive(val) {
- if (this.disabled) return;
- val ? this.callActivate() : this.callDeactivate();
- },
-
- positionX: 'updateDimensions',
- positionY: 'updateDimensions'
- },
- beforeMount: function beforeMount() {
- this.checkForWindow();
- },
-
- methods: {
- absolutePosition: function absolutePosition() {
- return {
- offsetTop: 0,
- offsetLeft: 0,
- scrollHeight: 0,
- top: this.positionY || this.absoluteY,
- bottom: this.positionY || this.absoluteY,
- left: this.positionX || this.absoluteX,
- right: this.positionX || this.absoluteX,
- height: 0,
- width: 0
- };
- },
- activate: function activate() {},
- calcLeft: function calcLeft(menuWidth) {
- return (this.isAttached ? this.computedLeft : this.calcXOverflow(this.computedLeft, menuWidth)) + 'px';
- },
- calcTop: function calcTop() {
- return (this.isAttached ? this.computedTop : this.calcYOverflow(this.computedTop)) + 'px';
- },
- calcXOverflow: function calcXOverflow(left, menuWidth) {
- var xOverflow = left + menuWidth - this.pageWidth + 12;
- if ((!this.left || this.right) && xOverflow > 0) {
- left = Math.max(left - xOverflow, 0);
- } else {
- left = Math.max(left, 12);
- }
- return left + this.getOffsetLeft();
- },
- calcYOverflow: function calcYOverflow(top) {
- var documentHeight = this.getInnerHeight();
- var toTop = this.pageYOffset + documentHeight;
- var activator = this.dimensions.activator;
- var contentHeight = this.dimensions.content.height;
- var totalHeight = top + contentHeight;
- var isOverflowing = toTop < totalHeight;
- // If overflowing bottom and offset
- // TODO: set 'bottom' position instead of 'top'
- if (isOverflowing && this.offsetOverflow &&
- // If we don't have enough room to offset
- // the overflow, don't offset
- activator.top > contentHeight) {
- top = this.pageYOffset + (activator.top - contentHeight);
- // If overflowing bottom
- } else if (isOverflowing && !this.allowOverflow) {
- top = toTop - contentHeight - 12;
- // If overflowing top
- } else if (top < this.pageYOffset && !this.allowOverflow) {
- top = this.pageYOffset + 12;
- }
- return top < 12 ? 12 : top;
- },
- callActivate: function callActivate() {
- if (!this.hasWindow) return;
- this.activate();
- },
- callDeactivate: function callDeactivate() {
- this.isContentActive = false;
- this.deactivate();
- },
- checkForWindow: function checkForWindow() {
- if (!this.hasWindow) {
- this.hasWindow = typeof window !== 'undefined';
- }
- },
- checkForPageYOffset: function checkForPageYOffset() {
- if (this.hasWindow) {
- this.pageYOffset = this.activatorFixed ? 0 : this.getOffsetTop();
- }
- },
- checkActivatorFixed: function checkActivatorFixed() {
- if (this.attach !== false) return;
- var el = this.getActivator();
- while (el) {
- if (window.getComputedStyle(el).position === 'fixed') {
- this.activatorFixed = true;
- return;
- }
- el = el.offsetParent;
- }
- this.activatorFixed = false;
- },
- deactivate: function deactivate() {},
- getActivator: function getActivator(e) {
- if (this.inputActivator) {
- return this.$el.querySelector('.v-input__slot');
- }
- if (this.activator) {
- return typeof this.activator === 'string' ? document.querySelector(this.activator) : this.activator;
- }
- if (this.$refs.activator) {
- return this.$refs.activator.children.length > 0 ? this.$refs.activator.children[0] : this.$refs.activator;
- }
- if (e) {
- this.activatedBy = e.currentTarget || e.target;
- return this.activatedBy;
- }
- if (this.activatedBy) return this.activatedBy;
- if (this.activatorNode) {
- var activator = Array.isArray(this.activatorNode) ? this.activatorNode[0] : this.activatorNode;
- var el = activator && activator.elm;
- if (el) return el;
- }
- },
- getInnerHeight: function getInnerHeight() {
- if (!this.hasWindow) return 0;
- return window.innerHeight || document.documentElement.clientHeight;
- },
- getOffsetLeft: function getOffsetLeft() {
- if (!this.hasWindow) return 0;
- return window.pageXOffset || document.documentElement.scrollLeft;
- },
- getOffsetTop: function getOffsetTop() {
- if (!this.hasWindow) return 0;
- return window.pageYOffset || document.documentElement.scrollTop;
- },
- getRoundedBoundedClientRect: function getRoundedBoundedClientRect(el) {
- var rect = el.getBoundingClientRect();
- return {
- top: Math.round(rect.top),
- left: Math.round(rect.left),
- bottom: Math.round(rect.bottom),
- right: Math.round(rect.right),
- width: Math.round(rect.width),
- height: Math.round(rect.height)
- };
- },
- measure: function measure(el) {
- if (!el || !this.hasWindow) return null;
- var rect = this.getRoundedBoundedClientRect(el);
- // Account for activator margin
- if (this.isAttached) {
- var style = window.getComputedStyle(el);
- rect.left = parseInt(style.marginLeft);
- rect.top = parseInt(style.marginTop);
- }
- return rect;
- },
- sneakPeek: function sneakPeek(cb) {
- var _this = this;
-
- requestAnimationFrame(function () {
- var el = _this.$refs.content;
- if (!el || _this.isShown(el)) return cb();
- el.style.display = 'inline-block';
- cb();
- el.style.display = 'none';
- });
- },
- startTransition: function startTransition() {
- var _this2 = this;
-
- return new Promise(function (resolve) {
- return requestAnimationFrame(function () {
- _this2.isContentActive = _this2.hasJustFocused = _this2.isActive;
- resolve();
- });
- });
- },
- isShown: function isShown(el) {
- return el.style.display !== 'none';
- },
- updateDimensions: function updateDimensions() {
- var _this3 = this;
-
- this.checkForWindow();
- this.checkActivatorFixed();
- this.checkForPageYOffset();
- this.pageWidth = document.documentElement.clientWidth;
- var dimensions = {};
- // Activator should already be shown
- if (!this.hasActivator || this.absolute) {
- dimensions.activator = this.absolutePosition();
- } else {
- var activator = this.getActivator();
- dimensions.activator = this.measure(activator);
- dimensions.activator.offsetLeft = activator.offsetLeft;
- if (this.isAttached) {
- // account for css padding causing things to not line up
- // this is mostly for v-autocomplete, hopefully it won't break anything
- dimensions.activator.offsetTop = activator.offsetTop;
- } else {
- dimensions.activator.offsetTop = 0;
- }
- }
- // Display and hide to get dimensions
- this.sneakPeek(function () {
- dimensions.content = _this3.measure(_this3.$refs.content);
- _this3.dimensions = dimensions;
- });
- }
- }
- });
- //# sourceMappingURL=menuable.js.map
|