feat: update drawer

pull/1790/head
tangjinzhou 2020-02-13 19:58:19 +08:00
parent 2ee50b4066
commit e7c80606ee
18 changed files with 292 additions and 84 deletions

View File

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

View File

@ -1,12 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Drawer class is test_drawer 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-right test_drawer">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right test_drawer">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%; opacity: 0; transition: opacity .3s;">
<div class="ant-drawer-wrapper-body" style="opacity: 0; transition: opacity .3s;">
<div class="ant-drawer-header-no-title"><button aria-label="Close" class="ant-drawer-close"><i aria-label="icon: close" class="anticon anticon-close"><svg viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
</svg></i></button></div>
@ -19,12 +19,12 @@ exports[`Drawer class is test_drawer 1`] = `
`;
exports[`Drawer closable is false 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-right">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%;">
<div class="ant-drawer-wrapper-body">
<div class="ant-drawer-body">Here is content of Drawer</div>
</div>
</div>
@ -34,12 +34,12 @@ exports[`Drawer closable is false 1`] = `
`;
exports[`Drawer destroyOnClose is true 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-right">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%; opacity: 0; transition: opacity .3s;">
<div class="ant-drawer-wrapper-body" style="opacity: 0; transition: opacity .3s;">
<div class="ant-drawer-body">Here is content of Drawer</div>
</div>
</div>
@ -49,12 +49,12 @@ exports[`Drawer destroyOnClose is true 1`] = `
`;
exports[`Drawer have a title 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-right">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%;">
<div class="ant-drawer-wrapper-body">
<div class="ant-drawer-header">
<div class="ant-drawer-title">Test Title</div><button aria-label="Close" class="ant-drawer-close"><i aria-label="icon: close" class="anticon anticon-close"><svg viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
@ -69,12 +69,12 @@ exports[`Drawer have a title 1`] = `
`;
exports[`Drawer render correctly 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-right">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 400px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%;">
<div class="ant-drawer-wrapper-body">
<div class="ant-drawer-header-no-title"><button aria-label="Close" class="ant-drawer-close"><i aria-label="icon: close" class="anticon anticon-close"><svg viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
</svg></i></button></div>
@ -87,8 +87,8 @@ exports[`Drawer render correctly 1`] = `
`;
exports[`Drawer render top drawer 1`] = `
<div class="">
<div class="ant-drawer ant-drawer-top">
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-top">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateY(-100%); height: 400px;">
<div class="ant-drawer-content">

View File

@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Drawer render correctly 1`] = `
<div><button type="button" class="ant-btn"><span>open</span></button>
<div class="">
<div class="ant-drawer ant-drawer-right">
<div><button type="button" class="ant-btn" ant-click-animating-without-extra-node="false"><span>open</span></button>
<div tabindex="-1" class="">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="overflow: auto; height: 100%;">
<div class="ant-drawer-wrapper-body">
<div class="ant-drawer-header-no-title"><button aria-label="Close" class="ant-drawer-close"><i aria-label="icon: close" class="anticon anticon-close"><svg viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
</svg></i></button></div>

View File

@ -28,6 +28,30 @@ exports[`renders ./components/drawer/demo/placement.md correctly 1`] = `
</div>
`;
exports[`renders ./components/drawer/demo/render-in-current.md correctly 1`] = `
<div style="height: 200px; overflow: hidden; position: relative; border: 1px solid #ebedf0; border-radius: 2px; padding: 48px; text-align: center; background: rgb(250, 250, 250);">
Render in this
<div style="margin-top: 16px;"><button type="button" class="ant-btn ant-btn-primary"><span>Open</span></button></div>
<div tabindex="-1" class="" style="position: absolute;">
<div tabindex="-1" class="ant-drawer ant-drawer-right">
<div class="ant-drawer-mask"></div>
<div class="ant-drawer-content-wrapper" style="transform: translateX(100%); width: 256px;">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body">
<div class="ant-drawer-header">
<div class="ant-drawer-title">Basic Drawer</div>
</div>
<div class="ant-drawer-body">
<p>Some contents...</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/drawer/demo/user-profile.md correctly 1`] = `
<div>
<div class="ant-list ant-list-split ant-list-bordered">
@ -38,7 +62,7 @@ exports[`renders ./components/drawer/demo/user-profile.md correctly 1`] = `
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title"><a href="https://www.antdv.com/">Lily</a></h4>
<div class="ant-list-item-meta-description">Progresser AFX</div>
<div class="ant-list-item-meta-description">Progresser XTech</div>
</div>
</div>
<ul class="ant-list-item-action">
@ -50,7 +74,7 @@ exports[`renders ./components/drawer/demo/user-profile.md correctly 1`] = `
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title"><a href="https://www.antdv.com/">Lily</a></h4>
<div class="ant-list-item-meta-description">Progresser AFX</div>
<div class="ant-list-item-meta-description">Progresser XTech</div>
</div>
</div>
<ul class="ant-list-item-action">

View File

@ -20,6 +20,8 @@ Basic drawer.
:closable="false"
@close="onClose"
:visible="visible"
:maskClosable="false"
:afterVisibleChange="afterVisibleChange"
>
<p>Some contents...</p>
<p>Some contents...</p>
@ -35,6 +37,9 @@ Basic drawer.
};
},
methods: {
afterVisibleChange(val) {
console.log('visible', val)
},
showDrawer() {
this.visible = true;
},

View File

@ -17,7 +17,7 @@ Use form in drawer with submit button.
:width="720"
@close="onClose"
:visible="visible"
:wrapStyle="{height: 'calc(100% - 108px)',overflow: 'auto',paddingBottom: '108px'}"
:bodyStyle="{paddingBottom: '80px'}"
>
<a-form :form="form" layout="vertical" hideRequiredMark>
<a-row :gutter="16">
@ -116,13 +116,14 @@ Use form in drawer with submit button.
<div
:style="{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'right',
zIndex: 1,
}"
>
<a-button :style="{marginRight: '8px'}" @click="onClose">

