97275c2a by simon

默认提交

1 parent 163c37bf
Showing 268 changed files with 3812 additions and 1459 deletions
@import "support";
// // Margin
// .u-mt-smaller {
// margin-top: $marginTopSmaller;
// }
// .u-mt-small {
// margin-top: $marginTopSmall;
// }
// .u-mt-medium {
// margin-top: $marginTopMedium;
// }
// .u-mt-large {
// margin-top: $marginTopLarge;
// }
// .u-mt-larger {
// margin-top: $marginTopLarger;
// }
// .u-mb-smaller {
// margin-bottom: $marginTopSmaller;
// }
// .u-mb-small {
// margin-bottom: $marginTopSmall;
// }
// .u-mb-medium {
// margin-bottom: $marginTopMedium;
// }
// .u-mb-large {
// margin-bottom: $marginTopLarge;
// }
// .u-mb-larger {
// margin-bottom: $marginTopLarger;
// }
// // Padding
// .u-pt-smaller {
// padding-top: $paddingTopSmaller;
// }
// .u-pt-small {
// padding-top: $paddingTopSmall;
// }
// .u-pt-medium {
// padding-top: $paddingTopMedium;
// }
// .u-pt-large {
// padding-top: $paddingTopLarge;
// }
// .u-pt-larger {
// padding-top: $paddingTopLarger;
// }
// .u-pb-smaller {
// padding-bottom: $paddingTopSmaller;
// }
// .u-pb-small {
// padding-bottom: $paddingTopSmall;
// }
// .u-pb-medium {
// padding-bottom: $paddingTopMedium;
// }
// .u-pb-large {
// padding-bottom: $paddingTopLarge;
// }
// .u-pb-larger {
// padding-bottom: $paddingTopLarger;
// }
// // 布局方位
// .u-ta-c {
// text-align: center !important;
// }
// .u-ta-l {
// text-align: left !important;
// }
// .u-ta-r {
// text-align: right !important;
// }
// .u-fl-l {
// float: left;
// }
// .u-fl-n {
// float: none;
// }
// .u-fl-r {
// float: right;
// }
// .u-d-b {
// display: block;
// }
// .u-d-i {
// display: inline !important;
// }
// .u-d-ib {
// display: inline-block !important;
// }
// .u-d-n {
// display: none !important;
// }
// .u-d-t {
// display: table;
// table-layout: fixed;
// }
// .u-d-tc {
// display: table-cell;
// }
// .u-va-b {
// vertical-align: bottom;
// }
// .u-va-m {
// vertical-align: middle;
// }
// .u-va-t {
// vertical-align: top;
// }
// // clearfix
// .u-clearfix {
// @include clearfix;
// }
// // 虚拟格式
// .u-cur-d {
// cursor: default;
// }
// .u-cur-p {
// cursor: pointer;
// }
// // flex
// .u-flex {
// display: -webkit-box;
// display: -webkit-flex;
// display: flex;
// }
// .u-flex-item {
// -webkit-box-flex: 1;
// -webkit-flex: 1;
// flex: 1;
// }
// // 小程序中模拟ul、li
// .u-ul {
// padding-left: 30px;
// text-align: left;
// display: block;
// }
// .u-li {
// position: relative;
// font-size: $fontSizeSmall;
// line-height: $fontSizeSmall + 4px;
// margin-bottom: $marginTopSmall;
// &:before {
// position: absolute;
// content: " ";
// top: 14px;
// left: -20px;
// width: 8px;
// height: 8px;
// border-radius: 8px;
// background-color: $colorBlack;
// }
// }
.bis {
background-repeat: no-repeat;
......@@ -213,6 +17,10 @@
justify-content: space-between;
}
.fla{
display: flex;
align-items: center;
}
.fje {
......
......@@ -57,10 +57,24 @@ Component({
},
onStepperChange(e) {
let val = e.detail;
if(val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum;
if(val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum;
// if(val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum;
// if(val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum;
this.setNum(val);
},
onStepperBlur(e) {
let val = e.detail.value;
this.fixStepperVal(val);
},
onStepperMod(e) {
let val = this.data.num;
this.fixStepperVal(val);
},
fixStepperVal(val) {
if (val > this.properties.productInfo.maxNum) val = this.properties.productInfo.maxNum;
if (val < this.properties.productInfo.minNum) val = this.properties.productInfo.minNum;
this.setNum(val);
},
bindRemarkInput(e) {
this.setData({
remark: e.detail.value
......
......@@ -44,8 +44,8 @@
.prize {
.image {
width: 180px;
height: 180px;
width: 200px;
height: 200px;
}
}
......@@ -71,9 +71,9 @@
}
.t2 {
// margin-top: 16px;
display: flex;
align-items: center;
margin-top: 4px;
// display: flex;
// align-items: center;
.t2-1 {
font-size: 30px;
......@@ -82,12 +82,17 @@
.t2-2 {
font-size: 20px;
color: #888888;
// margin-left: 20px;
}
.ml-20{
margin-left: 20px;
}
}
.t3 {
font-size: 36px;
}
}
}
......
......@@ -12,10 +12,11 @@
<view class="con">
<view class="tt t1">{{productInfo.seckillName}}</view>
<block wx:if="{{productInfo.minNum == productInfo.maxNum}}">
<!-- <block wx:if="{{1>0}}"> -->
<!-- 固定个数 -->
<view class="tt t2" wx:if="{{orderStatus != 1}}">
<view class="tt t2 fla" wx:if="{{orderStatus != 1}}">
<view class="t2-1">{{productInfo.minNum}}个</view>
<view class="t2-2">数量不可修改</view>
<view class="t2-2 ml-20">数量不可修改</view>
</view>
<view class="num" wx:else>{{num}}个</view>
</block>
......@@ -23,7 +24,8 @@
<!-- 不定个数 -->
<view class="tt t2" wx:if="{{orderStatus != 1}}">
<view class="t2-1">
<van-stepper bind:change="onStepperChange" value="{{ num }}" min="{{productInfo.minNum}}" max="{{productInfo.maxNum}}" integer />
<!-- <van-stepper bind:change="onStepperChange" value="{{ num }}" min="{{productInfo.minNum}}" max="{{productInfo.maxNum}}" integer /> -->
<van-stepper button-size="32px" input-width="64px" bind:change="onStepperChange" min="{{0}}" value="{{ num }}" integer bind:blur="onStepperBlur" bind:plus="onStepperMod" bind:minus="onStepperMod" />
</view>
<view class="t2-2">可选填{{productInfo.minNum}}-{{productInfo.maxNum}}个</view>
</view>
......@@ -40,7 +42,7 @@
</view>
<!-- 表单 -->
<view class="table" wx:else>
<view class="tips">*本活动仅记录订单,无需付款,后期由线下工作人员另行安排支付与配送,请确保收货信息准确。</view>
<view class="tips">*本活动仅记录订单,无需付款,后期由线下工作人员另行安排支付与配送,请确保信息准确。</view>
<view class="form">
<view class="form-item">
<view class="label">收件人:</view>
......
......@@ -2,7 +2,7 @@ let ENV_CONFIG = require('./env/index');
const APPID = ''
/** ====每次发布版本记得修改此环境配置==== */
const ENV = 'Prod'; // Dev Prod
const ENV = 'Dev'; // Dev Prod
const NET_CONFIG = ENV_CONFIG[ENV];
const MOCKAPI = ENV_CONFIG.mockApi;
......
......@@ -243,7 +243,7 @@ Page({
price: price * 100 //转成分
}
}).then((result) => {
console.log("result:", result);
// console.log("result:", result);
this.queryAuctionRecordLast().then((res2) => {
this.setData({
auctionBidSuccessVisible: true
......@@ -337,7 +337,7 @@ Page({
let parseData = JSON.parse(socketData);
result = parseData && parseData.content || null;
}
console.log("result:", result);
// console.log("result:", result);
if (!result) return;
let priceInfo = result.list || [];
......
......@@ -7,6 +7,7 @@ let app = getApp();
Page({
data: {
authorizeVisible: false,
signTipsCompVisible:false,
isInit: false,
total: 0,
page: 1,
......@@ -70,6 +71,10 @@ Page({
title: curData.auctionName
}
})
} else if(curData.isCanDetail == 2){
this.setData({
signTipsCompVisible: true,
})
} else {
wx.showModal({
content: curData.reason || "您未达到进入条件",
......@@ -111,10 +116,21 @@ Page({
})
},
/**
* 去验证
*/
toVipLoginHandler() {
app.router.push({
openType: "redirect",
path: "vipLogin"
})
},
// 隐藏蒙层
hideMask() {
this.setData({
authorizeVisible: false,
signTipsCompVisible: false,
})
},
// 子组件事件
......@@ -125,6 +141,19 @@ Page({
} = evt.detail;
switch (name) {
// 去验证
case "_evt_to_verify":
this.hideMask();
this.toVipLoginHandler();
break;
// 暂不验证
case "_evt_not_verify":
this.hideMask();
break;
// 隐藏弹窗
case "_evt_hide_mask":
this.hideMask();
......
......@@ -36,3 +36,7 @@
<van-popup show="{{ authorizeVisible }}">
<authorize-comp bind:evtcomp="evtcomp"></authorize-comp>
</van-popup>
<van-popup show="{{ signTipsCompVisible }}">
<sign-tips-comp bind:evtcomp="evtcomp"></sign-tips-comp>
</van-popup>
......
......@@ -147,7 +147,7 @@ Page({
this.setData({
productInfo: result
})
console.log("result:", result);
// console.log("result:", result);
resolve();
}).catch((err) => {
if (err.code == 1002) {
......@@ -178,7 +178,7 @@ Page({
url: app.api.seckillSubmit,
data: data
}).then((result) => {
console.log("result:", result);
// console.log("result:", result);
this.setData({
orderStatus: 1,
})
......
......@@ -7,6 +7,7 @@ let app = getApp();
Page({
data: {
authorizeVisible: false,
signTipsCompVisible:false,
isInit: false,
total: 0,
page: 1,
......@@ -63,6 +64,7 @@ Page({
onDetailHandler(evt) {
let curData = getBindtapData(evt);
console.log("curData:", curData);
// curData.isCanDetail = 2;
if (curData.status == 0 || curData.status == 1) {
if (curData.isCanDetail == 1) {
app.router.push({
......@@ -71,6 +73,10 @@ Page({
code: curData.seckillCode,
}
})
} else if(curData.isCanDetail == 2){
this.setData({
signTipsCompVisible: true,
})
} else {
wx.showModal({
content: curData.reason || "您未达到进入条件",
......@@ -106,10 +112,21 @@ Page({
})
},
/**
* 去验证
*/
toVipLoginHandler() {
app.router.push({
openType: "redirect",
path: "vipLogin"
})
},
// 隐藏蒙层
hideMask() {
this.setData({
authorizeVisible: false,
signTipsCompVisible: false,
})
},
// 子组件事件
......@@ -120,6 +137,18 @@ Page({
} = evt.detail;
switch (name) {
// 去验证
case "_evt_to_verify":
this.hideMask();
this.toVipLoginHandler();
break;
// 暂不验证
case "_evt_not_verify":
this.hideMask();
break;
// 隐藏弹窗
case "_evt_hide_mask":
this.hideMask();
......
......@@ -36,3 +36,7 @@
<van-popup show="{{ authorizeVisible }}">
<authorize-comp bind:evtcomp="evtcomp"></authorize-comp>
</van-popup>
<van-popup show="{{ signTipsCompVisible }}">
<sign-tips-comp bind:evtcomp="evtcomp"></sign-tips-comp>
</van-popup>
......
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 100
......@@ -21,6 +24,14 @@ VantComponent({
closeOnClickOverlay: {
type: Boolean,
value: true
},
closeOnClickAction: {
type: Boolean,
value: true
},
safeAreaInsetBottom: {
type: Boolean,
value: true
}
},
methods: {
......@@ -29,6 +40,9 @@ VantComponent({
const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.$emit('select', item);
if (this.data.closeOnClickAction) {
this.onClose();
}
}
},
onCancel() {
......@@ -36,6 +50,10 @@ VantComponent({
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
}
}
});
......
......@@ -3,12 +3,13 @@
<van-popup
show="{{ show }}"
position="bottom"
round="{{ round }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClose"
bind:close="onClickOverlay"
>
<view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
{{ title }}
......@@ -18,12 +19,16 @@
bind:click="onClose"
/>
</view>
<view wx:if="{{ description }}" class="van-action-sheet__description">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
open-type="{{ item.openType }}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
......@@ -33,7 +38,7 @@
{{ item.name }}
<text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
</block>
<van-loading wx:else size="20px" />
<van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
</button>
</view>
<slot />
......
@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;color:#333}.van-action-sheet__cancel,.van-action-sheet__item{height:50px;font-size:16px;line-height:50px;text-align:center;background-color:#fff}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel{height:60px}.van-action-sheet__cancel:before{display:block;height:10px;background-color:#f8f8f8;content:" "}.van-action-sheet__item--disabled{color:#c9c9c9}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff}.van-action-sheet__subname{margin-left:5px;font-size:12px;color:#7d7e80}.van-action-sheet__header{font-size:16px;font-weight:500;line-height:44px;text-align:center}.van-action-sheet__close{position:absolute!important;top:0;right:0;padding:0 15px;font-size:18px!important;line-height:inherit!important;color:#999}
\ No newline at end of file
@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:50px;line-height:var(--action-sheet-item-height,50px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:before{display:block;content:" ";height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f8f8f8;background-color:var(--action-sheet-cancel-padding-color,#f8f8f8)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-left:4px;margin-left:var(--padding-base,4px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#7d7e80;color:var(--action-sheet-subname-color,#7d7e80)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:44px;line-height:var(--action-sheet-header-height,44px)}.van-action-sheet__description{text-align:center;padding:16px;padding:var(--padding-md,16px);color:#7d7e80;color:var(--action-sheet-description-color,#7d7e80);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 12px;padding:var(--action-sheet-close-icon-padding,0 12px);font-size:18px!important;font-size:var(--action-sheet-close-icon-size,18px)!important;color:#969799;color:var(--action-sheet-close-icon-color,#969799)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important;height:50px;height:var(--action-sheet-item-height,50px)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
const COLUMNSPLACEHOLDERCODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
title: String,
value: String,
loading: Boolean,
cancelButtonText: String,
confirmButtonText: String,
itemHeight: {
type: Number,
value: 44
},
visibleItemCount: {
type: Number,
value: 5
},
columnsNum: {
type: [String, Number],
value: 3
},
areaList: {
props: Object.assign(Object.assign({}, pickerProps), { value: String, areaList: {
type: Object,
value: {}
}, columnsNum: {
type: null,
value: 3
}, columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
}
},
});
}
} }),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
displayColumns: [{ values: [] }, { values: [] }, { values: [] }]
displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {}
},
watch: {
value(value) {
......@@ -35,11 +33,16 @@ VantComponent({
},
areaList: 'setValues',
columnsNum(value) {
this.set({
this.setData({
displayColumns: this.data.columns.slice(0, +value)
});
}
},
mounted() {
setTimeout(() => {
this.setValues();
}, 0);
},
methods: {
getPicker() {
if (this.picker == null) {
......@@ -51,20 +54,38 @@ VantComponent({
this.emit('cancel', event.detail);
},
onConfirm(event) {
this.emit('confirm', event.detail);
const { index } = event.detail;
let { value } = event.detail;
value = this.parseOutputValues(value);
this.emit('confirm', { value, index });
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
// parse output columns data
parseOutputValues(values) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
// save undefined value
if (!value)
return value;
value = JSON.parse(JSON.stringify(value));
if (!value.code || value.name === columnsPlaceholder[index]) {
value.code = '';
value.name = '';
}
return value;
});
},
onChange(event) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
this.setValues().then(() => {
this.$emit('change', {
picker,
values: picker.getValues(),
values: this.parseOutputValues(picker.getValues()),
index
});
});
......@@ -74,6 +95,7 @@ VantComponent({
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
const { typeToColumnsPlaceholder } = this.data;
let result = [];
if (type !== 'province' && !code) {
return result;
......@@ -90,6 +112,14 @@ VantComponent({
}
result = result.filter(item => item.code.indexOf(code) === 0);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill = type === 'province' ? '' : type === 'city' ? COLUMNSPLACEHOLDERCODE.slice(2, 4) : COLUMNSPLACEHOLDERCODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type]
});
}
return result;
},
getIndex(type, code) {
......@@ -109,7 +139,18 @@ VantComponent({
},
setValues() {
const county = this.getConfig('county');
let code = this.code || Object.keys(county)[0] || '';
let { code } = this;
if (!code) {
if (this.data.columnsPlaceholder.length) {
code = COLUMNSPLACEHOLDERCODE;
}
else if (Object.keys(county)[0]) {
code = Object.keys(county)[0];
}
else {
code = '';
}
}
const province = this.getList('province');
const city = this.getList('city', code.slice(0, 2));
const picker = this.getPicker();
......@@ -120,7 +161,6 @@ VantComponent({
stack.push(picker.setColumnValues(0, province, false));
stack.push(picker.setColumnValues(1, city, false));
if (city.length && code.slice(2, 4) === '00') {
;
[{ code }] = city;
}
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
......@@ -162,8 +202,8 @@ VantComponent({
}
return area;
},
reset() {
this.code = '';
reset(code) {
this.code = code || '';
return this.setValues();
}
}
......
@import '../common/index.wxss';.van-badge-group{width:85px}
\ No newline at end of file
@import '../common/index.wxss';.van-badge{display:block;padding:20px 12px 20px 9px;overflow:hidden;font-size:14px;line-height:1.4;color:#7d7e80;word-break:break-all;background-color:#f8f8f8;border-left:3px solid transparent;box-sizing:border-box;-webkit-user-select:none;user-select:none}.van-badge--hover{background-color:#f2f3f5}.van-badge:after{border-bottom-width:1px}.van-badge--active{font-weight:700;color:#333;border-color:#f44}.van-badge--active:after{border-right-width:1px}.van-badge--active,.van-badge--active.van-badge--hover{background-color:#fff}.van-badge__text{position:relative}
\ No newline at end of file
......@@ -4,7 +4,11 @@ import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
classes: ['hover-class', 'loading-class'],
data: {
style: ''
},
props: {
icon: String,
plain: Boolean,
block: Boolean,
round: Boolean,
......@@ -13,6 +17,11 @@ VantComponent({
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular'
},
type: {
type: String,
value: 'default'
......@@ -24,6 +33,29 @@ VantComponent({
loadingSize: {
type: String,
value: '20px'
},
color: {
type: String,
observer(color) {
let style = '';
if (color) {
style += `color: ${this.data.plain ? color : 'white'};`;
if (!this.data.plain) {
// Use background instead of backgroundColor to make linear-gradient work
style += `background: ${color};`;
}
// hide border when color is linear-gradient
if (color.indexOf('gradient') !== -1) {
style += 'border: 0;';
}
else {
style += `border-color: ${color};`;
}
}
if (style !== this.data.style) {
this.setData({ style });
}
}
}
},
methods: {
......
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
......
......@@ -3,9 +3,10 @@
<button
id="{{ id }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
open-type="{{ openType }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
style="{{ style }} {{ customStyle }}"
open-type="{{ openType }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
......@@ -26,7 +27,8 @@
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
color="{{ type === 'default' ? '#c9c9c9' : '' }}"
type="{{ loadingType }}"
color="{{ type === 'default' ? '#c9c9c9' : 'white' }}"
/>
<view
wx:if="{{ loadingText }}"
......@@ -35,5 +37,16 @@
{{ loadingText }}
</view>
</block>
<slot wx:else />
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
<view class="van-button__text">
<slot />
</view>
</block>
</button>
......
@import '../common/index.wxss';.van-button{position:relative;display:inline-block;height:44px;padding:0;font-size:16px;line-height:42px;text-align:center;vertical-align:middle;box-sizing:border-box;border-radius:2px;-webkit-appearance:none;-webkit-text-size-adjust:100%}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#333;background-color:#fff;border:1px solid #eee}.van-button--primary{color:#fff;background-color:#07c160;border:1px solid #07c160}.van-button--info{color:#fff;background-color:#1989fa;border:1px solid #1989fa}.van-button--danger{color:#fff;background-color:#f44;border:1px solid #f44}.van-button--warning{color:#fff;background-color:#ff976a;border:1px solid #ff976a}.van-button--plain{background-color:#fff}.van-button--plain.van-button--primary{color:#07c160}.van-button--plain.van-button--info{color:#1989fa}.van-button--plain.van-button--danger{color:#f44}.van-button--plain.van-button--warning{color:#ff976a}.van-button--large{width:100%;height:50px;line-height:48px}.van-button--normal{padding:0 15px;font-size:14px}.van-button--small{height:30px;min-width:60px;padding:0 8px;font-size:12px;line-height:28px}.van-button--mini{display:inline-block;width:50px;height:22px;font-size:10px;line-height:20px}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:block;width:100%}.van-button--round{border-radius:10em}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5}.van-button__loading-text{margin-left:5px;display:inline-block;vertical-align:middle}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-width:1px;border-color:inherit;border-radius:4px}.van-button--hairline.van-button--round:after{border-radius:10em}.van-button--hairline.van-button--square:after{border-radius:0}
\ No newline at end of file
@import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;line-height:20px;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background-color:#fff;background-color:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:1px solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background-color:#07c160;background-color:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:1px solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background-color:#1989fa;background-color:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:1px solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background-color:#ee0a24;background-color:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:1px solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background-color:#ff976a;background-color:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:1px solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background-color:#fff;background-color:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
\ No newline at end of file
......
......@@ -34,6 +34,7 @@
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view>
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot name="bottom" />
</view>
</view>
</view>
......
@import '../common/index.wxss';.van-card{position:relative;padding:5px 15px;font-size:12px;color:#333;background-color:#fafafa;box-sizing:border-box}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;width:90px;height:90px;margin-right:10px;-webkit-flex:none;flex:none}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;min-width:0;-webkit-flex:1;flex:1}.van-card__desc,.van-card__title{word-break:break-all}.van-card__title{font-weight:700;line-height:16px}.van-card__desc{color:#7d7e80}.van-card__bottom,.van-card__desc{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#f44}.van-card__origin-price{display:inline-block;margin-left:5px;font-size:10px;color:#7d7e80;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{width:100%;text-align:right;-webkit-flex:none;flex:none}
\ No newline at end of file
@import '../common/index.wxss';.van-card{position:relative;box-sizing:border-box;padding:8px 16px;padding:var(--card-padding,8px 16px);font-size:12px;font-size:var(--card-font-size,12px);color:#323233;color:var(--card-text-color,#323233);background-color:#fafafa;background-color:var(--card-background-color,#fafafa)}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;-webkit-flex:none;flex:none;width:90px;width:var(--card-thumb-size,90px);height:90px;height:var(--card-thumb-size,90px);margin-right:8px;margin-right:var(--padding-xs,8px)}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;-webkit-flex:1;flex:1;min-width:0}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:16px;line-height:var(--card-title-line-height,16px)}.van-card__desc{line-height:20px;line-height:var(--card-desc-line-height,20px);color:#7d7e80;color:var(--card-desc-color,#7d7e80)}.van-card__bottom{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#ee0a24;color:var(--card-price-color,#ee0a24)}.van-card__origin-price{display:inline-block;margin-left:5px;text-decoration:line-through;font-size:10px;font-size:var(--card-origin-price-font-size,10px);color:#7d7e80;color:var(--card-origin-price-color,#7d7e80)}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{-webkit-flex:none;flex:none;width:100%;text-align:right}
\ No newline at end of file
......
@import '../common/index.wxss';.van-cell-group__title{font-size:14px;padding:15px 15px 5px;color:#999;line-height:16px}
\ No newline at end of file
@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
\ No newline at end of file
......
......@@ -22,6 +22,7 @@ VantComponent({
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true
......
......@@ -19,11 +19,13 @@
style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">
{{ title }}
<view wx:if="{{ label }}" class="van-cell__label label-class">{{ label }}</view>
</block>
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
<view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
<slot wx:if="{{ useLabelSlot }}" name="label" />
<block wx:elif="{{ label }}">{{ label }}</block>
</view>
</view>
<view class="van-cell__value value-class">
......
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;width:100%;padding:10px 15px;font-size:14px;line-height:24px;color:#333;background-color:#fff;box-sizing:border-box}.van-cell:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:auto;left:15px;right:0;bottom:0;-webkit-transform:scaleY(.5);transform:scaleY(.5);border-bottom:1px solid #eee}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff}.van-cell__label{margin-top:3px;font-size:12px;line-height:18px;color:#999}.van-cell__value{overflow:hidden;color:#999;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;height:24px;font-size:16px;-webkit-align-items:center;align-items:center}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#999}.van-cell__left-icon{line-height:24px;vertical-align:middle}.van-cell__right-icon{line-height:24px}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;left:7px;font-size:14px;color:#f44;content:"*"}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-bottom:12px}.van-cell--large .van-cell__title{font-size:16px}.van-cell--large .van-cell__label{font-size:14px}
\ No newline at end of file
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:auto;right:0;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}
\ No newline at end of file
......
......@@ -5,29 +5,34 @@ VantComponent({
name: 'checkbox',
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.set({
value: value.indexOf(target.data.name) !== -1,
disabled: disabled || target.data.disabled
});
this.children = this.children || [];
this.children.push(target);
this.updateChild(target);
},
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
},
props: {
max: Number,
value: Array,
disabled: Boolean
value: {
type: Array,
observer: 'updateChildren'
},
watch: {
value(value) {
const children = this.getRelationNodes('../checkbox/index');
children.forEach(child => {
child.set({ value: value.indexOf(child.data.name) !== -1 });
});
disabled: {
type: Boolean,
observer: 'updateChildren'
}
},
methods: {
updateChildren() {
(this.children || []).forEach((child) => this.updateChild(child));
},
disabled(disabled) {
const children = this.getRelationNodes('../checkbox/index');
children.forEach(child => {
child.set({ disabled: disabled || child.data.disabled });
updateChild(child) {
const { value, disabled } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
disabled: disabled || child.data.disabled
});
}
}
......
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
"component": true
}
......
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
function emit(target, value) {
target.$emit('input', value);
target.$emit('change', value);
}
VantComponent({
field: true,
relation: {
name: 'checkbox-group',
type: 'ancestor'
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
},
classes: ['icon-class', 'label-class'],
props: {
value: null,
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
......@@ -16,52 +27,61 @@ VantComponent({
shape: {
type: String,
value: 'round'
},
iconSize: {
type: null,
observer: 'setSizeWithUnit'
}
},
data: {
sizeWithUnit: '20px'
},
methods: {
emitChange(value) {
const parent = this.getRelationNodes('../checkbox-group/index')[0];
if (parent) {
this.setParentValue(parent, value);
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
this.$emit('input', value);
this.$emit('change', value);
emit(this, value);
}
},
toggle() {
if (!this.data.disabled) {
this.emitChange(!this.data.value);
const { disabled, value } = this.data;
if (!disabled) {
this.emitChange(!value);
}
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(!this.data.value);
const { labelDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled) {
this.emitChange(!value);
}
},
setParentValue(parent, value) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
const { max } = parent.data;
if (value) {
if (parent.data.max && parentValue.length >= parent.data.max) {
if (max && parentValue.length >= max) {
return;
}
/* istanbul ignore else */
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
parent.$emit('input', parentValue);
parent.$emit('change', parentValue);
emit(parent, parentValue);
}
}
else {
const index = parentValue.indexOf(name);
/* istanbul ignore else */
if (index !== -1) {
parentValue.splice(index, 1);
parent.$emit('input', parentValue);
parent.$emit('change', parentValue);
}
emit(parent, parentValue);
}
}
},
setSizeWithUnit(size) {
this.set({
sizeWithUnit: addUnit(size)
});
},
}
});
......
......@@ -6,10 +6,11 @@
<van-icon
wx:else
name="success"
size="0.8em"
class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
style="font-size: {{ sizeWithUnit }};{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
custom-class="icon-class"
custom-style="line-height: 20px;"
custom-style="line-height: 1.25em;"
/>
</view>
<view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel">
......
@import '../common/index.wxss';.van-checkbox{overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{display:inline-block;line-height:20px;vertical-align:middle}.van-checkbox__icon{display:block;font-size:14px;width:20px;height:20px;color:transparent;text-align:center;box-sizing:border-box;border:1px solid #e5e5e5;transition:.2s}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;border-color:#1989fa;background-color:#1989fa}.van-checkbox__icon--disabled{border-color:#c9c9c9;background-color:#eee}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c9c9c9}.van-checkbox__label{color:#333;margin-left:10px}.van-checkbox__label--left{float:left;margin:0 10px 0 0}.van-checkbox__label--disabled{color:#c9c9c9}.van-checkbox__label:empty{margin:0}
\ No newline at end of file
@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #e5e5e5;border:1px solid var(--checkbox-border-color,#e5e5e5);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { isObj } from '../common/utils';
import { BLUE, WHITE } from '../common/color';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round'
},
value: {
type: Number,
value: 0,
observer: 'reRender'
},
speed: {
type: Number,
value: 50
},
size: {
type: Number,
value: 100,
observer: 'setStyle'
},
fill: String,
layerColor: {
type: String,
value: WHITE
},
color: {
type: [String, Object],
value: BLUE,
observer: 'setHoverColor'
},
strokeWidth: {
type: Number,
value: 4
},
clockwise: {
type: Boolean,
value: true
}
},
data: {
style: 'width: 100px; height: 100px;',
hoverColor: BLUE
},
methods: {
getContext() {
if (!this.ctx) {
this.ctx = wx.createCanvasContext('van-circle', this);
}
return this.ctx;
},
setHoverColor() {
const context = this.getContext();
const { color, size } = this.data;
let hoverColor = color;
if (isObj(color)) {
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map(key => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
hoverColor = LinearColor;
}
this.setData({ hoverColor });
},
setStyle() {
const { size } = this.data;
const style = `width: ${size}px; height: ${size}px;`;
this.setData({ style });
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise, hoverColor } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const context = this.getContext();
const { size } = this.data;
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearInterval();
this.currentValue = this.currentValue || 0;
this.interval = setInterval(() => {
if (this.currentValue !== value) {
if (this.currentValue < value) {
this.currentValue += STEP;
}
else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
}
else {
this.clearInterval();
}
}, 1000 / speed);
},
clearInterval() {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
}
},
created() {
const { value } = this.data;
this.currentValue = value;
this.drawCircle(value);
},
destroyed() {
this.ctx = null;
this.clearInterval();
}
});
<view class="van-circle">
<canvas class="van-circle__canvas" style="{{ style }}" canvas-id="van-circle"></canvas>
<view wx:if="{{ !text }}" class="van-circle__text">
<slot></slot>
</view>
<cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
</view>
\ No newline at end of file
@import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}
\ No newline at end of file
......@@ -16,7 +16,7 @@ VantComponent({
const padding = `${gutter / 2}px`;
const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
if (style !== this.data.style) {
this.set({ style });
this.setData({ style });
}
}
}
......
......@@ -16,6 +16,7 @@ VantComponent({
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true
......@@ -34,7 +35,11 @@ VantComponent({
this.updateExpanded()
.then(nextTick)
.then(() => {
this.set({ transition: true });
const data = { transition: true };
if (this.data.expanded) {
data.contentHeight = 'auto';
}
this.setData(data);
});
},
methods: {
......@@ -66,11 +71,9 @@ VantComponent({
contentHeight: height ? `${height}px` : 'auto'
});
}
else {
return this.set({ contentHeight: `${height}px` })
.then(nextTick)
.then(() => this.set({ contentHeight: 0 }));
}
});
},
onClick() {
......@@ -84,7 +87,7 @@ VantComponent({
},
onTransitionEnd() {
if (this.data.expanded) {
this.set({
this.setData({
contentHeight: 'auto'
});
}
......
......@@ -5,9 +5,10 @@
title="{{ title }}"
title-class="title-class"
icon="{{ icon }}"
is-link="{{ isLink }}"
value="{{ value }}"
label="{{ label }}"
is-link="{{ isLink }}"
clickable="{{ clickable }}"
border="{{ border && expanded }}"
class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
right-icon-class="van-cell__right-icon"
......
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:.3s}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c9c9c9!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;font-size:13px;line-height:1.5;color:#999;background-color:#fff}
\ No newline at end of file
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;padding:var(--collapse-item-content-padding,15px);color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)}
\ No newline at end of file
......
......@@ -5,6 +5,9 @@ VantComponent({
type: 'descendant',
linked(child) {
this.children.push(child);
},
unlinked(child) {
this.children = this.children.filter((item) => item !== child);
}
},
props: {
......
export declare const RED = "#f44";
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
......
export const RED = '#f44';
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
......
declare function VantComponent<Data, Props, Watch, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Watch, Methods, Computed, CombinedComponentInstance<Data, Props, Watch, Methods, Computed>>): void;
import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
export { VantComponent };
......
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{content:"";display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
......
.van-clearfix:after{content:"";display:table;clear:both}
\ No newline at end of file
.van-clearfix:after{display:table;clear:both;content:""}
\ No newline at end of file
......
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
\ No newline at end of file
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
\ No newline at end of file
......
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
......
declare function isDef(value: any): boolean;
declare function isObj(x: any): boolean;
declare function isNumber(value: any): boolean;
declare function range(num: number, min: number, max: number): number;
export { isObj, isDef, isNumber, range };
/// <reference types="miniprogram-api-typings" />
export declare function isDef(value: any): boolean;
export declare function isObj(x: any): boolean;
export declare function isNumber(value: any): boolean;
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(fn: Function): void;
export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSuccessCallbackResult;
export declare function addUnit(value?: string | number): string | undefined;
......
function isDef(value) {
export function isDef(value) {
return value !== undefined && value !== null;
}
function isObj(x) {
export function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function isNumber(value) {
return /^\d+$/.test(value);
export function isNumber(value) {
return /^\d+(\.\d+)?$/.test(value);
}
function range(num, min, max) {
export function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
export { isObj, isDef, isNumber, range };
export function nextTick(fn) {
setTimeout(() => {
fn();
}, 1000 / 30);
}
let systemInfo = null;
export function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo;
}
export function addUnit(value) {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
......
import { VantComponent } from '../common/component';
import { isSameSecond, parseFormat, parseTimeData } from './utils';
function simpleTick(fn) {
return setTimeout(fn, 30);
}
VantComponent({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset'
},
format: {
type: String,
value: 'HH:mm:ss'
},
autoStart: {
type: Boolean,
value: true
}
},
data: {
timeData: parseTimeData(0),
formattedTime: '0'
},
destroyed() {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start() {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause() {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset() {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick() {
if (this.data.millisecond) {
this.microTick();
}
else {
this.macroTick();
}
},
microTick() {
this.tid = simpleTick(() => {
this.setRemain(this.getRemain());
if (this.remain !== 0) {
this.microTick();
}
});
},
macroTick() {
this.tid = simpleTick(() => {
const remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain !== 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
const timeData = parseTimeData(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: parseFormat(this.data.format, timeData)
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
}
}
});
<view class="van-count-down">
<slot wx:if="{{ useSlot }}"/>
<block wx:else>{{ formattedTime }}</block>
</view>
@import '../common/index.wxss';.van-count-down{color:#323233;color:var(--count-down-text-color,#323233);font-size:14px;font-size:var(--count-down-font-size,14px);line-height:20px;line-height:var(--count-down-line-height,20px)}
\ No newline at end of file
export declare type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
export declare function parseTimeData(time: number): TimeData;
export declare function parseFormat(format: string, timeData: TimeData): string;
export declare function isSameSecond(time1: number, time2: number): boolean;
function padZero(num, targetLength = 2) {
let str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
export function parseTimeData(time) {
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
days,
hours,
minutes,
seconds,
milliseconds
};
}
export function parseFormat(format, timeData) {
const { days } = timeData;
let { hours, minutes, seconds, milliseconds } = timeData;
if (format.indexOf('DD') === -1) {
hours += days * 24;
}
else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
}
else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
}
else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
}
else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
import { VantComponent } from '../common/component';
import { isDef } from '../common/utils';
import { pickerProps } from '../picker/shared';
const currentYear = new Date().getFullYear();
function isValidDate(date) {
return isDef(date) && !isNaN(new Date(date).getTime());
......@@ -12,7 +13,7 @@ function padZero(val) {
}
function times(n, iteratee) {
let index = -1;
const result = Array(n);
const result = Array(n < 0 ? 0 : n);
while (++index < n) {
result[index] = iteratee(index);
}
......@@ -29,100 +30,95 @@ function getTrueValue(formattedValue) {
function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
const defaultFormatter = (_, value) => value;
VantComponent({
props: {
value: null,
title: String,
loading: Boolean,
itemHeight: {
type: Number,
value: 44
},
visibleItemCount: {
type: Number,
value: 5
},
confirmButtonText: {
type: String,
value: '确认'
},
cancelButtonText: {
type: String,
value: '取消'
},
type: {
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { value: null, filter: null, type: {
type: String,
value: 'datetime'
},
showToolbar: {
}, showToolbar: {
type: Boolean,
value: true
},
minDate: {
}, formatter: {
type: null,
value: defaultFormatter
}, minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime()
},
maxDate: {
}, maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime()
},
minHour: {
}, minHour: {
type: Number,
value: 0
},
maxHour: {
}, maxHour: {
type: Number,
value: 23
},
minMinute: {
}, minMinute: {
type: Number,
value: 0
},
maxMinute: {
}, maxMinute: {
type: Number,
value: 59
}
},
} }),
data: {
innerValue: Date.now(),
columns: []
},
watch: {
value(val) {
value: 'updateValue',
type: 'updateValue',
minDate: 'updateValue',
maxDate: 'updateValue',
minHour: 'updateValue',
maxHour: 'updateValue',
minMinute: 'updateValue',
maxMinute: 'updateValue'
},
methods: {
updateValue() {
const { data } = this;
val = this.correctValue(val);
const val = this.correctValue(this.data.value);
const isEqual = val === data.innerValue;
if (!isEqual) {
this.updateColumnValue(val).then(() => {
this.$emit('input', val);
});
}
else {
this.updateColumns();
}
},
type: 'updateColumns',
minHour: 'updateColumns',
maxHour: 'updateColumns',
minMinute: 'updateColumns',
maxMinute: 'updateColumns'
},
methods: {
getPicker() {
if (this.picker == null) {
const picker = this.picker = this.selectComponent('.van-datetime-picker');
this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this;
const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
const results = this.getRanges().map(({ type, range }, index) => {
const values = times(range[1] - range[0] + 1, index => {
const { formatter = defaultFormatter } = this.data;
const results = this.getOriginColumns().map(column => ({
values: column.values.map(value => formatter(column.type, value))
}));
return this.set({ columns: results });
},
getOriginColumns() {
const { filter } = this.data;
const results = this.getRanges().map(({ type, range }) => {
let values = times(range[1] - range[0] + 1, index => {
let value = range[0] + index;
value = type === 'year' ? `${value}` : padZero(value);
return value;
});
return { values };
if (filter) {
values = filter(type, values);
}
return { type, values };
});
return this.set({ columns: results });
return results;
},
getRanges() {
const { data } = this;
......@@ -237,7 +233,7 @@ VantComponent({
const picker = this.getPicker();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`;
value = `${+data.columns[0].values[indexes[0]]}:${+data.columns[1].values[indexes[1]]}`;
}
else {
const values = picker.getValues();
......@@ -265,20 +261,26 @@ VantComponent({
},
updateColumnValue(value) {
let values = [];
const { data } = this;
const { type, formatter = defaultFormatter } = this.data;
const picker = this.getPicker();
if (data.type === 'time') {
if (type === 'time') {
const pair = value.split(':');
values = [pair[0], pair[1]];
values = [
formatter('hour', pair[0]),
formatter('minute', pair[1])
];
}
else {
const date = new Date(value);
values = [`${date.getFullYear()}`, padZero(date.getMonth() + 1)];
if (data.type === 'date') {
values.push(padZero(date.getDate()));
values = [
formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1))
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
if (data.type === 'datetime') {
values.push(padZero(date.getDate()), padZero(date.getHours()), padZero(date.getMinutes()));
if (type === 'datetime') {
values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
}
}
return this.set({ innerValue: value })
......
<van-picker
class="van-datetime-picker"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
title="{{ title }}"
columns="{{ columns }}"
item-height="{{ itemHeight }}"
......
/// <reference types="miniprogram-api-typings" />
import { Weapp } from './weapp';
declare type RecordToAny<T> = {
[K in keyof T]: any;
};
export declare type CombinedComponentInstance<Data, Props, Methods> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & {
data: Data & RecordToAny<Props>;
};
export interface VantComponentOptions<Data, Props, Methods, Instance> {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props & Weapp.PropertyOption;
watch?: Weapp.WatchOption<Instance>;
relation?: Weapp.RelationOption<Instance> & {
name: string;
};
relations?: {
[componentName: string]: Weapp.RelationOption<Instance>;
};
methods?: Methods & Weapp.MethodOption<Instance>;
beforeCreate?: (this: Instance) => void;
created?: (this: Instance) => void;
mounted?: (this: Instance) => void;
destroyed?: (this: Instance) => void;
}
export {};
/// <reference types="miniprogram-api-typings" />
export declare namespace Weapp {
export interface FormField {
data: {
name: string;
value: any;
};
}
interface Target {
id: string;
tagName: string;
dataset: {
[key: string]: any;
};
}
export interface Event {
/**
* 代表事件的类型。
*/
type: string;
/**
* 页面打开到触发事件所经过的毫秒数。
*/
timeStamp: number;
/**
* 触发事件的源组件。
*/
target: Target;
/**
* 事件绑定的当前组件。
*/
currentTarget: Target;
/**
* 额外的信息
*/
detail: any;
}
interface Touch {
/**
* 触摸点的标识符
*/
identifier: number;
/**
* 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
*/
pageX: number;
/**
* 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
*/
pageY: number;
/**
* 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
*/
clientX: number;
/**
* 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
*/
clientY: number;
}
export interface TouchEvent extends Event {
touches: Array<Touch>;
changedTouches: Array<Touch>;
}
/**
* relation定义,miniprogram-api-typings缺少this定义
*/
export interface RelationOption<Instance> {
/** 目标组件的相对关系 */
type: 'parent' | 'child' | 'ancestor' | 'descendant';
/** 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后 */
linked?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
/** 关系生命周期函数,当关系在页面节点树中发生改变时触发,触发时机在组件moved生命周期之后 */
linkChanged?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
/** 关系生命周期函数,当关系脱离页面节点树时触发,触发时机在组件detached生命周期之后 */
unlinked?(this: Instance, target: WechatMiniprogram.Component.TrivialInstance): void;
/** 如果这一项被设置,则它表示关联的目标节点所应具有的behavior,所有拥有这一behavior的组件节点都会被关联 */
target?: string;
}
/**
* obverser定义,miniprogram-api-typings缺少this定义
*/
type Observer<Instance, T> = (this: Instance, newVal: T, oldVal: T, changedPath: Array<string | number>) => void;
/**
* watch定义
*/
export interface WatchOption<Instance> {
[name: string]: string | Observer<Instance, any>;
}
/**
* methods定义,miniprogram-api-typings缺少this定义
*/
export interface MethodOption<Instance> {
[name: string]: (this: Instance, ...args: any[]) => any;
}
export interface ComputedOption<Instance> {
[name: string]: (this: Instance) => any;
}
type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | FunctionConstructor | null;
export interface PropertyOption {
[name: string]: PropertyType | PropertyType[] | {
/** 属性类型 */
type: PropertyType | PropertyType[];
/** 属性初始值 */
value?: any;
/** 属性值被更改时的响应函数 */
observer?: string | Observer<WechatMiniprogram.Component.TrivialInstance, any>;
/** 属性的类型(可以指定多个) */
optionalTypes?: PropertyType[];
};
}
export {};
}
/// <reference types="miniprogram-api-typings" />
declare type DialogAction = 'confirm' | 'cancel';
declare type DialogOptions = {
lang?: string;
show?: boolean;
title?: string;
width?: string | number;
zIndex?: number;
context?: any;
context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
className?: string;
customStyle?: string;
transition?: string;
asyncClose?: boolean;
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
......
......@@ -4,13 +4,14 @@ function getContext() {
return pages[pages.length - 1];
}
const Dialog = options => {
options = Object.assign({}, Dialog.currentOptions, options);
options = Object.assign(Object.assign({}, Dialog.currentOptions), options);
return new Promise((resolve, reject) => {
const context = options.context || getContext();
const dialog = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (dialog) {
dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
dialog.setData(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
queue.push(dialog);
}
else {
......@@ -21,13 +22,17 @@ const Dialog = options => {
Dialog.defaultOptions = {
show: true,
title: '',
width: null,
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
asyncClose: false,
messageAlign: '',
transition: 'scale',
selector: '#van-dialog',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
......
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
import { addUnit } from '../common/utils';
import { GRAY, BLUE } from '../common/color';
VantComponent({
mixins: [button, openType],
props: {
......@@ -8,11 +10,19 @@ VantComponent({
title: String,
message: String,
useSlot: Boolean,
className: String,
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
overlayStyle: String,
useTitleSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: {
type: null,
observer: 'setWidthWithUnit'
},
zIndex: {
type: Number,
value: 2000
......@@ -25,6 +35,14 @@ VantComponent({
type: String,
value: '取消'
},
confirmButtonColor: {
type: String,
value: BLUE
},
cancelButtonColor: {
type: String,
value: GRAY
},
showConfirmButton: {
type: Boolean,
value: true
......@@ -61,19 +79,19 @@ VantComponent({
},
handleAction(action) {
if (this.data.asyncClose) {
this.set({
this.setData({
[`loading.${action}`]: true
});
}
this.onClose(action);
},
close() {
this.set({
this.setData({
show: false
});
},
stopLoading() {
this.set({
this.setData({
loading: {
confirm: false,
cancel: false
......@@ -85,12 +103,17 @@ VantComponent({
this.close();
}
this.$emit('close', action);
//把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
// 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
this.$emit(action, { dialog: this });
const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
if (callback) {
callback(this);
}
},
setWidthWithUnit(val) {
this.setData({
widthWithUnit: addUnit(val)
});
}
}
});
......
......@@ -2,16 +2,19 @@
show="{{ show }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-dialog"
transition="{{ transition }}"
custom-class="van-dialog {{ className }}"
custom-style="{{ widthWithUnit ? 'width: ' + widthWithUnit + ';' : '' }}{{ customStyle }}"
overlay-style="{{ overlayStyle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view
wx:if="{{ title }}"
wx:if="{{ title || useTitleSlot }}"
class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
>
{{ title }}
<slot wx:if="{{ useTitleSlot }}" name="title" />
<block wx:elif="{{ title }}"> {{ title }}</block>
</view>
<slot wx:if="{{ useSlot }}" />
......@@ -19,7 +22,7 @@
wx:elif="{{ message }}"
class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
>
<text>{{ message }}</text>
<text class="van-dialog__message-text">{{ message }}</text>
</view>
<view class="van-hairline--top van-dialog__footer">
......@@ -29,6 +32,7 @@
loading="{{ loading.cancel }}"
class="van-dialog__button van-hairline--right"
custom-class="van-dialog__cancel"
custom-style="color: {{ cancelButtonColor }}"
bind:click="onCancel"
>
{{ cancelButtonText }}
......@@ -39,6 +43,7 @@
class="van-dialog__button"
loading="{{ loading.confirm }}"
custom-class="van-dialog__confirm"
custom-style="color: {{ confirmButtonColor }}"
open-type="{{ confirmButtonOpenType }}"
lang="{{ lang }}"
......
@import '../common/index.wxss';.van-dialog{width:85%;overflow:hidden;font-size:16px;background-color:#fff;border-radius:4px}.van-dialog__header{padding-top:25px;font-weight:500;text-align:center}.van-dialog__header--isolated{padding:25px 0}.van-dialog__message{max-height:60vh;padding:25px;overflow-y:auto;font-size:14px;line-height:1.5;text-align:center;-webkit-overflow-scrolling:touch}.van-dialog__message--has-title{padding-top:12px;color:#7d7e80}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog__confirm{color:#1989fa!important}.van-dialog-bounce-enter{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)}
\ No newline at end of file
@import '../common/index.wxss';.van-dialog{top:45%!important;overflow:hidden;width:320px;width:var(--dialog-width,320px);font-size:16px;font-size:var(--dialog-font-size,16px);border-radius:16px;border-radius:var(--dialog-border-radius,16px);background-color:#fff;background-color:var(--dialog-background-color,#fff)}@media (max-width:321px){.van-dialog{width:90%;width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{text-align:center;padding-top:24px;padding-top:var(--dialog-header-padding-top,24px);font-weight:500;font-weight:var(--dialog-header-font-weight,500);line-height:24px;line-height:var(--dialog-header-line-height,24px)}.van-dialog__header--isolated{padding:24px 0;padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{overflow-y:auto;text-align:center;-webkit-overflow-scrolling:touch;font-size:14px;font-size:var(--dialog-message-font-size,14px);line-height:20px;line-height:var(--dialog-message-line-height,20px);max-height:60vh;max-height:var(--dialog-message-max-height,60vh);padding:24px;padding:var(--dialog-message-padding,24px)}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--has-title{padding-top:12px;padding-top:var(--dialog-has-title-message-padding-top,12px);color:#7d7e80;color:var(--dialog-has-title-message-text-color,#7d7e80)}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-dialog-bounce-leave-active{-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9);opacity:0}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: {
type: Boolean,
value: false
},
hairline: {
type: Boolean,
value: false
},
contentPosition: {
type: String,
value: ''
},
fontSize: {
type: Number,
value: ''
},
borderColor: {
type: String,
value: ''
},
textColor: {
type: String,
value: ''
},
customStyle: {
type: String,
value: ''
}
}
});
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('divider', [{dashed, hairline}, contentPosition]) }}"
style="{{ borderColor ? 'border-color: ' + borderColor + ';' : '' }}{{ textColor ? 'color: ' + textColor + ';' : '' }} {{ fontSize ? 'font-size: ' + fontSize + 'px;' : '' }} {{ customStyle }}"
>
<slot />
</view>
@import '../common/index.wxss';.van-divider{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin:16px 0;margin:var(--divider-margin,16px 0);color:#969799;color:var(--divider-text-color,#969799);font-size:14px;font-size:var(--divider-font-size,14px);line-height:24px;line-height:var(--divider-line-height,24px);border:0 solid #ebedf0;border-color:var(--divider-border-color,#ebedf0)}.van-divider:after,.van-divider:before{display:block;-webkit-flex:1;flex:1;box-sizing:border-box;height:1px;border-color:inherit;border-style:inherit;border-width:1px 0 0}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:16px;margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:16px;margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:10%;max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:10%;max-width:var(--divider-content-right-width,10%)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'dropdown-menu',
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
},
props: {
value: null,
title: String,
disabled: Boolean,
titleClass: String,
options: {
type: Array,
value: []
}
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: ''
},
created() {
this.setData({ displayTitle: this.computedDisplayTitle(this.data.value) });
},
methods: {
computedDisplayTitle(curValue) {
const { title, options } = this.data;
if (title) {
return title;
}
const match = options.filter(option => option.value === curValue);
const displayTitle = match.length ? match[0].text : '';
return displayTitle;
},
onClickOverlay() {
this.toggle();
this.$emit('close');
},
onOptionTap(event) {
let { value, displayTitle } = this.data;
const { option } = event.currentTarget.dataset;
const { value: optionValue } = option;
if (optionValue !== value) {
value = optionValue;
displayTitle = this.computedDisplayTitle(optionValue);
this.$emit('change', optionValue);
}
this.setData({ showPopup: false, value, displayTitle });
const time = this.data.duration || 0;
setTimeout(() => {
this.setData({ showWrapper: false });
}, time);
// parent 中的 itemListData 是 children 上的数据的集合
// 数据的更新由 children 各自维护,但是模板的更新需要额外触发 parent 的 setData
this.parent.setData({ itemListData: this.parent.data.itemListData });
},
toggle() {
const { childIndex } = this.data;
this.parent.toggleItem(childIndex);
}
}
});
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index",
"van-switch": "../switch/index"
"van-icon": "../icon/index"
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ showWrapper }}"
class="{{ utils.bem('dropdown-item', direction) }}"
style="{{ wrapperStyle }}"
>
<van-popup
show="{{ showPopup }}"
custom-style="position: absolute;"
overlay-style="position: absolute;"
overlay="{{ overlay }}"
position="{{ direction === 'down' ? 'top' : 'bottom' }}"
duration="{{ transition ? duration : 0 }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<van-cell
wx:for="{{ options }}"
wx:key="{{ item.value }}"
data-option="{{ item }}"
class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
clickable
icon="{{ item.icon }}"
bind:tap="onOptionTap"
>
<view
slot="title"
class="van-dropdown-item__title"
style="{{ item.value === value ? 'color:' + activeColor : '' }}"
>
{{ item.text }}
</view>
<van-icon
wx:if="{{ item.value === value }}"
name="success"
class="van-dropdown-item__icon"
color="{{ activeColor }}"
/>
</van-cell>
<slot />
</van-popup>
</view>
@import '../common/index.wxss';.van-dropdown-item{position:fixed;right:0;left:0;overflow:hidden}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:#1989fa;color:var(--dropdown-menu-option-active-color,#1989fa)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
let ARRAY = [];
VantComponent({
field: true,
relation: {
name: 'dropdown-item',
type: 'descendant',
linked(target) {
this.children = this.children || [];
// 透传 props 给 dropdown-item
const { overlay, duration, activeColor, closeOnClickOverlay, direction } = this.data;
this.updateChildData(target, {
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
childIndex: this.children.length
});
this.children.push(target);
// 收集 dorpdown-item 的 data 挂在 data 上
target &&
this.setData({
itemListData: this.data.itemListData.concat([target.data])
});
},
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
},
props: {
activeColor: String,
overlay: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 10
},
duration: {
type: Number,
value: 200
},
direction: {
type: String,
value: 'down'
},
closeOnClickOverlay: {
type: Boolean,
value: true
},
closeOnClickOutside: {
type: Boolean,
value: true
}
},
data: {
itemListData: []
},
created() {
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter(item => item !== this);
},
methods: {
updateChildData(childItem, newData, needRefreshList = false) {
childItem.setData(newData);
if (needRefreshList) {
// dropdown-item data 更新,涉及到 title 的展示,触发模板更新
this.setData({ itemListData: this.data.itemListData });
}
},
toggleItem(active) {
this.children.forEach((item, index) => {
const { showPopup } = item.data;
if (index === active) {
this.toggleChildItem(item);
}
else if (showPopup) {
this.toggleChildItem(item, false, { immediate: true });
}
});
},
toggleChildItem(childItem, show, options = {}) {
const { showPopup, duration } = childItem.data;
if (show === undefined)
show = !showPopup;
if (show === showPopup) {
return;
}
const newChildData = { transition: !options.immediate, showPopup: show };
if (!show) {
const time = options.immediate ? 0 : duration;
this.updateChildData(childItem, Object.assign({}, newChildData), true);
setTimeout(() => {
this.updateChildData(childItem, { showWrapper: false }, true);
}, time);
return;
}
this.getChildWrapperStyle().then((wrapperStyle = '') => {
this.updateChildData(childItem, Object.assign(Object.assign({}, newChildData), { wrapperStyle, showWrapper: true }), true);
});
},
close() {
this.children.forEach((item) => {
this.toggleChildItem(item, false, { immediate: true });
});
},
getChildWrapperStyle() {
const { windowHeight } = wx.getSystemInfoSync();
const { zIndex, direction } = this.data;
let offset = 0;
return this.getRect('.van-dropdown-menu').then(rect => {
const { top = 0, bottom = 0 } = rect;
if (direction === 'down') {
offset = bottom;
}
else {
offset = windowHeight - top;
}
let wrapperStyle = `z-index: ${zIndex};`;
if (direction === 'down') {
wrapperStyle += `top: ${addUnit(offset)};`;
}
else {
wrapperStyle += `bottom: ${addUnit(offset)};`;
}
return Promise.resolve(wrapperStyle);
});
},
onTitleTap(event) {
// item ---> dropdown-item
const { item, index } = event.currentTarget.dataset;
if (!item.disabled) {
// menuItem ---> dropdown-menu
ARRAY.forEach(menuItem => {
if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== this) {
menuItem.close();
}
});
this.toggleItem(index);
}
}
}
});
{
"component": true
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-dropdown-menu van-dropdown-menu--top-bottom">
<view
wx:for="{{ itemListData }}"
wx:key="index"
data-item="{{ item }}"
data-index="{{ index }}"
class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
bind:tap="onTitleTap"
>
<view
class="{{ item.titleClass }} {{ utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }) }}"
style="{{ item.showPopup ? 'color:' + activeColor : '' }}"
>
<view class="van-ellipsis">
{{item.displayTitle}}
</view>
</view>
</view>
<slot />
</view>
@import '../common/index.wxss';.van-dropdown-menu{display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;height:50px;height:var(--dropdown-menu-height,50px);background-color:#fff;background-color:var(--dropdown-menu-background-color,#fff)}.van-dropdown-menu__item{display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:#969799;color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{position:relative;box-sizing:border-box;max-width:100%;padding:0 8px;padding:var(--dropdown-menu-title-padding,0 8px);color:#323233;color:var(--dropdown-menu-title-text-color,#323233);font-size:15px;font-size:var(--dropdown-menu-title-font-size,15px);line-height:18px;line-height:var(--dropdown-menu-title-line-height,18px)}.van-dropdown-menu__title:after{position:absolute;top:50%;right:-4px;margin-top:-5px;border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:.8;content:""}.van-dropdown-menu__title--active{color:#1989fa;color:var(--dropdown-menu-title-active-text-color,#1989fa)}.van-dropdown-menu__title--down:after{margin-top:-1px;-webkit-transform:rotate(135deg);transform:rotate(135deg)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { getSystemInfoSync } from '../common/utils';
VantComponent({
field: true,
classes: ['input-class'],
classes: ['input-class', 'right-icon-class'],
props: {
size: String,
icon: String,
......@@ -12,27 +13,37 @@ VantComponent({
center: Boolean,
isLink: Boolean,
leftIcon: String,
rightIcon: String,
disabled: Boolean,
autosize: Boolean,
readonly: Boolean,
required: Boolean,
password: Boolean,
iconClass: String,
clearable: Boolean,
clickable: Boolean,
inputAlign: String,
errorMessageAlign: String,
customClass: String,
placeholder: String,
customStyle: String,
confirmType: String,
confirmHold: Boolean,
holdKeyboard: Boolean,
errorMessage: String,
placeholder: String,
customStyle: String,
useIconSlot: Boolean,
useButtonSlot: Boolean,
arrowDirection: String,
placeholderStyle: String,
errorMessageAlign: String,
selectionEnd: {
type: Number,
value: -1
},
selectionStart: {
type: Number,
value: -1
},
showConfirmBar: {
type: Boolean,
value: true
},
placeholderStyle: String,
adjustPosition: {
type: Boolean,
value: true
......@@ -59,63 +70,29 @@ VantComponent({
}
},
data: {
showClear: false
},
beforeCreate() {
this.focused = false;
focused: false,
system: getSystemInfoSync().system.split(' ').shift().toLowerCase()
},
methods: {
onInput(event) {
const { value = '' } = event.detail || {};
this.set({
value,
showClear: this.getShowClear(value)
}, () => {
this.setData({ value }, () => {
this.emitChange(value);
});
},
onFocus(event) {
const { value = '', height = 0 } = event.detail || {};
this.$emit('focus', { value, height });
this.focused = true;
this.blurFromClear = false;
this.set({
showClear: this.getShowClear()
});
this.setData({ focused: true });
this.$emit('focus', event.detail);
},
onBlur(event) {
const { value = '', cursor = 0 } = event.detail || {};
this.$emit('blur', { value, cursor });
this.focused = false;
const showClear = this.getShowClear();
if (this.data.value === value) {
this.set({
showClear
});
}
else if (!this.blurFromClear) {
// fix: the handwritten keyboard does not trigger input change
this.set({
value,
showClear
}, () => {
this.emitChange(value);
});
}
this.setData({ focused: false });
this.$emit('blur', event.detail);
},
onClickIcon() {
this.$emit('click-icon');
},
getShowClear(value) {
value = value === undefined ? this.data.value : value;
return (this.data.clearable && this.focused && value && !this.data.readonly);
},
onClear() {
this.blurFromClear = true;
this.set({
value: '',
showClear: this.getShowClear('')
}, () => {
this.setData({ value: '' }, () => {
this.emitChange('');
this.$emit('clear', '');
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<van-cell
size="{{ size }}"
icon="{{ leftIcon }}"
title="{{ label }}"
center="{{ center }}"
border="{{ border }}"
is-link="{{ isLink }}"
required="{{ required }}"
custom-style="{{ customStyle }}"
clickable="{{ clickable }}"
title-width="{{ titleWidth }}"
custom-style="{{ customStyle }}"
arrow-direction="{{ arrowDirection }}"
custom-class="van-field"
size="{{ size }}"
>
<slot name="left-icon" slot="icon" />
<slot name="label" slot="title" />
<view class="van-field__body {{ type === 'textarea' ? 'van-field__body--textarea' : '' }}">
<view class="{{ utils.bem('field__body', [type, system]) }}">
<textarea
wx:if="{{ type === 'textarea' }}"
class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
class="input-class {{ utils.bem('field__input', [inputAlign, type, { disabled, error }]) }}"
fixed="{{ fixed }}"
focus="{{ focus }}"
value="{{ value }}"
disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}"
auto-height="{{ autosize }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
auto-height="{{ autosize }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
show-confirm-bar="{{ showConfirmBar }}"
hold-keyboard="{{ holdKeyboard }}"
selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}"
bindinput="onInput"
bind:blur="onBlur"
bind:focus="onFocus"
bind:confirm="onConfirm"
/>
>
</textarea>
<input
wx:else
class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
......@@ -45,34 +51,39 @@
maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
confirm-type="{{ confirmType }}"
confirm-hold="{{ confirmHold }}"
hold-keyboard="{{ holdKeyboard }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}"
password="{{ password || type === 'password' }}"
bindinput="onInput"
bind:blur="onBlur"
bind:focus="onFocus"
bind:confirm="onConfirm"
/>
<van-icon
wx:if="{{ showClear }}"
wx:if="{{ clearable && focused && value && !readonly }}"
size="16px"
name="clear"
class="van-field__clear-root"
custom-class="van-field__clear"
bind:touchstart="onClear"
class="van-field__clear-root van-field__icon-root"
bindtouchstart="onClear"
/>
<view class="van-field__icon-container" wx:if="{{ icon || useIconSlot }}" bind:tap="onClickIcon">
<view class="van-field__icon-container" bind:tap="onClickIcon">
<van-icon
wx:if="{{ icon }}"
wx:if="{{ rightIcon || icon }}"
size="16px"
name="{{ icon }}"
custom-class="van-field__icon {{ iconClass }}"
name="{{ rightIcon || icon }}"
class="van-field__icon-root {{ iconClass }}"
custom-class="right-icon-class"
/>
<slot wx:else name="icon" />
<slot name="right-icon" />
<slot name="icon" />
</view>
<view wx:if="{{ useButtonSlot }}" class="van-field__button">
<view class="van-field__button">
<slot name="button" />
</view>
</view>
......
@import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{min-height:24px}.van-field__input{display:block;width:100%;height:24px;min-height:24px;padding:0;margin:0;line-height:inherit;color:#333;text-align:left;background-color:initial;border:0;box-sizing:border-box;resize:none}.van-field__input--disabled{color:#999;background-color:initial;opacity:1}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__input--error{color:#f44}.van-field__placeholder{color:#999}.van-field__clear-root{display:-webkit-flex;display:flex;height:24px;-webkit-align-items:center;align-items:center}.van-field__button,.van-field__clear,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear,.van-field__icon-container{padding:0 10px;margin-right:-10px;line-height:inherit;vertical-align:middle}.van-field__clear{color:#c9c9c9}.van-field__icon-container{color:#999}.van-field__icon{display:block!important}.van-field__button{padding-left:10px}.van-field__error-message{font-size:12px;color:#f44;text-align:left}.van-field__error--center{text-align:center}.van-field__error--right{text-align:right}
\ No newline at end of file
@import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{line-height:1.2em;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__body--textarea.van-field__body--ios{margin-top:-4.5px}.van-field__input{position:relative;display:block;box-sizing:border-box;width:100%;margin:0;padding:0;line-height:inherit;text-align:left;background-color:initial;border:0;resize:none;color:#323233;color:var(--field-input-text-color,#323233);height:24px;height:var(--cell-line-height,24px);min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__input--textarea{height:18px;height:var(--field-text-area-min-height,18px);min-height:18px;min-height:var(--field-text-area-min-height,18px)}.van-field__input--error{color:#ee0a24;color:var(--field-input-error-text-color,#ee0a24)}.van-field__input--disabled{background-color:initial;opacity:1;color:#969799;color:var(--field-input-disabled-text-color,#969799)}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__placeholder{position:absolute;top:0;right:0;left:0;pointer-events:none;color:#969799;color:var(--field-placeholder-text-color,#969799)}.van-field__placeholder--error{color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;vertical-align:middle;padding:0 8px;padding:0 var(--padding-xs,8px);margin-right:-8px;margin-right:-var(--padding-xs,8px)}.van-field__button,.van-field__clear-root,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear-root{color:#c8c9cc;color:var(--field-clear-icon-color,#c8c9cc)}.van-field__icon-container{color:#969799;color:var(--field-icon-container-color,#969799)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:8px;padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{text-align:left;font-size:12px;font-size:var(--field-error-message-text-font-size,12px);color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}
\ No newline at end of file
......
......@@ -4,8 +4,16 @@ import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [link, button, openType],
relation: {
type: 'ancestor',
name: 'goods-action',
linked(parent) {
this.parent = parent;
}
},
props: {
text: String,
color: String,
loading: Boolean,
disabled: Boolean,
type: {
......@@ -13,10 +21,21 @@ VantComponent({
value: 'danger'
}
},
mounted() {
this.updateStyle();
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
updateStyle() {
const { children = [] } = this.parent;
const index = children.indexOf(this);
this.setData({
isFirst: index === 0,
isLast: index === children.length - 1
});
}
}
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<van-button
square
id="{{ id }}"
size="large"
lang="{{ lang }}"
type="{{ type }}"
color="{{ color }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
open-type="{{ openType }}"
custom-class="custom-class"
custom-class="{{ utils.bem('goods-action-button', [type, { first: isFirst, last: isLast }]) }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
app-parameter="{{ appParameter }}"
......
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}
\ No newline at end of file
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-goods-action-button{border:none!important;height:40px!important;height:var(--goods-action-button-height,40px)!important;font-weight:500!important;font-weight:var(--font-weight-bold,500)!important;line-height:40px!important;line-height:var(--goods-action-button-height,40px)!important}.van-goods-action-button--first{display:block!important;margin-left:5px;border-top-left-radius:20px!important;border-top-left-radius:var(--goods-action-button-border-radius,20px)!important;border-bottom-left-radius:20px!important;border-bottom-left-radius:var(--goods-action-button-border-radius,20px)!important}.van-goods-action-button--last{display:block!important;margin-right:5px;border-top-right-radius:20px!important;border-top-right-radius:var(--goods-action-button-border-radius,20px)!important;border-bottom-right-radius:20px!important;border-bottom-right-radius:var(--goods-action-button-border-radius,20px)!important}.van-goods-action-button--warning{background:linear-gradient(90deg,#ffd01e,#ff8917);background:var(--goods-action-button-warning-color,linear-gradient(90deg,#ffd01e,#ff8917))}.van-goods-action-button--danger{background:linear-gradient(90deg,#ff6034,#ee0a24);background:var(--goods-action-button-danger-color,linear-gradient(90deg,#ff6034,#ee0a24))}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
\ No newline at end of file
......
......@@ -7,6 +7,7 @@ VantComponent({
mixins: [link, button, openType],
props: {
text: String,
dot: Boolean,
info: String,
icon: String,
disabled: Boolean,
......
......@@ -22,14 +22,17 @@
bindgetphonenumber="bindGetPhoneNumber"
bindlaunchapp="bindLaunchApp"
>
<view class="van-goods-action-icon__content van-hairline--right">
<view class="van-goods-action-icon__content">
<van-icon
wx:if="{{ icon }}"
size="20px"
name="{{ icon }}"
dot="{{ dot }}"
info="{{ info }}"
class="van-goods-action-icon__icon"
custom-class="icon-class"
/>
<slot name="icon" />
<text class="text-class">{{ text }}</text>
</view>
</van-button>
......
@import '../common/index.wxss';.van-goods-action-icon{width:50px!important;border:none!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;height:100%;font-size:10px;line-height:1;color:#7d7e80;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-goods-action-icon__icon{margin-bottom:4px}
\ No newline at end of file
@import '../common/index.wxss';.van-goods-action-icon{border:none!important;width:50px!important;width:var(--goods-action-icon-height,50px)!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;height:100%;line-height:1;font-size:10px;font-size:var(--goods-action-icon-font-size,10px);color:#7d7e80;color:var(--goods-action-icon-text-color,#7d7e80)}.van-goods-action-icon__icon{margin-bottom:4px}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()]
relation: {
type: 'descendant',
name: 'goods-action-button',
linked(child) {
this.children.push(child);
},
unlinked(child) {
this.children = this.children.filter((item) => item !== child);
}
},
beforeCreate() {
this.children = [];
},
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true
}
}
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}">
<view class="custom-class {{ utils.bem('goods-action', { safe: safeAreaInsetBottom }) }}">
<slot />
</view>
......
@import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-goods-action--safe{padding-bottom:34px}
\ No newline at end of file
@import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;background-color:#fff;background-color:var(--goods-action-background-color,#fff)}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file
......
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'grid',
type: 'ancestor',
linked(parent) {
this.parent = parent;
}
},
mixins: [link],
props: {
icon: String,
dot: Boolean,
info: null,
text: String,
useSlot: Boolean
},
mounted() {
this.updateStyle();
},
methods: {
updateStyle() {
if (!this.parent) {
return;
}
const { data, children } = this.parent;
const { columnNum, border, square, gutter, clickable, center } = data;
const width = `${100 / columnNum}%`;
const styleWrapper = [];
styleWrapper.push(`width: ${width}`);
if (square) {
styleWrapper.push(`padding-top: ${width}`);
}
if (gutter) {
styleWrapper.push(`padding-right: ${gutter}px`);
const index = children.indexOf(this);
if (index >= columnNum) {
styleWrapper.push(`margin-top: ${gutter}px`);
}
}
this.setData({
style: styleWrapper.join('; '),
center,
border,
square,
gutter,
clickable
});
},
onClick() {
this.$emit('click');
this.jumpLink();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="{{ utils.bem('grid-item', { square }) }}" style="{{ style }}" bindtap="onClick">
<view class="{{ utils.bem('grid-item__content', { center, square, clickable, surround: border && gutter }) }} {{ border ? 'van-hairline--surround' : '' }}">
<block wx:if="{{ useSlot }}">
<slot />
</block>
<block wx:else>
<view class="van-grid-item__icon">
<van-icon wx:if="{{ icon }}" name="{{ icon }}" dot="{{ dot }}" info="{{ info }}" />
<slot wx:else name="icon"></slot>
</view>
<view class="van-grid-item__text">
<text wx:if="{{ text }}">{{ text }}</text>
<slot wx:else name="text"></slot>
</view>
</block>
</view>
</view>
@import '../common/index.wxss';.van-grid-item{position:relative;float:left;box-sizing:border-box}.van-grid-item--square{height:0}.van-grid-item__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;box-sizing:border-box;height:100%;padding:16px 8px;padding:var(--grid-item-content-padding,16px 8px);background-color:#fff;background-color:var(--grid-item-content-background-color,#fff)}.van-grid-item__content:after{z-index:1;border-width:0 1px 1px 0;border-bottom-width:var(--border-width-base,1px);border-right-width:var(--border-width-base,1px);border-top-width:0}.van-grid-item__content--surround:after{border-width:1px;border-width:var(--border-width-base,1px)}.van-grid-item__content--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-grid-item__content--square{position:absolute;top:0;right:0;left:0}.van-grid-item__content--clickable:active{background-color:#f2f3f5;background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{font-size:26px;font-size:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:#7d7e80;color:var(--grid-item-text-color,#7d7e80);font-size:12px;font-size:var(--grid-item-text-font-size,12px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'grid-item',
type: 'descendant',
linked(child) {
this.children.push(child);
},
unlinked(child) {
this.children = this.children.filter((item) => item !== child);
}
},
props: {
square: {
type: Boolean,
observer: 'updateChildren'
},
gutter: {
type: [Number, String],
value: 0,
observer: 'updateChildren'
},
clickable: {
type: Boolean,
observer: 'updateChildren'
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren'
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren'
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren'
}
},
beforeCreate() {
this.children = [];
},
created() {
const { gutter } = this.data;
if (gutter) {
this.setData({
style: `padding-left: ${gutter}px`
});
}
},
methods: {
updateChildren() {
this.children.forEach((child) => {
child.updateStyle();
});
}
}
});
<view class="van-grid {{ border && !gutter ? 'van-hairline--top' : '' }}" style="{{ style }}">
<slot />
</view>
@import '../common/index.wxss';.van-grid{position:relative;box-sizing:border-box;overflow:hidden}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
props: {
dot: Boolean,
info: null,
name: String,
size: String,
size: {
type: null,
observer: 'setSizeWithUnit'
},
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon'
},
name: {
type: String,
observer(val) {
this.setData({
isImageName: val.indexOf('/') !== -1
});
}
}
},
data: {
sizeWithUnit: null,
},
methods: {
onClick() {
this.$emit('click');
},
setSizeWithUnit(size) {
this.setData({
sizeWithUnit: addUnit(size)
});
}
}
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}"
style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}"
class="custom-class {{ classPrefix }} {{ isImageName ? 'van-icon--image' : classPrefix + '-' + name }}"
style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + sizeWithUnit + ';' : '' }}{{ customStyle }}"
bind:tap="onClick"
>
<van-info
wx:if="{{ info !== null }}"
wx:if="{{ info !== null || dot }}"
dot="{{ dot }}"
info="{{ info }}"
custom-class="van-icon__info"
/>
<image
wx:if="{{ utils.isSrc(name) }}"
wx:if="{{ isImageName }}"
src="{{ name }}"
mode="aspectFit"
class="van-icon__image"
/>
</view>
......
@import '../common/index.wxss';@font-face{font-style:normal;font-weight:400;font-family:vant-icon;src:url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-o:before{content:"\F03A"}.van-icon-comment:before{content:"\F03B"}.van-icon-completed:before{content:"\F03C"}.van-icon-contact:before{content:"\F03D"}.van-icon-coupon-o:before{content:"\F03E"}.van-icon-coupon:before{content:"\F03F"}.van-icon-credit-pay:before{content:"\F040"}.van-icon-cross:before{content:"\F041"}.van-icon-debit-pay:before{content:"\F042"}.van-icon-delete:before{content:"\F043"}.van-icon-descending:before{content:"\F044"}.van-icon-description:before{content:"\F045"}.van-icon-desktop-o:before{content:"\F046"}.van-icon-diamond-o:before{content:"\F047"}.van-icon-diamond:before{content:"\F048"}.van-icon-discount:before{content:"\F049"}.van-icon-ecard-pay:before{content:"\F04A"}.van-icon-edit:before{content:"\F04B"}.van-icon-ellipsis:before{content:"\F04C"}.van-icon-empty:before{content:"\F04D"}.van-icon-envelop-o:before{content:"\F04E"}.van-icon-exchange:before{content:"\F04F"}.van-icon-expand-o:before{content:"\F050"}.van-icon-expand:before{content:"\F051"}.van-icon-eye-o:before{content:"\F052"}.van-icon-eye:before{content:"\F053"}.van-icon-fail:before{content:"\F054"}.van-icon-failure:before{content:"\F055"}.van-icon-filter-o:before{content:"\F056"}.van-icon-fire-o:before{content:"\F057"}.van-icon-fire:before{content:"\F058"}.van-icon-flag-o:before{content:"\F059"}.van-icon-flower-o:before{content:"\F05A"}.van-icon-free-postage:before{content:"\F05B"}.van-icon-friends-o:before{content:"\F05C"}.van-icon-friends:before{content:"\F05D"}.van-icon-gem-o:before{content:"\F05E"}.van-icon-gem:before{content:"\F05F"}.van-icon-gift-card-o:before{content:"\F060"}.van-icon-gift-card:before{content:"\F061"}.van-icon-gift-o:before{content:"\F062"}.van-icon-gift:before{content:"\F063"}.van-icon-gold-coin-o:before{content:"\F064"}.van-icon-gold-coin:before{content:"\F065"}.van-icon-goods-collect-o:before{content:"\F066"}.van-icon-goods-collect:before{content:"\F067"}.van-icon-graphic:before{content:"\F068"}.van-icon-home-o:before{content:"\F069"}.van-icon-hot-o:before{content:"\F06A"}.van-icon-hot-sale-o:before{content:"\F06B"}.van-icon-hot-sale:before{content:"\F06C"}.van-icon-hot:before{content:"\F06D"}.van-icon-hotel-o:before{content:"\F06E"}.van-icon-idcard:before{content:"\F06F"}.van-icon-info-o:before{content:"\F070"}.van-icon-info:before{content:"\F071"}.van-icon-invition:before{content:"\F072"}.van-icon-label-o:before{content:"\F073"}.van-icon-label:before{content:"\F074"}.van-icon-like-o:before{content:"\F075"}.van-icon-like:before{content:"\F076"}.van-icon-live:before{content:"\F077"}.van-icon-location-o:before{content:"\F078"}.van-icon-location:before{content:"\F079"}.van-icon-lock:before{content:"\F07A"}.van-icon-logistics:before{content:"\F07B"}.van-icon-manager-o:before{content:"\F07C"}.van-icon-manager:before{content:"\F07D"}.van-icon-map-marked:before{content:"\F07E"}.van-icon-medel-o:before{content:"\F07F"}.van-icon-medel:before{content:"\F080"}.van-icon-more-o:before{content:"\F081"}.van-icon-more:before{content:"\F082"}.van-icon-music-o:before{content:"\F083"}.van-icon-new-arrival-o:before{content:"\F084"}.van-icon-new-arrival:before{content:"\F085"}.van-icon-new-o:before{content:"\F086"}.van-icon-new:before{content:"\F087"}.van-icon-newspaper-o:before{content:"\F088"}.van-icon-notes-o:before{content:"\F089"}.van-icon-orders-o:before{content:"\F08A"}.van-icon-other-pay:before{content:"\F08B"}.van-icon-paid:before{content:"\F08C"}.van-icon-passed:before{content:"\F08D"}.van-icon-pause-circle-o:before{content:"\F08E"}.van-icon-pause-circle:before{content:"\F08F"}.van-icon-pause:before{content:"\F090"}.van-icon-peer-pay:before{content:"\F091"}.van-icon-pending-payment:before{content:"\F092"}.van-icon-phone-circle-o:before{content:"\F093"}.van-icon-phone-o:before{content:"\F094"}.van-icon-phone:before{content:"\F095"}.van-icon-photo-o:before{content:"\F096"}.van-icon-photo:before{content:"\F097"}.van-icon-photograph:before{content:"\F098"}.van-icon-play-circle-o:before{content:"\F099"}.van-icon-play-circle:before{content:"\F09A"}.van-icon-play:before{content:"\F09B"}.van-icon-plus:before{content:"\F09C"}.van-icon-point-gift-o:before{content:"\F09D"}.van-icon-point-gift:before{content:"\F09E"}.van-icon-points:before{content:"\F09F"}.van-icon-printer:before{content:"\F0A0"}.van-icon-qr-invalid:before{content:"\F0A1"}.van-icon-qr:before{content:"\F0A2"}.van-icon-question-o:before{content:"\F0A3"}.van-icon-question:before{content:"\F0A4"}.van-icon-records:before{content:"\F0A5"}.van-icon-refund-o:before{content:"\F0A6"}.van-icon-replay:before{content:"\F0A7"}.van-icon-scan:before{content:"\F0A8"}.van-icon-search:before{content:"\F0A9"}.van-icon-send-gift-o:before{content:"\F0AA"}.van-icon-send-gift:before{content:"\F0AB"}.van-icon-service-o:before{content:"\F0AC"}.van-icon-service:before{content:"\F0AD"}.van-icon-setting-o:before{content:"\F0AE"}.van-icon-setting:before{content:"\F0AF"}.van-icon-share:before{content:"\F0B0"}.van-icon-shop-collect-o:before{content:"\F0B1"}.van-icon-shop-collect:before{content:"\F0B2"}.van-icon-shop-o:before{content:"\F0B3"}.van-icon-shop:before{content:"\F0B4"}.van-icon-shopping-cart-o:before{content:"\F0B5"}.van-icon-shopping-cart:before{content:"\F0B6"}.van-icon-shrink:before{content:"\F0B7"}.van-icon-sign:before{content:"\F0B8"}.van-icon-smile-comment-o:before{content:"\F0B9"}.van-icon-smile-comment:before{content:"\F0BA"}.van-icon-smile-o:before{content:"\F0BB"}.van-icon-star-o:before{content:"\F0BC"}.van-icon-star:before{content:"\F0BD"}.van-icon-stop-circle-o:before{content:"\F0BE"}.van-icon-stop-circle:before{content:"\F0BF"}.van-icon-stop:before{content:"\F0C0"}.van-icon-success:before{content:"\F0C1"}.van-icon-thumb-circle-o:before{content:"\F0C2"}.van-icon-todo-list-o:before{content:"\F0C3"}.van-icon-todo-list:before{content:"\F0C4"}.van-icon-tosend:before{content:"\F0C5"}.van-icon-tv-o:before{content:"\F0C6"}.van-icon-umbrella-circle:before{content:"\F0C7"}.van-icon-underway-o:before{content:"\F0C8"}.van-icon-underway:before{content:"\F0C9"}.van-icon-upgrade:before{content:"\F0CA"}.van-icon-user-circle-o:before{content:"\F0CB"}.van-icon-user-o:before{content:"\F0CC"}.van-icon-video-o:before{content:"\F0CD"}.van-icon-video:before{content:"\F0CE"}.van-icon-vip-card-o:before{content:"\F0CF"}.van-icon-vip-card:before{content:"\F0D0"}.van-icon-volume-o:before{content:"\F0D1"}.van-icon-volume:before{content:"\F0D2"}.van-icon-wap-home:before{content:"\F0D3"}.van-icon-wap-nav:before{content:"\F0D4"}.van-icon-warn-o:before{content:"\F0D5"}.van-icon-warning-o:before{content:"\F0D6"}.van-icon-weapp-nav:before{content:"\F0D7"}.van-icon-wechat:before{content:"\F0D8"}.van-icon-youzan-shield:before{content:"\F0D9"}.van-icon--image{width:1em;height:1em}.van-icon__image{position:absolute;top:0;right:0;bottom:0;left:0;max-width:100%;max-height:100%;margin:auto}.van-icon__info{z-index:1}
\ No newline at end of file
@import '../common/index.wxss';@font-face{font-weight:400;font-family:vant-icon;font-style:normal;font-display:auto;src:url(https://img.yzcdn.cn/vant/vant-icon-0bc654.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-0bc654.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-0bc654.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-circle:before{content:"\F03A"}.van-icon-comment-o:before{content:"\F03B"}.van-icon-comment:before{content:"\F03C"}.van-icon-completed:before{content:"\F03D"}.van-icon-contact:before{content:"\F03E"}.van-icon-coupon-o:before{content:"\F03F"}.van-icon-coupon:before{content:"\F040"}.van-icon-credit-pay:before{content:"\F041"}.van-icon-cross:before{content:"\F042"}.van-icon-debit-pay:before{content:"\F043"}.van-icon-delete:before{content:"\F044"}.van-icon-descending:before{content:"\F045"}.van-icon-description:before{content:"\F046"}.van-icon-desktop-o:before{content:"\F047"}.van-icon-diamond-o:before{content:"\F048"}.van-icon-diamond:before{content:"\F049"}.van-icon-discount:before{content:"\F04A"}.van-icon-down:before{content:"\F04B"}.van-icon-ecard-pay:before{content:"\F04C"}.van-icon-edit:before{content:"\F04D"}.van-icon-ellipsis:before{content:"\F04E"}.van-icon-empty:before{content:"\F04F"}.van-icon-envelop-o:before{content:"\F050"}.van-icon-exchange:before{content:"\F051"}.van-icon-expand-o:before{content:"\F052"}.van-icon-expand:before{content:"\F053"}.van-icon-eye-o:before{content:"\F054"}.van-icon-eye:before{content:"\F055"}.van-icon-fail:before{content:"\F056"}.van-icon-failure:before{content:"\F057"}.van-icon-filter-o:before{content:"\F058"}.van-icon-fire-o:before{content:"\F059"}.van-icon-fire:before{content:"\F05A"}.van-icon-flag-o:before{content:"\F05B"}.van-icon-flower-o:before{content:"\F05C"}.van-icon-free-postage:before{content:"\F05D"}.van-icon-friends-o:before{content:"\F05E"}.van-icon-friends:before{content:"\F05F"}.van-icon-gem-o:before{content:"\F060"}.van-icon-gem:before{content:"\F061"}.van-icon-gift-card-o:before{content:"\F062"}.van-icon-gift-card:before{content:"\F063"}.van-icon-gift-o:before{content:"\F064"}.van-icon-gift:before{content:"\F065"}.van-icon-gold-coin-o:before{content:"\F066"}.van-icon-gold-coin:before{content:"\F067"}.van-icon-good-job-o:before{content:"\F068"}.van-icon-good-job:before{content:"\F069"}.van-icon-goods-collect-o:before{content:"\F06A"}.van-icon-goods-collect:before{content:"\F06B"}.van-icon-graphic:before{content:"\F06C"}.van-icon-home-o:before{content:"\F06D"}.van-icon-hot-o:before{content:"\F06E"}.van-icon-hot-sale-o:before{content:"\F06F"}.van-icon-hot-sale:before{content:"\F070"}.van-icon-hot:before{content:"\F071"}.van-icon-hotel-o:before{content:"\F072"}.van-icon-idcard:before{content:"\F073"}.van-icon-info-o:before{content:"\F074"}.van-icon-info:before{content:"\F075"}.van-icon-invition:before{content:"\F076"}.van-icon-label-o:before{content:"\F077"}.van-icon-label:before{content:"\F078"}.van-icon-like-o:before{content:"\F079"}.van-icon-like:before{content:"\F07A"}.van-icon-live:before{content:"\F07B"}.van-icon-location-o:before{content:"\F07C"}.van-icon-location:before{content:"\F07D"}.van-icon-lock:before{content:"\F07E"}.van-icon-logistics:before{content:"\F07F"}.van-icon-manager-o:before{content:"\F080"}.van-icon-manager:before{content:"\F081"}.van-icon-map-marked:before{content:"\F082"}.van-icon-medel-o:before{content:"\F083"}.van-icon-medel:before{content:"\F084"}.van-icon-more-o:before{content:"\F085"}.van-icon-more:before{content:"\F086"}.van-icon-music-o:before{content:"\F087"}.van-icon-music:before{content:"\F088"}.van-icon-new-arrival-o:before{content:"\F089"}.van-icon-new-arrival:before{content:"\F08A"}.van-icon-new-o:before{content:"\F08B"}.van-icon-new:before{content:"\F08C"}.van-icon-newspaper-o:before{content:"\F08D"}.van-icon-notes-o:before{content:"\F08E"}.van-icon-orders-o:before{content:"\F08F"}.van-icon-other-pay:before{content:"\F090"}.van-icon-paid:before{content:"\F091"}.van-icon-passed:before{content:"\F092"}.van-icon-pause-circle-o:before{content:"\F093"}.van-icon-pause-circle:before{content:"\F094"}.van-icon-pause:before{content:"\F095"}.van-icon-peer-pay:before{content:"\F096"}.van-icon-pending-payment:before{content:"\F097"}.van-icon-phone-circle-o:before{content:"\F098"}.van-icon-phone-circle:before{content:"\F099"}.van-icon-phone-o:before{content:"\F09A"}.van-icon-phone:before{content:"\F09B"}.van-icon-photo-o:before{content:"\F09C"}.van-icon-photo:before{content:"\F09D"}.van-icon-photograph:before{content:"\F09E"}.van-icon-play-circle-o:before{content:"\F09F"}.van-icon-play-circle:before{content:"\F0A0"}.van-icon-play:before{content:"\F0A1"}.van-icon-plus:before{content:"\F0A2"}.van-icon-point-gift-o:before{content:"\F0A3"}.van-icon-point-gift:before{content:"\F0A4"}.van-icon-points:before{content:"\F0A5"}.van-icon-printer:before{content:"\F0A6"}.van-icon-qr-invalid:before{content:"\F0A7"}.van-icon-qr:before{content:"\F0A8"}.van-icon-question-o:before{content:"\F0A9"}.van-icon-question:before{content:"\F0AA"}.van-icon-records:before{content:"\F0AB"}.van-icon-refund-o:before{content:"\F0AC"}.van-icon-replay:before{content:"\F0AD"}.van-icon-scan:before{content:"\F0AE"}.van-icon-search:before{content:"\F0AF"}.van-icon-send-gift-o:before{content:"\F0B0"}.van-icon-send-gift:before{content:"\F0B1"}.van-icon-service-o:before{content:"\F0B2"}.van-icon-service:before{content:"\F0B3"}.van-icon-setting-o:before{content:"\F0B4"}.van-icon-setting:before{content:"\F0B5"}.van-icon-share:before{content:"\F0B6"}.van-icon-shop-collect-o:before{content:"\F0B7"}.van-icon-shop-collect:before{content:"\F0B8"}.van-icon-shop-o:before{content:"\F0B9"}.van-icon-shop:before{content:"\F0BA"}.van-icon-shopping-cart-o:before{content:"\F0BB"}.van-icon-shopping-cart:before{content:"\F0BC"}.van-icon-shrink:before{content:"\F0BD"}.van-icon-sign:before{content:"\F0BE"}.van-icon-smile-comment-o:before{content:"\F0BF"}.van-icon-smile-comment:before{content:"\F0C0"}.van-icon-smile-o:before{content:"\F0C1"}.van-icon-smile:before{content:"\F0C2"}.van-icon-star-o:before{content:"\F0C3"}.van-icon-star:before{content:"\F0C4"}.van-icon-stop-circle-o:before{content:"\F0C5"}.van-icon-stop-circle:before{content:"\F0C6"}.van-icon-stop:before{content:"\F0C7"}.van-icon-success:before{content:"\F0C8"}.van-icon-thumb-circle-o:before{content:"\F0C9"}.van-icon-thumb-circle:before{content:"\F0CA"}.van-icon-todo-list-o:before{content:"\F0CB"}.van-icon-todo-list:before{content:"\F0CC"}.van-icon-tosend:before{content:"\F0CD"}.van-icon-tv-o:before{content:"\F0CE"}.van-icon-umbrella-circle:before{content:"\F0CF"}.van-icon-underway-o:before{content:"\F0D0"}.van-icon-underway:before{content:"\F0D1"}.van-icon-upgrade:before{content:"\F0D2"}.van-icon-user-circle-o:before{content:"\F0D3"}.van-icon-user-o:before{content:"\F0D4"}.van-icon-video-o:before{content:"\F0D5"}.van-icon-video:before{content:"\F0D6"}.van-icon-vip-card-o:before{content:"\F0D7"}.van-icon-vip-card:before{content:"\F0D8"}.van-icon-volume-o:before{content:"\F0D9"}.van-icon-volume:before{content:"\F0DA"}.van-icon-wap-home-o:before{content:"\F0DB"}.van-icon-wap-home:before{content:"\F0DC"}.van-icon-wap-nav:before{content:"\F0DD"}.van-icon-warn-o:before{content:"\F0DE"}.van-icon-warning-o:before{content:"\F0DF"}.van-icon-warning:before{content:"\F0E0"}.van-icon-weapp-nav:before{content:"\F0E1"}.van-icon-wechat:before{content:"\F0E2"}.van-icon-youzan-shield:before{content:"\F0E3"}:host{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-icon--image{width:1em;height:1em}.van-icon__image{width:100%;height:100%}.van-icon__info{z-index:1}
\ No newline at end of file
......
import { addUnit, isDef } from '../common/utils';
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: String,
width: String,
height: String,
fit: {
type: String,
value: 'fill'
},
round: Boolean,
lazyLoad: Boolean,
showError: {
type: Boolean,
value: true
},
showLoading: {
type: Boolean,
value: true
},
showMenuByLongpress: Boolean,
// 受小程序slot限制所需要的属性
useLoadingSlot: Boolean,
useErrorSlot: Boolean,
},
data: {
fitWeapp: 'aspectFit',
FIT_MODE_MAP: {
contain: 'aspectFit',
cover: 'aspectFill',
fill: 'scaleToFill',
none: 'center',
// TODO: 这个没有原生的属性,需要后面实现,暂时先用contain;
'scale-down': 'aspectFit'
},
loading: true,
error: false
},
watch: {
src() {
this.setData({
loading: true,
error: false
});
}
},
mounted() {
this.init();
},
methods: {
init() {
const { FIT_MODE_MAP, fit } = this.data;
this.setData({
mode: FIT_MODE_MAP[fit],
style: this.getStyle(),
});
},
getStyle() {
const { width, height } = this.data;
let style = '';
if (isDef(width)) {
style += `width: ${addUnit(width)};`;
}
if (isDef(height)) {
style += `height: ${addUnit(height)};`;
}
return style;
},
onLoad(event) {
this.setData({
loading: false
});
this.$emit('load', event.detail);
},
onError(event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
},
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('image', { round })}}"
style="{{ style }}"
bind:tap="onClick"
>
<image
wx:if="{{ !error }}"
class="image-class van-image__img"
mode="{{ mode }}"
src="{{ src }}"
lazy-load="{{ lazyLoad }}"
show-menu-by-longpress="{{ showMenuByLongpress }}"
bind:load="onLoad"
bind:error="onError"
/>
<view
wx:if="{{ loading && showLoading }}"
class="loading-class van-image__loading"
>
<slot
wx:if="{{ useLoadingSlot }}"
name="loading"
/>
<van-icon
wx:else
name="photo-o"
size="22"
/>
</view>
<view
wx:if="{{ error && showError }}"
class="error-class van-image__error"
>
<slot
wx:if="{{ useErrorSlot }}"
name="error"
/>
<van-icon
wx:else
name="warning-o"
size="22"
/>
</view>
</view>
@import '../common/index.wxss';.van-image{position:relative;display:inline-block}.van-image--round{overflow:hidden;border-radius:50%}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;width:100%;height:100%}.van-image__error,.van-image__loading{position:absolute;top:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#969799;color:var(--image-placeholder-text-color,#969799);font-size:14px;font-size:var(--image-placeholder-font-size,14px);background-color:#f8f8f8;background-color:var(--image-placeholder-background-color,#f8f8f8)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'index-bar',
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
},
props: {
useSlot: Boolean,
index: null
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: ''
}
});
<view
class="van-index-anchor-wrapper"
style="{{ wrapperStyle }}"
>
<view
class="van-index-anchor {{ active ? 'van-index-anchor--active van-hairline--bottom' : '' }}"
style="{{ anchorStyle }}"
>
<slot wx:if="{{ useSlot }}"/>
<block wx:else>
<text>{{ index }}</text>
</block>
</view>
</view>
@import '../common/index.wxss';.van-index-anchor{padding:0 16px;padding:var(--index-anchor-padding,0 16px);color:#323233;color:var(--index-anchor-text-color,#323233);font-weight:500;font-weight:var(--index-anchor-font-weight,500);font-size:14px;font-size:var(--index-anchor-font-size,14px);line-height:32px;line-height:var(--index-anchor-line-height,32px);background-color:initial;background-color:var(--index-anchor-background-color,transparent)}.van-index-anchor--active{right:0;left:0;color:#07c160;color:var(--index-anchor-active-text-color,#07c160);background-color:#fff;background-color:var(--index-anchor-active-background-color,#fff)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { GREEN } from '../common/color';
const indexList = () => {
const indexList = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
VantComponent({
relation: {
name: 'index-anchor',
type: 'descendant',
linked() {
this.updateData();
},
linkChanged() {
this.updateData();
},
unlinked() {
this.updateData();
}
},
props: {
sticky: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 1
},
highlightColor: {
type: String,
value: GREEN
},
scrollTop: {
type: Number,
value: 0,
observer: 'onScroll'
},
stickyOffsetTop: {
type: Number,
value: 0
},
indexList: {
type: Array,
value: indexList()
}
},
data: {
activeAnchorIndex: null,
showSidebar: false
},
methods: {
updateData() {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.children = this.getRelationNodes('../index-anchor/index');
this.setData({
showSidebar: !!this.children.length
});
this.setRect().then(() => {
this.onScroll();
});
}, 0);
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect()
]);
},
setAnchorsRect() {
return Promise.all(this.children.map(anchor => (anchor.getRect('.van-index-anchor-wrapper').then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top + this.data.scrollTop
});
}))));
},
setListRect() {
return this.getRect('.van-index-bar').then((rect) => {
Object.assign(this, {
height: rect.height,
top: rect.top + this.data.scrollTop
});
});
},
setSiderbarRect() {
return this.getRect('.van-index-bar__sidebar').then(res => {
this.sidebar = {
height: res.height,
top: res.top
};
});
},
setDiffData({ target, data }) {
const diffData = {};
Object.keys(data).forEach(key => {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect(anchor) {
return anchor.getRect('.van-index-anchor-wrapper').then((rect) => ({
height: rect.height,
top: rect.top
}));
},
getActiveAnchorIndex() {
const { children } = this;
const { sticky, scrollTop, stickyOffsetTop } = this.data;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const { children = [] } = this;
if (!children.length) {
return;
}
const { sticky, stickyOffsetTop, zIndex, highlightColor, scrollTop } = this.data;
const active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active
}
});
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky = children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = `
color: ${highlightColor};
`;
if (isActiveAnchorSticky) {
wrapperStyle = `
height: ${children[index].height}px;
`;
anchorStyle = `
position: fixed;
top: ${stickyOffsetTop}px;
z-index: ${zIndex};
color: ${highlightColor};
`;
}
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
wrapperStyle
}
});
}
else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop = index === children.length - 1
? this.top
: children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = `
position: relative;
transform: translate3d(0, ${translateY}px, 0);
z-index: ${zIndex};
color: ${highlightColor};
`;
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle
}
});
}
else {
this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
}
});
}
});
}
},
onClick(event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove(event) {
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
}
else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop() {
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.filter(item => item.data.index === this.data.indexList[index])[0];
this.$emit('select', anchor.data.index);
anchor && wx.pageScrollTo({
duration: 0,
scrollTop: anchor.top
});
}
}
});
<view class="van-index-bar">
<slot />
<view
wx:if="{{ showSidebar }}"
class="van-index-bar__sidebar"
catch:tap="onClick"
catch:touchmove="onTouchMove"
catch:touchend="onTouchStop"
catch:touchcancel="onTouchStop"
>
<view
wx:for="{{ indexList }}"
wx:key="index"
class="van-index-bar__index"
style="z-index: {{ zIndex + 1 }}; color: {{ activeAnchorIndex === index ? highlightColor : '' }}"
data-index="{{ index }}"
>
{{ item }}
</view>
</view>
</view>
@import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{position:fixed;top:50%;right:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;text-align:center;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-weight:500;padding:0 4px 0 16px;padding:0 var(--padding-base,4px) 0 var(--padding-md,16px);font-size:10px;font-size:var(--index-bar-index-font-size,10px);line-height:14px;line-height:var(--index-bar-index-line-height,14px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
dot: Boolean,
info: null,
customStyle: String
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ info !== null }}"
class="custom-class van-info"
wx:if="{{ info !== null && info !== '' || dot }}"
class="custom-class van-info {{ utils.bem('info', { dot }) }}"
style="{{ customStyle }}"
>{{ info }}</view>
>{{ dot ? '' : info }}</view>
......
@import '../common/index.wxss';.van-info{position:absolute;top:-8px;right:0;min-width:16px;padding:0 3px;font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:12px;font-weight:500;line-height:14px;color:#fff;text-align:center;white-space:nowrap;background-color:#f44;border:1px solid #fff;border-radius:16px;-webkit-transform:translateX(50%);transform:translateX(50%);box-sizing:border-box;-webkit-transform-origin:100%;transform-origin:100%}
\ No newline at end of file
@import '../common/index.wxss';.van-info{position:absolute;top:0;right:0;box-sizing:border-box;white-space:nowrap;text-align:center;-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%);-webkit-transform-origin:100%;transform-origin:100%;min-width:16px;min-width:var(--info-size,16px);padding:0 3px;padding:var(--info-padding,0 3px);color:#fff;color:var(--info-color,#fff);font-weight:500;font-weight:var(--info-font-weight,500);font-size:12px;font-size:var(--info-font-size,12px);font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--info-font-family,PingFang SC,Helvetica Neue,Arial,sans-serif);line-height:14px;line-height:calc(var(--info-size, 16px) - var(--info-border-width, 1px)*2);background-color:#ee0a24;background-color:var(--info-background-color,#ee0a24);border:1px solid #fff;border:var(--info-border-width,1px) solid var(--white,#fff);border-radius:16px;border-radius:var(--info-size,16px)}.van-info--dot{min-width:0;border-radius:100%;width:8px;width:var(--info-dot-size,8px);height:8px;height:var(--info-dot-size,8px);background-color:#ee0a24;background-color:var(--info-dot-color,#ee0a24)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
props: {
size: {
type: String,
value: '30px'
},
color: String,
vertical: Boolean,
type: {
type: String,
value: 'circular'
},
color: {
size: {
type: String,
value: '#c9c9c9'
observer: 'setSizeWithUnit'
},
textSize: {
type: String,
observer: 'setTextSizeWithUnit'
}
},
methods: {
setSizeWithUnit(size) {
this.setData({
sizeWithUnit: addUnit(size)
});
},
setTextSizeWithUnit(size) {
this.set({
textSizeWithUnit: addUnit(size)
});
}
}
});
......
<view
class="van-loading custom-class"
style="width: {{ size }}; height: {{ size }}"
>
<view class="custom-class van-loading {{ vertical ? 'van-loading--vertical' : '' }}">
<view
class="van-loading__spinner van-loading__spinner--{{ type }}"
style="color: {{ color }};"
style="color: {{ color }}; width: {{ sizeWithUnit }}; height: {{ sizeWithUnit }}"
>
<view
wx:if="{{ type === 'spinner' }}"
......@@ -13,4 +10,7 @@
class="van-loading__dot"
/>
</view>
<view class="van-loading__text" style="font-size: {{ textSizeWithUnit }};">
<slot />
</view>
</view>
......
@import '../common/index.wxss';.van-loading{z-index:0;line-height:0;vertical-align:middle}.van-loading,.van-loading__spinner{position:relative;display:inline-block}.van-loading__spinner{z-index:-1;width:100%;height:100%;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border-radius:100%;border:1px solid transparent;border-top-color:initial}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot:before{width:2px;height:25%;content:" ";display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:first-of-type{opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(1turn);transform:rotate(1turn)}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
\ No newline at end of file
@import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#c8c9cc;color:var(--loading-spinner-color,#c8c9cc)}.van-loading__spinner{position:relative;box-sizing:border-box;width:30px;width:var(--loading-spinner-size,30px);max-width:100%;max-height:100%;height:30px;height:var(--loading-spinner-size,30px);-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite;-webkit-animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-top-color:initial;border-radius:100%}.van-loading__text{margin-left:8px;margin-left:var(--padding-xs,8px);color:#969799;color:var(--loading-text-color,#969799);font-size:14px;font-size:var(--loading-text-font-size,14px);line-height:20px;line-height:var(--loading-text-line-height,20px)}.van-loading__text:empty{display:none}.van-loading--vertical{-webkit-flex-direction:column;flex-direction:column}.van-loading--vertical .van-loading__text{margin:8px 0 0;margin:var(--padding-xs,8px) 0 0}.van-loading__dot{position:absolute;top:0;left:0;width:100%;height:100%}.van-loading__dot:before{display:block;width:2px;height:25%;margin:0 auto;background-color:currentColor;border-radius:40%;content:" "}.van-loading__dot:first-of-type{-webkit-transform:rotate(30deg);transform:rotate(30deg);opacity:1}.van-loading__dot:nth-of-type(2){-webkit-transform:rotate(60deg);transform:rotate(60deg);opacity:.9375}.van-loading__dot:nth-of-type(3){-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:.875}.van-loading__dot:nth-of-type(4){-webkit-transform:rotate(120deg);transform:rotate(120deg);opacity:.8125}.van-loading__dot:nth-of-type(5){-webkit-transform:rotate(150deg);transform:rotate(150deg);opacity:.75}.van-loading__dot:nth-of-type(6){-webkit-transform:rotate(180deg);transform:rotate(180deg);opacity:.6875}.van-loading__dot:nth-of-type(7){-webkit-transform:rotate(210deg);transform:rotate(210deg);opacity:.625}.van-loading__dot:nth-of-type(8){-webkit-transform:rotate(240deg);transform:rotate(240deg);opacity:.5625}.van-loading__dot:nth-of-type(9){-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:.5}.van-loading__dot:nth-of-type(10){-webkit-transform:rotate(300deg);transform:rotate(300deg);opacity:.4375}.van-loading__dot:nth-of-type(11){-webkit-transform:rotate(330deg);transform:rotate(330deg);opacity:.375}.van-loading__dot:nth-of-type(12){-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:.3125}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
\ No newline at end of file
......
export declare const basic: void;
export declare const basic: string;
......
export const basic = Behavior({
methods: {
$emit() {
this.triggerEvent.apply(this, arguments);
$emit(...args) {
this.triggerEvent(...args);
},
getRect(selector, all) {
return new Promise(resolve => {
......
export declare const button: void;
export declare const button: string;
......
export declare const link: void;
export declare const link: string;
......
export declare const behavior: void;
export declare const behavior: string;
......
function setAsync(context, data) {
return new Promise(resolve => {
context.setData(data, resolve);
});
}
;
export const behavior = Behavior({
created() {
if (!this.$options) {
return;
}
const cache = {};
const { computed } = this.$options();
const keys = Object.keys(computed);
this.calcComputed = () => {
const needUpdate = {};
keys.forEach(key => {
const value = computed[key].call(this);
if (cache[key] !== value) {
cache[key] = needUpdate[key] = value;
}
});
return needUpdate;
};
},
attached() {
this.set();
},
methods: {
// set data and set computed data
set(data, callback) {
const stack = [];
if (data) {
stack.push(setAsync(this, data));
}
if (this.calcComputed) {
stack.push(setAsync(this, this.calcComputed()));
}
return Promise.all(stack).then(res => {
return new Promise(resolve => {
this.setData(data, () => {
if (callback && typeof callback === 'function') {
callback.call(this);
}
return res;
resolve();
});
});
}
}
......
import { behavior } from './behavior';
import { observeProps } from './props';
export function observe(vantOptions, options) {
const { watch, computed } = vantOptions;
const { watch } = vantOptions;
options.behaviors.push(behavior);
if (watch) {
const props = options.properties || {};
......@@ -17,11 +16,4 @@ export function observe(vantOptions, options) {
});
options.properties = props;
}
if (computed) {
options.methods = options.methods || {};
options.methods.$options = () => vantOptions;
if (options.properties) {
observeProps(options.properties);
}
}
}
......
export declare function observeProps(props: any): void;
export function observeProps(props) {
if (!props) {
return;
}
Object.keys(props).forEach(key => {
let prop = props[key];
if (prop === null || !('type' in prop)) {
prop = { type: prop };
}
let { observer } = prop;
prop.observer = function () {
if (observer) {
if (typeof observer === 'string') {
observer = this[observer];
}
observer.apply(this, arguments);
}
this.set();
};
props[key] = prop;
});
}
export declare const openType: void;
export declare const openType: string;
......
export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
safeAreaInsetBottom?: boolean;
safeAreaInsetTop?: boolean;
}) => void;
let cache = null;
function getSafeArea() {
return new Promise((resolve, reject) => {
if (cache != null) {
resolve(cache);
}
else {
wx.getSystemInfo({
success: ({ model, screenHeight, statusBarHeight }) => {
const iphoneX = /iphone x/i.test(model);
const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
cache = {
isIPhoneX: iphoneX || iphoneNew,
statusBarHeight
};
resolve(cache);
},
fail: reject
});
}
});
}
export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
properties: {
safeAreaInsetTop: {
type: Boolean,
value: safeAreaInsetTop
},
safeAreaInsetBottom: {
type: Boolean,
value: safeAreaInsetBottom
}
},
created() {
getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
this.set({ isIPhoneX, statusBarHeight });
});
}
});
export declare const touch: void;
export declare const touch: string;
......
export declare const transition: (showDefaultValue: boolean) => void;
export declare const transition: (showDefaultValue: boolean) => any;
......
......@@ -10,85 +10,109 @@ export const transition = function (showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
// @ts-ignore
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow'
},
// @ts-ignore
duration: {
type: [Number, Object],
type: null,
value: 300,
observer: 'observeDuration'
},
name: {
type: String,
value: 'fade',
observer: 'updateClasses'
value: 'fade'
}
},
data: {
type: '',
inited: false,
display: false,
classNames: getClassNames('fade')
display: false
},
attached() {
if (this.data.show) {
this.show();
this.enter();
}
},
methods: {
observeShow(value) {
if (value) {
this.show();
}
else {
this.leave();
}
},
updateClasses(name) {
this.set({
classNames: getClassNames(name)
});
value ? this.enter() : this.leave();
},
show() {
const { classNames, duration } = this.data;
const currentDuration = isObj(duration) ? duration.leave : duration;
enter() {
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.enter : duration;
this.status = 'enter';
this.$emit('before-enter');
Promise.resolve()
.then(nextTick)
.then(() => this.set({
.then(() => {
this.checkStatus('enter');
this.$emit('enter');
this.setData({
inited: true,
display: true,
classes: classNames.enter,
currentDuration
}))
});
})
.then(nextTick)
.then(() => this.set({
.then(() => {
this.checkStatus('enter');
this.transitionEnded = false;
this.setData({
classes: classNames['enter-to']
}));
});
})
.catch(() => { });
},
leave() {
const { classNames, duration } = this.data;
const currentDuration = isObj(duration) ? duration.leave : duration;
if (+currentDuration === 0) {
this.onTransitionEnd();
if (!this.data.display) {
return;
}
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.leave : duration;
this.status = 'leave';
this.$emit('before-leave');
Promise.resolve()
.then(nextTick)
.then(() => this.set({
.then(() => {
this.checkStatus('leave');
this.$emit('leave');
this.setData({
classes: classNames.leave,
currentDuration
}))
});
})
.then(nextTick)
.then(() => this.set({
.then(() => {
this.checkStatus('leave');
this.transitionEnded = false;
setTimeout(() => this.onTransitionEnd(), currentDuration);
this.setData({
classes: classNames['leave-to']
}));
});
})
.catch(() => { });
},
checkStatus(status) {
if (status !== this.status) {
throw new Error(`incongruent status: ${status}`);
}
},
onTransitionEnd() {
if (!this.data.show) {
this.set({ display: false });
this.$emit('transitionEnd');
if (this.transitionEnded) {
return;
}
this.transitionEnded = true;
this.$emit(`after-${this.status}`);
const { show, display } = this.data;
if (!show && display) {
this.setData({ display: false });
}
}
}
......
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea({ safeAreaInsetTop: true })],
classes: ['title-class'],
props: {
title: String,
......@@ -15,8 +13,19 @@ VantComponent({
},
zIndex: {
type: Number,
value: 120
}
value: 1
},
safeAreaInsetTop: {
type: Boolean,
value: true
},
},
data: {
statusBarHeight: 0
},
created() {
const { statusBarHeight } = wx.getSystemInfoSync();
this.setData({ statusBarHeight });
},
methods: {
onClickLeft() {
......
......@@ -2,7 +2,7 @@
<view
class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}"
style="z-index: {{ zIndex }}; padding-top: {{ safeAreaInsetTop ? statusBarHeight : 0 }}px;"
>
<view class="van-nav-bar__left" bind:tap="onClickLeft">
<block wx:if="{{ leftArrow || leftText }}">
......
@import '../common/index.wxss';.van-nav-bar{position:relative;height:44px;line-height:44px;text-align:center;background-color:#fff;-webkit-user-select:none;user-select:none}.van-nav-bar__text{display:inline-block;padding:0 15px;margin:0 -15px;color:#1989fa;vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:#1989fa;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{padding-left:25px;margin-left:-20px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;font-size:16px;font-weight:500}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px}
\ No newline at end of file
@import '../common/index.wxss';.van-nav-bar{position:relative;text-align:center;-webkit-user-select:none;user-select:none;height:44px;height:var(--nav-bar-height,44px);line-height:44px;line-height:var(--nav-bar-height,44px);background-color:#fff;background-color:var(--nav-bar-background-color,#fff)}.van-nav-bar__text{display:inline-block;vertical-align:middle;margin:0 -16px;margin:0 -var(--padding-md,16px);padding:0 16px;padding:0 var(--padding-md,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__text--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-nav-bar__arrow{vertical-align:middle;font-size:16px;font-size:var(--nav-bar-arrow-size,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;color:#323233;color:var(--nav-bar-title-text-color,#323233);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--nav-bar-title-font-size,16px)}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px;font-size:var(--font-size-md,14px)}.van-nav-bar__left{left:16px;left:var(--padding-md,16px)}.van-nav-bar__right{right:16px;right:var(--padding-md,16px)}
\ No newline at end of file
......
......@@ -21,7 +21,7 @@ VantComponent({
},
delay: {
type: Number,
value: 0
value: 1
},
speed: {
type: Number,
......@@ -42,23 +42,18 @@ VantComponent({
backgroundColor: {
type: String,
value: BG_COLOR
}
},
wrapable: Boolean
},
data: {
show: true,
hasRightIcon: false
show: true
},
watch: {
text() {
this.set({}, this.init);
this.setData({}, this.init);
}
},
created() {
if (this.data.mode) {
this.set({
hasRightIcon: true
});
}
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear'
......@@ -71,7 +66,7 @@ VantComponent({
init() {
Promise.all([
this.getRect('.van-notice-bar__content'),
this.getRect('.van-notice-bar__content-wrap')
this.getRect('.van-notice-bar__wrap')
]).then((rects) => {
const [contentRect, wrapRect] = rects;
if (contentRect == null ||
......@@ -98,14 +93,14 @@ VantComponent({
scroll() {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.set({
this.setData({
animationData: this.resetAnimation
.translateX(this.wrapWidth)
.step()
.export()
});
setTimeout(() => {
this.set({
this.setData({
animationData: this.animation
.translateX(-this.contentWidth)
.step()
......@@ -119,7 +114,7 @@ VantComponent({
onClickIcon() {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.set({ show: false });
this.setData({ show: false });
},
onClick(event) {
this.$emit('click', event);
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ show }}"
class="custom-class van-notice-bar {{ hasRightIcon ? 'van-notice-bar--within-icon' : '' }}"
class="custom-class {{ utils.bem('notice-bar', { withicon: mode, wrapable }) }}"
style="color: {{ color }}; background-color: {{ backgroundColor }};"
bind:tap="onClick"
>
<view wx:if="{{ leftIcon }}" class="van-notice-bar__left-icon">
<image src="{{ leftIcon }}" />
</view>
<view class="van-notice-bar__content-wrap">
<view class="van-notice-bar__content {{ scrollable ? '' : 'van-ellipsis' }}" animation="{{ animationData }}">
<van-icon
wx:if="{{ leftIcon }}"
size="16px"
name="{{ leftIcon }}"
class="van-notice-bar__left-icon"
/>
<slot wx:else name="left-icon" />
<view class="van-notice-bar__wrap">
<view class="van-notice-bar__content {{ !scrollable && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}">
{{ text }}
</view>
</view>
......@@ -17,13 +24,14 @@
wx:if="{{ mode === 'closeable' }}"
class="van-notice-bar__right-icon"
name="cross"
bind:tap="onClickIcon"
catch:tap="onClickIcon"
/>
<navigator
wx:if="{{ mode === 'link' }}"
wx:elif="{{ mode === 'link' }}"
url="{{ url }}"
open-type="{{ openType }}"
>
<van-icon class="van-notice-bar__right-icon" name="arrow" />
</navigator>
<slot wx:else name="right-icon" />
</view>
......
@import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;height:40px;padding:0 15px;font-size:14px;line-height:24px;-webkit-align-items:center;align-items:center}.van-notice-bar--within-icon{position:relative;padding-right:40px}.van-notice-bar__left-icon{height:18px;min-width:20px;box-sizing:border-box}.van-notice-bar__left-icon>image{width:16px;height:16px}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px;font-size:16px}.van-notice-bar__content-wrap{position:relative;height:24px;overflow:hidden;-webkit-flex:1;flex:1}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
\ No newline at end of file
@import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:40px;height:var(--notice-bar-height,40px);padding:0 16px;padding:var(--notice-bar-padding,0 16px);font-size:14px;font-size:var(--notice-bar-font-size,14px);color:#ed6a0c;color:var(--notice-bar-text-color,#ed6a0c);line-height:24px;line-height:var(--notice-bar-line-height,24px);background-color:#fffbe8;background-color:var(--notice-bar-background-color,#fffbe8)}.van-notice-bar--withicon{position:relative;padding-right:40px}.van-notice-bar--wrapable{height:auto;padding:8px 16px;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:16px;font-size:var(--notice-bar-icon-size,16px);min-width:22px;min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px}.van-notice-bar__wrap{position:relative;-webkit-flex:1;flex:1;overflow:hidden;height:24px;height:var(--notice-bar-line-height,24px)}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { RED } from '../common/color';
import { safeArea } from '../mixins/safe-area';
import { WHITE } from '../common/color';
VantComponent({
mixins: [safeArea()],
props: {
text: String,
color: {
message: String,
background: String,
type: {
type: String,
value: '#fff'
value: 'danger'
},
backgroundColor: {
color: {
type: String,
value: RED
value: WHITE
},
duration: {
type: Number,
value: 3000
},
zIndex: {
type: Number,
value: 110
},
safeAreaInsetTop: {
type: Boolean,
value: false
}
},
methods: {
show() {
const { duration } = this.data;
const { duration, onOpened } = this.data;
clearTimeout(this.timer);
this.set({
this.setData({
show: true
});
}, onOpened);
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
......@@ -32,10 +39,17 @@ VantComponent({
}
},
hide() {
const { onClose } = this.data;
clearTimeout(this.timer);
this.set({
this.setData({
show: false
});
}, onClose);
},
onTap(event) {
const { onClick } = this.data;
if (onClick) {
onClick(event.detail);
}
}
}
});
......
<van-transition
name="slide-down"
show="{{ show }}"
custom-class="van-notify"
custom-style="background-color:{{ backgroundColor }}; color: {{ color }};"
custom-class="van-notify__container"
custom-style="z-index: {{ zIndex }};"
bind:tap="onTap"
>
<view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view>
{{ text }}
<view
class="van-notify van-notify--{{ type }}"
style="background:{{ background }};color:{{ color }};"
>
<view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-area"></view>
<text>{{ message }}</text>
</view>
</van-transition>
......
@import '../common/index.wxss';.van-notify{position:fixed;top:0;z-index:110;width:100%;padding:6px 15px;font-size:14px;line-height:20px;text-align:center;word-break:break-all;box-sizing:border-box}.van-notify__safe-top{height:44px}
\ No newline at end of file
@import '../common/index.wxss';.van-notify{text-align:center;word-wrap:break-word;padding:6px 15px;padding:var(--notify-padding,6px 15px);font-size:14px;font-size:var(--notify-font-size,14px);line-height:20px;line-height:var(--notify-line-height,20px)}.van-notify__container{position:fixed;top:0;box-sizing:border-box;width:100%}.van-notify__safe-area{height:constant(safe-area-inset-top);height:env(safe-area-inset-top)}.van-notify--primary{background-color:#1989fa;background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:#07c160;background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:#ee0a24;background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:#ff976a;background-color:var(--notify-warning-background-color,#ff976a)}
\ No newline at end of file
......
declare type NotifyOptions = {
text: string;
interface NotifyOptions {
type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string;
backgroundColor?: string;
zIndex?: number;
message: string;
context?: any;
duration?: number;
selector?: string;
context?: any;
background?: string;
safeAreaInsetTop?: boolean;
};
onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
export default function Notify(options: NotifyOptions | string): void;
export {};
......
import { isObj } from '../common/utils';
import { WHITE } from '../common/color';
const defaultOptions = {
selector: '#van-notify',
duration: 3000
type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
color: WHITE,
safeAreaInsetTop: false,
onClick: () => { },
onOpened: () => { },
onClose: () => { }
};
function parseOptions(text) {
return isObj(text) ? text : { text };
function parseOptions(message) {
return typeof message === 'string' ? { message } : message;
}
function getContext() {
const pages = getCurrentPages();
......@@ -14,6 +23,7 @@ export default function Notify(options) {
options = Object.assign({}, defaultOptions, parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (notify) {
notify.set(options);
......
......@@ -2,10 +2,9 @@ import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
customStyle: String,
duration: {
type: [Number, Object],
type: null,
value: 300
},
zIndex: {
......
<van-transition
show="{{ show }}"
custom-class="van-overlay"
custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}"
custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
duration="{{ duration }}"
bind:tap="onClick"
catch:touchmove="noop"
......
@import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0}
\ No newline at end of file
@import '../common/index.wxss';.van-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.7);background-color:var(--overlay-background-color,rgba(0,0,0,.7))}
\ No newline at end of file
......
@import '../common/index.wxss';.van-panel{background:#fff}.van-panel__header-value{color:#f44}.van-panel__footer{padding:10px 15px}
\ No newline at end of file
@import '../common/index.wxss';.van-panel{background:#fff;background:var(--panel-background-color,#fff)}.van-panel__header-value{color:#ee0a24;color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:8px 16px;padding:var(--panel-footer-padding,8px 16px)}
\ No newline at end of file
......
......@@ -34,31 +34,17 @@ VantComponent({
this.setIndex(defaultIndex);
});
},
computed: {
count() {
return this.data.options.length;
},
baseOffset() {
const { data } = this;
return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
},
wrapperStyle() {
const { data } = this;
return [
`transition: ${data.duration}ms`,
`transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
`line-height: ${data.itemHeight}px`
].join('; ');
}
},
watch: {
defaultIndex(value) {
this.setIndex(value);
}
},
methods: {
getCount() {
return this.data.options.length;
},
onTouchStart(event) {
this.set({
this.setData({
startY: event.touches[0].clientY,
startOffset: this.data.offset,
duration: 0
......@@ -67,17 +53,15 @@ VantComponent({
onTouchMove(event) {
const { data } = this;
const deltaY = event.touches[0].clientY - data.startY;
this.set({
offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight)
this.setData({
offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight)
});
},
onTouchEnd() {
const { data } = this;
if (data.offset !== data.startOffset) {
this.set({
duration: DEFAULT_DURATION
});
const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1);
this.setData({ duration: DEFAULT_DURATION });
const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
this.setIndex(index, true);
}
},
......@@ -87,8 +71,9 @@ VantComponent({
},
adjustIndex(index) {
const { data } = this;
index = range(index, 0, data.count);
for (let i = index; i < data.count; i++) {
const count = this.getCount();
index = range(index, 0, count);
for (let i = index; i < count; i++) {
if (!this.isDisabled(data.options[i]))
return i;
}
......@@ -115,9 +100,7 @@ VantComponent({
userAction && this.$emit('change', index);
});
}
else {
return this.set({ offset });
}
},
setValue(value) {
const { options } = this.data;
......
<wxs src="./index.wxs" module="getOptionText" />
<view
class="van-picker-column custom-class"
style="height: {{ itemHeight * visibleItemCount }}px"
......@@ -6,7 +8,7 @@
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<view style="{{ wrapperStyle }}">
<view style="transition: transform {{ duration }}ms; line-height: {{ itemHeight }}px; transform: translate3d(0, {{ offset + (itemHeight * (visibleItemCount - 1)) / 2 }}px, 0)">
<view
wx:for="{{ options }}"
wx:for-item="option"
......@@ -18,14 +20,3 @@
>{{ getOptionText(option, valueKey) }}</view>
</view>
</view>
<wxs module="getOptionText">
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
module.exports = function (option, valueKey) {
return isObj(option) && option[valueKey] ? option[valueKey] : option;
}
</wxs>
......
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
module.exports = function (option, valueKey) {
return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
}
@import '../common/index.wxss';.van-picker-column{overflow:hidden;font-size:16px;text-align:center}.van-picker-column__item{padding:0 5px;color:#999}.van-picker-column__item--selected{font-weight:500;color:#333}.van-picker-column__item--disabled{opacity:.3}
\ No newline at end of file
@import '../common/index.wxss';.van-picker-column{overflow:hidden;text-align:center;color:#000;color:var(--picker-option-text-color,#000);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--picker-option-selected-text-color,#323233)}.van-picker-column__item--disabled{opacity:.3;opacity:var(--picker-option-disabled-opacity,.3)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
function isSimple(columns) {
return columns.length && !columns[0].values;
}
import { pickerProps } from './shared';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
title: String,
loading: Boolean,
showToolbar: Boolean,
confirmButtonText: String,
cancelButtonText: String,
visibleItemCount: {
type: Number,
value: 5
},
valueKey: {
props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
type: String,
value: 'text'
},
itemHeight: {
}, toolbarPosition: {
type: String,
value: 'top'
}, defaultIndex: {
type: Number,
value: 44
},
columns: {
value: 0
}, columns: {
type: Array,
value: [],
observer(columns = []) {
this.simple = isSimple(columns);
this.simple = columns.length && !columns[0].values;
this.children = this.selectAllComponents('.van-picker__column');
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => { });
}
}
}
},
} }),
beforeCreate() {
this.children = [];
},
......@@ -89,7 +77,7 @@ VantComponent({
setColumnValue(index, value) {
const column = this.getColumn(index);
if (column == null) {
return Promise.reject('setColumnValue: 对应列不存在');
return Promise.reject(new Error('setColumnValue: 对应列不存在'));
}
return column.setValue(value);
},
......@@ -101,7 +89,7 @@ VantComponent({
setColumnIndex(columnIndex, optionIndex) {
const column = this.getColumn(columnIndex);
if (column == null) {
return Promise.reject('setColumnIndex: 对应列不存在');
return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
}
return column.setIndex(optionIndex);
},
......@@ -113,7 +101,7 @@ VantComponent({
setColumnValues(index, options, needReset = true) {
const column = this.children[index];
if (column == null) {
return Promise.reject('setColumnValues: 对应列不存在');
return Promise.reject(new Error('setColumnValues: 对应列不存在'));
}
const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) {
......
<view class="van-picker custom-class">
<template name="toolbar">
<view
wx:if="{{ showToolbar }}"
class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
......@@ -10,7 +10,7 @@
data-type="cancel"
bindtap="emit"
>
{{ cancelButtonText || '取消' }}
{{ cancelButtonText }}
</view>
<view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
<view
......@@ -20,9 +20,13 @@
data-type="confirm"
bindtap="emit"
>
{{ confirmButtonText || '确认' }}
{{ confirmButtonText }}
</view>
</view>
</template>
<view class="van-picker custom-class">
<template is="toolbar" wx:if="{{ toolbarPosition === 'top' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
<view wx:if="{{ loading }}" class="van-picker__loading">
<loading color="#1989fa"/>
</view>
......@@ -39,7 +43,7 @@
custom-class="column-class"
value-key="{{ valueKey }}"
initial-options="{{ isSimple(columns) ? item : item.values }}"
default-index="{{ item.defaultIndex }}"
default-index="{{ item.defaultIndex || defaultIndex }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
active-class="active-class"
......@@ -50,6 +54,7 @@
style="height: {{ itemHeight }}px"
/>
</view>
<template is="toolbar" wx:if="{{ toolbarPosition === 'bottom' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
</view>
<wxs module="isSimple">
......
@import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;background-color:#fff;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:-webkit-flex;display:flex;height:44px;line-height:44px;-webkit-justify-content:space-between;justify-content:space-between}.van-picker__cancel,.van-picker__confirm{padding:0 15px;font-size:14px;color:#1989fa}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5}.van-picker__title{max-width:50%;font-size:16px;font-weight:500;text-align:center}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;background-color:hsla(0,0%,100%,.9);-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;pointer-events:none;-webkit-transform:translateY(-50%);transform:translateY(-50%)}
\ No newline at end of file
@import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;-webkit-user-select:none;user-select:none;background-color:#fff;background-color:var(--picker-background-color,#fff)}.van-picker__toolbar{display:-webkit-flex;display:flex;-webkit-justify-content:space-between;justify-content:space-between;height:44px;height:var(--picker-toolbar-height,44px);line-height:44px;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#1989fa;color:var(--picker-action-text-color,#1989fa)}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5;background-color:var(--picker-action-active-color,#f2f3f5)}.van-picker__title{max-width:50%;text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background-color:hsla(0,0%,100%,.9);background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9))}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);pointer-events:none}
\ No newline at end of file
......
export declare const pickerProps: {
title: StringConstructor;
loading: BooleanConstructor;
showToolbar: BooleanConstructor;
cancelButtonText: {
type: StringConstructor;
value: string;
};
confirmButtonText: {
type: StringConstructor;
value: string;
};
visibleItemCount: {
type: NumberConstructor;
value: number;
};
itemHeight: {
type: NumberConstructor;
value: number;
};
};
export const pickerProps = {
title: String,
loading: Boolean,
showToolbar: Boolean,
cancelButtonText: {
type: String,
value: '取消'
},
confirmButtonText: {
type: String,
value: '确认'
},
visibleItemCount: {
type: Number,
value: 5
},
itemHeight: {
type: Number,
value: 44
}
};
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
import { safeArea } from '../mixins/safe-area';
VantComponent({
classes: [
'enter-class',
......@@ -10,14 +9,16 @@ VantComponent({
'leave-active-class',
'leave-to-class'
],
mixins: [transition(false), safeArea()],
mixins: [transition(false)],
props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: {
type: String,
observer: 'observeClass'
},
customStyle: String,
overlayStyle: String,
zIndex: {
type: Number,
value: 100
......@@ -26,6 +27,14 @@ VantComponent({
type: Boolean,
value: true
},
closeIcon: {
type: String,
value: 'cross'
},
closeIconPosition: {
type: String,
value: 'top-right'
},
closeOnClickOverlay: {
type: Boolean,
value: true
......@@ -34,12 +43,23 @@ VantComponent({
type: String,
value: 'center',
observer: 'observeClass'
},
safeAreaInsetBottom: {
type: Boolean,
value: true
},
safeAreaInsetTop: {
type: Boolean,
value: false
}
},
created() {
this.observeClass();
},
methods: {
onClickCloseIcon() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
......@@ -48,10 +68,13 @@ VantComponent({
},
observeClass() {
const { transition, position } = this.data;
this.updateClasses(transition || position);
const updateData = {
name: transition || position
};
if (transition === 'none') {
this.set({ duration: 0 });
updateData.duration = 0;
}
this.setData(updateData);
}
}
});
......
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index"
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<van-overlay
wx:if="{{ inited && overlay }}"
mask
wx:if="{{ overlay }}"
show="{{ show }}"
z-index="{{ zIndex }}"
custom-style="{{ overlayStyle }}"
......@@ -11,10 +10,15 @@
/>
<view
wx:if="{{ inited }}"
class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}"
style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
class="custom-class {{ classes }} {{ utils.bem('popup', [position, { round, safe: safeAreaInsetBottom, safeTop: safeAreaInsetTop }]) }}"
style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }};{{ customStyle }}"
bind:transitionend="onTransitionEnd"
>
<view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
<slot />
<van-icon
wx:if="{{ closeable }}"
name="{{ closeIcon }}"
class="van-popup__close-icon van-popup__close-icon--{{ closeIconPosition }}"
bind:tap="onClickCloseIcon"
/>
</view>
......
@import '../common/index.wxss';.van-popup{position:fixed;top:50%;left:50%;max-height:100%;overflow-y:auto;background-color:#fff;box-sizing:border-box;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;transition-timing-function:ease}.van-popup--center{-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--top{top:0;right:auto;bottom:auto;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--right{top:50%;right:0;bottom:auto;left:auto;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom{top:auto;right:auto;bottom:0;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--left{top:50%;right:auto;bottom:auto;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom.van-popup--safe{padding-bottom:34px}.van-popup--left .van-popup__safe-top,.van-popup--right .van-popup__safe-top,.van-popup--top .van-popup__safe-top{height:44px}.van-popup--bottom .van-popup__safe-top,.van-popup--center .van-popup__safe-top{padding-top:0!important}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
\ No newline at end of file
@import '../common/index.wxss';.van-popup{position:fixed;box-sizing:border-box;max-height:100%;overflow-y:auto;transition-timing-function:ease;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;background-color:#fff;background-color:var(--popup-background-color,#fff)}.van-popup--center{top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:20px;border-radius:var(--popup-round-border-radius,20px)}.van-popup--top{top:0;left:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 20px 20px;border-radius:0 0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px)}.van-popup--right{top:50%;right:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:20px 0 0 20px;border-radius:var(--popup-round-border-radius,20px) 0 0 var(--popup-round-border-radius,20px)}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:20px 20px 0 0;border-radius:var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0 0}.van-popup--left{top:50%;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 20px 20px 0;border-radius:0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{position:absolute;z-index:1;z-index:var(--popup-close-icon-z-index,1);color:#969799;color:var(--popup-close-icon-color,#969799);font-size:18px;font-size:var(--popup-close-icon-size,18px)}.van-popup__close-icon--top-left{top:16px;top:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{top:16px;top:var(--popup-close-icon-margin,16px);right:16px;right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:16px;bottom:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{right:16px;right:var(--popup-close-icon-margin,16px);bottom:16px;bottom:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { BLUE } from '../common/color';
import { addUnit } from '../common/utils';
VantComponent({
props: {
inactive: Boolean,
percentage: Number,
pivotText: String,
pivotColor: String,
trackColor: String,
showPivot: {
type: Boolean,
value: true
......@@ -17,48 +19,19 @@ VantComponent({
textColor: {
type: String,
value: '#fff'
}
},
data: {
pivotWidth: 0,
progressWidth: 0
},
watch: {
pivotText: 'getWidth',
showPivot: 'getWidth'
},
computed: {
portionStyle() {
const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
const background = this.getCurrentColor();
return `width: ${width}; background: ${background}; `;
},
pivotStyle() {
const color = this.data.textColor;
const background = this.data.pivotColor || this.getCurrentColor();
return `color: ${color}; background: ${background}`;
},
text() {
return this.data.pivotText || this.data.percentage + '%';
strokeWidth: {
type: null,
observer: 'setStrokeWidthUnit'
}
},
mounted() {
this.getWidth();
data: {
strokeWidthUnit: '4px'
},
methods: {
getCurrentColor() {
return this.data.inactive ? '#cacaca' : this.data.color;
},
getWidth() {
this.getRect('.van-progress').then(rect => {
this.set({
progressWidth: rect.width
});
});
this.getRect('.van-progress__pivot').then(rect => {
this.set({
pivotWidth: rect.width || 0
});
setStrokeWidthUnit(val) {
this.setData({
strokeWidthUnit: addUnit(val)
});
}
}
......
<view class="van-progress custom-class">
<wxs src="./index.wxs" module="getters" />
<view
class="van-progress custom-class"
style="height: {{ strokeWidthUnit }}; {{ trackColor ? 'background: ' + trackColor : '' }}"
>
<view
class="van-progress__portion {{ showPivot && text ? 'van-progress__portion--with-pivot' : '' }}"
style="{{ portionStyle }}"
class="van-progress__portion"
style="width: {{ percentage }}%; background: {{ inactive ? '#cacaca' : color }}"
>
<view
wx:if="{{ showPivot && text }}"
style="{{ pivotStyle }}"
wx:if="{{ showPivot && getters.text(pivotText, percentage) }}"
style="color: {{ textColor }}; background: {{ pivotColor ? pivotColor : inactive ? '#cacaca' : color }}"
class="van-progress__pivot"
>
{{ text }}
{{ getters.text(pivotText, percentage) }}
</view>
</view>
</view>
......
module.exports = {
text: function(pivotText, percentage) {
return pivotText || percentage + '%';
}
};
@import '../common/index.wxss';.van-progress{height:4px;position:relative;border-radius:4px;background:#e5e5e5}.van-progress__portion{left:0;height:100%;position:absolute;border-radius:inherit}.van-progress__portion--with-pivot{border-top-right-radius:0;border-bottom-right-radius:0}.van-progress__pivot{top:50%;right:0;min-width:2em;padding:0 5px;font-size:10px;position:absolute;line-height:1.6;text-align:center;border-radius:1em;word-break:keep-all;box-sizing:border-box;background-color:#e5e5e5;-webkit-transform:translate(100%,-50%);transform:translate(100%,-50%)}
\ No newline at end of file
@import '../common/index.wxss';.van-progress{position:relative;height:4px;height:var(--progress-height,4px);border-radius:4px;border-radius:var(--progress-height,4px);background:#e5e5e5;background:var(--progress-background-color,#e5e5e5)}.van-progress__portion{position:absolute;left:0;height:100%;border-radius:inherit;background:#1989fa;background:var(--progress-color,#1989fa)}.van-progress__pivot{position:absolute;top:50%;right:0;box-sizing:border-box;min-width:2em;text-align:center;word-break:keep-all;border-radius:1em;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#fff;color:var(--progress-pivot-text-color,#fff);padding:0 5px;padding:var(--progress-pivot-padding,0 5px);font-size:10px;font-size:var(--progress-pivot-font-size,10px);line-height:1.6;line-height:var(--progress-pivot-line-height,1.6);background-color:#1989fa;background-color:var(--progress-pivot-background-color,#1989fa)}
\ No newline at end of file
......
......@@ -5,28 +5,33 @@ VantComponent({
name: 'radio',
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.set({
value: value,
disabled: disabled || target.data.disabled
});
this.children = this.children || [];
this.children.push(target);
this.updateChild(target);
},
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
},
props: {
value: null,
disabled: Boolean
value: {
type: null,
observer: 'updateChildren'
},
watch: {
value(value) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.set({ value });
});
disabled: {
type: Boolean,
observer: 'updateChildren'
}
},
methods: {
updateChildren() {
(this.children || []).forEach((child) => this.updateChild(child));
},
disabled(disabled) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.set({ disabled: disabled || child.data.disabled });
updateChild(child) {
const { value, disabled } = this.data;
child.setData({
value,
disabled: disabled || child.data.disabled
});
}
}
......
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
"component": true
}
......
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
field: true,
relation: {
name: 'radio-group',
type: 'ancestor'
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
},
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right'
},
labelDisabled: Boolean,
labelPosition: String,
checkedColor: String
shape: {
type: String,
value: 'round'
},
iconSize: {
type: null,
observer: 'setIconSizeUnit'
}
},
data: {
iconSizeWithUnit: '20px'
},
methods: {
setIconSizeUnit(val) {
this.setData({
iconSizeWithUnit: addUnit(val)
});
},
emitChange(value) {
const instance = this.getRelationNodes('../radio-group/index')[0] || this;
const instance = this.parent || this;
instance.$emit('input', value);
instance.$emit('change', value);
},
onChange(event) {
this.emitChange(event.detail.value);
console.log(event);
this.emitChange(this.data.name);
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(this.data.name);
const { disabled, labelDisabled, name } = this.data;
if (!disabled && !labelDisabled) {
this.emitChange(name);
}
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-radio custom-class">
<view class="van-radio__input">
<radio-group bindchange="onChange">
<radio
value="{{ name }}"
checked="{{ value === name }}"
disabled="{{ disabled }}"
class="van-radio__control"
/>
</radio-group>
<view
wx:if="{{ labelPosition === 'left' }}"
class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
bindtap="onClickLabel"
>
<slot />
</view>
<view class="van-radio__icon-wrap" style="font-size: {{ iconSizeWithUnit }};" bindtap="onChange">
<slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon
class="{{ utils.bem('radio__icon', { disabled, checked: !disabled && name === value, check: !disabled && name !== value }) }}"
wx:else
name="success"
class="{{ utils.bem('radio__icon', [shape, { disabled, checked: value === name }]) }}"
style="{{ checkedColor && !disabled && value === name ? 'border-color:' + checkedColor + '; background-color:' + checkedColor + ';' : '' }}"
custom-class="icon-class"
color="{{ value === name ? checkedColor : '' }}"
name="{{ value === name ? 'checked' : 'circle' }}"
custom-style="line-height: {{ iconSizeWithUnit }};font-size: .8em;display: block;"
/>
</view>
<view class="van-radio__label van-radio__label--{{ labelPosition }} label-class" bindtap="onClickLabel">
<view
wx:if="{{ labelPosition === 'right' }}"
class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
bindtap="onClickLabel"
>
<slot />
</view>
</view>
......
@import '../common/index.wxss';.van-radio{overflow:hidden;line-height:1;-webkit-user-select:none;user-select:none}.van-radio__input,.van-radio__label{display:inline-block;vertical-align:middle}.van-radio__input{position:relative;font-size:20px}.van-radio__control{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;margin:0;opacity:0}.van-radio__label{margin-left:10px;color:#333;font-size:16px;line-height:20px}.van-radio__label--left{margin:0 10px 0 0;float:left}.van-radio__label:empty{margin:0}.van-radio__icon{pointer-events:none;display:block;line-height:0}.van-radio__icon--disabled{color:#e5e5e5}.van-radio__icon--checked{color:#1989fa}.van-radio__icon--check{color:#c9c9c9}
\ No newline at end of file
@import '../common/index.wxss';.van-radio{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{-webkit-flex:none;flex:none}.van-radio__icon{display:block;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;border:1px solid #e5e5e5;border:1px solid var(--radio-border-color,#e5e5e5);font-size:20px;font-size:var(--radio-size,20px);transition-duration:.2s;transition-duration:var(--radio-transition-duration,.2s)}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--radio-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--radio-checked-icon-color,#1989fa)}.van-radio__icon--disabled{background-color:#ebedf0;background-color:var(--radio-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:#c8c9cc;color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;margin-left:10px;margin-left:var(--radio-label-margin,10px);color:#323233;color:var(--radio-label-color,#323233);line-height:20px;line-height:var(--radio-size,20px)}.van-radio__label--left{float:left;margin:0 10px 0 0;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:#c8c9cc;color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
field: true,
classes: ['icon-class'],
props: {
value: Number,
readonly: Boolean,
disabled: Boolean,
size: {
type: Number,
value: 20
},
allowHalf: Boolean,
size: null,
icon: {
type: String,
value: 'star'
......@@ -33,46 +33,52 @@ VantComponent({
type: Number,
value: 5
},
value: {
type: Number,
value: 0
gutter: {
type: null,
observer: 'setGutterWithUnit'
},
touchable: {
type: Boolean,
value: true
}
},
data: {
innerValue: 0
innerValue: 0,
gutterWithUnit: undefined
},
watch: {
value(value) {
if (value !== this.data.innerValue) {
this.set({ innerValue: value });
this.setData({ innerValue: value });
}
}
},
computed: {
list() {
const { count, innerValue } = this.data;
return Array.from({ length: count }, (_, index) => index < innerValue);
}
},
methods: {
setGutterWithUnit(val) {
this.setData({
gutterWithUnit: addUnit(val)
});
},
onSelect(event) {
const { data } = this;
const { index } = event.currentTarget.dataset;
const { score } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) {
this.set({ innerValue: index + 1 });
this.$emit('input', index + 1);
this.$emit('change', index + 1);
this.setData({ innerValue: score + 1 });
this.$emit('input', score + 1);
this.$emit('change', score + 1);
}
},
onTouchMove(event) {
const { clientX, clientY } = event.touches[0];
this.getRect('.van-rate__item', true).then(list => {
const target = list.find(item => clientX >= item.left &&
clientX <= item.right &&
clientY >= item.top &&
clientY <= item.bottom);
const { touchable } = this.data;
if (!touchable)
return;
const { clientX } = event.touches[0];
this.getRect('.van-rate__icon', true).then((list) => {
const target = list
.sort(item => item.right - item.left)
.find(item => clientX >= item.left && clientX <= item.right);
if (target != null) {
this.onSelect(Object.assign({}, event, { currentTarget: target }));
this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
}
});
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="van-rate custom-class"
bind:touchmove="onTouchMove"
>
<van-icon
wx:for="{{ list }}"
wx:key="index"
<view
class="van-rate__item"
wx:for="{{ count }}"
wx:key="index"
style="padding-right: {{ index !== count - 1 ? gutterWithUnit : '' }}"
>
<van-icon
name="{{ index + 1 <= innerValue ? icon : voidIcon }}"
size="{{ size }}"
class="van-rate__icon"
custom-class="icon-class"
data-score="{{ index }}"
color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}"
bind:click="onSelect"
/>
<van-icon
wx:if="{{ allowHalf }}"
size="{{ size }}"
name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}"
class="{{ utils.bem('rate__icon', ['half']) }}"
custom-class="icon-class"
size="{{ size }}px"
data-index="{{ index }}"
name="{{ item ? icon : voidIcon }}"
color="{{ disabled ? disabledColor : item ? color : voidColor }}"
data-score="{{ index - 0.5 }}"
color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}"
bind:click="onSelect"
/>
</view>
</view>
......
@import '../common/index.wxss';.van-rate{-webkit-user-select:none;user-select:none}.van-rate__item{width:1em;padding:0 2px;box-sizing:initial}
\ No newline at end of file
@import '../common/index.wxss';.van-rate{display:-webkit-inline-flex;display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{position:relative;padding:0 2px;padding:0 var(--rate-horizontal-padding,2px)}.van-rate__icon{display:block;height:1em;font-size:20px;font-size:var(--rate-icon-size,20px)}.van-rate__icon--half{position:absolute;top:0;width:.5em;overflow:hidden;left:2px;left:var(--rate-horizontal-padding,2px)}
\ No newline at end of file
......
......@@ -27,7 +27,7 @@ VantComponent({
const style = gutter
? `margin-right: ${margin}; margin-left: ${margin};`
: '';
this.set({ style });
this.setData({ style });
this.getRelationNodes('../col/index').forEach(col => {
col.setGutter(this.data.gutter);
});
......
@import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both}
\ No newline at end of file
@import '../common/index.wxss';.van-row:after{display:table;clear:both;content:""}
\ No newline at end of file
......
......@@ -3,6 +3,7 @@ VantComponent({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
label: String,
focus: Boolean,
error: Boolean,
disabled: Boolean,
......@@ -10,8 +11,19 @@ VantComponent({
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search'
},
rightIcon: String,
placeholder: String,
placeholderStyle: String,
actionText: {
type: String,
value: '取消'
},
background: {
type: String,
value: '#ffffff'
......@@ -24,17 +36,26 @@ VantComponent({
type: String,
value: 'square'
},
label: String
clearable: {
type: Boolean,
value: true
}
},
methods: {
onChange(event) {
this.set({ value: event.detail });
this.setData({ value: event.detail });
this.$emit('change', event.detail);
},
onCancel() {
this.set({ value: '' });
/**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* https://github.com/youzan/vant-weapp/issues/1768
*/
setTimeout(() => {
this.setData({ value: '' });
this.$emit('cancel');
this.$emit('change', '');
}, 200);
},
onSearch() {
this.$emit('search', this.data.value);
......
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-field": "../field/index"
}
}
......
......@@ -9,9 +9,9 @@
<slot wx:else name="label" />
<van-field
clearable
type="search"
left-icon="search"
left-icon="{{ !useLeftIconSlot ? leftIcon : '' }}"
right-icon="{{ !useRightIconSlot ? rightIcon : '' }}"
focus="{{ focus }}"
error="{{ error }}"
border="{{ false }}"
......@@ -20,6 +20,7 @@
value="{{ value }}"
disabled="{{ disabled }}"
readonly="{{ readonly }}"
clearable="{{ clearable }}"
maxlength="{{ maxlength }}"
input-align="{{ inputAlign }}"
input-class="input-class"
......@@ -31,7 +32,10 @@
bind:change="onChange"
bind:confirm="onSearch"
bind:clear="onClear"
/>
>
<slot wx:if="{{ useLeftIconSlot }}" name="left-icon" slot="left-icon" />
<slot wx:if="{{ useRightIconSlot }}" name="right-icon" slot="right-icon" />
</van-field>
</view>
<view
......@@ -41,6 +45,6 @@
hover-stay-time="70"
>
<slot wx:if="{{ useActionSlot }}" name="action" />
<view wx:else bind:tap="onCancel" class="cancel-class">取消</view>
<view wx:else bind:tap="onCancel" class="cancel-class">{{ actionText }}</view>
</view>
</view>
......
@import '../common/index.wxss';.van-search{padding:10px 16px;-webkit-align-items:center;align-items:center;box-sizing:border-box}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{padding-left:10px;background-color:#f7f8fa;border-radius:2px;-webkit-flex:1;flex:1}.van-search__content--round{border-radius:17px}.van-search__label{padding:0 5px;font-size:14px;line-height:34px;color:#333}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#999}.van-search--withaction{padding-right:0}.van-search input::-webkit-search-cancel-button,.van-search input::-webkit-search-decoration,.van-search input::-webkit-search-results-button,.van-search input::-webkit-search-results-decoration{display:none}.van-search__action{padding:0 10px;font-size:14px;line-height:34px;color:#333}.van-search__action--hover{background-color:#f2f3f5}
\ No newline at end of file
@import '../common/index.wxss';.van-search{-webkit-align-items:center;align-items:center;box-sizing:border-box;padding:10px 12px;padding:var(--search-padding,10px 12px)}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{-webkit-flex:1;flex:1;padding-left:8px;padding-left:var(--padding-xs,8px);border-radius:2px;border-radius:var(--border-radius-sm,2px);background-color:#f7f8fa;background-color:var(--search-background-color,#f7f8fa)}.van-search__content--round{border-radius:17px;border-radius:calc(var(--search-input-height, 34px)/2)}.van-search__label{padding:0 5px;padding:var(--search-label-padding,0 5px);font-size:14px;font-size:var(--search-label-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-label-color,#323233)}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#969799;color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{padding:0 8px;padding:var(--search-action-padding,0 8px);font-size:14px;font-size:var(--search-action-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-action-text-color,#323233)}.van-search__action--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'active-class',
'disabled-class',
],
relation: {
type: 'ancestor',
name: 'badge-group'
name: 'sidebar',
linked(target) {
this.parent = target;
}
},
props: {
dot: Boolean,
info: null,
title: String
title: String,
disabled: Boolean
},
methods: {
onClick() {
const group = this.getRelationNodes('../badge-group/index')[0];
if (group) {
group.setActive(this);
const { parent } = this;
if (!parent || this.data.disabled) {
return;
}
const index = parent.children.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(active) {
this.set({ active });
setActive(selected) {
return this.setData({ selected });
}
}
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('badge', { active }) }} van-hairline custom-class"
hover-class="van-badge--hover"
class="{{ utils.bem('sidebar-item', { selected, disabled }) }} {{ selected ? 'active-class' : '' }} {{ disabled ? 'disabled-class' : '' }} custom-class"
hover-class="van-sidebar-item--hover"
hover-stay-time="70"
bind:tap="onClick"
>
<view class="van-badge__text">
<view class="van-sidebar-item__text">
<van-info
wx:if="{{ info !== null }}"
wx:if="{{ info !== null || dot }}"
dot="{{ dot }}"
info="{{ info }}"
custom-style="right: 4px"
/>
......
@import '../common/index.wxss';.van-sidebar-item{display:block;box-sizing:border-box;overflow:hidden;word-wrap:break-word;border-left:3px solid transparent;-webkit-user-select:none;user-select:none;padding:20px 12px 20px 8px;padding:var(--sidebar-padding,20px 12px 20px 8px);font-size:14px;font-size:var(--sidebar-font-size,14px);line-height:20px;line-height:var(--sidebar-line-height,20px);color:#323233;color:var(--sidebar-text-color,#323233);background-color:#fafafa;background-color:var(--sidebar-background-color,#fafafa)}.van-sidebar-item__text{position:relative;display:inline-block}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:#f2f3f5;background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{color:#323233;color:var(--sidebar-selected-text-color,#323233);font-weight:500;font-weight:var(--sidebar-selected-font-weight,500);border-color:#ee0a24;border-color:var(--sidebar-selected-border-color,#ee0a24)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:#fff;background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:#c8c9cc;color:var(--sidebar-disabled-text-color,#c8c9cc)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { isNumber } from '../common/utils';
VantComponent({
relation: {
name: 'badge',
name: 'sidebar-item',
type: 'descendant',
linked(target) {
this.badges.push(target);
this.setActive();
this.children.push(target);
this.setActive(this.data.activeKey);
},
unlinked(target) {
this.badges = this.badges.filter(item => item !== target);
this.setActive();
this.items = this.children.filter((item) => item !== target);
this.setActive(this.data.activeKey);
}
},
props: {
active: {
activeKey: {
type: Number,
value: 0
value: 0,
observer: 'setActive'
}
},
watch: {
active: 'setActive'
},
beforeCreate() {
this.badges = [];
this.children = [];
this.currentActive = -1;
},
methods: {
setActive(badge) {
let { active } = this.data;
const { badges } = this;
if (badge && !isNumber(badge)) {
active = badges.indexOf(badge);
}
if (active === this.currentActive) {
return;
setActive(activeKey) {
const { children, currentActive } = this;
if (!children.length) {
return Promise.resolve();
}
if (this.currentActive !== -1 && badges[this.currentActive]) {
this.$emit('change', active);
badges[this.currentActive].setActive(false);
this.currentActive = activeKey;
const stack = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (badges[active]) {
badges[active].setActive(true);
this.currentActive = active;
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
}
}
});
......
<view class="van-badge-group van-hairline--top-bottom custom-class">
<view class="van-sidebar van-hairline--top-bottom custom-class">
<slot />
</view>
......
@import '../common/index.wxss';.van-sidebar{width:85px;width:var(--sidebar-width,85px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
row: {
type: Number,
value: 0
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true
},
animate: {
type: Boolean,
value: true
},
avatarSize: {
type: String,
value: '32px'
},
avatarShape: {
type: String,
value: 'round'
},
titleWidth: {
type: String,
value: '40%'
},
rowWidth: {
type: null,
value: '100%',
observer(val) {
this.setData({ isArray: val instanceof Array });
}
}
},
data: {
isArray: false
}
});
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ loading }}"
class="custom-class {{ utils.bem('skeleton', [{animate}]) }}"
>
<view
wx:if="{{ avatar }}"
class="{{ utils.bem('skeleton__avatar', [avatarShape])}}"
style="{{ 'width:' + avatarSize + ';height:' + avatarSize }}"
/>
<view class="{{ utils.bem('skeleton__content')}}">
<view
wx:if="{{ title }}"
class="{{ utils.bem('skeleton__title') }}"
style="{{ 'width:' + titleWidth }}"
/>
<view
wx:for="row"
wx:key="index"
wx:for-index="index"
class="{{ utils.bem('skeleton__row') }}"
style="{{ 'width:' + (isArray ? rowWidth[index] : rowWidth) }}"
/>
</view>
</view>
<view wx:else class="{{ utils.bem('skeleton__content')}}">
<slot />
</view>
@import '../common/index.wxss';.van-skeleton{display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:0 16px;padding:var(--skeleton-padding,0 16px)}.van-skeleton__avatar{-webkit-flex-shrink:0;flex-shrink:0;margin-right:16px;margin-right:var(--padding-md,16px);background-color:#f2f3f5;background-color:var(--skeleton-avatar-background-color,#f2f3f5)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{-webkit-flex:1;flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:8px;padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{height:16px;height:var(--skeleton-row-height,16px);background-color:#f2f3f5;background-color:var(--skeleton-row-background-color,#f2f3f5)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:12px;margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{-webkit-animation:van-skeleton-blink 1.2s ease-in-out infinite;animation:van-skeleton-blink 1.2s ease-in-out infinite}@-webkit-keyframes van-skeleton-blink{50%{opacity:.6}}@keyframes van-skeleton-blink{50%{opacity:.6}}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { addUnit } from '../common/utils';
VantComponent({
mixins: [touch],
props: {
......@@ -24,7 +25,7 @@ VantComponent({
value: 0
},
barHeight: {
type: String,
type: null,
value: '2px'
}
},
......@@ -42,34 +43,50 @@ VantComponent({
return;
this.touchStart(event);
this.startValue = this.format(this.data.value);
this.dragStatus = 'start';
},
onTouchMove(event) {
if (this.data.disabled)
return;
if (this.dragStatus === 'start') {
this.$emit('drag-start');
}
this.touchMove(event);
this.dragStatus = 'draging';
this.getRect('.van-slider').then((rect) => {
const diff = this.deltaX / rect.width * 100;
this.updateValue(this.startValue + diff, false, true);
this.newValue = this.startValue + diff;
this.updateValue(this.newValue, false, true);
});
},
onTouchEnd() {
if (this.data.disabled)
return;
this.updateValue(this.data.value, true);
if (this.dragStatus === 'draging') {
this.updateValue(this.newValue, true);
this.$emit('drag-end');
}
},
onClick(event) {
if (this.data.disabled)
return;
const { min } = this.data;
this.getRect('.van-slider').then((rect) => {
const value = (event.detail.x - rect.left) / rect.width * 100;
const value = (event.detail.x - rect.left) / rect.width * this.getRange() + min;
this.updateValue(value, true);
});
},
updateValue(value, end, drag) {
value = this.format(value);
this.set({
const { barHeight, min } = this.data;
const width = `${((value - min) * 100) / this.getRange()}%`;
this.setData({
value,
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
barStyle: `
width: ${width};
height: ${addUnit(barHeight)};
${drag ? 'transition: none;' : ''}
`,
});
if (drag) {
this.$emit('drag', { value });
......@@ -78,6 +95,10 @@ VantComponent({
this.$emit('change', value);
}
},
getRange() {
const { max, min } = this.data;
return max - min;
},
format(value) {
const { max, min, step } = this.data;
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
......
@import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#1989fa}.van-slider__button{width:20px;height:20px;border-radius:50%;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper:after{content:"";position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3}
\ No newline at end of file
@import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;border-radius:var(--border-radius-max,999px);background-color:#e5e5e5;background-color:var(--slider-inactive-background-color,#e5e5e5)}.van-slider:before{position:absolute;right:0;left:0;content:"";top:-8px;top:-var(--padding-xs,8px);bottom:-8px;bottom:-var(--padding-xs,8px)}.van-slider__bar{position:relative;border-radius:inherit;transition:width .2s;transition:width var(--animation-duration-fast,.2s);background-color:#1989fa;background-color:var(--slider-active-background-color,#1989fa)}.van-slider__button{width:24px;height:24px;border-radius:50%;box-shadow:0 1px 2px rgba(0,0,0,.5);background-color:#fff;background-color:var(--slider-button-background-color,#fff)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider--disabled{opacity:.5}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { addUnit, isDef } from '../common/utils';
const LONG_PRESS_START_TIME = 600;
const LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1, num2) {
const cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
VantComponent({
field: true,
classes: [
'input-class',
'plus-class',
'minus-class'
],
classes: ['input-class', 'plus-class', 'minus-class'],
props: {
value: null,
integer: Boolean,
disabled: Boolean,
inputWidth: String,
inputWidth: null,
buttonSize: null,
asyncChange: Boolean,
disableInput: Boolean,
decimalLength: {
type: Number,
value: null
},
min: {
type: null,
value: 1
......@@ -24,14 +33,14 @@ VantComponent({
step: {
type: null,
value: 1
}
},
computed: {
minusDisabled() {
return this.data.disabled || this.data.value <= this.data.min;
showPlus: {
type: Boolean,
value: true
},
plusDisabled() {
return this.data.disabled || this.data.value >= this.data.max;
showMinus: {
type: Boolean,
value: true
}
},
watch: {
......@@ -40,20 +49,39 @@ VantComponent({
return;
}
const newValue = this.range(value);
if (typeof newValue === 'number' && value !== newValue) {
this.set({ value: newValue });
if (typeof newValue === 'number' && +this.data.value !== newValue) {
this.setData({ value: newValue });
}
},
inputWidth() {
this.set({
inputStyle: this.computeInputStyle()
});
},
buttonSize() {
this.set({
inputStyle: this.computeInputStyle(),
buttonStyle: this.computeButtonStyle()
});
}
},
data: {
focus: false
focus: false,
inputStyle: '',
buttonStyle: ''
},
created() {
this.set({
this.setData({
value: this.range(this.data.value)
});
},
methods: {
isDisabled(type) {
if (type === 'plus') {
return this.data.disabled || this.data.value >= this.data.max;
}
return this.data.disabled || this.data.value <= this.data.min;
},
onFocus(event) {
this.$emit('focus', event.detail);
},
......@@ -64,33 +92,79 @@ VantComponent({
},
// limit value range
range(value) {
return Math.max(Math.min(this.data.max, value), this.data.min);
value = String(value).replace(/[^0-9.-]/g, '');
// format range
value = value === '' ? 0 : +value;
value = Math.max(Math.min(this.data.max, value), this.data.min);
// format decimal
if (isDef(this.data.decimalLength)) {
value = value.toFixed(this.data.decimalLength);
}
return value;
},
onInput(event) {
const { value = '' } = event.detail || {};
this.triggerInput(value);
},
onChange(type) {
if (this.data[`${type}Disabled`]) {
onChange() {
const { type } = this;
if (this.isDisabled(type)) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = Math.round((this.data.value + diff) * 100) / 100;
const value = add(+this.data.value, diff);
this.triggerInput(this.range(value));
this.$emit(type);
},
onMinus() {
this.onChange('minus');
longPressStep() {
this.longPressTimer = setTimeout(() => {
this.onChange();
this.longPressStep();
}, LONG_PRESS_INTERVAL);
},
onTap(event) {
const { type } = event.currentTarget.dataset;
this.type = type;
this.onChange();
},
onTouchStart(event) {
clearTimeout(this.longPressTimer);
const { type } = event.currentTarget.dataset;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(() => {
this.isLongPress = true;
this.onChange();
this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onPlus() {
this.onChange('plus');
onTouchEnd() {
clearTimeout(this.longPressTimer);
},
triggerInput(value) {
this.set({
this.setData({
value: this.data.asyncChange ? this.data.value : value
});
this.$emit('change', value);
},
computeInputStyle() {
let style = '';
if (this.data.inputWidth) {
style = `width: ${addUnit(this.data.inputWidth)};`;
}
if (this.data.buttonSize) {
style += `height: ${addUnit(this.data.buttonSize)};`;
}
return style;
},
computeButtonStyle() {
let style = '';
const size = addUnit(this.data.buttonSize);
if (this.data.buttonSize) {
style = `width: ${size};height: ${size};`;
}
return style;
}
}
});
......
......@@ -2,15 +2,20 @@
<view class="van-stepper custom-class">
<view
class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}"
wx:if="{{ showMinus }}"
data-type="minus"
style="{{ buttonStyle }}"
class="minus-class {{ utils.bem('stepper__minus', { disabled: disabled || value <= min }) }}"
hover-class="van-stepper__minus--hover"
hover-stay-time="70"
bind:tap="onMinus"
bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
/>
<input
type="{{ integer ? 'number' : 'digit' }}"
class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
style="{{ inputWidth ? 'width: ' + inputWidth : '' }}"
style="{{ inputStyle }}"
value="{{ value }}"
focus="{{ focus }}"
disabled="{{ disabled || disableInput }}"
......@@ -19,9 +24,14 @@
bind:blur="onBlur"
/>
<view
class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}"
wx:if="{{ showPlus }}"
data-type="plus"
style="{{ buttonStyle }}"
class="plus-class {{ utils.bem('stepper__plus', { disabled: disabled || value >= max }) }}"
hover-class="van-stepper__plus--hover"
hover-stay-time="70"
bind:tap="onPlus"
bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
/>
</view>
......
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;width:28px;height:28px;padding:5px;margin:1px;vertical-align:middle;background-color:#f2f3f5;border:0;box-sizing:border-box}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:#333;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8}.van-stepper__minus--disabled,.van-stepper__plus--disabled{background-color:#f7f8fa}.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#c9c9c9}.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa}.van-stepper__minus{border-radius:4px 0 0 4px}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0}.van-stepper__input{display:inline-block;width:30px;height:26px;padding:1px;margin:1px;font-size:14px;color:#333;text-align:center;vertical-align:middle;background-color:#f2f3f5;border:0;border-width:1px 0;border-radius:0;box-sizing:initial;-webkit-appearance:none}.van-stepper__input--disabled{color:#c9c9c9;background-color:#f2f3f5}
\ No newline at end of file
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;box-sizing:border-box;margin:1px;vertical-align:middle;border:0;background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);color:#323233;color:var(--stepper-button-icon-color,#323233);width:28px;width:var(--stepper-input-height,28px);height:28px;height:var(--stepper-input-height,28px);padding:4px;padding:var(--padding-base,4px)}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;content:"";background-color:#323233;background-color:var(--text-color,#323233)}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8;background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:#c8c9cc;color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#f7f8fa;background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:4px 0 0 4px;border-radius:var(--stepper-border-radius,4px) 0 0 var(--stepper-border-radius,4px)}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0;border-radius:0 var(--stepper-border-radius,4px) var(--stepper-border-radius,4px) 0}.van-stepper__input{display:inline-block;box-sizing:border-box;min-height:0;margin:1px;padding:1px;text-align:center;vertical-align:middle;border:0;border-width:1px 0;border-radius:0;-webkit-appearance:none;font-size:14px;font-size:var(--stepper-input-font-size,14px);color:#323233;color:var(--stepper-input-text-color,#323233);background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);width:32px;width:var(--stepper-input-width,32px);height:28px;height:var(--stepper-input-height,28px)}.van-stepper__input--disabled{color:#c8c9cc;color:var(--stepper-input-disabled-text-color,#c8c9cc);background-color:#f2f3f5;background-color:var(--stepper-input-disabled-background-color,#f2f3f5)}
\ No newline at end of file
......
......@@ -12,6 +12,11 @@ VantComponent({
activeColor: {
type: String,
value: GREEN
}
},
activeIcon: {
type: String,
value: 'checked'
},
inactiveIcon: String
}
});
......
......@@ -12,10 +12,26 @@
<view>{{ item.desc }}</view>
</view>
<view class="van-step__circle-container">
<view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
<van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" />
<block wx:if="{{ index !== active }}">
<van-icon
wx:if="{{ inactiveIcon }}"
color="#969799"
name="{{ inactiveIcon }}"
custom-class="van-step__icon"
/>
<view
wx:else
class="van-step__circle"
style="{{ index < active ? 'background-color: ' + activeColor : '' }}"
/>
</block>
<van-icon wx:else name="{{ activeIcon }}" color="{{ activeColor }}" custom-class="van-step__icon" />
</view>
<view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
<view
wx:if="{{ index !== steps.length - 1 }}"
class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}"
/>
</view>
</view>
</view>
......
@import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;color:#999}.van-step--finish{color:#333}.van-step__circle{width:5px;height:5px;background-color:#999;border-radius:50%}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;padding:0 8px;background-color:#fff;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0)}.van-step--horizontal .van-step__title{display:inline-block;font-size:12px;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;background-color:#eee;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:#333}.van-step--horizontal.van-step--process .van-step__active{display:block;font-size:12px;line-height:1}.van-step--vertical{padding:10px 10px 10px 0;font-size:14px;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;background-color:#fff;content:""}.van-step--vertical .van-step__active,.van-step--vertical .van-step__circle,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__active{font-size:12px;line-height:1}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;background-color:#eee;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}
\ No newline at end of file
@import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff;background-color:var(--steps-background-color,#fff)}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;font-size:var(--step-font-size,14px);color:#969799;color:var(--step-text-color,#969799)}.van-step--finish{color:#323233;color:var(--step-finish-text-color,#323233)}.van-step__circle{border-radius:50%;width:5px;width:var(--step-circle-size,5px);height:5px;height:var(--step-circle-size,5px);background-color:#969799;background-color:var(--step-circle-color,#969799)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0);background-color:#fff;background-color:var(--white,#fff);padding:0 8px;padding:0 var(--padding-xs,8px)}.van-step--horizontal .van-step__title{display:inline-block;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);font-size:12px;font-size:var(--step-horizontal-title-font-size,12px)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}.van-step--horizontal.van-step--process{color:#323233;color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical{padding:10px 10px 10px 0;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;content:"";background-color:#fff;background-color:var(--white,#fff)}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__icon{line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
const ROOT_ELEMENT = '.van-sticky';
VantComponent({
props: {
zIndex: {
type: Number,
value: 99
},
offsetTop: {
type: Number,
value: 0,
observer: 'observeContent'
},
disabled: {
type: Boolean,
observer(value) {
if (!this.mounted) {
return;
}
value ? this.disconnectObserver() : this.initObserver();
}
},
container: {
type: null,
observer(target) {
if (typeof target !== 'function' || !this.data.height) {
return;
}
this.observeContainer();
}
}
},
data: {
wrapStyle: '',
containerStyle: ''
},
methods: {
setStyle() {
const { offsetTop, height, fixed, zIndex } = this.data;
if (fixed) {
this.setData({
wrapStyle: `top: ${offsetTop}px;`,
containerStyle: `height: ${height}px; z-index: ${zIndex};`
});
}
else {
this.setData({
wrapStyle: '',
containerStyle: ''
});
}
},
getContainerRect() {
const nodesRef = this.data.container();
return new Promise(resolve => nodesRef.boundingClientRect(resolve).exec());
},
initObserver() {
this.disconnectObserver();
this.getRect(ROOT_ELEMENT).then((rect) => {
this.setData({ height: rect.height });
wx.nextTick(() => {
this.observeContent();
this.observeContainer();
});
});
},
disconnectObserver(observerName) {
if (observerName) {
const observer = this[observerName];
observer && observer.disconnect();
}
else {
this.contentObserver && this.contentObserver.disconnect();
this.containerObserver && this.containerObserver.disconnect();
}
},
observeContent() {
const { offsetTop } = this.data;
this.disconnectObserver('contentObserver');
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 1]
});
this.contentObserver = contentObserver;
contentObserver.relativeToViewport({ top: -offsetTop });
contentObserver.observe(ROOT_ELEMENT, res => {
if (this.data.disabled) {
return;
}
this.setFixed(res.boundingClientRect.top);
});
},
observeContainer() {
if (typeof this.data.container !== 'function') {
return;
}
const { height } = this.data;
this.getContainerRect().then((rect) => {
this.containerHeight = rect.height;
this.disconnectObserver('containerObserver');
const containerObserver = this.createIntersectionObserver({
thresholds: [0, 1]
});
this.containerObserver = containerObserver;
containerObserver.relativeToViewport({
top: this.containerHeight - height
});
containerObserver.observe(ROOT_ELEMENT, res => {
if (this.data.disabled) {
return;
}
this.setFixed(res.boundingClientRect.top);
});
});
},
setFixed(top) {
const { offsetTop, height } = this.data;
const { containerHeight } = this;
const fixed = containerHeight && height
? top > height - containerHeight && top < offsetTop
: top < offsetTop;
this.$emit('scroll', {
scrollTop: top,
isFixed: fixed
});
this.setData({ fixed });
wx.nextTick(() => {
this.setStyle();
});
}
},
mounted() {
this.mounted = true;
if (!this.data.disabled) {
this.initObserver();
}
},
destroyed() {
this.disconnectObserver();
}
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class van-sticky" style="{{ containerStyle }}">
<view class="{{ utils.bem('sticky-wrap', { fixed }) }}" style="{{ wrapStyle }}">
<slot />
</view>
</view>
@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{position:fixed;right:0;left:0}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
classes: [
'bar-class',
'price-class',
'button-class'
],
props: {
tip: null,
tip: {
type: null,
observer: 'updateTip'
},
tipIcon: String,
type: Number,
price: null,
price: {
type: null,
observer: 'updatePrice'
},
label: String,
loading: Boolean,
disabled: Boolean,
......@@ -22,21 +27,29 @@ VantComponent({
buttonType: {
type: String,
value: 'danger'
}
},
computed: {
hasPrice() {
return typeof this.data.price === 'number';
},
priceStr() {
return (this.data.price / 100).toFixed(2);
decimalLength: {
type: Number,
value: 2,
observer: 'updatePrice'
},
tipStr() {
const { tip } = this.data;
return typeof tip === 'string' ? tip : '';
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true
}
},
methods: {
updatePrice() {
const { price, decimalLength } = this.data;
this.setData({
hasPrice: typeof price === 'number',
priceStr: (price / 100).toFixed(decimalLength)
});
},
updateTip() {
this.setData({ hasTip: typeof this.data.tip === 'string' });
},
onSubmit(event) {
this.$emit('submit', event.detail);
}
......
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
"van-button": "../button/index",
"van-icon": "../icon/index"
}
}
......
......@@ -3,19 +3,28 @@
<view class="van-submit-bar custom-class">
<slot name="top" />
<view wx:if="{{ tip }}" class="van-submit-bar__tip">
{{ tipStr }}<slot name="tip" />
<view class="van-submit-bar__tip">
<van-icon
wx:if="{{ tipIcon }}"
size="12px"
name="{{ tipIcon }}"
custom-class="van-submit-bar__tip-icon"
/>
<view wx:if="{{ hasTip }}" class="van-submit-bar__tip-text">
{{ tip }}
</view>
<slot name="tip" />
</view>
<view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}">
<view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom }) }}">
<slot />
<view class="van-submit-bar__text">
<block wx:if="{{ hasPrice }}">
<view wx:if="{{ hasPrice }}" class="van-submit-bar__text">
<text>{{ label || '合计:' }}</text>
<text class="van-submit-bar__price price-class">
<text class="van-submit-bar__currency">{{ currency }}</text> {{ priceStr }}
<text class="van-submit-bar__currency">{{ currency }} </text>
<text>{{ priceStr }}</text>
</text>
</block>
<text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
</view>
<van-button
square
......
@import '../common/index.wxss';.van-submit-bar{z-index:100;position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none}.van-submit-bar__tip{padding:10px;color:#f56723;font-size:12px;line-height:18px;background-color:#fff7cc}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:50px;background-color:#fff;font-size:14px}.van-submit-bar__bar--safe{padding-bottom:34px}.van-submit-bar__text{-webkit-flex:1;flex:1;color:#333;font-weight:500;text-align:right}.van-submit-bar__price{color:#f44;font-size:18px;padding-right:12px}.van-submit-bar__currency{font-size:14px}.van-submit-bar__button button{width:110px}
\ No newline at end of file
@import '../common/index.wxss';.van-submit-bar{position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none;z-index:100;z-index:var(--submit-bar-z-index,100);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__tip{padding:10px;padding:var(--submit-bar-tip-padding,10px);color:#f56723;color:var(--submit-bar-tip-color,#f56723);font-size:12px;font-size:var(--submit-bar-tip-font-size,12px);line-height:1.5;line-height:var(--submit-bar-tip-line-height,1.5);background-color:#fff7cc;background-color:var(--submit-bar-tip-background-color,#fff7cc)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{width:12px;height:12px;margin-right:4px;vertical-align:middle;font-size:12px;font-size:var(--submit-bar-tip-icon-size,12px);min-width:18px;min-width:calc(var(--submit-bar-tip-icon-size, 12px)*1.5)}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;height:50px;height:var(--submit-bar-height,50px);font-size:14px;font-size:var(--submit-bar-text-font-size,14px);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__bar--safe{padding-bottom:env(safe-area-inset-bottom)}.van-submit-bar__text{-webkit-flex:1;flex:1;text-align:right;color:#323233;color:var(--submit-bar-text-color,#323233);padding-right:12px;padding-right:var(--padding-sm,12px);font-weight:500;font-weight:var(--font-weight-bold,500)}.van-submit-bar__price{color:#ee0a24;color:var(--submit-bar-price-color,#ee0a24);font-size:18px;font-size:var(--submit-bar-price-font-size,18px)}.van-submit-bar__currency{font-size:14px;font-size:var(--submit-bar-currency-font-size,14px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{width:110px;width:var(--submit-bar-button-width,110px)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
const THRESHOLD = 0.3;
let ARRAY = [];
VantComponent({
props: {
disabled: Boolean,
......@@ -12,14 +13,22 @@ VantComponent({
type: Number,
value: 0
},
asyncClose: Boolean
asyncClose: Boolean,
name: {
type: [Number, String],
value: ''
}
},
mixins: [touch],
data: {
catchMove: true
catchMove: false
},
created() {
this.offset = 0;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter(item => item !== this);
},
methods: {
open(position) {
......@@ -35,8 +44,8 @@ VantComponent({
const transform = `translate3d(${offset}px, 0, 0)`;
const transition = this.draging
? 'none'
: '.6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.set({
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.setData({
wrapperStyle: `
-webkit-transform: ${transform};
-webkit-transition: ${transition};
......@@ -57,11 +66,17 @@ VantComponent({
else {
this.swipeMove(0);
}
this.setData({ catchMove: false });
},
startDrag(event) {
if (this.data.disabled) {
return;
}
ARRAY.forEach(item => {
if (item !== this) {
item.close();
}
});
this.draging = true;
this.startOffset = this.offset;
this.firstDirection = '';
......@@ -75,7 +90,7 @@ VantComponent({
this.touchMove(event);
if (!this.firstDirection) {
this.firstDirection = this.direction;
this.set({ catchMove: this.firstDirection === 'horizontal' });
this.setData({ catchMove: this.firstDirection === 'horizontal' });
}
if (this.firstDirection === 'vertical') {
return;
......@@ -102,7 +117,7 @@ VantComponent({
return;
}
if (this.data.asyncClose) {
this.$emit('close', { position, instance: this });
this.$emit('close', { position, instance: this, name: this.data.name });
}
else {
this.swipeMove(0);
......
import { VantComponent } from '../common/component';
VantComponent({
field: true,
props: {
value: null,
title: String,
border: Boolean,
checked: Boolean,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '24px'
},
activeValue: {
type: null,
value: true
},
inactiveValue: {
type: null,
value: false
}
},
watch: {
checked(value) {
this.set({ value });
}
},
created() {
this.set({ value: this.data.checked });
},
methods: {
onChange(event) {
this.$emit('change', event.detail);
}
}
});
<van-cell
center
title="{{ title }}"
border="{{ border }}"
custom-class="van-switch-cell"
>
<van-switch
size="{{ size }}"
checked="{{ checked }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
active-color="{{ activeColor }}"
inactive-color="{{ inactiveColor }}"
active-value="{{ activeValue }}"
inactive-value="{{ inactiveValue }}"
custom-class="van-switch-cell__switch"
bind:change="onChange"
/>
</van-cell>
@import '../common/index.wxss';.van-switch-cell{padding-top:9px;padding-bottom:9px}.van-switch-cell__switch{vertical-align:middle}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { BLUE, GRAY_DARK } from '../common/color';
VantComponent({
field: true,
classes: ['node-class'],
......@@ -23,13 +24,20 @@ VantComponent({
},
watch: {
checked(value) {
this.set({ value });
const loadingColor = this.getLoadingColor(value);
this.setData({ value, loadingColor });
}
},
created() {
this.set({ value: this.data.checked });
const { checked: value } = this.data;
const loadingColor = this.getLoadingColor(value);
this.setData({ value, loadingColor });
},
methods: {
getLoadingColor(checked) {
const { activeColor, inactiveColor } = this.data;
return checked ? activeColor || BLUE : inactiveColor || GRAY_DARK;
},
onClick() {
const { activeValue, inactiveValue } = this.data;
if (!this.data.disabled && !this.data.loading) {
......
......@@ -6,6 +6,6 @@
bind:tap="onClick"
>
<view class="van-switch__node node-class">
<van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" />
<van-loading wx:if="{{ loading }}" color="{{ loadingColor }}" custom-class="van-switch__loading" />
</view>
</view>
......
@import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:initial;transition:background-color .3s}.van-switch,.van-switch__node{height:1em;background-color:#fff}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05)}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4}
\ No newline at end of file
@import '../common/index.wxss';.van-switch{position:relative;display:inline-block;box-sizing:initial;width:2em;width:var(--switch-width,2em);height:1em;height:var(--switch-height,1em);background-color:#fff;background-color:var(--switch-background-color,#fff);border:1px solid rgba(0,0,0,.1);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:1em;border-radius:var(--switch-node-size,1em);transition:background-color .3s;transition:background-color var(--switch-transition-duration,.3s)}.van-switch__node{position:absolute;top:0;left:0;border-radius:100%;z-index:1;z-index:var(--switch-node-z-index,1);width:1em;width:var(--switch-node-size,1em);height:1em;height:var(--switch-node-size,1em);background-color:#fff;background-color:var(--switch-node-background-color,#fff);box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));transition:-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05),-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05),-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05)}.van-switch__loading{position:absolute!important;top:25%;left:25%;width:50%;height:50%}.van-switch--on{background-color:#1989fa;background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em);-webkit-transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:.4;opacity:var(--switch-disabled-opacity,.4)}
\ No newline at end of file
......
......@@ -2,20 +2,27 @@ import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'tabs',
type: 'ancestor'
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
},
props: {
dot: Boolean,
info: null,
title: String,
disabled: Boolean,
titleStyle: String
titleStyle: String,
name: {
type: [Number, String],
value: '',
}
},
data: {
width: null,
inited: false,
active: false,
animated: false
active: false
},
watch: {
title: 'update',
......@@ -25,10 +32,23 @@ VantComponent({
titleStyle: 'update'
},
methods: {
getComputedName() {
if (this.data.name !== '') {
return this.data.name;
}
return this.index;
},
updateRender(active, parent) {
const { data: parentData } = parent;
this.inited = this.inited || active;
this.setData({
active,
shouldRender: this.inited || !parentData.lazyRender
});
},
update() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.updateTabs();
if (this.parent) {
this.parent.updateTabs();
}
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ animated || inited }}"
wx:if="{{ shouldRender }}"
class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}"
>
<slot />
</view>
......
@import '../common/index.wxss';.van-tab__pane{box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
\ No newline at end of file
@import '../common/index.wxss';:host{-webkit-flex-shrink:0;flex-shrink:0;width:100%}.van-tab__pane,:host{box-sizing:border-box}.van-tab__pane{overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
\ No newline at end of file
......
......@@ -2,15 +2,13 @@ import { VantComponent } from '../common/component';
VantComponent({
props: {
info: null,
name: null,
icon: String,
dot: Boolean
},
relation: {
name: 'tabbar',
type: 'ancestor',
linked(target) {
this.parent = target;
}
type: 'ancestor'
},
data: {
active: false
......@@ -22,11 +20,28 @@ VantComponent({
}
this.$emit('click');
},
setActive({ active, color }) {
if (this.data.active !== active) {
return this.set({ active, color });
updateFromParent() {
const { parent } = this;
if (!parent) {
return;
}
const index = parent.children.indexOf(this);
const parentData = parent.data;
const { data } = this;
const active = (data.name || index) === parentData.active;
const patch = {};
if (active !== data.active) {
patch.active = active;
}
if (parentData.activeColor !== data.activeColor) {
patch.activeColor = parentData.activeColor;
}
if (parentData.inactiveColor !== data.inactiveColor) {
patch.inactiveColor = parentData.inactiveColor;
}
return Promise.resolve();
return Object.keys(patch).length > 0
? this.set(patch)
: Promise.resolve();
}
}
});
......
......@@ -2,14 +2,14 @@
<view
class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
style="{{ active && color ? 'color: ' + color : '' }}"
style="color: {{ active ? activeColor : inactiveColor }}"
bind:tap="onClick"
>
<view class="{{ utils.bem('tabbar-item__icon', { dot }) }}">
<view class="van-tabbar-item__icon">
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
customStyle="display: block"
custom-class="van-tabbar-item__icon__inner"
/>
<block wx:else>
<slot
......@@ -19,9 +19,9 @@
<slot wx:else name="icon" />
</block>
<van-info
wx:if="{{ info !== null }}"
dot="{{ dot }}"
info="{{ info }}"
custom-style="margin-top: 2px"
custom-class="van-tabbar-item__info"
/>
</view>
<view class="van-tabbar-item__text">
......
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{color:#7d7e80;height:100%;display:-webkit-flex;display:flex;line-height:1;font-size:12px;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-tabbar-item__icon{font-size:18px;margin-bottom:5px;position:relative}.van-tabbar-item__icon--dot:after{top:0;right:-8px;width:8px;height:8px;content:" ";position:absolute;border-radius:100%;background-color:#f44}.van-tabbar-item__icon image{width:30px;height:18px;display:block}.van-tabbar-item--active{color:#1989fa}
\ No newline at end of file
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;height:100%;color:#7d7e80;color:var(--tabbar-item-text-color,#7d7e80);font-size:12px;font-size:var(--tabbar-item-font-size,12px);line-height:1;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{position:relative;margin-bottom:5px;margin-bottom:var(--tabbar-item-margin-bottom,5px);font-size:18px;font-size:var(--tabbar-item-icon-size,18px)}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:#1989fa;color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
relation: {
name: 'tabbar-item',
type: 'descendant',
linked(target) {
this.children = this.children || [];
this.children.push(target);
this.setActiveItem();
target.parent = this;
target.updateFromParent();
},
unlinked(target) {
this.children = this.children || [];
this.children = this.children.filter(item => item !== target);
this.setActiveItem();
this.children = this.children.filter((item) => item !== target);
this.updateChildren();
}
},
props: {
active: Number,
activeColor: String,
active: {
type: null,
observer: 'updateChildren'
},
activeColor: {
type: String,
observer: 'updateChildren'
},
inactiveColor: {
type: String,
observer: 'updateChildren'
},
fixed: {
type: Boolean,
value: true
},
border: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 1
}
},
watch: {
active(active) {
this.currentActive = active;
this.setActiveItem();
safeAreaInsetBottom: {
type: Boolean,
value: true
}
},
created() {
this.currentActive = this.data.active;
beforeCreate() {
this.children = [];
},
methods: {
setActiveItem() {
if (!Array.isArray(this.children) || !this.children.length) {
updateChildren() {
const { children } = this;
if (!Array.isArray(children) || !children.length) {
return Promise.resolve();
}
return Promise.all(this.children.map((item, index) => item.setActive({
active: index === this.currentActive,
color: this.data.activeColor
})));
return Promise.all(children.map((child) => child.updateFromParent()));
},
onChange(child) {
const active = (this.children || []).indexOf(child);
if (active !== this.currentActive && active !== -1) {
this.currentActive = active;
this.setActiveItem().then(() => {
const index = this.children.indexOf(child);
const active = child.data.name || index;
if (active !== this.data.active) {
this.$emit('change', active);
});
}
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class van-hairline--top-bottom {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}"
class="custom-class {{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }) }}"
style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
>
<slot />
......
@import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;background-color:#fff}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:34px}
\ No newline at end of file
@import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;height:var(--tabbar-height,50px);background-color:#fff;background-color:var(--tabbar-background-color,#fff)}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { isDef, addUnit } from '../common/utils';
VantComponent({
mixins: [touch],
classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
relation: {
name: 'tab',
type: 'descendant',
linked(child) {
this.child.push(child);
this.updateTabs(this.data.tabs.concat(child.data));
linked(target) {
target.index = this.children.length;
this.children.push(target);
this.updateTabs();
},
unlinked(child) {
const index = this.child.indexOf(child);
const { tabs } = this.data;
tabs.splice(index, 1);
this.child.splice(index, 1);
this.updateTabs(tabs);
unlinked(target) {
this.children = this.children
.filter((child) => child !== target)
.map((child, index) => {
child.index = index;
return child;
});
this.updateTabs();
}
},
props: {
color: String,
color: {
type: String,
observer: 'setLine'
},
sticky: Boolean,
animated: Boolean,
animated: {
type: Boolean,
observer: 'setTrack'
},
swipeable: Boolean,
lineWidth: {
type: Number,
value: -1
type: [String, Number],
value: -1,
observer: 'setLine'
},
lineHeight: {
type: Number,
value: -1
type: [String, Number],
value: -1,
observer: 'setLine'
},
titleActiveColor: String,
titleInactiveColor: String,
active: {
type: Number,
value: 0
type: [String, Number],
value: 0,
observer(name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
}
},
type: {
type: String,
......@@ -43,6 +62,10 @@ VantComponent({
type: Boolean,
value: true
},
ellipsis: {
type: Boolean,
value: true
},
duration: {
type: Number,
value: 0.3
......@@ -53,12 +76,21 @@ VantComponent({
},
swipeThreshold: {
type: Number,
value: 4
value: 4,
observer(value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis
});
}
},
offsetTop: {
type: Number,
value: 0
}
},
lazyRender: {
type: Boolean,
value: true
},
},
data: {
tabs: [],
......@@ -66,89 +98,114 @@ VantComponent({
scrollLeft: 0,
scrollable: false,
trackStyle: '',
wrapStyle: '',
position: ''
},
watch: {
swipeThreshold() {
this.set({
scrollable: this.child.length > this.data.swipeThreshold
});
},
color: 'setLine',
lineWidth: 'setLine',
lineHeight: 'setLine',
active: 'setActiveTab',
animated: 'setTrack',
offsetTop: 'setWrapStyle'
currentIndex: null,
container: null
},
beforeCreate() {
this.child = [];
this.children = [];
},
mounted() {
this.setData({
container: () => this.createSelectorQuery().select('.van-tabs')
});
this.setLine(true);
this.setTrack();
this.scrollIntoView();
this.getRect('.van-tabs__wrap').then((rect) => {
this.navHeight = rect.height;
this.observerContentScroll();
});
},
destroyed() {
this.createIntersectionObserver().disconnect();
},
methods: {
updateTabs(tabs) {
tabs = tabs || this.data.tabs;
this.set({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
updateTabs() {
const { children = [], data } = this;
this.setData({
tabs: children.map((child) => child.data),
scrollable: this.children.length > data.swipeThreshold || !data.ellipsis
});
this.setActiveTab();
this.setCurrentIndexByName(this.getCurrentName() || data.active);
},
trigger(eventName, index) {
trigger(eventName) {
const { currentIndex } = this.data;
const child = this.children[currentIndex];
this.$emit(eventName, {
index,
title: this.data.tabs[index].title
index: currentIndex,
name: child.getComputedName(),
title: child.data.title
});
},
onTap(event) {
const { index } = event.currentTarget.dataset;
if (this.data.tabs[index].disabled) {
this.trigger('disabled', index);
const child = this.children[index];
if (child.data.disabled) {
this.trigger('disabled');
}
else {
this.trigger('click', index);
this.setActive(index);
this.setCurrentIndex(index);
wx.nextTick(() => {
this.trigger('click');
});
}
},
setActive(active) {
if (active !== this.data.active) {
this.trigger('change', active);
this.set({ active });
this.setActiveTab();
// correct the index of active tab
setCurrentIndexByName(name) {
const { children = [] } = this;
const matched = children.filter((child) => child.getComputedName() === name);
const defaultIndex = (children[0] || {}).index || 0;
this.setCurrentIndex(matched.length ? matched[0].index : defaultIndex);
},
setCurrentIndex(currentIndex) {
const { data, children = [] } = this;
if (!isDef(currentIndex) ||
currentIndex >= children.length ||
currentIndex < 0) {
return;
}
const shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex });
children.forEach((item, index) => {
const active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, this);
}
});
wx.nextTick(() => {
this.setLine();
this.setTrack();
this.scrollIntoView();
this.trigger('input');
if (shouldEmitChange) {
this.trigger('change');
}
});
},
getCurrentName() {
const activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
}
},
setLine(skipTransition) {
if (this.data.type !== 'line') {
return;
}
const { color, active, duration, lineWidth, lineHeight } = this.data;
this.getRect('.van-tab', true).then((rects) => {
const rect = rects[active];
const { color, duration, currentIndex, lineWidth, lineHeight } = this.data;
this.getRect('.van-tab', true).then((rects = []) => {
const rect = rects[currentIndex];
if (rect == null) {
return;
}
const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : '';
const height = lineHeight !== -1
? `height: ${addUnit(lineHeight)}; border-radius: ${addUnit(lineHeight)};`
: '';
let left = rects
.slice(0, active)
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
left += (rect.width - width) / 2;
const transition = skipTransition
? ''
: `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
this.set({
this.setData({
lineStyle: `
${height}
width: ${width}px;
width: ${addUnit(width)};
background-color: ${color};
-webkit-transform: translateX(${left}px);
transform: translateX(${left}px);
......@@ -158,47 +215,18 @@ VantComponent({
});
},
setTrack() {
const { animated, active, duration } = this.data;
if (!animated)
return '';
this.getRect('.van-tabs__content').then((rect) => {
const { width } = rect;
this.set({
const { animated, duration, currentIndex } = this.data;
this.setData({
trackStyle: `
width: ${width * this.child.length}px;
left: ${-1 * active * width}px;
transition: left ${duration}s;
display: -webkit-box;
display: flex;
transform: translate3d(${-100 * currentIndex}%, 0, 0);
-webkit-transition-duration: ${animated ? duration : 0}s;
transition-duration: ${animated ? duration : 0}s;
`
});
const props = { width, animated };
this.child.forEach((item) => {
item.set(props);
});
});
},
setActiveTab() {
this.child.forEach((item, index) => {
const data = {
active: index === this.data.active
};
if (data.active) {
data.inited = true;
}
if (data.active !== item.data.active) {
item.set(data);
}
});
this.set({}, () => {
this.setLine();
this.setTrack();
this.scrollIntoView();
});
},
// scroll active tab into view
scrollIntoView() {
const { active, scrollable } = this.data;
const { currentIndex, scrollable } = this.data;
if (!scrollable) {
return;
}
......@@ -206,15 +234,18 @@ VantComponent({
this.getRect('.van-tab', true),
this.getRect('.van-tabs__nav')
]).then(([tabRects, navRect]) => {
const tabRect = tabRects[active];
const tabRect = tabRects[currentIndex];
const offsetLeft = tabRects
.slice(0, active)
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
this.set({
this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2
});
});
},
onTouchScroll(event) {
this.$emit('scroll', event.detail);
},
onTouchStart(event) {
if (!this.data.swipeable)
return;
......@@ -229,84 +260,17 @@ VantComponent({
onTouchEnd() {
if (!this.data.swipeable)
return;
const { active, tabs } = this.data;
const { tabs, currentIndex } = this.data;
const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
if (deltaX > 0 && active !== 0) {
this.setActive(active - 1);
if (deltaX > 0 && currentIndex !== 0) {
this.setCurrentIndex(currentIndex - 1);
}
else if (deltaX < 0 && active !== tabs.length - 1) {
this.setActive(active + 1);
else if (deltaX < 0 && currentIndex !== tabs.length - 1) {
this.setCurrentIndex(currentIndex + 1);
}
}
},
setWrapStyle() {
const { offsetTop, position } = this.data;
let wrapStyle;
switch (position) {
case 'top':
wrapStyle = `
top: ${offsetTop}px;
position: fixed;
`;
break;
case 'bottom':
wrapStyle = `
top: auto;
bottom: 0;
`;
break;
default:
wrapStyle = '';
}
// cut down `set`
if (wrapStyle === this.data.wrapStyle)
return;
this.set({ wrapStyle });
},
observerContentScroll() {
if (!this.data.sticky) {
return;
}
const { offsetTop } = this.data;
const { windowHeight } = wx.getSystemInfoSync();
this.createIntersectionObserver().disconnect();
this.createIntersectionObserver()
.relativeToViewport({ top: -(this.navHeight + offsetTop) })
.observe('.van-tabs', (res) => {
const { top } = res.boundingClientRect;
if (top > offsetTop) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
this.createIntersectionObserver()
.relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
.observe('.van-tabs', (res) => {
const { top, bottom } = res.boundingClientRect;
if (bottom < this.navHeight) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : '';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
},
setPosition(position) {
if (position !== this.data.position) {
this.set({ position }).then(() => {
this.setWrapStyle();
});
}
}
}
});
......
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
"van-info": "../info/index",
"van-sticky": "../sticky/index"
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="getters" />
<view class="custom-class {{ utils.bem('tabs', [type]) }}">
<view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
<van-sticky
disabled="{{ !sticky }}"
z-index="{{ zIndex }}"
offset-top="{{ offsetTop }}"
container="{{ container }}"
bind:scroll="onTouchScroll"
>
<view class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
<slot name="nav-left" />
<scroll-view
scroll-x="{{ scrollable }}"
scroll-with-animation
scroll-left="{{ scrollLeft }}"
class="van-tabs__scroll--{{ type }}"
class="{{ utils.bem('tabs__scroll', [type]) }}"
style="{{ color ? 'border-color: ' + color : '' }}"
>
<view class="{{ utils.bem('tabs__nav', [type]) }} nav-class">
......@@ -17,15 +25,16 @@
wx:for="{{ tabs }}"
wx:key="index"
data-index="{{ index }}"
class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}"
style="{{ color && index !== active && type === 'card' && !item.disabled ? 'color: ' + color : '' }} {{ color && index === active && type === 'card' ? ';background-color:' + color : '' }} {{ color ? ';border-color: ' + color : '' }} {{ scrollable ? ';flex-basis:' + (88 / swipeThreshold) + '%' : '' }}"
class="{{ getters.tabClass(index === currentIndex, ellipsis) }} {{ utils.bem('tab', { active: index === currentIndex, disabled: item.disabled, complete: !ellipsis }) }}"
style="{{ getters.tabStyle(index === currentIndex, ellipsis, color, type, item.disabled, titleActiveColor, titleInactiveColor, swipeThreshold, scrollable) }}"
bind:tap="onTap"
>
<view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}">
<view class="{{ ellipsis ? 'van-ellipsis' : '' }}" style="{{ item.titleStyle }}">
{{ item.title }}
<van-info
wx:if="{{ item.info !== null }}"
wx:if="{{ item.info !== null || item.dot }}"
info="{{ item.info }}"
dot="{{ item.dot }}"
custom-class="van-tab__title__info"
/>
</view>
......@@ -35,6 +44,8 @@
<slot name="nav-right" />
</view>
</van-sticky>
<view
class="van-tabs__content"
bind:touchstart="onTouchStart"
......
/* eslint-disable */
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(
active,
ellipsis,
color,
type,
disabled,
activeColor,
inactiveColor,
swipeThreshold,
scrollable
) {
var styles = [];
var isCard = type === 'card';
// card theme color
if (color && isCard) {
styles.push('border-color:' + color);
if (!disabled) {
if (active) {
styles.push('background-color:' + color);
} else {
styles.push('color:' + color);
}
}
}
var titleColor = active ? activeColor : inactiveColor;
if (titleColor) {
styles.push('color:' + titleColor);
}
if (scrollable && ellipsis) {
styles.push('flex-basis:' + 88 / swipeThreshold + '%');
}
return styles.join(';');
}
module.exports.tabClass = tabClass;
module.exports.tabStyle = tabStyle;
@import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{position:absolute;top:0;right:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-tabs__wrap--page-top{position:fixed}.van-tabs__wrap--content-bottom{top:auto;bottom:0}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll--card{border:1px solid #f44;border-radius:2px}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--line{height:100%}.van-tabs__nav--card{height:30px}.van-tabs__nav--card .van-tab{line-height:30px;color:#f44;border-right:1px solid #f44}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;background-color:#f44}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;background-color:#f44;border-radius:3px}.van-tabs--line{padding-top:44px}.van-tabs--line .van-tabs__wrap{height:44px}.van-tabs--card{padding-top:30px;margin:0 15px}.van-tabs--card .van-tabs__wrap{height:30px}.van-tabs__content{overflow:hidden}.van-tab,.van-tabs__track{position:relative}.van-tab{min-width:0;padding:0 5px;font-size:14px;line-height:44px;color:#7d7e80;text-align:center;cursor:pointer;box-sizing:border-box;-webkit-flex:1;flex:1}.van-tab--active{font-weight:500;color:#333}.van-tab--disabled{color:#c9c9c9}.van-tab__title--dot:after{display:inline-block;width:8px;height:8px;vertical-align:middle;background-color:#f44;border-radius:100%;content:""}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
\ No newline at end of file
@import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{display:-webkit-flex;display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll{background-color:#fff;background-color:var(--tabs-nav-background-color,#fff)}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{margin:0 16px;margin:0 var(--padding-md,16px)}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:30px;height:var(--tabs-card-height,30px);border:1px solid #ee0a24;border:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24);border-radius:2px;border-radius:var(--border-radius-sm,2px)}.van-tabs__nav--card .van-tab{color:#ee0a24;color:var(--tabs-default-color,#ee0a24);line-height:28px;line-height:calc(var(--tabs-card-height, 30px) - 2*var(--border-width-base, 1px));border-right:1px solid #ee0a24;border-right:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;color:var(--white,#fff);background-color:#ee0a24;background-color:var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;height:var(--tabs-bottom-bar-height,3px);border-radius:3px;border-radius:var(--tabs-bottom-bar-height,3px);background-color:#ee0a24;background-color:var(--tabs-bottom-bar-color,#ee0a24)}.van-tabs__track{position:relative;display:-webkit-flex;display:flex;width:100%;height:100%;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-tabs__content{overflow:hidden}.van-tabs--line .van-tabs__wrap{height:44px;height:var(--tabs-line-height,44px)}.van-tabs--card .van-tabs__wrap{height:30px;height:var(--tabs-card-height,30px)}.van-tab{position:relative;-webkit-flex:1;flex:1;box-sizing:border-box;min-width:0;padding:0 5px;text-align:center;cursor:pointer;color:#7d7e80;color:var(--tab-text-color,#7d7e80);font-size:14px;font-size:var(--tab-font-size,14px);line-height:44px;line-height:var(--tabs-line-height,44px)}.van-tab--active{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--tab-active-text-color,#323233)}.van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab--complete{-webkit-flex:1 0 auto!important;flex:1 0 auto!important}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { RED, BLUE, GREEN } from '../common/color';
const DEFAULT_COLOR = '#999';
const COLOR_MAP = {
danger: RED,
primary: BLUE,
success: GREEN
};
VantComponent({
props: {
size: String,
type: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String
textColor: String,
type: {
type: String,
value: 'default'
},
computed: {
style() {
const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR;
const key = this.data.plain ? 'color' : 'background-color';
const style = { [key]: color };
if (this.data.textColor) {
style.color = this.data.textColor;
}
return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
closeable: Boolean
},
methods: {
onClose() {
this.$emit('close');
}
}
});
......
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
style="{{ style }}"
class="custom-class {{ utils.bem('tag', [type, size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
style="{{ color && !plain ? 'background-color: ' + color + ';' : '' }}{{ textColor || (color && plain) ? 'color: ' + (textColor || color) : '' }}"
>
<slot />
<van-icon
wx:if="{{ closeable }}"
name="cross"
custom-class="van-tag__close"
bind:click="onClose"
/>
</view>
......
@import '../common/index.wxss';.van-tag{color:#fff;font-size:10px;padding:.2em .5em;line-height:normal;border-radius:.2em;display:inline-block}.van-tag:after{border-color:currentColor;border-radius:.4em}.van-tag--mark{padding-right:.6em;border-radius:0 .8em .8em 0}.van-tag--mark:after{border-radius:0 1.6em 1.6em 0}.van-tag--round{border-radius:.8em}.van-tag--round:after{border-radius:1.6em}.van-tag--medium{font-size:12px}.van-tag--large{font-size:14px}
\ No newline at end of file
@import '../common/index.wxss';.van-tag{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;line-height:normal;padding:.2em .5em;padding:var(--tag-padding,.2em .5em);color:#fff;color:var(--tag-text-color,#fff);font-size:10px;font-size:var(--tag-font-size,10px);border-radius:.2em;border-radius:var(--tag-border-radius,.2em)}.van-tag:after{border-color:currentColor;border-radius:.2em * 2;border-radius:var(--tag-border-radius,.2em) * 2}.van-tag--default{background-color:#969799;background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:#969799;color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:#ee0a24;background-color:var(--tag-dander-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:#ee0a24;color:var(--tag-dander-color,#ee0a24)}.van-tag--primary{background-color:#1989fa;background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:#1989fa;color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:#07c160;background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:#07c160;color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:#ff976a;background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:#ff976a;color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:#fff;background-color:var(--tag-plain-background-color,#fff)}.van-tag--mark{padding-right:.7em}.van-tag--mark,.van-tag--mark:after{border-radius:0 999px 999px 0;border-radius:0 var(--tag-round-border-radius,999px) var(--tag-round-border-radius,999px) 0}.van-tag--round,.van-tag--round:after{border-radius:999px;border-radius:var(--tag-round-border-radius,999px)}.van-tag--medium{font-size:12px;font-size:var(--tag-medium-font-size,12px)}.van-tag--large{font-size:14px;font-size:var(--tag-large-font-size,14px)}.van-tag__close{margin-left:2px}
\ No newline at end of file
......
......@@ -23,11 +23,6 @@ VantComponent({
}
},
methods: {
clear() {
this.set({
show: false
});
},
// for prevent touchmove
noop() { }
}
......
<van-overlay
wx:if="{{ mask || forbidClick }}"
show="{{ show }}"
mask="{{ mask }}"
z-index="{{ zIndex }}"
custom-style="{{ mask ? '' : 'background-color: transparent;' }}"
/>
<van-transition
show="{{ show }}"
......@@ -27,5 +27,7 @@
<van-icon wx:else class="van-toast__icon" name="{{ type }}" />
<text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
</block>
<slot />
</view>
</van-transition>
......
@import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;color:#fff;font-size:14px;line-height:20px;border-radius:4px;word-break:break-all;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;box-sizing:initial;background-color:rgba(51,51,51,.88);white-space:pre-wrap}.van-toast__container{position:fixed;top:50%;left:50%;max-width:70%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-toast--text{padding:8px 12px;min-width:96px}.van-toast--icon{width:90px;padding:15px;min-height:90px}.van-toast--icon .van-toast__icon{font-size:48px}.van-toast--icon .van-toast__text{padding-top:5px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
\ No newline at end of file
@import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:initial;color:#fff;color:var(--toast-text-color,#fff);font-size:14px;font-size:var(--toast-font-size,14px);line-height:20px;line-height:var(--toast-line-height,20px);white-space:pre-wrap;word-wrap:break-word;background-color:rgba(50,50,51,.88);background-color:var(--toast-background-color,rgba(50,50,51,.88));border-radius:4px;border-radius:var(--toast-border-radius,4px)}.van-toast__container{position:fixed;top:50%;left:50%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);max-width:70%;max-width:var(--toast-max-width,70%)}.van-toast--text{min-width:96px;min-width:var(--toast-text-min-width,96px);padding:8px 12px;padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{width:90px;width:var(--toast-default-width,90px);min-height:90px;min-height:var(--toast-default-min-height,90px);padding:16px;padding:var(--toast-default-padding,16px)}.van-toast--icon .van-toast__icon{font-size:48px;font-size:var(--toast-icon-size,48px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
\ No newline at end of file
......
/// <reference types="miniprogram-api-typings" />
declare type ToastMessage = string | number;
export declare type ToastOptions = {
interface ToastOptions {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: any;
context?: WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
};
export interface Toast {
(message: ToastOptions | ToastMessage, options?: ToastOptions): Weapp.Component;
loading?(options?: ToastOptions | ToastMessage): Weapp.Component;
success?(options?: ToastOptions | ToastMessage): Weapp.Component;
fail?(options?: ToastOptions | ToastMessage): Weapp.Component;
clear?(): void;
setDefaultOptions?(options: ToastOptions): void;
resetDefaultOptions?(): void;
onClose?: () => void;
}
declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance;
declare namespace Toast {
var loading: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
var success: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
var fail: (options: string | number | ToastOptions) => WechatMiniprogram.Component.Instance<Record<string, any>, Record<string, any>, Record<string, any>>;
var clear: () => void;
var setDefaultOptions: (options: ToastOptions) => void;
var resetDefaultOptions: () => void;
}
declare const Toast: Toast;
export default Toast;
......
......@@ -5,7 +5,7 @@ const defaultOptions = {
message: '',
show: true,
zIndex: 1000,
duration: 3000,
duration: 2000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
......@@ -20,8 +20,8 @@ function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Toast = (options = {}) => {
options = Object.assign({}, currentOptions, parseOptions(options));
function Toast(toastOptions) {
const options = Object.assign(Object.assign({}, currentOptions), parseOptions(toastOptions));
const context = options.context || getContext();
const toast = context.selectComponent(options.selector);
if (!toast) {
......@@ -30,8 +30,14 @@ const Toast = (options = {}) => {
}
delete options.context;
delete options.selector;
toast.clear = () => {
toast.setData({ show: false });
if (options.onClose) {
options.onClose();
}
};
queue.push(toast);
toast.set(options);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration > 0) {
toast.timer = setTimeout(() => {
......@@ -40,18 +46,18 @@ const Toast = (options = {}) => {
}, options.duration);
}
return toast;
};
const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options)));
['loading', 'success', 'fail'].forEach(method => {
Toast[method] = createMethod(method);
});
}
const createMethod = (type) => (options) => Toast(Object.assign({ type }, parseOptions(options)));
Toast.loading = createMethod('loading');
Toast.success = createMethod('success');
Toast.fail = createMethod('fail');
Toast.clear = () => {
queue.forEach(toast => {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = options => {
Toast.setDefaultOptions = (options) => {
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = () => {
......
@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
\ No newline at end of file
@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);opacity:0}.van-fade-down-enter,.van-fade-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);opacity:0}.van-fade-left-enter,.van-fade-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.van-fade-right-enter,.van-fade-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
const ITEM_HEIGHT = 44;
import { addUnit } from '../common/utils';
VantComponent({
classes: [
'main-item-class',
......@@ -10,47 +10,50 @@ VantComponent({
'content-disabled-class'
],
props: {
items: Array,
items: {
type: Array,
observer: 'updateSubItems'
},
activeId: null,
mainActiveIndex: {
type: Number,
value: 0
value: 0,
observer: 'updateSubItems'
},
activeId: {
type: [Number, String]
height: {
type: [Number, String],
value: 300,
observer: 'updateHeight'
},
maxHeight: {
max: {
type: Number,
value: 300
value: Infinity
}
},
data: {
subItems: [],
mainHeight: 0,
itemHeight: 0
},
watch: {
items() {
this.updateSubItems().then(() => {
this.updateMainHeight();
});
},
maxHeight() {
this.updateItemHeight(this.data.subItems);
this.updateMainHeight();
subItems: []
},
mainActiveIndex: 'updateSubItems'
created() {
this.updateHeight();
},
methods: {
// 当一个子项被选择时
onSelectItem(event) {
const { item } = event.currentTarget.dataset;
if (!item.disabled) {
const isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
const isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
const isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav(event) {
const { index } = event.currentTarget.dataset;
const index = event.detail;
const item = this.data.items[index];
if (!item.disabled) {
this.$emit('click-nav', { index });
......@@ -60,19 +63,12 @@ VantComponent({
updateSubItems() {
const { items, mainActiveIndex } = this.data;
const { children = [] } = items[mainActiveIndex] || {};
this.updateItemHeight(children);
return this.set({ subItems: children });
},
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
updateMainHeight() {
const { items = [], subItems = [] } = this.data;
const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT);
this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
},
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
updateItemHeight(subItems) {
const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
return this.set({ itemHeight });
updateHeight() {
this.setData({
innerHeight: addUnit(this.data.height)
});
}
}
});
......
......@@ -2,6 +2,7 @@
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-cell": "../cell/index"
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
}
}
......
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="wxs" />
<view
class="van-tree-select"
style="height: {{ mainHeight }}px"
style="height: {{ innerHeight }}"
>
<scroll-view scroll-y class="van-tree-select__nav">
<view
<van-sidebar bind:change="onClickNav" custom-class="van-tree-select__nav__inner">
<van-sidebar-item
wx:for="{{ items }}"
wx:key="index"
class="van-ellipsis main-item-class {{ utils.bem('tree-select__nitem', { active: mainActiveIndex === index, disabled: item.disabled }) }} {{ mainActiveIndex === index ? 'main-active-class' : '' }} {{ item.disabled ? 'main-disabled-class' : '' }}"
data-index="{{ index }}"
bind:tap="onClickNav"
>
{{ item.text }}
</view>
custom-class="main-item-class"
active-class="main-active-class"
disabled-class="main-disabled-class"
title="{{ item.text }}"
disabled="{{ item.disabled }}"
/>
</van-sidebar>
</scroll-view>
<scroll-view
scroll-y
class="van-tree-select__content"
style="height: {{ itemHeight }}px"
>
<scroll-view scroll-y class="van-tree-select__content">
<slot name="content" />
<view
wx:for="{{ subItems }}"
wx:key="id"
class="van-ellipsis van-hairline--bottom content-item-class {{ utils.bem('tree-select__item', { active: activeId === item.id, disabled: item.disabled }) }} {{ activeId === item.id ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
class="van-ellipsis content-item-class {{ utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }) }} {{ wxs.isActive(activeId, item.id) ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
data-item="{{ item }}"
bind:tap="onSelectItem"
>
{{ item.text }}
<van-icon
wx:if="{{ activeId === item.id }}"
wx:if="{{ wxs.isActive(activeId, item.id) }}"
name="checked"
size="16px"
class="van-tree-select__selected"
......
/* eslint-disable */
var array = require('../wxs/array.wxs');
function isActive (activeList, itemId) {
if (array.isArray(activeList)) {
return activeList.indexOf(itemId) > -1;
}
return activeList === itemId;
}
module.exports.isActive = isActive;
@import '../common/index.wxss';.van-tree-select{position:relative;font-size:14px;-webkit-user-select:none;user-select:none}.van-tree-select__nav{position:absolute;top:0;bottom:0;left:0;width:35%;min-width:120px;background-color:#fafafa}.van-tree-select__nitem{position:relative;padding:0 9px 0 15px;line-height:44px}.van-tree-select__nitem--active:after{position:absolute;top:0;bottom:0;left:0;width:3.6px;background-color:#f44;content:""}.van-tree-select__nitem--active{font-weight:700;background-color:#fff}.van-tree-select__nitem--disabled{color:#999}.van-tree-select__content{width:65%;padding-left:15px;margin-left:35%;background-color:#fff;box-sizing:border-box}.van-tree-select__item{position:relative;font-weight:700;line-height:44px}.van-tree-select__item--active{color:#f44}.van-tree-select__item--disabled{color:#999}.van-tree-select__selected{position:absolute;top:0;right:15px;bottom:0;height:24px;margin:auto 0;line-height:24px}
\ No newline at end of file
@import '../common/index.wxss';.van-tree-select{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;font-size:14px;font-size:var(--tree-select-font-size,14px)}.van-tree-select__nav{-webkit-flex:1;flex:1;background-color:#fafafa;background-color:var(--tree-select-nav-background-color,#fafafa);--sidebar-padding:12px 8px 12px 12px}.van-tree-select__nav__inner{width:100%!important;height:100%}.van-tree-select__content{-webkit-flex:2;flex:2;background-color:#fff;background-color:var(--tree-select-content-background-color,#fff)}.van-tree-select__item{position:relative;font-weight:700;padding:0 32px 0 16px;padding:0 32px 0 var(--padding-md,16px);line-height:44px;line-height:var(--tree-select-item-height,44px)}.van-tree-select__item--active{color:#ee0a24;color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:#c8c9cc;color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:16px;right:var(--padding-md,16px)}
\ No newline at end of file
......
import { VantComponent } from '../common/component';
import { isImageFile } from './utils';
import { addUnit } from '../common/utils';
VantComponent({
props: {
disabled: Boolean,
multiple: Boolean,
uploadText: String,
previewSize: {
type: null,
value: 90,
observer: 'setComputedPreviewSize'
},
name: {
type: [Number, String],
value: ''
},
accept: {
type: String,
value: 'image'
},
fileList: {
type: Array,
value: [],
observer: 'formatFileList'
},
maxSize: {
type: Number,
value: Number.MAX_VALUE
},
maxCount: {
type: Number,
value: 100
},
previewImage: {
type: Boolean,
value: true
},
previewFullImage: {
type: Boolean,
value: true
},
imageFit: {
type: String,
value: 'scaleToFill'
},
useSlot: Boolean,
useBeforeRead: Boolean
},
data: {
lists: [],
computedPreviewSize: '',
isInCount: true
},
methods: {
formatFileList() {
const { fileList = [], maxCount } = this.data;
const lists = fileList.map(item => (Object.assign(Object.assign({}, item), { isImage: typeof item.isImage === 'undefined'
? isImageFile(item)
: item.isImage })));
this.setData({ lists, isInCount: lists.length < maxCount });
},
setComputedPreviewSize(val) {
this.setData({
computedPreviewSize: addUnit(val)
});
},
startUpload() {
if (this.data.disabled)
return;
const { name = '', capture = ['album', 'camera'], maxCount = 100, multiple = false, maxSize, accept, lists, useBeforeRead = false // 是否定义了 beforeRead
} = this.data;
let chooseFile = null;
const newMaxCount = maxCount - lists.length;
// 设置为只选择图片的时候使用 chooseImage 来实现
if (accept === 'image') {
chooseFile = new Promise((resolve, reject) => {
wx.chooseImage({
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
sourceType: capture,
success: resolve,
fail: reject
});
});
}
else {
chooseFile = new Promise((resolve, reject) => {
wx.chooseMessageFile({
count: multiple ? newMaxCount : 1,
type: 'file',
success: resolve,
fail: reject
});
});
}
chooseFile.then((res) => {
const file = multiple ? res.tempFiles : res.tempFiles[0];
// 检查文件大小
if (file instanceof Array) {
const sizeEnable = file.every(item => item.size <= maxSize);
if (!sizeEnable) {
this.$emit('oversize', { name });
return;
}
}
else if (file.size > maxSize) {
this.$emit('oversize', { name });
return;
}
// 触发上传之前的钩子函数
if (useBeforeRead) {
this.$emit('before-read', {
file,
name,
callback: (result) => {
if (result) {
// 开始上传
this.$emit('after-read', { file, name });
}
}
});
}
else {
this.$emit('after-read', { file, name });
}
});
},
deleteItem(event) {
const { index } = event.currentTarget.dataset;
this.$emit('delete', { index, name: this.data.name });
},
doPreviewImage(event) {
if (!this.data.previewFullImage)
return;
const curUrl = event.currentTarget.dataset.url;
const images = this.data.lists
.filter(item => item.isImage)
.map(item => item.url || item.path);
this.$emit('click-preview', { url: curUrl, name: this.data.name });
wx.previewImage({
urls: images,
current: curUrl,
fail() {
wx.showToast({ title: '预览图片失败', icon: 'none' });
}
});
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="van-uploader"
>
<view class="van-uploader__wrapper">
<!-- 预览样式 -->
<block wx:if="{{ previewImage }}">
<view
wx:for="{{ lists }}"
wx:key="{{ index }}"
class="van-uploader__preview"
>
<image
wx:if="{{ item.isImage }}"
mode="{{ imageFit }}"
src="{{ item.url || item.path }}"
alt="{{ item.name || ('图片' + index) }}"
class="van-uploader__preview-image"
style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
data-url="{{ item.url || item.path }}"
bind:tap="doPreviewImage"
/>
<view
wx:else
class="van-uploader__file"
style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
>
<van-icon name="description" class="van-uploader__file-icon" />
<view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url || item.path }}</view>
</view>
<van-icon
name="delete"
class="van-uploader__preview-delete"
bind:tap="deleteItem"
data-index="{{ index }}"
/>
</view>
</block>
<!-- 上传样式 -->
<block wx:if="{{ isInCount }}">
<block wx:if="{{ useSlot }}">
<view class="van-uploader__slot" bind:tap="startUpload">
<slot />
</view>
</block>
<block wx:else>
<!-- 默认上传样式 -->
<view
class="van-uploader__upload"
style="width: {{ computedPreviewSize }}px; height: {{ computedPreviewSize }}px;"
bind:tap="startUpload"
>
<van-icon name="plus" class="van-uploader__upload-icon" />
<text wx:if="{{ uploadText }}" class="van-uploader__upload-text">{{ uploadText }}</text>
</view>
</block>
</block>
</view>
</view>
@import '../common/index.wxss';.van-uploader{position:relative;display:inline-block}.van-uploader__wrapper{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.van-uploader__upload{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:80px;height:80px;margin:0 8px 8px 0;background-color:#fff;border:1px dashed #e5e5e5}.van-uploader__upload-icon{display:inline-block;width:24px;height:24px;color:#969799;font-size:24px}.van-uploader__upload-text{margin-top:8px;color:#969799;font-size:12px}.van-uploader__preview{position:relative;margin:0 8px 8px 0}.van-uploader__preview-image{display:block;width:80px;height:80px}.van-uploader__preview-delete{position:absolute;right:0;bottom:0;display:inline-block;width:18px;height:18px;padding:1px;color:#fff;text-align:center;background-color:rgba(0,0,0,.45)}.van-uploader__file{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;width:80px;height:80px;background-color:#f8f8f8}.van-uploader__file-icon{display:inline-block;width:20px;height:20px;color:#7d7e80;font-size:20px}.van-uploader__file-name{box-sizing:border-box;width:100%;margin-top:8px;padding:0 5px;color:#7d7e80;font-size:12px;text-align:center}
\ No newline at end of file
interface File {
path: string;
url: string;
size: number;
name: string;
type: string;
time: number;
image: boolean;
}
export declare function isImageUrl(url: string): boolean;
export declare function isImageFile(item: File): boolean;
export {};
const IMAGE_EXT = ['jpeg', 'jpg', 'gif', 'png', 'svg'];
export function isImageUrl(url) {
return IMAGE_EXT.some(ext => url.indexOf(`.${ext}`) !== -1);
}
export function isImageFile(item) {
if (item.type) {
return item.type.indexOf('image') === 0;
}
if (item.path) {
return isImageUrl(item.path);
}
if (item.url) {
return isImageUrl(item.url);
}
return false;
}
var bem = require('./bem.wxs').bem;
var memoize = require('./memoize.wxs').memoize;
function isSrc(url) {
return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
}
module.exports = {
bem: memoize(bem),
isSrc: isSrc,
memoize: memoize
};
......
......@@ -4,8 +4,6 @@ var filter = {
var result = val * 0.01; //分到元
// result += ''; //转成字符串
// result = result.toFixed(2); //留两位小数
console.log("val:",val);
console.log("result:",result);
return result.toFixed(2);
},
// 毫秒转格式
......