438 lines
15 KiB
JavaScript
438 lines
15 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.default = void 0;
|
||
|
|
||
|
require("../../../src/components/VMenu/VMenu.sass");
|
||
|
|
||
|
var _delayable = _interopRequireDefault(require("../../mixins/delayable"));
|
||
|
|
||
|
var _dependent = _interopRequireDefault(require("../../mixins/dependent"));
|
||
|
|
||
|
var _detachable = _interopRequireDefault(require("../../mixins/detachable"));
|
||
|
|
||
|
var _menuable = _interopRequireDefault(require("../../mixins/menuable"));
|
||
|
|
||
|
var _returnable = _interopRequireDefault(require("../../mixins/returnable"));
|
||
|
|
||
|
var _toggleable = _interopRequireDefault(require("../../mixins/toggleable"));
|
||
|
|
||
|
var _themeable = _interopRequireDefault(require("../../mixins/themeable"));
|
||
|
|
||
|
var _clickOutside = _interopRequireDefault(require("../../directives/click-outside"));
|
||
|
|
||
|
var _resize = _interopRequireDefault(require("../../directives/resize"));
|
||
|
|
||
|
var _mixins = _interopRequireDefault(require("../../util/mixins"));
|
||
|
|
||
|
var _helpers = require("../../util/helpers");
|
||
|
|
||
|
var _ThemeProvider = _interopRequireDefault(require("../../util/ThemeProvider"));
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
|
||
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
|
||
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||
|
|
||
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
|
||
|
|
||
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
|
||
|
|
||
|
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
|
||
|
|
||
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
|
||
|
|
||
|
var baseMixins = (0, _mixins.default)(_dependent.default, _delayable.default, _detachable.default, _menuable.default, _returnable.default, _toggleable.default, _themeable.default);
|
||
|
/* @vue/component */
|
||
|
|
||
|
var _default = baseMixins.extend({
|
||
|
name: 'v-menu',
|
||
|
provide: function provide() {
|
||
|
return {
|
||
|
isInMenu: true,
|
||
|
// Pass theme through to default slot
|
||
|
theme: this.theme
|
||
|
};
|
||
|
},
|
||
|
directives: {
|
||
|
ClickOutside: _clickOutside.default,
|
||
|
Resize: _resize.default
|
||
|
},
|
||
|
props: {
|
||
|
auto: Boolean,
|
||
|
closeOnClick: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
},
|
||
|
closeOnContentClick: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
},
|
||
|
disabled: Boolean,
|
||
|
disableKeys: Boolean,
|
||
|
fullWidth: Boolean,
|
||
|
maxHeight: {
|
||
|
type: [Number, String],
|
||
|
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 {
|
||
|
calculatedTopAuto: 0,
|
||
|
defaultOffset: 8,
|
||
|
hasJustFocused: false,
|
||
|
listIndex: -1,
|
||
|
resizeTimeout: 0,
|
||
|
selectedIndex: null,
|
||
|
tiles: []
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
activeTile: function activeTile() {
|
||
|
return this.tiles[this.listIndex];
|
||
|
},
|
||
|
calculatedLeft: function calculatedLeft() {
|
||
|
var menuWidth = Math.max(this.dimensions.content.width, parseFloat(this.calculatedMinWidth));
|
||
|
if (!this.auto) return this.calcLeft(menuWidth) || '0';
|
||
|
return (0, _helpers.convertToUnit)(this.calcXOverflow(this.calcLeftAuto(), menuWidth)) || '0';
|
||
|
},
|
||
|
calculatedMaxHeight: function calculatedMaxHeight() {
|
||
|
var height = this.auto ? '200px' : (0, _helpers.convertToUnit)(this.maxHeight);
|
||
|
return height || '0';
|
||
|
},
|
||
|
calculatedMaxWidth: function calculatedMaxWidth() {
|
||
|
return (0, _helpers.convertToUnit)(this.maxWidth) || '0';
|
||
|
},
|
||
|
calculatedMinWidth: function calculatedMinWidth() {
|
||
|
if (this.minWidth) {
|
||
|
return (0, _helpers.convertToUnit)(this.minWidth) || '0';
|
||
|
}
|
||
|
|
||
|
var minWidth = Math.min(this.dimensions.activator.width + Number(this.nudgeWidth) + (this.auto ? 16 : 0), Math.max(this.pageWidth - 24, 0));
|
||
|
var calculatedMaxWidth = isNaN(parseInt(this.calculatedMaxWidth)) ? minWidth : parseInt(this.calculatedMaxWidth);
|
||
|
return (0, _helpers.convertToUnit)(Math.min(calculatedMaxWidth, minWidth)) || '0';
|
||
|
},
|
||
|
calculatedTop: function calculatedTop() {
|
||
|
var top = !this.auto ? this.calcTop() : (0, _helpers.convertToUnit)(this.calcYOverflow(this.calculatedTopAuto));
|
||
|
return top || '0';
|
||
|
},
|
||
|
hasClickableTiles: function hasClickableTiles() {
|
||
|
return Boolean(this.tiles.find(function (tile) {
|
||
|
return tile.tabIndex > -1;
|
||
|
}));
|
||
|
},
|
||
|
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: {
|
||
|
isActive: function isActive(val) {
|
||
|
if (!val) this.listIndex = -1;
|
||
|
},
|
||
|
isContentActive: function isContentActive(val) {
|
||
|
this.hasJustFocused = val;
|
||
|
},
|
||
|
listIndex: function listIndex(next, prev) {
|
||
|
if (next in this.tiles) {
|
||
|
var tile = this.tiles[next];
|
||
|
tile.classList.add('v-list-item--highlighted');
|
||
|
this.$refs.content.scrollTop = tile.offsetTop - tile.clientHeight;
|
||
|
}
|
||
|
|
||
|
prev in this.tiles && this.tiles[prev].classList.remove('v-list-item--highlighted');
|
||
|
}
|
||
|
},
|
||
|
mounted: function mounted() {
|
||
|
this.isActive && this.callActivate();
|
||
|
},
|
||
|
methods: {
|
||
|
activate: function activate() {
|
||
|
var _this = this;
|
||
|
|
||
|
// 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());
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
calcScrollPosition: function calcScrollPosition() {
|
||
|
var $el = this.$refs.content;
|
||
|
var activeTile = $el.querySelector('.v-list-item--active');
|
||
|
var maxScrollTop = $el.scrollHeight - $el.offsetHeight;
|
||
|
return activeTile ? Math.min(maxScrollTop, Math.max(0, activeTile.offsetTop - $el.offsetHeight / 2 + activeTile.offsetHeight / 2)) : $el.scrollTop;
|
||
|
},
|
||
|
calcLeftAuto: function calcLeftAuto() {
|
||
|
return parseInt(this.dimensions.activator.left - this.defaultOffset * 2);
|
||
|
},
|
||
|
calcTopAuto: function calcTopAuto() {
|
||
|
var $el = this.$refs.content;
|
||
|
var activeTile = $el.querySelector('.v-list-item--active');
|
||
|
|
||
|
if (!activeTile) {
|
||
|
this.selectedIndex = null;
|
||
|
}
|
||
|
|
||
|
if (this.offsetY || !activeTile) {
|
||
|
return this.computedTop;
|
||
|
}
|
||
|
|
||
|
this.selectedIndex = Array.from(this.tiles).indexOf(activeTile);
|
||
|
var tileDistanceFromMenuTop = activeTile.offsetTop - this.calcScrollPosition();
|
||
|
var firstTileOffsetTop = $el.querySelector('.v-list-item').offsetTop;
|
||
|
return this.computedTop - tileDistanceFromMenuTop - firstTileOffsetTop - 1;
|
||
|
},
|
||
|
changeListIndex: function changeListIndex(e) {
|
||
|
// For infinite scroll and autocomplete, re-evaluate children
|
||
|
this.getTiles();
|
||
|
|
||
|
if (!this.isActive || !this.hasClickableTiles) {
|
||
|
return;
|
||
|
} else if (e.keyCode === _helpers.keyCodes.tab) {
|
||
|
this.isActive = false;
|
||
|
return;
|
||
|
} else if (e.keyCode === _helpers.keyCodes.down) {
|
||
|
this.nextTile();
|
||
|
} else if (e.keyCode === _helpers.keyCodes.up) {
|
||
|
this.prevTile();
|
||
|
} else if (e.keyCode === _helpers.keyCodes.enter && this.listIndex !== -1) {
|
||
|
this.tiles[this.listIndex].click();
|
||
|
} else {
|
||
|
return;
|
||
|
} // One of the conditions was met, prevent default action (#2988)
|
||
|
|
||
|
|
||
|
e.preventDefault();
|
||
|
},
|
||
|
closeConditional: function closeConditional(e) {
|
||
|
var target = e.target;
|
||
|
return this.isActive && this.closeOnClick && !this.$refs.content.contains(target);
|
||
|
},
|
||
|
genActivatorListeners: function genActivatorListeners() {
|
||
|
var listeners = _menuable.default.options.methods.genActivatorListeners.call(this);
|
||
|
|
||
|
if (!this.disableKeys) {
|
||
|
listeners.keydown = this.onKeyDown;
|
||
|
}
|
||
|
|
||
|
return listeners;
|
||
|
},
|
||
|
genTransition: function genTransition() {
|
||
|
if (!this.transition) return this.genContent();
|
||
|
return this.$createElement('transition', {
|
||
|
props: {
|
||
|
name: this.transition
|
||
|
}
|
||
|
}, [this.genContent()]);
|
||
|
},
|
||
|
genDirectives: function genDirectives() {
|
||
|
var _this2 = this;
|
||
|
|
||
|
var directives = [{
|
||
|
name: 'show',
|
||
|
value: this.isContentActive
|
||
|
}]; // Do not add click outside for hover menu
|
||
|
|
||
|
if (!this.openOnHover && this.closeOnClick) {
|
||
|
directives.push({
|
||
|
name: 'click-outside',
|
||
|
value: function value() {
|
||
|
_this2.isActive = false;
|
||
|
},
|
||
|
args: {
|
||
|
closeConditional: this.closeConditional,
|
||
|
include: function include() {
|
||
|
return [_this2.$el].concat(_toConsumableArray(_this2.getOpenDependentElements()));
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return directives;
|
||
|
},
|
||
|
genContent: function genContent() {
|
||
|
var _this3 = this;
|
||
|
|
||
|
var options = {
|
||
|
attrs: _objectSpread({}, this.getScopeIdAttrs(), {
|
||
|
role: 'role' in this.$attrs ? this.$attrs.role : 'menu'
|
||
|
}),
|
||
|
staticClass: 'v-menu__content',
|
||
|
class: _objectSpread({}, this.rootThemeClasses, _defineProperty({
|
||
|
'v-menu__content--auto': this.auto,
|
||
|
'v-menu__content--fixed': this.activatorFixed,
|
||
|
menuable__content__active: this.isActive
|
||
|
}, this.contentClass.trim(), true)),
|
||
|
style: this.styles,
|
||
|
directives: this.genDirectives(),
|
||
|
ref: 'content',
|
||
|
on: {
|
||
|
click: function click(e) {
|
||
|
e.stopPropagation();
|
||
|
var target = e.target;
|
||
|
if (target.getAttribute('disabled')) return;
|
||
|
if (_this3.closeOnContentClick) _this3.isActive = false;
|
||
|
},
|
||
|
keydown: this.onKeyDown
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (!this.disabled && this.openOnHover) {
|
||
|
options.on = options.on || {};
|
||
|
options.on.mouseenter = this.mouseEnterHandler;
|
||
|
}
|
||
|
|
||
|
if (this.openOnHover) {
|
||
|
options.on = options.on || {};
|
||
|
options.on.mouseleave = this.mouseLeaveHandler;
|
||
|
}
|
||
|
|
||
|
return this.$createElement('div', options, this.showLazyContent(this.getContentSlot()));
|
||
|
},
|
||
|
getTiles: function getTiles() {
|
||
|
this.tiles = Array.from(this.$refs.content.querySelectorAll('.v-list-item'));
|
||
|
},
|
||
|
mouseEnterHandler: function mouseEnterHandler() {
|
||
|
var _this4 = this;
|
||
|
|
||
|
this.runDelay('open', function () {
|
||
|
if (_this4.hasJustFocused) return;
|
||
|
_this4.hasJustFocused = true;
|
||
|
_this4.isActive = true;
|
||
|
});
|
||
|
},
|
||
|
mouseLeaveHandler: function mouseLeaveHandler(e) {
|
||
|
var _this5 = this;
|
||
|
|
||
|
// Prevent accidental re-activation
|
||
|
this.runDelay('close', function () {
|
||
|
if (_this5.$refs.content.contains(e.relatedTarget)) return;
|
||
|
requestAnimationFrame(function () {
|
||
|
_this5.isActive = false;
|
||
|
|
||
|
_this5.callDeactivate();
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
nextTile: function nextTile() {
|
||
|
var tile = this.tiles[this.listIndex + 1];
|
||
|
|
||
|
if (!tile) {
|
||
|
if (!this.tiles.length) return;
|
||
|
this.listIndex = -1;
|
||
|
this.nextTile();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.listIndex++;
|
||
|
if (tile.tabIndex === -1) this.nextTile();
|
||
|
},
|
||
|
prevTile: function prevTile() {
|
||
|
var tile = this.tiles[this.listIndex - 1];
|
||
|
|
||
|
if (!tile) {
|
||
|
if (!this.tiles.length) return;
|
||
|
this.listIndex = this.tiles.length;
|
||
|
this.prevTile();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.listIndex--;
|
||
|
if (tile.tabIndex === -1) this.prevTile();
|
||
|
},
|
||
|
onKeyDown: function onKeyDown(e) {
|
||
|
var _this6 = this;
|
||
|
|
||
|
if (e.keyCode === _helpers.keyCodes.esc) {
|
||
|
// Wait for dependent elements to close first
|
||
|
setTimeout(function () {
|
||
|
_this6.isActive = false;
|
||
|
});
|
||
|
var activator = this.getActivator();
|
||
|
this.$nextTick(function () {
|
||
|
return activator && activator.focus();
|
||
|
});
|
||
|
} else if (!this.isActive && [_helpers.keyCodes.up, _helpers.keyCodes.down].includes(e.keyCode)) {
|
||
|
this.isActive = true;
|
||
|
} // Allow for isActive watcher to generate tile list
|
||
|
|
||
|
|
||
|
this.$nextTick(function () {
|
||
|
return _this6.changeListIndex(e);
|
||
|
});
|
||
|
},
|
||
|
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 = window.setTimeout(this.updateDimensions, 100);
|
||
|
}
|
||
|
},
|
||
|
render: function render(h) {
|
||
|
var data = {
|
||
|
staticClass: 'v-menu',
|
||
|
class: {
|
||
|
'v-menu--inline': !this.fullWidth && (this.$slots.activator || this.$scopedSlots.activator)
|
||
|
},
|
||
|
directives: [{
|
||
|
arg: '500',
|
||
|
name: 'resize',
|
||
|
value: this.onResize
|
||
|
}]
|
||
|
};
|
||
|
return h('div', data, [this.genActivator(), this.$createElement(_ThemeProvider.default, {
|
||
|
props: {
|
||
|
root: true,
|
||
|
light: this.light,
|
||
|
dark: this.dark
|
||
|
}
|
||
|
}, [this.genTransition()])]);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
exports.default = _default;
|
||
|
//# sourceMappingURL=VMenu.js.map
|