"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _stackable = _interopRequireDefault(require("../stackable"));

var _positionable = require("../positionable");

var _activatable = _interopRequireDefault(require("../activatable"));

var _detachable = _interopRequireDefault(require("../detachable"));

var _mixins = _interopRequireDefault(require("../../util/mixins"));

var _helpers = require("../../util/helpers");

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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(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; }

var baseMixins = (0, _mixins.default)(_stackable.default, (0, _positionable.factory)(['top', 'right', 'bottom', 'left', 'absolute']), _activatable.default, _detachable.default);
/* @vue/component */

var _default = baseMixins.extend().extend({
  name: 'menuable',
  props: {
    allowOverflow: 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 {
      activatorNode: [],
      absoluteX: 0,
      absoluteY: 0,
      activatedBy: null,
      activatorFixed: false,
      dimensions: {
        activator: {
          top: 0,
          left: 0,
          bottom: 0,
          right: 0,
          width: 0,
          height: 0,
          offsetTop: 0,
          scrollHeight: 0,
          offsetLeft: 0
        },
        content: {
          top: 0,
          left: 0,
          bottom: 0,
          right: 0,
          width: 0,
          height: 0,
          offsetTop: 0,
          scrollHeight: 0
        }
      },
      relativeYOffset: 0,
      hasJustFocused: false,
      hasWindow: false,
      inputActivator: false,
      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.attach !== false ? a.offsetLeft : a.left) || 0;
      var minWidth = Math.max(a.width, c.width);
      var left = 0;
      left += activatorLeft;
      if (this.left || this.$ifrontui.rtl && !this.right) left -= minWidth - a.width;

      if (this.offsetX) {
        var maxWidth = isNaN(Number(this.maxWidth)) ? a.width : Math.min(a.width, Number(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.attach !== false) 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;
    },
    absoluteYOffset: function absoluteYOffset() {
      return this.pageYOffset - this.relativeYOffset;
    }
  },
  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.hasWindow = typeof window !== 'undefined';

    if (this.hasWindow) {
      window.addEventListener('resize', this.updateDimensions, false);
    }
  },
  beforeDestroy: function beforeDestroy() {
    if (this.hasWindow) {
      window.removeEventListener('resize', this.updateDimensions, false);
    }
  },
  methods: {
    absolutePosition: function absolutePosition() {
      return {
        offsetTop: this.positionY || this.absoluteY,
        offsetLeft: this.positionX || this.absoluteX,
        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 (0, _helpers.convertToUnit)(this.attach !== false ? this.computedLeft : this.calcXOverflow(this.computedLeft, menuWidth));
    },
    calcTop: function calcTop() {
      return (0, _helpers.convertToUnit)(this.attach !== false ? this.computedTop : this.calcYOverflow(this.computedTop));
    },
    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.absoluteYOffset + 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.absoluteYOffset && !this.allowOverflow) {
        top = this.absoluteYOffset + 12;
      }

      return top < 12 ? 12 : top;
    },
    callActivate: function callActivate() {
      if (!this.hasWindow) return;
      this.activate();
    },
    callDeactivate: function callDeactivate() {
      this.isContentActive = false;
      this.deactivate();
    },
    checkForPageYOffset: function checkForPageYOffset() {
      if (this.hasWindow) {
        this.pageYOffset = this.activatorFixed ? 0 : this.getOffsetTop();
      }
    },
    checkActivatorFixed: function checkActivatorFixed() {
      if (this.attach !== false) {
        this.activatorFixed = 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() {},
    genActivatorListeners: function genActivatorListeners() {
      var _this = this;

      var listeners = _activatable.default.options.methods.genActivatorListeners.call(this);

      var onClick = listeners.click;

      if (onClick) {
        listeners.click = function (e) {
          if (_this.openOnClick) {
            onClick && onClick(e);
          }

          _this.absoluteX = e.clientX;
          _this.absoluteY = e.clientY;
        };
      }

      return listeners;
    },
    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.attach !== false) {
        var style = window.getComputedStyle(el);
        rect.left = parseInt(style.marginLeft);
        rect.top = parseInt(style.marginTop);
      }

      return rect;
    },
    sneakPeek: function sneakPeek(cb) {
      var _this2 = this;

      requestAnimationFrame(function () {
        var el = _this2.$refs.content;

        if (!el || el.style.display !== 'none') {
          cb();
          return;
        }

        el.style.display = 'inline-block';
        cb();
        el.style.display = 'none';
      });
    },
    startTransition: function startTransition() {
      var _this3 = this;

      return new Promise(function (resolve) {
        return requestAnimationFrame(function () {
          _this3.isContentActive = _this3.hasJustFocused = _this3.isActive;
          resolve();
        });
      });
    },
    updateDimensions: function updateDimensions() {
      var _this4 = this;

      this.hasWindow = typeof window !== 'undefined';
      this.checkActivatorFixed();
      this.checkForPageYOffset();
      this.pageWidth = document.documentElement.clientWidth;
      var dimensions = {
        activator: _objectSpread({}, this.dimensions.activator),
        content: _objectSpread({}, this.dimensions.content)
      }; // Activator should already be shown

      if (!this.hasActivator || this.absolute) {
        dimensions.activator = this.absolutePosition();
      } else {
        var activator = this.getActivator();
        if (!activator) return;
        dimensions.activator = this.measure(activator);
        dimensions.activator.offsetLeft = activator.offsetLeft;

        if (this.attach !== false) {
          // 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 () {
        if (_this4.$refs.content) {
          if (_this4.$refs.content.offsetParent) {
            var offsetRect = _this4.getRoundedBoundedClientRect(_this4.$refs.content.offsetParent);

            _this4.relativeYOffset = window.pageYOffset + offsetRect.top;
            dimensions.activator.top -= _this4.relativeYOffset;
            dimensions.activator.left -= window.pageXOffset + offsetRect.left;
          }

          dimensions.content = _this4.measure(_this4.$refs.content);
        }

        _this4.dimensions = dimensions;
      });
    }
  }
});

exports.default = _default;
//# sourceMappingURL=index.js.map