UNPKG

@meve/ui

Version:

Argon design system components library

461 lines (403 loc) 14.4 kB
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;