diff --git a/components/message/__tests__/config.test.js b/components/message/__tests__/config.test.js index 050b7a319e..50c22cea4b 100644 --- a/components/message/__tests__/config.test.js +++ b/components/message/__tests__/config.test.js @@ -2,83 +2,91 @@ import { sleep } from '../../../tests/utils'; import message from '..'; describe('message.config', () => { -beforeEach(() => { - jest.useFakeTimers(); -}); - -afterEach(() => { - message.destroy(); - jest.useRealTimers(); -}); - -it('should be able to config top', () => { - message.config({ - top: 100, + beforeEach(() => { + jest.useFakeTimers(); }); - message.info('whatever'); - expect(document.querySelectorAll('.ant-message')[0].style.top).toBe('100px'); -}); -it('should be able to config getContainer', () => { - message.config({ - getContainer: () => { - const div = document.createElement('div'); - div.className = 'custom-container'; - document.body.appendChild(div); - return div; - }, + afterEach(() => { + message.destroy(); + jest.useRealTimers(); }); - message.info('whatever'); - expect(document.querySelectorAll('.custom-container').length).toBe(1); -}); -it('should be able to config maxCount', () => { - message.config({ - maxCount: 5, + it('should be able to config top', () => { + message.config({ + top: 100, + }); + message.info('whatever'); + expect(document.querySelectorAll('.ant-message')[0].style.top).toBe('100px'); }); - for (let i = 0; i < 10; i += 1) { - message.info('test'); - } - message.info('last'); - expect(document.querySelectorAll('.ant-message-notice').length).toBe(5); - expect(document.querySelectorAll('.ant-message-notice')[4].textContent).toBe('last'); - jest.runAllTimers(); - expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); -}); -it('should be able to config duration', async () => { - jest.useRealTimers(); - message.config({ - duration: 0.5, + it('should be able to config rtl', () => { + message.config({ + rtl: true, + }); + message.info('whatever'); + expect(document.querySelectorAll('.ant-message-rtl').length).toBe(1); }); - message.info('last'); - await sleep(600); - expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); - message.config({ - duration: 3, + + it('should be able to config getContainer', () => { + message.config({ + getContainer: () => { + const div = document.createElement('div'); + div.className = 'custom-container'; + document.body.appendChild(div); + return div; + }, + }); + message.info('whatever'); + expect(document.querySelectorAll('.custom-container').length).toBe(1); }); -}); -it('should be able to config prefixCls', () => { - message.config({ - prefixCls: 'prefix-test', + it('should be able to config maxCount', () => { + message.config({ + maxCount: 5, + }); + for (let i = 0; i < 10; i += 1) { + message.info('test'); + } + message.info('last'); + expect(document.querySelectorAll('.ant-message-notice').length).toBe(5); + expect(document.querySelectorAll('.ant-message-notice')[4].textContent).toBe('last'); + jest.runAllTimers(); + expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); }); - message.info('last'); - expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); - expect(document.querySelectorAll('.prefix-test-notice').length).toBe(1); - message.config({ - prefixCls: 'ant-message', + + it('should be able to config duration', async () => { + jest.useRealTimers(); + message.config({ + duration: 0.5, + }); + message.info('last'); + await sleep(600); + expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); + message.config({ + duration: 3, + }); }); -}); -it('should be able to config transitionName', () => { - message.config({ - transitionName: '', + it('should be able to config prefixCls', () => { + message.config({ + prefixCls: 'prefix-test', + }); + message.info('last'); + expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); + expect(document.querySelectorAll('.prefix-test-notice').length).toBe(1); + message.config({ + prefixCls: 'ant-message', + }); }); - message.info('last'); - expect(document.querySelectorAll('.move-up-enter').length).toBe(0); - message.config({ - transitionName: 'move-up', + + it('should be able to config transitionName', () => { + message.config({ + transitionName: '', + }); + message.info('last'); + expect(document.querySelectorAll('.move-up-enter').length).toBe(0); + message.config({ + transitionName: 'move-up', + }); }); }); -}); \ No newline at end of file diff --git a/components/message/index.en-US.md b/components/message/index.en-US.md index 11d7806d62..d633a5e8ec 100644 --- a/components/message/index.en-US.md +++ b/components/message/index.en-US.md @@ -70,6 +70,7 @@ message.config({ top: 100, duration: 2, maxCount: 3, + rtl: true, }); ``` @@ -79,3 +80,4 @@ message.config({ | getContainer | Return the mount node for Message | () => HTMLElement | () => document.body | | maxCount | max message show, drop oldest if exceed limit | number | - | | top | distance from top | number | 24 | +| rtl | whether to enable RTL mode | boolean | `false` | diff --git a/components/message/index.tsx b/components/message/index.tsx index 9bd3a8d931..284f8cab6f 100755 --- a/components/message/index.tsx +++ b/components/message/index.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import classNames from 'classnames'; import Notification from 'rc-notification'; import LoadingOutlined from '@ant-design/icons/LoadingOutlined'; import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; @@ -14,6 +15,7 @@ let prefixCls = 'ant-message'; let transitionName = 'move-up'; let getContainer: () => HTMLElement; let maxCount: number; +let rtl = false; function getMessageInstance(callback: (i: any) => void) { if (messageInstance) { @@ -72,6 +74,11 @@ function notice(args: ArgsProps): MessageType { const duration = args.duration !== undefined ? args.duration : defaultDuration; const IconComponent = iconMap[args.type]; + const messageClass = classNames(`${prefixCls}-custom-content`, { + [`${prefixCls}-${args.type}`]: args.type, + [`${prefixCls}-rtl`]: rtl === true, + }); + const target = args.key || key++; const closePromise = new Promise(resolve => { const callback = () => { @@ -86,11 +93,7 @@ function notice(args: ArgsProps): MessageType { duration, style: {}, content: ( -
+
{args.icon || (IconComponent && )} {args.content}
@@ -129,6 +132,7 @@ export interface ConfigOptions { getContainer?: () => HTMLElement; transitionName?: string; maxCount?: number; + rtl?: boolean; } const api: any = { @@ -155,6 +159,9 @@ const api: any = { maxCount = options.maxCount; messageInstance = null; } + if (options.rtl !== undefined) { + rtl = options.rtl; + } }, destroy() { if (messageInstance) { diff --git a/components/message/index.zh-CN.md b/components/message/index.zh-CN.md index ffd91a1dd9..95fc10c63d 100644 --- a/components/message/index.zh-CN.md +++ b/components/message/index.zh-CN.md @@ -71,6 +71,7 @@ message.config({ top: 100, duration: 2, maxCount: 3, + rtl: true, }); ``` @@ -80,3 +81,4 @@ message.config({ | getContainer | 配置渲染节点的输出位置 | () => HTMLElement | () => document.body | | maxCount | 最大显示数, 超过限制时,最早的消息会被自动关闭 | number | - | | top | 消息距离顶部的位置 | number | 24 | +| rtl | 是否开启 RTL 模式 | boolean | `false` | diff --git a/components/message/style/index.less b/components/message/style/index.less index 62e2be4c70..795979d820 100644 --- a/components/message/style/index.less +++ b/components/message/style/index.less @@ -72,3 +72,5 @@ opacity: 0; } } + +@import './rtl'; diff --git a/components/message/style/rtl.less b/components/message/style/rtl.less new file mode 100644 index 0000000000..944803bd3e --- /dev/null +++ b/components/message/style/rtl.less @@ -0,0 +1,17 @@ +@import '../../style/themes/index'; +@import '../../style/mixins/index'; + +@message-prefix-cls: ~'@{ant-prefix}-message'; + +.@{message-prefix-cls}-rtl { + direction: rtl; + + span { + direction: rtl; + } + + .@{iconfont-css-prefix} { + margin-right: 0; + margin-left: 8px; + } +}