feat: update notification

pull/1845/head
tangjinzhou 2020-02-22 16:28:21 +08:00
parent e43f6905be
commit b95760b9cd
9 changed files with 296 additions and 248 deletions

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
dev: { dev: {
componentName: 'modal', // dev components componentName: 'notification', // dev components
}, },
}; };

View File

@ -9,14 +9,16 @@ exports[`renders ./components/notification/demo/custom-style.md correctly 1`] =
exports[`renders ./components/notification/demo/duration.md correctly 1`] = `<button type="button" class="ant-btn ant-btn-primary"><span>Open the notification box</span></button>`; exports[`renders ./components/notification/demo/duration.md correctly 1`] = `<button type="button" class="ant-btn ant-btn-primary"><span>Open the notification box</span></button>`;
exports[`renders ./components/notification/demo/placement.md correctly 1`] = ` exports[`renders ./components/notification/demo/placement.md correctly 1`] = `
<div> <div><button type="button" class="ant-btn ant-btn-primary"><i aria-label="icon: radius-upleft" class="anticon anticon-radius-upleft"><svg viewBox="64 64 896 896" data-icon="radius-upleft" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<div tabindex="0" class="ant-select ant-select-enabled" style="width: 120px; margin-right: 10px;"> <path d="M656 200h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm58 624h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM192 650h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm696-696h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-348 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-174 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm174-696H358c-127 0-230 103-230 230v182c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V358c0-87.3 70.7-158 158-158h182c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"></path>
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-controls="test-uuid" class="ant-select-selection ant-select-selection--single"> </svg></i><span>topLeft</span></button> <button type="button" class="ant-btn ant-btn-primary"><i aria-label="icon: radius-upright" class="anticon anticon-radius-upright"><svg viewBox="64 64 896 896" data-icon="radius-upright" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<div class="ant-select-selection__rendered"> <path d="M368 128h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-2 696h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm522-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM192 128h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm348 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm174 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-48-696H484c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h182c87.3 0 158 70.7 158 158v182c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V358c0-127-103-230-230-230z"></path>
<div title="topRight" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">topRight</div> </svg></i><span>topRight</span></button>
</div><span unselectable="on" class="ant-select-arrow" style="user-select: none;"><i aria-label="icon: down" class="ant-select-arrow-icon anticon anticon-down"><svg viewBox="64 64 896 896" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span> <div role="separator" class="ant-divider ant-divider-horizontal"></div> <button type="button" class="ant-btn ant-btn-primary"><i aria-label="icon: radius-bottomleft" class="anticon anticon-radius-bottomleft"><svg viewBox="64 64 896 896" data-icon="radius-bottomleft" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
</div> <path d="M712 824h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm2-696h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM136 374h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm0-174h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm752 624h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-348 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-230 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm230 624H358c-87.3 0-158-70.7-158-158V484c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v182c0 127 103 230 230 230h182c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"></path>
</div> <button type="button" class="ant-btn ant-btn-primary"><span>Open the notification box</span></button> </svg></i><span>bottomLeft</span></button> <button type="button" class="ant-btn ant-btn-primary"><i aria-label="icon: radius-bottomright" class="anticon anticon-radius-bottomright"><svg viewBox="64 64 896 896" data-icon="radius-bottomright" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M368 824h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-58-624h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm578 102h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM192 824h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0-174h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm292 72h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm174 0h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm230 276h-56c-4.4 0-8 3.6-8 8v182c0 87.3-70.7 158-158 158H484c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h182c127 0 230-103 230-230V484c0-4.4-3.6-8-8-8z"></path>
</svg></i><span>bottomRight</span></button>
</div> </div>
`; `;

View File

