add notification
parent
92568220f4
commit
e6fad3803a
|
@ -1,16 +1,15 @@
|
|||
import cloneDeep from 'lodash.clonedeep'
|
||||
export function cloneVNode (vnode, deep) {
|
||||
const componentOptions = vnode.componentOptions
|
||||
const data = vnode.data
|
||||
|
||||
let listeners = {}
|
||||
if (componentOptions && componentOptions.listeners) {
|
||||
listeners = cloneDeep(componentOptions.listeners)
|
||||
listeners = { ...componentOptions.listeners }
|
||||
}
|
||||
|
||||
let on = {}
|
||||
if (data && data.on) {
|
||||
on = cloneDeep(data.on)
|
||||
on = { ...data.on }
|
||||
}
|
||||
|
||||
const cloned = new vnode.constructor(
|
||||
|
@ -98,11 +97,23 @@ export function isEmptyElement (ele) {
|
|||
}
|
||||
|
||||
export function getClass (ele) {
|
||||
return ele.data && (ele.data.class || ele.data.staticClass)
|
||||
let data = {}
|
||||
if (ele.data) {
|
||||
data = ele.data
|
||||
} else if (ele.$vnode && ele.$vnode.data) {
|
||||
data = ele.$vnode.data
|
||||
}
|
||||
return data.class || data.staticClass
|
||||
}
|
||||
|
||||
export function getStyle (ele) {
|
||||
return ele.data && (ele.data.style || ele.data.staticStyle)
|
||||
let data = {}
|
||||
if (ele.data) {
|
||||
data = ele.data
|
||||
} else if (ele.$vnode && ele.$vnode.data) {
|
||||
data = ele.$vnode.data
|
||||
}
|
||||
return data.style || data.staticStyle
|
||||
}
|
||||
|
||||
export function filterEmpty (children = []) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
| -------- | ----------- | ---- | ------- |
|
||||
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||
| getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` |
|
||||
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||
| overlay(slot) | the dropdown menu | [Menu](#/us/components/menu) | - |
|
||||
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||
| visible(v-model) | whether the dropdown menu is visible | boolean | - |
|
||||
|
@ -16,7 +16,7 @@
|
|||
| --- | --- | --- |
|
||||
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | function(visible) |
|
||||
|
||||
You should use [Menu](#/components/us/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||
You should use [Menu](#/us/components/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||
|
||||
> Warning: You must set a unique `key` for `Menu.Item`.
|
||||
>
|
||||
|
@ -27,11 +27,11 @@ You should use [Menu](#/components/us/menu/) as `overlay`. The menu items and di
|
|||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||
| overlay(slot) | the dropdown menu | [Menu](#/us/components/menu) | - |
|
||||
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||
| size | size of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||
| size | size of the button, the same as [Button](#/us/components/button) | string | `default` |
|
||||
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||
| type | type of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||
| type | type of the button, the same as [Button](#/us/components/button) | string | `default` |
|
||||
| visible | whether the dropdown menu is visible | boolean | - |
|
||||
|
||||
|
||||
|
@ -39,5 +39,5 @@ You should use [Menu](#/components/us/menu/) as `overlay`. The menu items and di
|
|||
### Dropdown.Button events
|
||||
| Events Name | Description | Arguments |
|
||||
| --- | --- | --- |
|
||||
| click | a callback function, the same as [Button](#/components/us/button), which will be executed when you click the button on the left | Function |
|
||||
| click | a callback function, the same as [Button](#/us/components/button), which will be executed when you click the button on the left | Function |
|
||||
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | Function |
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
| --- | --- | --- | --- |
|
||||
| disabled | 菜单是否禁用 | boolean | - |
|
||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` |
|
||||
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu) | - |
|
||||
| overlay(slot) | 菜单 | [Menu](#/cn/components/menu) | - |
|
||||
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||
|
||||
`overlay` 菜单使用 [Menu](#/components/cn/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。
|
||||
`overlay` 菜单使用 [Menu](#/cn/components/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。
|
||||
|
||||
> 注意: Menu.Item 必须设置唯一的 key 属性。
|
||||
>
|
||||
|
@ -28,15 +28,15 @@
|
|||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| disabled | 菜单是否禁用 | boolean | - |
|
||||
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu/) | - |
|
||||
| overlay(slot) | 菜单 | [Menu](#/cn/components/menu/) | - |
|
||||
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||
| size | 按钮大小,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||
| size | 按钮大小,和 [Button](#/cn/components/button/) 一致 | string | 'default' |
|
||||
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||
| type | 按钮类型,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||
| type | 按钮类型,和 [Button](#/cn/components/button/) 一致 | string | 'default' |
|
||||
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||
|
||||
### Dropdown.Button事件
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
| --- | --- | --- |
|
||||
| click | 点击左侧按钮的回调,和 [Button](#/components/cn/button/) 一致 | Function |
|
||||
| click | 点击左侧按钮的回调,和 [Button](#/cn/components/button/) 一致 | Function |
|
||||
| visibleChange | 菜单显示状态改变时调用,参数为 visible | function(visible) |
|
||||
|
|
|
@ -59,3 +59,10 @@ export { default as Divider } from './divider'
|
|||
import Collapse from './collapse'
|
||||
const CollapsePanel = Collapse.Panel
|
||||
export { Collapse, CollapsePanel }
|
||||
|
||||
import notification from './notification'
|
||||
|
||||
const api = {
|
||||
notification,
|
||||
}
|
||||
export { api }
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
<cn>
|
||||
#### 基本
|
||||
最简单的用法,4.5 秒后自动关闭。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Basic
|
||||
The simplest usage that close the notification box after 4.5s.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
openNotification () {
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
<cn>
|
||||
#### 自定义图标
|
||||
图标可以被自定义。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Customized Icon
|
||||
The icon can be customized to any vue node or (h) => vue node.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
openNotification () {
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
icon: <a-icon type="smile-circle" style="color: #108ee9" />,
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
<cn>
|
||||
#### 自定义样式
|
||||
使用 style 和 className 来定义样式。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Customized style
|
||||
The style and className are available to customize Notification.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
openNotification () {
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
style: {
|
||||
width: '600px',
|
||||
marginLeft: `${335 - 600}px`,
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
<cn>
|
||||
#### 自动关闭的延时
|
||||
自定义通知框自动关闭的延时,默认`4.5s`,取消自动关闭只要将该值设为 `0` 即可。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Duration after which the notification box is closed
|
||||
`Duration` can be used to specify how long the notification stays open. After the duration time elapses,
|
||||
the notification closes automatically. If not specified, default value is 4.5 seconds. If you set the value to 0,
|
||||
the notification box will never close automatically.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
openNotification () {
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'I will never close automatically. I will be close automatically. I will never close automatically.',
|
||||
duration: 0,
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<script>
|
||||
import Basic from './basic'
|
||||
import CustomIcon from './custom-icon'
|
||||
import CustomStyle from './custom-style'
|
||||
import Duration from './duration'
|
||||
import Placement from './placement'
|
||||
import WithBtn from './with-btn'
|
||||
import WithIcon from './with-icon'
|
||||
import CN from '../index.zh-CN.md'
|
||||
import US from '../index.en-US.md'
|
||||
const md = {
|
||||
cn: `# 通知提醒框
|
||||
全局展示通知提醒信息。
|
||||
## 何时使用
|
||||
在系统四个角显示通知提醒信息。经常用于以下情况:
|
||||
- 较为复杂的通知内容。
|
||||
- 带有交互的通知,给出用户下一步的行动点。
|
||||
- 系统主动推送。
|
||||
## 代码演示`,
|
||||
us: `# Notification
|
||||
Display a notification message globally.
|
||||
## When To Use
|
||||
To display a notification message at any of the four corners of the viewport. Typically it can be
|
||||
used in the following cases:
|
||||
- A notification with complex content.
|
||||
- A notification providing a feedback based on the user interaction. Or it may show some details
|
||||
about upcoming steps the user may have to follow.
|
||||
- A notification that is pushed by the application.`,
|
||||
}
|
||||
export default {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<md cn={md.cn} us={md.us}/>
|
||||
<Basic />
|
||||
<CustomIcon />
|
||||
<CustomStyle />
|
||||
<Duration />
|
||||
<Placement />
|
||||
<WithBtn />
|
||||
<WithIcon />
|
||||
<api>
|
||||
<CN slot='cn' />
|
||||
<US/>
|
||||
</api>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
<cn>
|
||||
#### 位置
|
||||
可以设置通知从右上角、右下角、左下角、左上角弹出。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Placement
|
||||
A notification box can pop up from `topRight` or `bottomRight` or `bottomLeft` or `topLeft`.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<select v-model="selected">
|
||||
<option v-for="val in options">{{val}}</option>
|
||||
</select>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</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 () {
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
<cn>
|
||||
#### 基本
|
||||
最简单的用法,4.5 秒后自动关闭。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Basic
|
||||
The simplest usage that close the notification box after 4.5s.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-button type="primary" @click="openNotification">Open the notification box</a-button>
|
||||
</template>
|
||||
<script>
|
||||
const close = () => {
|
||||
console.log('Notification was closed. Either the close button was clicked or duration time elapsed.');
|
||||
};
|
||||
export default {
|
||||
methods: {
|
||||
openNotification () {
|
||||
const key = `open${Date.now()}`;
|
||||
this.$notification.open({
|
||||
message: 'Notification Title',
|
||||
description: 'A function will be be called after the notification is closed (automatically after the "duration" time of manually).',
|
||||
btn: (h)=>{
|
||||
return h('a-button', {
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'small',
|
||||
},
|
||||
on: {
|
||||
click: () => this.$notification.close(key)
|
||||
}
|
||||
}, 'Confirm')
|
||||
},
|
||||
key,
|
||||
onClose: close,
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
<cn>
|
||||
#### 带有图标的通知提醒框
|
||||
通知提醒框左侧有图标。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Notification with icon
|
||||
A notification box with a icon at the left side.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-button @click="() => openNotificationWithIcon('success')">Success</a-button>
|
||||
<a-button @click="() => openNotificationWithIcon('info')">Info</a-button>
|
||||
<a-button @click="() => openNotificationWithIcon('warning')">Warning</a-button>
|
||||
<a-button @click="() => openNotificationWithIcon('error')">Error</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
openNotificationWithIcon (type) {
|
||||
this.$notification[type]({
|
||||
message: 'Notification Title',
|
||||
description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -1,22 +1,3 @@
|
|||
---
|
||||
category: Components
|
||||
type: Feedback
|
||||
noinstant: true
|
||||
title: Notification
|
||||
---
|
||||
|
||||
Display a notification message globally.
|
||||
|
||||
## When To Use
|
||||
|
||||
To display a notification message at any of the four corners of the viewport. Typically it can be
|
||||
used in the following cases:
|
||||
|
||||
- A notification with complex content.
|
||||
- A notification providing a feedback based on the user interaction. Or it may show some details
|
||||
about upcoming steps the user may have to follow.
|
||||
- A notification that is pushed by the application.
|
||||
|
||||
## API
|
||||
|
||||
- `notification.success(config)`
|
||||
|
@ -31,15 +12,15 @@ The properties of config are as follows:
|
|||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| btn | Customized close button | ReactNode | - |
|
||||
| className | Customized CSS class | string | - |
|
||||
| description | The content of notification box (required) | string\|ReactNode | - |
|
||||
| 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 | ReactNode | - |
|
||||
| icon | Customized icon | vueNode \|function(h) | - |
|
||||
| key | The unique identifier of the Notification | string | - |
|
||||
| message | The title of notification box (required) | string\|ReactNode | - |
|
||||
| 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 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| style | Customized inline style | Object \| string | - |
|
||||
| onClose | Specify a function that will be called when the close button is clicked | Function | - |
|
||||
|
||||
`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.
|
||||
|
@ -49,15 +30,15 @@ The properties of config are as follows:
|
|||
```js
|
||||
notification.config({
|
||||
placement: 'bottomRight',
|
||||
bottom: 50,
|
||||
bottom: '50px',
|
||||
duration: 3,
|
||||
});
|
||||
```
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | number | 24 |
|
||||
| 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). | number | 24 |
|
||||
| top | Distance from the top of the viewport, when `placement` is `topRight` or `topLeft` (unit: pixels). | string | `24px` |
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
import Notification from './src/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
|
||||
|
||||
// export interface ConfigProps {
|
||||
// top?: number;
|
||||
// bottom?: number;
|
||||
// duration?: number;
|
||||
// placement?: NotificationPlacement;
|
||||
// getContainer?: () => HTMLElement;
|
||||
// }
|
||||
function setNotificationConfig (options) {
|
||||
const { duration, placement, bottom, top, getContainer } = options
|
||||
if (duration !== undefined) {
|
||||
defaultDuration = duration
|
||||
}
|
||||
if (placement !== undefined) {
|
||||
defaultPlacement = placement
|
||||
}
|
||||
if (bottom !== undefined) {
|
||||
defaultBottom = bottom
|
||||
}
|
||||
if (top !== undefined) {
|
||||
defaultTop = top
|
||||
}
|
||||
if (getContainer !== undefined) {
|
||||
defaultGetContainer = getContainer
|
||||
}
|
||||
}
|
||||
|
||||
function getPlacementStyle (placement) {
|
||||
let style
|
||||
switch (placement) {
|
||||
case 'topLeft':
|
||||
style = {
|
||||
left: 0,
|
||||
top: defaultTop,
|
||||
bottom: 'auto',
|
||||
}
|
||||
break
|
||||
case 'topRight':
|
||||
style = {
|
||||
right: 0,
|
||||
top: defaultTop,
|
||||
bottom: 'auto',
|
||||
}
|
||||
break
|
||||
case 'bottomLeft':
|
||||
style = {
|
||||
left: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
}
|
||||
break
|
||||
default:
|
||||
style = {
|
||||
right: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
}
|
||||
break
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
function getNotificationInstance (prefixCls, placement, callback) {
|
||||
const cacheKey = `${prefixCls}-${placement}`
|
||||
if (notificationInstance[cacheKey]) {
|
||||
callback(notificationInstance[cacheKey])
|
||||
return
|
||||
}
|
||||
Notification.newInstance({
|
||||
prefixCls,
|
||||
class: `${prefixCls}-${placement}`,
|
||||
style: getPlacementStyle(placement),
|
||||
getContainer: defaultGetContainer,
|
||||
}, (notification) => {
|
||||
notificationInstance[cacheKey] = notification
|
||||
callback(notification)
|
||||
})
|
||||
}
|
||||
|
||||
const typeToIcon = {
|
||||
success: 'check-circle-o',
|
||||
info: 'info-circle-o',
|
||||
error: 'cross-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) {
|
||||
const { icon, type, description, placement, message, btn } = args
|
||||
const outerPrefixCls = args.prefixCls || 'ant-notification'
|
||||
const prefixCls = `${outerPrefixCls}-notice`
|
||||
const duration = args.duration === undefined ? defaultDuration : args.duration
|
||||
|
||||
let iconNode = null
|
||||
if (icon) {
|
||||
iconNode = (h) => (
|
||||
<span class={`${prefixCls}-icon`}>
|
||||
{typeof icon === 'function' ? icon(h) : icon}
|
||||
</span>
|
||||
)
|
||||
} else if (type) {
|
||||
const iconType = typeToIcon[type]
|
||||
iconNode = (h) => (
|
||||
<Icon
|
||||
class={`${prefixCls}-icon ${prefixCls}-icon-${type}`}
|
||||
type={iconType}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const autoMarginTag = (!description && iconNode)
|
||||
? <span class={`${prefixCls}-message-single-line-auto-margin`} />
|
||||
: null
|
||||
|
||||
getNotificationInstance(outerPrefixCls, placement || defaultPlacement, (notification) => {
|
||||
notification.notice({
|
||||
content: (h) => (
|
||||
<div class={iconNode ? `${prefixCls}-with-icon` : ''}>
|
||||
{iconNode && iconNode(h)}
|
||||
<div class={`${prefixCls}-message`}>
|
||||
{autoMarginTag}
|
||||
{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,
|
||||
key: args.key,
|
||||
style: args.style || {},
|
||||
class: args.class,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const api = {
|
||||
open: notice,
|
||||
close (key) {
|
||||
Object.keys(notificationInstance)
|
||||
.forEach(cacheKey => notificationInstance[cacheKey].removeNotice(key))
|
||||
},
|
||||
config: setNotificationConfig,
|
||||
destroy () {
|
||||
Object.keys(notificationInstance).forEach(cacheKey => {
|
||||
notificationInstance[cacheKey].destroy()
|
||||
delete notificationInstance[cacheKey]
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
['success', 'info', 'warning', 'error'].forEach((type) => {
|
||||
api[type] = (args) => api.open({
|
||||
...args,
|
||||
type,
|
||||
})
|
||||
})
|
||||
|
||||
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
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
<script>
|
||||
import Notification from './src/notification';
|
||||
import Icon from '../icon';
|
||||
|
||||
export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
|
||||
|
||||
export type IconType = 'success' | 'info' | 'error' | 'warning';
|
||||
|
||||
const notificationInstance: { [key: string]: any } = {};
|
||||
let defaultDuration = 4.5;
|
||||
let defaultTop = 24;
|
||||
let defaultBottom = 24;
|
||||
let defaultPlacement: NotificationPlacement = 'topRight';
|
||||
let defaultGetContainer: () => HTMLElement;
|
||||
|
||||
export interface ConfigProps {
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
duration?: number;
|
||||
placement?: NotificationPlacement;
|
||||
getContainer?: () => HTMLElement;
|
||||
}
|
||||
function setNotificationConfig(options: ConfigProps) {
|
||||
const { duration, placement, bottom, top, getContainer } = options;
|
||||
if (duration !== undefined) {
|
||||
defaultDuration = duration;
|
||||
}
|
||||
if (placement !== undefined) {
|
||||
defaultPlacement = placement;
|
||||
}
|
||||
if (bottom !== undefined) {
|
||||
defaultBottom = bottom;
|
||||
}
|
||||
if (top !== undefined) {
|
||||
defaultTop = top;
|
||||
}
|
||||
if (getContainer !== undefined) {
|
||||
defaultGetContainer = getContainer;
|
||||
}
|
||||
}
|
||||
|
||||
function getPlacementStyle(placement: NotificationPlacement) {
|
||||
let style;
|
||||
switch (placement) {
|
||||
case 'topLeft':
|
||||
style = {
|
||||
left: 0,
|
||||
top: defaultTop,
|
||||
bottom: 'auto',
|
||||
};
|
||||
break;
|
||||
case 'topRight':
|
||||
style = {
|
||||
right: 0,
|
||||
top: defaultTop,
|
||||
bottom: 'auto',
|
||||
};
|
||||
break;
|
||||
case 'bottomLeft':
|
||||
style = {
|
||||
left: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
style = {
|
||||
right: 0,
|
||||
top: 'auto',
|
||||
bottom: defaultBottom,
|
||||
};
|
||||
break;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function getNotificationInstance(prefixCls: string, placement: NotificationPlacement, callback: (n: any) => void) {
|
||||
const cacheKey = `${prefixCls}-${placement}`;
|
||||
if (notificationInstance[cacheKey]) {
|
||||
callback(notificationInstance[cacheKey]);
|
||||
return;
|
||||
}
|
||||
(Notification as any).newInstance({
|
||||
prefixCls,
|
||||
className: `${prefixCls}-${placement}`,
|
||||
style: getPlacementStyle(placement),
|
||||
getContainer: defaultGetContainer,
|
||||
}, (notification: any) => {
|
||||
notificationInstance[cacheKey] = notification;
|
||||
callback(notification);
|
||||
});
|
||||
}
|
||||
|
||||
const typeToIcon = {
|
||||
success: 'check-circle-o',
|
||||
info: 'info-circle-o',
|
||||
error: 'cross-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: ArgsProps) {
|
||||
const outerPrefixCls = args.prefixCls || 'ant-notification';
|
||||
const prefixCls = `${outerPrefixCls}-notice`;
|
||||
const duration = args.duration === undefined ? defaultDuration : args.duration;
|
||||
|
||||
let iconNode: React.ReactNode = null;
|
||||
if (args.icon) {
|
||||
iconNode = (
|
||||
<span className={`${prefixCls}-icon`}>
|
||||
{args.icon}
|
||||
</span>
|
||||
);
|
||||
} else if (args.type) {
|
||||
const iconType = typeToIcon[args.type];
|
||||
iconNode = (
|
||||
<Icon
|
||||
className={`${prefixCls}-icon ${prefixCls}-icon-${args.type}`}
|
||||
type={iconType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const autoMarginTag = (!args.description && iconNode)
|
||||
? <span className={`${prefixCls}-message-single-line-auto-margin`} />
|
||||
: null;
|
||||
|
||||
getNotificationInstance(outerPrefixCls, args.placement || defaultPlacement, (notification: any) => {
|
||||
notification.notice({
|
||||
content: (
|
||||
<div className={iconNode ? `${prefixCls}-with-icon` : ''}>
|
||||
{iconNode}
|
||||
<div className={`${prefixCls}-message`}>
|
||||
{autoMarginTag}
|
||||
{args.message}
|
||||
</div>
|
||||
<div className={`${prefixCls}-description`}>{args.description}</div>
|
||||
{args.btn ? <span className={`${prefixCls}-btn`}>{args.btn}</span> : null}
|
||||
</div>
|
||||
),
|
||||
duration,
|
||||
closable: true,
|
||||
onClose: args.onClose,
|
||||
key: args.key,
|
||||
style: args.style || {},
|
||||
className: args.className,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const api: any = {
|
||||
open: notice,
|
||||
close(key: string) {
|
||||
Object.keys(notificationInstance)
|
||||
.forEach(cacheKey => notificationInstance[cacheKey].removeNotice(key));
|
||||
},
|
||||
config: setNotificationConfig,
|
||||
destroy() {
|
||||
Object.keys(notificationInstance).forEach(cacheKey => {
|
||||
notificationInstance[cacheKey].destroy();
|
||||
delete notificationInstance[cacheKey];
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
['success', 'info', 'warning', 'error'].forEach((type) => {
|
||||
api[type] = (args: ArgsProps) => api.open({
|
||||
...args,
|
||||
type,
|
||||
});
|
||||
});
|
||||
|
||||
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 as NotificationApi;
|
||||
|
||||
</script>
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
category: Components
|
||||
type: Feedback
|
||||
noinstant: true
|
||||
title: Notification
|
||||
subtitle: 通知提醒框
|
||||
---
|
||||
|
||||
全局展示通知提醒信息。
|
||||
|
||||
## 何时使用
|
||||
|
||||
在系统四个角显示通知提醒信息。经常用于以下情况:
|
||||
|
@ -30,15 +20,15 @@ config 参数如下:
|
|||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| btn | 自定义关闭按钮 | ReactNode | - |
|
||||
| className | 自定义 CSS class | string | - |
|
||||
| description | 通知提醒内容,必选 | string\|ReactNode | - |
|
||||
| btn | 自定义关闭按钮 | vueNode \|function(h) | - |
|
||||
| class | 自定义 CSS class | string | - |
|
||||
| description | 通知提醒内容,必选 | string \|vueNode \|function(h) | - |
|
||||
| duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 |
|
||||
| icon | 自定义图标 | ReactNode | - |
|
||||
| icon | 自定义图标 | vueNode \|function(h) | - |
|
||||
| key | 当前通知唯一标志 | string | - |
|
||||
| message | 通知提醒标题,必选 | string\|ReactNode | - |
|
||||
| message | 通知提醒标题,必选 | string \|vueNode \|function(h) | - |
|
||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
| style | 自定义内联样式 | [React.CSSProperties](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e434515761b36830c3e58a970abf5186f005adac/types/react/index.d.ts#L794) | - |
|
||||
| style | 自定义内联样式 | Object \| string | - |
|
||||
| onClose | 点击默认关闭按钮时触发的回调函数 | Function | - |
|
||||
|
||||
还提供了一个全局配置方法,在调用前提前配置,全局一次生效。
|
||||
|
@ -48,15 +38,15 @@ config 参数如下:
|
|||
```js
|
||||
notification.config({
|
||||
placement: 'bottomRight',
|
||||
bottom: 50,
|
||||
bottom: '50px',
|
||||
duration: 3,
|
||||
});
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 |
|
||||
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | string | `24px` |
|
||||
| duration | 默认自动关闭延时,单位秒 | number | 4.5 |
|
||||
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body |
|
||||
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |
|
||||
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | number | 24 |
|
||||
| top | 消息从顶部弹出时,距离顶部的位置,单位像素。 | string | `24px` |
|
||||
|
|
|
@ -7,23 +7,27 @@ export default {
|
|||
mixins: [BaseMixin],
|
||||
props: {
|
||||
duration: PropTypes.number.def(1.5),
|
||||
closable: PropTypes.bool,
|
||||
prefixCls: PropTypes.string,
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.startCloseTimer()
|
||||
},
|
||||
|
||||
beforeDestory () {
|
||||
beforeDestroy () {
|
||||
this.clearCloseTimer()
|
||||
this.willDestroy = true // beforeDestroy调用后依然会触发onMouseleave事件
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.clearCloseTimer()
|
||||
this._emit('close')
|
||||
this.__emit('close')
|
||||
},
|
||||
|
||||
startCloseTimer () {
|
||||
if (this.duration) {
|
||||
this.clearCloseTimer()
|
||||
if (!this.willDestroy && this.duration) {
|
||||
this.closeTimer = setTimeout(() => {
|
||||
this.close()
|
||||
}, this.duration * 1000)
|
||||
|
|
|
@ -57,26 +57,32 @@ const Notification = {
|
|||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
render (h) {
|
||||
const { prefixCls, notices, remove, getTransitionName } = this
|
||||
const transitionProps = getTransitionProps(getTransitionName())
|
||||
const noticeNodes = notices.map((notice) => {
|
||||
const onClose = createChainedFunction(remove.bind(this, notice.key), notice.on.close)
|
||||
const { content, duration, closable, onClose, key, style, class: className } = notice
|
||||
const close = createChainedFunction(remove.bind(this, key), onClose)
|
||||
const noticeProps = {
|
||||
...notice,
|
||||
props: {
|
||||
prefixCls,
|
||||
...notice.props,
|
||||
duration,
|
||||
closable,
|
||||
},
|
||||
on: {
|
||||
...notice.on,
|
||||
close: onClose,
|
||||
close,
|
||||
},
|
||||
style,
|
||||
class: className,
|
||||
key,
|
||||
}
|
||||
return (<Notice
|
||||
{...noticeProps}
|
||||
>
|
||||
{notice.content}
|
||||
</Notice>)
|
||||
return (
|
||||
<Notice
|
||||
{...noticeProps}
|
||||
>
|
||||
{content(h)}
|
||||
</Notice>
|
||||
)
|
||||
})
|
||||
const className = {
|
||||
[prefixCls]: 1,
|
||||
|
@ -87,14 +93,14 @@ const Notification = {
|
|||
top: '65px',
|
||||
left: '50%',
|
||||
}}>
|
||||
<transition-group {...getTransitionProps(getTransitionName(), { tag: 'div' })}>{noticeNodes}</transition-group>
|
||||
<transition-group {...transitionProps}>{noticeNodes}</transition-group>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
Notification.newInstance = function newNotificationInstance (properties, callback) {
|
||||
const { getContainer, style, class: className, on = {}, ...props } = properties || {}
|
||||
const { getContainer, style, class: className, ...props } = properties || {}
|
||||
const div = document.createElement('div')
|
||||
if (getContainer) {
|
||||
const root = getContainer()
|
||||
|
@ -102,7 +108,7 @@ Notification.newInstance = function newNotificationInstance (properties, callbac
|
|||
} else {
|
||||
document.body.appendChild(div)
|
||||
}
|
||||
const notificationInstance = new Vue({
|
||||
new Vue({
|
||||
el: div,
|
||||
mounted () {
|
||||
const self = this
|
||||
|
@ -116,9 +122,8 @@ Notification.newInstance = function newNotificationInstance (properties, callbac
|
|||
},
|
||||
component: self,
|
||||
destroy () {
|
||||
// self.$destroy()
|
||||
notificationInstance.$destroy()
|
||||
div.parentNode.removeChild(div)
|
||||
self.$destroy()
|
||||
self.$el.parentNode.removeChild(self.$el)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
@ -126,7 +131,6 @@ Notification.newInstance = function newNotificationInstance (properties, callbac
|
|||
render () {
|
||||
const p = {
|
||||
props,
|
||||
on,
|
||||
ref: 'notification',
|
||||
style,
|
||||
class: className,
|
||||
|
|
|
@ -18,3 +18,4 @@ import './dropdown/style'
|
|||
import './divider/style'
|
||||
import './card/style'
|
||||
import './collapse/style'
|
||||
import './notification/style'
|
||||
|
|
|
@ -13,6 +13,8 @@ Popover | done
|
|||
Menu | done
|
||||
Dropdown | done
|
||||
Divider | done
|
||||
notification | done
|
||||
message
|
||||
Carousel
|
||||
Mention
|
||||
Input | done |select完成后补全demo
|
||||
|
@ -32,9 +34,7 @@ Affix
|
|||
Alert
|
||||
BackTop
|
||||
Layout
|
||||
message
|
||||
Modal
|
||||
notification
|
||||
Anchor
|
||||
Tree
|
||||
TreeSelect
|
||||
|
@ -46,7 +46,7 @@ Avatar | done
|
|||
Badge | done
|
||||
Breadcrumb | done
|
||||
Card | done
|
||||
Collapse
|
||||
Collapse | done
|
||||
LocaleProvider
|
||||
Progress
|
||||
Slider
|
||||
|
|
|
@ -15,7 +15,7 @@ export default {
|
|||
<div class='main-wrapper'>
|
||||
<a-menu class='nav' selectedKeys={[name]}>
|
||||
{Object.keys(AllDemo).map(d => <a-menu-item key={d}>
|
||||
<router-link to={{ path: `/components/${lang}/${d}` }}>{d}</router-link>
|
||||
<router-link to={{ path: `/${lang}/components/${d}` }}>{d}</router-link>
|
||||
</a-menu-item>)}
|
||||
</a-menu>
|
||||
<div class='content main-container'>
|
||||
|
|
|
@ -19,4 +19,5 @@ export { default as tooltip } from 'antd/tooltip/demo/index.vue'
|
|||
export { default as dropdown } from 'antd/dropdown/demo/index.vue'
|
||||
export { default as divider } from 'antd/divider/demo/index.vue'
|
||||
export { default as collapse } from 'antd/collapse/demo/index.vue'
|
||||
export { default as notification } from 'antd/notification/demo/index.vue'
|
||||
|
||||
|
|
|
@ -16,8 +16,14 @@ Vue.component(Md.name, Md)
|
|||
Vue.component(Api.name, Api)
|
||||
Vue.component('demo-box', demoBox)
|
||||
Object.keys(Components).forEach(k => {
|
||||
const name = `a${k.replace(/([A-Z])/g, '-$1').toLowerCase()}`
|
||||
Vue.component(name, Components[k])
|
||||
if (k === 'api') {
|
||||
Object.keys(Components[k]).forEach(api => {
|
||||
Vue.prototype[`$${api}`] = Components[k][api]
|
||||
})
|
||||
} else {
|
||||
const name = `a${k.replace(/([A-Z])/g, '-$1').toLowerCase()}`
|
||||
Vue.component(name, Components[k])
|
||||
}
|
||||
})
|
||||
|
||||
const router = new VueRouter({
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import Demo from './components/demo.vue'
|
||||
const AsyncComp = () => {
|
||||
const hashs = window.location.hash.split('/')
|
||||
const d = hashs[hashs.length - 1]
|
||||
return {
|
||||
component: import(`../components/collapse/demo/index.vue`),
|
||||
component: import(`../components/notification/demo/${d}.md`),
|
||||
}
|
||||
}
|
||||
export default [
|
||||
{ path: '/components/:lang/:name/:demo?', component: Demo },
|
||||
{ path: '/:lang/components/:name/:demo?', component: Demo },
|
||||
{ path: '/:lang?/test/:name/:demo?', component: AsyncComp },
|
||||
{ path: '/*', redirect: '/components/cn/menu' },
|
||||
{ path: '/*', redirect: '/cn/components/menu' },
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue