295 lines
16 KiB
JavaScript
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());
|
||
|
}
|
||
|
}));
|
||
|
}
|
||
|
});
|