useMessage.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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 * as React from 'react';
  11. import CloseOutlined from "@ant-design/icons/es/icons/CloseOutlined";
  12. import classNames from 'classnames';
  13. import { NotificationProvider, useNotification as useRcNotification } from 'rc-notification';
  14. import { devUseWarning } from '../_util/warning';
  15. import { ConfigContext } from '../config-provider';
  16. import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
  17. import { PureContent } from './PurePanel';
  18. import useStyle from './style';
  19. import { getMotion, wrapPromiseFn } from './util';
  20. const DEFAULT_OFFSET = 8;
  21. const DEFAULT_DURATION = 3;
  22. const Wrapper = ({
  23. children,
  24. prefixCls
  25. }) => {
  26. const rootCls = useCSSVarCls(prefixCls);
  27. const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
  28. return wrapCSSVar(/*#__PURE__*/React.createElement(NotificationProvider, {
  29. classNames: {
  30. list: classNames(hashId, cssVarCls, rootCls)
  31. }
  32. }, children));
  33. };
  34. const renderNotifications = (node, {
  35. prefixCls,
  36. key
  37. }) => (/*#__PURE__*/React.createElement(Wrapper, {
  38. prefixCls: prefixCls,
  39. key: key
  40. }, node));
  41. const Holder = /*#__PURE__*/React.forwardRef((props, ref) => {
  42. const {
  43. top,
  44. prefixCls: staticPrefixCls,
  45. getContainer: staticGetContainer,
  46. maxCount,
  47. duration = DEFAULT_DURATION,
  48. rtl,
  49. transitionName,
  50. onAllRemoved
  51. } = props;
  52. const {
  53. getPrefixCls,
  54. getPopupContainer,
  55. message,
  56. direction
  57. } = React.useContext(ConfigContext);
  58. const prefixCls = staticPrefixCls || getPrefixCls('message');
  59. // =============================== Style ===============================
  60. const getStyle = () => ({
  61. left: '50%',
  62. transform: 'translateX(-50%)',
  63. top: top !== null && top !== void 0 ? top : DEFAULT_OFFSET
  64. });
  65. const getClassName = () => classNames({
  66. [`${prefixCls}-rtl`]: rtl !== null && rtl !== void 0 ? rtl : direction === 'rtl'
  67. });
  68. // ============================== Motion ===============================
  69. const getNotificationMotion = () => getMotion(prefixCls, transitionName);
  70. // ============================ Close Icon =============================
  71. const mergedCloseIcon = /*#__PURE__*/React.createElement("span", {
  72. className: `${prefixCls}-close-x`
  73. }, /*#__PURE__*/React.createElement(CloseOutlined, {
  74. className: `${prefixCls}-close-icon`
  75. }));
  76. // ============================== Origin ===============================
  77. const [api, holder] = useRcNotification({
  78. prefixCls,
  79. style: getStyle,
  80. className: getClassName,
  81. motion: getNotificationMotion,
  82. closable: false,
  83. closeIcon: mergedCloseIcon,
  84. duration,
  85. getContainer: () => (staticGetContainer === null || staticGetContainer === void 0 ? void 0 : staticGetContainer()) || (getPopupContainer === null || getPopupContainer === void 0 ? void 0 : getPopupContainer()) || document.body,
  86. maxCount,
  87. onAllRemoved,
  88. renderNotifications
  89. });
  90. // ================================ Ref ================================
  91. React.useImperativeHandle(ref, () => Object.assign(Object.assign({}, api), {
  92. prefixCls,
  93. message
  94. }));
  95. return holder;
  96. });
  97. // ==============================================================================
  98. // == Hook ==
  99. // ==============================================================================
  100. let keyIndex = 0;
  101. export function useInternalMessage(messageConfig) {
  102. const holderRef = React.useRef(null);
  103. const warning = devUseWarning('Message');
  104. // ================================ API ================================
  105. const wrapAPI = React.useMemo(() => {
  106. // Wrap with notification content
  107. // >>> close
  108. const close = key => {
  109. var _a;
  110. (_a = holderRef.current) === null || _a === void 0 ? void 0 : _a.close(key);
  111. };
  112. // >>> Open
  113. const open = config => {
  114. if (!holderRef.current) {
  115. process.env.NODE_ENV !== "production" ? warning(false, 'usage', 'You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.') : void 0;
  116. const fakeResult = () => {};
  117. fakeResult.then = () => {};
  118. return fakeResult;
  119. }
  120. const {
  121. open: originOpen,
  122. prefixCls,
  123. message
  124. } = holderRef.current;
  125. const noticePrefixCls = `${prefixCls}-notice`;
  126. const {
  127. content,
  128. icon,
  129. type,
  130. key,
  131. className,
  132. style,
  133. onClose
  134. } = config,
  135. restConfig = __rest(config, ["content", "icon", "type", "key", "className", "style", "onClose"]);
  136. let mergedKey = key;
  137. if (mergedKey === undefined || mergedKey === null) {
  138. keyIndex += 1;
  139. mergedKey = `antd-message-${keyIndex}`;
  140. }
  141. return wrapPromiseFn(resolve => {
  142. originOpen(Object.assign(Object.assign({}, restConfig), {
  143. key: mergedKey,
  144. content: (/*#__PURE__*/React.createElement(PureContent, {
  145. prefixCls: prefixCls,
  146. type: type,
  147. icon: icon
  148. }, content)),
  149. placement: 'top',
  150. className: classNames(type && `${noticePrefixCls}-${type}`, className, message === null || message === void 0 ? void 0 : message.className),
  151. style: Object.assign(Object.assign({}, message === null || message === void 0 ? void 0 : message.style), style),
  152. onClose: () => {
  153. onClose === null || onClose === void 0 ? void 0 : onClose();
  154. resolve();
  155. }
  156. }));
  157. // Return close function
  158. return () => {
  159. close(mergedKey);
  160. };
  161. });
  162. };
  163. // >>> destroy
  164. const destroy = key => {
  165. var _a;
  166. if (key !== undefined) {
  167. close(key);
  168. } else {
  169. (_a = holderRef.current) === null || _a === void 0 ? void 0 : _a.destroy();
  170. }
  171. };
  172. const clone = {
  173. open,
  174. destroy
  175. };
  176. const keys = ['info', 'success', 'warning', 'error', 'loading'];
  177. keys.forEach(type => {
  178. const typeOpen = (jointContent, duration, onClose) => {
  179. let config;
  180. if (jointContent && typeof jointContent === 'object' && 'content' in jointContent) {
  181. config = jointContent;
  182. } else {
  183. config = {
  184. content: jointContent
  185. };
  186. }
  187. // Params
  188. let mergedDuration;
  189. let mergedOnClose;
  190. if (typeof duration === 'function') {
  191. mergedOnClose = duration;
  192. } else {
  193. mergedDuration = duration;
  194. mergedOnClose = onClose;
  195. }
  196. const mergedConfig = Object.assign(Object.assign({
  197. onClose: mergedOnClose,
  198. duration: mergedDuration
  199. }, config), {
  200. type
  201. });
  202. return open(mergedConfig);
  203. };
  204. clone[type] = typeOpen;
  205. });
  206. return clone;
  207. }, []);
  208. // ============================== Return ===============================
  209. return [wrapAPI, /*#__PURE__*/React.createElement(Holder, Object.assign({
  210. key: "message-holder"
  211. }, messageConfig, {
  212. ref: holderRef
  213. }))];
  214. }
  215. export default function useMessage(messageConfig) {
  216. return useInternalMessage(messageConfig);
  217. }