vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
352 lines (351 loc) • 14.4 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { defineComponent, h, ref, nextTick, onBeforeUnmount, onMounted, reactive, watch } from 'vue';
import XEUtils from 'xe-utils';
import GlobalConfig from '../../v-x-e-table/src/conf';
import { useSize } from '../../hooks/size';
import { getLastZIndex, nextZIndex, formatText } from '../../tools/utils';
import { getAbsolutePos, getDomNode } from '../../tools/dom';
import { getSlotVNs } from '../../tools/vn';
export default defineComponent({
name: 'VxeTooltip',
props: {
modelValue: Boolean,
size: { type: String, default: function () { return GlobalConfig.tooltip.size || GlobalConfig.size; } },
trigger: { type: String, default: function () { return GlobalConfig.tooltip.trigger; } },
theme: { type: String, default: function () { return GlobalConfig.tooltip.theme; } },
content: { type: [String, Number], default: null },
useHTML: Boolean,
zIndex: [String, Number],
popupClassName: [String, Function],
isArrow: { type: Boolean, default: true },
enterable: Boolean,
enterDelay: { type: Number, default: function () { return GlobalConfig.tooltip.enterDelay; } },
leaveDelay: { type: Number, default: function () { return GlobalConfig.tooltip.leaveDelay; } }
},
emits: [
'update:modelValue'
],
setup: function (props, context) {
var slots = context.slots, emit = context.emit;
var xID = XEUtils.uniqueId();
var computeSize = useSize(props);
var reactData = reactive({
target: null,
isUpdate: false,
visible: false,
tipContent: '',
tipActive: false,
tipTarget: null,
tipZindex: 0,
tipStore: {
style: {},
placement: '',
arrowStyle: {}
}
});
var refElem = ref();
var refMaps = {
refElem: refElem
};
var $xetooltip = {
xID: xID,
props: props,
context: context,
reactData: reactData,
getRefMaps: function () { return refMaps; }
};
var tooltipMethods = {};
var updateTipStyle = function () {
var tipTarget = reactData.tipTarget, tipStore = reactData.tipStore;
if (tipTarget) {
var _a = getDomNode(), scrollTop = _a.scrollTop, scrollLeft = _a.scrollLeft, visibleWidth = _a.visibleWidth;
var _b = getAbsolutePos(tipTarget), top_1 = _b.top, left = _b.left;
var el = refElem.value;
var marginSize = 6;
var offsetHeight = el.offsetHeight;
var offsetWidth = el.offsetWidth;
var tipLeft = left;
var tipTop = top_1 - offsetHeight - marginSize;
tipLeft = Math.max(marginSize, left + Math.floor((tipTarget.offsetWidth - offsetWidth) / 2));
if (tipLeft + offsetWidth + marginSize > scrollLeft + visibleWidth) {
tipLeft = scrollLeft + visibleWidth - offsetWidth - marginSize;
}
if (top_1 - offsetHeight < scrollTop + marginSize) {
tipStore.placement = 'bottom';
tipTop = top_1 + tipTarget.offsetHeight + marginSize;
}
tipStore.style.top = "".concat(tipTop, "px");
tipStore.style.left = "".concat(tipLeft, "px");
tipStore.arrowStyle.left = "".concat(left - tipLeft + tipTarget.offsetWidth / 2, "px");
}
};
var updateValue = function (value) {
if (value !== reactData.visible) {
reactData.visible = value;
reactData.isUpdate = true;
emit('update:modelValue', value);
}
};
var updateZindex = function () {
if (reactData.tipZindex < getLastZIndex()) {
reactData.tipZindex = nextZIndex();
}
};
var clickEvent = function () {
if (reactData.visible) {
tooltipMethods.close();
}
else {
tooltipMethods.open();
}
};
var targetMouseenterEvent = function () {
tooltipMethods.open();
};
var targetMouseleaveEvent = function () {
var trigger = props.trigger, enterable = props.enterable, leaveDelay = props.leaveDelay;
reactData.tipActive = false;
if (enterable && trigger === 'hover') {
setTimeout(function () {
if (!reactData.tipActive) {
tooltipMethods.close();
}
}, leaveDelay);
}
else {
tooltipMethods.close();
}
};
var wrapperMouseenterEvent = function () {
reactData.tipActive = true;
};
var wrapperMouseleaveEvent = function () {
var trigger = props.trigger, enterable = props.enterable, leaveDelay = props.leaveDelay;
reactData.tipActive = false;
if (enterable && trigger === 'hover') {
setTimeout(function () {
if (!reactData.tipActive) {
tooltipMethods.close();
}
}, leaveDelay);
}
};
var showTip = function () {
var tipStore = reactData.tipStore;
var el = refElem.value;
if (el) {
var parentNode = el.parentNode;
if (!parentNode) {
document.body.appendChild(el);
}
}
updateValue(true);
updateZindex();
tipStore.placement = 'top';
tipStore.style = { width: 'auto', left: 0, top: 0, zIndex: props.zIndex || reactData.tipZindex };
tipStore.arrowStyle = { left: '50%' };
return tooltipMethods.updatePlacement();
};
var showDelayTip = XEUtils.debounce(function () {
if (reactData.tipActive) {
showTip();
}
}, props.enterDelay, { leading: false, trailing: true });
tooltipMethods = {
dispatchEvent: function (type, params, evnt) {
emit(type, Object.assign({ $tooltip: $xetooltip, $event: evnt }, params));
},
open: function (target, content) {
return tooltipMethods.toVisible(target || reactData.target, content);
},
close: function () {
reactData.tipTarget = null;
reactData.tipActive = false;
Object.assign(reactData.tipStore, {
style: {},
placement: '',
arrowStyle: null
});
updateValue(false);
return nextTick();
},
toVisible: function (target, content) {
if (target) {
var trigger = props.trigger, enterDelay = props.enterDelay;
reactData.tipActive = true;
reactData.tipTarget = target;
if (content) {
reactData.tipContent = content;
}
if (enterDelay && trigger === 'hover') {
showDelayTip();
}
else {
return showTip();
}
}
return nextTick();
},
updatePlacement: function () {
return nextTick().then(function () {
var tipTarget = reactData.tipTarget;
var el = refElem.value;
if (tipTarget && el) {
updateTipStyle();
return nextTick().then(updateTipStyle);
}
});
},
isActived: function () {
return reactData.tipActive;
},
setActived: function (actived) {
reactData.tipActive = !!actived;
}
};
Object.assign($xetooltip, tooltipMethods);
watch(function () { return props.content; }, function () {
reactData.tipContent = props.content;
});
watch(function () { return props.modelValue; }, function () {
if (!reactData.isUpdate) {
if (props.modelValue) {
tooltipMethods.open();
}
else {
tooltipMethods.close();
}
}
reactData.isUpdate = false;
});
onMounted(function () {
nextTick(function () {
var trigger = props.trigger, content = props.content, modelValue = props.modelValue;
var wrapperElem = refElem.value;
if (wrapperElem) {
var parentNode_1 = wrapperElem.parentNode;
if (parentNode_1) {
reactData.tipContent = content;
reactData.tipZindex = nextZIndex();
XEUtils.arrayEach(wrapperElem.children, function (elem, index) {
if (index > 1) {
parentNode_1.insertBefore(elem, wrapperElem);
if (!reactData.target) {
reactData.target = elem;
}
}
});
parentNode_1.removeChild(wrapperElem);
var target = reactData.target;
if (target) {
if (trigger === 'hover') {
target.onmouseenter = targetMouseenterEvent;
target.onmouseleave = targetMouseleaveEvent;
}
else if (trigger === 'click') {
target.onclick = clickEvent;
}
}
if (modelValue) {
tooltipMethods.open();
}
}
}
});
});
onBeforeUnmount(function () {
var trigger = props.trigger;
var target = reactData.target;
var wrapperElem = refElem.value;
if (wrapperElem) {
var parentNode = wrapperElem.parentNode;
if (parentNode) {
parentNode.removeChild(wrapperElem);
}
}
if (target) {
if (trigger === 'hover') {
target.onmouseenter = null;
target.onmouseleave = null;
}
else if (trigger === 'click') {
target.onclick = null;
}
}
});
var renderContent = function () {
var useHTML = props.useHTML;
var tipContent = reactData.tipContent;
var contentSlot = slots.content;
if (contentSlot) {
return h('div', {
key: 1,
class: 'vxe-table--tooltip-content'
}, getSlotVNs(contentSlot({})));
}
if (useHTML) {
return h('div', {
key: 2,
class: 'vxe-table--tooltip-content',
innerHTML: tipContent
});
}
return h('div', {
key: 3,
class: 'vxe-table--tooltip-content'
}, formatText(tipContent));
};
var renderVN = function () {
var _a;
var popupClassName = props.popupClassName, theme = props.theme, isArrow = props.isArrow, enterable = props.enterable;
var tipActive = reactData.tipActive, visible = reactData.visible, tipStore = reactData.tipStore;
var defaultSlot = slots.default;
var vSize = computeSize.value;
var ons;
if (enterable) {
ons = {
onMouseenter: wrapperMouseenterEvent,
onMouseleave: wrapperMouseleaveEvent
};
}
return h('div', __assign({ ref: refElem, class: ['vxe-table--tooltip-wrapper', "theme--".concat(theme), popupClassName ? (XEUtils.isFunction(popupClassName) ? popupClassName({ $tooltip: $xetooltip }) : popupClassName) : '', (_a = {},
_a["size--".concat(vSize)] = vSize,
_a["placement--".concat(tipStore.placement)] = tipStore.placement,
_a['is--enterable'] = enterable,
_a['is--visible'] = visible,
_a['is--arrow'] = isArrow,
_a['is--active'] = tipActive,
_a)], style: tipStore.style }, ons), __spreadArray([
renderContent(),
h('div', {
class: 'vxe-table--tooltip-arrow',
style: tipStore.arrowStyle
})
], (defaultSlot ? getSlotVNs(defaultSlot({})) : []), true));
};
$xetooltip.renderVN = renderVN;
return $xetooltip;
},
render: function () {
return this.renderVN();
}
});