@ -1,5 +1,6 @@
import { asyncExpect } from '@/tests/utils'; import { asyncExpect } from '@/tests/utils';
import notification from '..'; import notification from '..';
import Icon from '../../icon';
describe('notification', () => { describe('notification', () => {
beforeEach(() => { beforeEach(() => {
@ -90,4 +91,33 @@ describe('notification', () => {
}); });
expect(document.querySelectorAll('.ant-notification').length).toBe(1); expect(document.querySelectorAll('.ant-notification').length).toBe(1);
}); });
it('support closeIcon', async () => {
await asyncExpect(() => {
notification.open({
message: 'Notification Title',
duration: 0,
closeIcon: h => <Icon type="step-backward" />,
});
});
await asyncExpect(() => {
expect(document.querySelectorAll('.anticon-step-backward').length).toBe(1);
});
});
it('support config closeIcon', async () => {
notification.config({
closeIcon: h => <Icon type="step-backward" />,
});
await asyncExpect(() => {
notification.open({
message: 'Notification Title',
duration: 0,
closeIcon: h => <Icon type="step-backward" />,
});
});
await asyncExpect(() => {
expect(document.querySelectorAll('.anticon-step-backward').length).toBe(1);
});
});
}); });

View File

@ -30,125 +30,128 @@ describe('Notification.placement', () => {
open(); open();
} }
it('change notification placement by `open` method', async () => { describe('placement', () => {
const defaultTop = '24px'; it('change notification placement by `open` method', async () => {
const defaultBottom = '24px'; const defaultTop = '24px';
let style; const defaultBottom = '24px';
let style;
// topLeft // topLeft
open({ open({
placement: 'topLeft', placement: 'topLeft',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-topLeft')[0]);
expect(style.top).toBe(defaultTop);
expect(style.left).toBe('0px');
expect(style.bottom).toBe('');
});
open({
placement: 'topLeft',
});
await asyncExpect(() => {
expect($$('.ant-notification-topLeft').length).toBe(1);
});
// topRight
open({
placement: 'topRight',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-topRight')[0]);
expect(style.top).toBe(defaultTop);
expect(style.right).toBe('0px');
expect(style.bottom).toBe('');
});
open({
placement: 'topRight',
});
await asyncExpect(() => {
expect($$('.ant-notification-topRight').length).toBe(1);
});
// bottomRight
open({
placement: 'bottomRight',
bottom: '100px',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-bottomRight')[0]);
expect(style.top).toBe('');
expect(style.right).toBe('0px');
expect(style.bottom).toBe('100px');
});
open({
placement: 'bottomRight',
});
await asyncExpect(() => {
expect($$('.ant-notification-bottomRight').length).toBe(1);
});
// bottomLeft
open({
placement: 'bottomLeft',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-bottomLeft')[0]);
expect(style.top).toBe('');
expect(style.left).toBe('0px');
expect(style.bottom).toBe(defaultBottom);
});
open({
placement: 'bottomLeft',
});
await asyncExpect(() => {
expect($$('.ant-notification-bottomLeft').length).toBe(1);
});
await asyncExpect(() => {});
await asyncExpect(() => {});
}); });
await asyncExpect(() => {
it('change notification placement by `config` method', () => {
let style;
// topLeft
config({
placement: 'topLeft',
top: '50px',
bottom: '50px',
});
style = getStyle($$('.ant-notification-topLeft')[0]); style = getStyle($$('.ant-notification-topLeft')[0]);
expect(style.top).toBe(defaultTop); expect(style.top).toBe('50px');
expect(style.left).toBe('0px'); expect(style.left).toBe('0px');
expect(style.bottom).toBe(''); expect(style.bottom).toBe('');
});
open({ // topRight
placement: 'topLeft', config({
}); placement: 'topRight',
await asyncExpect(() => { top: '100px',
expect($$('.ant-notification-topLeft').length).toBe(1); bottom: '50px',
}); });
// topRight
open({
placement: 'topRight',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-topRight')[0]); style = getStyle($$('.ant-notification-topRight')[0]);
expect(style.top).toBe(defaultTop); expect(style.top).toBe('100px');
expect(style.right).toBe('0px'); expect(style.right).toBe('0px');
expect(style.bottom).toBe(''); expect(style.bottom).toBe('');
});
open({ // bottomRight
placement: 'topRight', config({
}); placement: 'bottomRight',
await asyncExpect(() => { top: '50px',
expect($$('.ant-notification-topRight').length).toBe(1); bottom: '100px',
}); });
// bottomRight
open({
placement: 'bottomRight',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-bottomRight')[0]); style = getStyle($$('.ant-notification-bottomRight')[0]);
expect(style.top).toBe(''); expect(style.top).toBe('');
expect(style.right).toBe('0px'); expect(style.right).toBe('0px');
expect(style.bottom).toBe(defaultBottom); expect(style.bottom).toBe('100px');
});
open({ // bottomLeft
placement: 'bottomRight', config({
}); placement: 'bottomLeft',
await asyncExpect(() => { top: 100,
expect($$('.ant-notification-bottomRight').length).toBe(1); bottom: 50,
}); });
// bottomLeft
open({
placement: 'bottomLeft',
});
await asyncExpect(() => {
style = getStyle($$('.ant-notification-bottomLeft')[0]); style = getStyle($$('.ant-notification-bottomLeft')[0]);
expect(style.top).toBe(''); expect(style.top).toBe('');
expect(style.left).toBe('0px'); expect(style.left).toBe('0px');
expect(style.bottom).toBe(defaultBottom); expect(style.bottom).toBe('50px');
}); });
open({
placement: 'bottomLeft',
});
await asyncExpect(() => {
expect($$('.ant-notification-bottomLeft').length).toBe(1);
});
await asyncExpect(() => {});
await asyncExpect(() => {});
});
it('change notification placement by `config` method', () => {
let style;
// topLeft
config({
placement: 'topLeft',
top: '50px',
bottom: '50px',
});
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: '100px',
bottom: '50px',
});
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: '50px',
bottom: '100px',
});
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', () => { it('change notification mountNode by `config` method', () => {
const $container = document.createElement('div'); const $container = document.createElement('div');

