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 = {
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/placement.md correctly 1`] = `
<div>
<div tabindex="0" class="ant-select ant-select-enabled" style="width: 120px; margin-right: 10px;">
<div role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-controls="test-uuid" class="ant-select-selection ant-select-selection--single">
<div class="ant-select-selection__rendered">
<div title="topRight" class="ant-select-selection-selected-value" style="display: block; opacity: 1;">topRight</div>
</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>
</div> <button type="button" class="ant-btn ant-btn-primary"><span>Open the notification box</span></button>
<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="">
<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>
</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="">
<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>
</svg></i><span>topRight</span></button>
<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="">
<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>
</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>
`;

View File

@ -1,5 +1,6 @@
import { asyncExpect } from '@/tests/utils';
import notification from '..';
import Icon from '../../icon';
describe('notification', () => {
beforeEach(() => {
@ -90,4 +91,33 @@ describe('notification', () => {
});
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();
}
it('change notification placement by `open` method', async () => {
const defaultTop = '24px';
const defaultBottom = '24px';
let style;
describe('placement', () => {
it('change notification placement by `open` method', async () => {
const defaultTop = '24px';
const defaultBottom = '24px';
let style;
// topLeft
open({
placement: 'topLeft',
// topLeft
open({
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]);
expect(style.top).toBe(defaultTop);
expect(style.top).toBe('50px');
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(() => {
// topRight
config({
placement: 'topRight',
top: '100px',
bottom: '50px',
});
style = getStyle($$('.ant-notification-topRight')[0]);
expect(style.top).toBe(defaultTop);
expect(style.top).toBe('100px');
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',
});
await asyncExpect(() => {
// 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(defaultBottom);
});
open({
placement: 'bottomRight',
});
await asyncExpect(() => {
expect($$('.ant-notification-bottomRight').length).toBe(1);
});
// bottomLeft
open({
placement: 'bottomLeft',
});
await asyncExpect(() => {
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(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', () => {
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
<template>
<div>
<a-select v-model="selected" :style="{ width: '120px', marginRight: '10px' }">
<a-select-option v-for="val in options" :key="val" :value="val">{{val}}</a-select-option>
</a-select>
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
<a-button type="primary" @click="openNotification('topLeft')">
<a-icon type="radius-upleft" />
topLeft
</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>
</template>
<script>
const options = ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'];
export default {
data() {
return {
options,
selected: 'topRight',
};
},
watch: {
selected(val) {
this.$notification.config({
placement: val,
});
},
},
methods: {
openNotification(val) {
openNotification(placement) {
this.$notification.open({
message: 'Notification Title',
message: `Notification ${placement}`,
description:
'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:
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| btn | Customized close button | vueNode \|function(h) | - |
| class | Customized CSS class | string | - |
| description | The content of notification box (required) | string\| 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 |
| icon | Customized icon | vueNode \|function(h) | - |
| key | The unique identifier of the Notification | string | - |
| message | The title of notification box (required) | string\|vueNode \|function(h) | - |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` |
| 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 | - |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | string | `24px` | 1.5.0 |
| btn | Customized close button | vueNode \|function(h) | - | |
| class | Customized CSS class | string | - | |
| description | The content of notification box (required) | string\| 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 | |
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | |
| icon | Customized icon | vueNode \|function(h) | - | |
| key | The unique identifier of the Notification | string | - | |
| message | The title of notification box (required) | string\|vueNode \|function(h) | - | |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | |
| 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.
@ -37,10 +41,11 @@ notification.config({
});
```
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| 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 |
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body |
| 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` |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| 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 | |
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | |
| 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` | |
| closeIcon | custom close icon | VNode \| function(h) | - | 1.5.0 |

View File

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

View File

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

View File

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