xdesign-vue-next
Version:
XDesign Component for vue-next
442 lines (434 loc) • 17 kB
JavaScript
/**
* xdesign v1.0.6
* (c) 2023 xdesign
* @license MIT
*/
;
Object.defineProperty(exports, '__esModule', { value: true });
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var vue = require('vue');
var core = require('@popperjs/core');
var isFunction = require('lodash/isFunction');
var isObject = require('lodash/isObject');
var debounce = require('lodash/debounce');
var isString = require('lodash/isString');
var hooks_useConfig = require('../hooks/useConfig.js');
var hooks_useVModel = require('../hooks/useVModel.js');
var utils_dom = require('../utils/dom.js');
var _common_js_utils_setStyle = require('../_common/js/utils/set-style.js');
var popup_container = require('./container.js');
var popup_props = require('./props.js');
var hooks_tnode = require('../hooks/tnode.js');
require('../config-provider/useConfig.js');
require('lodash/cloneDeep');
require('../config-provider/context.js');
require('lodash/mergeWith');
require('lodash/merge');
require('../_common/js/global-config/default-config.js');
require('../_common/js/global-config/locale/en_US.js');
require('../_chunks/dep-8d10b59f.js');
require('lodash/isArray');
require('lodash/kebabCase');
require('../utils/easing.js');
require('@babel/runtime/helpers/toConsumableArray');
require('../hooks/useResizeObserver.js');
require('lodash/camelCase');
require('../utils/render-tnode.js');
require('lodash/isEmpty');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
var isFunction__default = /*#__PURE__*/_interopDefaultLegacy(isFunction);
var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _isSlot(s) {
return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
}
var POPUP_ATTR_NAME = "data-td-popup";
var POPUP_PARENT_ATTR_NAME = "data-td-popup-parent";
function getPopperTree(id, upwards) {
var list = [];
var selectors = [POPUP_PARENT_ATTR_NAME, POPUP_ATTR_NAME];
if (!id) return list;
if (upwards) {
selectors.unshift(selectors.pop());
}
recurse(id);
return list;
function recurse(id2) {
var children = document.querySelectorAll("[".concat(selectors[0], "=\"").concat(id2, "\"]"));
children.forEach(function (el) {
list.push(el);
var childId = el.getAttribute(selectors[1]);
if (childId && childId !== id2) {
recurse(childId);
}
});
}
}
var parentKey = Symbol();
function getPopperPlacement(placement) {
return placement.replace(/-(left|top)$/, "-start").replace(/-(right|bottom)$/, "-end");
}
function attachListeners(elm) {
var offs = [];
return {
add: function add(type, listener) {
if (!type) return;
utils_dom.on(elm.value, type, listener);
offs.push(function () {
utils_dom.off(elm.value, type, listener);
});
},
clean: function clean() {
offs.forEach(function (handler) {
return handler === null || handler === void 0 ? void 0 : handler();
});
offs.length = 0;
}
};
}
var _Popup = vue.defineComponent({
name: "XPopup",
props: _objectSpread(_objectSpread({}, popup_props["default"]), {}, {
expandAnimation: {
type: Boolean
}
}),
setup: function setup(props2, _ref) {
var _process$env;
var expose = _ref.expose;
var _toRefs = vue.toRefs(props2),
propVisible = _toRefs.visible,
modelValue = _toRefs.modelValue;
var _useVModel = hooks_useVModel["default"](propVisible, modelValue, props2.defaultVisible, props2.onVisibleChange, "visible"),
_useVModel2 = _slicedToArray__default["default"](_useVModel, 2),
visible = _useVModel2[0],
setVisible = _useVModel2[1];
var renderTNodeJSX = hooks_tnode.useTNodeJSX();
var renderContent = hooks_tnode.useContent();
var popper;
var showTimeout;
var hideTimeout;
var triggerEl = vue.ref(null);
var overlayEl = vue.ref(null);
var popperEl = vue.ref(null);
var containerRef = vue.ref(null);
var id = typeof process !== "undefined" && (_process$env = process.env) !== null && _process$env !== void 0 && _process$env.TEST ? "" : Date.now().toString(36);
var parent = vue.inject(parentKey, void 0);
vue.provide(parentKey, {
id: id,
assertMouseLeave: onMouseLeave
});
var prefixCls = hooks_useConfig.usePrefixClass("popup");
var _useCommonClassName = hooks_useConfig.useCommonClassName(),
commonCls = _useCommonClassName.STATUS;
var delay = vue.computed(function () {
var _props2$delay, _delay2$;
var delay2 = props2.trigger !== "hover" ? [0, 0] : [].concat((_props2$delay = props2.delay) !== null && _props2$delay !== void 0 ? _props2$delay : [250, 150]);
return {
show: delay2[0],
hide: (_delay2$ = delay2[1]) !== null && _delay2$ !== void 0 ? _delay2$ : delay2[0]
};
});
var trigger = attachListeners(triggerEl);
vue.watch(function () {
return [props2.trigger, triggerEl.value];
}, function () {
if (!triggerEl.value) return;
trigger.clean();
trigger.add({
hover: "mouseenter",
focus: "focusin",
"context-menu": "contextmenu",
click: "click"
}[props2.trigger], function (ev) {
if (props2.disabled) return;
if (ev.type === "contextmenu") {
ev.preventDefault();
}
if ((ev.type === "click" || ev.type === "contextmenu") && visible.value) {
hide(ev);
return;
}
show(ev);
});
trigger.add({
hover: "mouseleave",
focus: "focusout"
}[props2.trigger], hide);
});
vue.watch(function () {
return [props2.overlayStyle, props2.overlayInnerStyle, overlayEl.value];
}, function () {
updateOverlayInnerStyle();
updatePopper();
});
vue.watch(function () {
return props2.placement;
}, function () {
destroyPopper();
updatePopper();
});
vue.watch(function () {
return visible.value;
}, function (visible2) {
if (visible2) {
utils_dom.on(document, "mousedown", onDocumentMouseDown, true);
if (props2.trigger === "focus") {
utils_dom.once(triggerEl.value, "keydown", function (ev) {
var _process$env2;
var code = typeof process !== "undefined" && (_process$env2 = process.env) !== null && _process$env2 !== void 0 && _process$env2.TEST ? "27" : "Escape";
if (ev.code === code) {
hide(ev);
}
});
}
return;
}
utils_dom.off(document, "mousedown", onDocumentMouseDown, true);
});
vue.onUnmounted(function () {
destroyPopper();
clearAllTimeout();
utils_dom.off(document, "mousedown", onDocumentMouseDown, true);
});
expose({
update: updatePopper,
close: function close() {
return hide();
},
getOverlay: function getOverlay() {
return overlayEl.value;
}
});
function getOverlayStyle() {
var overlayStyle = props2.overlayStyle;
if (!triggerEl.value || !overlayEl.value) return;
if (isFunction__default["default"](overlayStyle)) {
return overlayStyle(triggerEl.value, overlayEl.value);
}
if (isObject__default["default"](overlayStyle)) {
return overlayStyle;
}
}
function updateOverlayInnerStyle() {
var overlayInnerStyle = props2.overlayInnerStyle;
if (!triggerEl.value || !overlayEl.value) return;
if (isFunction__default["default"](overlayInnerStyle)) {
_common_js_utils_setStyle["default"](overlayEl.value, overlayInnerStyle(triggerEl.value, overlayEl.value));
} else if (isObject__default["default"](overlayInnerStyle)) {
_common_js_utils_setStyle["default"](overlayEl.value, overlayInnerStyle);
}
}
function updatePopper() {
if (!popperEl.value || !visible.value) return;
if (popper) {
var rect = triggerEl.value.getBoundingClientRect();
var parent2 = triggerEl.value;
while (parent2 && parent2 !== document.body) {
parent2 = parent2.parentElement;
}
var isHidden = parent2 !== document.body || rect.width === 0 && rect.height === 0;
if (!isHidden) {
popper.state.elements.reference = triggerEl.value;
popper.update();
} else {
setVisible(false, {
trigger: getTriggerType({
type: "mouseenter"
})
});
}
return;
}
popper = core.createPopper(triggerEl.value, popperEl.value, _objectSpread({
placement: getPopperPlacement(props2.placement),
onFirstUpdate: function onFirstUpdate() {
vue.nextTick(updatePopper);
}
}, props2.popperOptions));
}
function destroyPopper() {
if (popper) {
var _popper;
(_popper = popper) === null || _popper === void 0 ? void 0 : _popper.destroy();
popper = null;
}
if (props2.destroyOnClose) {
var _containerRef$value;
(_containerRef$value = containerRef.value) === null || _containerRef$value === void 0 ? void 0 : _containerRef$value.unmountContent();
}
}
function show(ev) {
clearAllTimeout();
showTimeout = setTimeout(function () {
setVisible(true, {
trigger: getTriggerType(ev)
});
}, delay.value.show);
}
function hide(ev) {
clearAllTimeout();
hideTimeout = setTimeout(function () {
setVisible(false, {
trigger: getTriggerType(ev)
});
}, delay.value.hide);
}
function clearAllTimeout() {
clearTimeout(showTimeout);
clearTimeout(hideTimeout);
}
function getTriggerType(ev) {
switch (ev === null || ev === void 0 ? void 0 : ev.type) {
case "mouseenter":
case "mouseleave":
return "trigger-element-hover";
case "focusin":
return "trigger-element-focus";
case "focusout":
return "trigger-element-blur";
case "click":
return "trigger-element-click";
case "context-menu":
case "keydown":
return "keydown-esc";
case "mousedown":
return "document";
default:
return "trigger-element-close";
}
}
function onDocumentMouseDown(ev) {
if (popperEl.value.contains(ev.target)) {
return;
}
if (triggerEl.value.contains(ev.target)) {
return;
}
var activedPopper = getPopperTree(id).find(function (el) {
return el.contains(ev.target);
});
if (activedPopper && getPopperTree(activedPopper.getAttribute(POPUP_PARENT_ATTR_NAME), true).some(function (el) {
return el === popperEl.value;
})) {
return;
}
hide(ev);
}
function onMouseLeave(ev) {
if (props2.trigger !== "hover" || triggerEl.value.contains(ev.target)) return;
var isCursorOverlaps = getPopperTree(id).some(function (el) {
var rect = el.getBoundingClientRect();
return ev.x > rect.x && ev.x < rect.x + rect.width && ev.y > rect.y && ev.y < rect.y + rect.height;
});
if (!isCursorOverlaps) {
hide(ev);
parent === null || parent === void 0 ? void 0 : parent.assertMouseLeave(ev);
}
}
var updateScrollTop = vue.inject("updateScrollTop", void 0);
function handleOnScroll(e) {
var _props2$onScroll;
var _e$target = e.target,
scrollTop = _e$target.scrollTop,
clientHeight = _e$target.clientHeight,
scrollHeight = _e$target.scrollHeight;
var debounceOnScrollBottom = debounce__default["default"](function (e2) {
var _props2$onScrollToBot;
return (_props2$onScrollToBot = props2.onScrollToBottom) === null || _props2$onScrollToBot === void 0 ? void 0 : _props2$onScrollToBot.call(props2, {
e: e2
});
}, 100);
if (clientHeight + Math.floor(scrollTop) === scrollHeight) {
debounceOnScrollBottom(e);
}
(_props2$onScroll = props2.onScroll) === null || _props2$onScroll === void 0 ? void 0 : _props2$onScroll.call(props2, {
e: e
});
}
vue.watch(function () {
return [visible.value, overlayEl.value];
}, function () {
if (visible.value && overlayEl.value && updateScrollTop) {
updateScrollTop === null || updateScrollTop === void 0 ? void 0 : updateScrollTop(overlayEl.value);
}
});
return function () {
var _ref2, _ref3;
var content = renderTNodeJSX("content");
var hidePopup = props2.hideEmptyPopup && ["", void 0, null].includes(content);
var overlay = visible.value || !props2.destroyOnClose ? vue.withDirectives(vue.createVNode("div", vue.mergeProps((_ref2 = {}, _defineProperty__default["default"](_ref2, POPUP_ATTR_NAME, id), _defineProperty__default["default"](_ref2, POPUP_PARENT_ATTR_NAME, parent === null || parent === void 0 ? void 0 : parent.id), _ref2), {
"class": [prefixCls.value, props2.overlayClassName],
"ref": function ref(ref2) {
return popperEl.value = ref2;
},
"style": [{
zIndex: props2.zIndex
}, getOverlayStyle(), hidePopup && {
visibility: "hidden"
}]
}, props2.trigger === "hover" && {
onMouseenter: function onMouseenter() {
if (visible.value) {
clearAllTimeout();
}
},
onMouseleave: onMouseLeave
}), [vue.createVNode("div", {
"class": ["".concat(prefixCls.value, "__content"), (_ref3 = {}, _defineProperty__default["default"](_ref3, "".concat(prefixCls.value, "__content--text"), isString__default["default"](props2.content)), _defineProperty__default["default"](_ref3, "".concat(prefixCls.value, "__content--arrow"), props2.showArrow), _defineProperty__default["default"](_ref3, commonCls.value.disabled, props2.disabled), _ref3), props2.overlayInnerClassName],
"ref": overlayEl,
"onScroll": handleOnScroll
}, [content, props2.showArrow && vue.createVNode("div", {
"class": "".concat(prefixCls.value, "__arrow")
}, null)])]), [[vue.vShow, visible.value]]) : null;
return vue.createVNode(popup_container["default"], {
"ref": function ref(ref2) {
return containerRef.value = ref2;
},
"forwardRef": function forwardRef(ref2) {
return triggerEl.value = ref2;
},
"onContentMounted": function onContentMounted() {
if (visible.value) {
updatePopper();
var timer = setTimeout(function () {
updateOverlayInnerStyle();
clearTimeout(timer);
}, 60);
}
},
"onResize": function onResize() {
if (visible.value) {
updatePopper();
}
},
"visible": visible.value,
"attach": props2.attach
}, {
content: function content() {
return vue.createVNode(vue.Transition, {
"name": "".concat(prefixCls.value, "--animation").concat(props2.expandAnimation ? "-expand" : ""),
"appear": true,
"onEnter": updatePopper,
"onAfterLeave": destroyPopper
}, _isSlot(overlay) ? overlay : {
"default": function _default() {
return [overlay];
}
});
},
"default": function _default() {
return renderContent("default", "triggerElement");
}
});
};
}
});
exports["default"] = _Popup;
//# sourceMappingURL=popup.js.map