View File

@ -4,6 +4,7 @@ import Placement from './placement';
import UserProfile from './user-profile';
import MultiLevelDrawer from './multi-level-drawer';
import FormInDrawer from './form-in-drawer';
import RenderInCurrent from './render-in-current';
// import CustomPaging from './customPaging'
// import CustomArrows from './customArrows'
@ -20,21 +21,21 @@ const md = {
抽屉从父窗体边缘滑入覆盖住部分父窗体内容用户在抽屉内操作时不必离开当前任务操作完成后可以平滑地回到到原任务
* 当需要一个附加的面板来控制父窗体内容这个面板在需要时呼出比如控制界面展示样式往界面中添加内容
* 当需要在当前任务流中插入临时任务创建或预览附加内容比如展示协议条款创建子对象
- 当需要一个附加的面板来控制父窗体内容这个面板在需要时呼出比如控制界面展示样式往界面中添加内容
- 当需要在当前任务流中插入临时任务创建或预览附加内容比如展示协议条款创建子对象
## 代码演示
`,
us: `# Drawer
Panel slides from screen edge.
A panel which slides in from the edge of the screen.
## When To Use
A Drawer is a panel that is typically overlaid on top of a page and slides in from the side. It contains a set of information or actions. Since that user can interact with the Drawer without leaving the current page, tasks can be achieved more efficient within the same context.
A Drawer is a panel that is typically overlaid on top of a page and slides in from the side. It contains a set of information or actions. Since the user can interact with the Drawer without leaving the current page, tasks can be achieved more efficiently within the same context.
* Use a Form to create or edit a set of information.
* Processing subtasks. When subtasks are too heavy for Popover and we still want to keep the subtasks in the context of the main task, Drawer comes very handy.
* When a same Form is needed in multiple places.
- Use a Form to create or edit a set of information.
- Processing subtasks. When subtasks are too heavy for a Popover and we still want to keep the subtasks in the context of the main task, Drawer comes very handy.
- When the same Form is needed in multiple places.
## Examples
`,
};
@ -53,6 +54,7 @@ export default {
<FormInDrawer />
<UserProfile />
<MultiLevelDrawer />
<RenderInCurrent />
<api>
<CN slot="cn" />
<US />

View File

@ -5,7 +5,7 @@
<us>
#### Multi-level drawer
Open a new drawer on top of an existing drawer to handle multi branch tasks
Open a new drawer on top of an existing drawer to handle multi branch tasks.
</us>
```tpl

View File

@ -5,7 +5,7 @@
<us>
#### Custom Placement
Basic drawer.
The Drawer can appear from any edge of the screen.
</us>
```tpl

View File

@ -0,0 +1,64 @@
<cn>
#### 渲染在当前 DOM
渲染在当前 dom 里。自定义容器,查看 getContainer。
</cn>
<us>
#### Render in current dom
Render in current dom. custom container, check getContainer.
</us>
```tpl
<template>
<div
:style="{
height: '200px',
overflow: 'hidden',
position: 'relative',
border: '1px solid #ebedf0',
borderRadius: '2px',
padding: '48px',
textAlign: 'center',
background: '#fafafa',
}"
>
Render in this
<div style="margin-top: 16px">
<a-button type="primary" @click="showDrawer">
Open
</a-button>
</div>
<a-drawer
title="Basic Drawer"
placement="right"
:closable="false"
@close="onClose"
:visible="visible"
:getContainer="false"
style="position: absolute"
>
<p>Some contents...</p>
</a-drawer>
</div>
</template>
<script>
export default {
data() {
return {
visible: false,
};
},
methods: {
afterVisibleChange(val) {
console.log('visible', val)
},
showDrawer() {
this.visible = true;
},
onClose() {
this.visible = false;
},
},
};
</script>
```

View File

@ -5,7 +5,7 @@
<us>
#### Preview drawer
Use when you need to quickly preview the outline of the object. Such as list item preview.
Use Drawer to quickly preview details of an object, such as those in a list.
</us>
```tpl
@ -22,9 +22,9 @@ Use when you need to quickly preview the outline of the object. Such as list ite
]"
bordered
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-list-item slot="renderItem" slot-scope="item, index" :key="`a-${item.id}`">
<a slot="actions" @click="showDrawer">View Profile</a>
<a-list-item-meta description="Progresser AFX">
<a-list-item-meta description="Progresser XTech">
<a slot="title" href="https://www.antdv.com/">{{item.name}}</a>
<a-avatar
slot="avatar"
@ -80,7 +80,7 @@ Use when you need to quickly preview the outline of the object. Such as list ite
</a-row>
<a-row>
<a-col :span="12">
<description-item title="Department" content="AFX" />
<description-item title="Department" content="XTech" />
</a-col>
<a-col :span="12">
<description-item title="Supervisor">

