2024-01-29 09:26:07 +08:00

295 lines
16 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderArrow = exports.popoverBodyProps = void 0;
const vue_1 = require("vue");
const vueuc_1 = require("vueuc");
const vdirs_1 = require("vdirs");
const seemly_1 = require("seemly");
const scrollbar_1 = require("../../_internal/scrollbar");
const interface_1 = require("../../drawer/src/interface");
const interface_2 = require("../../modal/src/interface");
const _mixins_1 = require("../../_mixins");
const _utils_1 = require("../../_utils");
const styles_1 = require("../styles");
const interface_3 = require("./interface");
const index_cssr_1 = __importDefault(require("./styles/index.cssr"));
exports.popoverBodyProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), { to: _utils_1.useAdjustedTo.propTo, show: Boolean, trigger: String, showArrow: Boolean, delay: Number, duration: Number, raw: Boolean, arrowPointToCenter: Boolean, arrowClass: String, arrowStyle: [String, Object], arrowWrapperClass: String, arrowWrapperStyle: [String, Object], displayDirective: String, x: Number, y: Number, flip: Boolean, overlap: Boolean, placement: String, width: [Number, String], keepAliveOnHover: Boolean, scrollable: Boolean, contentClass: String, contentStyle: [Object, String], headerClass: String, headerStyle: [Object, String], footerClass: String, footerStyle: [Object, String],
// private
internalDeactivateImmediately: Boolean, animated: Boolean, onClickoutside: Function, internalTrapFocus: Boolean, internalOnAfterLeave: Function,
// deprecated
minWidth: Number, maxWidth: Number });
const renderArrow = ({ arrowClass, arrowStyle, arrowWrapperClass, arrowWrapperStyle, clsPrefix }) => {
return ((0, vue_1.h)("div", { key: "__popover-arrow__", style: arrowWrapperStyle, class: [`${clsPrefix}-popover-arrow-wrapper`, arrowWrapperClass] },
(0, vue_1.h)("div", { class: [`${clsPrefix}-popover-arrow`, arrowClass], style: arrowStyle })));
};
exports.renderArrow = renderArrow;
exports.default = (0, vue_1.defineComponent)({
name: 'PopoverBody',
inheritAttrs: false,
props: exports.popoverBodyProps,
setup(props, { slots, attrs }) {
const { namespaceRef, mergedClsPrefixRef, inlineThemeDisabled } = (0, _mixins_1.useConfig)(props);
const themeRef = (0, _mixins_1.useTheme)('Popover', '-popover', index_cssr_1.default, styles_1.popoverLight, props, mergedClsPrefixRef);
const followerRef = (0, vue_1.ref)(null);
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
const NPopover = (0, vue_1.inject)('NPopover');
const bodyRef = (0, vue_1.ref)(null);
const followerEnabledRef = (0, vue_1.ref)(props.show);
const displayedRef = (0, vue_1.ref)(false);
(0, vue_1.watchEffect)(() => {
const { show } = props;
if (show && !(0, _utils_1.isJsdom)() && !props.internalDeactivateImmediately) {
displayedRef.value = true;
}
});
const directivesRef = (0, vue_1.computed)(() => {
const { trigger, onClickoutside } = props;
const directives = [];
const { positionManuallyRef: { value: positionManually } } = NPopover;
if (!positionManually) {
if (trigger === 'click' && !onClickoutside) {
directives.push([
vdirs_1.clickoutside,
handleClickOutside,
undefined,
{ capture: true }
]);
}
if (trigger === 'hover') {
directives.push([vdirs_1.mousemoveoutside, handleMouseMoveOutside]);
}
}
if (onClickoutside) {
directives.push([
vdirs_1.clickoutside,
handleClickOutside,
undefined,
{ capture: true }
]);
}
if (props.displayDirective === 'show' ||
(props.animated && displayedRef.value)) {
directives.push([vue_1.vShow, props.show]);
}
return directives;
});
const styleRef = (0, vue_1.computed)(() => {
const width = props.width === 'trigger' ? undefined : (0, _utils_1.formatLength)(props.width);
const style = [];
if (width) {
style.push({ width });
}
const { maxWidth, minWidth } = props;
if (maxWidth) {
style.push({ maxWidth: (0, _utils_1.formatLength)(maxWidth) });
}
if (minWidth) {
style.push({ maxWidth: (0, _utils_1.formatLength)(minWidth) });
}
if (!inlineThemeDisabled) {
style.push(cssVarsRef.value);
}
return style;
});
const cssVarsRef = (0, vue_1.computed)(() => {
const { common: { cubicBezierEaseInOut, cubicBezierEaseIn, cubicBezierEaseOut }, self: { space, spaceArrow, padding, fontSize, textColor, dividerColor, color, boxShadow, borderRadius, arrowHeight, arrowOffset, arrowOffsetVertical } } = themeRef.value;
return {
'--n-box-shadow': boxShadow,
'--n-bezier': cubicBezierEaseInOut,
'--n-bezier-ease-in': cubicBezierEaseIn,
'--n-bezier-ease-out': cubicBezierEaseOut,
'--n-font-size': fontSize,
'--n-text-color': textColor,
'--n-color': color,
'--n-divider-color': dividerColor,
'--n-border-radius': borderRadius,
'--n-arrow-height': arrowHeight,
'--n-arrow-offset': arrowOffset,
'--n-arrow-offset-vertical': arrowOffsetVertical,
'--n-padding': padding,
'--n-space': space,
'--n-space-arrow': spaceArrow
};
});
const themeClassHandle = inlineThemeDisabled
? (0, _mixins_1.useThemeClass)('popover', undefined, cssVarsRef, props)
: undefined;
NPopover.setBodyInstance({
syncPosition
});
(0, vue_1.onBeforeUnmount)(() => {
NPopover.setBodyInstance(null);
});
(0, vue_1.watch)((0, vue_1.toRef)(props, 'show'), (value) => {
// If no animation, no transition component will be applied to the
// component. So we need to trigger follower manaully.
if (props.animated)
return;
if (value) {
followerEnabledRef.value = true;
}
else {
followerEnabledRef.value = false;
}
});
function syncPosition() {
var _a;
(_a = followerRef.value) === null || _a === void 0 ? void 0 : _a.syncPosition();
}
function handleMouseEnter(e) {
if (props.trigger === 'hover' && props.keepAliveOnHover && props.show) {
NPopover.handleMouseEnter(e);
}
}
function handleMouseLeave(e) {
if (props.trigger === 'hover' && props.keepAliveOnHover) {
NPopover.handleMouseLeave(e);
}
}
function handleMouseMoveOutside(e) {
if (props.trigger === 'hover' &&
!getTriggerElement().contains((0, seemly_1.getPreciseEventTarget)(e))) {
NPopover.handleMouseMoveOutside(e);
}
}
function handleClickOutside(e) {
if ((props.trigger === 'click' &&
!getTriggerElement().contains((0, seemly_1.getPreciseEventTarget)(e))) ||
props.onClickoutside) {
NPopover.handleClickOutside(e);
}
}
function getTriggerElement() {
return NPopover.getTriggerElement();
}
(0, vue_1.provide)(interface_3.popoverBodyInjectionKey, bodyRef);
(0, vue_1.provide)(interface_1.drawerBodyInjectionKey, null);
(0, vue_1.provide)(interface_2.modalBodyInjectionKey, null);
function renderContentNode() {
themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender();
const shouldRenderDom = props.displayDirective === 'show' ||
props.show ||
(props.animated && displayedRef.value);
if (!shouldRenderDom) {
return null;
}
let contentNode;
const renderBody = NPopover.internalRenderBodyRef.value;
const { value: mergedClsPrefix } = mergedClsPrefixRef;
if (!renderBody) {
const { value: extraClass } = NPopover.extraClassRef;
const { internalTrapFocus } = props;
const hasHeaderOrFooter = !(0, _utils_1.isSlotEmpty)(slots.header) || !(0, _utils_1.isSlotEmpty)(slots.footer);
const renderContentInnerNode = () => {
var _a, _b;
const body = hasHeaderOrFooter ? ((0, vue_1.h)(vue_1.Fragment, null,
(0, _utils_1.resolveWrappedSlot)(slots.header, (children) => {
return children ? ((0, vue_1.h)("div", { class: [
`${mergedClsPrefix}-popover__header`,
props.headerClass
], style: props.headerStyle }, children)) : null;
}),
(0, _utils_1.resolveWrappedSlot)(slots.default, (children) => {
return children ? ((0, vue_1.h)("div", { class: [
`${mergedClsPrefix}-popover__content`,
props.contentClass
], style: props.contentStyle }, slots)) : null;
}),
(0, _utils_1.resolveWrappedSlot)(slots.footer, (children) => {
return children ? ((0, vue_1.h)("div", { class: [
`${mergedClsPrefix}-popover__footer`,
props.footerClass
], style: props.footerStyle }, children)) : null;
}))) : props.scrollable ? ((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)) : ((0, vue_1.h)("div", { class: [
`${mergedClsPrefix}-popover__content`,
props.contentClass
], style: props.contentStyle }, slots));
const maybeScrollableBody = props.scrollable ? ((0, vue_1.h)(scrollbar_1.NxScrollbar, { contentClass: hasHeaderOrFooter
? undefined
: `${mergedClsPrefix}-popover__content ${(_b = props.contentClass) !== null && _b !== void 0 ? _b : ''}`, contentStyle: hasHeaderOrFooter ? undefined : props.contentStyle }, {
default: () => body
})) : (body);
const arrow = props.showArrow
? (0, exports.renderArrow)({
arrowClass: props.arrowClass,
arrowStyle: props.arrowStyle,
arrowWrapperClass: props.arrowWrapperClass,
arrowWrapperStyle: props.arrowWrapperStyle,
clsPrefix: mergedClsPrefix
})
: null;
return [maybeScrollableBody, arrow];
};
contentNode = (0, vue_1.h)('div', (0, vue_1.mergeProps)({
class: [
`${mergedClsPrefix}-popover`,
`${mergedClsPrefix}-popover-shared`,
themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass.value,
extraClass.map((v) => `${mergedClsPrefix}-${v}`),
{
[`${mergedClsPrefix}-popover--scrollable`]: props.scrollable,
[`${mergedClsPrefix}-popover--show-header-or-footer`]: hasHeaderOrFooter,
[`${mergedClsPrefix}-popover--raw`]: props.raw,
[`${mergedClsPrefix}-popover-shared--overlap`]: props.overlap,
[`${mergedClsPrefix}-popover-shared--show-arrow`]: props.showArrow,
[`${mergedClsPrefix}-popover-shared--center-arrow`]: props.arrowPointToCenter
}
],
ref: bodyRef,
style: styleRef.value,
onKeydown: NPopover.handleKeydown,
onMouseenter: handleMouseEnter,
onMouseleave: handleMouseLeave
}, attrs), internalTrapFocus ? ((0, vue_1.h)(vueuc_1.VFocusTrap, { active: props.show, autoFocus: true }, { default: renderContentInnerNode })) : (renderContentInnerNode()));
}
else {
contentNode = renderBody(
// The popover class and overlap class must exists, they will be used
// to place the body & transition animation.
// Shadow class exists for reuse box-shadow.
[
`${mergedClsPrefix}-popover-shared`,
themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass.value,
props.overlap && `${mergedClsPrefix}-popover-shared--overlap`,
props.showArrow && `${mergedClsPrefix}-popover-shared--show-arrow`,
props.arrowPointToCenter &&
`${mergedClsPrefix}-popover-shared--center-arrow`
], bodyRef, styleRef.value, handleMouseEnter, handleMouseLeave);
}
return (0, vue_1.withDirectives)(contentNode, directivesRef.value);
}
return {
displayed: displayedRef,
namespace: namespaceRef,
isMounted: NPopover.isMountedRef,
zIndex: NPopover.zIndexRef,
followerRef,
adjustedTo: (0, _utils_1.useAdjustedTo)(props),
followerEnabled: followerEnabledRef,
renderContentNode
};
},
render() {
return ((0, vue_1.h)(vueuc_1.VFollower, { ref: "followerRef", zIndex: this.zIndex, show: this.show, enabled: this.followerEnabled, to: this.adjustedTo, x: this.x, y: this.y, flip: this.flip, placement: this.placement, containerClass: this.namespace, overlap: this.overlap, width: this.width === 'trigger' ? 'target' : undefined, teleportDisabled: this.adjustedTo === _utils_1.useAdjustedTo.tdkey }, {
default: () => {
return this.animated ? ((0, vue_1.h)(vue_1.Transition, { name: "popover-transition", appear: this.isMounted,
// Don't use watch to enable follower, since the transition may
// make position sync timing very subtle and buggy.
onEnter: () => {
this.followerEnabled = true;
}, onAfterLeave: () => {
var _a;
(_a = this.internalOnAfterLeave) === null || _a === void 0 ? void 0 : _a.call(this);
this.followerEnabled = false;
this.displayed = false;
} }, {
default: this.renderContentNode
})) : (this.renderContentNode());
}
}));
}
});