mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 21:19:37 +08:00
Merge pull request #16123 from Nouzbe/feature
feat: Make notification functions accept top, bottom and getContainer as arguments
This commit is contained in:
commit
7409150ade
@ -28,126 +28,157 @@ describe('Notification.placement', () => {
|
||||
open();
|
||||
}
|
||||
|
||||
it('change notification placement by `open` method', () => {
|
||||
const defaultTop = '24px';
|
||||
const defaultBottom = '24px';
|
||||
let style;
|
||||
describe('placement', () => {
|
||||
it('can be configured per notification using the `open` method', () => {
|
||||
const defaultTop = '24px';
|
||||
const defaultBottom = '24px';
|
||||
let style;
|
||||
|
||||
// topLeft
|
||||
open({
|
||||
placement: 'topLeft',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topLeft')[0]);
|
||||
expect(style.top).toBe(defaultTop);
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
// topLeft
|
||||
open({
|
||||
placement: 'topLeft',
|
||||
top: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topLeft')[0]);
|
||||
expect(style.top).toBe('50px');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
open({
|
||||
placement: 'topLeft',
|
||||
});
|
||||
expect($$('.ant-notification-topLeft').length).toBe(1);
|
||||
open({
|
||||
placement: 'topLeft',
|
||||
});
|
||||
expect($$('.ant-notification-topLeft').length).toBe(1);
|
||||
|
||||
// topRight
|
||||
open({
|
||||
placement: 'topRight',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topRight')[0]);
|
||||
expect(style.top).toBe(defaultTop);
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
// topRight
|
||||
open({
|
||||
placement: 'topRight',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topRight')[0]);
|
||||
expect(style.top).toBe(defaultTop);
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
open({
|
||||
placement: 'topRight',
|
||||
});
|
||||
expect($$('.ant-notification-topRight').length).toBe(1);
|
||||
open({
|
||||
placement: 'topRight',
|
||||
});
|
||||
expect($$('.ant-notification-topRight').length).toBe(1);
|
||||
|
||||
// bottomRight
|
||||
open({
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomRight')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe(defaultBottom);
|
||||
// bottomRight
|
||||
open({
|
||||
placement: 'bottomRight',
|
||||
bottom: 100,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomRight')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('100px');
|
||||
|
||||
open({
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
expect($$('.ant-notification-bottomRight').length).toBe(1);
|
||||
open({
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
expect($$('.ant-notification-bottomRight').length).toBe(1);
|
||||
|
||||
// bottomLeft
|
||||
open({
|
||||
placement: 'bottomLeft',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomLeft')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe(defaultBottom);
|
||||
// bottomLeft
|
||||
open({
|
||||
placement: 'bottomLeft',
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomLeft')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe(defaultBottom);
|
||||
|
||||
open({
|
||||
placement: 'bottomLeft',
|
||||
open({
|
||||
placement: 'bottomLeft',
|
||||
});
|
||||
expect($$('.ant-notification-bottomLeft').length).toBe(1);
|
||||
});
|
||||
|
||||
it('can be configured globally using the `config` method', () => {
|
||||
let style;
|
||||
|
||||
// topLeft
|
||||
config({
|
||||
placement: 'topLeft',
|
||||
top: 50,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topLeft')[0]);
|
||||
expect(style.top).toBe('50px');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
// topRight
|
||||
config({
|
||||
placement: 'topRight',
|
||||
top: 100,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topRight')[0]);
|
||||
expect(style.top).toBe('100px');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
// bottomRight
|
||||
config({
|
||||
placement: 'bottomRight',
|
||||
top: 50,
|
||||
bottom: 100,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomRight')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('100px');
|
||||
|
||||
// bottomLeft
|
||||
config({
|
||||
placement: 'bottomLeft',
|
||||
top: 100,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomLeft')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('50px');
|
||||
});
|
||||
expect($$('.ant-notification-bottomLeft').length).toBe(1);
|
||||
});
|
||||
|
||||
it('change notification placement by `config` method', () => {
|
||||
let style;
|
||||
|
||||
// topLeft
|
||||
config({
|
||||
placement: 'topLeft',
|
||||
top: 50,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topLeft')[0]);
|
||||
expect(style.top).toBe('50px');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
// topRight
|
||||
config({
|
||||
placement: 'topRight',
|
||||
top: 100,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-topRight')[0]);
|
||||
expect(style.top).toBe('100px');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('');
|
||||
|
||||
// bottomRight
|
||||
config({
|
||||
placement: 'bottomRight',
|
||||
top: 50,
|
||||
bottom: 100,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomRight')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.right).toBe('0px');
|
||||
expect(style.bottom).toBe('100px');
|
||||
|
||||
// bottomLeft
|
||||
config({
|
||||
placement: 'bottomLeft',
|
||||
top: 100,
|
||||
bottom: 50,
|
||||
});
|
||||
style = getStyle($$('.ant-notification-bottomLeft')[0]);
|
||||
expect(style.top).toBe('');
|
||||
expect(style.left).toBe('0px');
|
||||
expect(style.bottom).toBe('50px');
|
||||
});
|
||||
it('change notification mountNode by `config` method', () => {
|
||||
describe('mountNode', () => {
|
||||
const $container = document.createElement('div');
|
||||
document.body.appendChild($container);
|
||||
config({
|
||||
top: 50,
|
||||
bottom: 100,
|
||||
getContainer() {
|
||||
return $container;
|
||||
},
|
||||
beforeEach(() => {
|
||||
document.body.appendChild($container);
|
||||
});
|
||||
afterEach(() => {
|
||||
$container.remove();
|
||||
});
|
||||
|
||||
it('can be configured per notification using the `open` method', () => {
|
||||
open({
|
||||
getContainer: () => $container,
|
||||
});
|
||||
expect($container.querySelector('.ant-notification')).not.toBe(null);
|
||||
|
||||
notification.destroy();
|
||||
|
||||
setTimeout(() => {
|
||||
// Upcoming notifications still use their default mountNode and not $container
|
||||
open();
|
||||
expect($container.querySelector('.ant-notification')).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
it('can be configured globally using the `config` method', () => {
|
||||
config({
|
||||
getContainer: () => $container,
|
||||
});
|
||||
expect($container.querySelector('.ant-notification')).not.toBe(null);
|
||||
|
||||
notification.destroy();
|
||||
|
||||
setTimeout(() => {
|
||||
// Upcoming notifications are mounted in $container
|
||||
open();
|
||||
expect($container.querySelector('.ant-notification')).not.toBe(null);
|
||||
});
|
||||
});
|
||||
expect($container.querySelector('.ant-notification')).not.toBe(null);
|
||||
$container.remove();
|
||||
});
|
||||
});
|
||||
|
@ -32,17 +32,20 @@ The properties of config are as follows:
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | number | 24 |
|
||||
| btn | Customized close button | ReactNode | - |
|
||||
| className | Customized CSS class | string | - |
|
||||
| description | The content of notification box (required) | string\|ReactNode | - |
|
||||
| duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 |
|
||||
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body |
|
||||
| icon | Customized icon | ReactNode | - |
|
||||
| key | The unique identifier of the Notification | string | - |
|
||||
| message | The title of notification box (required) | string\|ReactNode | - |
|
||||
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` |
|
||||
| style | Customized inline style | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| onClose | Specify a function that will be called when the close button is clicked | Function | - |
|
||||
| onClick | Specify a function that will be called when the notification is clicked | Function | - |
|
||||
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` |
|
||||
| style | Customized inline style | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | number | 24 |
|
||||
|
||||
`notification` also provides a global `config()` method that can be used for specifying the default options. Once this method is used, all the notification boxes will take into account these globally defined options when displaying.
|
||||
|
||||
|
@ -40,20 +40,24 @@ function setNotificationConfig(options: ConfigProps) {
|
||||
}
|
||||
}
|
||||
|
||||
function getPlacementStyle(placement: NotificationPlacement) {
|
||||
function getPlacementStyle(
|
||||
placement: NotificationPlacement,
|
||||
top: number = defaultTop,
|
||||
bottom: number = defaultBottom,
|
||||
) {
|
||||
let style;
|
||||
switch (placement) {
|
||||
case 'topLeft':
|
||||
style = {
|
||||
left: 0,
|
||||
top: defaultTop,
|
||||
top,
|
||||
bottom: 'auto',
|
||||
};
|
||||
break;
|
||||
case 'topRight':
|
||||
style = {
|
||||
right: 0,
|
||||
top: defaultTop,
|
||||
top,
|
||||
bottom: 'auto',
|
||||
};
|
||||
break;
|
||||
@ -61,23 +65,36 @@ function getPlacementStyle(placement: NotificationPlacement) {
|
||||
style = {
|
||||
left: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
bottom,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
style = {
|
||||
right: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
bottom,
|
||||
};
|
||||
break;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
type NotificationInstanceProps = {
|
||||
prefixCls: string;
|
||||
placement?: NotificationPlacement;
|
||||
getContainer?: () => HTMLElement;
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
};
|
||||
|
||||
function getNotificationInstance(
|
||||
prefixCls: string,
|
||||
placement: NotificationPlacement,
|
||||
{
|
||||
prefixCls,
|
||||
placement = defaultPlacement,
|
||||
getContainer = defaultGetContainer,
|
||||
top,
|
||||
bottom,
|
||||
}: NotificationInstanceProps,
|
||||
callback: (n: any) => void,
|
||||
) {
|
||||
const cacheKey = `${prefixCls}-${placement}`;
|
||||
@ -89,8 +106,8 @@ function getNotificationInstance(
|
||||
{
|
||||
prefixCls,
|
||||
className: `${prefixCls}-${placement}`,
|
||||
style: getPlacementStyle(placement),
|
||||
getContainer: defaultGetContainer,
|
||||
style: getPlacementStyle(placement, top, bottom),
|
||||
getContainer,
|
||||
closeIcon: <Icon className={`${prefixCls}-close-icon`} type={'close'} />,
|
||||
},
|
||||
(notification: any) => {
|
||||
@ -121,6 +138,9 @@ export interface ArgsProps {
|
||||
className?: string;
|
||||
readonly type?: IconType;
|
||||
onClick?: () => void;
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
getContainer?: () => HTMLElement;
|
||||
}
|
||||
|
||||
function notice(args: ArgsProps) {
|
||||
@ -143,9 +163,16 @@ function notice(args: ArgsProps) {
|
||||
<span className={`${prefixCls}-message-single-line-auto-margin`} />
|
||||
) : null;
|
||||
|
||||
const { placement, top, bottom, getContainer } = args;
|
||||
|
||||
getNotificationInstance(
|
||||
outerPrefixCls,
|
||||
args.placement || defaultPlacement,
|
||||
{
|
||||
prefixCls: outerPrefixCls,
|
||||
placement,
|
||||
top,
|
||||
bottom,
|
||||
getContainer,
|
||||
},
|
||||
(notification: any) => {
|
||||
notification.notice({
|
||||
content: (
|
||||
|
@ -32,16 +32,19 @@ config 参数如下:
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| btn | 自定义关闭按钮 | ReactNode | - |
|
||||
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 |
|
||||
| className | 自定义 CSS class | string | - |
|
||||
| description | 通知提醒内容,必选 | string\|ReactNode | - |
|
||||
| duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 |
|
||||
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body |
|
||||
| icon | 自定义图标 | ReactNode | - |
|
||||
| key | 当前通知唯一标志 | string | - |
|
||||
| message | 通知提醒标题,必选 | string\|ReactNode | - |
|
||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
| style | 自定义内联样式 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | - |
|
||||
| onClick | 点击通知时触发的回调函数 | Function | - |
|
||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
| style | 自定义内联样式 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | number | 24 |
|
||||
|
||||
还提供了一个全局配置方法,在调用前提前配置,全局一次生效。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user