[improvement] rename packages dir to src (#3659)
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { RED } from '../utils/color';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import Icon from '../icon';
|
||||
import Cell from '../cell';
|
||||
import Radio from '../radio';
|
||||
|
||||
// Types
|
||||
import { CreateElement, RenderContext } from 'vue/types';
|
||||
import { DefaultSlots } from '../utils/types';
|
||||
|
||||
export type AddressItemData = {
|
||||
id: string | number;
|
||||
tel: string | number;
|
||||
name: string;
|
||||
address: string;
|
||||
};
|
||||
|
||||
export type AddressItemProps = {
|
||||
data: AddressItemData;
|
||||
disabled?: boolean;
|
||||
switchable?: boolean;
|
||||
};
|
||||
|
||||
export type AddressItemEvents = {
|
||||
onEdit(): void;
|
||||
onSelect(): void;
|
||||
};
|
||||
|
||||
const [createComponent, bem] = createNamespace('address-item');
|
||||
|
||||
function AddressItem(
|
||||
h: CreateElement,
|
||||
props: AddressItemProps,
|
||||
slots: DefaultSlots,
|
||||
ctx: RenderContext<AddressItemProps>
|
||||
) {
|
||||
const { disabled, switchable } = props;
|
||||
|
||||
function onSelect() {
|
||||
if (switchable) {
|
||||
emit(ctx, 'select');
|
||||
}
|
||||
}
|
||||
|
||||
const renderRightIcon = () => (
|
||||
<Icon
|
||||
name="edit"
|
||||
class={bem('edit')}
|
||||
onClick={(event: Event) => {
|
||||
event.stopPropagation();
|
||||
emit(ctx, 'edit');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderContent = () => {
|
||||
const { data } = props;
|
||||
const Info = [
|
||||
<div class={bem('name')}>{`${data.name},${data.tel}`}</div>,
|
||||
<div class={bem('address')}>{data.address}</div>
|
||||
];
|
||||
|
||||
return switchable && !disabled ? (
|
||||
<Radio name={data.id} iconSize={16} checkedColor={RED}>
|
||||
{Info}
|
||||
</Radio>
|
||||
) : (
|
||||
Info
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Cell
|
||||
class={bem({ disabled })}
|
||||
valueClass={bem('value')}
|
||||
clickable={switchable && !disabled}
|
||||
scopedSlots={{
|
||||
default: renderContent,
|
||||
'right-icon': renderRightIcon
|
||||
}}
|
||||
onClick={onSelect}
|
||||
{...inherit(ctx)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
AddressItem.props = {
|
||||
data: Object,
|
||||
disabled: Boolean,
|
||||
switchable: Boolean
|
||||
};
|
||||
|
||||
export default createComponent<AddressItemProps, AddressItemEvents>(AddressItem);
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<van-address-list
|
||||
v-model="chosenAddressId"
|
||||
:list="$t('list')"
|
||||
:disabled-list="$t('disabledList')"
|
||||
:disabled-text="$t('disabledText')"
|
||||
@add="onAdd"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
i18n: {
|
||||
'zh-CN': {
|
||||
list: [
|
||||
{
|
||||
id: '1',
|
||||
name: '张三',
|
||||
tel: '13000000000',
|
||||
address: '浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '李四',
|
||||
tel: '1310000000',
|
||||
address: '浙江省杭州市拱墅区莫干山路 50 号'
|
||||
}
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: '王五',
|
||||
tel: '1320000000',
|
||||
address: '浙江省杭州市滨江区江南大道 15 号'
|
||||
}
|
||||
],
|
||||
add: '新增地址',
|
||||
edit: '编辑地址',
|
||||
disabledText: '以下地址超出配送范围'
|
||||
},
|
||||
'en-US': {
|
||||
list: [
|
||||
{
|
||||
id: '1',
|
||||
name: 'John Snow',
|
||||
tel: '13000000000',
|
||||
address: 'Somewhere'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Ned Stark',
|
||||
tel: '1310000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: 'Tywin',
|
||||
tel: '1320000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
],
|
||||
add: 'Add',
|
||||
edit: 'Edit',
|
||||
disabledText: 'The following address is out of range'
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
chosenAddressId: '1'
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onAdd() {
|
||||
this.$toast(this.$t('add'));
|
||||
},
|
||||
|
||||
onEdit(item, index) {
|
||||
this.$toast(`${this.$t('edit')}:${index}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,103 @@
|
||||
# AddressList
|
||||
|
||||
### Install
|
||||
``` javascript
|
||||
import { AddressList } from 'vant';
|
||||
|
||||
Vue.use(AddressList);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```html
|
||||
<van-address-list
|
||||
v-model="chosenAddressId"
|
||||
:list="list"
|
||||
:disabled-list="disabledList"
|
||||
disabled-text="The following address is out of range"
|
||||
@add="onAdd"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
chosenAddressId: '1',
|
||||
list: [
|
||||
{
|
||||
id: '1',
|
||||
name: 'John Snow',
|
||||
tel: '13000000000',
|
||||
address: 'Somewhere'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Ned Stark',
|
||||
tel: '1310000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: 'Tywin',
|
||||
tel: '1320000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onAdd() {
|
||||
Toast('Add');
|
||||
},
|
||||
onEdit(item, index) {
|
||||
Toast('Edit:' + index);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| v-model | Id of chosen address | String | - |
|
||||
| list | Address list | Array | `[]` |
|
||||
| disabled-list | Disabled address list | `Array` | `[]` |
|
||||
| disabled-text | Disabled text | `String` | - |
|
||||
| switchable | Whether to allow switch address | `Boolean` | `true` |
|
||||
| add-button-text | Add button text | String | `Add new address` |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| add | Triggered when click add button | - |
|
||||
| edit | Triggered when edit address | item: address object,index |
|
||||
| select | Triggered when select address | item: address object,index |
|
||||
| edit-disabled | Triggered when edit disabled address | item: address object,index |
|
||||
| select-disabled | Triggered when select disabled address | item: address object,index |
|
||||
|
||||
### Address Data Structure
|
||||
|
||||
| key | Description | Type |
|
||||
|------|------|------|
|
||||
| id | Id | `String | Number` |
|
||||
| name | Name | `String` |
|
||||
| tel | Phone | `String | Number` |
|
||||
| address | Address | `String` |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| default | Custom content after list |
|
||||
| top | Custom content before list |
|
||||
@@ -0,0 +1,57 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-address-list {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
||||
&__add {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: @address-list-add-button-z-index;
|
||||
}
|
||||
|
||||
&__disabled-text {
|
||||
padding: 0 15px;
|
||||
color: @address-list-disabled-text-color;
|
||||
font-size: @address-list-disabled-text-font-size;
|
||||
line-height: @address-list-disabled-text-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
.van-address-item {
|
||||
padding: @address-list-item-padding;
|
||||
|
||||
&__value {
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
&__name {
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
&__address {
|
||||
color: @address-list-item-text-color;
|
||||
font-size: @address-list-item-font-size;
|
||||
line-height: @address-list-item-line-height;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
.van-address-item__name,
|
||||
.van-address-item__address {
|
||||
color: @address-list-item-disabled-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__edit {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 15px;
|
||||
font-size: @address-list-edit-icon-size;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import Button from '../button';
|
||||
import RadioGroup from '../radio-group';
|
||||
import AddressItem, { AddressItemData } from './Item';
|
||||
|
||||
// Types
|
||||
import { CreateElement, RenderContext } from 'vue/types';
|
||||
import { ScopedSlot, DefaultSlots } from '../utils/types';
|
||||
|
||||
export type AddressListProps = {
|
||||
value?: string | number;
|
||||
switchable: boolean;
|
||||
disabledText?: string;
|
||||
addButtonText?: string;
|
||||
list: AddressItemData[];
|
||||
disabledList: AddressItemData[];
|
||||
};
|
||||
|
||||
export type AddressListSlots = DefaultSlots & {
|
||||
top?: ScopedSlot;
|
||||
};
|
||||
|
||||
const [createComponent, bem, t] = createNamespace('address-list');
|
||||
|
||||
function AddressList(
|
||||
h: CreateElement,
|
||||
props: AddressListProps,
|
||||
slots: AddressListSlots,
|
||||
ctx: RenderContext<AddressListProps>
|
||||
) {
|
||||
const getList = (list: AddressItemData[], disabled?: boolean) =>
|
||||
list.map((item, index) => (
|
||||
<AddressItem
|
||||
data={item}
|
||||
key={item.id}
|
||||
disabled={disabled}
|
||||
switchable={props.switchable}
|
||||
onSelect={() => {
|
||||
emit(ctx, disabled ? 'select-disabled' : 'select', item, index);
|
||||
}}
|
||||
onEdit={() => {
|
||||
emit(ctx, disabled ? 'edit-disabled' : 'edit', item, index);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
|
||||
const List = getList(props.list);
|
||||
const DisabledList = getList(props.disabledList, true);
|
||||
|
||||
return (
|
||||
<div class={bem()} {...inherit(ctx)}>
|
||||
{slots.top && slots.top()}
|
||||
<RadioGroup
|
||||
value={props.value}
|
||||
onInput={(event: Event) => {
|
||||
emit(ctx, 'input', event);
|
||||
}}
|
||||
>
|
||||
{List}
|
||||
</RadioGroup>
|
||||
{props.disabledText && (
|
||||
<div class={bem('disabled-text')}>{props.disabledText}</div>
|
||||
)}
|
||||
{DisabledList}
|
||||
{slots.default && slots.default()}
|
||||
<Button
|
||||
square
|
||||
size="large"
|
||||
type="danger"
|
||||
class={bem('add')}
|
||||
text={props.addButtonText || t('add')}
|
||||
onClick={() => {
|
||||
emit(ctx, 'add');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
AddressList.props = {
|
||||
list: Array,
|
||||
disabledList: Array,
|
||||
disabledText: String,
|
||||
addButtonText: String,
|
||||
value: [String, Number],
|
||||
switchable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
};
|
||||
|
||||
export default createComponent<AddressListProps>(AddressList);
|
||||
@@ -0,0 +1,38 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div class="van-address-list">
|
||||
<div role="radiogroup" class="van-radio-group">
|
||||
<div class="van-cell van-cell--clickable van-address-item">
|
||||
<div class="van-cell__value van-cell__value--alone van-address-item__value">
|
||||
<div role="radio" tabindex="0" aria-checked="true" class="van-radio">
|
||||
<div class="van-radio__icon van-radio__icon--round van-radio__icon--checked" style="font-size: 16px;"><i class="van-icon van-icon-success" style="border-color: #f44; background-color: rgb(255, 68, 68);">
|
||||
<!----></i></div><span class="van-radio__label"><div class="van-address-item__name">张三,13000000000</div><div class="van-address-item__address">浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室</div></span>
|
||||
</div>
|
||||
</div><i class="van-icon van-icon-edit van-address-item__edit">
|
||||
<!----></i>
|
||||
</div>
|
||||
<div class="van-cell van-cell--clickable van-address-item">
|
||||
<div class="van-cell__value van-cell__value--alone van-address-item__value">
|
||||
<div role="radio" tabindex="-1" aria-checked="false" class="van-radio">
|
||||
<div class="van-radio__icon van-radio__icon--round" style="font-size: 16px;"><i class="van-icon van-icon-success">
|
||||
<!----></i></div><span class="van-radio__label"><div class="van-address-item__name">李四,1310000000</div><div class="van-address-item__address">浙江省杭州市拱墅区莫干山路 50 号</div></span>
|
||||
</div>
|
||||
</div><i class="van-icon van-icon-edit van-address-item__edit">
|
||||
<!----></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-address-list__disabled-text">以下地址超出配送范围</div>
|
||||
<div class="van-cell van-address-item van-address-item--disabled">
|
||||
<div class="van-cell__value van-cell__value--alone van-address-item__value">
|
||||
<div class="van-address-item__name">王五,1320000000</div>
|
||||
<div class="van-address-item__address">浙江省杭州市滨江区江南大道 15 号</div>
|
||||
</div><i class="van-icon van-icon-edit van-address-item__edit">
|
||||
<!----></i>
|
||||
</div><button class="van-button van-button--danger van-button--large van-button--square van-address-list__add"><span class="van-button__text">新增地址</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`unswitchable 1`] = `
|
||||
<div class="van-address-list">
|
||||
<div role="radiogroup" class="van-radio-group">
|
||||
<div class="van-cell van-address-item">
|
||||
<div class="van-cell__value van-cell__value--alone van-address-item__value">
|
||||
<div class="van-address-item__name">张三,13000000000</div>
|
||||
<div class="van-address-item__address">浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室</div>
|
||||
</div><i class="van-icon van-icon-edit van-address-item__edit">
|
||||
<!----></i>
|
||||
</div>
|
||||
<div class="van-cell van-address-item">
|
||||
<div class="van-cell__value van-cell__value--alone van-address-item__value">
|
||||
<div class="van-address-item__name">李四,1310000000</div>
|
||||
<div class="van-address-item__address">浙江省杭州市拱墅区莫干山路 50 号</div>
|
||||
</div><i class="van-icon van-icon-edit van-address-item__edit">
|
||||
<!----></i>
|
||||
</div>
|
||||
</div><button class="van-button van-button--danger van-button--large van-button--square van-address-list__add"><span class="van-button__text">新增地址</span></button>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,4 @@
|
||||
import Demo from '../demo';
|
||||
import demoTest from '../../../test/demo-test';
|
||||
|
||||
demoTest(Demo);
|
||||
@@ -0,0 +1,46 @@
|
||||
import { mount } from '../../../test/utils';
|
||||
import AddressList from '..';
|
||||
|
||||
const list = [
|
||||
{
|
||||
id: '1',
|
||||
name: '张三',
|
||||
tel: '13000000000',
|
||||
address: '浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '李四',
|
||||
tel: '1310000000',
|
||||
address: '浙江省杭州市拱墅区莫干山路 50 号'
|
||||
}
|
||||
];
|
||||
|
||||
test('unswitchable', () => {
|
||||
const wrapper = mount(AddressList, {
|
||||
propsData: {
|
||||
list,
|
||||
switchable: false
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('select event', () => {
|
||||
const onSelect = jest.fn();
|
||||
const wrapper = mount(AddressList, {
|
||||
propsData: {
|
||||
list
|
||||
},
|
||||
context: {
|
||||
on: {
|
||||
select: onSelect
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapper.find('.van-radio__icon').trigger('click');
|
||||
|
||||
expect(onSelect).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
# AddressList 地址列表
|
||||
|
||||
### 引入
|
||||
``` javascript
|
||||
import { AddressList } from 'vant';
|
||||
|
||||
Vue.use(AddressList);
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础用法
|
||||
|
||||
```html
|
||||
<van-address-list
|
||||
v-model="chosenAddressId"
|
||||
:list="list"
|
||||
:disabled-list="disabledList"
|
||||
disabled-text="以下地址超出配送范围"
|
||||
@add="onAdd"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
chosenAddressId: '1',
|
||||
list: [
|
||||
{
|
||||
id: '1',
|
||||
name: '张三',
|
||||
tel: '13000000000',
|
||||
address: '浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '李四',
|
||||
tel: '1310000000',
|
||||
address: '浙江省杭州市拱墅区莫干山路 50 号'
|
||||
}
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: '王五',
|
||||
tel: '1320000000',
|
||||
address: '浙江省杭州市滨江区江南大道 15 号'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onAdd() {
|
||||
Toast('新增地址');
|
||||
},
|
||||
|
||||
onEdit(item, index) {
|
||||
Toast('编辑地址:' + index);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|------|------|------|------|------|
|
||||
| v-model | 当前选中地址的 id | `String` | - | - |
|
||||
| list | 地址列表 | `Array` | `[]` | - |
|
||||
| add-button-text | 底部按钮文字 | `String` | `新增地址` | - |
|
||||
| disabled-list | 不可配送地址列表 | `Array` | `[]` | 1.3.0 |
|
||||
| disabled-text | 不可配送提示文案 | `String` | - | 1.3.0 |
|
||||
| switchable | 是否允许切换地址 | `Boolean` | `true` | 1.3.8 |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 | 版本 |
|
||||
|------|------|------|------|
|
||||
| add | 点击新增按钮时触发 | - | - |
|
||||
| edit | 点击编辑按钮时触发 | item: 地址对象,index: 索引 | - |
|
||||
| select | 切换选中的地址时触发 | item: 地址对象,index: 索引 | - |
|
||||
| edit-disabled | 编辑不可配送的地址时触发 | item: 地址对象,index: 索引 | 1.3.0 |
|
||||
| select-disabled | 选中不可配送的地址时触发 | item: 地址对象,index: 索引 | 1.3.0 |
|
||||
|
||||
### 地址列表字段说明
|
||||
|
||||
| key | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| id | 每条地址的唯一标识 | `String | Number` |
|
||||
| name | 收货人姓名 | `String` |
|
||||
| tel | 收货人手机号 | `String | Number` |
|
||||
| address | 收货地址 | `String` |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| default | 在列表下方插入内容 |
|
||||
| top | 在顶部插入内容 |
|
||||
Reference in New Issue
Block a user