@meve/ui
Version:
Argon design system components library
461 lines (403 loc) • 14.4 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import Teleport from '../teleport';
import context from '../context';
import { props } from './props';
import { createNamespace } from '../utils/create';
import { doubleRaf, getLeft, getTop, toPxNum } from '../utils/elements';
import { createChildrenMixin, createParentMixin } from '../utils/mixins/relation';
import { createZIndexMixin } from '../utils/mixins/zIndex';
var _createNamespace = createNamespace('popover'),
namespace = _createNamespace.namespace,
createComponent = _createNamespace.createComponent;
var transformOrigins = {
bottom: 'top',
'bottom-start': 'left top',
'bottom-end': 'right top',
top: 'bottom',
'top-start': 'left bottom',
'top-end': 'right bottom',
left: 'right',
'left-start': 'right top',
'left-end': 'right bottom',
right: 'left',
'right-start': 'left top',
'right-end': 'left bottom'
};
var PopoverPlugin = createComponent({
mixins: [createParentMixin('popover'), createChildrenMixin('popover'), createZIndexMixin('show')],
props: props,
watch: {
placement: {
handler: function handler(newValue) {
this.localPlacement = newValue;
if (this.show) {
this.open();
return;
}
this.inset = this.getDefaultInset();
},
immediate: true
}
},
data: function data() {
return {
triggerWidth: undefined,
show: false,
inset: {},
zIndex: context.zIndex++,
closeAnimation: null,
hover: false,
opener: null,
closer: null,
localPlacement: null,
clickSelf: false
};
},
mounted: function mounted() {
window.addEventListener('resize', this.resize);
},
beforeDestroy: function beforeDestroy() {
document.removeEventListener('click', this.handleClickBlur);
window.removeEventListener('resize', this.resize);
},
methods: {
getDefaultInset: function getDefaultInset() {
return {
transform: 'scale(0.8)',
transformOrigin: transformOrigins[this.localPlacement],
opacity: 0
};
},
handleClick: function handleClick(event) {
if (this.trigger !== 'click' || this.disabled) {
return;
}
if (this.parent) {
event.stopPropagation();
}
this.clickSelf = true;
document.addEventListener('click', this.handleClickBlur);
this.closeSibling();
this.closeChildren();
this.open();
},
handleClickBlur: function handleClickBlur() {
if (this.clickSelf) {
this.clickSelf = false;
return;
}
this.close();
},
handleMouseEnter: function handleMouseEnter() {
if (this.trigger !== 'hover' || this.disabled) {
return;
}
this.clearParentsCloser();
this.hover = true;
this.opener = setTimeout(this.open, 100);
},
handleMouseLeave: function handleMouseLeave() {
var _this = this;
if (this.trigger !== 'hover' || this.disabled) {
return;
}
this.hover = false;
clearTimeout(this.opener);
this.closer = setTimeout(function () {
_this.close(true);
_this.checkParentsHoverDoClose();
}, 250);
},
clearParentsCloser: function clearParentsCloser() {
var parents = this.findParents();
parents.forEach(function (parent) {
return clearTimeout(parent.closer);
});
clearTimeout(this.closer);
},
findParents: function findParents() {
var parents = [];
var parent = this.parent;
while (parent) {
parents.push(parent);
parent = parent.parent;
}
return parents;
},
checkParentsHoverDoClose: function checkParentsHoverDoClose() {
var parents = this.findParents();
if (!parents.some(function (parent) {
return parent.hover;
})) {
parents.forEach(function (parent) {
return parent.close(true);
});
}
},
closeSibling: function closeSibling() {
var _this2 = this;
if (this.parent) {
this.parent.children.forEach(function (child) {
if (child !== _this2) {
child.close();
}
});
}
},
closeChildren: function closeChildren() {
this.children.forEach(function (child) {
return child.close();
});
},
open: function open() {
var _this3 = this;
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _this3$parent;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!_this3.show) {
_context.next = 2;
break;
}
return _context.abrupt("return");
case 2:
clearTimeout(_this3.closeAnimation);
_this3.$emit('open');
(_this3$parent = _this3.parent) == null ? void 0 : _this3$parent.open();
_this3.show = true;
_this3.triggerWidth = _this3.$refs.trigger.offsetWidth;
_context.next = 9;
return doubleRaf();
case 9:
_this3.resize();
case 10:
case "end":
return _context.stop();
}
}
}, _callee);
}))();
},
close: function close(onlySelf) {
var _this4 = this;
if (onlySelf === void 0) {
onlySelf = false;
}
if (!this.show) {
return;
}
if (this.trigger === 'click') {
document.removeEventListener('click', this.handleClickBlur);
}
this.$emit('close');
this.resizeDefault();
if (!onlySelf) {
this.closeChildren();
}
this.closeAnimation = setTimeout(function () {
if (_this4.closeAnimation) {
_this4.show = false;
_this4.$emit('closed');
}
}, 250);
},
resize: function resize() {
if (!this.show) {
return;
}
this.inset = this.getInset();
},
resizeDefault: function resizeDefault() {
this.inset = _extends({}, this.inset, this.getDefaultInset());
},
computeInset: function computeInset(trigger, container, placement, x, y) {
var top = 0;
var left = 0;
var width = trigger.offsetWidth;
var height = trigger.offsetHeight;
var cWidth = container.offsetWidth;
var cHeight = container.offsetHeight;
if (['bottom', 'top'].includes(placement)) {
left -= cWidth / 2;
}
if (['left', 'left-start', 'left-end', 'top-end', 'bottom-end'].includes(placement)) {
left -= cWidth;
}
if (['top', 'top-start', 'top-end', 'left-end', 'right-end'].includes(placement)) {
top -= cHeight;
}
if (['left', 'right'].includes(placement)) {
top -= cHeight / 2;
}
if (['bottom', 'left-end', 'right-end', 'bottom-start', 'bottom-end'].includes(placement)) {
top = top + getTop(trigger) + height;
}
if (['top', 'top-start', 'top-end', 'left-start', 'right-start'].includes(placement)) {
top += getTop(trigger);
}
if (['left', 'right'].includes(placement)) {
top = top + getTop(trigger) + height / 2;
}
if (['left', 'left-start', 'left-end', 'top-start', 'bottom-start'].includes(placement)) {
left += getLeft(trigger);
}
if (['right', 'right-start', 'right-end', 'top-end', 'bottom-end'].includes(placement)) {
left = left + getLeft(trigger) + width;
}
if (['bottom', 'top'].includes(placement)) {
left = left + getLeft(trigger) + width / 2;
}
return {
top: Math.floor(top + y),
left: Math.floor(left + x)
};
},
getInset: function getInset() {
this.localPlacement = this.placement;
var _this$$refs = this.$refs,
trigger = _this$$refs.trigger,
container = _this$$refs.container;
if (!trigger || !container) {
return {};
}
this.triggerWidth = this.$refs.trigger.offsetWidth;
var bodyWidth = document.body.scrollWidth;
var bodyHeight = document.body.scrollHeight;
var cWidth = container.offsetWidth;
var cHeight = container.offsetHeight;
var x = this.x,
y = this.y;
x = toPxNum(x);
y = toPxNum(y);
var _this$computeInset = this.computeInset(trigger, container, this.localPlacement, x, y),
possibleLeft = _this$computeInset.left,
possibleTop = _this$computeInset.top;
var fullWidth = possibleLeft + cWidth;
var fullHeight = possibleTop + cHeight;
var inYClient = fullHeight <= bodyHeight && possibleTop >= 0;
var inXClient = possibleLeft >= 0 && fullWidth <= bodyWidth;
var exceedLeft = possibleLeft < 0;
var exceedRight = fullWidth > bodyWidth;
var exceedTop = possibleTop < 0;
var exceedBottom = fullHeight > bodyHeight;
var placement = this.localPlacement;
var dashRE = /(-\w+)|$/;
if (exceedLeft && inYClient) {
this.localPlacement = placement.includes('left') ? placement.replace('left', 'right') : placement.replace(dashRE, '-start');
} else if (exceedRight && inYClient) {
this.localPlacement = placement.includes('right') ? placement.replace('right', 'left') : placement.replace(dashRE, '-end');
} else if (exceedTop && inXClient) {
this.localPlacement = placement.includes('top') ? placement.replace('top', 'bottom') : placement.replace(dashRE, '-start');
} else if (exceedBottom && inXClient) {
this.localPlacement = placement.includes('bottom') ? placement.replace('bottom', 'top') : placement.replace(dashRE, '-end');
} else if (exceedLeft && exceedBottom) {
this.localPlacement = 'right-end';
} else if (exceedLeft && exceedTop) {
this.localPlacement = 'right-start';
} else if (exceedRight && exceedTop) {
this.localPlacement = 'left-start';
} else if (exceedRight && exceedBottom) {
this.localPlacement = 'left-end';
}
var _this$computeInset2 = this.computeInset(trigger, container, this.localPlacement, x, y),
top = _this$computeInset2.top,
left = _this$computeInset2.left;
return {
top: top + 'px',
left: left + 'px',
transform: 'scale(1)',
transformOrigin: transformOrigins[this.localPlacement]
};
},
handleTransitionEnd: function handleTransitionEnd(event) {
if (event.propertyName === 'opacity' && event.currentTarget === event.target && window.getComputedStyle(event.currentTarget).opacity === '1') {
this.$emit('opened');
}
}
},
render: function render() {
var h = arguments[0];
var show = this.show,
inset = this.inset,
zIndex = this.zIndex,
defaultStyle = this.defaultStyle,
sameWidth = this.sameWidth,
triggerWidth = this.triggerWidth,
handleClick = this.handleClick,
handleMouseEnter = this.handleMouseEnter,
handleMouseLeave = this.handleMouseLeave,
handleTransitionEnd = this.handleTransitionEnd;
return h("div", {
"ref": "trigger",
"class": namespace(),
"on": _extends({}, {
"click": function click($event) {
for (var _len = arguments.length, attrs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
attrs[_key - 1] = arguments[_key];
}
handleClick.apply(void 0, [$event].concat(attrs));
},
"mouseenter": function mouseenter($event) {
for (var _len2 = arguments.length, attrs = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
attrs[_key2 - 1] = arguments[_key2];
}
handleMouseEnter.apply(void 0, [$event].concat(attrs));
},
"mouseleave": function mouseleave($event) {
for (var _len3 = arguments.length, attrs = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
attrs[_key3 - 1] = arguments[_key3];
}
handleMouseLeave.apply(void 0, [$event].concat(attrs));
}
})
}, [this.slots('trigger'), h(Teleport, {
"ref": "teleport",
"attrs": {
"to": "body"
}
}, [h("div", {
"ref": "container",
"class": [namespace('__container'), defaultStyle ? namespace('--default-style') : null],
"style": _extends({}, inset, {
zIndex: zIndex,
width: sameWidth ? triggerWidth + "px" : undefined
}),
"directives": [{
name: "show",
value: show
}],
"on": _extends({}, {
"transitionend": function transitionend($event) {
for (var _len4 = arguments.length, attrs = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
attrs[_key4 - 1] = arguments[_key4];
}
handleTransitionEnd.apply(void 0, [$event].concat(attrs));
},
"mouseenter": function mouseenter($event) {
for (var _len5 = arguments.length, attrs = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
attrs[_key5 - 1] = arguments[_key5];
}
handleMouseEnter.apply(void 0, [$event].concat(attrs));
},
"mouseleave": function mouseleave($event) {
for (var _len6 = arguments.length, attrs = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
attrs[_key6 - 1] = arguments[_key6];
}
handleMouseLeave.apply(void 0, [$event].concat(attrs));
},
"click": function click($event) {
for (var _len7 = arguments.length, attrs = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) {
attrs[_key7 - 1] = arguments[_key7];
}
handleClick.apply(void 0, [$event].concat(attrs));
}
})
}, [this.slots()])])]);
}
});
export var _PopoverComponent = PopoverPlugin;
export default PopoverPlugin;