View File

@ -11,34 +11,34 @@ A notification box can pop up from `topRight` or `bottomRight` or `bottomLeft` o
```tpl ```tpl
<template> <template>
<div> <div>
<a-select v-model="selected" :style="{ width: '120px', marginRight: '10px' }"> <a-button type="primary" @click="openNotification('topLeft')">
<a-select-option v-for="val in options" :key="val" :value="val">{{val}}</a-select-option> <a-icon type="radius-upleft" />
</a-select> topLeft
<a-button type="primary" @click="openNotification">Open the notification box</a-button> </a-button>
<a-button type="primary" @click="openNotification('topRight')">
<a-icon type="radius-upright" />
topRight
</a-button>
<a-divider />
<a-button type="primary" @click="openNotification('bottomLeft')">
<a-icon type="radius-bottomleft" />
bottomLeft
</a-button>
<a-button type="primary" @click="openNotification('bottomRight')">
<a-icon type="radius-bottomright" />
bottomRight
</a-button>
</div> </div>
</template> </template>
<script> <script>
const options = ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'];
export default { export default {
data() {
return {
options,
selected: 'topRight',
};
},
watch: {
selected(val) {
this.$notification.config({
placement: val,
});
},
},
methods: { methods: {
openNotification(val) { openNotification(placement) {
this.$notification.open({ this.$notification.open({
message: 'Notification Title', message: `Notification ${placement}`,
description: description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.', 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
placement,
}); });
}, },
}, },

View File

@ -11,19 +11,23 @@
The properties of config are as follows: The properties of config are as follows:
| Property | Description | Type | Default | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| btn | Customized close button | vueNode \|function(h) | - | | bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | string | `24px` | 1.5.0 |
| class | Customized CSS class | string | - | | btn | Customized close button | vueNode \|function(h) | - | |
| description | The content of notification box (required) | string\| vueNode \|function(h) | - | | class | Customized CSS class | string | - | |
| duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | description | The content of notification box (required) | string\| vueNode \|function(h) | - | |
| icon | Customized icon | vueNode \|function(h) | - | | duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | |
| key | The unique identifier of the Notification | string | - | | getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | |
| message | The title of notification box (required) | string\|vueNode \|function(h) | - | | icon | Customized icon | vueNode \|function(h) | - | |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | key | The unique identifier of the Notification | string | - | |
| style | Customized inline style | Object \| string | - | | message | The title of notification box (required) | string\|vueNode \|function(h) | - | |
| onClose | Specify a function that will be called when the close button is clicked | Function | - | | placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | |
| onClick | Specify a function that will be called when the notification is clicked | Function | - | | style | Customized inline style | Object \| string | - | |
| 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 | - | |
| top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` | 1.5.0 |
| closeIcon | custom close icon | VNode \| function(h) | - | 1.5.0 |
`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. `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.
@ -37,10 +41,11 @@ notification.config({
}); });
``` ```
| Property | Description | Type | Default | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | string | `24px` | | bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | string | `24px` | |
| duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | 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 | | getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | |
| top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` | | top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` | |
| closeIcon | custom close icon | VNode \| function(h) | - | 1.5.0 |

View File

@ -1,26 +1,16 @@
import Notification from '../vc-notification'; import Notification from '../vc-notification';
import Icon from '../icon'; import Icon from '../icon';
// export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
// export type IconType = 'success' | 'info' | 'error' | 'warning';
const notificationInstance = {}; const notificationInstance = {};
let defaultDuration = 4.5; let defaultDuration = 4.5;
let defaultTop = '24px'; let defaultTop = '24px';
let defaultBottom = '24px'; let defaultBottom = '24px';
let defaultPlacement = 'topRight'; let defaultPlacement = 'topRight';
let defaultGetContainer = () => document.body; let defaultGetContainer = () => document.body;
let defaultCloseIcon = null;
// export interface ConfigProps {
// top?: number;
// bottom?: number;
// duration?: number;
// placement?: NotificationPlacement;
// getContainer?: () => HTMLElement;
// }
function setNotificationConfig(options) { function setNotificationConfig(options) {
const { duration, placement, bottom, top, getContainer } = options; const { duration, placement, bottom, top, getContainer, closeIcon } = options;
if (duration !== undefined) { if (duration !== undefined) {
defaultDuration = duration; defaultDuration = duration;
} }
@ -36,22 +26,25 @@ function setNotificationConfig(options) {
if (getContainer !== undefined) { if (getContainer !== undefined) {
defaultGetContainer = getContainer; defaultGetContainer = getContainer;
} }
if (closeIcon !== undefined) {
defaultCloseIcon = closeIcon;
}
} }
function getPlacementStyle(placement) { function getPlacementStyle(placement, top = defaultTop, bottom = defaultBottom) {
let style; let style;
switch (placement) { switch (placement) {
case 'topLeft': case 'topLeft':
style = { style = {
left: 0, left: 0,
top: defaultTop, top,
bottom: 'auto', bottom: 'auto',
}; };
break; break;
case 'topRight': case 'topRight':
style = { style = {
right: 0, right: 0,
top: defaultTop, top,
bottom: 'auto', bottom: 'auto',
}; };
break; break;
@ -59,21 +52,31 @@ function getPlacementStyle(placement) {
style = { style = {
left: 0, left: 0,
top: 'auto', top: 'auto',
bottom: defaultBottom, bottom,
}; };
break; break;
default: default:
style = { style = {
right: 0, right: 0,
top: 'auto', top: 'auto',
bottom: defaultBottom, bottom,
}; };
break; break;
} }
return style; return style;
} }
function getNotificationInstance(prefixCls, placement, callback) { function getNotificationInstance(
{
prefixCls,
placement = defaultPlacement,
getContainer = defaultGetContainer,
top,
bottom,
closeIcon = defaultCloseIcon,
},
callback,
) {
const cacheKey = `${prefixCls}-${placement}`; const cacheKey = `${prefixCls}-${placement}`;
if (notificationInstance[cacheKey]) { if (notificationInstance[cacheKey]) {
callback(notificationInstance[cacheKey]); callback(notificationInstance[cacheKey]);
@ -83,9 +86,17 @@ function getNotificationInstance(prefixCls, placement, callback) {
{ {
prefixCls, prefixCls,
class: `${prefixCls}-${placement}`, class: `${prefixCls}-${placement}`,
style: getPlacementStyle(placement), style: getPlacementStyle(placement, top, bottom),
getContainer: defaultGetContainer, getContainer,
closeIcon: h => <Icon class={`${prefixCls}-close-icon`} type={'close'} />, // eslint-disable-line closeIcon: h => {
const icon = typeof closeIcon === 'function' ? closeIcon(h) : closeIcon;
const closeIconToRender = (
<span class={`${prefixCls}-close-x`}>
{icon || <Icon class={`${prefixCls}-close-icon`} type="close" />}
</span>
);
return closeIconToRender;
},
}, },
notification => { notification => {
notificationInstance[cacheKey] = notification; notificationInstance[cacheKey] = notification;
@ -101,22 +112,8 @@ const typeToIcon = {
warning: 'exclamation-circle-o', warning: 'exclamation-circle-o',
}; };
// export interface ArgsProps {
// message: React.ReactNode;
// description: React.ReactNode;
// btn?: React.ReactNode;
// key?: string;
// onClose?: () => void;
// duration?: number | null;
// icon?: React.ReactNode;
// placement?: NotificationPlacement;
// style?: React.CSSProperties;
// prefixCls?: string;
// className?: string;
// readonly type?: IconType;
// }
function notice(args) { function notice(args) {
const { icon, type, description, placement, message, btn } = args; const { icon, type, description, message, btn } = args;
const outerPrefixCls = args.prefixCls || 'ant-notification'; const outerPrefixCls = args.prefixCls || 'ant-notification';
const prefixCls = `${outerPrefixCls}-notice`; const prefixCls = `${outerPrefixCls}-notice`;
const duration = args.duration === undefined ? defaultDuration : args.duration; const duration = args.duration === undefined ? defaultDuration : args.duration;
@ -130,35 +127,45 @@ function notice(args) {
const iconType = typeToIcon[type]; const iconType = typeToIcon[type];
iconNode = h => <Icon class={`${prefixCls}-icon ${prefixCls}-icon-${type}`} type={iconType} />; // eslint-disable-line iconNode = h => <Icon class={`${prefixCls}-icon ${prefixCls}-icon-${type}`} type={iconType} />; // eslint-disable-line
} }
const { placement, top, bottom, getContainer, closeIcon } = args;
getNotificationInstance(outerPrefixCls, placement || defaultPlacement, notification => { getNotificationInstance(
notification.notice({ {
content: h => ( prefixCls: outerPrefixCls,
<div class={iconNode ? `${prefixCls}-with-icon` : ''}> placement,
{iconNode && iconNode(h)} top,
<div class={`${prefixCls}-message`}> bottom,
{!description && iconNode ? ( getContainer,
<span class={`${prefixCls}-message-single-line-auto-margin`} /> closeIcon,
},
notification => {
notification.notice({
content: h => (
<div class={iconNode ? `${prefixCls}-with-icon` : ''}>
{iconNode && iconNode(h)}
<div class={`${prefixCls}-message`}>
{!description && iconNode ? (
<span class={`${prefixCls}-message-single-line-auto-margin`} />
) : null}
{typeof message === 'function' ? message(h) : message}
</div>
<div class={`${prefixCls}-description`}>
{typeof description === 'function' ? description(h) : description}
</div>
{btn ? (
<span class={`${prefixCls}-btn`}>{typeof btn === 'function' ? btn(h) : btn}</span>
) : null} ) : null}
{typeof message === 'function' ? message(h) : message}
</div> </div>
<div class={`${prefixCls}-description`}> ),
{typeof description === 'function' ? description(h) : description} duration,
</div> closable: true,
{btn ? ( onClose: args.onClose,
<span class={`${prefixCls}-btn`}>{typeof btn === 'function' ? btn(h) : btn}</span> onClick: args.onClick,
) : null} key: args.key,
</div> style: args.style || {},
), class: args.class,
duration, });
closable: true, },
onClose: args.onClose, );
onClick: args.onClick,
key: args.key,
style: args.style || {},
class: args.class,
});
});
} }
const api = { const api = {
@ -186,16 +193,4 @@ const api = {
}); });
api.warn = api.warning; api.warn = api.warning;
// export interface NotificationApi {
// success(args: ArgsProps): void;
// error(args: ArgsProps): void;
// info(args: ArgsProps): void;
// warn(args: ArgsProps): void;
// warning(args: ArgsProps): void;
// open(args: ArgsProps): void;
// close(key: string): void;
// config(options: ConfigProps): void;
// destroy(): void;
// }
export default api; export default api;

View File

@ -19,19 +19,23 @@
config 参数如下: config 参数如下:
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| btn | 自定义关闭按钮 | vueNode \|function(h) | - | | btn | 自定义关闭按钮 | vueNode \|function(h) | - | |
| class | 自定义 CSS class | string | - | | bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 | 1.5.0 |
| description | 通知提醒内容,必选 | string \|vueNode \|function(h) | - | | class | 自定义 CSS class | string | - | |
| duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 | | description | 通知提醒内容,必选 | string \|vueNode \|function(h) | - | |
| icon | 自定义图标 | vueNode \|function(h) | - | | duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 | |
| key | 当前通知唯一标志 | string | - | | getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | |
| message | 通知提醒标题,必选 | string \|vueNode \|function(h) | - | | icon | 自定义图标 | vueNode \|function(h) | - | |
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | key | 当前通知唯一标志 | string | - | |
| style | 自定义内联样式 | Object \| string | - | | message | 通知提醒标题,必选 | string \|vueNode \|function(h) | - | |
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | - | | placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | |
| onClick | 点击通知时触发的回调函数 | Function | - | | style | 自定义内联样式 | Object \| string | - | |
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | - | |
| onClick | 点击通知时触发的回调函数 | Function | - | |
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | number | 24 | 1.5.0 |
| closeIcon | 自定义关闭图标 | VNode \| function(h) | - | 1.5.0 |
还提供了一个全局配置方法,在调用前提前配置,全局一次生效。 还提供了一个全局配置方法,在调用前提前配置,全局一次生效。
@ -45,10 +49,11 @@ notification.config({
}); });
``` ```
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | string | `24px` | | bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | string | `24px` | |
| duration | 默认自动关闭延时,单位秒 | number | 4.5 | | duration | 默认自动关闭延时,单位秒 | number | 4.5 | |
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | | getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | |
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | |
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | string | `24px` | | top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | string | `24px` | |
| closeIcon | 自定义关闭图标 | VNode \| function(h) | - | 1.5.0 |

View File

@ -73,6 +73,12 @@ export interface NotificationOptions {
* @type Function * @type Function
*/ */
onClick?: Function; onClick?: Function;
closeIcon?: any;
getContainer?: () => HTMLElement;
bottom?: string;
top?: string;
} }
export interface NotificationConfigOptions { export interface NotificationConfigOptions {
@ -110,6 +116,8 @@ export interface NotificationConfigOptions {
* @type string * @type string
*/ */
top?: string; top?: string;
closeIcon?: any;
} }
export declare class Notification { export declare class Notification {