mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 02:49:18 +08:00
Compare commits
10 Commits
6.2.3
...
wuxh/impro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a541d5aa4b | ||
|
|
a1a0cb64e6 | ||
|
|
856dabd295 | ||
|
|
7dfc686bb7 | ||
|
|
42ff8e0ed3 | ||
|
|
a076b23da2 | ||
|
|
3d70240760 | ||
|
|
2f53a841db | ||
|
|
2c04426dd7 | ||
|
|
4e1835e54f |
@@ -44,7 +44,7 @@ export interface PurePanelProps
|
||||
/** @private Internal Component. Do not use in your production. */
|
||||
const PurePanel: React.FC<PurePanelProps> = (props) => {
|
||||
const { prefixCls: staticPrefixCls, className, type, icon, content, ...restProps } = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const { getPrefixCls, message } = React.useContext(ConfigContext);
|
||||
|
||||
const prefixCls = staticPrefixCls || getPrefixCls('message');
|
||||
|
||||
@@ -61,6 +61,7 @@ const PurePanel: React.FC<PurePanelProps> = (props) => {
|
||||
`${prefixCls}-notice-pure-panel`,
|
||||
cssVarCls,
|
||||
rootCls,
|
||||
message?.className,
|
||||
)}
|
||||
eventKey="pure"
|
||||
duration={null}
|
||||
|
||||
@@ -57,10 +57,13 @@ let taskQueue: Task[] = [];
|
||||
let defaultGlobalConfig: ConfigOptions = {};
|
||||
|
||||
function getGlobalContext() {
|
||||
const { getContainer, duration, rtl, maxCount, top } = defaultGlobalConfig;
|
||||
const { getContainer, ...restConfig } = defaultGlobalConfig;
|
||||
const mergedContainer = getContainer?.() || document.body;
|
||||
|
||||
return { getContainer: () => mergedContainer, duration, rtl, maxCount, top };
|
||||
return {
|
||||
...restConfig,
|
||||
getContainer: () => mergedContainer,
|
||||
};
|
||||
}
|
||||
|
||||
interface GlobalHolderRef {
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
import type * as React from 'react';
|
||||
import type { NotificationConfig as RcNotificationConfig } from 'rc-notification';
|
||||
|
||||
export type NoticeType = 'info' | 'success' | 'error' | 'warning' | 'loading';
|
||||
|
||||
export interface ConfigOptions {
|
||||
type SharedProps = Pick<
|
||||
RcNotificationConfig,
|
||||
'prefixCls' | 'maxCount' | 'duration' | 'getContainer' | 'pauseOnHover'
|
||||
>;
|
||||
|
||||
export interface ConfigOptions extends SharedProps {
|
||||
top?: string | number;
|
||||
duration?: number;
|
||||
prefixCls?: string;
|
||||
getContainer?: () => HTMLElement;
|
||||
transitionName?: string;
|
||||
maxCount?: number;
|
||||
rtl?: boolean;
|
||||
}
|
||||
|
||||
export interface ArgsProps {
|
||||
export interface ArgsProps extends SharedProps {
|
||||
/**
|
||||
* @descCN 消息通知的内容,接收组件或者字符串
|
||||
* @descEN The content of the message notification, receiving component or string
|
||||
*/
|
||||
content: React.ReactNode;
|
||||
/**
|
||||
* @descCN 消息通知持续显示的时间
|
||||
* @descEN How long the message notification remains displayed
|
||||
*/
|
||||
duration?: number;
|
||||
/**
|
||||
* @descCN 消息通知的类型,可以是 'info'、'success'、'error'、'warning' 或 'loading'
|
||||
* @descEN The type of message notification, which can be 'info', 'success', 'error', 'warning' or 'loading'
|
||||
|
||||
@@ -60,11 +60,11 @@ const Holder = React.forwardRef<HolderRef, HolderProps>((props, ref) => {
|
||||
top,
|
||||
prefixCls: staticPrefixCls,
|
||||
getContainer: staticGetContainer,
|
||||
maxCount,
|
||||
duration = DEFAULT_DURATION,
|
||||
rtl,
|
||||
transitionName,
|
||||
onAllRemoved,
|
||||
...restProps
|
||||
} = props;
|
||||
const { getPrefixCls, getPopupContainer, message, direction } = React.useContext(ConfigContext);
|
||||
|
||||
@@ -91,6 +91,7 @@ const Holder = React.forwardRef<HolderRef, HolderProps>((props, ref) => {
|
||||
|
||||
// ============================== Origin ===============================
|
||||
const [api, holder] = useRcNotification({
|
||||
...restProps,
|
||||
prefixCls,
|
||||
style: getStyle,
|
||||
className: getClassName,
|
||||
@@ -99,7 +100,6 @@ const Holder = React.forwardRef<HolderRef, HolderProps>((props, ref) => {
|
||||
closeIcon: mergedCloseIcon,
|
||||
duration,
|
||||
getContainer: () => staticGetContainer?.() || getPopupContainer?.() || document.body,
|
||||
maxCount,
|
||||
onAllRemoved,
|
||||
renderNotifications,
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
import type { IconType } from './interface';
|
||||
import useStyle from './style';
|
||||
import PurePanelStyle from './style/pure-panel';
|
||||
import { getCloseIconConfig } from './util';
|
||||
|
||||
export const TypeIcon = {
|
||||
info: <InfoCircleFilled />,
|
||||
@@ -87,12 +88,11 @@ const PurePanel: React.FC<PurePanelProps> = (props) => {
|
||||
description,
|
||||
btn,
|
||||
actions,
|
||||
closable = true,
|
||||
closable,
|
||||
closeIcon,
|
||||
className: notificationClassName,
|
||||
...restProps
|
||||
} = props;
|
||||
const { getPrefixCls } = React.useContext(ConfigContext);
|
||||
const { getPrefixCls, notification } = React.useContext(ConfigContext);
|
||||
const mergedActions = actions ?? btn;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('Notification');
|
||||
@@ -101,12 +101,21 @@ const PurePanel: React.FC<PurePanelProps> = (props) => {
|
||||
const prefixCls = staticPrefixCls || getPrefixCls('notification');
|
||||
const noticePrefixCls = `${prefixCls}-notice`;
|
||||
|
||||
const realCloseIcon = getCloseIcon(prefixCls, getCloseIconConfig(closeIcon, notification));
|
||||
|
||||
const rootCls = useCSSVarCls(prefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||
|
||||
return wrapCSSVar(
|
||||
<div
|
||||
className={classNames(`${noticePrefixCls}-pure-panel`, hashId, className, cssVarCls, rootCls)}
|
||||
className={classNames(
|
||||
`${noticePrefixCls}-pure-panel`,
|
||||
hashId,
|
||||
className,
|
||||
cssVarCls,
|
||||
rootCls,
|
||||
notification?.className,
|
||||
)}
|
||||
>
|
||||
<PurePanelStyle prefixCls={prefixCls} />
|
||||
<Notice
|
||||
@@ -114,11 +123,8 @@ const PurePanel: React.FC<PurePanelProps> = (props) => {
|
||||
prefixCls={prefixCls}
|
||||
eventKey="pure"
|
||||
duration={null}
|
||||
closable={closable}
|
||||
className={classNames({
|
||||
notificationClassName,
|
||||
})}
|
||||
closeIcon={getCloseIcon(prefixCls, closeIcon)}
|
||||
closable={closable ?? !!realCloseIcon}
|
||||
closeIcon={realCloseIcon}
|
||||
content={
|
||||
<PureContent
|
||||
prefixCls={noticePrefixCls}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import notification, { actWrapper } from '..';
|
||||
import { act, fireEvent } from '../../../tests/utils';
|
||||
import type { ArgsProps, GlobalConfigProps } from '../interface';
|
||||
import type { ArgsProps, NotificationConfig } from '../interface';
|
||||
import { awaitPromise, triggerMotionEnd } from './util';
|
||||
|
||||
// TODO: Remove this. Mock for React 19
|
||||
@@ -24,7 +24,7 @@ describe('Notification.placement', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function config(args: Partial<GlobalConfigProps>) {
|
||||
function config(args: Partial<NotificationConfig>) {
|
||||
notification.config({
|
||||
...args,
|
||||
});
|
||||
|
||||
@@ -21,7 +21,6 @@ const App: React.FC = () => {
|
||||
{ length: Math.round(Math.random() * 5) + 1 },
|
||||
() => 'This is the content of the notification.',
|
||||
).join('\n')}`,
|
||||
duration: null,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { useContext } from 'react';
|
||||
import { AppConfigContext } from '../app/context';
|
||||
import ConfigProvider, { ConfigContext, globalConfig, warnContext } from '../config-provider';
|
||||
import { unstableSetRender } from '../config-provider/UnstableContext';
|
||||
import type { ArgsProps, GlobalConfigProps, NotificationInstance } from './interface';
|
||||
import type { ArgsProps, NotificationConfig, NotificationInstance } from './interface';
|
||||
import PurePanel from './PurePanel';
|
||||
import useNotification, { useInternalNotification } from './useNotification';
|
||||
|
||||
@@ -31,21 +31,15 @@ type Task =
|
||||
|
||||
let taskQueue: Task[] = [];
|
||||
|
||||
let defaultGlobalConfig: GlobalConfigProps = {};
|
||||
let defaultGlobalConfig: NotificationConfig = {};
|
||||
|
||||
function getGlobalContext() {
|
||||
const { getContainer, rtl, maxCount, top, bottom, showProgress, pauseOnHover } =
|
||||
defaultGlobalConfig;
|
||||
const { getContainer, ...restConfig } = defaultGlobalConfig;
|
||||
const mergedContainer = getContainer?.() || document.body;
|
||||
|
||||
return {
|
||||
...restConfig,
|
||||
getContainer: () => mergedContainer,
|
||||
rtl,
|
||||
maxCount,
|
||||
top,
|
||||
bottom,
|
||||
showProgress,
|
||||
pauseOnHover,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,7 +50,7 @@ interface GlobalHolderRef {
|
||||
|
||||
const GlobalHolder = React.forwardRef<
|
||||
GlobalHolderRef,
|
||||
{ notificationConfig: GlobalConfigProps; sync: () => void }
|
||||
{ notificationConfig: NotificationConfig; sync: () => void }
|
||||
>((props, ref) => {
|
||||
const { notificationConfig, sync } = props;
|
||||
|
||||
@@ -93,7 +87,7 @@ const GlobalHolder = React.forwardRef<
|
||||
|
||||
const GlobalHolderWrapper = React.forwardRef<GlobalHolderRef, unknown>((_, ref) => {
|
||||
const [notificationConfig, setNotificationConfig] =
|
||||
React.useState<GlobalConfigProps>(getGlobalContext);
|
||||
React.useState<NotificationConfig>(getGlobalContext);
|
||||
|
||||
const sync = () => {
|
||||
setNotificationConfig(getGlobalContext);
|
||||
@@ -183,7 +177,7 @@ const flushNotificationQueue = () => {
|
||||
// == Export ==
|
||||
// ==============================================================================
|
||||
|
||||
function setNotificationGlobalConfig(config: GlobalConfigProps) {
|
||||
function setNotificationGlobalConfig(config: NotificationConfig) {
|
||||
defaultGlobalConfig = {
|
||||
...defaultGlobalConfig,
|
||||
...config,
|
||||
@@ -214,7 +208,7 @@ const destroy: BaseMethods['destroy'] = (key) => {
|
||||
interface BaseMethods {
|
||||
open: (config: ArgsProps) => void;
|
||||
destroy: (key?: React.Key) => void;
|
||||
config: (config: GlobalConfigProps) => void;
|
||||
config: (config: NotificationConfig) => void;
|
||||
useNotification: typeof useNotification;
|
||||
/** @private Internal Component. Do not use in your production. */
|
||||
_InternalPanelDoNotUseOrYouWillBeFired: typeof PurePanel;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type * as React from 'react';
|
||||
|
||||
import type { ClosableType } from '../_util/hooks/useClosable';
|
||||
import type { NotificationConfig as RcNotificationConfig } from 'rc-notification';
|
||||
|
||||
interface DivProps extends React.HTMLProps<HTMLDivElement> {
|
||||
'data-testid'?: string;
|
||||
@@ -14,11 +13,25 @@ export const NotificationPlacements = [
|
||||
'bottomLeft',
|
||||
'bottomRight',
|
||||
] as const;
|
||||
|
||||
export type NotificationPlacement = (typeof NotificationPlacements)[number];
|
||||
|
||||
export type IconType = 'success' | 'info' | 'error' | 'warning';
|
||||
|
||||
export interface ArgsProps {
|
||||
type SharedProps = Pick<
|
||||
RcNotificationConfig,
|
||||
| 'prefixCls'
|
||||
| 'getContainer'
|
||||
| 'maxCount'
|
||||
| 'stack'
|
||||
| 'duration'
|
||||
| 'showProgress'
|
||||
| 'pauseOnHover'
|
||||
| 'closeIcon'
|
||||
| 'closable'
|
||||
>;
|
||||
|
||||
export interface ArgsProps extends SharedProps {
|
||||
message: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
/** @deprecated Please use `actions` instead */
|
||||
@@ -26,17 +39,15 @@ export interface ArgsProps {
|
||||
actions?: React.ReactNode;
|
||||
key?: React.Key;
|
||||
onClose?: () => void;
|
||||
duration?: number | null;
|
||||
showProgress?: boolean;
|
||||
pauseOnHover?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
placement?: NotificationPlacement;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
readonly type?: IconType;
|
||||
onClick?: () => void;
|
||||
closeIcon?: React.ReactNode;
|
||||
closable?: ClosableType;
|
||||
/**
|
||||
* @private It may be internal, uncertain, so it's better not to use it.
|
||||
*/
|
||||
props?: DivProps;
|
||||
role?: 'alert' | 'status';
|
||||
}
|
||||
@@ -52,33 +63,16 @@ export interface NotificationInstance {
|
||||
destroy: (key?: React.Key) => void;
|
||||
}
|
||||
|
||||
export interface GlobalConfigProps {
|
||||
// Prevent destructive updates, We do not internally use.
|
||||
export type GlobalConfigProps = NotificationConfig;
|
||||
|
||||
export interface NotificationConfig extends SharedProps {
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
duration?: number;
|
||||
showProgress?: boolean;
|
||||
pauseOnHover?: boolean;
|
||||
prefixCls?: string;
|
||||
getContainer?: () => HTMLElement | ShadowRoot;
|
||||
placement?: NotificationPlacement;
|
||||
closeIcon?: React.ReactNode;
|
||||
closable?: ClosableType;
|
||||
rtl?: boolean;
|
||||
maxCount?: number;
|
||||
/**
|
||||
* @private It may be internal, uncertain, so it's better not to use it.
|
||||
*/
|
||||
props?: DivProps;
|
||||
}
|
||||
|
||||
export interface NotificationConfig {
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
prefixCls?: string;
|
||||
getContainer?: () => HTMLElement | ShadowRoot;
|
||||
placement?: NotificationPlacement;
|
||||
maxCount?: number;
|
||||
rtl?: boolean;
|
||||
stack?: boolean | { threshold?: number };
|
||||
duration?: number;
|
||||
showProgress?: boolean;
|
||||
pauseOnHover?: boolean;
|
||||
closeIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import classNames from 'classnames';
|
||||
import { NotificationProvider, useNotification as useRcNotification } from 'rc-notification';
|
||||
import type { NotificationAPI, NotificationConfig as RcNotificationConfig } from 'rc-notification';
|
||||
|
||||
import extendsObject from '../_util/extendsObject';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import type { NotificationConfig as CPNotificationConfig } from '../config-provider/context';
|
||||
@@ -17,7 +18,7 @@ import type {
|
||||
} from './interface';
|
||||
import { getCloseIcon, PureContent } from './PurePanel';
|
||||
import useStyle from './style';
|
||||
import { getMotion, getPlacementStyle, getCloseIconConfig } from './util';
|
||||
import { getCloseIconConfig, getMotion, getPlacementStyle } from './util';
|
||||
|
||||
const DEFAULT_OFFSET = 24;
|
||||
const DEFAULT_DURATION = 4.5;
|
||||
@@ -60,13 +61,12 @@ const Holder = React.forwardRef<HolderRef, HolderProps>((props, ref) => {
|
||||
bottom,
|
||||
prefixCls: staticPrefixCls,
|
||||
getContainer: staticGetContainer,
|
||||
maxCount,
|
||||
rtl,
|
||||
onAllRemoved,
|
||||
stack,
|
||||
duration,
|
||||
duration = DEFAULT_DURATION,
|
||||
pauseOnHover = true,
|
||||
showProgress,
|
||||
closeIcon,
|
||||
...restProps
|
||||
} = props;
|
||||
const { getPrefixCls, getPopupContainer, notification, direction } = useContext(ConfigContext);
|
||||
const [, token] = useToken();
|
||||
@@ -84,27 +84,17 @@ const Holder = React.forwardRef<HolderRef, HolderProps>((props, ref) => {
|
||||
|
||||
// ============================== Origin ===============================
|
||||
const [api, holder] = useRcNotification({
|
||||
...restProps,
|
||||
prefixCls,
|
||||
style: getStyle,
|
||||
className: getClassName,
|
||||
motion: getNotificationMotion,
|
||||
closable: true,
|
||||
closeIcon: getCloseIcon(prefixCls),
|
||||
duration: duration ?? DEFAULT_DURATION,
|
||||
closeIcon: getCloseIcon(prefixCls, closeIcon),
|
||||
duration,
|
||||
getContainer: () => staticGetContainer?.() || getPopupContainer?.() || document.body,
|
||||
maxCount,
|
||||
pauseOnHover,
|
||||
showProgress,
|
||||
onAllRemoved,
|
||||
renderNotifications,
|
||||
stack:
|
||||
stack === false
|
||||
? false
|
||||
: {
|
||||
threshold: typeof stack === 'object' ? stack?.threshold : undefined,
|
||||
offset: 8,
|
||||
gap: token.margin,
|
||||
},
|
||||
stack: stack === false ? false : extendsObject({ offset: 8, gap: token.margin }, stack),
|
||||
});
|
||||
|
||||
// ================================ Ref ================================
|
||||
@@ -155,7 +145,8 @@ export function useInternalNotification(
|
||||
closeIcon,
|
||||
closable,
|
||||
...restConfig
|
||||
} = config;
|
||||
} = extendsObject(notificationConfig, config);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warning.deprecated(!btn, 'btn', 'actions');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user