tdesign-react
Version:
TDesign Component for React
378 lines (374 loc) • 15.2 kB
JavaScript
/**
* tdesign v1.16.2
* (c) 2025 tdesign
* @license MIT
*/
import { _ as _defineProperty } from '../_chunks/dep-d67deb2c.js';
import { _ as _slicedToArray } from '../_chunks/dep-10d5731f.js';
import React, { forwardRef, useState, useRef, useEffect, useMemo, useImperativeHandle } from 'react';
import { CSSTransition } from 'react-transition-group';
import classNames from 'classnames';
import { isFunction, debounce } from 'lodash-es';
import { g as getCssVarsValue } from '../_chunks/dep-ca8d3fa0.js';
import Portal from '../common/Portal.js';
import useAnimation from '../hooks/useAnimation.js';
import useAttach from '../hooks/useAttach.js';
import useConfig from '../hooks/useConfig.js';
import useControlled from '../hooks/useControlled.js';
import useDefaultProps from '../hooks/useDefaultProps.js';
import useMutationObservable from '../hooks/useMutationObserver.js';
import usePopper from '../hooks/usePopper.js';
import useWindowSize from '../hooks/useWindowSize.js';
import { popupDefaultProps } from './defaultProps.js';
import useTrigger from './hooks/useTrigger.js';
import { getTransitionParams } from './utils/transition.js';
import '../_chunks/dep-8abcbcbc.js';
import '../_chunks/dep-74a10cfb.js';
import 'react-dom';
import '../hooks/useLayoutEffect.js';
import '../config-provider/ConfigContext.js';
import '../_chunks/dep-6b235a32.js';
import '../_chunks/dep-b9afa32b.js';
import 'dayjs';
import '../_util/noop.js';
import '../hooks/useLatest.js';
import '../_chunks/dep-a3a3e527.js';
import 'react-fast-compare';
import '@popperjs/core';
import '../_util/listener.js';
import '../_util/ref.js';
import 'react-is';
import '../_util/isFragment.js';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var DEFAULT_TRANSITION_TIMEOUT = 180;
var ARROW_WIDTH = 8;
var ARROW_HEIGHT = 8;
var Popup = /*#__PURE__*/forwardRef(function (originalProps, ref) {
var props = useDefaultProps(originalProps, popupDefaultProps);
var trigger = props.trigger,
content = props.content,
placement = props.placement,
attach = props.attach,
showArrow = props.showArrow,
destroyOnClose = props.destroyOnClose,
overlayClassName = props.overlayClassName,
overlayInnerClassName = props.overlayInnerClassName,
overlayStyle = props.overlayStyle,
overlayInnerStyle = props.overlayInnerStyle,
triggerElement = props.triggerElement,
_props$children = props.children,
children = _props$children === void 0 ? triggerElement : _props$children,
disabled = props.disabled,
popperOptions = props.popperOptions,
zIndex = props.zIndex,
onScroll = props.onScroll,
onScrollToBottom = props.onScrollToBottom,
expandAnimation = props.expandAnimation,
delay = props.delay,
hideEmptyPopup = props.hideEmptyPopup,
updateScrollTop = props.updateScrollTop;
var _useConfig = useConfig(),
classPrefix = _useConfig.classPrefix;
var popupAttach = useAttach("popup", attach);
var _useAnimation = useAnimation(),
keepExpand = _useAnimation.keepExpand,
keepFade = _useAnimation.keepFade;
var _useWindowSize = useWindowSize(),
windowHeight = _useWindowSize.height,
windowWidth = _useWindowSize.width;
var _useControlled = useControlled(props, "visible", props.onVisibleChange),
_useControlled2 = _slicedToArray(_useControlled, 2),
visible = _useControlled2[0],
onVisibleChange = _useControlled2[1];
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
isOverlayHover = _useState2[0],
setIsOverlayHover = _useState2[1];
var _useState3 = useState(null),
_useState4 = _slicedToArray(_useState3, 2),
popupElement = _useState4[0],
setPopupElement = _useState4[1];
var _useState5 = useState({}),
_useState6 = _slicedToArray(_useState5, 2),
arrowStyle = _useState6[0],
setArrowStyle = _useState6[1];
var popupRef = useRef(null);
var portalRef = useRef(null);
var contentRef = useRef(null);
var popperRef = useRef(null);
var arrowRef = useRef(null);
useEffect(function () {
if (!content && hideEmptyPopup) {
requestAnimationFrame(function () {
return setPopupElement(null);
});
}
}, [content, hideEmptyPopup]);
var showOverlay = useMemo(function () {
if (hideEmptyPopup && !content) return false;
return visible || popupElement;
}, [hideEmptyPopup, content, visible, popupElement]);
var popperPlacement = useMemo(function () {
return placement.replace(/-(left|top)$/, "-start").replace(/-(right|bottom)$/, "-end");
}, [placement]);
var _useTrigger = useTrigger({
triggerElement: triggerElement,
content: content,
disabled: disabled,
trigger: trigger,
visible: visible,
delay: delay,
onVisibleChange: onVisibleChange
}),
triggerElementIsString = _useTrigger.triggerElementIsString,
getTriggerElement = _useTrigger.getTriggerElement,
getTriggerNode = _useTrigger.getTriggerNode,
getPopupProps = _useTrigger.getPopupProps;
var triggerEl = getTriggerElement();
var arrowModifierEnabled = useMemo(function () {
var _popperOptions$modifi;
var arrowModifier = popperOptions === null || popperOptions === void 0 || (_popperOptions$modifi = popperOptions.modifiers) === null || _popperOptions$modifi === void 0 ? void 0 : _popperOptions$modifi.find(function (m) {
return m.name === "arrow";
});
return arrowModifier && arrowModifier.enabled !== false;
}, [popperOptions]);
popperRef.current = usePopper(triggerEl, popupElement, _objectSpread({
placement: popperPlacement
}, popperOptions));
var _popperRef$current = popperRef.current,
styles = _popperRef$current.styles,
attributes = _popperRef$current.attributes;
var triggerNode = isFunction(children) ? getTriggerNode(children({
visible: visible
})) : getTriggerNode(children);
var updateTimeRef = useRef(null);
useMutationObservable(triggerEl, function () {
var isDisplayNone = getCssVarsValue("display", triggerEl) === "none";
if (visible && !isDisplayNone) {
clearTimeout(updateTimeRef.current);
updateTimeRef.current = setTimeout(function () {
var _popperRef$current2, _popperRef$current2$u;
return (_popperRef$current2 = popperRef.current) === null || _popperRef$current2 === void 0 || (_popperRef$current2$u = _popperRef$current2.update) === null || _popperRef$current2$u === void 0 ? void 0 : _popperRef$current2$u.call(_popperRef$current2);
}, 0);
}
});
useEffect(function () {
return function () {
return clearTimeout(updateTimeRef.current);
};
}, []);
var calculateArrowStyle = function calculateArrowStyle() {
if (!triggerEl || !popupElement || !showArrow) return {};
var triggerRect = triggerEl.getBoundingClientRect();
var popupRect = popupElement.getBoundingClientRect();
var inRange = function inRange(value, min, max) {
return value >= min && value <= max;
};
if (placement.startsWith("top") || placement.startsWith("bottom")) {
var offsetLeft = Math.abs(triggerRect.left + triggerRect.width / 2 - popupRect.left);
var popupWidth = popupElement.offsetWidth || popupElement.clientWidth;
var maxPopupOffsetLeft = popupWidth - ARROW_WIDTH / 2;
var minPopupOffsetLeft = ARROW_WIDTH + ARROW_WIDTH / 2;
if (inRange(offsetLeft, 0, popupWidth)) {
return {
left: "".concat(Math.max(minPopupOffsetLeft, Math.min(maxPopupOffsetLeft, offsetLeft)) - ARROW_WIDTH / 2, "px"),
marginLeft: 0
};
}
return {};
}
var offsetTop = triggerRect.top + triggerRect.height / 2 - popupRect.top;
var popupHeight = popupElement.offsetHeight || popupElement.clientHeight;
var maxPopupOffsetTop = popupHeight - ARROW_HEIGHT;
var minPopupOffsetTop = ARROW_HEIGHT;
if (inRange(offsetTop, 0, popupHeight)) {
return {
top: "".concat(Math.max(minPopupOffsetTop, Math.min(maxPopupOffsetTop, offsetTop)) - ARROW_HEIGHT / 2, "px"),
marginTop: 0
};
}
return {};
};
var updateArrowPosition = function updateArrowPosition() {
if (visible && popupElement && showArrow) {
var newArrowStyle = calculateArrowStyle();
setArrowStyle(newArrowStyle);
}
};
useEffect(function () {
if (visible) {
requestAnimationFrame(function () {
var _popperRef$current3, _popperRef$current3$u;
(_popperRef$current3 = popperRef.current) === null || _popperRef$current3 === void 0 || (_popperRef$current3$u = _popperRef$current3.update) === null || _popperRef$current3$u === void 0 || _popperRef$current3$u.call(_popperRef$current3);
});
}
}, [visible, content, windowHeight, windowWidth]);
useEffect(function () {
if (visible && popupElement) {
updateScrollTop === null || updateScrollTop === void 0 || updateScrollTop(contentRef.current);
updateArrowPosition();
}
}, [visible, popupElement, updateScrollTop]);
function handleExited() {
setIsOverlayHover(false);
!destroyOnClose && popupElement && (popupElement.style.display = "none");
}
function handleEnter() {
setIsOverlayHover(true);
!destroyOnClose && popupElement && (popupElement.style.display = "block");
}
function handleScroll(e) {
onScroll === null || onScroll === void 0 || onScroll({
e: e
});
var debounceOnScrollBottom = debounce(function (e2) {
return onScrollToBottom === null || onScrollToBottom === void 0 ? void 0 : onScrollToBottom({
e: e2
});
}, 100);
var _e$target = e.target,
scrollTop = _e$target.scrollTop,
clientHeight = _e$target.clientHeight,
scrollHeight = _e$target.scrollHeight;
if (clientHeight + Math.floor(scrollTop) === scrollHeight) {
debounceOnScrollBottom(e);
}
}
function getOverlayStyle(overlayStyle2) {
if (triggerEl && popupRef.current && typeof overlayStyle2 === "function") {
return _objectSpread({}, overlayStyle2(triggerEl, popupRef.current));
}
return _objectSpread({}, overlayStyle2);
}
var overlay = showOverlay && /* @__PURE__ */React.createElement(CSSTransition, {
appear: true,
"in": visible,
timeout: DEFAULT_TRANSITION_TIMEOUT,
nodeRef: portalRef,
unmountOnExit: destroyOnClose,
onEnter: handleEnter,
onExited: handleExited
}, /* @__PURE__ */React.createElement(Portal, {
ref: portalRef,
triggerNode: triggerEl,
attach: popupAttach,
style: {
position: "absolute",
top: 0,
left: 0,
width: "100%"
}
}, /* @__PURE__ */React.createElement(CSSTransition, _objectSpread({
appear: true,
timeout: 0,
"in": visible,
nodeRef: popupRef
}, getTransitionParams({
classPrefix: classPrefix,
fadeAnimation: keepFade,
expandAnimation: expandAnimation && keepExpand
})), /* @__PURE__ */React.createElement("div", _objectSpread(_objectSpread({
ref: function ref(node) {
if (node) {
popupRef.current = node;
setPopupElement(node);
}
},
style: _objectSpread(_objectSpread({}, styles.popper), {}, {
zIndex: zIndex
}, getOverlayStyle(overlayStyle)),
className: classNames("".concat(classPrefix, "-popup"), overlayClassName)
}, attributes.popper), {}, {
onClick: function onClick(e) {
var _props$onOverlayClick;
return (_props$onOverlayClick = props.onOverlayClick) === null || _props$onOverlayClick === void 0 ? void 0 : _props$onOverlayClick.call(props, {
e: e
});
}
}, getPopupProps()), /* @__PURE__ */React.createElement("div", {
ref: contentRef,
className: classNames("".concat(classPrefix, "-popup__content"), _defineProperty({}, "".concat(classPrefix, "-popup__content--arrow"), showArrow), overlayInnerClassName),
style: getOverlayStyle(overlayInnerStyle),
onScroll: handleScroll
}, content, showArrow && /* @__PURE__ */React.createElement("div", _objectSpread({
ref: arrowRef,
style: _objectSpread(_objectSpread({}, styles.arrow), arrowStyle),
className: "".concat(classPrefix, "-popup__arrow")
}, arrowModifierEnabled && {
"data-popper-arrow": ""
})))))));
function updatePopper() {
var popper = popperRef.current;
if (!popper || !visible) return;
try {
var root = triggerEl === null || triggerEl === void 0 ? void 0 : triggerEl.getRootNode();
if (root && root instanceof ShadowRoot) {
if (popper.state) popper.state.elements.reference = triggerEl;
popper.update();
} else {
var rect = triggerEl === null || triggerEl === void 0 ? void 0 : triggerEl.getBoundingClientRect();
var parent = triggerEl;
while (parent && parent !== document.body) {
parent = parent.parentElement;
}
var isHidden = parent !== document.body || rect && rect.width === 0 && rect.height === 0;
if (!isHidden) {
if (popper.state) popper.state.elements.reference = triggerEl;
popper.update();
} else {
onVisibleChange(false, {
trigger: "document"
});
}
}
} catch (e) {
popper.update();
}
updateArrowPosition();
}
useImperativeHandle(ref, function () {
return {
getPopupElement: function getPopupElement() {
return popupRef.current;
},
getPortalElement: function getPortalElement() {
return portalRef.current;
},
getPopupContentElement: function getPopupContentElement() {
return contentRef.current;
},
setVisible: function setVisible(visible2) {
return onVisibleChange(visible2, {
trigger: "document"
});
},
getPopper: function getPopper() {
var popper = popperRef.current;
if (!popper) return null;
return {
state: popper.state,
update: popper.update,
forceUpdate: popper.forceUpdate,
destroy: popper.destroy,
setOptions: popper.setOptions
};
},
getOverlay: function getOverlay() {
return portalRef.current;
},
getOverlayState: function getOverlayState() {
return {
hover: isOverlayHover
};
},
update: function update() {
return updatePopper();
}
};
});
return /* @__PURE__ */React.createElement(React.Fragment, null, triggerElementIsString ? null : triggerNode, overlay);
});
Popup.displayName = "Popup";
export { Popup as default };
//# sourceMappingURL=Popup.js.map