FloatButtonGroup.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. "use client";
  2. var __rest = this && this.__rest || function (s, e) {
  3. var t = {};
  4. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  5. if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  6. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  7. }
  8. return t;
  9. };
  10. import React from 'react';
  11. import CloseOutlined from "@ant-design/icons/es/icons/CloseOutlined";
  12. import FileTextOutlined from "@ant-design/icons/es/icons/FileTextOutlined";
  13. import classNames from 'classnames';
  14. import CSSMotion from 'rc-motion';
  15. import useEvent from "rc-util/es/hooks/useEvent";
  16. import useMergedState from "rc-util/es/hooks/useMergedState";
  17. import { useZIndex } from '../_util/hooks/useZIndex';
  18. import { devUseWarning } from '../_util/warning';
  19. import { useComponentConfig } from '../config-provider/context';
  20. import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
  21. import { FloatButtonGroupProvider } from './context';
  22. import FloatButton, { floatButtonPrefixCls } from './FloatButton';
  23. import useStyle from './style';
  24. const FloatButtonGroup = props => {
  25. var _a;
  26. const {
  27. prefixCls: customizePrefixCls,
  28. className,
  29. style,
  30. shape = 'circle',
  31. type = 'default',
  32. placement = 'top',
  33. icon = /*#__PURE__*/React.createElement(FileTextOutlined, null),
  34. closeIcon,
  35. description,
  36. trigger,
  37. children,
  38. onOpenChange,
  39. open: customOpen,
  40. onClick: onTriggerButtonClick
  41. } = props,
  42. floatButtonProps = __rest(props, ["prefixCls", "className", "style", "shape", "type", "placement", "icon", "closeIcon", "description", "trigger", "children", "onOpenChange", "open", "onClick"]);
  43. const {
  44. direction,
  45. getPrefixCls,
  46. closeIcon: contextCloseIcon
  47. } = useComponentConfig('floatButtonGroup');
  48. const mergedCloseIcon = (_a = closeIcon !== null && closeIcon !== void 0 ? closeIcon : contextCloseIcon) !== null && _a !== void 0 ? _a : /*#__PURE__*/React.createElement(CloseOutlined, null);
  49. const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls);
  50. const rootCls = useCSSVarCls(prefixCls);
  51. const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
  52. const groupPrefixCls = `${prefixCls}-group`;
  53. const isMenuMode = trigger && ['click', 'hover'].includes(trigger);
  54. const isValidPlacement = placement && ['top', 'left', 'right', 'bottom'].includes(placement);
  55. const groupCls = classNames(groupPrefixCls, hashId, cssVarCls, rootCls, className, {
  56. [`${groupPrefixCls}-rtl`]: direction === 'rtl',
  57. [`${groupPrefixCls}-${shape}`]: shape,
  58. [`${groupPrefixCls}-${shape}-shadow`]: !isMenuMode,
  59. [`${groupPrefixCls}-${placement}`]: isMenuMode && isValidPlacement // 只有菜单模式才支持弹出方向
  60. });
  61. // ============================ zIndex ============================
  62. const [zIndex] = useZIndex('FloatButton', style === null || style === void 0 ? void 0 : style.zIndex);
  63. const mergedStyle = Object.assign(Object.assign({}, style), {
  64. zIndex
  65. });
  66. const wrapperCls = classNames(hashId, `${groupPrefixCls}-wrap`);
  67. const [open, setOpen] = useMergedState(false, {
  68. value: customOpen
  69. });
  70. const floatButtonGroupRef = React.useRef(null);
  71. // ========================== Open ==========================
  72. const hoverTrigger = trigger === 'hover';
  73. const clickTrigger = trigger === 'click';
  74. const triggerOpen = useEvent(nextOpen => {
  75. if (open !== nextOpen) {
  76. setOpen(nextOpen);
  77. onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(nextOpen);
  78. }
  79. });
  80. // ===================== Trigger: Hover =====================
  81. const onMouseEnter = () => {
  82. if (hoverTrigger) {
  83. triggerOpen(true);
  84. }
  85. };
  86. const onMouseLeave = () => {
  87. if (hoverTrigger) {
  88. triggerOpen(false);
  89. }
  90. };
  91. // ===================== Trigger: Click =====================
  92. const onInternalTriggerButtonClick = e => {
  93. if (clickTrigger) {
  94. triggerOpen(!open);
  95. }
  96. onTriggerButtonClick === null || onTriggerButtonClick === void 0 ? void 0 : onTriggerButtonClick(e);
  97. };
  98. React.useEffect(() => {
  99. if (clickTrigger) {
  100. const onDocClick = e => {
  101. var _a;
  102. // Skip if click on the group
  103. if ((_a = floatButtonGroupRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target)) {
  104. return;
  105. }
  106. triggerOpen(false);
  107. };
  108. document.addEventListener('click', onDocClick, {
  109. capture: true
  110. });
  111. return () => document.removeEventListener('click', onDocClick, {
  112. capture: true
  113. });
  114. }
  115. }, [clickTrigger]);
  116. // ======================== Warning =========================
  117. if (process.env.NODE_ENV !== 'production') {
  118. const warning = devUseWarning('FloatButton.Group');
  119. process.env.NODE_ENV !== "production" ? warning(!('open' in props) || !!trigger, 'usage', '`open` need to be used together with `trigger`') : void 0;
  120. }
  121. // ========================= Render =========================
  122. return wrapCSSVar(/*#__PURE__*/React.createElement(FloatButtonGroupProvider, {
  123. value: shape
  124. }, /*#__PURE__*/React.createElement("div", {
  125. ref: floatButtonGroupRef,
  126. className: groupCls,
  127. style: mergedStyle,
  128. // Hover trigger
  129. onMouseEnter: onMouseEnter,
  130. onMouseLeave: onMouseLeave
  131. }, isMenuMode ? (/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CSSMotion, {
  132. visible: open,
  133. motionName: `${groupPrefixCls}-wrap`
  134. }, ({
  135. className: motionClassName
  136. }) => (/*#__PURE__*/React.createElement("div", {
  137. className: classNames(motionClassName, wrapperCls)
  138. }, children))), /*#__PURE__*/React.createElement(FloatButton, Object.assign({
  139. type: type,
  140. icon: open ? mergedCloseIcon : icon,
  141. description: description,
  142. "aria-label": props['aria-label'],
  143. className: `${groupPrefixCls}-trigger`,
  144. onClick: onInternalTriggerButtonClick
  145. }, floatButtonProps)))) : children)));
  146. };
  147. export default FloatButtonGroup;