feat: add ShareSheet component

This commit is contained in:
chenjiahan 2020-04-08 20:11:47 +08:00 committed by neverland
parent 8144e3de50
commit 5080761cfe
8 changed files with 356 additions and 1 deletions

46
src/share-sheet/README.md Normal file
View File

@ -0,0 +1,46 @@
# ShareSheet
### Install
```js
import Vue from 'vue';
import { ShareSheet } from 'vant';
Vue.use(ShareSheet);
```
## Usage
### Basic Usage
## API
### Props
| Attribute | Description | Type | Default |
|------|------|------|------|
| options | Share options | *Option[]* | `[]` |
| title | Title | *string* | - |
| cancel-text | Cancel button text | *string* | `'Cancel'` |
| description | Description | *string* | - |
### Data Structure of Option
| Key | Description | Type |
|------|------|------|
| name | Option name | *string* |
| icon | Option iconcan be set to `wechat` `link` `qrcode` `poster` or image URL | *string* |
### Events
| Event | Description | Arguments |
|------|------|------|
| select | Triggered when click option | *option: Option, index: number* |
| cancel | Triggered when click cancel button | - |
### Slots
| Name | Description |
|------|------|
| title | Custom title |
| description | Custom description |

View File

@ -0,0 +1,66 @@
# ShareSheet 分享面板
### 介绍
底部弹起的模态面板用于展示各分享渠道对应的操作按钮不包含具体的分享逻辑。2.6 版本开始支持此组件。
### 引入
```js
import Vue from 'vue';
import { ShareSheet } from 'vant';
Vue.use(ShareSheet);
```
## 代码演示
### 基础用法
```html
<van-share-sheet :options="options" />
```
```js
export default {
data() {
return {
options: [],
};
},
};
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|------|------|------|------|
| options | 分享选项 | *Option[]* | `[]` |
| title | 顶部标题 | *string* | - |
| cancel-text | 取消按钮文字 | *string* | `'取消'` |
| description | 标题下方的辅助描述文字 | *string* | - |
### Option 数据结构
`options`属性为一个对象数组,数组中的每个对象配置一列,对象可以包含以下值:
| 键名 | 说明 | 类型 |
|------|------|------|
| name | 分享渠道名称 | *string* |
| icon | 图标,可选值为 `wechat` `link` `qrcode` `poster`,支持传入图片 URL | *string* |
### Events
| 事件名 | 说明 | 回调参数 |
|------|------|------|
| select | 点击分享选项时触发 | *option: Option, index: number* |
| cancel | 点击取消按钮时触发 | - |
### Slots
| 名称 | 说明 |
|------|------|
| title | 自定义顶部标题 |
| description | 自定义描述文字 |

View File

@ -0,0 +1,52 @@
<template>
<demo-section>
<demo-block :title="t('basicUsage')">
<van-cell
is-link
:title="t('showSheet')"
@click="showBasicSheet = true"
/>
<van-share-sheet v-model="showBasicSheet" :options="options" />
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
link: '复制链接',
wechat: '微信',
poster: '分享海报',
qrcode: '二维码',
showSheet: '显示分享面板',
},
'en-US': {
link: 'Link',
wechat: 'Wechat',
poster: 'Poster',
qrcode: 'Qrcode',
showSheet: 'Show ShareSheet',
},
},
data() {
return {
showBasicSheet: false,
};
},
created() {
this.options = [
{ name: this.t('wechat'), icon: 'wechat' },
{ name: this.t('link'), icon: 'link' },
{ name: this.t('poster'), icon: 'poster' },
{ name: this.t('qrcode'), icon: 'qrcode' },
];
},
};
</script>
<style lang="less">
@import '../../style/var';
</style>

97
src/share-sheet/index.js Normal file
View File

@ -0,0 +1,97 @@
// Utils
import { createNamespace, isDef } from '../utils';
// Mixins
import { popupMixinProps } from '../mixins/popup';
// Components
import Popup from '../popup';
const PRESET_ICONS = ['wechat', 'link', 'qrcode', 'poster'];
const [createComponent, bem, t] = createNamespace('share-sheet');
export default createComponent({
props: {
...popupMixinProps,
title: String,
cancelText: String,
description: String,
options: {
type: Array,
default: () => [],
},
safeAreaInsetBottom: {
type: Boolean,
default: true,
},
},
methods: {
onCancel() {
this.toggle(false);
},
onSelect(option, index) {
this.$emit('select', option, index);
},
toggle(val) {
this.$emit('input', val);
},
getIconURL(icon) {
if (PRESET_ICONS.indexOf(icon) !== -1) {
return `https://img.yzcdn.cn/vant/share-icon-${icon}.svg`;
}
return icon;
},
genOptions() {
return (
<div class={bem('options')}>
{this.options.map((option, index) => (
<div
class={bem('option')}
onClick={() => {
this.onSelect(option, index);
}}
>
<img src={this.getIconURL(option.icon)} class={bem('icon')} />
<span class={bem('name')}>{option.name || ''}</span>
</div>
))}
</div>
);
},
genCancelText() {
const cancelText = isDef(this.cancelText) ? this.cancelText : t('cancel');
if (cancelText) {
return (
<button type="button" class={bem('cancel')} onClick={this.onCancel}>
{cancelText}
</button>
);
}
},
},
render() {
return (
<Popup
round
class={bem()}
value={this.value}
position="bottom"
safeAreaInsetBottom={this.safeAreaInsetBottom}
onInput={this.toggle}
>
{this.genOptions()}
{this.genCancelText()}
</Popup>
);
},
});

