项目原始demo,不改动
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
Den här utvecklingskatalogen är arkiverad. Du kan se filer och klona katalogen, men inte öppna ärenden eller genomföra push- eller pull-förfrågningar.
 
 
 
 

463 rader
16 KiB

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. require("../../../src/components/VMenu/VMenu.sass");
  7. var _VThemeProvider = require("../VThemeProvider");
  8. var _activatable = _interopRequireDefault(require("../../mixins/activatable"));
  9. var _delayable = _interopRequireDefault(require("../../mixins/delayable"));
  10. var _dependent = _interopRequireDefault(require("../../mixins/dependent"));
  11. var _detachable = _interopRequireDefault(require("../../mixins/detachable"));
  12. var _menuable = _interopRequireDefault(require("../../mixins/menuable"));
  13. var _returnable = _interopRequireDefault(require("../../mixins/returnable"));
  14. var _toggleable = _interopRequireDefault(require("../../mixins/toggleable"));
  15. var _themeable = _interopRequireDefault(require("../../mixins/themeable"));
  16. var _clickOutside = _interopRequireDefault(require("../../directives/click-outside"));
  17. var _resize = _interopRequireDefault(require("../../directives/resize"));
  18. var _mixins = _interopRequireDefault(require("../../util/mixins"));
  19. var _console = require("../../util/console");
  20. var _helpers = require("../../util/helpers");
  21. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  22. function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
  23. function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
  24. function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
  25. 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; } }
  26. 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; }
  27. 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; }
  28. 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; }
  29. var baseMixins = (0, _mixins.default)(_dependent.default, _delayable.default, _detachable.default, _menuable.default, _returnable.default, _toggleable.default, _themeable.default);
  30. /* @vue/component */
  31. var _default = baseMixins.extend({
  32. name: 'v-menu',
  33. provide: function provide() {
  34. return {
  35. isInMenu: true,
  36. // Pass theme through to default slot
  37. theme: this.theme
  38. };
  39. },
  40. directives: {
  41. ClickOutside: _clickOutside.default,
  42. Resize: _resize.default
  43. },
  44. props: {
  45. auto: Boolean,
  46. closeOnClick: {
  47. type: Boolean,
  48. default: true
  49. },
  50. closeOnContentClick: {
  51. type: Boolean,
  52. default: true
  53. },
  54. disabled: Boolean,
  55. disableKeys: Boolean,
  56. maxHeight: {
  57. type: [Number, String],
  58. default: 'auto'
  59. },
  60. offsetX: Boolean,
  61. offsetY: Boolean,
  62. openOnClick: {
  63. type: Boolean,
  64. default: true
  65. },
  66. openOnHover: Boolean,
  67. origin: {
  68. type: String,
  69. default: 'top left'
  70. },
  71. transition: {
  72. type: [Boolean, String],
  73. default: 'v-menu-transition'
  74. }
  75. },
  76. data: function data() {
  77. return {
  78. calculatedTopAuto: 0,
  79. defaultOffset: 8,
  80. hasJustFocused: false,
  81. listIndex: -1,
  82. resizeTimeout: 0,
  83. selectedIndex: null,
  84. tiles: []
  85. };
  86. },
  87. computed: {
  88. activeTile: function activeTile() {
  89. return this.tiles[this.listIndex];
  90. },
  91. calculatedLeft: function calculatedLeft() {
  92. var menuWidth = Math.max(this.dimensions.content.width, parseFloat(this.calculatedMinWidth));
  93. if (!this.auto) return this.calcLeft(menuWidth) || '0';
  94. return (0, _helpers.convertToUnit)(this.calcXOverflow(this.calcLeftAuto(), menuWidth)) || '0';
  95. },
  96. calculatedMaxHeight: function calculatedMaxHeight() {
  97. var height = this.auto ? '200px' : (0, _helpers.convertToUnit)(this.maxHeight);
  98. return height || '0';
  99. },
  100. calculatedMaxWidth: function calculatedMaxWidth() {
  101. return (0, _helpers.convertToUnit)(this.maxWidth) || '0';
  102. },
  103. calculatedMinWidth: function calculatedMinWidth() {
  104. if (this.minWidth) {
  105. return (0, _helpers.convertToUnit)(this.minWidth) || '0';
  106. }
  107. var minWidth = Math.min(this.dimensions.activator.width + Number(this.nudgeWidth) + (this.auto ? 16 : 0), Math.max(this.pageWidth - 24, 0));
  108. var calculatedMaxWidth = isNaN(parseInt(this.calculatedMaxWidth)) ? minWidth : parseInt(this.calculatedMaxWidth);
  109. return (0, _helpers.convertToUnit)(Math.min(calculatedMaxWidth, minWidth)) || '0';
  110. },
  111. calculatedTop: function calculatedTop() {
  112. var top = !this.auto ? this.calcTop() : (0, _helpers.convertToUnit)(this.calcYOverflow(this.calculatedTopAuto));
  113. return top || '0';
  114. },
  115. hasClickableTiles: function hasClickableTiles() {
  116. return Boolean(this.tiles.find(function (tile) {
  117. return tile.tabIndex > -1;
  118. }));
  119. },
  120. styles: function styles() {
  121. return {
  122. maxHeight: this.calculatedMaxHeight,
  123. minWidth: this.calculatedMinWidth,
  124. maxWidth: this.calculatedMaxWidth,
  125. top: this.calculatedTop,
  126. left: this.calculatedLeft,
  127. transformOrigin: this.origin,
  128. zIndex: this.zIndex || this.activeZIndex
  129. };
  130. }
  131. },
  132. watch: {
  133. isActive: function isActive(val) {
  134. if (!val) this.listIndex = -1;
  135. },
  136. isContentActive: function isContentActive(val) {
  137. this.hasJustFocused = val;
  138. },
  139. listIndex: function listIndex(next, prev) {
  140. if (next in this.tiles) {
  141. var tile = this.tiles[next];
  142. tile.classList.add('v-list-item--highlighted');
  143. this.$refs.content.scrollTop = tile.offsetTop - tile.clientHeight;
  144. }
  145. prev in this.tiles && this.tiles[prev].classList.remove('v-list-item--highlighted');
  146. }
  147. },
  148. created: function created() {
  149. /* istanbul ignore next */
  150. if (this.$attrs.hasOwnProperty('full-width')) {
  151. (0, _console.removed)('full-width', this);
  152. }
  153. },
  154. mounted: function mounted() {
  155. this.isActive && this.callActivate();
  156. },
  157. methods: {
  158. activate: function activate() {
  159. var _this = this;
  160. // Update coordinates and dimensions of menu
  161. // and its activator
  162. this.updateDimensions(); // Start the transition
  163. requestAnimationFrame(function () {
  164. // Once transitioning, calculate scroll and top position
  165. _this.startTransition().then(function () {
  166. if (_this.$refs.content) {
  167. _this.calculatedTopAuto = _this.calcTopAuto();
  168. _this.auto && (_this.$refs.content.scrollTop = _this.calcScrollPosition());
  169. }
  170. });
  171. });
  172. },
  173. calcScrollPosition: function calcScrollPosition() {
  174. var $el = this.$refs.content;
  175. var activeTile = $el.querySelector('.v-list-item--active');
  176. var maxScrollTop = $el.scrollHeight - $el.offsetHeight;
  177. return activeTile ? Math.min(maxScrollTop, Math.max(0, activeTile.offsetTop - $el.offsetHeight / 2 + activeTile.offsetHeight / 2)) : $el.scrollTop;
  178. },
  179. calcLeftAuto: function calcLeftAuto() {
  180. return parseInt(this.dimensions.activator.left - this.defaultOffset * 2);
  181. },
  182. calcTopAuto: function calcTopAuto() {
  183. var $el = this.$refs.content;
  184. var activeTile = $el.querySelector('.v-list-item--active');
  185. if (!activeTile) {
  186. this.selectedIndex = null;
  187. }
  188. if (this.offsetY || !activeTile) {
  189. return this.computedTop;
  190. }
  191. this.selectedIndex = Array.from(this.tiles).indexOf(activeTile);
  192. var tileDistanceFromMenuTop = activeTile.offsetTop - this.calcScrollPosition();
  193. var firstTileOffsetTop = $el.querySelector('.v-list-item').offsetTop;
  194. return this.computedTop - tileDistanceFromMenuTop - firstTileOffsetTop - 1;
  195. },
  196. changeListIndex: function changeListIndex(e) {
  197. // For infinite scroll and autocomplete, re-evaluate children
  198. this.getTiles();
  199. if (!this.isActive || !this.hasClickableTiles) {
  200. return;
  201. } else if (e.keyCode === _helpers.keyCodes.tab) {
  202. this.isActive = false;
  203. return;
  204. } else if (e.keyCode === _helpers.keyCodes.down) {
  205. this.nextTile();
  206. } else if (e.keyCode === _helpers.keyCodes.up) {
  207. this.prevTile();
  208. } else if (e.keyCode === _helpers.keyCodes.enter && this.listIndex !== -1) {
  209. this.tiles[this.listIndex].click();
  210. } else {
  211. return;
  212. } // One of the conditions was met, prevent default action (#2988)
  213. e.preventDefault();
  214. },
  215. closeConditional: function closeConditional(e) {
  216. var target = e.target;
  217. return this.isActive && !this._isDestroyed && this.closeOnClick && !this.$refs.content.contains(target);
  218. },
  219. genActivatorAttributes: function genActivatorAttributes() {
  220. var attributes = _activatable.default.options.methods.genActivatorAttributes.call(this);
  221. if (this.activeTile && this.activeTile.id) {
  222. return _objectSpread({}, attributes, {
  223. 'aria-activedescendant': this.activeTile.id
  224. });
  225. }
  226. return attributes;
  227. },
  228. genActivatorListeners: function genActivatorListeners() {
  229. var listeners = _menuable.default.options.methods.genActivatorListeners.call(this);
  230. if (!this.disableKeys) {
  231. listeners.keydown = this.onKeyDown;
  232. }
  233. return listeners;
  234. },
  235. genTransition: function genTransition() {
  236. var content = this.genContent();
  237. if (!this.transition) return content;
  238. return this.$createElement('transition', {
  239. props: {
  240. name: this.transition
  241. }
  242. }, [content]);
  243. },
  244. genDirectives: function genDirectives() {
  245. var _this2 = this;
  246. var directives = [{
  247. name: 'show',
  248. value: this.isContentActive
  249. }]; // Do not add click outside for hover menu
  250. if (!this.openOnHover && this.closeOnClick) {
  251. directives.push({
  252. name: 'click-outside',
  253. value: function value() {
  254. _this2.isActive = false;
  255. },
  256. args: {
  257. closeConditional: this.closeConditional,
  258. include: function include() {
  259. return [_this2.$el].concat(_toConsumableArray(_this2.getOpenDependentElements()));
  260. }
  261. }
  262. });
  263. }
  264. return directives;
  265. },
  266. genContent: function genContent() {
  267. var _this3 = this;
  268. var options = {
  269. attrs: _objectSpread({}, this.getScopeIdAttrs(), {
  270. role: 'role' in this.$attrs ? this.$attrs.role : 'menu'
  271. }),
  272. staticClass: 'v-menu__content',
  273. class: _objectSpread({}, this.rootThemeClasses, _defineProperty({
  274. 'v-menu__content--auto': this.auto,
  275. 'v-menu__content--fixed': this.activatorFixed,
  276. menuable__content__active: this.isActive
  277. }, this.contentClass.trim(), true)),
  278. style: this.styles,
  279. directives: this.genDirectives(),
  280. ref: 'content',
  281. on: {
  282. click: function click(e) {
  283. var target = e.target;
  284. if (target.getAttribute('disabled')) return;
  285. if (_this3.closeOnContentClick) _this3.isActive = false;
  286. },
  287. keydown: this.onKeyDown
  288. }
  289. };
  290. if (!this.disabled && this.openOnHover) {
  291. options.on = options.on || {};
  292. options.on.mouseenter = this.mouseEnterHandler;
  293. }
  294. if (this.openOnHover) {
  295. options.on = options.on || {};
  296. options.on.mouseleave = this.mouseLeaveHandler;
  297. }
  298. return this.$createElement('div', options, this.getContentSlot());
  299. },
  300. getTiles: function getTiles() {
  301. if (!this.$refs.content) return;
  302. this.tiles = Array.from(this.$refs.content.querySelectorAll('.v-list-item'));
  303. },
  304. mouseEnterHandler: function mouseEnterHandler() {
  305. var _this4 = this;
  306. this.runDelay('open', function () {
  307. if (_this4.hasJustFocused) return;
  308. _this4.hasJustFocused = true;
  309. _this4.isActive = true;
  310. });
  311. },
  312. mouseLeaveHandler: function mouseLeaveHandler(e) {
  313. var _this5 = this;
  314. // Prevent accidental re-activation
  315. this.runDelay('close', function () {
  316. if (_this5.$refs.content.contains(e.relatedTarget)) return;
  317. requestAnimationFrame(function () {
  318. _this5.isActive = false;
  319. _this5.callDeactivate();
  320. });
  321. });
  322. },
  323. nextTile: function nextTile() {
  324. var tile = this.tiles[this.listIndex + 1];
  325. if (!tile) {
  326. if (!this.tiles.length) return;
  327. this.listIndex = -1;
  328. this.nextTile();
  329. return;
  330. }
  331. this.listIndex++;
  332. if (tile.tabIndex === -1) this.nextTile();
  333. },
  334. prevTile: function prevTile() {
  335. var tile = this.tiles[this.listIndex - 1];
  336. if (!tile) {
  337. if (!this.tiles.length) return;
  338. this.listIndex = this.tiles.length;
  339. this.prevTile();
  340. return;
  341. }
  342. this.listIndex--;
  343. if (tile.tabIndex === -1) this.prevTile();
  344. },
  345. onKeyDown: function onKeyDown(e) {
  346. var _this6 = this;
  347. if (e.keyCode === _helpers.keyCodes.esc) {
  348. // Wait for dependent elements to close first
  349. setTimeout(function () {
  350. _this6.isActive = false;
  351. });
  352. var activator = this.getActivator();
  353. this.$nextTick(function () {
  354. return activator && activator.focus();
  355. });
  356. } else if (!this.isActive && [_helpers.keyCodes.up, _helpers.keyCodes.down].includes(e.keyCode)) {
  357. this.isActive = true;
  358. } // Allow for isActive watcher to generate tile list
  359. this.$nextTick(function () {
  360. return _this6.changeListIndex(e);
  361. });
  362. },
  363. onResize: function onResize() {
  364. if (!this.isActive) return; // Account for screen resize
  365. // and orientation change
  366. // eslint-disable-next-line no-unused-expressions
  367. this.$refs.content.offsetWidth;
  368. this.updateDimensions(); // When resizing to a smaller width
  369. // content width is evaluated before
  370. // the new activator width has been
  371. // set, causing it to not size properly
  372. // hacky but will revisit in the future
  373. clearTimeout(this.resizeTimeout);
  374. this.resizeTimeout = window.setTimeout(this.updateDimensions, 100);
  375. }
  376. },
  377. render: function render(h) {
  378. var _this7 = this;
  379. var data = {
  380. staticClass: 'v-menu',
  381. class: {
  382. 'v-menu--attached': this.attach === '' || this.attach === true || this.attach === 'attach'
  383. },
  384. directives: [{
  385. arg: '500',
  386. name: 'resize',
  387. value: this.onResize
  388. }]
  389. };
  390. return h('div', data, [!this.activator && this.genActivator(), this.showLazyContent(function () {
  391. return [_this7.$createElement(_VThemeProvider.VThemeProvider, {
  392. props: {
  393. root: true,
  394. light: _this7.light,
  395. dark: _this7.dark
  396. }
  397. }, [_this7.genTransition()])];
  398. })]);
  399. }
  400. });
  401. exports.default = _default;
  402. //# sourceMappingURL=VMenu.js.map