diff --git a/examples/wxcomponents-template/App.vue b/examples/wxcomponents-template/App.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c44f2a168a1861d16c464c4376bf19283f088f6a
--- /dev/null
+++ b/examples/wxcomponents-template/App.vue
@@ -0,0 +1,25 @@
+
+
+
diff --git a/examples/wxcomponents-template/README.md b/examples/wxcomponents-template/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4acc08878901eaa2ecca2931acb6b79ff27f9bdb
--- /dev/null
+++ b/examples/wxcomponents-template/README.md
@@ -0,0 +1,12 @@
+# 小程序自定义组件使用示例
+
+## 注意事项
+* 小程序自定义组件需放在wxcomponents目录
+* 使用的组件需添加到pages.json文件内
+* 原组件内事件名称需修改为驼峰命名,如:
+```js
+// wxcomponents/vant-weapp/dist/nav-bar/index.js
+this.$emit('click-left');
+// 改为
+this.$emit('clickLeft');
+```
\ No newline at end of file
diff --git a/examples/wxcomponents-template/main.js b/examples/wxcomponents-template/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..0656173c0697ae240062bb8648a95ce73e63a46b
--- /dev/null
+++ b/examples/wxcomponents-template/main.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import App from './App'
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+ ...App
+})
+app.$mount()
diff --git a/examples/wxcomponents-template/manifest.json b/examples/wxcomponents-template/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..f098ca4fcba18ad213fbd319c428b86f5a3fc205
--- /dev/null
+++ b/examples/wxcomponents-template/manifest.json
@@ -0,0 +1,55 @@
+{
+ "name" : "wxcomponents-template",
+ "appid" : "__UNI__773C51E",
+ "description": "",
+ "versionName": "1.0.0",
+ "versionCode": "100",
+ "transformPx":false,
+ "app-plus": { /* 5+App特有相关 */
+ "modules": { /* 模块配置 */
+
+ },
+ "distribute": { /* 应用发布信息 */
+ "android": { /* android打包配置 */
+ "permissions": ["",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ "ios": { /* ios打包配置 */
+
+ },
+ "sdkConfigs": { /* SDK配置 */
+
+ }
+ }
+ },
+ "quickapp": { /* 快应用特有相关 */
+
+ },
+ "mp-weixin": { /* 小程序特有相关 */
+ "appid": "",
+ "setting" : {
+ "urlCheck" : true
+ }
+ }
+}
diff --git a/examples/wxcomponents-template/pages.json b/examples/wxcomponents-template/pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..9714c6100dbd4bb114b5bfc71799aab6d3a745e0
--- /dev/null
+++ b/examples/wxcomponents-template/pages.json
@@ -0,0 +1,37 @@
+{
+ "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+ {
+ "path": "pages/index/index",
+ "style": {
+ "navigationBarTitleText": "小程序组件示例"
+ }
+ },
+ {
+ "path": "pages/vant/vant",
+ "style": {
+ "navigationBarTitleText": "vant组件示例",
+ "usingComponents": {
+ "van-nav-bar": "/wxcomponents/vant-weapp/dist/nav-bar/index",
+ "van-icon": "/wxcomponents/vant-weapp/dist/icon/index"
+ }
+ }
+ },
+ {
+ "path": "pages/wux/wux",
+ "style": {
+ "navigationBarTitleText": "wux组件示例",
+ "usingComponents": {
+ "wux-calendar": "/wxcomponents/wux-weapp/dist/calendar/index",
+ "wux-cell-group": "/wxcomponents/wux-weapp/dist/cell-group/index",
+ "wux-cell": "/wxcomponents/wux-weapp/dist/cell/index"
+ }
+ }
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "小程序组件示例",
+ "navigationBarBackgroundColor": "#F8F8F8",
+ "backgroundColor": "#F8F8F8"
+ }
+}
diff --git a/examples/wxcomponents-template/pages/index/index.vue b/examples/wxcomponents-template/pages/index/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ac3d2ce424e8a75e86e7bb95d36e40a6e12ddd7a
--- /dev/null
+++ b/examples/wxcomponents-template/pages/index/index.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/wxcomponents-template/pages/vant/vant.vue b/examples/wxcomponents-template/pages/vant/vant.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2773013779445e89b5cfca958f9de2d2ec42b88e
--- /dev/null
+++ b/examples/wxcomponents-template/pages/vant/vant.vue
@@ -0,0 +1,32 @@
+
+
+ 导航栏
+
+
+
+
+
+
+
+
+
diff --git a/examples/wxcomponents-template/pages/wux/wux.vue b/examples/wxcomponents-template/pages/wux/wux.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7ca6c7e5f594d597e8334dc32adc9678e8b42b85
--- /dev/null
+++ b/examples/wxcomponents-template/pages/wux/wux.vue
@@ -0,0 +1,80 @@
+
+
+ 日历组件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/wxcomponents-template/static/.gitkeep b/examples/wxcomponents-template/static/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.js b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba24cbba877d8d9cf18656717dd589bdaa800347
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.js
@@ -0,0 +1,20 @@
+import { create } from '../common/create';
+
+create({
+ props: {
+ info: null,
+ name: String,
+ size: String,
+ color: String,
+ classPrefix: {
+ type: String,
+ value: 'van-icon'
+ }
+ },
+
+ methods: {
+ onClick() {
+ this.$emit('click');
+ }
+ }
+});
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.json b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..467ce2945f917ae0035594117b51f5304cdcdfa6
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxml b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxml
new file mode 100644
index 0000000000000000000000000000000000000000..2ea3e9fbacd16c3f6c524195dc001575090314a4
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxml
@@ -0,0 +1,7 @@
+
+ {{ info }}
+
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxss b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxss
new file mode 100644
index 0000000000000000000000000000000000000000..59f39c5e71fb7223f9b7624105518d8a772fa658
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/icon/index.wxss
@@ -0,0 +1 @@
+@font-face{font-style:normal;font-weight:400;font-family:vant-icon;src:url(https://img.yzcdn.cn/vant/vant-icon-76f274.ttf) format('truetype')}.van-icon{position:relative;display:inline-block;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto}.van-icon__info{color:#fff;left:100%;top:-.5em;font-size:.5em;padding:0 .3em;text-align:center;min-width:1.2em;line-height:1.2;position:absolute;border-radius:.6em;box-sizing:border-box;background-color:#f44;-webkit-transform:translateX(-50%);transform:translateX(-50%);font-family:PingFang SC,Helvetica Neue,Arial,sans-serif}.van-icon::before{display:inline-block}.van-icon-add-o::before{content:"\F000"}.van-icon-add::before{content:"\F001"}.van-icon-add2::before{content:"\F002"}.van-icon-after-sale::before{content:"\F003"}.van-icon-aim::before{content:"\F004"}.van-icon-alipay::before{content:"\F005"}.van-icon-arrow-left::before{content:"\F006"}.van-icon-arrow::before{content:"\F007"}.van-icon-balance-pay::before{content:"\F008"}.van-icon-browsing-history::before{content:"\F009"}.van-icon-card::before{content:"\F00A"}.van-icon-cart::before{content:"\F00B"}.van-icon-cash-back-record::before{content:"\F00C"}.van-icon-cash-on-deliver::before{content:"\F00D"}.van-icon-certificate::before{content:"\F00E"}.van-icon-chat::before{content:"\F00F"}.van-icon-check::before{content:"\F010"}.van-icon-checked::before{content:"\F011"}.van-icon-clear::before{content:"\F012"}.van-icon-clock::before{content:"\F013"}.van-icon-close::before{content:"\F014"}.van-icon-completed::before{content:"\F015"}.van-icon-contact::before{content:"\F016"}.van-icon-coupon::before{content:"\F017"}.van-icon-credit-pay::before{content:"\F018"}.van-icon-debit-pay::before{content:"\F019"}.van-icon-delete::before{content:"\F01A"}.van-icon-description::before{content:"\F01B"}.van-icon-discount::before{content:"\F01C"}.van-icon-ecard-pay::before{content:"\F01D"}.van-icon-edit-data::before{content:"\F01E"}.van-icon-edit::before{content:"\F01F"}.van-icon-exchange-record::before{content:"\F020"}.van-icon-exchange::before{content:"\F021"}.van-icon-fail::before{content:"\F022"}.van-icon-free-postage::before{content:"\F023"}.van-icon-gift-card-pay::before{content:"\F024"}.van-icon-gift-card::before{content:"\F025"}.van-icon-gift::before{content:"\F026"}.van-icon-gold-coin::before{content:"\F027"}.van-icon-goods-collect::before{content:"\F028"}.van-icon-home::before{content:"\F029"}.van-icon-hot-sale::before{content:"\F02A"}.van-icon-hot::before{content:"\F02B"}.van-icon-idcard::before{content:"\F02C"}.van-icon-info-o::before{content:"\F02D"}.van-icon-like-o::before{content:"\F02E"}.van-icon-like::before{content:"\F02F"}.van-icon-location::before{content:"\F030"}.van-icon-logistics::before{content:"\F031"}.van-icon-more-o::before{content:"\F032"}.van-icon-more::before{content:"\F033"}.van-icon-new-arrival::before{content:"\F034"}.van-icon-new::before{content:"\F035"}.van-icon-other-pay::before{content:"\F036"}.van-icon-passed::before{content:"\F037"}.van-icon-password-not-view::before{content:"\F038"}.van-icon-password-view::before{content:"\F039"}.van-icon-pause::before{content:"\F03A"}.van-icon-peer-pay::before{content:"\F03B"}.van-icon-pending-deliver::before{content:"\F03C"}.van-icon-pending-evaluate::before{content:"\F03D"}.van-icon-pending-orders::before{content:"\F03E"}.van-icon-pending-payment::before{content:"\F03F"}.van-icon-phone::before{content:"\F040"}.van-icon-photo::before{content:"\F041"}.van-icon-photograph::before{content:"\F042"}.van-icon-play::before{content:"\F043"}.van-icon-point-gift::before{content:"\F044"}.van-icon-points-mall::before{content:"\F045"}.van-icon-points::before{content:"\F046"}.van-icon-qr-invalid::before{content:"\F047"}.van-icon-qr::before{content:"\F048"}.van-icon-question::before{content:"\F049"}.van-icon-receive-gift::before{content:"\F04A"}.van-icon-records::before{content:"\F04B"}.van-icon-search::before{content:"\F04C"}.van-icon-send-gift::before{content:"\F04D"}.van-icon-setting::before{content:"\F04E"}.van-icon-share::before{content:"\F04F"}.van-icon-shop-collect::before{content:"\F050"}.van-icon-shop::before{content:"\F051"}.van-icon-shopping-cart::before{content:"\F052"}.van-icon-sign::before{content:"\F053"}.van-icon-stop::before{content:"\F054"}.van-icon-success::before{content:"\F055"}.van-icon-tosend::before{content:"\F056"}.van-icon-underway::before{content:"\F057"}.van-icon-upgrade::before{content:"\F058"}.van-icon-value-card::before{content:"\F059"}.van-icon-wap-home::before{content:"\F05A"}.van-icon-wap-nav::before{content:"\F05B"}.van-icon-warn::before{content:"\F05C"}.van-icon-wechat::before{content:"\F05D"}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.js b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..db96154662642ed1b5b8407b1c184e6075c2d5eb
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.js
@@ -0,0 +1,27 @@
+import { create } from '../common/create';
+
+create({
+ classes: ['title-class'],
+
+ props: {
+ title: String,
+ leftText: String,
+ rightText: String,
+ leftArrow: Boolean,
+ fixed: Boolean,
+ zIndex: {
+ type: Number,
+ value: 1
+ }
+ },
+
+ methods: {
+ onClickLeft() {
+ this.$emit('clickLeft');
+ },
+
+ onClickRight() {
+ this.$emit('clickRight');
+ }
+ }
+});
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.json b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..0a336c083ec7c8f87af66097dd241c13b3f6dc2e
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "../icon/index"
+ }
+}
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxml b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxml
new file mode 100644
index 0000000000000000000000000000000000000000..e53a5918020a2fe7ead6bfe3bc8dc4a954c58b07
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxml
@@ -0,0 +1,24 @@
+
+
+
+
+ {{ leftText }}
+
+
+
+
+ {{ title }}
+
+
+
+ {{ rightText }}
+
+
+
diff --git a/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxss b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxss
new file mode 100644
index 0000000000000000000000000000000000000000..c21c6b735d20200a55b57adf4d0752a6a222ccd3
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/vant-weapp/dist/nav-bar/index.wxss
@@ -0,0 +1 @@
+.van-nav-bar{height:46px;position:relative;-webkit-user-select:none;user-select:none;text-align:center;line-height:46px;background-color:#fff}.van-nav-bar__arrow{color:#38f;vertical-align:middle;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{top:0;left:0;width:100%;position:fixed}.van-nav-bar__title{margin:0 auto;max-width:60%;font-size:16px}.van-nav-bar__left,.van-nav-bar__right{bottom:0;font-size:14px;position:absolute}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px}.van-nav-bar__text{color:#38f;margin:0 -15px;padding:0 15px;display:inline-block;vertical-align:middle}.van-nav-bar__text:active{background-color:#e8e8e8}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/.babelrc b/examples/wxcomponents-template/wxcomponents/wux-weapp/.babelrc
new file mode 100644
index 0000000000000000000000000000000000000000..69f50d59a72b7a0efbf1799206b22e36be57dcc1
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["env"]
+}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..a50d2a43124974b1d27c8289b13926bdb9119401
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.js
@@ -0,0 +1,717 @@
+import baseBehavior from '../helpers/baseBehavior'
+import mergeOptionsToData from '../helpers/mergeOptionsToData'
+import { $wuxBackdrop } from '../index'
+
+const defaults = {
+ monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ dayNames: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+ dayNamesShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+ firstDay: 1, // First day of the week, Monday
+ weekendDays: [0, 6], // Sunday and Saturday
+ multiple: false,
+ dateFormat: 'yyyy-mm-dd',
+ direction: 'horizontal', // or 'vertical'
+ minDate: null,
+ maxDate: null,
+ touchMove: true,
+ animate: true,
+ closeOnSelect: true,
+ weekHeader: true,
+ toolbar: true,
+ value: [],
+ onMonthAdd() {},
+ onChange() {},
+ onOpen() {},
+ onClose() {},
+ onDayClick() {},
+ onMonthYearChangeStart() {},
+ onMonthYearChangeEnd() {},
+}
+
+// 获取手指触摸点坐标
+const getTouchPosition = (e) => {
+ const touches = e.touches[0] || e.changedTouches[0]
+ return {
+ x: touches.pageX,
+ y: touches.pageY,
+ }
+}
+
+// 获取元素旋转属性
+const getTransform = (translate, isH) => `transform: translate3d(${isH ? translate : 0}%, ${isH ? 0 : translate}%, 0)`
+
+// 判断两个日期是否在同一天
+const isSameDate = (a, b) => {
+ const prev = new Date(a)
+ const next = new Date(b)
+ return prev.getFullYear() === next.getFullYear() && prev.getMonth() === next.getMonth() && prev.getDate() === next.getDate()
+}
+
+Component({
+ behaviors: [baseBehavior],
+ externalClasses: ['wux-class'],
+ data: mergeOptionsToData(defaults),
+ methods: {
+ /**
+ * 打开日历
+ * @param {Object} opts
+ */
+ open(opts = {}) {
+ const options = this.$$mergeOptionsAndBindMethods(Object.assign({}, defaults, opts))
+
+ this.monthsTranslate = 0
+ this.isH = options.direction === 'horizontal'
+
+ this.$$setData({ in: true, ...options })
+ .then(() => {
+ const weeks = this.setWeekHeader()
+ const months = this.setMonthsHTML()
+ const monthsTranslate = this.setMonthsTranslate()
+
+ if (typeof this.fns.onMonthAdd === 'function') {
+ months.forEach((month) => {
+ this.fns.onMonthAdd.call(this, month)
+ })
+ }
+
+ return this.$$setData({ weeks, months, monthsTranslate, wrapperTranslate: '' })
+ })
+ .then(() => this.$$setData({...this.updateCurrentMonthYear() }))
+
+ this.setValue(options.value)
+ this.$wuxBackdrop.retain()
+
+ if (typeof this.fns.onOpen === 'function') {
+ this.fns.onOpen.call(this)
+ }
+ },
+ /**
+ * 关闭日历
+ */
+ close() {
+ this.$$setData({ in: false })
+ this.$wuxBackdrop.release()
+
+ if (typeof this.fns.onClose === 'function') {
+ this.fns.onClose.call(this)
+ }
+ },
+ /**
+ * 设置月份的位置信息
+ * @param {Number} translate
+ */
+ setMonthsTranslate(translate = this.monthsTranslate) {
+ const prevMonthTranslate = -(translate + 1) * 100
+ const currentMonthTranslate = -translate * 100
+ const nextMonthTranslate = -(translate - 1) * 100
+
+ return [
+ getTransform(prevMonthTranslate, this.isH),
+ getTransform(currentMonthTranslate, this.isH),
+ getTransform(nextMonthTranslate, this.isH),
+ ]
+ },
+ /**
+ * 更新当前年月
+ * @param {String} dir 方向
+ */
+ updateCurrentMonthYear(dir) {
+ const { months, monthNames } = this.data
+
+ if (typeof dir === 'undefined') {
+ const currentMonth = parseInt(months[1].month, 10)
+ const currentYear = parseInt(months[1].year, 10)
+ const currentMonthName = monthNames[currentMonth]
+
+ return {
+ currentMonth,
+ currentYear,
+ currentMonthName,
+ }
+ }
+
+ const currentMonth = parseInt(months[dir === 'next' ? (months.length - 1) : 0].month, 10)
+ const currentYear = parseInt(months[dir === 'next' ? (months.length - 1) : 0].year, 10)
+ const currentMonthName = monthNames[currentMonth]
+
+ return {
+ currentMonth,
+ currentYear,
+ currentMonthName,
+ }
+ },
+ /**
+ * 手指触摸动作开始
+ * @param {Object} e 事件对象
+ */
+ onTouchStart(e) {
+ if (!this.data.touchMove || this.isMoved || this.isRendered) {
+ return false
+ }
+
+ this.start = getTouchPosition(e)
+ this.move = {}
+ this.touchesDiff = 0
+ this.allowItemClick = true
+ this.isMoved = false
+ },
+ /**
+ * 手指触摸后移动
+ * @param {Object} e 事件对象
+ */
+ onTouchMove(e) {
+ if (!this.data.touchMove || this.isRendered) {
+ return false
+ }
+
+ this.allowItemClick = false
+
+ if (!this.isMoved) {
+ this.isMoved = true
+ }
+
+ const query = wx.createSelectorQuery().in(this)
+ query.select('.wux-calendar__months-content').boundingClientRect((rect) => {
+ if (!rect) {
+ return false
+ }
+
+ this.move = getTouchPosition(e)
+ this.touchesDiff = this.isH ? this.move.x - this.start.x : this.move.y - this.start.y
+
+ const { width, height } = rect
+ const percentage = this.touchesDiff / (this.isH ? width : height)
+ const currentTranslate = (this.monthsTranslate + percentage) * 100
+ const transform = getTransform(currentTranslate, this.isH)
+
+ this.$$setData({
+ wrapperTranslate: `transition-duration: 0s; ${transform}`,
+ })
+ })
+ query.exec()
+ },
+ /**
+ * 手指触摸动作结束
+ */
+ onTouchEnd() {
+ if (!this.data.touchMove || !this.isMoved || this.isRendered) {
+ return false
+ }
+
+ this.isMoved = false
+
+ if (Math.abs(this.touchesDiff) < 30) {
+ this.resetMonth()
+ } else if (this.touchesDiff >= 30) {
+ this.prevMonth()
+ } else {
+ this.nextMonth()
+ }
+
+ // Allow click
+ setTimeout(() => (this.allowItemClick = true), 100)
+ },
+ /**
+ * 日期的点击事件
+ * @param {Object} e 事件对象
+ */
+ onDayClick(e) {
+ if (this.allowItemClick) {
+ const dataset = e.currentTarget.dataset
+ const dateYear = dataset.year
+ const dateMonth = dataset.month
+ const dateDay = dataset.day
+ const dateType = dataset.type
+
+ if (dateType.selected && !this.data.multiple) return false
+ if (dateType.disabled) return false
+ if (dateType.next) this.nextMonth()
+ if (dateType.prev) this.prevMonth()
+
+ if (typeof this.fns.onDayClick === 'function') {
+ this.fns.onDayClick.call(this, dateYear, dateMonth, dateDay)
+ }
+
+ this.addValue(new Date(dateYear, dateMonth, dateDay).getTime())
+
+ if (this.data.closeOnSelect && !this.data.multiple) {
+ this.close()
+ }
+ }
+ },
+ /**
+ * 重置月份的位置信息
+ */
+ resetMonth() {
+ const translate = this.monthsTranslate * 100
+ const transform = getTransform(translate, this.isH)
+
+ this.$$setData({
+ wrapperTranslate: `transition-duration: 0s; ${transform}`,
+ })
+ },
+ /**
+ * 设置年月
+ * @param {String} year 年份
+ * @param {String} month 月份
+ */
+ setYearMonth(year = this.data.currentYear, month = this.data.currentMonth) {
+ const { months, monthsTranslate, maxDate, minDate, currentYear, currentMonth } = this.data
+ const targetDate = year < currentYear ? new Date(year, month + 1, -1).getTime() : new Date(year, month).getTime()
+
+ // 判断是否存在最大日期
+ if (maxDate && targetDate > new Date(maxDate).getTime()) {
+ return false
+ }
+
+ // 判断是否存在最小日期
+ if (minDate && targetDate < new Date(minDate).getTime()) {
+ return false
+ }
+
+ const currentDate = new Date(currentYear, currentMonth).getTime()
+ const dir = targetDate > currentDate ? 'next' : 'prev'
+ const newMonthHTML = this.monthHTML(new Date(year, month))
+
+ const prevTranslate = this.monthsTranslate = this.monthsTranslate || 0
+
+ if (targetDate > currentDate) {
+ this.monthsTranslate = this.monthsTranslate - 1
+
+ const translate = -(prevTranslate - 1) * 100
+ const nextMonthTranslate = getTransform(translate, this.isH)
+
+ this.$$setData({
+ months: [months[1], months[2], newMonthHTML],
+ monthsTranslate: [monthsTranslate[1], monthsTranslate[2], nextMonthTranslate],
+ })
+ } else {
+ this.monthsTranslate = this.monthsTranslate + 1
+
+ const translate = -(prevTranslate + 1) * 100
+ const prevMonthTranslate = getTransform(translate, this.isH)
+
+ this.$$setData({
+ months: [newMonthHTML, months[0], months[1]],
+ monthsTranslate: [prevMonthTranslate, monthsTranslate[0], monthsTranslate[1]],
+ })
+ }
+
+ this.onMonthChangeStart(dir)
+
+ const transform = getTransform(this.monthsTranslate * 100, this.isH)
+ const duration = this.data.animate ? .3 : 0
+ const wrapperTranslate = `transition-duration: ${duration}s; ${transform}`
+
+ this.$$setData({
+ wrapperTranslate,
+ })
+
+ setTimeout(() => this.onMonthChangeEnd(dir, true), duration)
+ },
+ /**
+ * 下一年
+ */
+ nextYear() {
+ this.setYearMonth(this.data.currentYear + 1)
+ },
+ /**
+ * 上一年
+ */
+ prevYear() {
+ this.setYearMonth(this.data.currentYear - 1)
+ },
+ /**
+ * 下一月
+ */
+ nextMonth() {
+ const { months, monthsTranslate, maxDate, currentMonth } = this.data
+ const nextMonth = parseInt(months[months.length - 1].month, 10)
+ const nextYear = parseInt(months[months.length - 1].year, 10)
+ const nextDate = new Date(nextYear, nextMonth)
+ const nextDateTime = nextDate.getTime()
+
+ // 判断是否存在最大日期
+ if (maxDate && nextDateTime > new Date(maxDate).getTime()) {
+ return this.resetMonth()
+ }
+
+ this.monthsTranslate = this.monthsTranslate - 1
+
+ if (nextMonth === currentMonth) {
+ const translate = -(this.monthsTranslate) * 100
+ const nextMonthHTML = this.monthHTML(nextDateTime, 'next')
+ const nextMonthTranslate = getTransform(translate, this.isH)
+ const months = [this.data.months[1], this.data.months[2], nextMonthHTML]
+
+ this.$$setData({
+ months,
+ monthsTranslate: [monthsTranslate[1], monthsTranslate[2], nextMonthTranslate],
+ })
+
+ if (typeof this.fns.onMonthAdd === 'function') {
+ this.fns.onMonthAdd.call(this, months[months.length - 1])
+ }
+ }
+
+ this.onMonthChangeStart('next')
+
+ const transform = getTransform(this.monthsTranslate * 100, this.isH)
+ const duration = this.data.animate ? .3 : 0
+ const wrapperTranslate = `transition-duration: ${duration}s; ${transform}`
+
+ this.$$setData({
+ wrapperTranslate,
+ })
+
+ setTimeout(() => this.onMonthChangeEnd('next'), duration)
+ },
+ /**
+ * 上一月
+ */
+ prevMonth() {
+ const { months, monthsTranslate, minDate, currentMonth } = this.data
+ const prevMonth = parseInt(months[0].month, 10)
+ const prevYear = parseInt(months[0].year, 10)
+ const prevDate = new Date(prevYear, prevMonth + 1, -1)
+ const prevDateTime = prevDate.getTime()
+
+ // 判断是否存在最小日期
+ if (minDate && prevDateTime < new Date(minDate).getTime()) {
+ return this.resetMonth()
+ }
+
+ this.monthsTranslate = this.monthsTranslate + 1
+
+ if (prevMonth === currentMonth) {
+ const translate = -(this.monthsTranslate) * 100
+ const prevMonthHTML = this.monthHTML(prevDateTime, 'prev')
+ const prevMonthTranslate = getTransform(translate, this.isH)
+ const months = [prevMonthHTML, this.data.months[0], this.data.months[1]]
+
+ this.$$setData({
+ months,
+ monthsTranslate: [prevMonthTranslate, monthsTranslate[0], monthsTranslate[1]],
+ })
+
+ if (typeof this.fns.onMonthAdd === 'function') {
+ this.fns.onMonthAdd.call(this, months[0])
+ }
+ }
+
+ this.onMonthChangeStart('prev')
+
+ const transform = getTransform(this.monthsTranslate * 100, this.isH)
+ const duration = this.data.animate ? .3 : 0
+ const wrapperTranslate = `transition-duration: ${duration}s; ${transform}`
+
+ this.$$setData({
+ wrapperTranslate,
+ })
+
+ setTimeout(() => this.onMonthChangeEnd('prev'), duration)
+ },
+ /**
+ * 月份变化开始时的回调函数
+ * @param {String} dir 方向
+ */
+ onMonthChangeStart(dir) {
+ const params = this.updateCurrentMonthYear(dir)
+
+ this.$$setData(params)
+
+ if (typeof this.fns.onMonthYearChangeStart === 'function') {
+ this.fns.onMonthYearChangeStart.call(this, params.currentYear, params.currentMonth)
+ }
+ },
+ /**
+ * 月份变化完成时的回调函数
+ * @param {String} dir 方向
+ * @param {Boolean} rebuildBoth 重置
+ */
+ onMonthChangeEnd(dir = 'next', rebuildBoth = false) {
+ const { currentYear, currentMonth } = this.data
+ let nextMonthHTML, prevMonthHTML, newMonthHTML, months = [...this.data.months]
+
+ if (!rebuildBoth) {
+ newMonthHTML = this.monthHTML(new Date(currentYear, currentMonth), dir)
+ if (dir === 'next') {
+ months = [months[1], months[2], newMonthHTML]
+ } else if (dir === 'prev') {
+ months = [newMonthHTML, months[0], months[1]]
+ }
+ } else {
+ prevMonthHTML = this.monthHTML(new Date(currentYear, currentMonth), 'prev')
+ nextMonthHTML = this.monthHTML(new Date(currentYear, currentMonth), 'next')
+ months = [prevMonthHTML, months[dir === 'next' ? months.length - 1 : 0], nextMonthHTML]
+ }
+
+ const monthsTranslate = this.setMonthsTranslate(this.monthsTranslate)
+
+ this.isRendered = true
+ this.$$setData({ months, monthsTranslate }).then(() => (this.isRendered = false))
+
+ if (typeof this.fns.onMonthAdd === 'function') {
+ this.fns.onMonthAdd.call(this, dir === 'next' ? months[months.length - 1] : months[0])
+ }
+
+ if (typeof this.fns.onMonthYearChangeEnd === 'function') {
+ this.fns.onMonthYearChangeEnd.call(this, currentYear, currentMonth)
+ }
+ },
+ /**
+ * 设置星期
+ */
+ setWeekHeader() {
+ const { weekHeader, firstDay, dayNamesShort, weekendDays } = this.data
+ const weeks = []
+
+ if (weekHeader) {
+ for (let i = 0; i < 7; i++) {
+ const weekDayIndex = (i + firstDay > 6) ? (i - 7 + firstDay) : (i + firstDay)
+ const dayName = dayNamesShort[weekDayIndex]
+ const weekend = weekendDays.indexOf(weekDayIndex) >= 0
+
+ weeks.push({
+ weekend,
+ dayName,
+ })
+ }
+ }
+
+ return weeks
+ },
+ /**
+ * 判断日期是否存在
+ */
+ daysInMonth(date) {
+ const d = new Date(date)
+ return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate()
+ },
+ /**
+ * 设置月份数据
+ */
+ monthHTML(date, offset) {
+ date = new Date(date)
+ let year = date.getFullYear(),
+ month = date.getMonth(),
+ time = date.getTime()
+
+ const monthHTML = {
+ year,
+ month,
+ time,
+ items: [],
+ }
+
+ if (offset === `next`) {
+ if (month === 11) date = new Date(year + 1, 0)
+ else date = new Date(year, month + 1, 1)
+ }
+
+ if (offset === `prev`) {
+ if (month === 0) date = new Date(year - 1, 11)
+ else date = new Date(year, month - 1, 1)
+ }
+
+ if (offset === `next` || offset === `prev`) {
+ month = date.getMonth()
+ year = date.getFullYear()
+ time = date.getTime()
+ }
+
+ let daysInPrevMonth = this.daysInMonth(new Date(date.getFullYear(), date.getMonth()).getTime() - 10 * 24 * 60 * 60 * 1000),
+ daysInMonth = this.daysInMonth(date),
+ firstDayOfMonthIndex = new Date(date.getFullYear(), date.getMonth()).getDay()
+ if (firstDayOfMonthIndex === 0) firstDayOfMonthIndex = 7
+
+ let dayDate, currentValues = [],
+ i, j,
+ rows = 6,
+ cols = 7,
+ dayIndex = 0 + (this.data.firstDay - 1),
+ today = new Date().setHours(0, 0, 0, 0),
+ minDate = this.data.minDate ? new Date(this.data.minDate).getTime() : null,
+ maxDate = this.data.maxDate ? new Date(this.data.maxDate).getTime() : null
+
+ if (this.data.value && this.data.value.length) {
+ for (let i = 0; i < this.data.value.length; i++) {
+ currentValues.push(new Date(this.data.value[i]).setHours(0, 0, 0, 0))
+ }
+ }
+
+ for (let i = 1; i <= rows; i++) {
+ let rowHTML = []
+ let row = i
+
+ for (let j = 1; j <= cols; j++) {
+ let col = j
+ dayIndex++
+ let dayNumber = dayIndex - firstDayOfMonthIndex
+ let type = {}
+
+ if (dayNumber < 0) {
+ dayNumber = daysInPrevMonth + dayNumber + 1
+ type.prev = true
+ dayDate = new Date(month - 1 < 0 ? year - 1 : year, month - 1 < 0 ? 11 : month - 1, dayNumber).getTime()
+ } else {
+ dayNumber = dayNumber + 1
+ if (dayNumber > daysInMonth) {
+ dayNumber = dayNumber - daysInMonth
+ type.next = true
+ dayDate = new Date(month + 1 > 11 ? year + 1 : year, month + 1 > 11 ? 0 : month + 1, dayNumber).getTime()
+ } else {
+ dayDate = new Date(year, month, dayNumber).getTime()
+ }
+ }
+
+ // Today
+ if (dayDate === today) type.today = true
+
+ // Selected
+ if (currentValues.indexOf(dayDate) >= 0) type.selected = true
+
+ // Weekend
+ if (this.data.weekendDays.indexOf(col - 1) >= 0) {
+ type.weekend = true
+ }
+
+ // Disabled
+ if ((minDate && dayDate < minDate) || (maxDate && dayDate > maxDate)) {
+ type.disabled = true
+ }
+
+ dayDate = new Date(dayDate)
+ const dayYear = dayDate.getFullYear()
+ const dayMonth = dayDate.getMonth()
+
+ rowHTML.push({
+ type,
+ year: dayYear,
+ month: dayMonth,
+ day: dayNumber,
+ date: `${dayYear}-${dayMonth + 1}-${dayNumber}`,
+ })
+ }
+
+ monthHTML.year = year
+ monthHTML.month = month
+ monthHTML.time = time
+
+ monthHTML.items.push(rowHTML)
+ }
+
+ return monthHTML
+ },
+ /**
+ * 设置月份
+ */
+ setMonthsHTML() {
+ const layoutDate = this.data.value && this.data.value.length ? this.data.value[0] : new Date().setHours(0, 0, 0, 0)
+ const prevMonthHTML = this.monthHTML(layoutDate, `prev`)
+ const currentMonthHTML = this.monthHTML(layoutDate)
+ const nextMonthHTML = this.monthHTML(layoutDate, `next`)
+
+ return [prevMonthHTML, currentMonthHTML, nextMonthHTML]
+ },
+ /**
+ * 格式化日期
+ */
+ formatDate(date) {
+ date = new Date(date)
+ const year = date.getFullYear()
+ const month = date.getMonth()
+ const month1 = month + 1
+ const day = date.getDate()
+ const weekDay = date.getDay()
+
+ return this.data.dateFormat
+ .replace(/yyyy/g, year)
+ .replace(/yy/g, (year + '').substring(2))
+ .replace(/mm/g, month1 < 10 ? '0' + month1 : month1)
+ .replace(/m/g, month1)
+ .replace(/MM/g, this.data.monthNames[month])
+ .replace(/M/g, this.data.monthNamesShort[month])
+ .replace(/dd/g, day < 10 ? '0' + day : day)
+ .replace(/d/g, day)
+ .replace(/DD/g, this.data.dayNames[weekDay])
+ .replace(/D/g, this.data.dayNamesShort[weekDay])
+ },
+ /**
+ * 添加选中值
+ */
+ addValue(value) {
+ if (this.data.multiple) {
+ let arrValues = this.data.value || []
+ let inValuesIndex = -1
+
+ for (let i = 0; i < arrValues.length; i++) {
+ if (isSameDate(value, arrValues[i])) {
+ inValuesIndex = i
+ }
+ }
+
+ if (inValuesIndex === -1) {
+ arrValues.push(value)
+ } else {
+ arrValues.splice(inValuesIndex, 1)
+ }
+
+ this.setValue(arrValues)
+ } else {
+ this.setValue([value])
+ }
+ },
+ /**
+ * 设置选择值
+ */
+ setValue(value) {
+ this.$$setData({ value }).then(() => this.updateValue())
+ },
+ /**
+ * 更新日历
+ */
+ updateValue() {
+ const changedPath = {}
+
+ this.data.months.forEach((n, i) => {
+ n.items.forEach((v, k) => {
+ v.forEach((p, j) => {
+ if (p.type.selected) {
+ changedPath[`months[${i}].items[${k}][${j}].type.selected`] = false
+ }
+ })
+ })
+ })
+
+ for (let ii = 0; ii < this.data.value.length; ii++) {
+ const valueDate = new Date(this.data.value[ii])
+ const valueYear = valueDate.getFullYear()
+ const valueMonth = valueDate.getMonth()
+ const valueDay = valueDate.getDate()
+
+ this.data.months.forEach((n, i) => {
+ if (n.year === valueYear && n.month === valueMonth) {
+ n.items.forEach((v, k) => {
+ v.forEach((p, j) => {
+ if (p.year === valueYear && p.month === valueMonth && p.day === valueDay) {
+ changedPath[`months[${i}].items[${k}][${j}].type.selected`] = true
+ }
+ })
+ })
+ }
+ })
+ }
+
+ this.$$setData(changedPath)
+
+ if (typeof this.fns.onChange === 'function') {
+ this.fns.onChange.call(this, this.data.value, this.data.value.map((n) => this.formatDate(n)))
+ }
+ },
+ },
+ created() {
+ this.$wuxBackdrop = $wuxBackdrop('#wux-backdrop', this)
+ },
+})
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.json b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..34b34c1642644e429486f5716710b7de06b6652b
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.json
@@ -0,0 +1,7 @@
+{
+ "component": true,
+ "usingComponents": {
+ "wux-animation-group": "../animation-group/index",
+ "wux-backdrop": "../backdrop/index"
+ }
+}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxml b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxml
new file mode 100644
index 0000000000000000000000000000000000000000..8ffb7760df4be0b9b5f16ff735218ca725fc9875
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ {{ currentMonthName }}
+
+
+
+
+
+
+
+
+ {{ currentYear }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.dayName }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ col.day }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxss b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxss
new file mode 100644
index 0000000000000000000000000000000000000000..c635ea4c77d4e3a029861a612bc3edbf35f98388
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/calendar/index.wxss
@@ -0,0 +1,322 @@
+.wux-calendar {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ height: 13rem;
+ z-index: 1500;
+ background: #cfd5da;
+ background: #fff;
+ height: 600rpx;
+ width: 100%;
+ overflow: hidden;
+}
+.wux-calendar__content {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ -webkit-transition: -webkit-transform .3s;
+ transition: -webkit-transform .3s;
+ transition: transform .3s;
+ transition: transform .3s, -webkit-transform .3s;
+}
+.wux-calendar__bd {
+ height: 100%;
+ position: relative;
+ overflow: hidden;
+}
+.wux-calendar__hd {
+ position: relative;
+ width: 100%;
+}
+.wux-calendar__hd:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 2rpx;
+ width: 100%;
+ background-color: #999999;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+.wux-calendar__hd + .wux-calendar__bd {
+ height: calc(97.8%);
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .wux-calendar__hd:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .wux-calendar__hd:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.wux-calendar--inline {
+ display: block;
+ position: relative;
+ z-index: inherit;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.wux-calendar--inline .wux-calendar__hd:before {
+ display: none;
+}
+.wux-calendar--inline .wux-calendar__hd:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 2rpx;
+ width: 100%;
+ background-color: #999999;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .wux-calendar--inline .wux-calendar__hd:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .wux-calendar--inline .wux-calendar__hd:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+@media (orientation: landscape) and (max-height: 830rpx) {
+ .wux-calendar:not(.wux-calendar--inline) {
+ height: 440rpx;
+ }
+}
+.wux-calendar__toolbar {
+ height: 2.2rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ text-align: center;
+}
+.wux-calendar__picker {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ width: 50%;
+ max-width: 400rpx;
+ -webkit-flex-shrink: 10;
+ flex-shrink: 10;
+ display: block;
+ line-height: 2.2rem;
+}
+.wux-calendar__link {
+ float: left;
+ width: 25%;
+ height: 2.2rem;
+ line-height: 2rem;
+ min-width: 72rpx;
+}
+.wux-calendar__icon {
+ display: inline-block;
+ vertical-align: middle;
+ background-size: 100% auto;
+ background-position: center;
+}
+.wux-calendar__icon--next,
+.wux-calendar__icon--prev {
+ width: 0.75rem;
+ height: 0.75rem;
+}
+.wux-calendar__icon--next {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M1%2C1.6l11.8%2C5.8L1%2C13.4V1.6%20M0%2C0v15l15-7.6L0%2C0L0%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+}
+.wux-calendar__icon--prev {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M14%2C1.6v11.8L2.2%2C7.6L14%2C1.6%20M15%2C0L0%2C7.6L15%2C15V0L15%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+}
+.wux-calendar__value {
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ float: left;
+ width: 50%;
+ height: 2.2rem;
+}
+.wux-calendar__weekdays {
+ height: 36rpx;
+ background: #f7f7f8;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ font-size: 22rpx;
+ box-sizing: border-box;
+ position: relative;
+}
+.wux-calendar__weekdays:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 2rpx;
+ width: 100%;
+ background-color: #c4c4c4;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+.wux-calendar__weekdays + .wux-calendar__months {
+ height: calc(82%);
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .wux-calendar__weekdays:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .wux-calendar__weekdays:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.wux-calendar__weekday {
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ width: 14.28571429%;
+ width: calc(14.28571429%);
+ line-height: 34rpx;
+ text-align: center;
+}
+.wux-calendar__months {
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ position: relative;
+}
+.wux-calendar__months-content {
+ width: 100%;
+ height: 100%;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ position: relative;
+ -webkit-backface-visibility: hidden;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.wux-calendar__month {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+.wux-calendar__days {
+ height: 16.66666667%;
+ height: calc(16.66666667%);
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ width: 100%;
+ position: relative;
+}
+.wux-calendar__days:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 2rpx;
+ width: 100%;
+ background-color: #cccccc;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+.wux-calendar__days:last-child:after {
+ display: none;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .wux-calendar__days:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .wux-calendar__days:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.wux-calendar__day {
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ box-sizing: border-box;
+ width: 14.28571429%;
+ width: calc(14.28571429%);
+ text-align: center;
+ color: #3d4145;
+ font-size: 30rpx;
+ cursor: pointer;
+}
+.wux-calendar__day--prev,
+.wux-calendar__day--next {
+ color: #cccccc;
+}
+.wux-calendar__day--disabled {
+ color: #d4d4d4;
+ cursor: auto;
+}
+.wux-calendar__day--today .wux-calendar__text {
+ background: #e3e3e3;
+}
+.wux-calendar__day--selected .wux-calendar__text {
+ background: #0894ec;
+ color: #fff;
+}
+.wux-calendar__text {
+ display: inline-block;
+ border-radius: 100%;
+ width: 60rpx;
+ height: 60rpx;
+ line-height: 60rpx;
+}
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fc9cce32c7b3a12bcced952c8cf6cb131bfe336
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.js
@@ -0,0 +1,38 @@
+Component({
+ externalClasses: ['wux-class'],
+ relations: {
+ '../cell/index': {
+ type: 'child',
+ linked() {
+ this.updateIsLastElement('../cell/index')
+ },
+ linkChanged() {
+ this.updateIsLastElement('../cell/index')
+ },
+ unlinked() {
+ this.updateIsLastElement('../cell/index')
+ },
+ },
+ },
+ properties: {
+ title: {
+ type: String,
+ value: '',
+ },
+ label: {
+ type: String,
+ value: '',
+ },
+ },
+ methods: {
+ updateIsLastElement() {
+ const elements = this.getRelationNodes('../cell/index')
+ if (elements.length > 0) {
+ const lastIndex = elements.length - 1
+ elements.forEach((element, index) => {
+ element.updateIsLastElement(index === lastIndex)
+ })
+ }
+ },
+ },
+})
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.json b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..fba482a42bfc985e328144eb7f5cc005680b7c57
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxml b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxml
new file mode 100644
index 0000000000000000000000000000000000000000..3fa656dbd47d8b791f2052224f979dca6ac2bbbe
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxml
@@ -0,0 +1,7 @@
+
+ {{ title }}
+
+
+
+ {{ label }}
+
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxss b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxss
new file mode 100644
index 0000000000000000000000000000000000000000..44d9831ff296d5e7e2f8c70d52cc99b5901a74c0
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell-group/index.wxss
@@ -0,0 +1,33 @@
+.wux-cell-group__hd {
+ padding: 30rpx 30rpx 18rpx;
+ font-size: 28rpx;
+ color: #888;
+ width: 100%;
+ box-sizing: border-box;
+}
+.wux-cell-group__bd {
+ position: relative;
+ background-color: #fff;
+}
+.wux-cell-group__bd:after {
+ content: " ";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 200%;
+ height: 200%;
+ -webkit-transform: scale(0.5);
+ transform: scale(0.5);
+ -webkit-transform-origin: 0 0;
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ border: 0 solid #D9D9D9;
+ border-top-width: 2rpx;
+ border-bottom-width: 2rpx;
+}
+.wux-cell-group__ft {
+ padding: 18rpx 30rpx 30rpx;
+ font-size: 28rpx;
+ color: #888;
+}
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..15cafabd671aa50afe65cda5a311f01673b0d0ce
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.js
@@ -0,0 +1,79 @@
+Component({
+ externalClasses: ['wux-class'],
+ options: {
+ multipleSlots: true,
+ },
+ relations: {
+ '../cell-group/index': {
+ type: 'parent',
+ },
+ },
+ data: {
+ isLast: false,
+ },
+ properties: {
+ hoverClass: {
+ type: String,
+ value: 'wux-cell--hover',
+ },
+ thumb: {
+ type: String,
+ value: '',
+ },
+ title: {
+ type: String,
+ value: '',
+ },
+ label: {
+ type: String,
+ value: '',
+ },
+ extra: {
+ type: String,
+ value: '',
+ },
+ isLink: {
+ type: Boolean,
+ value: false,
+ },
+ openType: {
+ type: String,
+ value: 'navigateTo',
+ },
+ url: {
+ type: String,
+ value: '',
+ },
+ delta: {
+ type: Number,
+ value: 1,
+ },
+ },
+ methods: {
+ onTap() {
+ const { url, isLink, openType, delta } = this.data
+ const navigate = [
+ 'navigateTo',
+ 'redirectTo',
+ 'switchTab',
+ 'navigateBack',
+ 'reLaunch',
+ ]
+
+ this.triggerEvent('click')
+
+ if (!isLink || !url) {
+ return false
+ } else if (!navigate.includes(openType)) {
+ return console.warn('openType 属性可选值为 navigateTo、redirectTo、switchTab、navigateBack、reLaunch', openType)
+ } else if (openType === 'navigateBack') {
+ return wx[openType].call(wx, { delta })
+ } else {
+ return wx[openType].call(wx, { url })
+ }
+ },
+ updateIsLastElement(isLast) {
+ this.setData({ isLast })
+ },
+ },
+})
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.json b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..fba482a42bfc985e328144eb7f5cc005680b7c57
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxml b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxml
new file mode 100644
index 0000000000000000000000000000000000000000..1437d3daa4a54d4c937d949f3ad0b6d5c4a8f6a0
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+ {{ label }}
+
+
+
+ {{ extra }}
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxss b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxss
new file mode 100644
index 0000000000000000000000000000000000000000..488b886fdee04a323b5b79d8b1eec9c01a1fceef
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/cell/index.wxss
@@ -0,0 +1,77 @@
+.wux-cell {
+ padding: 20rpx 30rpx;
+ position: relative;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ background: #fff;
+}
+.wux-cell:after {
+ content: " ";
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ height: 2rpx;
+ border-bottom: 2rpx solid #D9D9D9;
+ color: #D9D9D9;
+ -webkit-transform-origin: 0 100%;
+ transform-origin: 0 100%;
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ left: 30rpx;
+}
+.wux-cell--last:after {
+ display: none;
+}
+.wux-cell--hover {
+ background-color: #ECECEC;
+}
+.wux-cell__thumb {
+ display: block;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 10rpx;
+}
+.wux-cell__bd {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ flex: 1;
+}
+.wux-cell__text {
+ text-align: left;
+}
+.wux-cell__desc {
+ text-align: left;
+ line-height: 1.2;
+ font-size: 24rpx;
+ color: #808080;
+}
+.wux-cell__ft {
+ text-align: right;
+ color: #808080;
+}
+.wux-cell--access .wux-cell__ft {
+ padding-right: 26rpx;
+ position: relative;
+}
+.wux-cell--access .wux-cell__ft:after {
+ content: " ";
+ display: inline-block;
+ height: 12rpx;
+ width: 12rpx;
+ border-width: 4rpx 4rpx 0 0;
+ border-color: #C8C8CD;
+ border-style: solid;
+ -webkit-transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
+ transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
+ position: relative;
+ top: -4rpx;
+ position: absolute;
+ top: 50%;
+ margin-top: -8rpx;
+ right: 4rpx;
+}
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countdown/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countdown/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..59ca76deb912faad252923725915628d87225ffc
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countdown/index.js
@@ -0,0 +1,176 @@
+class Countdown {
+ constructor(options = {}, page = getCurrentPages()[getCurrentPages().length - 1]) {
+ Object.assign(this, {
+ page,
+ options,
+ })
+ this.__init()
+ }
+
+ /**
+ * 初始化
+ */
+ __init() {
+ this.setData = this.page.setData.bind(this.page)
+ this.restart(this.options)
+ }
+
+ /**
+ * 默认参数
+ */
+ setDefaults() {
+ return {
+ date: `June 7, 2087 15:03:25`,
+ refresh: 1000,
+ offset: 0,
+ onEnd() {},
+ render(date) {},
+ }
+ }
+
+ /**
+ * 合并参数
+ */
+ mergeOptions(options) {
+ const defaultOptions = this.setDefaults()
+
+ for (let i in defaultOptions) {
+ if (defaultOptions.hasOwnProperty(i)) {
+ this.options[i] = typeof options[i] !== `undefined` ? options[i] : defaultOptions[i]
+
+ if (i === `date` && typeof this.options.date !== `object`) {
+ this.options.date = new Date(this.options.date)
+ }
+
+ if (typeof this.options[i] === `function`) {
+ this.options[i] = this.options[i].bind(this)
+ }
+ }
+ }
+
+ if (typeof this.options.date !== `object`) {
+ this.options.date = new Date(this.options.date)
+ }
+ }
+
+ /**
+ * 计算日期差
+ */
+ getDiffDate() {
+ let diff = (this.options.date.getTime() - Date.now() + this.options.offset) / 1000
+
+ let dateData = {
+ years: 0,
+ days: 0,
+ hours: 0,
+ min: 0,
+ sec: 0,
+ millisec: 0,
+ }
+
+ if (diff <= 0) {
+ if (this.interval) {
+ this.stop()
+ this.options.onEnd()
+ }
+ return dateData
+ }
+
+ if (diff >= (365.25 * 86400)) {
+ dateData.years = Math.floor(diff / (365.25 * 86400))
+ diff -= dateData.years * 365.25 * 86400
+ }
+
+ if (diff >= 86400) {
+ dateData.days = Math.floor(diff / 86400)
+ diff -= dateData.days * 86400
+ }
+
+ if (diff >= 3600) {
+ dateData.hours = Math.floor(diff / 3600)
+ diff -= dateData.hours * 3600
+ }
+
+ if (diff >= 60) {
+ dateData.min = Math.floor(diff / 60)
+ diff -= dateData.min * 60
+ }
+
+ dateData.sec = Math.round(diff)
+
+ dateData.millisec = diff % 1 * 1000
+
+ return dateData
+ }
+
+ /**
+ * 补零
+ */
+ leadingZeros(num, length = 2) {
+ num = String(num)
+ if (num.length > length) return num
+ return (Array(length + 1).join(`0`) + num).substr(-length)
+ }
+
+ /**
+ * 更新组件
+ */
+ update(newDate) {
+ this.options.date = typeof newDate !== `object` ? new Date(newDate) : newDate
+ this.render()
+ return this
+ }
+
+ /**
+ * 停止倒计时
+ */
+ stop() {
+ if (this.interval) {
+ clearInterval(this.interval)
+ this.interval = !1
+ }
+ return this
+ }
+
+ /**
+ * 渲染组件
+ */
+ render() {
+ this.options.render(this.getDiffDate())
+ return this
+ }
+
+ /**
+ * 启动倒计时
+ */
+ start() {
+ if (this.interval) return !1
+ this.render()
+ if (this.options.refresh) {
+ this.interval = setInterval(() => {
+ this.render()
+ }, this.options.refresh)
+ }
+ return this
+ }
+
+ /**
+ * 更新offset
+ */
+ updateOffset(offset) {
+ this.options.offset = offset
+ return this
+ }
+
+ /**
+ * 重启倒计时
+ */
+ restart(options = {}) {
+ this.mergeOptions(options)
+ this.interval = !1
+ this.start()
+ return this
+ }
+}
+
+export default Countdown
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countup/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countup/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b8894ebf7c6ce17885e479c29ad98714089c85b
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/countup/index.js
@@ -0,0 +1,220 @@
+class CountUp {
+ constructor(startVal, endVal, decimals, duration, options = {}, page = getCurrentPages()[getCurrentPages().length - 1]) {
+ Object.assign(this, {
+ page,
+ startVal,
+ endVal,
+ decimals,
+ duration,
+ options,
+ })
+ this.__init()
+ }
+
+ /**
+ * 初始化
+ */
+ __init() {
+ this.setData = this.page.setData.bind(this.page)
+
+ this.lastTime = 0
+
+ // merge options
+ this.mergeOptions(this.options)
+
+ this.startVal = Number(this.startVal)
+ this.cacheVal = this.startVal
+ this.endVal = Number(this.endVal)
+ this.countDown = (this.startVal > this.endVal)
+ this.frameVal = this.startVal
+ this.decimals = Math.max(0, this.decimals || 0)
+ this.dec = Math.pow(10, this.decimals)
+ this.duration = Number(this.duration) * 1000 || 2000
+
+ // format startVal on initialization
+ this.printValue(this.formattingFn(this.startVal))
+ }
+
+ /**
+ * 默认参数
+ */
+ setDefaultOptions() {
+ return {
+ useEasing: true, // toggle easing
+ useGrouping: true, // 1,000,000 vs 1000000
+ separator: `,`, // character to use as a separator
+ decimal: `.`, // character to use as a decimal
+ easingFn: null, // optional custom easing closure function, default is Robert Penner's easeOutExpo
+ formattingFn: null, // optional custom formatting function, default is this.formatNumber below
+ printValue(value) {}, // printValue
+ }
+ }
+
+ /**
+ * 合并参数
+ */
+ mergeOptions(options) {
+ const defaultOptions = this.setDefaultOptions()
+
+ // extend default options with passed options object
+ for (let key in defaultOptions) {
+ if (defaultOptions.hasOwnProperty(key)) {
+ this.options[key] = typeof options[key] !== `undefined` ? options[key] : defaultOptions[key]
+ if (typeof this.options[key] === `function`) {
+ this.options[key] = this.options[key].bind(this)
+ }
+ }
+ }
+
+ if (this.options.separator === ``) { this.options.useGrouping = !1 }
+ if (!this.options.prefix) this.options.prefix = ``
+ if (!this.options.suffix) this.options.suffix = ``
+
+ this.easingFn = this.options.easingFn ? this.options.easingFn : this.easeOutExpo
+ this.formattingFn = this.options.formattingFn ? this.options.formattingFn : this.formatNumber
+ this.printValue = this.options.printValue ? this.options.printValue : function() {}
+ }
+
+ /**
+ * 创建定时器
+ */
+ requestAnimationFrame(callback) {
+ let currTime = new Date().getTime()
+ let timeToCall = Math.max(0, 16 - (currTime - this.lastTime))
+ let timeout = setTimeout(() => {
+ callback.bind(this)(currTime + timeToCall)
+ }, timeToCall)
+ this.lastTime = currTime + timeToCall
+ return timeout
+ }
+
+ /**
+ * 清空定时器
+ */
+ cancelAnimationFrame(timeout) {
+ clearTimeout(timeout)
+ }
+
+ /**
+ * 格式化数字
+ */
+ formatNumber(nStr) {
+ nStr = nStr.toFixed(this.decimals)
+ nStr += ``
+ let x, x1, x2, rgx
+ x = nStr.split(`.`)
+ x1 = x[0]
+ x2 = x.length > 1 ? this.options.decimal + x[1] : ``
+ rgx = /(\d+)(\d{3})/
+ if (this.options.useGrouping) {
+ while (rgx.test(x1)) {
+ x1 = x1.replace(rgx, `$1` + this.options.separator + `$2`)
+ }
+ }
+ return this.options.prefix + x1 + x2 + this.options.suffix
+ }
+
+ /**
+ * 过渡效果
+ */
+ easeOutExpo(t, b, c, d) {
+ return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b
+ }
+
+ /**
+ * 计数函数
+ */
+ count(timestamp) {
+ if (!this.startTime) { this.startTime = timestamp }
+
+ this.timestamp = timestamp
+ const progress = timestamp - this.startTime
+ this.remaining = this.duration - progress
+
+ // to ease or not to ease
+ if (this.options.useEasing) {
+ if (this.countDown) {
+ this.frameVal = this.startVal - this.easingFn(progress, 0, this.startVal - this.endVal, this.duration)
+ } else {
+ this.frameVal = this.easingFn(progress, this.startVal, this.endVal - this.startVal, this.duration)
+ }
+ } else {
+ if (this.countDown) {
+ this.frameVal = this.startVal - ((this.startVal - this.endVal) * (progress / this.duration))
+ } else {
+ this.frameVal = this.startVal + (this.endVal - this.startVal) * (progress / this.duration)
+ }
+ }
+
+ // don't go past endVal since progress can exceed duration in the last frame
+ if (this.countDown) {
+ this.frameVal = (this.frameVal < this.endVal) ? this.endVal : this.frameVal
+ } else {
+ this.frameVal = (this.frameVal > this.endVal) ? this.endVal : this.frameVal
+ }
+
+ // decimal
+ this.frameVal = Math.round(this.frameVal * this.dec) / this.dec
+
+ // format and print value
+ this.printValue(this.formattingFn(this.frameVal))
+
+ // whether to continue
+ if (progress < this.duration) {
+ this.rAF = this.requestAnimationFrame(this.count)
+ } else {
+ if (this.callback) { this.callback() }
+ }
+ }
+
+ /**
+ * 启动计数器
+ */
+ start(callback) {
+ this.callback = callback
+ this.rAF = this.requestAnimationFrame(this.count)
+ return !1
+ }
+
+ /**
+ * 停止计数器
+ */
+ pauseResume() {
+ if (!this.paused) {
+ this.paused = !0
+ this.cancelAnimationFrame(this.rAF)
+ } else {
+ this.paused = !1
+ delete this.startTime
+ this.duration = this.remaining
+ this.startVal = this.frameVal
+ this.requestAnimationFrame(this.count)
+ }
+ }
+
+ /**
+ * 重置计数器
+ */
+ reset() {
+ this.paused = !1
+ delete this.startTime
+ this.startVal = this.cacheVal
+ this.cancelAnimationFrame(this.rAF)
+ this.printValue(this.formattingFn(this.startVal))
+ }
+
+ /**
+ * 更新计数器
+ */
+ update(newEndVal) {
+ this.cancelAnimationFrame(this.rAF)
+ this.paused = !1
+ delete this.startTime
+ this.startVal = this.frameVal
+ this.endVal = Number(newEndVal)
+ this.countDown = (this.startVal > this.endVal)
+ this.rAF = this.requestAnimationFrame(this.count)
+ }
+}
+
+export default CountUp
\ No newline at end of file
diff --git a/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/index.js b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0422d68d3cb6fd06fec81f478b5b3a7f913d0b4
--- /dev/null
+++ b/examples/wxcomponents-template/wxcomponents/wux-weapp/dist/index.js
@@ -0,0 +1,47 @@
+import $wuxCountDown from './countdown/index'
+import $wuxCountUp from './countup/index'
+
+/**
+ * 使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象
+ * @param {String} selector 节点选择器
+ * @param {Object} ctx 页面栈或组件的实例,默认为当前页面栈实例
+ */
+const getCtx = (selector, ctx = getCurrentPages()[getCurrentPages().length - 1]) => {
+ const componentCtx = ctx.selectComponent(selector)
+
+ if (!componentCtx) {
+ throw new Error('无法找到对应的组件,请按文档说明使用组件')
+ }
+
+ return componentCtx
+}
+
+const $wuxActionSheet = (selector = '#wux-actionsheet', ctx) => getCtx(selector, ctx)
+const $wuxBackdrop = (selector = '#wux-backdrop', ctx) => getCtx(selector, ctx)
+const $wuxToast = (selector = '#wux-toast', ctx) => getCtx(selector, ctx)
+const $wuxLoading = (selector = '#wux-loading', ctx) => getCtx(selector, ctx)
+const $wuxDialog = (selector = '#wux-dialog', ctx) => getCtx(selector, ctx)
+const $wuxToptips = (selector = '#wux-toptips', ctx) => getCtx(selector, ctx)
+const $wuxGallery = (selector = '#wux-gallery', ctx) => getCtx(selector, ctx)
+const $wuxNotification = (selector = '#wux-notification', ctx) => getCtx(selector, ctx)
+const $wuxKeyBoard = (selector = '#wux-keyboard', ctx) => getCtx(selector, ctx)
+const $wuxSelect = (selector = '#wux-select', ctx) => getCtx(selector, ctx)
+const $wuxCalendar = (selector = '#wux-calendar', ctx) => getCtx(selector, ctx)
+const $stopWuxRefresher = (selector = '#wux-refresher', ctx) => getCtx(selector, ctx).finishPullToRefresh()
+
+export {
+ $wuxActionSheet,
+ $wuxBackdrop,
+ $wuxToast,
+ $wuxLoading,
+ $wuxDialog,
+ $wuxToptips,
+ $wuxGallery,
+ $wuxNotification,
+ $wuxKeyBoard,
+ $wuxSelect,
+ $wuxCalendar,
+ $stopWuxRefresher,
+ $wuxCountDown,
+ $wuxCountUp,
+}
\ No newline at end of file