View File

@ -13,12 +13,15 @@
| wrapClassName | The class name of the container of the Drawer dialog. | string | - | |
| wrapStyle | Style of wrapper element which **contains mask** compare to `drawerStyle` | object | - | |
| drawerStyle | Style of the popup layer element | object | - | 1.4.11 |
| headerStyle | Style of the drawer header part | object | - | 1.5.0 |
| bodyStyle | Style of the drawer content part | object | - | |
| width | Width of the Drawer dialog. | string\|number | 256 | |
| height | placement is `top` or `bottom`, height of the Drawer dialog. | string\|number | - | |
| zIndex | The `z-index` of the Drawer. | Number | 1000 | |
| placement | The placement of the Drawer. | 'top' \| 'right' \| 'bottom' \| 'left' | 'right' | |
| handle | After setting, the drawer is directly mounted on the DOM, and you can control the drawer to open or close through this `handle`. | VNode \| slot | - | |
| afterVisibleChange | Callback after the animation ends when switching drawers. | function(visible) | - | 1.5.0 |
| keyboard | Whether support press esc to close | Boolean | true | 1.5.0 |
## Methods

View File

@ -1,4 +1,5 @@
import classnames from 'classnames';
import omit from 'omit.js';
import VcDrawer from '../vc-drawer/src';
import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
@ -18,6 +19,7 @@ const Drawer = {
maskStyle: PropTypes.object,
wrapStyle: PropTypes.object,
bodyStyle: PropTypes.object,
headerStyle: PropTypes.object,
drawerStyle: PropTypes.object,
title: PropTypes.any,
visible: PropTypes.bool,
@ -29,6 +31,8 @@ const Drawer = {
level: PropTypes.any.def(null),
wrapClassName: PropTypes.string, // not use class like react, vue will add class to root dom
handle: PropTypes.any,
afterVisibleChange: PropTypes.func,
keyboard: PropTypes.bool.def(true),
},
mixins: [BaseMixin],
data() {
@ -49,6 +53,14 @@ const Drawer = {
parentDrawer: this,
};
},
mounted() {
// fix: delete drawer in child and re-render, no push started.
// <Drawer>{show && <Drawer />}</Drawer>
const { visible } = this;
if (visible && this.parentDrawer) {
this.parentDrawer.push();
}
},
updated() {
this.$nextTick(() => {
if (this.preVisible !== this.visible && this.parentDrawer) {
@ -61,19 +73,23 @@ const Drawer = {
this.preVisible = this.visible;
});
},
beforeDestroy() {
// unmount drawer in child, clear push.
if (this.parentDrawer) {
this.parentDrawer.pull();
this.parentDrawer = null;
}
},
methods: {
close(e) {
if (this.visible !== undefined) {
this.$emit('close', e);
return;
}
},
onMaskClick(e) {
if (!this.maskClosable) {
return;
}
this.close(e);
},
// onMaskClick(e) {
// if (!this.maskClosable) {
// return;
// }
// this.close(e);
// },
push() {
this.setState({
_push: true,
@ -117,7 +133,7 @@ const Drawer = {
};
},
renderHeader(prefixCls) {
const { closable } = this.$props;
const { closable, headerStyle } = this.$props;
const title = getComponentFromProp(this, 'title');
if (!title && !closable) {
return null;
@ -125,17 +141,20 @@ const Drawer = {
const headerClassName = title ? `${prefixCls}-header` : `${prefixCls}-header-no-title`;
return (
<div class={headerClassName}>
<div class={headerClassName} style={headerStyle}>
{title && <div class={`${prefixCls}-title`}>{title}</div>}
{closable ? this.renderCloseIcon(prefixCls) : null}
</div>
);
},
renderCloseIcon(prefixCls) {
const { closable } = this;
return (
closable && (
<button key="closer" onClick={this.close} aria-label="Close" class={`${prefixCls}-close`}>
<Icon type="close" />
</button>
)
);
},
// render drawer body dom
@ -144,15 +163,9 @@ const Drawer = {
return null;
}
this.destroyClose = false;
const { placement, bodyStyle, drawerStyle } = this.$props;
const { bodyStyle, drawerStyle } = this.$props;
const containerStyle =
placement === 'left' || placement === 'right'
? {
overflow: 'auto',
height: '100%',
}
: {};
const containerStyle = {};
const isDestroyOnClose = this.getDestroyOnClose();
if (isDestroyOnClose) {
@ -184,9 +197,10 @@ const Drawer = {
visible,
placement,
wrapClassName,
mask,
...rest
} = props;
const haveMask = rest.mask ? '' : 'no-mask';
const haveMask = mask ? '' : 'no-mask';
const offsetStyle = {};
if (placement === 'left' || placement === 'right') {
offsetStyle.width = typeof width === 'number' ? `${width}px` : width;
@ -199,12 +213,28 @@ const Drawer = {
const vcDrawerProps = {
props: {
...rest,
...omit(rest, [
'closable',
'destroyOnClose',
'drawerStyle',
'headerStyle',
'bodyStyle',
'title',
'push',
'visible',
'getPopupContainer',
'rootPrefixCls',
'getPrefixCls',
'renderEmpty',
'csp',
'pageHeader',
'autoInsertSpaceInButton',
]),
handler,
...offsetStyle,
prefixCls,
open: visible,
showMask: props.mask,
showMask: mask,
placement,
className: classnames({
[wrapClassName]: !!wrapClassName,
@ -213,7 +243,6 @@ const Drawer = {
wrapStyle: this.getRcDrawerStyle(),
},
on: {
maskClick: this.onMaskClick,
...getListeners(this),
},
};

View File

@ -13,12 +13,15 @@
| wrapClassName | 对话框外层容器的类名 | string | - | |
| wrapStyle | 可用于设置 Drawer 最外层容器的样式,和 `drawerStyle` 的区别是作用节点包括 `mask` | object | - | |
| drawerStyle | 用于设置 Drawer 弹出层的样式 | object | - | 1.4.11 |
| headerStyle | 用于设置 Drawer 头部的样式 | object | - | 1.5.0 |
| bodyStyle | 可用于设置 Drawer 内容部分的样式 | object | - | |
| width | 宽度 | string \| number | 256 | |
| height | 高度, 在 `placement``top``bottom` 时使用 | string \| number | 256 | |
| zIndex | 设置 Drawer 的 `z-index` | Number | 1000 | |
| placement | 抽屉的方向 | 'top' \| 'right' \| 'bottom' \| 'left' | 'right' | |
| handle | 设置后抽屉直接挂载到 DOM 上,你可以通过该 handle 控制抽屉打开关闭 | VNode \| slot | - | |
| afterVisibleChange | 切换抽屉时动画结束后的回调 | function(visible) | 无 | 1.5.0 |
| keyboard | 是否支持键盘 esc 关闭 | boolean | true | 1.5.0 |
## 方法

View File

@ -6,7 +6,8 @@ import { initDefaultProps, getEvents, getListeners } from '../../_util/props-uti
import { cloneElement } from '../../_util/vnode';
import ContainerRender from '../../_util/ContainerRender';
import getScrollBarSize from '../../_util/getScrollBarSize';
import drawerProps from './drawerProps';
import { IDrawerProps } from './IDrawerPropTypes';
import KeyCode from '../../_util/KeyCode';
import {
dataToArray,
transitionEnd,
@ -29,7 +30,7 @@ const windowIsUndefined = !(
Vue.use(ref, { name: 'ant-ref' });
const Drawer = {
mixins: [BaseMixin],
props: initDefaultProps(drawerProps, {
props: initDefaultProps(IDrawerProps, {
prefixCls: 'drawer',
placement: 'left',
getContainer: 'body',
@ -151,8 +152,14 @@ const Drawer = {
}
},
methods: {
onKeyDown(e) {
if (e.keyCode === KeyCode.ESC) {
e.stopPropagation();
this.$emit('close', e);
}
},
onMaskTouchEnd(e) {
this.$emit('maskClick', e);
this.$emit('close', e);
this.onTouchEnd(e, true);
},
onIconTouchEnd(e) {
@ -170,15 +177,19 @@ const Drawer = {
});
},
onWrapperTransitionEnd(e) {
if (e.target === this.contentWrapper) {
if (e.target === this.contentWrapper && e.propertyName.match(/transform$/)) {
const open = this.getOpen();
this.dom.style.transition = '';
if (!this.sOpen && this.getCurrentDrawerSome()) {
if (!open && this.getCurrentDrawerSome()) {
document.body.style.overflowX = '';
if (this.maskDom) {
this.maskDom.style.left = '';
this.maskDom.style.width = '';
}
}
if (this.afterVisibleChange) {
this.afterVisibleChange(!!open);
}
}
},
getDefault(props) {
@ -380,12 +391,15 @@ const Drawer = {
width,
height,
wrapStyle,
keyboard,
maskClosable,
} = this.$props;
const children = this.$slots.default;
const wrapperClassname = classnames(prefixCls, {
[`${prefixCls}-${placement}`]: true,
[`${prefixCls}-open`]: open,
[className]: !!className,
'no-mask': !showMask,
});
const isOpenChange = this.isOpenChange;
const isHorizontal = placement === 'left' || placement === 'right';
@ -428,7 +442,6 @@ const Drawer = {
],
});
}
const domContProps = {
class: wrapperClassname,
directives: [
@ -441,6 +454,7 @@ const Drawer = {
],
on: {
transitionend: this.onWrapperTransitionEnd,
keydown: open && keyboard ? this.onKeyDown : noop,
},
style: wrapStyle,
};
@ -469,11 +483,11 @@ const Drawer = {
},
];
return (
<div {...domContProps}>
<div {...domContProps} tabIndex={-1}>
{showMask && (
<div
class={`${prefixCls}-mask`}
onClick={this.onMaskTouchEnd}
onClick={maskClosable ? this.onMaskTouchEnd : noop}
style={maskStyle}
{...{ directives: directivesMaskDom }}
/>
@ -610,7 +624,7 @@ const Drawer = {
},
];
return (
<div class={wrapperClassName} {...{ directives }}>
<div tabIndex={-1} class={wrapperClassName} {...{ directives }}>
{children}
</div>
);

View File

@ -1,7 +1,6 @@
import PropTypes from '../../_util/vue-types';
export default {
wrapperClassName: PropTypes.string,
const IProps = {
width: PropTypes.any,
height: PropTypes.any,
defaultOpen: PropTypes.bool,
@ -13,15 +12,33 @@ export default {
levelMove: PropTypes.oneOfType([PropTypes.number, PropTypes.func, PropTypes.array]),
ease: PropTypes.string,
duration: PropTypes.string,
handler: PropTypes.any,
showMask: PropTypes.bool,
maskStyle: PropTypes.object,
className: PropTypes.string,
wrapStyle: PropTypes.object,
maskClosable: PropTypes.bool,
afterVisibleChange: PropTypes.func,
keyboard: PropTypes.bool,
};
const IDrawerProps = {
...IProps,
wrapperClassName: PropTypes.string,
forceRender: PropTypes.bool,
getContainer: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.object,
PropTypes.bool,
]),
handler: PropTypes.any,
showMask: PropTypes.bool,
maskStyle: PropTypes.object,
className: PropTypes.string,
wrapStyle: PropTypes.object,
};
const IDrawerChildProps = {
...IProps,
getContainer: PropTypes.func,
getOpenCount: PropTypes.func,
switchScrollingEffect: PropTypes.func,
};
export { IDrawerProps, IDrawerChildProps };

View File

@ -54,3 +54,48 @@ export function transformArguments(arg, cb) {
export const isNumeric = value => {
return !isNaN(parseFloat(value)) && isFinite(value); // eslint-disable-line
};
export const windowIsUndefined = !(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
export const getTouchParentScroll = (root, currentTarget, differX, differY) => {
if (!currentTarget || currentTarget === document || currentTarget instanceof Document) {
return false;
}
// root 为 drawer-content 设定了 overflow, 判断为 root 的 parent 时结束滚动;
if (currentTarget === root.parentNode) {
return true;
}
const isY = Math.max(Math.abs(differX), Math.abs(differY)) === Math.abs(differY);
const isX = Math.max(Math.abs(differX), Math.abs(differY)) === Math.abs(differX);
const scrollY = currentTarget.scrollHeight - currentTarget.clientHeight;
const scrollX = currentTarget.scrollWidth - currentTarget.clientWidth;
const style = document.defaultView.getComputedStyle(currentTarget);
const overflowY = style.overflowY === 'auto' || style.overflowY === 'scroll';
const overflowX = style.overflowX === 'auto' || style.overflowX === 'scroll';
const y = scrollY && overflowY;
const x = scrollX && overflowX;
if (
(isY &&
(!y ||
(y &&
((currentTarget.scrollTop >= scrollY && differY < 0) ||
(currentTarget.scrollTop <= 0 && differY > 0))))) ||
(isX &&
(!x ||
(x &&
((currentTarget.scrollLeft >= scrollX && scrollX < 0) ||
(currentTarget.scrollLeft <= 0 && scrollX > 0)))))
) {
return getTouchParentScroll(root, currentTarget.parentNode, differX, differY);
}
return false;
};

5
types/drawer.d.ts vendored
View File

@ -83,7 +83,7 @@ export declare class Drawer extends AntdComponent {
* @type object
*/
bodyStyle: object;
headerStyle: object;
/**
* Width of the Drawer dialog.
* @default 256
@ -110,7 +110,8 @@ export declare class Drawer extends AntdComponent {
* @type string
*/
placement: 'top' | 'right' | 'bottom' | 'left';
afterVisibleChange?: (visible: boolean) => void;
keyboard?: boolean;
/**
* Specify a callback that will be called when a user clicks mask, close button or Cancel button.
*/