[improvement] rename packages dir to src (#3659)

This commit is contained in:
neverland
2019-06-27 11:25:57 +08:00
committed by GitHub
parent 8489918dca
commit 75c79b7044
619 changed files with 21 additions and 21 deletions
+104
View File
@@ -0,0 +1,104 @@
<template>
<div>
<demo-section>
<van-notice-bar>{{ $t('tips') }}</van-notice-bar>
<demo-block :title="$t('basicUsage')">
<van-swipe-cell>
<template #left>
<van-button
square
type="danger"
:text="$t('button1')"
/>
</template>
<van-cell
:border="false"
:title="$t('title')"
:value="$t('content')"
/>
<template #right>
<van-button
square
type="danger"
:text="$t('button2')"
/>
</template>
</van-swipe-cell>
</demo-block>
<demo-block :title="$t('title2')">
<van-swipe-cell :on-close="onClose">
<template #left>
<van-button
square
type="danger"
:text="$t('button1')"
/>
</template>
<van-cell
:border="false"
:title="$t('title')"
:value="$t('content')"
/>
<template #right>
<van-button
square
type="danger"
:text="$t('button2')"
/>
</template>
</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="less">
@import '../../style/var';
.demo-swipe-cell {
user-select: none;
}
</style>
+123
View File
@@ -0,0 +1,123 @@
# SwipeCell
### Install
``` javascript
import { SwipeCell } from 'vant';
Vue.use(SwipeCell);
```
## Usage
### Basic Usage
```html
<van-swipe-cell :right-width="65" :left-width="65">
<van-button
square
slot="left"
type="danger"
text="Select"
/>
<van-cell
:border="false"
title="Cell"
value="Cell Content"
/>
<van-button
square
slot="right"
type="danger"
text="Delete"
/>
</van-swipe-cell>
```
### Async close
```html
<van-swipe-cell :right-width="65" :left-width="65" :on-close="onClose">
<van-button
square
slot="left"
type="danger"
text="Select"
/>
<van-cell
:border="false"
title="Cell"
value="Cell Content"
/>
<van-button
square
slot="right"
type="danger"
text="Delete"
/>
</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
### Props
| Attribute | Description | Type | Default |
|------|------|------|------|
| on-close | Callback function before close | `Function` | - |
| disabled | Whether to disabled swipe | `Boolean` | `false` |
| left-width | Width of the left swipe area | `Number` | `auto` |
| right-width | Width of the right swipe area | `Number` | `auto` |
### Slots
| Name | Description |
|------|------|
| default | custom content |
| left | content of left scrollable area |
| right | content of right scrollabe area |
### Events
| Event | Description | Arguments |
|------|------|------|
| click | Triggered when clicked | Click positon (`left` `right` `cell` `outside`) |
### 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 |
+195
View File
@@ -0,0 +1,195 @@
import { createNamespace } from '../utils';
import { range } from '../utils/format/number';
import { preventDefault } from '../utils/dom/event';
import { TouchMixin } from '../mixins/touch';
import { ClickOutsideMixin } from '../mixins/click-outside';
const [createComponent, bem] = createNamespace('swipe-cell');
const THRESHOLD = 0.15;
export default createComponent({
mixins: [
TouchMixin,
ClickOutsideMixin({
event: 'touchstart',
method: 'onClick'
})
],
props: {
onClose: Function,
disabled: Boolean,
leftWidth: Number,
rightWidth: Number
},
data() {
return {
offset: 0,
dragging: false
};
},
computed: {
computedLeftWidth() {
return this.leftWidth || this.getWidthByRef('left');
},
computedRightWidth() {
return this.rightWidth || this.getWidthByRef('right');
}
},
methods: {
getWidthByRef(ref) {
if (this.$refs[ref]) {
const rect = this.$refs[ref].getBoundingClientRect();
return rect.width;
}
return 0;
},
open(position) {
const offset = position === 'left' ? this.computedLeftWidth : -this.computedRightWidth;
this.swipeMove(offset);
this.resetSwipeStatus();
},
close() {
this.offset = 0;
},
resetSwipeStatus() {
this.swiping = false;
this.opened = true;
},
swipeMove(offset = 0) {
this.offset = range(offset, -this.computedRightWidth, this.computedLeftWidth);
if (this.offset) {
this.swiping = true;
} else {
this.opened = false;
}
},
swipeLeaveTransition(direction) {
const { offset, computedLeftWidth, computedRightWidth } = this;
const threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;
// right
if (
direction === 'right' &&
-offset > computedRightWidth * threshold &&
computedRightWidth > 0
) {
this.open('right');
// left
} else if (
direction === 'left' &&
offset > computedLeftWidth * threshold &&
computedLeftWidth > 0
) {
this.open('left');
// reset
} else {
this.swipeMove(0);
}
},
startDrag(event) {
if (this.disabled) {
return;
}
this.dragging = true;
this.startOffset = this.offset;
this.touchStart(event);
},
onDrag(event) {
if (this.disabled) {
return;
}
this.touchMove(event);
if (this.direction === 'horizontal') {
preventDefault(event);
this.swipeMove(this.deltaX + this.startOffset);
}
},
endDrag() {
if (this.disabled) {
return;
}
this.dragging = false;
if (this.swiping) {
this.swipeLeaveTransition(this.offset > 0 ? 'left' : 'right');
}
},
onClick(position = 'outside') {
this.$emit('click', position);
if (!this.offset) {
return;
}
if (this.onClose) {
this.onClose(position, this);
} else {
this.swipeMove(0);
}
}
},
render(h) {
const onClick = (position, stop) => event => {
if (stop) {
event.stopPropagation();
}
this.onClick(position);
};
const wrapperStyle = {
transform: `translate3d(${this.offset}px, 0, 0)`,
transition: this.dragging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
};
return (
<div
class={bem()}
onClick={onClick('cell')}
onTouchstart={this.startDrag}
onTouchmove={this.onDrag}
onTouchend={this.endDrag}
onTouchcancel={this.endDrag}
>
<div
class={bem('wrapper')}
style={wrapperStyle}
onTransitionend={() => {
this.swiping = false;
}}
>
{this.slots('left') && (
<div ref="left" class={bem('left')} onClick={onClick('left', true)}>
{this.slots('left')}
</div>
)}
{this.slots()}
{this.slots('right') && (
<div ref="right" class={bem('right')} onClick={onClick('right', true)}>
{this.slots('right')}
</div>
)}
</div>
</div>
);
}
});
+23
View File
@@ -0,0 +1,23 @@
@import '../style/var';
.van-swipe-cell {
position: relative;
overflow: hidden;
&__left,
&__right {
position: absolute;
top: 0;
height: 100%;
}
&__left {
left: 0;
transform: translate3d(-100%, 0, 0);
}
&__right {
right: 0;
transform: translate3d(100%, 0, 0);
}
}
@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div>
<div role="alert" class="van-notice-bar">
<div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; 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"><button class="van-button van-button--danger van-button--normal van-button--square"><span class="van-button__text">选择</span></button></div>
<div class="van-cell van-cell--borderless">
<div class="van-cell__title"><span>单元格</span></div>
<div class="van-cell__value"><span>内容</span></div>
</div>
<div class="van-swipe-cell__right"><button class="van-button van-button--danger van-button--normal van-button--square"><span class="van-button__text">删除</span></button></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"><button class="van-button van-button--danger van-button--normal van-button--square"><span class="van-button__text">选择</span></button></div>
<div class="van-cell van-cell--borderless">
<div class="van-cell__title"><span>单元格</span></div>
<div class="van-cell__value"><span>内容</span></div>
</div>
<div class="van-swipe-cell__right"><button class="van-button van-button--danger van-button--normal van-button--square"><span class="van-button__text">删除</span></button></div>
</div>
</div>
</div>
</div>
</div>
`;
@@ -0,0 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`auto calc width 1`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(50px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`drag and show left part 1`] = `
<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">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`drag and show left part 2`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(100px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`drag and show left part 3`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(100px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`drag and show left part 4`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(100px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`drag and show right part 1`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(-100px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
<div class="van-swipe-cell__right">Right</div>
</div>
</div>
`;
exports[`render one side 1`] = `
<div class="van-swipe-cell">
<div class="van-swipe-cell__wrapper" style="transform: translate3d(50px, 0, 0); transition: .6s cubic-bezier(0.18, 0.89, 0.32, 1);">
<div class="van-swipe-cell__left">Left</div>
</div>
</div>
`;
+4
View File
@@ -0,0 +1,4 @@
import Demo from '../demo';
import demoTest from '../../../test/demo-test';
demoTest(Demo);
+126
View File
@@ -0,0 +1,126 @@
import SwipeCell from '..';
import { mount, triggerDrag, later, mockGetBoundingClientRect } from '../../../test/utils';
const THRESHOLD = 0.15;
const defaultProps = {
propsData: {
leftWidth: 100,
rightWidth: 100
},
scopedSlots: {
left: () => 'Left',
right: () => 'Right'
}
};
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 right part', () => {
const wrapper = mount(SwipeCell, defaultProps);
triggerDrag(wrapper, -50, 0);
expect(wrapper).toMatchSnapshot();
});
it('on close prop', () => {
let position;
let instance;
const wrapper = mount(SwipeCell, {
...defaultProps,
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);
});
it('should reset after drag', () => {
const wrapper = mount(SwipeCell, defaultProps);
triggerDrag(wrapper, (defaultProps.leftWidth * THRESHOLD - 1), 0);
expect(wrapper.vm.offset).toEqual(0);
});
it('disabled prop', () => {
const wrapper = mount(SwipeCell, {
propsData: {
...defaultProps.propsData,
disabled: true,
}
});
triggerDrag(wrapper, 50, 0);
expect(wrapper.vm.offset).toEqual(0);
});
it('auto calc width', async () => {
const restoreMock = mockGetBoundingClientRect({
width: 50
});
const wrapper = mount(SwipeCell, {
scopedSlots: defaultProps.scopedSlots
});
await later();
triggerDrag(wrapper, 100, 0);
expect(wrapper).toMatchSnapshot();
restoreMock();
});
it('render one side', async () => {
const restoreMock = mockGetBoundingClientRect({
width: 50
});
const wrapper = mount(SwipeCell, {
scopedSlots: {
left: defaultProps.scopedSlots.left
}
});
await later();
triggerDrag(wrapper, 100, 0);
expect(wrapper).toMatchSnapshot();
restoreMock();
});
+123
View File
@@ -0,0 +1,123 @@
# SwipeCell 滑动单元格
### 引入
``` javascript
import { SwipeCell } from 'vant';
Vue.use(SwipeCell);
```
## 代码演示
### 基础用法
```html
<van-swipe-cell :right-width="60" :left-width="60">
<van-button
square
slot="left"
type="danger"
text="选择"
/>
<van-cell
:border="false"
title="单元格"
value="内容"
/>
<van-button
square
slot="right"
type="danger"
text="删除"
/>
</van-swipe-cell>
```
### 异步关闭
```html
<van-swipe-cell :right-width="60" :left-width="60" :on-close="onClose">
<van-button
square
slot="left"
type="danger"
text="选择"
/>
<van-cell
:border="false"
title="单元格"
value="内容"
/>
<van-button
square
slot="right"
type="danger"
text="删除"
/>
</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
### Props
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| on-close | 关闭时的回调函数 | `Function` | - | - |
| disabled | 是否禁用滑动 | `Boolean` | `false` | 1.3.4 |
| left-width | 指定左侧滑动区域宽度 | `Number` | `auto` | - |
| right-width | 指定右侧滑动区域宽度 | `Number` | `auto` | - |
### Slots
| 名称 | 说明 |
|------|------|
| default | 自定义显示内容 |
| left | 左侧滑动内容 |
| right | 右侧滑动内容 |
### Events
| 事件名 | 说明 | 回调参数 |
|------|------|------|
| click | 点击时触发 | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
### onClose 参数
| 参数 | 类型 | 说明 |
|------|------|------|
| clickPosition | `String` | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| instance | `Object` | SwipeCell 实例 |
### 方法
通过 ref 可以获取到 SwipeCell 实例并调用实例方法
| 方法名 | 参数 | 返回值 | 介绍 |
|------|------|------|------|
| open | position: `left | right` | - | 打开单元格侧边栏 |
| close | - | - | 收起单元格侧边栏 |