element-plus
Version:
A Component Library for Vue 3
242 lines (241 loc) • 9.01 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePopperHook = exports.usePopperProps = exports.usePopperControlProps = exports.LIGHT_EFFECT = exports.DARK_EFFECT = void 0;
const vue_1 = require("vue");
const shared_1 = require("@vue/shared");
const core_1 = require("@popperjs/core");
const directives_1 = require("element-plus/lib/directives");
const util_1 = require("element-plus/lib/utils/util");
const vnode_1 = require("element-plus/lib/utils/vnode");
const dom_1 = require("element-plus/lib/utils/dom");
const popup_manager_1 = __importDefault(require("element-plus/lib/utils/popup-manager"));
const error_1 = require("element-plus/lib/utils/error");
const use_teleport_1 = __importDefault(require("../use-teleport"));
const use_timeout_1 = __importDefault(require("../use-timeout"));
const use_model_toggle_1 = require("../use-model-toggle");
const use_transition_fallthrough_1 = require("../use-transition-fallthrough");
const use_popper_options_1 = require("./use-popper-options");
const use_target_events_1 = require("./use-target-events");
exports.DARK_EFFECT = 'dark';
exports.LIGHT_EFFECT = 'light';
exports.usePopperControlProps = {
appendToBody: {
type: Boolean,
default: true,
},
arrowOffset: {
type: Number,
},
popperOptions: use_popper_options_1.defaultPopperOptions,
popperClass: {
type: String,
default: '',
},
};
exports.usePopperProps = Object.assign(Object.assign({}, exports.usePopperControlProps), { autoClose: {
type: Number,
default: 0,
}, content: {
type: String,
default: '',
}, class: String, style: Object, hideAfter: {
type: Number,
default: 200,
}, disabled: {
type: Boolean,
default: false,
}, effect: {
type: String,
default: exports.DARK_EFFECT,
}, enterable: {
type: Boolean,
default: true,
}, manualMode: {
type: Boolean,
default: false,
}, showAfter: {
type: Number,
default: 0,
}, pure: {
type: Boolean,
default: false,
}, showArrow: {
type: Boolean,
default: true,
}, transition: {
type: String,
default: 'el-fade-in-linear',
}, trigger: {
type: [String, Array],
default: use_target_events_1.DEFAULT_TRIGGER,
}, visible: {
type: Boolean,
default: undefined,
}, stopPopperMouseEvent: {
type: Boolean,
default: true,
} });
const usePopperHook = () => {
const vm = (0, vue_1.getCurrentInstance)();
const props = vm.props;
const { slots } = vm;
const arrowRef = (0, vue_1.ref)(null);
const triggerRef = (0, vue_1.ref)(null);
const popperRef = (0, vue_1.ref)(null);
const popperStyle = (0, vue_1.ref)({ zIndex: popup_manager_1.default.nextZIndex() });
const visible = (0, vue_1.ref)(false);
const isManual = (0, vue_1.computed)(() => props.manualMode || props.trigger === 'manual');
const popperId = `el-popper-${(0, util_1.generateId)()}`;
let popperInstance = null;
const { renderTeleport, showTeleport, hideTeleport } = (0, use_teleport_1.default)(popupRenderer, (0, vue_1.toRef)(props, 'appendToBody'));
const { show, hide } = (0, use_model_toggle_1.useModelToggle)({
indicator: visible,
onShow,
onHide,
});
const { registerTimeout, cancelTimeout } = (0, use_timeout_1.default)();
function onShow() {
popperStyle.value.zIndex = popup_manager_1.default.nextZIndex();
(0, vue_1.nextTick)(initializePopper);
}
function onHide() {
hideTeleport();
(0, vue_1.nextTick)(detachPopper);
}
function delayShow() {
if (isManual.value || props.disabled)
return;
showTeleport();
registerTimeout(show, props.showAfter);
}
function delayHide() {
if (isManual.value)
return;
registerTimeout(hide, props.hideAfter);
}
function onToggle() {
if (visible.value) {
delayShow();
}
else {
delayHide();
}
}
function detachPopper() {
var _a;
(_a = popperInstance === null || popperInstance === void 0 ? void 0 : popperInstance.destroy) === null || _a === void 0 ? void 0 : _a.call(popperInstance);
popperInstance = null;
}
function onPopperMouseEnter() {
if (props.enterable && props.trigger !== 'click') {
cancelTimeout();
}
}
function onPopperMouseLeave() {
const { trigger } = props;
const shouldPrevent = ((0, util_1.isString)(trigger) && (trigger === 'click' || trigger === 'focus')) ||
(trigger.length === 1 &&
(trigger[0] === 'click' || trigger[0] === 'focus'));
if (shouldPrevent)
return;
delayHide();
}
function initializePopper() {
if (!visible.value || popperInstance !== null) {
return;
}
const unwrappedTrigger = triggerRef.value;
const $el = (0, util_1.isHTMLElement)(unwrappedTrigger)
? unwrappedTrigger
: unwrappedTrigger.$el;
popperInstance = (0, core_1.createPopper)($el, popperRef.value, buildPopperOptions());
popperInstance.update();
}
function buildPopperOptions() {
const modifiers = [...use_popper_options_1.defaultModifiers, ...props.popperOptions.modifiers];
if (props.showArrow) {
modifiers.push({
name: 'arrow',
options: {
padding: props.arrowOffset || 5,
element: arrowRef.value,
},
});
}
return Object.assign(Object.assign({}, props.popperOptions), { modifiers });
}
const { onAfterEnter, onAfterLeave, onBeforeEnter, onBeforeLeave } = (0, use_transition_fallthrough_1.useTransitionFallthrough)();
const events = (0, use_target_events_1.useTargetEvents)(delayShow, delayHide, onToggle);
const arrowRefAttacher = (0, util_1.refAttacher)(arrowRef);
const popperRefAttacher = (0, util_1.refAttacher)(popperRef);
const triggerRefAttacher = (0, util_1.refAttacher)(triggerRef);
function popupRenderer() {
const mouseUpAndDown = props.stopPopperMouseEvent ? dom_1.stop : shared_1.NOOP;
return (0, vue_1.h)(vue_1.Transition, {
name: props.transition,
onAfterEnter,
onAfterLeave,
onBeforeEnter,
onBeforeLeave,
}, {
default: () => () => visible.value
? (0, vue_1.h)('div', {
'aria-hidden': false,
class: [
props.popperClass,
'el-popper',
`is-${props.effect}`,
props.pure ? 'is-pure' : '',
],
style: popperStyle.value,
id: popperId,
ref: popperRefAttacher,
role: 'tooltip',
onMouseenter: onPopperMouseEnter,
onMouseleave: onPopperMouseLeave,
onClick: dom_1.stop,
onMousedown: mouseUpAndDown,
onMouseup: mouseUpAndDown,
}, [
(0, vue_1.renderSlot)(slots, 'default', {}, () => [
(0, vue_1.toDisplayString)(props.content),
]),
arrowRenderer(),
])
: null,
});
}
function arrowRenderer() {
return props.showArrow
? (0, vue_1.h)('div', {
ref: arrowRefAttacher,
class: 'el-popper__arrow',
'data-popper-arrow': '',
}, null)
: null;
}
function triggerRenderer(triggerProps) {
var _a;
const trigger = (_a = slots.trigger) === null || _a === void 0 ? void 0 : _a.call(slots);
const firstElement = (0, vnode_1.getFirstValidNode)(trigger, 1);
if (!firstElement)
(0, error_1.throwError)('renderTrigger', 'trigger expects single rooted node');
return (0, vue_1.cloneVNode)(firstElement, triggerProps, true);
}
function render() {
const trigger = triggerRenderer(Object.assign({ 'aria-describedby': popperId, class: props.class, style: props.style, ref: triggerRefAttacher }, events));
return (0, vue_1.h)(vue_1.Fragment, null, [
isManual.value
? trigger
: (0, vue_1.withDirectives)(trigger, [[directives_1.ClickOutside, delayHide]]),
renderTeleport(),
]);
}
return {
render,
};
};
exports.usePopperHook = usePopperHook;