UNPKG

tdesign-react

Version:
378 lines (374 loc) 15.2 kB
/** * 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