[breaking change] CellSwipe: rename to SwipeCell (#1652)

This commit is contained in:
neverland
2018-08-20 10:15:30 +08:00
committed by GitHub
parent 7f00320e1f
commit e6cc4eab03
19 changed files with 116 additions and 116 deletions
+88
View File
@@ -0,0 +1,88 @@
<template>
<div>
<demo-section>
<van-notice-bar>{{ $t('tips') }}</van-notice-bar>
<demo-block :title="$t('basicUsage')">
<van-swipe-cell :right-width="65" :left-width="65">
<span slot="left">{{ $t('button1') }}</span>
<van-cell-group>
<van-cell :title="$t('title')" :value="$t('content')" />
</van-cell-group>
<span slot="right">{{ $t('button2') }}</span>
</van-swipe-cell>
</demo-block>
<demo-block :title="$t('title2')">
<van-swipe-cell :right-width="65" :left-width="65" :on-close="onClose">
<span slot="left">{{ $t('button1') }}</span>
<van-cell-group>
<van-cell :title="$t('title')" :value="$t('content')" />
</van-cell-group>
<span slot="right">{{ $t('button2') }}</span>
</van-swipe-cell>
</demo-block>
</demo-section>
</div>
</template>
<script>
export default {
i18n: {
'zh-CN': {
button1: '选择',
button2: '删除',
title: '单元格',
title2: '异步关闭',
confirm: '确定删除吗?',
tips: '建议在手机模式下浏览本示例'
},
'en-US': {
button1: 'Select',
button2: 'Delete',
title: 'Cell',
title2: 'Async close',
confirm: 'Are you sure to delete?',
tips: 'Please try this demo in mobile mode'
}
},
methods: {
onClose(clickPosition, instance) {
switch (clickPosition) {
case 'left':
case 'cell':
case 'outside':
instance.close();
break;
case 'right':
this.$dialog.confirm({
message: this.$t('confirm')
}).then(() => {
instance.close();
});
break;
}
}
}
};
</script>
<style lang="postcss">
.demo-swipe-cell {
user-select: none;
.van-swipe-cell {
&__left,
&__right {
color: #FFFFFF;
font-size: 15px;
width: 65px;
height: 44px;
display: inline-block;
text-align: center;
line-height: 44px;
background-color: #F44;
}
}
}
</style>
+89
View File
@@ -0,0 +1,89 @@
## SwipeCell
### Install
``` javascript
import { SwipeCell } from 'vant';
Vue.use(SwipeCell);
```
### Usage
#### Basic Usage
```html
<van-swipe-cell :right-width="65" :left-width="65">
<span slot="left">Select</span>
<van-cell-group>
<van-cell title="Cell" value="Cell Content" />
</van-cell-group>
<span slot="right">Delete</span>
</van-swipe-cell>
```
#### Async close
```html
<van-swipe-cell :right-width="65" :left-width="65" :on-close="onClose">
<span slot="left">Select</span>
<van-cell-group>
<van-cell title="Cell" value="Cell Content" />
</van-cell-group>
<span slot="right">Delete</span>
</van-swipe-cell>
```
```js
export default {
methods: {
onClose(clickPosition, instance) {
switch (clickPosition) {
case 'left':
case 'cell':
case 'outside':
instance.close();
break;
case 'right':
Dialog.confirm({
message: 'Are you sure to delete?'
}).then(() => {
instance.close();
});
break;
}
}
}
}
```
### API
| Attribute | Description | Type | Default |
|-----------|-----------|-----------|-------------|
| left-width | Width of the left scrollable area | `Number` | `0` |
| right-width | Width of the right scrollable area | `Number` | `0` |
| on-close | Callback function before close | `Function` | - |
### Slot
| name | Description |
|-----------|-----------|
| - | custom content |
| left | content of left scrollable area |
| right | content of right scrollabe area |
### onClose Params
| Argument | Type | Description |
|-----------|-----------|-----------|
| clickPosition | `String` | Click positon (`left` `right` `cell` `outside`) |
| instance | `Object` | SwipeCell instance |
### Methods
Use ref to get SwipeCell instance and call instance methods
| Name | Attribute | Return value | Description |
|-----------|-----------|-----------|-------------|
| open | position: 'left' \| 'right' | - | open SwipeCell |
| close | - | - | close SwipeCell |
+152
View File
@@ -0,0 +1,152 @@
<template>
<div
v-clickoutside:touchstart="onClick"
:class="b()"
@click="onClick('cell')"
@touchstart="startDrag"
@touchmove="onDrag"
@touchend="endDrag"
@touchcancel="endDrag"
>
<div
:class="b('wrapper')"
:style="wrapperStyle"
@transitionend="swipe = false"
>
<div v-if="leftWidth" :class="b('left')" @click.stop="onClick('left')">
<slot name="left" />
</div>
<slot />
<div v-if="rightWidth" :class="b('right')" @click.stop="onClick('right')">
<slot name="right" />
</div>
</div>
</div>
</template>
<script>
import create from '../utils/create';
import Clickoutside from '../utils/clickoutside';
import Touch from '../mixins/touch';
const THRESHOLD = 0.15;
export default create({
name: 'swipe-cell',
mixins: [Touch],
props: {
onClose: Function,
leftWidth: {
type: Number,
default: 0
},
rightWidth: {
type: Number,
default: 0
}
},
directives: {
Clickoutside
},
data() {
return {
offset: 0,
draging: false
};
},
computed: {
wrapperStyle() {
return {
transform: `translate3d(${this.offset}px, 0, 0)`,
transition: this.draging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
};
}
},
methods: {
open(position) {
const offset = position === 'left' ? this.leftWidth : -this.rightWidth;
this.swipeMove(offset);
this.resetSwipeStatus();
},
close() {
this.offset = 0;
},
resetSwipeStatus() {
this.swiping = false;
this.opened = true;
},
swipeMove(offset = 0) {
this.offset = offset;
offset && (this.swiping = true);
!offset && (this.opened = false);
},
swipeLeaveTransition(direction) {
const { offset, leftWidth, rightWidth } = this;
const threshold = this.opened ? (1 - THRESHOLD) : THRESHOLD;
// right
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
this.open('right');
// left
} else if (direction < 0 && offset > leftWidth * threshold && leftWidth > 0) {
this.open('left');
} else {
this.swipeMove();
}
},
startDrag(event) {
this.draging = true;
this.touchStart(event);
if (this.opened) {
this.startX -= this.offset;
}
},
onDrag(event) {
this.touchMove(event);
const { deltaX } = this;
if ((deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
(deltaX > 0 && (deltaX > this.leftWidth || deltaX > 0 && !this.leftWidth))) {
return;
}
if (this.direction === 'horizontal') {
event.preventDefault();
this.swipeMove(deltaX);
};
},
endDrag() {
this.draging = false;
if (this.swiping) {
this.swipeLeaveTransition(this.offset > 0 ? -1 : 1);
};
},
onClick(position = 'outside') {
if (!this.offset) {
return;
}
if (this.onClose) {
this.onClose(position, this);
} else {
this.swipeMove(0);
}
}
}
});
</script>
@@ -0,0 +1,51 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div>
<div class="van-notice-bar" style="color:undefined;background:undefined;">
<!---->
<div class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left:0;animation-delay:1s;animation-duration:0s;">建议在手机模式下浏览本示例</div>
</div>
<!---->
</div>
<div>
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform:translate3d(0px, 0, 0);transition:.6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left"><span>选择</span></div>
<div class="van-cell-group van-hairline--top-bottom">
<div class="van-cell van-hairline">
<!---->
<div class="van-cell__title"><span>单元格</span>
<!---->
</div>
<div class="van-cell__value"><span>内容</span></div>
<!---->
</div>
</div>
<div class="van-swipe-cell__right"><span>删除</span></div>
</div>
</div>
</div>
<div>
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform:translate3d(0px, 0, 0);transition:.6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left"><span>选择</span></div>
<div class="van-cell-group van-hairline--top-bottom">
<div class="van-cell van-hairline">
<!---->
<div class="van-cell__title"><span>单元格</span>
<!---->
</div>
<div class="van-cell__value"><span>内容</span></div>
<!---->
</div>
</div>
<div class="van-swipe-cell__right"><span>删除</span></div>
</div>
</div>
</div>
</div>
</div>
`;
@@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`drag and show left part 1`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper">
<div class="van-swipe-cell__left"></div>
<div class="van-swipe-cell__right"></div>
</div>
</div>
`;
exports[`drag and show left part 2`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper">
<div class="van-swipe-cell__left"></div>
<div class="van-swipe-cell__right"></div>
</div>
</div>
`;
exports[`drag and show left part 3`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper">
<div class="van-swipe-cell__left"></div>
<div class="van-swipe-cell__right"></div>
</div>
</div>
`;
exports[`drag and show left part 4`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper">
<div class="van-swipe-cell__left"></div>
<div class="van-swipe-cell__right"></div>
</div>
</div>
`;
exports[`drag and show left part 5`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper">
<div class="van-swipe-cell__left"></div>
<div class="van-swipe-cell__right"></div>
</div>
</div>
`;
+4
View File
@@ -0,0 +1,4 @@
import Demo from '../demo';
import demoTest from '../../../test/demo-test';
demoTest(Demo);
+66
View File
@@ -0,0 +1,66 @@
import SwipeCell from '..';
import { mount, triggerDrag } from '../../../test/utils';
const defaultProps = {
propsData: {
leftWidth: 100,
rightWidth: 100
}
};
it('drag and show left part', () => {
const wrapper = mount(SwipeCell, defaultProps);
triggerDrag(wrapper, 10, 0);
expect(wrapper).toMatchSnapshot();
triggerDrag(wrapper, 50, 0);
expect(wrapper).toMatchSnapshot();
triggerDrag(wrapper, 500, 0);
expect(wrapper).toMatchSnapshot();
triggerDrag(wrapper, 0, 100);
expect(wrapper).toMatchSnapshot();
});
it('drag and show left part', () => {
const wrapper = mount(SwipeCell, defaultProps);
triggerDrag(wrapper, -50, 0);
expect(wrapper).toMatchSnapshot();
});
test('on close prop', () => {
let position;
let instance;
const wrapper = mount(SwipeCell, {
propsData: {
...defaultProps.propsData,
onClose(pos, ins) {
position = pos;
instance = ins;
}
}
});
wrapper.trigger('click');
expect(position).toEqual(undefined);
wrapper.setData({ offset: 100 });
wrapper.trigger('click');
expect(position).toEqual('cell');
wrapper.find('.van-swipe-cell__left').trigger('click');
expect(position).toEqual('left');
wrapper.find('.van-swipe-cell__right').trigger('click');
expect(position).toEqual('right');
instance.close();
expect(wrapper.vm.offset).toEqual(0);
wrapper.setData({ offset: 100, onClose: null });
wrapper.trigger('click');
expect(wrapper.vm.offset).toEqual(0);
});
+89
View File
@@ -0,0 +1,89 @@
## SwipeCell 滑动单元格
### 使用指南
``` javascript
import { SwipeCell } from 'vant';
Vue.use(SwipeCell);
```
### 代码演示
#### 基础用法
```html
<van-swipe-cell :right-width="65" :left-width="65">
<span slot="left">选择</span>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<span slot="right">删除</span>
</van-swipe-cell>
```
#### 异步关闭
```html
<van-swipe-cell :right-width="65" :left-width="65" :on-close="onClose">
<span slot="left">选择</span>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<span slot="right">删除</span>
</van-swipe-cell>
```
```js
export default {
methods: {
onClose(clickPosition, instance) {
switch (clickPosition) {
case 'left':
case 'cell':
case 'outside':
instance.close();
break;
case 'right':
Dialog.confirm({
message: '确定删除吗?'
}).then(() => {
instance.close();
});
break;
}
}
}
}
```
### API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| left-width | 左侧滑动区域宽度 | `Number` | `0` |
| right-width | 右侧滑动区域宽度 | `Number` | `0` |
| on-close | 关闭时的回调函数 | `Function` | - |
### Slot
| 名称 | 说明 |
|-----------|-----------|
| - | 自定义显示内容 |
| left | 左侧滑动内容 |
| right | 右侧滑动内容 |
### onClose 参数
| 参数 | 类型 | 说明 |
|-----------|-----------|-----------|
| clickPosition | `String` | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| instance | `Object` | SwipeCell 实例 |
### 方法
通过 ref 可以获取到 SwipeCell 实例并调用实例方法
| 方法名 | 参数 | 返回值 | 介绍 |
|-----------|-----------|-----------|-------------|
| open | position: 'left' \| 'right' | - | 打开单元格侧边栏 |
| close | - | - | 收起单元格侧边栏 |