View File

@ -0,0 +1,69 @@
@import '../style/var';
.van-share-sheet {
&__options {
display: flex;
padding: 16px 0 16px 24px;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
// fix right-padding issue for overflow-x element
// see: https://stackoverflow.com/questions/10054870
&::after {
display: block;
width: 24px;
content: '';
}
}
&__option {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 32px;
cursor: pointer;
user-select: none;
&:last-child {
padding-right: 16px;
}
&:active {
opacity: @active-opacity;
}
}
&__icon {
width: 48px;
height: 48px;
}
&__name {
margin-top: 8px;
color: #646566;
font-size: 12px;
}
&__cancel {
display: block;
width: 100%;
padding: 0;
font-size: 16px;
line-height: 48px;
text-align: center;
background-color: @white;
border: none;
cursor: pointer;
&::before {
display: block;
height: 8px;
background-color: @background-color;
content: ' ';
}
&:active {
background-color: @active-color;
}
}
}

View File

@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div>
<div role="button" tabindex="0" class="van-cell van-cell--clickable">
<div class="van-cell__title"><span>显示分享面板</span></div><i class="van-icon van-icon-arrow van-cell__right-icon">
<!----></i>
</div>
<!---->
</div>
</div>
`;

View File

@ -0,0 +1,4 @@
import Demo from '../demo';
import { snapshotDemo } from '../../../test/demo';
snapshotDemo(Demo);

View File

@ -177,7 +177,7 @@ module.exports = {
items: [
{
path: 'action-sheet',
title: 'ActionSheet 上拉菜单',
title: 'ActionSheet 动作面板',
},
{
path: 'dialog',
@ -203,6 +203,10 @@ module.exports = {
path: 'pull-refresh',
title: 'PullRefresh 下拉刷新',
},
{
path: 'share-sheet',
title: 'ShareSheet 分享面板',
},
{
path: 'swipe-cell',
title: 'SwipeCell 滑动单元格',
@ -550,6 +554,10 @@ module.exports = {
path: 'pull-refresh',
title: 'PullRefresh',
},
{
path: 'share-sheet',
title: 'ShareSheet',
},
{
path: 'swipe-cell',
title: 'SwipeCell',