Full Code of jinhuiWong/vux-2.0 for AI

master e4d51274ed98 cached
385 files
953.4 KB
327.8k tokens
212 symbols
1 requests
Download .txt
Showing preview only (1,080K chars total). Download the full file or copy to clipboard to get everything.
Repository: jinhuiWong/vux-2.0
Branch: master
Commit: e4d51274ed98
Files: 385
Total size: 953.4 KB

Directory structure:
gitextract_ozu3psze/

├── .babelrc
├── .editorconfig
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── build/
│   ├── build.js
│   ├── check-versions.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config/
│   ├── dev.env.js
│   ├── index.js
│   ├── prod.env.js
│   └── test.env.js
├── index.html
├── package.json
├── src/
│   ├── App.vue
│   ├── Home.vue
│   ├── Wechat.vue
│   ├── components/
│   │   ├── actionsheet/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── alert/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── badge/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── blur/
│   │   │   ├── blur.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── box/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── button-tab/
│   │   │   ├── button-tab-item.vue
│   │   │   ├── button-tab.vue
│   │   │   ├── index.js
│   │   │   └── metas.yml
│   │   ├── calendar/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── card/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── cell/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── check-icon/
│   │   │   └── index.vue
│   │   ├── checker/
│   │   │   ├── checker-item.vue
│   │   │   ├── checker.vue
│   │   │   ├── index.js
│   │   │   └── metas.yml
│   │   ├── checklist/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   └── object-filter.js
│   │   ├── circle/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── clocker/
│   │   │   ├── clocker.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── color-picker/
│   │   │   └── index.vue
│   │   ├── confirm/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── countdown/
│   │   │   └── index.vue
│   │   ├── countup/
│   │   │   └── index.vue
│   │   ├── datetime/
│   │   │   ├── datetimepicker.js
│   │   │   ├── format.js
│   │   │   ├── index.vue
│   │   │   └── util.js
│   │   ├── dev-tip/
│   │   │   └── index.vue
│   │   ├── dialog/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── divider/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── flexbox/
│   │   │   ├── flexbox-item.vue
│   │   │   ├── flexbox.vue
│   │   │   └── index.js
│   │   ├── fullpage/
│   │   │   ├── DemoBasic.vue
│   │   │   ├── index.vue
│   │   │   └── lib.js
│   │   ├── group/
│   │   │   ├── component.json
│   │   │   ├── index.md
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── group-title/
│   │   │   └── index.vue
│   │   ├── icon/
│   │   │   ├── component.json
│   │   │   ├── index.md
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── index.js
│   │   ├── inline-calendar/
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   ├── props.js
│   │   │   └── util.js
│   │   ├── inline-desc/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── inline-x-number/
│   │   │   └── index.vue
│   │   ├── loading/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── masker/
│   │   │   ├── converter.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── number-roller/
│   │   │   ├── index.vue
│   │   │   └── lib.js
│   │   ├── orientation/
│   │   │   ├── index.js
│   │   │   └── orientation.js
│   │   ├── panel/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── picker/
│   │   │   ├── animate.js
│   │   │   ├── chain.js
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   ├── scroller.css
│   │   │   ├── scroller.js
│   │   │   └── util.js
│   │   ├── popover/
│   │   │   ├── DemoIndex.vue
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── popup/
│   │   │   ├── index.vue
│   │   │   └── popup.js
│   │   ├── popup-picker/
│   │   │   └── index.vue
│   │   ├── previewer/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── progress/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── qrcode/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── radio/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── range/
│   │   │   ├── index.vue
│   │   │   ├── powerange.less
│   │   │   └── range/
│   │   │       └── lib/
│   │   │           ├── horizontal.js
│   │   │           ├── lib/
│   │   │           │   ├── classes.js
│   │   │           │   ├── closest-num.js
│   │   │           │   ├── closest.js
│   │   │           │   ├── delegate.js
│   │   │           │   ├── emitter.js
│   │   │           │   ├── event.js
│   │   │           │   ├── events.js
│   │   │           │   ├── indexof.js
│   │   │           │   ├── matches-selector.js
│   │   │           │   ├── mouse.js
│   │   │           │   ├── percentage-calc.js
│   │   │           │   ├── query.js
│   │   │           │   └── super.js
│   │   │           ├── main.js
│   │   │           └── powerange.js
│   │   ├── rater/
│   │   │   └── index.vue
│   │   ├── scroller/
│   │   │   └── index.vue
│   │   ├── search/
│   │   │   └── index.vue
│   │   ├── selector/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── shake/
│   │   │   └── index.vue
│   │   ├── spinner/
│   │   │   ├── index.vue
│   │   │   ├── requestAnimationFrame.js
│   │   │   └── spinner.js
│   │   ├── step/
│   │   │   ├── index.js
│   │   │   ├── step-item.vue
│   │   │   └── step.vue
│   │   ├── sticky/
│   │   │   ├── index.vue
│   │   │   └── sticky.js
│   │   ├── swiper/
│   │   │   ├── index.vue
│   │   │   └── swiper.js
│   │   ├── swiper-item/
│   │   │   └── index.vue
│   │   ├── tab/
│   │   │   ├── index.js
│   │   │   ├── tab-item.vue
│   │   │   └── tab.vue
│   │   ├── tabbar/
│   │   │   ├── component.json
│   │   │   ├── index.js
│   │   │   ├── metas.yml
│   │   │   ├── tabbar-item.vue
│   │   │   └── tabbar.vue
│   │   ├── timeline/
│   │   │   ├── index.js
│   │   │   ├── timeline-item.vue
│   │   │   └── timeline.vue
│   │   ├── tip/
│   │   │   └── index.vue
│   │   ├── toast/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── video/
│   │   │   ├── index.vue
│   │   │   ├── zy.media.css
│   │   │   └── zy.media.js
│   │   ├── view-box/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── wechat-emotion/
│   │   │   └── index.vue
│   │   ├── x-address/
│   │   │   ├── data/
│   │   │   │   └── compress.js
│   │   │   ├── index.vue
│   │   │   ├── list.json
│   │   │   └── metas.yml
│   │   ├── x-button/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── x-header/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── x-img/
│   │   │   └── index.vue
│   │   ├── x-input/
│   │   │   └── index.vue
│   │   ├── x-number/
│   │   │   └── index.vue
│   │   ├── x-switch/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   └── x-textarea/
│   │       ├── component.json
│   │       ├── index.vue
│   │       └── metas.yml
│   ├── demos/
│   │   ├── 1px.vue
│   │   ├── Actionsheet.vue
│   │   ├── Address.vue
│   │   ├── Alert.vue
│   │   ├── Badge.vue
│   │   ├── Blur.vue
│   │   ├── Button-tab.vue
│   │   ├── Calendar.vue
│   │   ├── Card.vue
│   │   ├── Cell.vue
│   │   ├── Center.vue
│   │   ├── Checker.vue
│   │   ├── Checklist.vue
│   │   ├── Circle.vue
│   │   ├── Clocker.vue
│   │   ├── Close.vue
│   │   ├── Color-picker.vue
│   │   ├── Comment.vue
│   │   ├── Confirm.vue
│   │   ├── Countdown.vue
│   │   ├── Countup.vue
│   │   ├── Date-formatter.vue
│   │   ├── Datetime.vue
│   │   ├── Demo.vue
│   │   ├── Device.vue
│   │   ├── Dialog.vue
│   │   ├── Divider.vue
│   │   ├── Donate.vue
│   │   ├── Flexbox.vue
│   │   ├── Icon-loading.vue
│   │   ├── Icon.vue
│   │   ├── Inline-calendar-start-date.vue
│   │   ├── Inline-calendar.vue
│   │   ├── Input.vue
│   │   ├── Inview.vue
│   │   ├── Issue189.vue
│   │   ├── Issue414.vue
│   │   ├── Issue461.vue
│   │   ├── Loading.vue
│   │   ├── Masker.vue
│   │   ├── Number-roller.vue
│   │   ├── Number.vue
│   │   ├── Orientation.vue
│   │   ├── Panel.vue
│   │   ├── Picker.vue
│   │   ├── Popup-picker.vue
│   │   ├── Popup.vue
│   │   ├── Previewer.vue
│   │   ├── Progress.vue
│   │   ├── Pulldown.vue
│   │   ├── PulldownPullup.vue
│   │   ├── Pullup.vue
│   │   ├── Qrcode.vue
│   │   ├── Radio.vue
│   │   ├── Range.vue
│   │   ├── Rater.vue
│   │   ├── Reddot.vue
│   │   ├── Scroller-full.vue
│   │   ├── Scroller-header.vue
│   │   ├── Scroller-swiper.vue
│   │   ├── Scroller.vue
│   │   ├── Search-static.vue
│   │   ├── Search.vue
│   │   ├── Selector.vue
│   │   ├── Shake.vue
│   │   ├── Spinner.vue
│   │   ├── Step.vue
│   │   ├── Sticky.vue
│   │   ├── Swiper.vue
│   │   ├── Switch.vue
│   │   ├── Tab.vue
│   │   ├── Tabbar.vue
│   │   ├── TabbarLink.vue
│   │   ├── Test.vue
│   │   ├── Textarea.vue
│   │   ├── Thanks.vue
│   │   ├── Timeline.vue
│   │   ├── Tip.vue
│   │   ├── Toast.vue
│   │   ├── Wechat-emotion.vue
│   │   ├── X-button.vue
│   │   ├── X-header.vue
│   │   ├── X-img-scroller.vue
│   │   ├── XImg.vue
│   │   └── style.css
│   ├── directives/
│   │   ├── click-outside/
│   │   │   └── index.js
│   │   └── inview/
│   │       ├── index.js
│   │       └── inview.js
│   ├── filters/
│   │   ├── array2String.js
│   │   ├── friendly-time.js
│   │   ├── name2value.js
│   │   └── value2name.js
│   ├── libs/
│   │   ├── base.js
│   │   ├── eventor.js
│   │   ├── mixin_uuid.js
│   │   ├── router.js
│   │   └── trim.js
│   ├── main.js
│   ├── mixins/
│   │   └── multi-items.js
│   ├── pages/
│   │   └── home/
│   │       └── home.vue
│   ├── plugins/
│   │   ├── alert/
│   │   │   └── index.js
│   │   ├── device/
│   │   │   └── index.js
│   │   └── toast/
│   │       └── index.js
│   ├── routers/
│   │   └── router.js
│   ├── styles/
│   │   ├── 1px.less
│   │   ├── center.less
│   │   ├── close.less
│   │   ├── index.less
│   │   ├── index.vue
│   │   ├── loading.less
│   │   ├── reddot.less
│   │   ├── reset.less
│   │   ├── tap.less
│   │   ├── transition.less
│   │   ├── variable.less
│   │   └── weui/
│   │       ├── base/
│   │       │   ├── fn.less
│   │       │   ├── mixin/
│   │       │   │   ├── mobile.less
│   │       │   │   ├── setArrow.less
│   │       │   │   ├── setChecked.less
│   │       │   │   ├── setOnepx.less
│   │       │   │   └── text.less
│   │       │   ├── reset.less
│   │       │   └── variable/
│   │       │       ├── global.less
│   │       │       ├── monokai.less
│   │       │       ├── weui_button.less
│   │       │       ├── weui_cell.less
│   │       │       ├── weui_grid.less
│   │       │       ├── weui_msg.less
│   │       │       └── weui_progress.less
│   │       ├── icon/
│   │       │   ├── weui_font.less
│   │       │   └── weui_icon_font.less
│   │       ├── weui.less
│   │       └── widget/
│   │           ├── weui_button/
│   │           │   ├── weui_btn_default.less
│   │           │   ├── weui_btn_disabled.less
│   │           │   ├── weui_btn_global.less
│   │           │   ├── weui_btn_plain.less
│   │           │   ├── weui_btn_primary.less
│   │           │   ├── weui_btn_warn.less
│   │           │   └── weui_button.less
│   │           ├── weui_cell/
│   │           │   ├── weui_access.less
│   │           │   ├── weui_cell_global.less
│   │           │   ├── weui_check/
│   │           │   │   ├── weui_check_common.less
│   │           │   │   ├── weui_checkbox.less
│   │           │   │   └── weui_radio.less
│   │           │   ├── weui_check.less
│   │           │   ├── weui_form/
│   │           │   │   ├── weui_form_common.less
│   │           │   │   ├── weui_select.less
│   │           │   │   ├── weui_select_after.less
│   │           │   │   ├── weui_select_before.less
│   │           │   │   └── weui_vcode.less
│   │           │   ├── weui_form.less
│   │           │   ├── weui_switch.less
│   │           │   └── weui_uploader.less
│   │           ├── weui_grid/
│   │           │   └── weui_grid.less
│   │           ├── weui_media_box/
│   │           │   └── weui_media_box.less
│   │           ├── weui_page/
│   │           │   ├── weui_article.less
│   │           │   └── weui_msg.less
│   │           ├── weui_panel/
│   │           │   └── weui_panel.less
│   │           ├── weui_progress/
│   │           │   └── weui_progress.less
│   │           ├── weui_searchbar/
│   │           │   └── weui_searchbar.less
│   │           ├── weui_tab/
│   │           │   ├── navbar.less
│   │           │   ├── tabbar.less
│   │           │   ├── weui_tab.less
│   │           │   └── weui_tab_tabbar.less
│   │           └── weui_tips/
│   │               ├── weui_actionsheet.less
│   │               ├── weui_dialog.less
│   │               ├── weui_mask.less
│   │               └── weui_toast.less
│   ├── vuex/
│   │   └── store.js
│   └── yi.vue
├── static/
│   └── .gitkeep
└── test/
    ├── e2e/
    │   ├── custom-assertions/
    │   │   └── elementCount.js
    │   ├── nightwatch.conf.js
    │   ├── runner.js
    │   └── specs/
    │       └── test.js
    └── unit/
        ├── .eslintrc
        ├── index.js
        ├── karma.conf.js
        └── specs/
            └── Hello.spec.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  	"presets": ["es2015", "stage-2"],
  	"plugins": ["transform-runtime"],
  	"comments": false
}


================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules/
dist/
npm-debug.log
test/unit/coverage
test/e2e/reports
selenium-debug.log
node_modules/
.idea/


================================================
FILE: .npmrc
================================================
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
phantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/
registry=https://registry.npm.taobao.org


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# vux-2.0
根据vux-https://github.com/airyland/vux 修改升级的2.0

## Docs

+ [中文文档](https://jinhuiwong.gitbooks.io/vuxx/content/)

## Demo

<p align="center">
  <a href="http://jhwong.cn/vux2">http://jhwong.cn/vux2</a><br/>
  (You can view the demos' codes in <a href="https://github.com/jinhuiWong/vux-2.0/tree/master/src/demos"><strong>/src/demos</strong></a>)<br/>
  <img src="http://og1rlwcj8.bkt.clouddn.com/1485876811.png" width="300">
</p>

## Use
``` bash
# install 
npm install vuxx

#vue-cli项目引用
#在webpack.base.conf.js添加loader

{
  test: /vuxx.src.*?js$/,
  loader: 'babel'
}

#使用组件
<template>
  <div>
    <group>
      <cell title="示例"></cell>
    </group>
  </div>
</template>

<script>
import Cell from 'vuxx/src/components/Cell'
import Group from 'vuxx/src/components/Group'
export default {
  components: {
    Group,
    Cell
  }
}
</script>

```

## Development Setup

``` bash
# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

```
交流qq群:537322257
![alt text]( http://og1rlwcj8.bkt.clouddn.com/7f4c4fe1gw1evv8bc0r3tj20go0ghjs3.jpg "Title")


================================================
FILE: build/build.js
================================================
// https://github.com/shelljs/shelljs
require('./check-versions')()
require('shelljs/global')
env.NODE_ENV = 'production'

var path = require('path')
var config = require('../config')
var ora = require('ora')
var webpack = require('webpack')
var webpackConfig = require('./webpack.prod.conf')

console.log(
  '  Tip:\n' +
  '  Built files are meant to be served over an HTTP server.\n' +
  '  Opening index.html over file:// won\'t work.\n'
)

var spinner = ora('打包中...')
spinner.start()

var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm('-rf', assetsPath)
mkdir('-p', assetsPath)
cp('-R', 'static/*', assetsPath)

webpack(webpackConfig, function (err, stats) {
  spinner.stop()
  if (err) throw err
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }) + '\n')
})


================================================
FILE: build/check-versions.js
================================================
var semver = require('semver')
var chalk = require('chalk')
var packageConfig = require('../package.json')
var exec = function (cmd) {
  return require('child_process')
    .execSync(cmd).toString().trim()
}

var versionRequirements = [
  {
    name: 'node',
    currentVersion: semver.clean(process.version),
    versionRequirement: packageConfig.engines.node
  },
  {
    name: 'npm',
    currentVersion: exec('npm --version'),
    versionRequirement: packageConfig.engines.npm
  }
]

module.exports = function () {
  var warnings = []
  for (var i = 0; i < versionRequirements.length; i++) {
    var mod = versionRequirements[i]
    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
      warnings.push(mod.name + ': ' +
        chalk.red(mod.currentVersion) + ' should be ' +
        chalk.green(mod.versionRequirement)
      )
    }
  }

  if (warnings.length) {
    console.log('')
    console.log(chalk.yellow('To use this template, you must update following to modules:'))
    console.log()
    for (var i = 0; i < warnings.length; i++) {
      var warning = warnings[i]
      console.log('  ' + warning)
    }
    console.log()
    process.exit(1)
  }
}


================================================
FILE: build/dev-client.js
================================================
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')

hotClient.subscribe(function (event) {
  if (event.action === 'reload') {
    window.location.reload()
  }
})


================================================
FILE: build/dev-server.js
================================================
require('./check-versions')();
var config = require('../config');
if (!process.env.NODE_ENV) process.env.NODE_ENV = config.dev.env
var path = require('path');
var fs = require('fs');
var http = require('http');
var https = require('https');
var express = require('express');
var webpack = require('webpack');
var opn = require('opn');
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = process.env.NODE_ENV === 'testing' ? require('./webpack.prod.conf') : require('./webpack.dev.conf')
    // 定义监听端口
    // default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port;
    // Define HTTP proxies to your custom API backend
    // https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable;

var app = express()
var compiler = webpack(webpackConfig);

var devMiddleware = require('webpack-dev-middleware')(compiler, {
    publicPath: webpackConfig.output.publicPath,
    stats: {
        colors: true,
        chunks: false
    }
});

var hotMiddleware = require('webpack-hot-middleware')(compiler);
    // force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function(data, cb) {
        hotMiddleware.publish({ action: 'reload' })
        cb()
    })
});

// proxy api requests
// Object.keys(proxyTable).forEach(function (context) {
//   var options = proxyTable[context]
//   if (typeof options === 'string') {
//     options = { target: options }
//   }
//   app.use(proxyMiddleware(context, options))
// })

// 设置反向代理地址
// Object.keys(proxyTable).forEach(function(context) {
//     var options = proxyTable[context];
//     if (typeof options === 'string') {
//         options = { target: options, changeOrigin: true }
//     }
//     //var apiProxy =proxyMiddleware(context, options);
//     //console.log(apiProxy);
//     //app.use('/biz',apiProxy);
//     app.use(context, proxyMiddleware(options));
// });


// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)


module.exports = app.listen(port, function(err) {
    if (err) {
        console.log(err)
        return
    }
    var uri = 'http://localhost:' + port + config.build.assetsPublicPath
    console.log('Listening at ' + uri + '\n')
    opn(uri)
})


================================================
FILE: build/utils.js
================================================
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

exports.assetsPath = function (_path) {
  var assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory
  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function (options) {
  options = options || {}
  // generate loader string to be used with extract text plugin
  function generateLoaders (loaders) {
    var sourceLoader = loaders.map(function (loader) {
      var extraParamChar
      if (/\?/.test(loader)) {
        loader = loader.replace(/\?/, '-loader?')
        extraParamChar = '&'
      } else {
        loader = loader + '-loader'
        extraParamChar = '?'
      }
      return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
    }).join('!')

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
    } else {
      return ['vue-style-loader', sourceLoader].join('!')
    }
  }

  // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
  return {
    css: generateLoaders(['css']),
    postcss: generateLoaders(['css']),
    less: generateLoaders(['css', 'less']),
    sass: generateLoaders(['css', 'sass?indentedSyntax']),
    scss: generateLoaders(['css', 'sass']),
    stylus: generateLoaders(['css', 'stylus']),
    styl: generateLoaders(['css', 'stylus'])
  }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
  var output = []
  var loaders = exports.cssLoaders(options)
  for (var extension in loaders) {
    var loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      loader: loader
    })
  }
  return output
}


================================================
FILE: build/webpack.base.conf.js
================================================
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../')

var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
// various preprocessor loaders added to vue-loader at the end of this file
var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd

module.exports = {
  entry: {
    app: './src/main.js',
    fetch : 'whatwg-fetch'
  },
  //entry: ["whatwg-fetch","./src/main.js"],
  output: {
    path: config.build.assetsRoot,
    publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
    filename: '[name].js'
  },
  resolve: {
    extensions: ['', '.js', '.vue'],
    fallback: [path.join(__dirname, '../node_modules')],
    alias: {
      'vue$': 'vue/dist/vue',
      'src': path.resolve(__dirname, '../src'),
      'assets': path.resolve(__dirname, '../src/assets'),
      'components': path.resolve(__dirname, '../src/components'),
      'pages' : path.resolve(__dirname,'../src/pages'),
      'store' : path.resolve(__dirname,'../src/store')
    }
  },
  resolveLoader: {
    fallback: [path.join(__dirname, '../node_modules')]
  },
  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel',
        include: projectRoot,
        exclude: /node_modules/
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url',
        query: {
          limit: 1,
          // name: utils.assetsPath('img/[name].[hash:7].[ext]')
          name: utils.assetsPath('img/[name].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url',
        query: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  vue: {
    loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }),
    postcss: [
      require('autoprefixer')({
        browsers: ['last 2 versions']
      })
    ]
  }
}


================================================
FILE: build/webpack.dev.conf.js
================================================
var config = require('../config')
var webpack = require('webpack')
var merge = require('webpack-merge')
var utils = require('./utils')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')

// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
  module: {
    loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
  },
  // eval-source-map is faster for development
  devtool: '#eval-source-map',
  plugins: [
    new webpack.DefinePlugin({
      'process.env': config.dev.env
    }),
    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    })
  ]
})


================================================
FILE: build/webpack.prod.conf.js
================================================
var path = require('path')
var config = require('../config')
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : config.build.env

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  vue: {
    loaders: utils.cssLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
      // extract: false
    })
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    // extract css into its own file
    new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    })
  ]
})

if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

module.exports = webpackConfig


================================================
FILE: config/dev.env.js
================================================
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})


================================================
FILE: config/index.js
================================================
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/vux2/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css']
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    //反向代理配置
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}


================================================
FILE: config/prod.env.js
================================================
module.exports = {
  NODE_ENV: '"production"'
}


================================================
FILE: config/test.env.js
================================================
var merge = require('webpack-merge')
var devEnv = require('./dev.env')

module.exports = merge(devEnv, {
  NODE_ENV: '"testing"'
})


================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <link rel="icon" href="http://og1rlwcj8.bkt.clouddn.com/favicon.ico" type="image/x-icon">
    <title>Vux2.0</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>


================================================
FILE: package.json
================================================
{
  "name": "vuxx",
  "version": "0.1.7",
  "description": "vux2.0 project",
  "author": "wong <405176029@qq.com>",
  "repository": {
    "type": "git",
    "url": "https://github.com/jinhuiWong/vux-2.0"
  },
  "homepage": "https://github.com/jinhuiWong/vux-2.0",
  "bugs": {
    "url": "https://github.com/jinhuiWong/vux-2.0/issues"
  },
  "license": "MIT",
  "keywords": [
    "vux",
    "vue",
    "weui",
    "weex",
    "vue-components",
    "web-components",
    "component",
    "components",
    "mobile ui",
    "framework",
    "frontend"
  ],
  "scripts": {
    "dev": "node build/dev-server.js",
    "build": "node build/build.js",
    "unit": "karma start test/unit/karma.conf.js --single-run",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run unit && npm run e2e"
  },
  "dependencies": {
    "array-filter": "^1.0.0",
    "array-find": "^1.0.0",
    "array-from": "^2.1.1",
    "array-map": "0.0.0",
    "array-shuffle": "^1.0.1",
    "autosize": "^3.0.20",
    "countup": "^1.6.2",
    "fastclick": "^1.0.6",
    "less": "^2.7.1",
    "less-loader": "^2.2.3",
    "node-sass": "^3.13.0",
    "object-assign": "^4.1.0",
    "photoswipe": "^4.1.1",
    "qr.js": "0.0.0",
    "sass-loader": "^4.0.2",
    "shake.js": "^1.2.2",
    "validator": "^6.2.0",
    "vue": "^2.0.1",
    "vue-router": "^2.0.1",
    "vuex": "^2.0.0",
    "vuex-router-sync": "^3.0.0",
    "vux-blazy": "^1.6.4",
    "vux-xscroll": "^3.1.8",
    "webp-support": "^1.0.3",
    "whatwg-fetch": "^1.0.0"
  },
  "devDependencies": {
    "autoprefixer": "^6.4.0",
    "babel-core": "^6.0.0",
    "babel-loader": "^6.0.0",
    "babel-plugin-component": "^0.5.1",
    "babel-plugin-transform-runtime": "^6.0.0",
    "babel-preset-es2015": "^6.0.0",
    "babel-preset-stage-2": "^6.0.0",
    "babel-register": "^6.0.0",
    "chai": "^3.5.0",
    "chalk": "^1.1.3",
    "chromedriver": "^2.21.2",
    "connect-history-api-fallback": "^1.1.0",
    "cross-spawn": "^4.0.2",
    "css-loader": "^0.25.0",
    "eventsource-polyfill": "^0.9.6",
    "express": "^4.13.3",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.9.0",
    "function-bind": "^1.0.2",
    "html-webpack-plugin": "^2.8.1",
    "http-proxy-middleware": "^0.17.2",
    "inject-loader": "^2.0.1",
    "isparta-loader": "^2.0.0",
    "json-loader": "^0.5.4",
    "karma": "^1.3.0",
    "karma-coverage": "^1.1.1",
    "karma-mocha": "^1.2.0",
    "karma-phantomjs-launcher": "^1.0.0",
    "karma-sinon-chai": "^1.2.0",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-spec-reporter": "0.0.26",
    "karma-webpack": "^1.7.0",
    "less-loader": "^2.2.3",
    "lolex": "^1.4.0",
    "mocha": "^3.1.0",
    "nightwatch": "^0.9.8",
    "opn": "^4.0.2",
    "ora": "^0.3.0",
    "phantomjs-prebuilt": "^2.1.3",
    "selenium-server": "2.53.1",
    "semver": "^5.3.0",
    "shelljs": "^0.7.4",
    "sinon": "^1.17.3",
    "sinon-chai": "^2.8.0",
    "url-loader": "^0.5.7",
    "vue-loader": "^9.4.0",
    "vue-style-loader": "^1.0.0",
    "webpack": "^1.13.2",
    "webpack-dev-middleware": "^1.8.3",
    "webpack-hot-middleware": "^2.12.2",
    "webpack-merge": "^0.14.1"
  },
  "engines": {
    "node": ">= 4.0.0",
    "npm": ">= 3.0.0"
  }
}


================================================
FILE: src/App.vue
================================================
<template>
  <div style="height:100%;">
    <!-- <loading :show="isLoading" position="absolute"></loading> -->
    <loading :show="isLoading" position="absolute" text="加载中"></loading>
    <view-box ref="viewbox">
      <!--header slot-->
      <div class="vux-demo-header-box" slot="header">
        <x-header :left-options="leftOptions" :transition="headerTransition" :title="title" @on-click-title="scrollTop"></x-header>
      </div>
      <!--default slot-->
      <router-view
      :transition="'vux-pop-' + (direction === 'forward' ? 'in' : 'out')"
      ></router-view>
      <!--bottom slot-->
      <tabbar class="vux-demo-tabbar" icon-class="vux-center" v-show="!isTabbarDemo" slot="bottom">
        <tabbar-item :link="{path:'/'}" :selected="route.path === '/'">
          <span class="demo-icon-22 vux-demo-tabbar-icon-home" slot="icon">&#xe637;</span>
          <span slot="label">Home</span>
        </tabbar-item>
        <tabbar-item :link="{path:'/demo'}" :selected="isDemo" badge="9">
          <span class="demo-icon-22" slot="icon">&#xe633;</span>
          <span slot="label"><span v-if="componentName" class="vux-demo-tabbar-component">{{componentName}}</span><span v-else>Demos</span></span>
        </tabbar-item>
        <tabbar-item :link="{path:'/project/donate'}" :selected="route.path === '/project/donate'" show-dot>
          <span class="demo-icon-22" slot="icon">&#xe630;</span>
          <span slot="label">Donate</span>
        </tabbar-item>
      </tabbar>
    </view-box>
  </div>
</template>

<script>
import { Tabbar, TabbarItem, Loading, ViewBox, XHeader } from './components'

export default {
  components: {
    Tabbar,
    TabbarItem,
    Loading,
    ViewBox,
    XHeader
  },
  data () {
    return {
      routerTransition: {
        forward: 'slideRL',
        back: 'slideLR'
      }
    }
  },
  methods: {
    scrollTop () {
      this.$refs.viewbox.$refs.viewboxbody.scrollTop = 0
    }
  },
  computed: {
    route(){
        return this.$store.state.route
    },
    leftOptions () {
      return {
        showBack: this.route.path !== '/'
      }
    },
    headerTransition () {
      return this.direction === 'forward' ? 'vux-header-fade-in-right' : 'vux-header-fade-in-left'
    },
    componentName () {
      if(!this.route.path) return false
      const parts = this.route.path.split('/');
      if (/component/.test(this.route.path) && parts[2]) return parts[2]
    },
    isDemo () {
      return /component|demo/.test(this.route.path)
    },
    isTabbarDemo () {
      return /tabbar/.test(this.route.path)
    },
    title () {
      if (this.route.path === '/') return 'Home'
      if (this.route.path === '/project/donate') return 'Donate'
      if (this.route.path === '/demo') return 'Demo list'
      return this.componentName ? `Demo/${this.componentName}` : 'Demo/~~'
    }
  },
  mounted(){
    console.log(this.route);
  }
}
</script>

<style lang="less">
@import 'styles/index.less';
@import './styles/weui/base/reset';

html, body {
  height: 100%;
  width: 100%;
  overflow-x: hidden;
}
body {
  background-color: #fbf9fe;
}
/* v-r-transition, default is {forward: 'forward', back: 'back'}*/
.forward-enter, .forward-leave {
  transform: translate3d(-100%, 0, 0);
}
.back-enter, .back-leave {
  transform: translate3d(100%, 0, 0);
}
.demo-icon-22 {
  font-family: 'vux-demo';
  font-size: 22px;
  color: #888;
}
.weui_tabbar.vux-demo-tabbar {
  backdrop-filter: blur(10px);
  background-color: none;
  background: rgba(247, 247, 250, 0.5);
}
.vux-demo-tabbar .weui_bar_item_on .demo-icon-22 {
  color: #F70968;
}
.vux-demo-tabbar .weui_tabbar_item.weui_bar_item_on .weui_tabbar_label {
  color: #35495e;
}
.vux-demo-tabbar .weui_tabbar_item.weui_bar_item_on .vux-demo-tabbar-icon-home {
  color: rgb(53, 73, 94);
}
.demo-icon-22:before {
  content: attr(icon);
}
.vux-demo-tabbar-component {
  background-color: #F70968;
  color: #fff;
  border-radius: 7px;
  padding: 0 4px;
  line-height: 14px;
}
.weui_tabbar_icon + .weui_tabbar_label {
  margin-top: 0!important;
}
.vux-demo-header-box {
  z-index: 100;
  position: absolute;
  width: 100%;
  left: 0;
  top: 0;
}
.weui_tab_bd {
  padding-top: 46px;
}

/**
* vue-router transition
*/
.vux-pop-out-transition,
.vux-pop-in-transition {
  width: 100%;
  animation-duration: 0.5s;
  animation-fill-mode: both;
  backface-visibility: hidden;
}
.vux-pop-out-enter,
.vux-pop-out-leave,
.vux-pop-in-enter,
.vux-pop-in-leave {
  will-change: transform;
  height: 100%;
  position: absolute;
  left: 0;
}
.vux-pop-out-enter {
  animation-name: popInLeft;
}
.vux-pop-out-leave {
  animation-name: popOutRight;
}
.vux-pop-in-enter {
  perspective: 1000;
  animation-name: popInRight;
}
.vux-pop-in-leave {
  animation-name: popOutLeft;
}
@keyframes popInLeft {
  from {
    transform: translate3d(-100%, 0, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}
@keyframes popOutLeft {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-100%, 0, 0);
  }
}
@keyframes popInRight {
  from {
    transform: translate3d(100%, 0, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}
@keyframes popOutRight {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(100%, 0, 0);
  }
}
</style>


================================================
FILE: src/Home.vue
================================================
<template>
  <div>
    <div class="center">
      <svg style="width:60px;height:60px;" version="1.1" id="图形" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve"><path class="svgpath" data-index="path_0" fill="#35495e" d="M512 816.64 51.2 985.6l460.8-947.2 460.8 947.2L512 816.64 512 816.64zM509.44 207.36 189.44 862.72l317.44-117.76L506.88 207.36 509.44 207.36zM509.44 207.36" /></svg>

      <h1 class="vux-title" style="display:none;">
        <span class="demo-icon" slot="icon" style="font-size:60px;color:#35495e;display: block;">&#xe637;</span>
      </h1>
      <p class="vux-notice">v{{version}}</p>
    </div>
    <group>
      <cell title="Demo" link="/demo" value="演示">
        <span class="demo-icon" slot="icon" style="color:#F70968">&#xe633;</span>
      </cell>
    </group>
    <group>
      <cell title="Buy me a coffee" link="project/donate">
        <span class="demo-icon" slot="icon" style="color:red;">&#xe630;</span>
        <div class="badge-value vux-center-v" slot="value" >
          <badge text="捐赠"></badge>
        </div>
      </cell>
      <cell title="Github" link="https://github.com/jinhuiWong/vux-2.0" value="Star me">
        <span class="demo-icon" slot="icon" style="color:#35495e;">&#xe62f;</span>
      </cell>
    </group>
  </div>
</template>

<script>
import { Cell, Group, Badge } from './components'
const version = require('../package.json').version
export default {
  components: {
    Cell,
    Group,
    Badge
  },
  data () {
    return {
      version: '2.0.0'
    }
  }
}
</script>

<style>
@import './demos/style.css';
.badge-value{
  display: inline-block;
}
.center {
  margin-top: 15px;
  text-align: center;
}
.vux-notice {
  color: #666;
  line-height: 40px;
}
.vux-title {
  vertical-align: middle;
  text-align: center;
  color: #04BE02;
  display: inline-block;
  width: 75px;
  height: 75px;
  line-height: 75px;
  border-radius: 50%;
}
body {
  font-family: Helvetica, sans-serif;
  background-color: #fbf9fe;
}
</style>


================================================
FILE: src/Wechat.vue
================================================
<template>
  <div>
    <group>
      <cell title="接收新消息通知" value="已启用"></cell>
    </group>
    <tip>如果你要关闭或开启微信的新消息通知,请在iPhone的"设置"-"通知"功能中,找到应用程序"微信"更改。</tip>

    <group>
      <x-switch title="通知显示消息详情" :value="true"></x-switch>
    </group>
    <tip>关闭后,当收到微信消息时,通知提示将不再显示发信人和内容摘要。</tip>

    <group>
      <cell title="功能消息免打扰" is-link></cell>
    </group>
    <tip>设置系统功能消息提示声音和振动的时段。</tip>

    <group>
      <x-switch title="声音" :value="false"></x-switch>
      <x-switch title="振动" :value="true"></x-switch>
    </group>
    <tip>当微信在运行时,你可以设置是否需要声音或者振动。</tip>

    <group>
      <x-switch title="朋友圈照片更新" :value="true"></x-switch>
    </group>
    <tip>关闭后,有朋友更新照片时,界面下面的"发现"切换按钮上不再出现红点提示。</tip>
  </div>
</template>

<script>
import { DevTip, Number, Selector, Group, GroupTitle, Button as Btn, Tip, XSwitch, Radio, Checklist, Cell, Xinput } from './components'

export default {
  components: {
    Number,
    Selector,
    Group,
    Btn,
    Tip,
    XSwitch,
    GroupTitle,
    Radio,
    DevTip,
    Checklist,
    Cell,
    Xinput
  },
  data () {
    return {
    }
  },
  methods: {
    change (value) {
      console.log('change:', value)
    }
  }
}
</script>

<style>
</style>


================================================
FILE: src/components/actionsheet/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/actionsheet/index.vue
================================================
<template>
  <div class="vux-actionsheet">
    <div class="weui_mask_transition" :class="{'weui_fade_toggle': props_show}" :style="{display: props_show ? 'block' : 'none'}" @click="props_show=false"></div>
    <div class="weui_actionsheet" :class="{'weui_actionsheet_toggle': props_show}">
      <div class="weui_actionsheet_menu">
        <div class="actionsheet_cell_container">
          <div class="weui_actionsheet_cell" v-for="(text, key) in menus" @click="emitEvent('on-click-menu', key)" v-html="text">
          </div>
        </div>
        <!-- <div class="vux-actionsheet-gap" v-if="showCancel"></div> -->
        <div class="weui_actionsheet_cell vux-actionsheet-cancel" @click="emitEvent('on-click-menu', 'cancel')" v-if="showCancel">{{cancelText}}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  created(){
    this.props_show=this.show
    if(this.value) this.props_show=this.value
  },
  mounted () {
    this.$tabbar = document.querySelector('.weui_tabbar')
  },
  props: {
    show: Boolean,
    value: {
      type:Boolean,
      default:false
    },
    showCancel: Boolean,
    cancelText: {
      type: String,
      default: 'cancel'
    },
    menus: {
      type: Object,
      default: () => {}
    }
  },
  data(){
    return{
      props_show:false
    }
  },
  methods: {
    emitEvent (event, menu) {
      if (event === 'on-click-menu' && !/.noop/.test(menu)) {
        this.$emit(event, menu)
        this.$emit(`${event}-${menu}`)
        this.props_show = false
      }
    },
    fixIos (zIndex) {
      if (this.$tabbar && /iphone/i.test(navigator.userAgent)) {
        this.$tabbar.style.zIndex = zIndex
      }
    }
  },
  watch: {
    value(val){
      this.props_show=val
    },
    props_show(val){
      if (val) {
        this.fixIos(-1)
      } else {
        setTimeout(() => {
          this.fixIos(100)
        }, 200)
      }
      this.$emit('input',val)
    },
    show (val) {
      this.props_show=val
    }
  },
  beforeDestroy () {
    this.fixIos(100)
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_tips/weui_mask';
@import '../../styles/weui/widget/weui_tips/weui_actionsheet';

.vux-actionsheet-gap {
  height: 8px;
  width: 100%;
  background-color: #eee;
}

.vux-actionsheet-cancel{
  border-radius: 15px;
  margin:0px 15px;
  margin-bottom:13px;
}

.vux-actionsheet-cancel:before {
  border-top: none;
}

// css hack
.weui_fade_toggle {
  background: rgba(0, 0, 0, 0.3);
}

.weui_actionsheet {
    background-color: inherit ;
}

.weui_actionsheet_menu {
    background-color: inherit;
}

.weui_actionsheet_cell {
    background-color: #fff;
    padding: 15px 0;
}

.actionsheet_cell_container{
  border-radius: 15px;
  margin:15px;
  margin-bottom:5px;
  overflow:hidden
}
</style>


================================================
FILE: src/components/actionsheet/metas.yml
================================================
props:
  show:
    en: if show the component
    zh-CN: 是否显示
  show-cancel:
    en: if show the cancel menu
    zh-CN: 是否显示取消菜单
  cancel-text:
    en: text of cancel menu
    zh-CN: 取消菜单文字
  menus:
    en: "menu items, for example: `{menu1: 'some text'}`, menu name with `.noop` will not trigger click events"
    zh-CN: "菜单项列表,举例:`{menu1: '删除'}`,如果名字上带有`.noop`表明这是纯文本展示,不会触发事件,用于展示描述"
events:
  on-click-menu:
    en: triggers when clicking on the menu
    zh-CN: 点击菜单时触发,参数为当前菜单项对象
  on-click-menu-{menuName}:
    en: shortcut event for easily listening, you can listen on `on-click-menu-delete` if you have a menu named `delete`
    zh-CN: 点击事件的快捷方式, 如果你有一个菜单名字为`delete`, 那么你可以监听 `on-click-menu-delete`
  on-click-menu-cancel:
    en: triggers when click on cancel menu
    zh-CN: 点击取消菜单时触发


================================================
FILE: src/components/alert/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/alert/index.vue
================================================
<template>
  <div class="vux-alert">
    <input style="display:none" v-model="props_show">
    <x-dialog
    class="weui_dialog_alert"
    :show="props_show"
    :mask-transition="maskTransition"
    :dialog-transition="dialogTransition"
    @on-hide="$emit('on-hide')"
    @on-show="$emit('on-show')">
      <div class="weui_dialog_hd"><strong class="weui_dialog_title">{{title}}</strong></div>
      <div class="weui_dialog_bd"><slot></slot></div>
      <div class="weui_dialog_ft">
        <a href="javascript:" class="weui_btn_dialog primary" @click="onHide">{{buttonText}}</a>
      </div>
    </x-dialog>
  </div>
</template>

<script>
import XDialog from '../dialog'

export default {
  components: {
    XDialog
  },
  props: {
    value: {
      type: Boolean,
      default: false
    },
    show: Boolean,
    title: String,
    buttonText: {
      type: String,
      default: 'OK'
    },
    maskTransition: {
      type: String,
      default: 'vux-fade'
    },
    dialogTransition: {
      type: String,
      default: 'vux-dialog'
    }
  },
  created(){
    this.props_show=this.show
    if(this.value) this.props_show=this.value
  },
  methods: {
    onHide () {
      this.props_show = false
    }
  },
  watch: {
    value(val){
      this.props_show=val
    },
    props_show(val){
      this.$emit('input',val)
    },
    show (val) {
      this.props_show=val
    }
  },
  data(){
    return{
      props_show:false
    }
  }
}
</script>

<style lang="less">
@import '../../styles/transition.less';
@import '../../styles/weui/widget/weui_tips/weui_mask';
@import '../../styles/weui/widget/weui_tips/weui_dialog';
</style>


================================================
FILE: src/components/alert/metas.yml
================================================
extends:
  - Dialog
when:
  -
    - en: Show some information that user should pay attention to and should be closed only after user has clicked the close button
    - zh-CN: 显示一个用户必须注意到并且必须点击按钮确认才能关闭的信息
props:
  show:
    en: visibility of the component
    zh-CN: 是否显示
  title:
    en: title
    zh-CN: 弹窗标题
  button-text:
    en: button text
    zh-CN: 按钮文字
  mask-transition:
    en: mask transition
    zh-CN: 遮罩动画
  dialog-transition:
    en: dialog transition
    zh-CN: 弹窗主体动画


================================================
FILE: src/components/badge/index.vue
================================================
<template>
  <span v-text="text" :class="['vux-badge', {'vux-badge-single': text.length === 1}]"></span>
</template>

<script>
export default {
  props: {
    text: [String, Number]
  }
}
</script>

<style lang="less">
@import '../../styles/variable.less';

.vux-badge {
  display: inline-block;
  text-align: center;
  background: @badge-bg-color;
  color: #fff;
  font-size: 12px;
  height: 16px;
  line-height: 16px;
  border-radius: 8px;
  padding: 0 6px;
  background-clip: padding-box;
}
.vux-badge-single {
  padding: 0;
  width: 16px;
}
</style>


================================================
FILE: src/components/badge/metas.yml
================================================
props:
  text:
    en: text of the Badge
    zh-CN: 显示的文字


================================================
FILE: src/components/blur/blur.js
================================================
/* Image Blur plugin, author @msurguy

 Usage:

 Create a set of elements that follows the following HTML structure:

 <div class="container">
   <div class="content">
   ...
   </div>
 </div>

 Add the following css:

 .container {
   overflow: hidden
   width: 100%
   position: relative
 }

 .container .bg-blur-overlay {
   z-index: -1
   position: absolute
   width: 100%
   height: 100%
   background-image: url('data:image/svg+xmlbase64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wOCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMDgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC45Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g')
   background-size: 100%
   background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(46%, rgba(0, 0, 0, 0.08)), color-stop(59%, rgba(0, 0, 0, 0.08)), color-stop(100%, rgba(0, 0, 0, 0.9)))
   background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.08) 46%, rgba(0, 0, 0, 0.08) 59%, rgba(0, 0, 0, 0.9) 100%)
   background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.08) 46%, rgba(0, 0, 0, 0.08) 59%, rgba(0, 0, 0, 0.9) 100%)
   background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.08) 46%, rgba(0, 0, 0, 0.08) 59%, rgba(0, 0, 0, 0.9) 100%)
 }

 .container .bg-blur {
   z-index: -2
   opacity: 0
   position: absolute
   width: 100%
   min-height: 100%
   height: auto
   display: block
   top: 0
   left: 0
 }

 .container .content {
  z-index: 1
 }

 */

import Eventor from '../../libs/eventor'

// Random ID generator
var randomID = function () {
  return '_' + Math.random().toString(36).substr(2, 9)
}

// micro lib that creates SVG elements and adds attributes to it
var SVG = {

  // namespaces
  svgns: 'http://www.w3.org/2000/svg',
  xlink: 'http://www.w3.org/1999/xlink',

  // creating of SVG element
  createElement (name, attrs) {
    var element = document.createElementNS(SVG.svgns, name)

    if (attrs) {
      SVG.setAttr(element, attrs)
    }
    return element
  },

  // setting attributes
  setAttr (element, attrs) {
    for (var i in attrs) {
      if (i === 'href') { // path of an image should be stored as xlink:href attribute
        element.setAttributeNS(SVG.xlink, i, attrs[i])
      } else { // other common attribute
        element.setAttribute(i, attrs[i])
      }
    }
    return element
  }
}

// backgroundBlur PUBLIC CLASS DEFINITION
// ================================

var Blur = function (element, options) {
  this.internalID = randomID()
  this.element = element
  this.width = element.offsetWidth
  this.height = element.offsetHeight
  this.element = element
  this.parent = this.element.parentNode
  this.options = Object.assign({}, Blur.DEFAULTS, options)
  this.overlayEl = this.createOverlay()
  this.blurredImage = null
  this.attachListeners()
  this.generateBlurredImage(this.options.url)
}

Blur.VERSION = '0.0.1'

Eventor.mixTo(Blur)

Blur.DEFAULTS = {
  url: '', // URL to the image
  blurAmount: 10, // Amount of blurrines
  imageClass: '', // CSS class that will be applied to the image and to the SVG element,
  overlayClass: '', // CSS class of the element that will overlay the blur image
  duration: false, // If the image needs to be faded in, how long should that take
  opacity: 1 // Specify the final opacity
}

Blur.prototype.setBlurAmount = function (blurAmount) {
  this.options.blurAmount = blurAmount
}

Blur.prototype.attachListeners = function () {
  this.on('ui.blur.loaded', this.fadeIn.bind(this))
  this.on('ui.blur.unload', this.fadeOut.bind(this))
}

Blur.prototype.fadeIn = function () {
}

Blur.prototype.fadeOut = function () {
}

Blur.prototype.generateBlurredImage = function (url) {
  const previousImage = this.blurredImage
  this.internalID = randomID()

  if (previousImage) {
    previousImage.parentNode.removeChild(previousImage)
  }

  this.blurredImage = this.createSVG(url, this.width, this.height)
}

Blur.prototype.createOverlay = function () {
  if (this.options.overlayClass && this.options.overlayClass !== '') {
    const div = document.createElement('div')
    div.classList.add(this.options.overlayClass)
    this.parent.insertBefore(div, this.element)
    return div
  }

  return false
}

Blur.prototype.createSVG = function (url, width, height) {
  var that = this
  var svg = SVG.createElement('svg', { // our SVG element
    xmlns: SVG.svgns,
    version: '1.1',
    width: width,
    height: height,
    id: 'blurred' + this.internalID,
    'class': this.options.imageClass,
    viewBox: '0 0 ' + width + ' ' + height,
    preserveAspectRatio: 'none'
  })

  var filterId = 'blur' + this.internalID // id of the filter that is called by image element
  var filter = SVG.createElement('filter', { // filter
    id: filterId
  })

  var gaussianBlur = SVG.createElement('feGaussianBlur', { // gaussian blur element
    'in': 'SourceGraphic', // "in" is keyword. Opera generates an error if we don't put quotes
    stdDeviation: this.options.blurAmount // intensity of blur
  })

  var image = SVG.createElement('image', { // The image that uses the filter of blur
    x: 0,
    y: 0,
    width: width,
    height: height,
    'externalResourcesRequired': 'true',
    href: url,
    style: 'filter:url(#' + filterId + ')', // filter link
    preserveAspectRatio: 'none'
  })

  image.addEventListener('load', function () {
    that.emit('ui.blur.loaded')
  }, true)

  image.addEventListener('SVGLoad', function () {
    that.emit('ui.blur.loaded')
  }, true)

  filter.appendChild(gaussianBlur) // adding the element of blur into the element of filter
  svg.appendChild(filter) // adding the filter into the SVG
  svg.appendChild(image) // adding an element of an image into the SVG

  // Ensure that the image is shown after duration + 100 msec in case the SVG load event didn't fire or took too long
  if (that.options.duration && that.options.duration > 0) {
    svg.style.opacity = 0
    window.setTimeout(function () {
      if (getStyle(svg, 'opacity') === '0') {
        svg.style.opacity = 1
      }
    }, this.options.duration + 100)
  }
  this.element.insertBefore(svg, this.element.firstChild)
  return svg
}

Blur.prototype.createIMG = function (url, width, height) {
  var that = this
  var originalImage = this.prependImage(url)
  var newBlurAmount = ((this.options.blurAmount * 2) > 100) ? 100 : (this.options.blurAmount * 2)
  // apply special CSS attributes to the image to blur it
  const styles = {
    // filter property here the intensity of blur multipied by two is around equal to the intensity in common browsers.
    filter: 'progid:DXImageTransform.Microsoft.Blur(pixelradius=' + newBlurAmount + ') ',
    // aligning of the blurred image by vertical and horizontal
    top: -this.options.blurAmount * 2.5,
    left: -this.options.blurAmount * 2.5,
    width: width + (this.options.blurAmount * 2.5),
    height: height + (this.options.blurAmount * 2.5)
  }
  for (var i in styles) {
    originalImage.style[i] = styles[i]
  }
  originalImage.setAttribute('id', this.internalID)

  originalImage.onload = function () {
    that.trigger('ui.blur.loaded')
  }
  // Ensure that the image is shown after duration + 100 msec in case the image load event didn't fire or took too long
  if (this.options.duration && this.options.duration > 0) {
    window.setTimeout(function () {
      if (getStyle(originalImage, 'opacity') === '0') {
        originalImage.style.opacity = 1
      }
    }, this.options.duration + 100)
  }
  return originalImage
}

Blur.prototype.prependImage = function (url) {
  const img = document.createElement('img')
  img.url = url
  img.setAttribute('id', this.internalID)
  img.classList.add(this.options.imageClass)
  if (this.overlayEl) {
    this.parent.insertBefore(img, this.overlayEl)
  } else {
    this.parent.insertBefore(img, this.parent.firstChild)
  }
  return img
}

export default Blur

function getStyle (ele, prop) {
  return window.getComputedStyle(ele, null).getPropertyValue(prop)
}


================================================
FILE: src/components/blur/index.vue
================================================
<template>
  <div :style="{height: height + 'px',position: 'relative', overflow: 'hidden'}">
    <slot></slot>
  </div>
</template>

<script>
import Blur from './blur'

export default {
  mounted () {
    this._blur = new Blur(this.$el, {
      url: this.url,
      blurAmount: this.blurAmount,
      imageClass: 'vux-bg-blur',
      duration: 100, // If the image needs to be faded in, how long that should take
      opacity: 1 // Specify the final opacity that the image will have
    })
  },
  props: {
    blurAmount: {
      type: Number,
      default: 10
    },
    url: {
      type: String,
      required: true
    },
    height: {
      type: Number,
      default: 200
    }
  },
  watch: {
    blurAmount (blurAmount) {
      this._blur.setBlurAmount(blurAmount)
      this._blur.generateBlurredImage(this.url)
    },
    url (url) {
      this._blur.generateBlurredImage(url)
    }
  }
}
</script>

<style lang="less">
.vux-bg-blur {
  z-index: -2;
  opacity: 0;
  position: absolute;
  min-height: 100%;
  display: block;
  top: 0;
  max-height: none;
  /* Add this CSS to remove transparent border around the image */
  left: -20%;
  top: -20%;
  width: 140%;
  height: 140%;
  transition: opacity linear 0.8s;
}
/*
An element with this class is added by the plugin to provide an overlay above the blurred image
It could drastically improve the appearance of the blurred image for content readability
*/
.vux-bg-blur-overlay {
  z-index: -1;
  position: absolute;
  width: 100%;
  height: 100%;
  background: linear-gradient(to bottom,  rgba(0,0,0,0.15) 0%,rgba(0,0,0,1) 100%);
}
</style>


================================================
FILE: src/components/blur/metas.yml
================================================
tips:
  -
    - en: If the component renders slowly on your target platform, you can try `css3 blur filter`
    - zh-CN: 如果在手机上渲染过慢,可以尝试使用css3的`blur filter`
props:
  blur-amount:
    en: blur amount of the effect
    zh-CN: 模糊程度
  url:
    en: url of the image
    zh-CN: 图片地址
  height:
    en: height of the container
    zh-CN: 容器高度
slots:
  default:
    en: content of the container, above the blur image
    zh-CN: 容器内容,显示在模糊内容上面


================================================
FILE: src/components/box/index.vue
================================================
<template>
  <div :style="{margin:gap}"><slot></slot></div>
</template>

<script>
export default {
  props: {
    gap: String
  }
}
</script>


================================================
FILE: src/components/box/metas.yml
================================================
intro:
  en: a small component for lazy persons who don't want to write less code
  zh-CN: 为div设置margin值,懒人才需要的组件
props:
  gap:
    en: margin value
    zh-CN: margin值


================================================
FILE: src/components/button-tab/button-tab-item.vue
================================================
<template>
  <a class="vux-button-tab-item" :class="classes" href="javascript:" :style="style" @click="onItemClick">
    <slot></slot>
  </a>
</template>

<script>

export default {
  mounted() {
    this.$parent.updateIndex()
    this.props_selected=this.selected
  },
  computed: {
    classes () {
      return {
        'vux-button-group-current': this.index === this.$parent.props_index,
        'no-border-right': this.shouldRemoveBorder
      }
    },
    style () {
      if (this.$parent.height) {
        return {
          height: `${this.$parent.height}px`,
          lineHeight: `${this.$parent.height}px`
        }
      }
    }
  },
  props: {
    selected: {
      type: Boolean,
      default: false
    }
  },
  mounted() {
    this.$parent.updateIndex()
  },
  beforeDestroy() {
    const $parent = this.$parent
    this.$nextTick(() => {
      $parent.updateIndex()
    })
  },
  methods: {
    onItemClick() {
      if (typeof this.disabled === 'undefined' || this.disabled === false) {
          this.props_selected = true;
          this.$parent.$emit('onTabItemClick',this.index);
      }
    }
  },
  watch: {
    props_selected(val){
      if (val) {
          this.$parent.$emit('onTabItemClick',this.index);
        }
    },
    selected (val) {
      console.log('selected');
      this.props_selected=val;
    }
  },
  data() {
    return {
      index: -1,
      shouldRemoveBorder: false,
      props_selected:false
    }
  }


}
</script>


================================================
FILE: src/components/button-tab/button-tab.vue
================================================
<template>
  <div class="vux-button-group">
    <slot></slot>
  </div>
</template>

<script>

export default {
  mounted() {
    this.updateIndex()
    this.$on('onTabItemClick',function(index){
        this.props_index = index;
        this.$emit('on-index-change', this.props_index);
    });
  },
  methods: {
    updateIndex() {
      if (!this.$children) return
      this.number = this.$children.length
      let children = this.$children
      for (let i = 0; i < children.length; i++) {
        children[i].index = i
        if (children[i]=== this.index) {
            this.props_index = i
        }
      }
    }
  },
  props: {
    index: {
      type: Number,
      default: -1
    },
    value: {
      type: Number,
      default: 0
    },
    height: Number
  },
  watch: {
    props_index(newIndex, oldIndex) {
      oldIndex > -1 && this.$children[oldIndex] && (this.$children[oldIndex].props_selected = false)
      newIndex > -1 && (this.$children[newIndex].props_selected = true)
      this.$emit('input',newIndex);
    },
    value(val){
      this.props_index=val
    },
    index : function(newIndex, oldIndex){
        this.props_index=newIndex;
    },
  },
  data() {
    return {
      number: this.$children.length,
      props_index:0
    }
  }
}
</script>

<style lang="less">
@import '../../styles/variable.less';

.vux-button-group {
  & {
    display: box;
    display: flex;
  }

  & > a  {
    display: block;
    flex: 1;
    width: 100%;
    height: 30px;
    padding: 0;
    font-size: 14px;
    line-height: 31px;
    text-align: center;
    border: 1px solid #d2d2d2;
    border-width: 1px 1px 1px 0;
    color: #999;
    white-space: nowrap;
    background: #fdfdfd
  }

  & > a.vux-button-group-current,
  & > a.hover,
  & > a:active {
    border-color: @color-wechat-green;
    color: #FFF;
    background: @color-wechat-green
  }

  & > a:first-child {
    border-width: 1px;
    border-top-left-radius: 16px;
    border-bottom-left-radius: 16px;
    background-clip: padding-box
  }

  & > a:last-child {
    border-top-right-radius: 16px;
    border-bottom-right-radius: 16px;
    background-clip: padding-box;
  }

  & > a.vux-button-group-current:disabled,
  & > a:disabled {
    border-color: #CDCDCD;
    background: #e5e5e5;
    box-shadow: 0 1px 0 rgba(255,255,255,.6);
    text-shadow: 0 1px 0 rgba(255,255,255,.8);
    color: #aaa
  }
  & .no-border-right {
    border-right-width: 0!important;
  }
}
</style>


================================================
FILE: src/components/button-tab/index.js
================================================
import ButtonTab from './button-tab'
import ButtonTabItem from './button-tab-item'

export {
  ButtonTab,
  ButtonTabItem
}


================================================
FILE: src/components/button-tab/metas.yml
================================================
button-tab:
  props:
    index:
      zh-CN: 当前选中索引值,从0开始
    height:
      zh-CN: 高度值
button-tab-item:
  props:
    selected:
      zh-CN: 是否选中
  events:
    on-item-click:
      zh-CN: 当前按钮点击时触发


================================================
FILE: src/components/calendar/index.vue
================================================
<template>
<div>
  <cell :title="title" primary="content" :value="props_value" @click="onClick" is-link></cell>
  <popup v-model="show">
    <inline-calendar
    :value="props_value"
    @on-change="onSelect"
    :render-month="renderMonth"
    :start-date="startDate"
    :end-date="endDate"
    :show-last-month="showLastMonth"
    :show-next-month="showNextMonth"
    :highlight-weekend="highlightWeekend"
    :return-six-rows="returnSixRows"
    :hide-header="hideHeader"
    :hide-week-list="hideWeekList"
    :replace-text-list="replaceTextList"
    :weeks-list="weeksList"
    :custom-slot-fn="customSlotFn"
    :render-on-value-change="renderOnValueChange"
    :disable-past="disablePast"
    :disable-future="disableFuture"
    ></inline-calendar>
  </popup>
</div>
</template>

<script>
import InlineCalendar from '../inline-calendar'
import Popup from '../popup'
import Cell from '../cell'
import props from '../inline-calendar/props'

const Props = props()
Props.title = {
  type: String,
  required: true
}

export default {
  components: {
    InlineCalendar,
    Popup,
    Cell
  },
  created(){
    this.props_value=this.value
  },
  props: Props,
  methods: {
    onClick () {
      this.show = true
    },
    onSelect (val) {
      this.show = false
      this.props_value=val
      this.$emit('on-change',val)
    }
  },
  watch:{
    value(val){
      this.props_value=val
    }
  },
  data () {
    return {
      show: false,
      props_value:''
    }
  }
}
</script>


================================================
FILE: src/components/calendar/metas.yml
================================================
extends:
  - inline-calendar
  - popup
  - cell
intro:
  zh-CN: 扩展自inline-calendar, 相关属性可查看inline-calendar文档
props:
  value:
    zh-CN: 选中值
  title:
    zh-CN: label文字
events:
  on-change:
    zh-CN: 值改变时触发


================================================
FILE: src/components/card/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/card/index.vue
================================================
<template>
	<div class="weui_panel weui_panel_access">
    <div class="weui_panel_hd" v-if="header && header.title" v-html="header.title" @click="$emit('on-click-header')"></div>
    <slot name="header"></slot>
    <div class="weui_panel_bd">
      <div class="vux-card-content"><slot name="content"></slot></div>
    </div>
    <a class="weui_panel_ft" href="javascript:" v-if="footer && footer.title" v-html="footer.title" @click="onClickFooter"></a>
    <slot name="footer"></slot>
  </div>
</template>

<script>
import { go } from '../../libs/router'

export default {
  props: {
    header: Object,
    footer: Object
  },
  methods: {
    onClickFooter () {
      this.footer.link && go(this.footer.link, this.$router)
      this.$emit('on-click-footer')
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_panel/weui_panel';
</style>


================================================
FILE: src/components/card/metas.yml
================================================
props:
  header.title:
    zh-CN: 头部标题,不指定则不显示
  footer.title:
    zh-CN: 底部标题,不指定则不显示
  footer.link:
    zh-CN: 底部链接,普通url或者v-link参数
events:
  on-click-footer:
    zh-CN: 点击底部时触发
  on-click-header:
    zh-CN: 点击头部时触发
slots:
  header:
    zh-CN: 头部位置
  content:
    zh-CN: 中间主体位置
  footer:
    zh-CN: 底部位置


================================================
FILE: src/components/cell/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/cell/index.vue
================================================
<template>
  <div class="weui_cell" :class="{'vux-tap-active': isLink || !!link}" @click="onClick">
    <div class="weui_cell_hd">
      <slot name="icon"></slot>
    </div>
    <div class="weui_cell_bd" :class="{'weui_cell_primary':primary==='title'}">
      <p>
        {{title}}
        <slot name="after-title"></slot>
      </p>
      <inline-desc>{{inlineDesc}}</inline-desc>
    </div>
    <div class="weui_cell_ft" :class="{'weui_cell_primary':primary==='content', 'with_arrow': isLink || !!link}">
      {{value}}
      <slot name="value"></slot>
      <slot></slot>
    </div>
    <slot name="child"></slot>
  </div>
</template>

<script>
import InlineDesc from '../inline-desc'
// import { go } from '../../libs/router'

export default {
  components: {
    InlineDesc
  },
  props: {
    title: String,
    value: [String, Number],
    isLink: Boolean,
    inlineDesc: [String, Number],
    primary: {
      type: String,
      default: 'title'
    },
    link: {
      type: [String, Object]
    }
  },
  methods: {
    onClick () {
      // go(this.link, this.$router);
      this.link ? this.$router.push(this.link) : false
      this.$emit("click")
    }
  }
}
</script>

<style lang="less">
@import '../../styles/variable.less';
@import '../../styles/tap.less';
@import '../../styles/weui/widget/weui_cell/weui_cell_global';

.weui_cell_bd > p {
  color: @cell-body-label-color;
}

.weui_cell_ft.with_arrow:after {
  content: " ";
  display: inline-block;
  transform: rotate(45deg);
  height: 6px;
  width: 6px;
  border-width: 2px 2px 0 0;
  border-color: #C8C8CD;
  border-style: solid;
  position: relative;
  top: -1px;
  margin-left: .3em;
}
</style>


================================================
FILE: src/components/cell/metas.yml
================================================
props:
  title:
    en: label text
    zh-CN: 左边标题文字
  value:
    en: right text
    zh-CN: 右侧文字,复杂的样式布局请使用slot
  inline-desc:
    en: the text below title
    zh-CN: 标题下面文字,一般为说明文字
  is-link:
    en: if this is a link, if true, there will be an arrow on the right
    zh-CN: 是否为链接,如果是,右侧将会出现指引点击的右箭头
  primary:
    en: "main content area, can be in ['title', 'content']"
    zh-CN: "可选值为 ['title', 'content'],对应的div会加上weui_cell_primary类名实现内容宽度自适应"
slots:
  default:
    en: "right area, you can use default slot instead of prop:value so you can use complexed layout"
    zh-CN: 右侧内容,相比于value的优点是可以用复杂的样式或者调用组件
  value:
    en: "[deprecated] the same as default slot"
    zh-CN: "[废弃] 同默认slot"
  icon:
    en: icon area before title
    zh-CN: 标题左侧的图像位置
  after-title:
    en: after title
    zh-CN: 标题右侧位置
  child:
    en: the child element of the cell, you can add an element with absolute position
    zh-CN: cell的直接子元素,因此可以添加一个相对于cell绝对定位的元素


================================================
FILE: src/components/check-icon/index.vue
================================================
<template>
  <div class="vux-check-icon" @click="value = !value">
    <icon type="success" v-show="type === 'default' && value"></icon>
    <icon type="success_circle" v-show="type === 'plain' && value"></icon>
    <icon type="circle" v-show="!value"></icon>
    <span><slot></slot></span>
  </div>
</template>

<script>
import Icon from '../icon'

export default {
  components: {
    Icon
  },
  props: {
    value: Boolean,
    type: {
      type: String,
      default: 'default'
    }
  }
}
</script>

<style lang="less">
@import '../../styles/variable.less';

.vux-check-icon {
  display: inline-block;
}
.vux-check-icon span {
  line-height: 20px;
  color: #222;
  vertical-align: bottom;
}
.vux-check-icon > .weui_icon_success:before, .vux-check-icon > .weui_icon_success_circle:before {
  color: @check-icon-color-checked;
}
</style>




================================================
FILE: src/components/checker/checker-item.vue
================================================
<template>
  <div class="vux-checker-item" :class="classNames" @click="select">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: [String, Number],
      required: true
    },
    disabled: Boolean
  },
  computed: {
    classNames () {
      const names = {
        'vux-tap-active': !this.disabled
      }
      if (this.$parent.defaultItemClass) {
        names[this.$parent.defaultItemClass] = true
      }
      if (this.$parent.selectedItemClass) {
        names[this.$parent.selectedItemClass] = this.$parent.type === 'radio' ? (this.$parent.props_value[0] === this.value) : (this.$parent.props_value.indexOf(this.value) > -1)
      }
      if (this.$parent.disabledItemClass) {
        names[this.$parent.disabledItemClass] = this.disabled
      }
      return names
    }
  },
  methods: {
    select () {
      if (this.$parent.type === 'radio') {
        this.selectRadio()
      } else {
        this.selectCheckbox()
      }
    },
    selectRadio () {
      if (!this.disabled) {
        if(this.$parent.props_value.length === 0){
          this.$parent.props_value.push(this.value)
        }else{
          this.$parent.props_value.splice(0,1, this.value)
        }
        // this.$parent.$set(this.$parent,'props_value', this.value)
        this.$emit('on-item-click', this.value, this.disabled)
      }
    },
    selectCheckbox () {
      if (!this.disabled) {
        const index = this.$parent.props_value.indexOf(this.value)
        if (index > -1) {
          this.$parent.props_value.splice(index, 1)
        } else {
          if (!this.$parent.max || (this.$parent.max && this.$parent.props_value.length < this.$parent.max)) {
            this.$parent.props_value.push(this.value)
          }
        }
        this.$emit('on-item-click', this.value, this.disabled)
      }
    }
  }
}
</script>

<style lang="less">
@import '../../styles/tap.less';
</style>


================================================
FILE: src/components/checker/checker.vue
================================================
<template>
  <div class="vux-checker-box">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    defaultItemClass: String,
    selectedItemClass: String,
    disabledItemClass: String,
    type: {
      type: String,
      default: 'radio'
    },
    value: [Array],
    max: Number
  },
  data(){
    return {
      props_value:[]
    }
  },
  created(){
    this.props_value=this.value
  },
  watch: {
    props_value(val){
      this.$emit('on-change', val)
    },
    value (newValue) {
      this.props_value=this.value
    }
  }
}
</script>

<style>
.vux-checker-item {
  display: inline-block;
}
</style>


================================================
FILE: src/components/checker/index.js
================================================
import Checker from './checker'
import CheckerItem from './checker-item'

export {
  Checker,
  CheckerItem
}


================================================
FILE: src/components/checker/metas.yml
================================================
checker:
  props:
    default-item-class:
      zh-CN: 默认class
    selected-item-class:
      zh-CN: 选中样式
    disabled-item-class:
      zh-CN: 不可选样式
    type:
      zh-CN: 类型,单选为radio, 多选为checkbox
    value:
      zh-CN: 表单值
    max:
      zh-CN: 最多可选个数,多选时可用
  events:
    on-change:
      zh-CN: value值变化时触发
checker-item:
  props:
    value:
      zh-CN: 当前项的值
    disabled:
      zh-CN: 是否为不可选
  events:
    on-item-click:
      zh-CN: 当前项被点击时触发,参数为(itemValue, itemDisabled)


================================================
FILE: src/components/checklist/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/checklist/index.vue
================================================
<template>
<div>
  <div v-show="title" class="weui_cells_title">{{title}}</div>
  <div class="weui_cells weui_cells_checkbox">
    <label class="weui_cell weui_check_label" :for="'checkbox_'+uuid+'_'+index" v-for="(one, index) in props_options">
      <div class="weui_cell_hd">
        <input type="checkbox" class="weui_check" :value="getItemKey(one)" v-model="props_value" :id="'checkbox_'+uuid+'_'+index">
        <i class="weui_icon_checked"></i>
      </div>
      <div class="weui_cell_bd weui_cell_primary">
        <p v-html="getItemValue(one)"></p>
      </div>
    </label>
  </div>
  <tip v-show="!valid && dirty"><icon type="warn" class="icon_small"></icon>{{error}}</tip>
</div>

</template>

<script>
import Tip from '../tip'
import Icon from '../icon'
import { getValue, getKey } from './object-filter'
import shuffle from 'array-shuffle'

export default {
  components: {
    Tip,
    Icon
  },
  props: {
    title: String,
    required: {
      type: Boolean,
      default: true
    },
    options: {
      type: Array,
      required: true
    },
    value: {
      type: Array,
      default: () => []
    },
    required: {
      type: Boolean,
      default: true
    },
    max: Number,
    min: Number,
    fillMode: Boolean,
    randomOrder: Boolean
  },
  data(){
    return {
      errors: {},
      prisine: true,
      touched: false,
      // valid: true,
      props_options:[],
      props_value:[]
    }
  },
  created(){
    this.handleChangeEvent = false
    this.uuid = Math.random().toString(36).substring(3, 8)
    this.props_options=this.options
    this.props_value=this.value
  },
  mounted () {
    this.handleChangeEvent = true
    if (this.randomOrder) {
      this.props_options = shuffle(this.props_options)
    }
  },
  computed: {
    _total () {
      return this.fillMode ? (this.props_options.length + 1) : this.props_options.length
    },
    _min () {
      if (!this.required) {
        return 0
      }
      if (this.min) {
        if (this.min < 0) {
          return 1
        }
        if (this.min >= this._total) {
          return this._total
        }
        return this.min
      } else {
        return 1
      }
    },
    _max () {
      if (!this.required) {
        return this._total
      }
      if (this.max) {
        if (this.max > this._total) {
          return this._total
        }
        return this.max
      } else {
        return this._total
      }
    },
    valid () {
      return this.props_value.length >= this._min && this.props_value.length <= this._max
    },
    error () {
      let err = []
      if (this.props_value.length < this._min) {
        err.push('最少要选择'+this._min+'个哦')
      }
      if (this.props_value.length > this._max) {
        err.push('最多只能选择'+this._max+'个哦')
      }
      return err.join('')
    },
    dirty () {
      return !this.prisine
    },
    invalid () {
      return !this.valid
    }
  },
  methods:{
    setTouched () {
      this.touched = true
    },
    getItemKey(item){
      return getKey(item)
    },
    getItemValue(item){
      return getValue(item)
    }
  },
  watch: {
    props_value(newVal){
      if (this.prisine === true) {
        this.prisine = false
      }
      if (!this.handleChangeEvent) {
        this.$emit('on-change', newVal)
      }
      this.$emit('on-change', JSON.parse(JSON.stringify(newVal)))
      this.$emit('input',newVal)
    },
    value (newVal) {
      this.props_value=newVal
    },
    options(val){
      this.props_options=val
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_cell/weui_cell_global';
@import '../../styles/weui/widget/weui_cell/weui_check';

.weui_cells_checkbox > label > * {
  pointer-events: none;
}
.weui_cells > a {
  color:#000;
}
</style>


================================================
FILE: src/components/checklist/metas.yml
================================================
props:
  value:
    zh-CN: 表单值
  title:
    zh-CN: 标题
  required:
    zh-CN: 是否为必填
  options:
    zh-CN: 选项列表,可以为`[{name:'name',value:'value'}]`的形式
  max:
    zh-CN: 最多可选个数
  min:
    zh-CN: 最少可选个数
  fill-mode:
    zh-CN: 是否允许填写值
  random-order:
    zh-CN: 是否随机打乱选项顺序
events:
  on-change:
    zh-CN: 值变化时触发,参数为 (value)


================================================
FILE: src/components/checklist/object-filter.js
================================================
export const getValue = function (item) {
  return typeof item === 'object' ? item.value : item
}

export const getKey = function (item) {
  return typeof item === 'object' ? item.key : item
}


================================================
FILE: src/components/circle/index.vue
================================================
<template>
  <div class="vux-circle">
    <svg viewBox="0 0 100 100">
      <path :d="pathString" :stroke="trailColor" :stroke-width="trailWidth" :fill-opacity="0"/>
      <path :d="pathString" stroke-linecap="round" :stroke="strokeColor" :stroke-width="strokeWidth" fill-opacity="0" :style="pathStyle"/>
    </svg>
    <div class="vux-circle-content"><slot></slot></div>
  </div>
</template>

<script>
/**
* Fork from https://github.com/react-component/progress
* MIT license
*/

export default {
  props: {
    strokeWidth: {
      type: Number,
      default: 1
    },
    strokeColor: {
      type: String,
      default: '#3FC7FA'
    },
    trailWidth: {
      type: Number,
      default: 1
    },
    trailColor: {
      type: String,
      default: '#D9D9D9'
    },
    percent: {
      type: Number,
      default: 0
    }
  },
  computed: {
    radius () {
      return 50 - this.strokeWidth / 2
    },
    pathString () {
      return `M 50,50 m 0,-${this.radius}
      a ${this.radius},${this.radius} 0 1 1 0,${2 * this.radius}
      a ${this.radius},${this.radius} 0 1 1 0,-${2 * this.radius}`
    },
    len () {
      return Math.PI * 2 * this.radius
    },
    pathStyle () {
      return {
        'stroke-dasharray': `${this.len}px ${this.len}px`,
        'stroke-dashoffset': `${((100 - this.percent) / 100 * this.len)}px`,
        'transition': 'stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease'
      }
    }
  }
}
</script>

<style>
.vux-circle {
  position: relative;
  width: 100%;
  height: 100%;
}
.vux-circle-content {
  width: 100%;
  text-align: center;
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}
</style>


================================================
FILE: src/components/circle/metas.yml
================================================
props:
  stroke-width:
    zh-CN: 线条宽度
  stoke-color:
    zh-CN: 线条颜色
  trail-width:
    zh-CN: 背景线条宽度
  trail-color:
    zh-CN: 背景线条颜色
  percent:
    zh-CN: 进度百分比


================================================
FILE: src/components/clocker/clocker.js
================================================
// https://github.com/MoeKit/clocker
var instances = []
var matchers = []
// Miliseconds
matchers.push(/^[0-9]*$/.source)
// Month/Day/Year [hours:minutes:seconds]
matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/
  .source)
// Year/Day/Month [hours:minutes:seconds] and
// Year-Day-Month [hours:minutes:seconds]
matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/
  .source)
// Cast the matchers to a regular expression object
matchers = new RegExp(matchers.join('|'))
// Parse a Date formatted has String to a native object

function parseDateString (dateString) {
  // Pass through when a native object is sent
  if (dateString instanceof Date) {
    return dateString
  }
  // Caste string to date object
  if (String(dateString).match(matchers)) {
    // If looks like a milisecond value cast to number before
    // final casting (Thanks to @msigley)
    if (String(dateString).match(/^[0-9]*$/)) {
      dateString = Number(dateString)
    }
    // Replace dashes to slashes
    if (String(dateString).match(/\-/)) {
      dateString = String(dateString).replace(/\-/g, '/')
    }
    return new Date(dateString)
  } else {
    throw new Error('Couldn\'t cast `' + dateString +
      '` to a date object.')
  }
}
// Map to convert from a directive to offset object property
var DIRECTIVE_KEY_MAP = {
  'Y': 'years',
  'm': 'months',
  'w': 'weeks',
  'D': 'days',
  'H': 'hours',
  'M': 'minutes',
  'S': 'seconds'
}
// Returns an escaped regexp from the string

function escapedRegExp (str) {
  var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')
  return new RegExp(sanitize)
}
// Time string formatter

function strftime (offsetObject) {
  return function (format) {
    var directives = format.match(/%(-|!)?[A-Z]{1}(:[^]+)?/gi)
    if (directives) {
      for (var i = 0, len = directives.length; i < len; ++i) {
        var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^]+)?/)
        var regexp = escapedRegExp(directive[0])
        var modifier = directive[1] || ''
        var plural = directive[3] || ''
        var value = null
        // Get the key
        directive = directive[2]
        // Swap shot-versions directives
        if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
          value = DIRECTIVE_KEY_MAP[directive]
          value = Number(offsetObject[value])
        }
        if (value !== null) {
          // Pluralize
          if (modifier === '!') {
            value = pluralize(plural, value)
          }
          // Add zero-padding
          if (modifier === '') {
            if (value < 10) {
              value = '0' + value.toString()
            }
          }
          // Replace the directive
          format = format.replace(regexp, value.toString())
        }
      }
    }
    format = format.replace('%_M1', offsetObject.minutes_1)
      .replace('%_M2', offsetObject.minutes_2)
      .replace('%_S1', offsetObject.seconds_1)
      .replace('%_S2', offsetObject.seconds_2)
      .replace('%_H1', offsetObject.hours_1)
      .replace('%_H2', offsetObject.hours_2)
      .replace('%_D1', offsetObject.days_1)
      .replace('%_D2', offsetObject.days_2)
    format = format.replace(/%%/, '%')
    return format
  }
}
// Pluralize

function pluralize (format, count) {
  var plural = 's'
  var singular = ''
  if (format) {
    format = format.replace(/(:||\s)/gi, '').split(/,/)
    if (format.length === 1) {
      plural = format[0]
    } else {
      singular = format[0]
      plural = format[1]
    }
  }
  if (Math.abs(count) === 1) {
    return singular
  } else {
    return plural
  }
}

function splitNumber (number) {
  number = number + ''
  number = (number.length === 1 ? ('0' + number) : number) + ''
  return number.split('')
}

// The Final Countdown
var Countdown = function (finalDate, option) {
  option = option || {}
  this.PRECISION = option.precision || 100 // 0.1 seconds, used to update the DOM
  this.interval = null
  this.offset = {}
  // Register this instance
  this.instanceNumber = instances.length
  instances.push(this)
  // Set the final date and start
  this.setFinalDate(finalDate)
}
var Eventor = require('../../libs/eventor')
Eventor.mixTo(Countdown)
var pro = Countdown.prototype

var fns = {
  start () {
    if (this.interval !== null) {
      clearInterval(this.interval)
    }
    var self = this
    this.update()
    this.interval = setInterval(function () {
      self.update()
    }, this.PRECISION)
    return this
  },
  stop () {
    clearInterval(this.interval)
    this.interval = null
    this._dispatchEvent('stoped')
    return this
  },
  toggle () {
    if (this.interval) {
      this.stop()
    } else {
      this.start()
    }
    return this
  },
  pause () {
    return this.stop()
  },
  resume () {
    return this.start()
  },
  remove () {
    this.stop()
    instances[this.instanceNumber] = null
  },
  setFinalDate (value) {
    this.finalDate = parseDateString(value) // Cast the given date
    return this
  },
  getOffset () {
    this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime() // In miliseconds
    this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1000)
    this.totalSecsLeft = this.totalSecsLeft < 0 ? 0 : this.totalSecsLeft
    // Calculate the offsets
    return {
      seconds: this.totalSecsLeft % 60,
      minutes: Math.floor(this.totalSecsLeft / 60) % 60,
      hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
      days: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
      weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
      months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30),
      years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365)
    }
  },
  update () {
    // Calculate the offsets
    this.offset = this.getOffset()
    // split offset only for days, hours, minutes, seconds and two number like 45, do not support 100

    var list = ['days', 'hours', 'minutes', 'seconds']

    for (var i = 0; i < list.length; i++) {
      var key = list[i]
      var numbers = splitNumber(this.offset[key])
      this.offset[key + '_1'] = numbers[0]
      this.offset[key + '_2'] = numbers[1]
    }
    // Dispatch an event
    if (this.totalSecsLeft === 0) {
      this.stop()
      this._dispatchEvent('finish')
    } else {
      this._dispatchEvent('update')
    }
    return this
  },
  _dispatchEvent (eventName) {
    var event = {}
    event.finalDate = this.finalDate
    event.offset = this.offset
    event.strftime = strftime(this.offset)
    this.emit(eventName, event)
    this.emit('tick', event)
  }
}

for (var i in fns) {
  pro[i] = fns[i]
}

module.exports = Countdown


================================================
FILE: src/components/clocker/index.vue
================================================
<template>
  <div style="display:inline-block;">
    <span v-if="showTimeString">{{timeString}}</span>
    <div class="vux-clocker-tpl"><slot></slot></div>
  </div>
</template>

<script>
const Clocker = require('./clocker')
export default {
  mounted () {
    this.slot = this.$el.querySelector('.vux-clocker-tpl')
    this.slotString = this.slot.innerHTML
    if (this.slotString !== '') {
      this.showTimeString = false
    }
    this.render()
  },
  methods: {
    render () {
      if (!this.time) return
      this.clocker = new Clocker(this.time)
      .on('tick', event => {
        this.update(event)
        this.$emit('on-tick', event)
      })
      .on('finish', () => {
        this.timeString = '00:00:00'
        this.$emit('on-finish')
      })
      .start()
    },
    update (event) {
      if (this.showTimeString) {
        this.timeString = event.strftime(this.format)
      } else {
        let string = event.strftime(this.slotString)
        if (string !== this.cacheSlotString) {
          this.slot.innerHTML = this.cacheSlotString = string
        }
      }
    }
  },
  props: {
    time: [String, Number],
    format: {
      type: String,
      default: '%D 天 %H 小时 %M 分 %S 秒'
    }
  },
  watch: {
    time () {
      this.clocker.remove()
      this.render()
    }
  },
  data () {
    return {
      showTimeString: true,
      timeString: '',
      slotString: '',
      cacheSlotString: ''
    }
  },
  beforeDestroy () {
    this.clocker.remove()
    this.clocker = null
  }
}
</script>


================================================
FILE: src/components/clocker/metas.yml
================================================
props:
  time:
    en: the end time
    zh-CN: 结束时间
  format:
    en: the result format
    zh-CN: 显示格式
events:
  on-tick:
    en: triggers on time ticking
    zh-CN: 时间计算时触发,但非每1s触发
  on-finish:
    en: triggers on time end
    zh-CN: 时间结束时触发
slots:
  default:
    en: if specified, will be the format for the result
    zh-CN: 若存在,则作为最终显示出来的结果模板


================================================
FILE: src/components/color-picker/index.vue
================================================
<template>
  <div class="vux-color-picker">
    <input style="display:none" v-model="props_value">
    <flexbox>
      <flexbox-item v-for="color in colors" class="vux-color-box">
        <span class="vux-color-item" :style="{borderRadius: width/2 + 'px',backgroundColor: color, width: width + 'px', height: width + 'px'}" @click="change(color)" :class="{'vux-color-white': color === '#fff' || color === '#fff', 'vux-color-picker-small': size === 'small', 'vux-color-picker-middle': size === 'middle'}">
          <icon v-if="color === props_value" class="vux-color-checked" :style="{lineHeight: width + 'px'}" type="success_no_circle"></icon>
        </span>
      </flexbox-item>
    </flexbox>
  </div>
</template>

<script>
import Icon from '../icon'
import { Flexbox, FlexboxItem } from '../flexbox'

const sizeMap = {
  'large': 40,
  'middle': 30,
  'small': 20
}
export default {
  components: {
    Icon,
    Flexbox,
    FlexboxItem
  },
  props: {
    colors: {
      type: Array,
      required: true
    },
    size: {
      type: String,
      default: 'large'
    },
    value: String
  },
  computed: {
    width () {
      return sizeMap[this.size]
    }
  },
  data(){
    return {
      props_value : ''
    }
  },
  created(){
    this.props_value=this.value
  },
  methods: {
    change (color) {
      this.props_value = color
      this.$emit('on-change', color)
    }
  },
  watch:{
    value(val){
      this.props_value=val
    },
    props_value(val){
      this.$emit('input',val);
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/icon/weui_icon_font';

.vux-color-box {
  text-align: center;
}
.vux-color-picker {
  font-size: 0;
}
.vux-color-item {
  display: inline-block;
  text-align: center;
  box-sizing: border-box;
  position: relative
}
.vux-color-checked.weui_icon_success_no_circle:before {
  color: #fff;
}
.vux-color-checked {
  width: 100%;
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}
.vux-color-white {
  border: 1px solid #ccc;
}
.vux-color-white .vux-color-checked:before {
  color: #ccc;
}
.vux-color-picker-small .vux-color-checked:before{
  font-size: 10px;
}
.vux-color-picker-middle .vux-color-checked:before{
  font-size: 18px;
}
</style>


================================================
FILE: src/components/confirm/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/confirm/index.vue
================================================
<template>
  <div>
    <x-dialog class="weui_dialog_confirm"
    :show="props_show"
    :mask-transition="maskTransition"
    :dialog-transition="dialogTransition"
    @on-hide="$emit('on-hide')"
    @on-show="$emit('on-show')">
      <div class="weui_dialog_hd"><strong class="weui_dialog_title">{{title}}</strong></div>
      <div class="weui_dialog_bd"><slot></slot></div>
      <div class="weui_dialog_ft">
        <a href="javascript:;" class="weui_btn_dialog default" @click="onCancel">{{cancelText}}</a>
        <a href="javascript:;" class="weui_btn_dialog primary" @click="onConfirm">{{confirmText}}</a>
      </div>
    </x-dialog>
  </div>
</template>

<script>
import XDialog from '../dialog'

export default {
  components: {
    XDialog
  },
  props: {
    value: {
      type: Boolean,
      default: false
    },
    show: Boolean,
    title: {
      type: String,
      required: true
    },
    confirmText: {
      type: String,
      default: 'confirm'
    },
    cancelText: {
      type: String,
      default: 'cancel'
    },
    maskTransition: {
      type: String,
      default: 'vux-fade'
    },
    dialogTransition: {
      type: String,
      default: 'vux-dialog'
    }
  },
  created(){
    this.props_show=this.show
    if(this.value) this.props_show=this.value
  },
  watch: {
    value(val){
      this.props_show=val
    },
    props_show(val){
      this.$emit('input',val)
    },
    show (val) {
      this.props_show=val
    }
  },
  data(){
    return {
      props_show:false
    }
  },
  methods: {
    onConfirm () {
      this.props_show = false
      this.$emit('on-confirm')
    },
    onCancel () {
      this.props_show = false
      this.$emit('on-cancel')
    }
  }
}
</script>

<style lang="less">
@import '../../styles/transition.less';
@import '../../styles/weui/widget/weui_tips/weui_mask';
@import '../../styles/weui/widget/weui_tips/weui_dialog';
</style>

================================================
FILE: src/components/confirm/metas.yml
================================================
tags:
  en:
    - message
    - confirm
  zh-CN:
    - 消息提示
    - 确认
props:
  show:
    en: visibility of the component
    zh-CN: 是否显示
  title:
    en: dialog title
    zh-CN: 弹窗标题
  confirm-text:
    en: confirm button text
    zh-CN: 确认按钮文字
  cancel-text:
    en: cancel button text
    zh-CN: 取消按钮文字
  mask-transition:
    en: mask's transition
    zh-CN: 遮罩动画
  dialog-transition:
    en: dialog's transition
    zh-CN: 弹窗动画
slots:
  default:
    en: body content of the dialog
    zh-CN: 弹窗主体内容
events:
  on-cancel:
    en: triggers when the cancel button is clicked
    zh-CN: 点击取消按钮时触发
  on-confirm:
    en: triggers when the confirm button is clicked
    zh-CN: 点击确定按钮时触发


================================================
FILE: src/components/countdown/index.vue
================================================
<template>
  <span>{{props_time}}<input style="display:none" v-model="props_time"></span>
</template>

<script>
export default {
  props: {
    value: Number,
    time: {
      type: Number,
      default: 60
    },
    start: {
      type: Boolean,
      default: true
    }
  },
  created(){
    this.props_time=this.time
    if(this.value) this.props_time=this.value
  },
  methods: {
    tick () {
      let _this = this
      this.interval = setInterval(function () {
        if (_this.props_time > 0) {
          _this.props_time--
        } else {
          _this.stop()
          _this.index++
          _this.$emit('on-finish', _this.index)
        }
      }, 1000)
    },
    stop () {
      clearInterval(this.interval)
    }
  },
  watch: {
    value(val){
      this.props_time=val
    },
    props_time(val){
      this.$emit('input',val)
    },
    time (val) {
      this.props_time=val
    },
    start (newVal, oldVal) {
      if (newVal === true && oldVal === false && this.props_time > 0) {
        this.tick()
      }
      if (newVal === false && oldVal === true) {
        this.stop()
      }
    }
  },
  mounted () {
    if (this.start) {
      this.tick()
    }
  },
  data () {
    return {
      interval: null,
      index: 0,
      props_time :60
    }
  }
}
</script>


================================================
FILE: src/components/countup/index.vue
================================================
<template>
  <span>{{startVal}}</span>
</template>

<script>
import Countup from 'countup'

export default {
  mounted () {
    this._countup = new Countup(this.$el, this.startVal, this.endVal, this.decimals, this.duration, this.options)
    this._countup.start()
  },
  props: {
    startVal: {
      type: Number,
      default: 0
    },
    endVal: {
      type: Number,
      required: true
    },
    // number of decimal places in number
    decimals: {
      type: Number,
      default: 0
    },
    // duration in seconds
    duration: {
      type: Number,
      default: 2
    },
    options: {
      type: Object,
      default () {
        return {}
      }
    }
  },
  watch: {
    endVal (val) {
      this._countup.update(val)
    }
  }
}
</script>


================================================
FILE: src/components/datetime/datetimepicker.js
================================================
import Scroller from '../picker/scroller'
import { each, trimZero, addZero, getMaxDay, parseRow, parseDate, getElement, toElement, removeElement } from './util'

const MASK_TEMPLATE = '<div class="dp-mask"></div>'

const TEMPLATE = `<div class="dp-container">
  <div class="dp-header">
    <div class="dp-item dp-left" data-role="cancel">cancel</div>
    <div class="dp-item dp-center" data-role="clear"></div>
    <div class="dp-item dp-right" data-role="confirm">ok</div>
  </div>
  <div class="dp-content">
    <div class="dp-item" data-role="year"></div>
    <div class="dp-item" data-role="month"></div>
    <div class="dp-item" data-role="day"></div>
    <div class="dp-item" data-role="hour"></div>
    <div class="dp-item" data-role="minute"></div>
  </div>
</div>`

var SHOW_ANIMATION_TIME = 100 // ms
var SHOW_CONTAINER_TIME = 300

var TYPE_MAP = {
  year: ['YYYY'],
  month: ['MM', 'M'],
  day: ['DD', 'D'],
  hour: ['HH', 'H'],
  minute: ['mm', 'm']
}

var MASK = null

var CURRENT_PICKER

var NOW = new Date()

var DEFAULT_CONFIG = {
  template: TEMPLATE,
  trigger: null,
  output: null,
  currentYear: NOW.getFullYear(),
  currentMonth: NOW.getMonth() + 1,
  minYear: 2000,
  maxYear: 2030,
  yearRow: '{value}',
  monthRow: '{value}',
  dayRow: '{value}',
  hourRow: '{value}',
  minuteRow: '{value}',
  format: 'YYYY-MM-DD',
  value: NOW.getFullYear() + '-' + (NOW.getMonth() + 1) + '-' + NOW.getDate(),
  onSelect () {},
  onConfirm () {},
  onClear () {},
  onShow () {},
  onHide () {},
  confirmText: 'ok',
  clearText: '',
  cancelText: 'cancel'
}

function renderScroller (el, data, value, fn) {
  var scroller = new Scroller(el, {
    data: data,
    defaultValue: value,
    onSelect: fn
  })
  return scroller
}

function showMask () {
  if (!MASK) {
    MASK = toElement(MASK_TEMPLATE)
    document.body.appendChild(MASK)

    MASK.addEventListener('click', function () {
      CURRENT_PICKER && CURRENT_PICKER.hide()
    }, false)
  }

  MASK.style.display = 'block'

  setTimeout(function () {
    MASK && (MASK.style.opacity = 0.5)
  }, 0)
}

function hideMask () {
  if (!MASK) {
    return
  }

  MASK.style.opacity = 0

  setTimeout(function () {
    MASK && (MASK.style.display = 'none')
    // hideMaskTimer = null
  }, SHOW_ANIMATION_TIME)
}

function DatetimePicker (config) {
  var self = this
  self.config = {}
  self.value = config.value || ''
  each(DEFAULT_CONFIG, function (key, val) {
    self.config[key] = config[key] || val
  })

  var trigger = self.config.trigger
  if (trigger) {
    var output = self.config.output || trigger
    trigger = self.trigger = getElement(trigger)
    output = self.output = getElement(output)

    trigger.addEventListener('click', function (e) {
      e.preventDefault()
      self.show(self.value)
    }, false)
  }
}

DatetimePicker.prototype = {

  _show (newValueMap) {
    var self = this

    self.container.style.display = 'block'

    each(TYPE_MAP, function (type) {
      self[type + 'Scroller'] && self[type + 'Scroller'].select(trimZero(newValueMap[type]), false)
    })

    setTimeout(function () {
      self.container.style['-webkit-transform'] = 'translateY(0)'
      self.container.style.transform = 'translateY(0)'
    }, 0)
  },
  show (value) {
    var self = this
    var config = self.config
    CURRENT_PICKER = self
    var valueMap = self.valueMap = parseDate(config.format, value || config.value)
    var newValueMap = {}

    each(TYPE_MAP, function (type, list) {
      newValueMap[type] = list.length === 1 ? valueMap[list[0]] : (valueMap[list[0]] || valueMap[list[1]])
    })

    if (self.container) {
      self._show(newValueMap)
    } else {
      var container = self.container = toElement(config.template)
      document.body.appendChild(container)

      self.container.style.display = 'block'

      container.addEventListener('touchstart', function (e) {
        // e.preventDefault()
      }, false)

      each(TYPE_MAP, function (type) {
        // 清除格式里没有列
        var div = self.find('[data-role=' + type + ']')
        if (newValueMap[type] === undefined) {
          removeElement(div)
          return
        }
        var data
        if (type === 'day') {
          data = self._makeData(type, trimZero(newValueMap.year), trimZero(newValueMap.month))
        } else {
          data = self._makeData(type)
        }

        self[type + 'Scroller'] = renderScroller(div, data, trimZero(newValueMap[type]), function (currentValue) {
          config.onSelect.call(self, type, currentValue)
          var currentDay
          if (!self.dayScroller) {
            return
          }
          if (type === 'year') {
            var currentMonth = self.monthScroller ? self.monthScroller.value : config.currentMonth
            currentDay = self.dayScroller.value
            self._setDayScroller(currentValue, currentMonth, currentDay)
          } else if (type === 'month') {
            var currentYear = self.yearScroller ? self.yearScroller.value : config.currentYear
            currentDay = self.dayScroller.value
            self._setDayScroller(currentYear, currentValue, currentDay)
          }
        })
      })

      if (!self.renderText) {
        if (self.config.confirmText) {
          self.find('[data-role=confirm]').innerText = self.config.confirmText
        }

        if (self.config.cancelText) {
          self.find('[data-role=cancel]').innerText = self.config.cancelText
        }
        if (self.config.clearText) {
          self.find('[data-role=clear]').innerText = self.config.clearText
        }
        self.renderText = true
      }

      this._show(newValueMap)

      self.find('[data-role=cancel]').addEventListener('click', function (e) {
        e.preventDefault()
        self.hide()
      }, false)

      self.find('[data-role=confirm]').addEventListener('click', function (e) {
        e.preventDefault()
        self.confirm()
      }, false)

      if (self.config.clearText) {
        self.find('[data-role=clear]').addEventListener('click', function (e) {
          e.preventDefault()
          self.clear()
        }, false)
      }
    }

    showMask()
    config.onShow.call(self)
  },

  _makeData (type, year, month) {
    var config = this.config
    var valueMap = this.valueMap
    var list = TYPE_MAP[type]
    var data = []
    var min
    var max
    if (type === 'year') {
      min = config.minYear
      max = config.maxYear
    } else if (type === 'month') {
      min = 1
      max = 12
    } else if (type === 'day') {
      min = 1
      max = getMaxDay(year, month)
    } else if (type === 'hour') {
      min = 0
      max = 23
    } else if (type === 'minute') {
      min = 0
      max = 59
    }
    for (var i = min; i <= max; i++) {
      var name
      if (type === 'year') {
        name = parseRow(config.yearRow, i)
      } else {
        var val = valueMap[list[0]] ? addZero(i) : i
        name = parseRow(config[type + 'Row'], val)
      }
      data.push({
        name: name,
        value: i
      })
    }
    return data
  },

  _setDayScroller (year, month, day) {
    var self = this
    var maxDay = getMaxDay(year, month)
    if (day > maxDay) {
      day = maxDay
    }
    self.dayScroller.destroy()
    var div = self.find('[data-role=day]')
    self.dayScroller = renderScroller(div, self._makeData('day', year, month), day, function (currentValue) {
      self.config.onSelect.call(self, 'day', currentValue)
    })
  },

  find (selector) {
    return this.container.querySelector(selector)
  },

  hide () {
    var self = this
    self.container.style.removeProperty('transform')
    self.container.style.removeProperty('-webkit-transform')

    setTimeout(function () {
      self.container.style.display = 'none'
    }, SHOW_CONTAINER_TIME)

    hideMask()

    self.config.onHide.call(self)
  },

  select (type, value) {
    this[type + 'Scroller'].select(value, false)
  },

  destroy () {
    var self = this
    removeElement(MASK)
    removeElement(self.container)
    MASK = null
    self.container = null
  },

  getValue () {
    var self = this
    var config = self.config

    var value = config.format

    function formatValue (scroller, expr1, expr2) {
      if (scroller) {
        var val = scroller.value
        if (expr1) {
          value = value.replace(new RegExp(expr1, 'g'), addZero(val))
        }
        if (expr2) {
          value = value.replace(new RegExp(expr2, 'g'), trimZero(val))
        }
      }
    }

    each(TYPE_MAP, function (key, list) {
      formatValue(self[key + 'Scroller'], list[0], list[1])
    })

    return value
  },

  confirm () {
    var self = this
    var value = self.getValue()
    this.value = value

    if (self.config.onConfirm.call(self, value) === false) {
      return
    }

    self.hide()
  },

  clear () {
    var self = this
    var value = self.getValue()

    if (self.config.onClear.call(self, value) === false) {
      return
    }

    self.hide()
  }
}

export default DatetimePicker


================================================
FILE: src/components/datetime/format.js
================================================
module.exports = function (date, fmt = 'YYYY-MM-DD HH:mm:ss') {
  var o = {
    'M+': date.getMonth() + 1,
    'D+': date.getDate(),
    'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
    'H+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds(),
    'q+': Math.floor((date.getMonth() + 3) / 3),
    'S': date.getMilliseconds()
  }
  var week = {
    '0': '/u65e5',
    '1': '/u4e00',
    '2': '/u4e8c',
    '3': '/u4e09',
    '4': '/u56db',
    '5': '/u4e94',
    '6': '/u516d'
  }
  if (/(Y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  if (/(E+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '/u661f/u671f' : '/u5468') : '') + week[date.getDay() + ''])
  }
  for (var k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
    }
  }
  return fmt
}


================================================
FILE: src/components/datetime/index.vue
================================================
<template>
  <a class="weui_cell" href="javascript:">
    <input style="display:none" v-model="props_value">
    <div class="weui_cell_bd weui_cell_primary">
      <p>{{title}}</p>
      <inline-desc v-if="inlineDesc">{{inlineDesc}}</inline-desc>
    </div>
    <div class="weui_cell_ft with_arrow vux-datetime-value">{{ props_value || placeholder}}</div>
  </a>
</template>

<script>
import Picker from './datetimepicker'
import Group from '../group'
import InlineDesc from '../inline-desc'
import Base from '../../libs/base'

export default {
  mixins: [Base],
  components: {
    Group,
    InlineDesc
  },
  props: {
    format: {
      type: String,
      default: 'YYYY-MM-DD'
    },
    title: {
      type: String,
      required: true
    },
    value: {
      type: String,
      default: ''
    },
    inlineDesc: String,
    placeholder: String,
    minYear: Number,
    maxYear: Number,
    confirmText: {
      type: String,
      default: 'ok'
    },
    cancelText: {
      type: String,
      default: 'cancel'
    },
    clearText: {
      type: String,
      default: ''
    },
    yearRow: {
      type: String,
      default: '{value}'
    },
    monthRow: {
      type: String,
      default: '{value}'
    },
    dayRow: {
      type: String,
      default: '{value}'
    },
    hourRow: {
      type: String,
      default: '{value}'
    },
    minuteRow: {
      type: String,
      default: '{value}'
    }
  },
  created () {
    this.props_value=this.value
    this.handleChangeEvent = true
  },
  data(){
    return{
      props_value:''
    }
  },
  mounted () {
    const uuid = this.uuid
    this.$el.setAttribute('id', 'vux-datetime-' + uuid)
    this.render()
  },
  computed: {
    pickerOptions () {
      const _this = this
      const options = {
        trigger: '#vux-datetime-' + this.uuid,
        format: this.format,
        value: this.props_value,
        output: '.vux-datetime-value',
        confirmText: this.confirmText,
        cancelText: _this.cancelText,
        clearText: _this.clearText,
        yearRow: this.yearRow,
        monthRow: this.monthRow,
        dayRow: this.dayRow,
        hourRow: this.hourRow,
        minuteRow: this.minuteRow,
        onConfirm (value) {
          _this.props_value = value
        },
        onClear (value) {
          _this.$emit('on-clear', value)
        }
      }
      if (this.minYear) {
        options.minYear = this.minYear
      }
      if (this.maxYear) {
        options.maxYear = this.maxYear
      }
      return options
    }
  },
  methods: {
    render () {
      if (this.picker) {
        this.picker.destroy()
      }
      this.picker = new Picker(this.pickerOptions)
    }
  },
  watch: {
    props_value(val){
      this.$emit('on-change', val)
      this.$emit('input',val)
    },
    value (val) {
      this.props_value=val
    }
  },
  beforeDestroy () {
    this.picker.destroy()
  }
}
</script>

<style>
.weui_cell_ft.with_arrow:after {
  content: " ";
  display: inline-block;
  transform: rotate(45deg);
  height: 6px;
  width: 6px;
  border-width: 2px 2px 0 0;
  border-color: #C8C8CD;
  border-style: solid;
  position: relative;
  top: -1px;
  margin-left: .3em;
}
.scroller-component {
  display: block;
  position: relative;
  height: 238px;
  overflow: hidden;
  width: 100%;
}

.scroller-content {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: -1;
}

.scroller-mask {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  margin: 0 auto;
  width: 100%;
  z-index: 3;
  background-image:
    linear-gradient(to bottom, rgba(255,255,255,0.95), rgba(255,255,255,0.6)),
    linear-gradient(to top, rgba(255,255,255,0.95), rgba(255,255,255,0.6));
  background-position: top, bottom;
  background-size: 100% 102px;
  background-repeat: no-repeat;
}

.scroller-item {
  text-align: center;
  font-size: 16px;
  height: 34px;
  line-height: 34px;
  color: #000;
}

.scroller-indicator {
  width: 100%;
  height: 34px;
  position: absolute;
  left: 0;
  top: 102px;
  z-index: 3;
  background-image:
    linear-gradient(to bottom, #d0d0d0, #d0d0d0, transparent, transparent),
    linear-gradient(to top, #d0d0d0, #d0d0d0, transparent, transparent);
  background-position: top, bottom;
  background-size: 100% 1px;
  background-repeat: no-repeat;
}

.dp-container {
  position: fixed;
  width: 100%;
  left: 0;
  bottom: 0;
  z-index: 10000;
  background-color: #fff;
  display: none;
  transition: transform 0.3s ease;
  transform: translateY(100%);
}

.dp-mask {
  z-index: 998;
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0px;
  top: 0px;
  opacity: 0;
  transition: opacity 0.1s ease;
  background-color: #000;
  z-index: 9999;
}

.dp-header {
  display: flex;
  width: 100%;
  box-align: center;
  align-items: center;
  background-image: linear-gradient(to bottom, #e7e7e7, #e7e7e7, transparent, transparent);
  background-position: bottom;
  background-size: 100% 1px;
  background-repeat: no-repeat;
}

.dp-header .dp-item {
  color: #04BE02;
  font-size: 18px;
  height: 44px;
  line-height: 44px;
  cursor: pointer;
}

.dp-content {
  display: flex;
  width: 100%;
  box-align: center;
  align-items: center;
  padding: 10px 0;
}

.dp-header .dp-item,
.dp-content .dp-item {
  box-sizing: border-box;
  flex: 1;
  text-align: center;
}
</style>


================================================
FILE: src/components/datetime/util.js
================================================
import formater from './format'

export function each (obj, fn) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (fn.call(obj[key], key, obj[key]) === false) {
        break
      }
    }
  }
}

export function trimZero (val) {
  val = String(val)
  val = val ? parseFloat(val.replace(/^0+/g, '')) : ''
  val = val || 0
  val = val + ''
  return val
}

export function addZero (val) {
  val = String(val)
  return val.length < 2 ? '0' + val : val
}

export function isLeapYear (year) {
  return year % 100 !== 0 && year % 4 === 0 || year % 400 === 0
}

export function getMaxDay (year, month) {
  year = parseFloat(year)
  month = parseFloat(month)
  if (month === 2) {
    return isLeapYear(year) ? 29 : 28
  }
  return [4, 6, 9, 11].indexOf(month) >= 0 ? 30 : 31
}

export function parseRow (tmpl, value) {
  return tmpl.replace(/\{value\}/g, value)
}

// parse Date String
export function parseDate (format, value) {
  var formatParts = format.split(/[^A-Za-z]+/)
  var valueParts = value.split(/\D+/)
  if (formatParts.length !== valueParts.length) {
    // if it is error date, use current date
    var date = formater(new Date(), format)
    valueParts = date.split(/\D+/)
  }

  var result = {}

  for (var i = 0; i < formatParts.length; i++) {
    if (formatParts[i]) {
      result[formatParts[i]] = valueParts[i]
    }
  }
  return result
}

export function getElement (expr) {
  return (typeof expr === 'string') ? document.querySelector(expr) : expr
}

export function toElement (html) {
  var tempContainer = document.createElement('div')
  tempContainer.innerHTML = html
  return tempContainer.firstElementChild
}

export function removeElement (el) {
  el && el.parentNode.removeChild(el)
}


================================================
FILE: src/components/dev-tip/index.vue
================================================
<template>
  <div class="vux-dev-tip">
    <slot></slot>
  </div>
</template>

<style>
.vux-dev-tip {
  padding:5px 10px;
  background-color: #FFCC00;
  color:#000;
  margin-bottom:0.3em;
  font-size:12px;
}
</style>


================================================
FILE: src/components/dialog/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/dialog/index.vue
================================================
<template>
  <div class="weui_dialog_alert fix_ios_fixed" @touchmove="onTouchMove" v-show="props_show">
    <transition name="vux-mask">
      <div class="weui_mask" @click="hideOnBlur && (props_show = false)" v-show="props_show"></div>
    </transition>
    <input style="display:none" v-model="props_show">
    <transition name="vux-dialog">
      <div class="weui_dialog" v-show="props_show" >
        <slot></slot>
      </div>
    </transition>
  </div>
</template>

<script>
export default {
  props: {
    show: {
      type: Boolean,
      default: false
    },
    value: {
      type: Boolean,
      default: false
    },
    maskTransition: {
      type: String,
      default: 'vux-fade'
    },
    dialogTransition: {
      type: String,
      default: 'vux-dialog'
    },
    hideOnBlur: Boolean,
    scroll: {
      type: Boolean,
      default: true
    }
  },
  created(){
    this.props_show=this.show
    if(this.value) this.props_show=this.value

  },
  watch: {
    value(val){
      this.props_show=val
    },
    props_show(val){
      this.$emit(val ? 'on-show' : 'on-hide')
      this.$emit('input',val)
    },
    show (val) {
      this.props_show=val
    }
  },
  data(){
    return {
      props_show:false
    }
  },
  methods:{
    onTouchMove:function(event){
      !this.scroll && event.preventDefault()
    }
  }
}
</script>

<style lang="less">
@import '../../styles/transition.less';
@import '../../styles/weui/widget/weui_tips/weui_mask';
@import '../../styles/weui/widget/weui_tips/weui_dialog';
</style>


================================================
FILE: src/components/divider/index.vue
================================================
<template>
  <p class="vux-divider">
    <slot></slot>
  </p>
</template>

<style>
.vux-divider {
  display: table;
  white-space: nowrap;
  height: auto;
  overflow: hidden;
  line-height: 1;
  text-align: center;
  padding: 10px 0;
  color: #666;
}

.vux-divider:after,.vux-divider:before {
  content: '';
  display: table-cell;
  position: relative;
  top: 50%;
  width: 50%;
  background-repeat: no-repeat;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC)
}

.vux-divider:before {
  background-position: right 1em top 50%
}

.vux-divider:after {
  background-position: left 1em top 50%
}
</style>


================================================
FILE: src/components/divider/metas.yml
================================================
tips:
  -
    en: cannot custom line color for the moment
    zh-CN: 暂时不可定义分割线颜色
slots:
  default:
    en: divider title
    zh-CN: 分隔线标题
references:
  - http://www.daqianduan.com/4258.html


================================================
FILE: src/components/flexbox/flexbox-item.vue
================================================
<template>
  <div class="vux-flexbox-item" :style="style">
    <slot></slot>
  </div>
</template>

<script>
const prefixList = ['-moz-box-', '-webkit-box-', '']

export default {
  props: {
    span: [Number, String],
    order: [Number, String]
  },
  methods: {
    buildWidth (width) {
      if (typeof width === 'number') {
        if (width < 1) {
          return width
        } else {
          return width / 12
        }
      } else if (typeof width === 'string') {
        return width.replace('px', '') / this.bodyWidth
      }
    }
  },
  computed: {
    style () {
      let styles = {}
      let marginName = this.$parent.orient === 'horizontal' ? 'marginLeft' : 'marginTop'
      styles[marginName] = `${this.$parent.gutter}px`

      if (this.span) {
        for (let i = 0; i < prefixList.length; i++) {
          styles[prefixList[i] + 'flex'] = `0 0 ${this.buildWidth(this.span) * 100}%`
        }
      }
      if (typeof this.order !== 'undefined') {
        styles.order = this.order
      }
      return styles
    }
  },
  data () {
    return {
      bodyWidth: document.documentElement.offsetWidth
    }
  }
}
</script>


================================================
FILE: src/components/flexbox/flexbox.vue
================================================
<template>
  <div class="vux-flexbox" :class="{'vux-flex-col': orient === 'vertical', 'vux-flex-row': orient === 'horizontal'}" :style="styles">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    gutter: {
      type: Number,
      default: 8
    },
    orient: {
      type: String,
      default: 'horizontal'
    },
    justify: String,
    align: String,
    wrap: String,
    direction: String
  },
  computed: {
    styles () {
      return {
        'justify-content': this.justify,
        'align-items': this.align,
        'flex-wrap': this.wrap,
        'flex-direction': this.direction
      }
    }
  }
}
</script>

<style lang="less">
.vux-flexbox{
  width: 100%;
  text-align: left;
  display: flex;
  box-align: center;
  align-items: center;
}
.vux-flexbox .vux-flexbox-item {
  flex: 1;
  min-width: 20px;
  width: 0%;
}
.vux-flexbox-item > .vux-flexbox {
  width: 100%;
}

.vux-flexbox .vux-flexbox-item:first-child{
  margin-left: 0!important;
  margin-top: 0!important;
}
.vux-flex-col {
  box-orient: vertical;
  flex-direction: column;
}
.vux-flex-col > .vux-flexbox-item {
  width: 100%;
}
.vux-flex-row {
  box-direction: row;
  box-orient: horizontal;
  flex-direction: row;
}
</style>


================================================
FILE: src/components/flexbox/index.js
================================================
import Flexbox from './flexbox'
import FlexboxItem from './flexbox-item'

export {
  Flexbox,
  FlexboxItem
}


================================================
FILE: src/components/fullpage/DemoBasic.vue
================================================
<template>
  <div>
    <fullpage
    class="fullpage-demo"
    drag
    :start="0"
    :duration="100"
    @on-change="onChange"
    @on-before-change="onBeforeChange"
    @on-after-change="onAfterChange">
      <div><div>1</div></div>
      <div><div>2</div></div>
      <div><div>3</div></div>
      <div><div>4</div></div>
    </fullpage>
  </div>
</template>

<script>
import Fullpage from './'

export default {
  components: {
    Fullpage
  },
  methods: {
    onChange (data) {
      console.log('chage', data)
    },
    onBeforeChange (data) {
      console.log('before change', data)
    },
    onAfterChange (data) {
      console.log('after change', data)
    }
  }
}
</script>

<style scoped>
.fullpage-demo {
  background-color:yellow;
  font-size: 72px;
  line-height: 320px;
  text-align: center;
}
</style>

================================================
FILE: src/components/fullpage/index.vue
================================================
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
import Fullpage from './lib'

export default {
  ready () {
    const self = this
    this._fullpage = new Fullpage(this.$el, {
      dir: self.dir,
      loop: self.loop,
      drag: self.drag,
      start: self.start,
      duration: self.duration,
      page: self.page,
      der: self.der,
      change: function (data) {
        self.$emit('on-change', data)
      },
      beforeChange: function (data) {
        self.$emit('on-before-change', data)
      },
      afterChange: function (data) {
        self.$emit('on-after-change', data)
      },
      orientationchange: function (orientation) {
        self.$emit('on-orientation-change', orientation)
      }
    })
  },
  props: {
    page: String,
    start: {
      type: Number,
      default: 0
    },
    duration: {
      type: Number,
      default: 500
    },
    loop: Boolean,
    drag: Boolean,
    dir: {
      type: String,
      default: 'v'
    },
    der: {
      type: Number,
      default: 0.1
    }
  }
}
</script>

<style lang="less">
.vux-fullpage-box {
  transform: translate3d(0, 0, 0);
}

.vux-fullpage-box:after {
  display: block;
  content: ' ';
  height: 0;
  clear: both;
}

.vux-fullpage-box.vux-fullpage-box-anim {
  transition: all 500ms ease-out 0s;
}

.vux-fullpage-item {
  display: block;
  overflow: hidden;
}

.vux-fullpage-dir-h {
  float: left;
}
</style>


================================================
FILE: src/components/fullpage/lib.js
================================================
/*!
 * zepto.fullpage.js v0.5.0 (https://github.com/yanhaijing/zepto.fullpage)
 * API https://github.com/yanhaijing/zepto.fullpage/blob/master/doc/api.md
 * Copyright 2014 yanhaijing. All Rights Reserved
 * Licensed under MIT (https://github.com/yanhaijing/zepto.fullpage/blob/master/LICENSE)
 */

const BOX_CLASS = 'vux-fullpage-box'
const ANIM_CLASS = 'vux-fullpage-box-anim'
const ITEM_CLASS = 'vux-fullpage-item'
const DIR_CLASS = 'vux-fullpage-dir'

var d = {
  page: null,
  start: 0,
  duration: 500,
  loop: false,
  drag: false,
  dir: 'v',
  der: 0.1,
  change: function (data) {},
  beforeChange: function (data) {},
  afterChange: function (data) {},
  orientationchange: function (orientation) {}
}

function touchmove (e) {
  e.preventDefault()
}

function fix (cur, pagesLength, loop) {
  if (cur < 0) {
    return loop ? pagesLength - 1 : 0
  }

  if (cur >= pagesLength) {
    return loop ? 0 : pagesLength - 1
  }

  return cur
}

function move (ele, dir, dist) {
  var xPx = '0px'
  var yPx = '0px'
  if (dir === 'v') yPx = dist + 'px'
  else xPx = dist + 'px'
  ele.style.cssText += ('-webkit-transform : translate3d(' + xPx + ', ' + yPx + ', 0px);' +
    'transform : translate3d(' + xPx + ', ' + yPx + ', 0px)')
}

function init (option) {
  var o = option || {}
  for (var key in d) {
    if (!o.hasOwnProperty(key)) {
      o[key] = d[key]
    }
  }

  var that = this
  that.curIndex = -1
  that.o = o

  that.startY = 0
  that.movingFlag = false

  that.ele.classList.add(BOX_CLASS)
  that.parentEle = that.ele.parentNode

  var query = o.page
  if (query && query.indexOf('.') === 0) {
    query = query.substring(1, query.length)
    that.pageEles = that.ele.getElementsByClassName(query)
  }

  if (!query) {
    that.pageEles = that.ele.children
  }

  for (var i = 0; i < that.pageEles.length; i++) {
    var pageEle = that.pageEles[i]
    pageEle.classList.add(ITEM_CLASS)
    pageEle.classList.add(DIR_CLASS + o.dir)
  }

  that.pagesLength = that.pageEles.length
  that.update()
  that.initEvent()
  that.start()
}

function Fullpage (ele, option) {
  this.ele = ele
  init.call(this, option)
}

Fullpage.prototype.update = function () {
  let pageEle
  if (this.o.dir === 'h') {
    this.width = this.parentEle.offsetWidth
    for (let i = 0; i < this.pageEles.length; i++) {
      pageEle = this.pageEles[i]
      pageEle.style.width = this.width + 'px'
    }
    this.ele.style.width = (this.width * this.pagesLength) + 'px'
  }

  this.height = this.parentEle.offsetHeight
  for (let i = 0; i < this.pageEles.length; i++) {
    pageEle = this.pageEles[i]
    pageEle.style.height = this.height + 'px'
  }

  this.moveTo(this.curIndex < 0 ? this.o.start : this.curIndex)
}

Fullpage.prototype.initEvent = function () {
  var that = this
  var ele = that.ele

  ele.addEventListener('touchstart', function (e) {
    if (!that.status) {
      return 1
    }
    // e.preventDefault()
    if (that.movingFlag) {
      return 0
    }

    that.startX = e.targetTouches[0].pageX
    that.startY = e.targetTouches[0].pageY
  })
  ele.addEventListener('touchend', function (e) {
    if (!that.status) {
      return 1
    }
    // e.preventDefault()
    if (that.movingFlag) {
      return 0
    }

    var sub = that.o.dir === 'v' ? (e.changedTouches[0].pageY - that.startY) / that.height : (e.changedTouches[0].pageX - that.startX) / that.width
    var der = (sub > that.o.der || sub < -that.o.der) ? sub > 0 ? -1 : 1 : 0

    that.moveTo(that.curIndex + der, true)
  })
  if (that.o.drag) {
    ele.addEventListener('touchmove', function (e) {
      if (!that.status) {
        return 1
      }
      // e.preventDefault()
      if (that.movingFlag) {
        that.startX = e.targetTouches[0].pageX
        that.startY = e.targetTouches[0].pageY
        return 0
      }

      var y = e.changedTouches[0].pageY - that.startY
      if ((that.curIndex === 0 && y > 0) || (that.curIndex === that.pagesLength - 1 && y < 0)) y /= 2
      var x = e.changedTouches[0].pageX - that.startX
      if ((that.curIndex === 0 && x > 0) || (that.curIndex === that.pagesLength - 1 && x < 0)) x /= 2
      var dist = (that.o.dir === 'v' ? (-that.curIndex * that.height + y) : (-that.curIndex * that.width + x))
      ele.classList.remove(ANIM_CLASS)
      move(ele, that.o.dir, dist)
    })
  }

  window.addEventListener('orientationchange', function () {
    if (window.orientation === 180 || window.orientation === 0) {
      that.o.orientationchange('portrait')
    }
    if (window.orientation === 90 || window.orientation === -90) {
      that.o.orientationchange('landscape')
    }
  }, false)

  window.addEventListener('resize', function () {
    that.update()
  }, false)
}

Fullpage.prototype.holdTouch = function () {
  document.addEventListener('touchmove', touchmove)
}

Fullpage.prototype.unholdTouch = function () {
  document.removeEventListener('touchmove', touchmove)
}

Fullpage.prototype.start = function () {
  this.status = 1
  this.holdTouch()
}

Fullpage.prototype.stop = function () {
  this.status = 0
  this.unholdTouch()
}

Fullpage.prototype.getCurIndex = function () {
  return this.curIndex
}

Fullpage.prototype.moveTo = function (next, anim) {
  var that = this
  var ele = that.ele
  var cur = that.curIndex
  next = fix(next, that.pagesLength, that.o.loop)

  if (anim) {
    ele.classList.add(ANIM_CLASS)
  } else {
    ele.classList.remove(ANIM_CLASS)
  }

  if (next !== cur) {
    var flag = that.o.beforeChange({
      next: next,
      cur: cur
    })

    // beforeChange return false to stop scrolling
    if (flag === false) {
      return 1
    }
  }

  that.movingFlag = true
  that.curIndex = next
  move(ele, that.o.dir, -next * (that.o.dir === 'v' ? that.height : that.width))

  if (next !== cur) {
    that.o.change({
      prev: cur,
      cur: next
    })
  }

  window.setTimeout(function () {
    that.movingFlag = false
    if (next !== cur) {
      that.o.afterChange({
        prev: cur,
        cur: next
      })
      for (var i = 0; i < that.pageEles.length; i++) {
        var pageEle = that.pageEles[i]
        if (i === next) {
          pageEle.classList.add('cur')
        } else {
          pageEle.classList.remove('cur')
        }
      }
    }
  }, that.o.duration)
}

Fullpage.prototype.movePrev = function (anim) {
  this.moveTo(this.curIndex - 1, anim)
}

Fullpage.prototype.moveNext = function (anim) {
  this.moveTo(this.curIndex + 1, anim)
}

export default Fullpage



================================================
FILE: src/components/group/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/group/index.md
================================================
[zh-CN]
`Group`是一个特殊的表单`wrapper`组件,主要用于将表单分组,单个表单元素也算一组。所以常见的`行内`组件都`必须`作为`Group`的子组件。

包括:

+ Cell
+ XInput
+ XTextarea
+ Switch
+ Calendar
+ XNumber
+ Radio
+ Address
+ Datetime
+ Selector


================================================
FILE: src/components/group/index.vue
================================================
<template>
  <div>
    <div class="weui_cells_title" v-if="title" :style="{color:titleColor}" v-html="title"></div>
    <div class="weui_cells" :class="{'vux-no-group-title':!title}" :style="{marginTop: gutter}">
      <slot name="after-title"></slot>
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    title: String,
    titleColor: String,
    labelWidth: String,
    labelAlign: String,
    labelMarginRight: String,
    gutter: String
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_cell/weui_access';
@import '../../styles/weui/widget/weui_cell/weui_cell_global';

.vux-no-group-title {
  margin-top:15px;
}
.weui_cells > a {
  color:#000;
}
</style>


================================================
FILE: src/components/group/metas.yml
================================================
props:
  title:
    en: group title
    zh-CN:分组标题
  titleColor:
    en: group title's color
    zh-CN: 分组标题文字颜色
  labelWidth:
    en: common label width for child components
    zh-CN: 为子元素设定统一label宽度
  labelAlign:
    en: common label text-align for child components
    zh-CN: 为子元素设定统一对齐方式
  labelMarginRight:
    en: common margin right value for child components
    zh-CN: 为子元素设定统一的右边margin
  gutter:
    en: set the marginTop value when there is no title
    zh-CN: 设定group的上边距,只能用于没有标题时
slot:
  default:
    en: content body for child components
    zh-CN: 子组件插槽


================================================
FILE: src/components/group-title/index.vue
================================================
<template>
  <div class="weui_cells_title">
    <slot></slot>
  </div>
</template>


================================================
FILE: src/components/icon/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/icon/index.md
================================================
```
<template>
  <div>
    <icon type="success"></icon>
    <icon type="info"></icon>
    <icon type="info_circle"></icon>
    <icon type="warn"></icon>
    <icon type="waiting"></icon>
    <icon type="waiting_circle"></icon>
    <icon type="safe_success"></icon>
    <icon type="safe_warn"></icon>
    <icon type="success_circle"></icon>
    <icon type="success_no_circle"></icon>
    <icon type="circle"></icon>
    <icon type="download"></icon>
    <icon type="cancel"></icon>
    <icon type="search"></icon>
    <icon type="clear"></icon>
    <br/>
    <icon type="success" class="icon_big"></icon>
    <icon type="info" class="icon_big"></icon>
    <icon type="safe_success" class="icon_big"></icon>
    <icon type="safe_warn" class="icon_big"></icon>
  </div>
</template>
```


================================================
FILE: src/components/icon/index.vue
================================================
<template>
  <i :class="className"></i>
</template>

<script>
export default {
  props: {
    type: String
  },
  computed: {
    className () {
      return `weui_icon weui_icon_${this.type}`
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/icon/weui_icon_font';

.icon_big:before {
  font-size: 104px;
}

.icon_small:before {
  font-size: 12px;
}
</style>


================================================
FILE: src/components/icon/metas.yml
================================================
props:
  type:
    en: icon name
    zh-CN: 图标名字,可选值见demo


================================================
FILE: src/components/index.js
================================================
/* only for building vux.css */
import Style from '../styles/index.vue' // eslint-disable-line

import Radio from './radio'
import DevTip from './dev-tip'
import XInput from './x-input'
import XNumber from './x-number'
import Cell from './cell'
import InlineDesc from './inline-desc'
import Checklist from './checklist'
import XSwitch from './x-switch'
import XTextarea from './x-textarea'
import Group from './group'
import GroupTitle from './group-title'
import Box from './box'
import Tip from './tip'
import Selector from './selector'
import XButton from './x-button'
import Swiper from './swiper'
import SwiperItem from './swiper-item'
import Sticky from './sticky'
import Picker from './picker'
import Datetime from './datetime'
import Popup from './popup'
import Range from './range'
import Actionsheet from './actionsheet'
import Clocker from './clocker'
import Rater from './rater'
import PopupPicker from './popup-picker'
import XAddress from './x-address'
import Toast from './toast'
import Loading from './loading'
import Alert from './alert'
import Confirm from './confirm'
import XProgress from './progress'
import XImg from './x-img'
import Spinner from './spinner'
import Calendar from './calendar'
import Icon from './icon'
import XCircle from './circle'
import ColorPicker from './color-picker'
import AddressChinaData from './x-address/list.json'
import Divider from './divider'
import Blur from './blur'
import Countup from './countup'
import Scroller from './scroller'
import Shake from './shake'
import WechatEmotion from './wechat-emotion'
import Search from './search'
import DateFormatter from './datetime/format'
import Masker from './masker'
import Countdown from './countdown'
import FriendlyTime from '../filters/friendly-time'
import XHeader from './x-header'
import Panel from './panel'
import InlineCalendar from './inline-calendar'
import Badge from './badge'
import XDialog from './dialog'
import Card from './card'
import Previewer from './previewer'
import NumberRoller from './number-roller'
import ViewBox from './view-box'
import Popover from './popover'

import { ButtonTab, ButtonTabItem } from './button-tab'
import { Checker, CheckerItem } from './checker'
import { Flexbox, FlexboxItem } from './flexbox'
import { Step, StepItem } from './step'
import { Timeline, TimelineItem } from './timeline'
import { Tabbar, TabbarItem } from './tabbar'
import { Tab, TabItem } from './tab'

const vux = {
  Radio,
  Group,
  DevTip,
  XInput,
  GroupTitle,
  XNumber,
  Checklist,
  XSwitch,
  Box,
  Tip,
  Selector,
  Cell,
  InlineDesc,
  XButton,
  XTextarea,
  Flexbox,
  FlexboxItem,
  Tab,
  TabItem,
  Swiper,
  SwiperItem,
  Sticky,
  Picker,
  Datetime,
  Popup,
  Range,
  Actionsheet,
  Clocker,
  Rater,
  PopupPicker,
  XAddress,
  Toast,
  Loading,
  Alert,
  Confirm,
  XProgress,
  XImg,
  Spinner,
  Calendar,
  Icon,
  XCircle,
  ColorPicker,
  AddressChinaData,
  Divider,
  Blur,
  Countup,
  Scroller,
  Shake,
  WechatEmotion,
  Search,
  DateFormatter,
  Masker,
  Countdown,
  FriendlyTime,
  XHeader,
  Checker,
  CheckerItem,
  Timeline,
  TimelineItem,
  Step,
  StepItem,
  Tabbar,
  TabbarItem,
  Panel,
  ButtonTab,
  ButtonTabItem,
  InlineCalendar,
  Badge,
  XDialog,
  Card,
  Previewer,
  NumberRoller,
  ViewBox,
  Popover
}

// if (DEV) { // eslint-disable-line
//   const { getMetas } = require('../../build/build-metas')
//   const metas = getMetas(vux)
//   if (window.fetch) {
//     window.fetch(`http://${window.location.hostname}:8899/api/doc`, {
//       method: 'POST',
//       body: JSON.stringify(metas),
//       headers: {
//         'Accept': 'application/json',
//         'Content-Type': 'application/json'
//       }
//     })
//   }
// }

module.exports = vux


================================================
FILE: src/components/inline-calendar/index.vue
================================================
<template>
  <div class="inline-calendar" :class="{'is-weekend-highlight': highlightWeekend}">
    <div class="calendar-header" v-show="!hideHeader">
      <div class="calendar-year">
        <a class="year-prev vux-prev-icon" href="javascript:" @click="go(year - 1, month)"></a>
        <a class="calendar-year-txt calendar-title" href="javascript:">{{year}}</a>
        <a class="year-next vux-next-icon" href="javascript:" @click="go(year + 1, month)"></a>
      </div>

      <div class="calendar-month">
        <a @click="prev" class="month-prev vux-prev-icon" href="javascript:"></a>
        <a class="calendar-month-txt calendar-title" href="javascript:">{{months[month]}}</a>
        <a @click="next" class="month-next vux-next-icon" href="javascript:"></a>
      </div>
    </div>

    <table>
      <thead v-show="!hideWeekList">
        <tr>
          <th v-for="(week, index) in weeksList" class="week" :class=" 'is-week-list-' + index ">{{week}}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(day,k1) in days">
          <td
          :data-date="formatDate(year, month, child)"
          :data-current="props_value"
          v-for="(child,k2) in day"
          :class="buildClass(k2, child, formatDate(year, month, child) === props_value && !child.isLastMonth && !child.isNextMonth)"
          @click="select(k1,k2,$event)">
            <span
            v-show="(!child.isLastMonth && !child.isNextMonth ) || (child.isLastMonth && showLastMonth) || (child.isNextMonth && showNextMonth)">{{replaceText(child.day, formatDate(year, month, child))}}</span>
            <div v-html="customSlotFn(k1, k2, child)"></div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import format from '../datetime/format'
import { getDays, zero } from './util'
import props from './props'

export default {
  props: props(),
  data () {
    return {
      year: 0,
      month: 0,
      days: [],
      current: [],
      today: format(new Date(), 'YYYY-MM-DD'),
      months: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
      props_value:''
    }
  },
  created(){
    this.props_value=this.value
  },
  mounted () {
    this.props_value = this.convertDate(this.props_value)
    this.render(this.renderMonth[0], this.renderMonth[1] - 1)
  },
  computed: {
    _replaceTextList () {
      const rs = {}
      for (let i in this.replaceTextList) {
        rs[this.convertDate(i)] = this.replaceTextList[i]
      }
      return rs
    }
  },
  watch: {
    value(val){
      this.props_value=val
    },
    props_value (val) {
      this.props_value = this.convertDate(val)
      if (this.renderOnValueChange) {
        this.render(null, null, val)
      } else {
        this.render(this.year, this.month, this.props_value)
      }
      this.$emit('on-change', val)
    },
    returnSixRows (val) {
      this.render(this.year, this.month, this.props_value)
    },
    disablePast () {
      this.render(this.year, this.month, this.props_value)
    },
    disableFuture () {
      this.render(this.year, this.month, this.props_value)
    }
  },
  methods: {
    replaceText (day, formatDay) {
      return this._replaceTextList[formatDay] || day
    },
    convertDate (date) {
      return date === 'TODAY' ? this.today : date
    },
    buildClass (index, child, isCurrent) {
      const className = {
        current: child.current || isCurrent,
        'is-disabled': child.disabled,
        'is-today': child.isToday
      }
      className[`is-week-${index}`] = true
      return className
    },
    render (year, month) {
      let data = getDays({
        year: year,
        month: month,
        value: this.props_value,
        rangeBegin: this.convertDate(this.startDate),
        rangeEnd: this.convertDate(this.endDate),
        returnSixRows: this.returnSixRows,
        disablePast: this.disablePast,
        disableFuture: this.disableFuture
      })
      this.days = data.days
      this.year = data.year
      this.month = data.month
    },
    formatDate: (year, month, child) => {
      return [year, zero(child.month + 1), zero(child.day)].join('-')
    },
    prev () {
      if (this.month === 0) {
        this.month = 11
        this.year = this.year - 1
      } else {
        this.month = this.month - 1
      }
      this.render(this.year, this.month)
    },
    next () {
      if (this.month === 11) {
        this.month = 0
        this.year = this.year + 1
      } else {
        this.month = this.month + 1
      }
      this.render(this.year, this.month)
    },
    go (year, month) {
      this.render(year, month)
    },
    select (k1, k2) {
      if (this.current.length > 0) {
        this.days[this.current[0]][this.current[1]].isCurrent = false
      }
      this.days[k1][k2].current = true
      this.current = [k1, k2]
      this.props_value = [this.year, zero(this.month + 1), zero(this.days[k1][k2].day)].join('-')
    }
  }
}
</script>
 
<style>
.vux-prev-icon, .vux-next-icon {
  position: absolute;
  left: 0;
  top: 15px;
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 1px solid #04be02;
  border-radius: 0;
  border-top: none;
  border-right: none;
  transform: rotate(45deg);
  margin-left: 15px;
  line-height: 40px;
}
.vux-next-icon {
  transform: rotate(-135deg);
  left: auto;
  top: 14px;
  right: 15px;
}
.vux-prev-icon:before {
  display: block;
  width: 12px;
  height: 12px;
  border: 1px solid #04be02;
  border-width: 1px 0 0 1px;
  transform: rotate(315deg)
}
.is-weekend-highlight td.is-week-list-0,
.is-weekend-highlight td.is-week-list-6,
.is-weekend-highlight td.is-week-0,
.is-weekend-highlight td.is-week-6 {
  color: #E59313;
}
.inline-calendar a {
  text-decoration: none;
  tap-highlight-color: rgba(0, 0, 0, 0);
}
.calendar-year, .calendar-month {
  position: relative;
}
.calendar-header {
  line-height: 40px;
  font-size: 1.2em;
  overflow: hidden;
}
.calendar-header > div {
  float: left;
  width: 50%;
  text-align: center;
  overflow: hidden;
}
.calendar-header a:last-of-type {
  float: right;
  vertical-align: bottom;
}
.switch-btn, .calendar-title {
  display: inline-block;
  border-radius: 4px;
  line-height: 30px;
}
.switch-btn {
  width: 30px;
  margin: 5px;
  color: #39b5b8;
  font-family: "SimSun";
}
.calendar-title {
  padding: 0 6%;
  color: #333;
}
.switch-btn:active, .calendar-title:active, .calendar-header a.active {
  background-color: #39b5b8;
  color: #fff;
}
.calendar-week {
  overflow: hidden;
}
.calendar-week span {
  float: left;
  width: 14.28%;
  font-size: 1.6em;
  line-height: 34px;
  text-align: center;
}
.inline-calendar {
  width: 100%;
  background: #fff;
  border-radius: 2px;
  transition: all .5s ease;
}
.inline-calendar td.is-today, .inline-calendar td.is-today.is-disabled {
  color: #04be02;
}
.calendar-enter, .calendar-leave {
  opacity: 0;
  transform: translate3d(0,-10px, 0);
}
.calendar:before {
  position: absolute;
  left:30px;
  top: -10px;
  content: "";
  border:5px solid rgba(0, 0, 0, 0);
  border-bottom-color: #DEDEDE;
}
.calendar:after {
  position: absolute;
  left:30px;
  top: -9px;
  content: "";
  border:5px solid rgba(0, 0, 0, 0);
  border-bottom-color: #fff;
}
.calendar-tools{
  height:32px;
  font-size: 20px;
  line-height: 32px;
  color: #04be02;
}
.calendar-tools .float.left{
  float:left;
}
.calendar-tools .float.right{
  float:right;
}
.calendar-tools input{
  font-size: 20px;
  line-height: 32px;
  color: #04be02;
  width: 70px;
  text-align: center;
  border:none;
  background-color: transparent;
}
.calendar-tools>i{
  margin:0 16px;
  line-height: 32px;
  cursor: pointer;
  color:#707070;
}
.calendar-tools>i:hover{
  color:#5e7a88;
}
.inline-calendar table {
  clear: both;
  width: 100%;
  border-collapse: collapse;
  color: #444444;
}
.inline-calendar td {
  padding:5px 0;
  text-align: center;
  vertical-align: middle;
  font-size:16px;
  position: relative;
}
.inline-calendar td.week{
  pointer-events:none !important;
  cursor: default !important;
}
.inline-calendar td.is-disabled {
  color: #c0c0c0;
  pointer-events:none !important;
  cursor: default !important;
}
.inline-calendar td > span {
  display: inline-block;
  width: 26px;
  height: 26px;
  line-height: 26px;
  border-radius: 50%;
  text-align: center;
}
.inline-calendar td.placeholder {

}
.vux-calendar-range.inline-calendar td.current {
  background-color: #04be02;
}
.vux-calendar-range table {
  margin-bottom: 10px;
}
.inline-calendar td.current > span {
  background-color: #04be02;
  color: #fff;
}
.inline-calendar .timer{
  margin:10px 0;
  text-align: center;
}
.inline-calendar .timer input{
  border-radius: 2px;
  padding:5px;
  font-size: 14px;
  line-height: 18px;
  color: #5e7a88;
  width: 50px;
  text-align: center;
  border:1px solid #efefef;
}
.inline-calendar .timer input:focus{
  border:1px solid #5e7a88;
}
.calendar-button{
  text-align: center;
}
.calendar-button button{
  border:none;
  cursor: pointer;
  display: inline-block;
  min-height: 1em;
  min-width: 8em;
  vertical-align: baseline;
  background:#5e7a88;
  color:#fff;
  margin: 0 .25em 0 0;
  padding: .8em 2.5em;
  font-size: 1em;
  line-height: 1em;
  text-align: center;
  border-radius: .3em;
}
.calendar-button button.cancel{
  background:#efefef;
  color:#666;
}
</style>


================================================
FILE: src/components/inline-calendar/metas.yml
================================================
props:
  value:
    en:
    zh-CN: 当前选中日期,双向绑定,默认为空,即选中当天日期
  render-month:
    en:
    zh-CN: 指定渲染日期,如 [2018, 8]
  start-date:
    en:
    zh-CN: 起始日期,格式为'YYYY-MM-dd'
  end-date:
    en:
    zh-CN: 结束日期,格式为'YYYY-MM-dd'
  show-last-month:
    en:
    zh-CN: 是否显示上个月的日期
  show-next-month:
    en:
    zh-CN: 是否显示下个月的日期
  highlight-weekend:
    en:
    zh-CN: 是否高亮周末
  return-six-rows:
    en:
    zh-CN: 是否总是渲染6行日期
  hide-header:
    en:
    zh-CN: 是否隐藏日历头部
  hide-week-list:
    en:
    zh-CN: 是否隐藏星期列表
  replace-text-list:
    en:
    zh-CN: "替换列表,可以将默认的日期换成文字,比如今天的日期替换成今,{'TODAY':'今'}"
  weeks-list:
    en:
    zh-CN: 星期列表,从周日开始
  custom-slot-fn:
    en:
    zh-CN: 用于为特定日期添加额外的html内容,参数为(行index,列index,日期详细属性)
  render-on-value-change:
    en:
    zh-CN: 当日期变化时是否重新渲染日历,如果是渲染了多个日历的话需要设为false
  disable-past:
    en:
    zh-CN: 禁止选择过去的日期,该选项可以与start-date同时使用
  disable-future:
    en:
    zh-CN: 禁止选择未来的日期,该选项可以end-date同时使用


================================================
FILE: src/components/inline-calendar/props.js
================================================
export default () => ({
  value: {
    type: String,
    default: ''
  },
  renderMonth: {
    type: Array, // [2018, 8]
    default () {
      return [null, null]
    }
  },
  startDate: {
    type: String
  },
  endDate: {
    type: String
  },
  showLastMonth: {
    type: Boolean,
    default: true
  },
  showNextMonth: {
    type: Boolean,
    default: true
  },
  highlightWeekend: {
    type: Boolean,
    default: false
  },
  returnSixRows: {
    type: Boolean,
    default: true
  },
  hideHeader: {
    type: Boolean,
    default: false
  },
  hideWeekList: {
    type: Boolean,
    default: false
  },
  replaceTextList: {
    type: Object,
    default () {
      return {}
    }
  },
  weeksList: {
    type: Array,
    default: () => ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
  },
  customSlotFn: {
    type: Function,
    default: () => ''
  },
  renderOnValueChange: {
    type: Boolean,
    default: true
  },
  disablePast: {
    type: Boolean,
    default: false
  },
  disableFuture: {
    type: Boolean,
    default: false
  }
})


================================================
FILE: src/components/inline-calendar/util.js
================================================
import format from '../datetime/format'

export function zero (n) {
  return n < 10 ? '0' + n : n
}

export function splitValue (value) {
  let split = value.split('-')
  return {
    year: parseInt(split[0], 10),
    month: parseInt(split[1], 10) - 1,
    day: parseInt(split[2], 10)
  }
}

export function getPrevTime (year, month) {
  if (month === 0) {
    return {
      month: 11,
      year: year - 1
    }
  } else {
    return {
      year,
      month: month - 1
    }
  }
}

export function getNextTime (year, month) {
  if (month === 11) {
    return {
      month: 0,
      year: year + 1
    }
  } else {
    return {
      year,
      month: month + 1
    }
  }
}

function getTime (str) {
  if (typeof str === 'number') {
    return str
  }
  return typeof str === 'string' ? new Date(str.replace(/-/g, '/')).getTime() : str.getTime()
}

function isBetween (value, start, end) {
  value = getTime(value)
  let isGte = start ? value >= getTime(start) : true
  let isLte = end ? value <= getTime(end) : true
  return isGte && isLte
}

export function getDays ({year, month, value, isRange = false, rangeBegin, rangeEnd, returnSixRows = true, disablePast = false, disableFuture = false}) {
  let today = format(new Date(), 'YYYY-MM-DD')
  let startOfToday = new Date()
  startOfToday.setHours(0, 0, 0, 0)

  let _splitValue = splitValue(value || today)

  // if year or month is not specified, get them from value
  if (typeof year !== 'number' || typeof month !== 'number' || month < 0) {
    year = _splitValue.year
    month = _splitValue.month
  }

  // if disablePast === true
  if (disablePast) {
    if (!rangeBegin) {
      rangeBegin = startOfToday
    } else {
      rangeBegin = Math.max(startOfToday.getTime(), getTime(rangeBegin))
    }
  }

  // if disableFuture === true
  if (disableFuture) {
    if (!rangeEnd) {
      rangeEnd = startOfToday
    } else {
      rangeEnd = Math.min(startOfToday.getTime(), getTime(rangeEnd))
    }
  }

  var firstDayOfMonth = new Date(year, month, 1).getDay()
  var lastDateOfMonth = new Date(year, month + 1, 0).getDate()
  var lastDayOfLastMonth = new Date(year, month, 0).getDate()

  var i
  var line = 0
  var temp = []
  for (i = 1; i <= lastDateOfMonth; i++) {
    var dow = new Date(year, month, i).getDay()
      // 第一行
    if (dow === 0) {
      temp[line] = []
    } else if (i === 1) {
      temp[line] = []

      var k = lastDayOfLastMonth - firstDayOfMonth + 1
      for (let j = 0; j < firstDayOfMonth; j++) {
        let rs = getPrevTime(year, month)
        temp[line].push({
          year: rs.year,
          month: rs.month,
          month_str: rs.month + 1,
          day: k,
          disabled: true,
          isLastMonth: true
        })
        k++
      }
    }

    let _format = format(new Date(year + '/' + (month + 1) + '/' + i), 'YYYY/MM/DD')
    let options = {
      year: year,
      month: month,
      month_str: month + 1,
      day: i,
      isCurrent: value && format(new Date(value), 'YYYY/MM/DD') === _format,
      disabled: !isBetween(_format, rangeBegin, rangeEnd),
      isToday: format(new Date(), 'YYYY/MM/DD') === _format
    }
    temp[line].push(options)

    if (dow === 6) {
      line++
    } else if (i === lastDateOfMonth) {
      let k = 1
      for (dow; dow < 6; dow++) {
        let rs = getNextTime(year, month)
        temp[line].push({
          year: rs.year,
          month: rs.month,
          month_str: rs.month + 1,
          day: k,
          disabled: true,
          isNextMonth: true
        })
        k++
      }
    }
  }

  if (returnSixRows && temp.length === 5) {
    let rs = getNextTime(year, month)
    let start = temp[4][6].isNextMonth ? temp[4][6].day : 0
    temp[6] = []
    for (let i = 0; i < 7; i++) {
      temp[6].push({
        year: rs.year,
        month: rs.month,
        month_str: rs.month + 1,
        day: ++start,
        disabled: true,
        isNextMonth: true
      })
    }
  }

  // 2026-02, there is only 4 lines
  if (returnSixRows && temp.length === 4) {
    let rs = getNextTime(year, month)
    let start = 0
    temp[5] = []
    temp[6] = []
    for (let i = 0; i < 7; i++) {
      temp[5].push({
        year: rs.year,
        month: rs.month,
        month_str: rs.month + 1,
        day: ++start,
        disabled: true,
        isNextMonth: true
      })
      temp[6].push({
        year: rs.year,
        month: rs.month,
        month_str: rs.month + 1,
        day: ++start,
        disabled: true,
        isNextMonth: true
      })
    }
  }

  return {
    year: year,
    month: month,
    month_str: month + 1,
    days: temp
  }
}


================================================
FILE: src/components/inline-desc/index.vue
================================================
<template>
  <span class="vux-label-desc"><slot></slot></span>
</template>

<style>
.vux-label-desc {
  font-size:14px;
  color:#666;
}
</style>


================================================
FILE: src/components/inline-desc/metas.yml
================================================
intro:
  en: it is the child component of cell, you cannot use it alone
  zh-CN: cell的子组件,不能单独使用
slots:
  default:
    en: text content
    zh-CN: 文字内容


================================================
FILE: src/components/inline-x-number/index.vue
================================================
<template>
  <div>
    <a @click="sub" class="vux-number-selector vux-number-selector-sub":class="{'vux-number-disabled':disabledMin}">-</a>
    <input v-model="value" :name="name" class="vux-number-input" :style="{width: width+'px'}" number :readonly="!fillable" pattern="[0-9]*"/>
    <a @click="add" class="vux-number-selector vux-number-selector-plus" :class="{'vux-number-disabled':disabledMax}">+</a>
  </div>
</template>

<script>
export default {
  props: {
    min: Number,
    max: Number,
    step: {
      type: Number,
      default: 1
    },
    value: {
      type: Number,
      default: 0
    },
    name: String,
    title: String,
    fillable: {
      type: Boolean,
      default: true
    },
    width: {
      type: Number,
      default: 50
    }
  },
  computed: {
    disabledMin () {
      return typeof this.min === 'undefined' ? false : this.value <= this.min
    },
    disabledMax () {
      return typeof this.max === 'undefined' ? false : this.value >= this.max
    }
  },
  ready () {
  },
  watch: {
    value (newValue, old) {
      if (this.min && this.value < this.min) {
        this.value = this.min
      }
      if (this.max && this.value > this.max) {
        this.value = this.max
      }
      this.$emit('on-change', this.value)
    }
  },
  methods: {
    add () {
      if (!this.disabledMax) {
        this.value += this.step
      }
    },
    sub () {
      if (!this.disabledMin) {
        this.value -= this.step
      }
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_cell/weui_cell_global';

.vux-number-input {
  float:left;
  height:20px;
  font-size:20px;
  color: @x-number-number-color;
  appearance: none;
  border:1px solid #ececec;
  padding:3px 0;
  text-align:center;
  border-radius: 1px;
}
.vux-number-selector {
  float:left;
  height:20px;
  font-size:25px;
  line-height:18px;
  color: @x-number-button-color;
  border:1px solid #ececec;
}
.vux-number-selector.vux-number-disabled{
  color:#ccc;
}
.vux-number-selector-sub {
  border-right:none;
  padding:3px 10px;
  border-radius:2px 0 0 2px;
}
.vux-number-selector-plus {
  border-left:none;
  margin-right: 5px;
  padding:3px 8px;
  border-radius:0 2px 2px 0;
}
</style>


================================================
FILE: src/components/loading/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/loading/index.vue
================================================
<template>
  <div class="weui_loading_toast" v-show="show">
    <div class="weui_mask_transparent"></div>
    <div class="weui_toast" :style="{position: position}">
      <i class="weui-loading weui-icon_toast"></i>
      <p class="weui_toast_content">{{text}}<slot></slot></p>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    show: Boolean,
    text: {
      type: String,
      default: 'Loading'
    },
    position: String
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_tips/weui_mask';
@import '../../styles/weui/widget/weui_tips/weui_toast';

.weui_loading_toast .weui_toast_content{
    margin-top: 0;
}

.weui-icon_toast.weui-loading {
    margin: 30px 0 0;
    width: 38px;
    height: 38px;
    vertical-align: baseline;
}

.weui-loading {
  width:20px;
  height:20px;
  display: inline-block;
  vertical-align: middle;
  animation: weuiLoading 1s steps(12, end) infinite;
  background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
  background-size: 100%;
}

@-webkit-keyframes weuiLoading {
  0% {
    transform: rotate3d(0, 0, 1, 0deg);
  }

  100% {
    transform: rotate3d(0, 0, 1, 360deg);
  }
}

@keyframes weuiLoading {
  0% {
    transform: rotate3d(0, 0, 1, 0deg);
  }

  100% {
    transform: rotate3d(0, 0, 1, 360deg);
  }
}

</style>


================================================
FILE: src/components/loading/metas.yml
================================================
props:
  show:
    en: visibility of the component
    zh-CN: 显示状态
  text:
    en: loading text
    zh-CN: 提示文字
  position:
    en: position, default is `fixed`, you can use `absolute`
    zh-CN: 定位方式,默认为`fixed`,在100%的布局下用`absolute`可以避免抖动
slots:
  default:
    en: content area
    zh-CN: 提示文字区域


================================================
FILE: src/components/masker/converter.js
================================================
/*!
 * HEX <=> RGB Conversion
 * Copyright(c) 2011 Daniel Lamb <daniellmb.com>
 * MIT Licensed
 */

export function toRGB (color) {
  let num = parseInt(color, 16)
  return [num >> 16, num >> 8 & 255, num & 255]
}

export function toHex (red, green, blue) {
  return ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1)
}


================================================
FILE: src/components/masker/index.vue
================================================
<template>
  <div class="vux-masker-box">
    <slot></slot>
    <div class="vux-masker" :style="style">
      <slot name="content"></slot>
    </div>
  </div>
</template>

<script>
import { toRGB } from './converter'

export default {
  props: {
    color: {
      type: String,
      default: '0, 0, 0'
    },
    opacity: {
      type: Number,
      default: 0.5
    }
  },
  computed: {
    style () {
      let color = /,/.test(this.color) ? this.color : toRGB(this.color.replace('#', '')).join(',')
      return {
        backgroundColor: `rgba(${color},${this.opacity})`
      }
    }
  }
}
</script>

<style>
.vux-masker-box {
  position: relative;
}
.vux-masker {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  border-radius: inherit;
}
</style>


================================================
FILE: src/components/masker/metas.yml
================================================
props:
  color:
    en: the mask's color in rgb format, for example, '0, 0, 0'
    zh-CN: 遮罩颜色,rgb值,'0, 0, 0'
  opacity:
    en: the opacity of the mask
    zh-CN: 遮罩透明度
slots:
  default:
    en: content below the mask
    zh-CN: 背景内容,位于遮罩下方,一般为图片
  content:
    en: content above the mask
    zh-CN: 遮罩上方内容,一般显示标题消息


================================================
FILE: src/components/number-roller/index.vue
================================================
<template>
  <div style="height:100px;font-size:100px;"></div>
</template>

<script>
import Roller from './lib'

export default {
  props: {
    number: Number,
    width: {
      type: Number,
      default: 3
    }
  },
  mounted () {
    this._roller = new Roller({
      container: this.$el,
      width: this.width
    })
    this._roller.roll(this.number)
  },
  watch: {
    number (newVal, oldVal) {
      if (newVal.toString().length !== oldVal.toString().length) {
        this._roller.width = newVal.toString().length
        this._roller.setWidth()
      }
      this._roller.roll(newVal)
    }
  }
}
</script>


================================================
FILE: src/components/number-roller/lib.js
================================================
const Roller = class {
  constructor (opts) {
    this.container = typeof opts.container === 'string' ? document.querySelector(opts.container) : opts.container
    this.width = opts.width || 1
    if (!this.container) {
      throw Error('no container')
    }
    this.container.style.overflow = 'hidden'
    this.rollHeight = parseInt(getComputedStyle(this.container).height)

    if (this.rollHeight < 1) {
      this.container.style.height = '20px'
      this.rollHeight = 20
    }
    this.setWidth()
  }

  roll (n) {
    var self = this
    this.number = parseInt(n) + ''
    if (this.number.length < this.width) {
      this.number = new Array(this.width - this.number.length + 1).join('0') + this.number
    } else if (this.number.length > this.width) {
      this.width = this.number.length
      this.setWidth()
    }
    Array.prototype.forEach.call(this.container.querySelectorAll('.num'), function (item, i) {
      var currentNum = parseInt(item.querySelector('div:last-child').innerHTML)
      var goalNum = parseInt(self.number[i])
      var gapNum = 0
      var gapStr = ''
      if (currentNum === goalNum) {
        return
      } else if (currentNum < goalNum) {
        gapNum = goalNum - currentNum
        for (let j = currentNum; j < goalNum + 1; j++) {
          gapStr += '<div>' + j + '</div>'
        }
      } else {
        gapNum = 10 - currentNum + goalNum
        for (let j = currentNum; j < 10; j++) {
          gapStr += '<div>' + j + '</div>'
        }
        for (let j = 0; j < goalNum + 1; j++) {
          gapStr += '<div>' + j + '</div>'
        }
      }
      item.style.cssText += '-webkit-transition-duration:0;s-webkit-transform:translateY(0)'
      item.innerHTML = gapStr
      let time = gapNum * (1 / 9)
      setTimeout(() => {
        item.style.cssText += '-webkit-transition-duration:' + time + 's;-webkit-transform:translateY(-' + self.rollHeight * gapNum + 'px)'
      }, 50)
    })
  }

  setWidth (n) {
    n = n || this.width
    var str = ''
    for (var i = 0; i < n; i++) {
      str += '<div class="num" style="float:left;height:100%;line-height:' + this.rollHeight + 'px"><div>0</div></div>'
    }
    this.container.innerHTML = str
  }
}

export default Roller


================================================
FILE: src/components/orientation/index.js
================================================
/**
 * v-orientaion="landscape" v-orientaion="portrait"
 */
import Orientation from './orientation'
export default {
  bind () {
    const _this = this
    const value = this.expression
    const _value = value.toString()[0].toUpperCase() + value.toString().slice(1)

    if (Orientation['is' + _value]()) {
      this.el.style.display = 'block'
    } else {
      this.el.style.display = 'none'
    }

    Orientation.change(function (e) {
      let info = Orientation.getInfo()
      _this.el.style.display = info[value] ? 'block' : 'none'
    })
  },
  update () {
  },
  unbind () {
  }
}


================================================
FILE: src/components/orientation/orientation.js
================================================
/**
 * 横竖屏切换监听器
 * @author ningzbruc@gmail.com
 * @gitbub http://gitbub.com/kingback/orientation/
 * @date 2014-01-15
 * @version 0.0.1
 */

// 原生不支持用resize模拟
var ORIENTATION_CHANGE = 'orientationchange'
var RESIZE = 'resize'
var EVT_ORIENTATION_CHANGE = 'onorientationchange' in window ? ORIENTATION_CHANGE : RESIZE
var FUNCTION = 'function'
var ON = 'on'
var AFTER = 'after'

/**
 * 混入对象属性
 * @method merge
 * @param {Object} s 提供对象
 * @return {Object} r 接收对象
 * @private
 */

function merge (s) {
  var r = {}
  var k

  if (s) {
    for (k in s) {
      if (s.hasOwnProperty(k)) {
        r[k] = s[k]
      }
    }
  }

  return r
}

/**
 * 绑定方法上下文
 * @method bind
 * @param {Function} fn
 * @param {Object} context
 * @return {Function}
 * @private
 */

function bind (fn, context) {
  return fn.bind ? fn.bind(context) : function () {
    fn.apply(context, arguments)
  }
}

/**
 * 横竖屏切换监听器
 * @constructor Orientation
 * @class
 */

function Orientation () {
  this.init.apply(this, arguments)
}

Orientation.prototype = {

  /**
   * 构造器
   * @property constructor
   * @public
   */
  constructor: Orientation,

  /**
   * 初始化
   * @method init
   * @public
   */
  init: function (cfg) {
    this._cfg = merge({
      delay: 400
    }, cfg)

    // 事件订阅数组
    this._subs = {
      on: [],
      after: []
    }

    // 当前信息
    this.info = this.getInfo()

    // 绑定事件回调上下文
    this._onWinOrientationChange = bind(this._onWinOrientationChange, this)

    // 绑定窗口切换事件
    window.addEventListener(EVT_ORIENTATION_CHANGE, this._onWinOrientationChange, false)
  },

  /**
   * 销毁
   * @method destroy
   * @public
   */
  destroy: function () {
    window.removeEventListener(EVT_ORIENTATION_CHANGE, this._onWinOrientationChange, false)
    delete this._subs
  },

  /**
   * 创建新实例
   * @method create
   * @return {Orientation} Orientation实例对象
   * @public
   */
  create: function (cfg) {
    return new Orientation(cfg)
  },

  /**
   * 获取横竖屏信息
   * @method getInfo
   * @return {Object} 横竖屏相关信息
   * @public
   */
  getInfo: function () {
    // 90度为横屏
    return (EVT_ORIENTATION_CHANGE === ORIENTATION_CHANGE) ? {
      landscape: (window.orientation === 90 || window.orientation === -90),
      portrait: (window.orientation === 0 || window.orientation === -180),
      orientation: window.orientation
    } : {
      landscape: window.screen.width > window.screen.height,
      portrait: window.screen.width <= window.screen.height,
      orientation: window.screen.width > window.screen.height ? 90 : 0
    }
  },

  /**
   * 是否是横屏
   * @method isLandscape
   * @return {Boolean}
   * @public
   */
  isLandscape: function () {
    return this.info.landscape
  },

  /**
   * 是否是竖屏
   * @method isPortrait
   * @return {Boolean}
   * @public
   */
  isPortrait: function () {
    return this.info.portrait
  },

  /**
   * 添加change事件
   * @method change
   * @param {Function} fn 回调函数
   * @param {Boolean} after 时候绑定after事件
   * @chainable
   */
  change: function (fn, after) {
    if (typeof fn === FUNCTION) {
      this._subs[after ? AFTER : ON].push(fn)
    }

    return this
  },

  /**
   * 触发横竖屏事件
   * @method _fireChange
   * @param {EventFacade} e
   * @protected
   */
  _fireChange: function (e) {
    var self = this
    var info = this.getInfo()
    var subs = this._subs
    var i
    var l

    // 如果不等于上次方向,则触发
    if (info.landscape !== this.info.landscape) {
      this.info = merge(info)
      info.originEvent = e
      info.originType = e.type

      // 执行on
      for (i = 0, l = subs.on.length; i < l; i++) {
        subs.on[i].call(self, e)
      }

      // 执行after
      setTimeout(function () {
        for (i = 0, l = subs.after.length; i < l; i++) {
          subs.after[i].call(self, e)
        }
      }, 0)
    }
  },

  /**
   * 检查旋转是否已经完成
   * @method _checkChange
   * @param {EventFacade} e
   * @protected
   */
  _checkChange: function (e) {
    var self = this

    if (self._cfg.delay) {
      // iPad打开键盘时旋转比较慢
      clearTimeout(this._changeTimer)
      self._changeTimer = setTimeout(function () {
        self._fireChange(e)
      }, self._cfg.delay)
    } else {
      self._fireChange(e)
    }
  },

  /**
   * 横竖屏事件回调
   * @method _onWinOrientationChange
   * @param {EventFacade} e 事件对象
   * @protected
   */
  _onWinOrientationChange: function (e) {
    if (e.type === RESIZE) {
      this._fireChange(e)
    } else {
      this._checkChange(e)
    }
  }

}

// 返回实例
export default Orientation.prototype.create()


================================================
FILE: src/components/panel/component.json
================================================
{
  "vux": {
    "is_weui": true
  }
}

================================================
FILE: src/components/panel/index.vue
================================================
<template>
  <div class="weui_panel weui_panel_access">
    <div class="weui_panel_hd" v-if="header" @click="onClickHeader" v-html="header"></div>
    <div class="weui_panel_bd">
      <!--type==='1'-->
      <a :href="getUrl(item.url)" v-for="item in list" @click.prevent="onItemClick(item)" class="weui_media_box weui_media_appmsg" v-if="type === '1'">
        <div class="weui_media_hd" v-if="item.src">
          <img class="weui_media_appmsg_thumb" :src="item.src" alt="">
        </div>
        <div class="weui_media_bd">
          <h4 class="weui_media_title">{{item.title}}</h4>
          <p class="weui_media_desc">{{item.desc}}</p>
        </div>
      </a>
      <!--type==='2'-->
      <div class="weui_media_box weui_media_text" v-for="item in list" @click.prevent="onItemClick(item)" v-if="type === '2'">
          <h4 class="weui_media_title">{{item.title}}</h4>
          <p class="weui_media_desc">{{item.desc}}</p>
      </div>
      <!--type==='3'-->
      <div class="weui_media_box weui_media_small_appmsg">
          <div class="weui_cells weui_cells_access">
            <a class="weui_cell" :href="getUrl(item.url)" v-for="item in list" @click.prevent="onItemClick(item)" v-if="type === '3'">
              <div class="weui_cell_hd">
                <img :src="item.src" alt="" style="width:20px;margin-right:5px;display:block">
              </div>
              <div class="weui_cell_bd weui_cell_primary">
                <p>{{item.title}}</p>
              </div>
              <span class="weui_cell_ft"></span>
            </a>
          </div>
      </div>
    </div>
    <a class="weui_panel_ft" :href="getUrl(footer.url)" v-if="footer && type !== '3'" @click.prevent="onClickFooter" v-html="footer.title"></a>
  </div>
</template>

<script>
import { go, getUrl } from '../../libs/router'

export default {
  props: {
    header: String,
    footer: Object,
    list: Array,
    type: {
      type: String,
      default: '1'
    }
  },
  methods: {
    getUrl (url) {
      return getUrl(url, this.$router)
    },
    onClickFooter () {
      this.$emit('on-click-footer')
      go(this.footer.url, this.$router)
    },
    onClickHeader () {
      this.$emit('on-click-header')
    },
    onItemClick (item) {
      this.$emit('on-click-item', item)
      go(item.url, this.$router)
    }
  }
}
</script>

<style lang="less">
@import '../../styles/weui/widget/weui_panel/weui_panel';
@import '../../styles/weui/widget/weui_media_box/weui_media_box';
</style>


================================================
FILE: src/components/picker/animate.js
================================================
const time = Date.now || function () {
  return +new Date()
}

let running = {}
let counter = 1
let desiredFrames = 60
let millisecondsPerSecond = 1000

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel
;(function () {
  var lastTime = 0
  var vendors = ['ms', 'moz', 'webkit', 'o']
  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']
  }

  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function (callback, element) {
      var currTime = new Date().getTime()
      var timeToCall = Math.max(0, 16 - (currTime - lastTime))
      var id = window.setTimeout(function () { callback(currTime + timeToCall) },
            timeToCall)
      lastTime = currTime + timeToCall
      return id
    }
  }
  if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function (id) {
      clearTimeout(id)
    }
  }
}())

export default {

  // A requestAnimationFrame wrapper / polyfill.
  requestAnimationFrame: (function () {
    var requestFrame = window.requestAnimationFrame
    return function (callback, root) {
      requestFrame(callback, root)
    }
  })(),

  // Stops the given animation.
  stop (id) {
    var cleared = running[id] != null
    if (cleared) {
      running[id] = null
    }
    return cleared
  },

  // Whether the given animation is still running.
  isRunning (id) {
    return running[id] != null
  },

  // Start the animation.
  start (stepCallback, verifyCallback, completedCallback, duration, easingMethod, root) {
    var _this = this
    var start = time()
    var lastFrame = start
    var percent = 0
    var dropCounter = 0
    var id = counter++

    if (!root) {
      root = document.body
    }

    // Compacting running db automatically every few new animations
    if (id % 20 === 0) {
      var newRunning = {}
      for (var usedId in running) {
        newRunning[usedId] = true
      }
      running = newRunning
    }

    // This is the internal step method which is called every few milliseconds
    var step = function (virtual) {
      // Normalize virtual value
      var render = virtual !== true
      // Get current time
      var now = time()

      // Verification is executed before next animation step
      if (!running[id] || (verifyCallback && !verifyCallback(id))) {
        running[id] = null
        completedCallback && completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, false)
        return
      }

      // For the current rendering to apply let's update omitted steps in memory.
      // This is important to bring internal state variables up-to-date with progress in time.
      if (render) {
        var droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1
        for (var j = 0; j < Math.min(droppedFrames, 4); j++) {
          step(true)
          dropCounter++
        }
      }

      // Compute percent value
      if (duration) {
        percent = (now - start) / duration
        if (percent > 1) {
          percent = 1
        }
      }

      // Execute step callback, then...
      var value = easingMethod ? easingMethod(percent) : percent
      if ((stepCallback(value, now, render) === false || percent === 1) && render) {
        running[id] = null
        completedCallback && completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, percent === 1 || duration == null)
      } else if (render) {
        lastFrame = now
        _this.requestAnimationFrame(step, root)
      }
    }

    // Mark as running
    running[id] = true
    // Init first step
    _this.requestAnimationFrame(step, root)
    // Return unique animation ID
    return id
  }
}


================================================
FILE: src/components/picker/chain.js
================================================
import filter from 'array-filter'

const Manager = class {
  constructor (data, count, fixedColumns) {
    this.data = data
    this.count = count
    if (fixedColumns) {
      this.fixedColumns = fixedColumns
    }
  }

  getChildren (value) {
    return filter(this.data, one => {
      return one.parent === value
    })
  }

  getFirstColumn () {
    return filter(this.data, one => {
      return !one.parent || one.parent === 0 || one.parent === '0'
    })
  }

  getPure (obj) {
    return JSON.parse(JSON.stringify(obj))
  }

  getColumns (value) {
    // check is data contains the values
    if (value.length > 0) {
      const matchCount = this.getPure(this.data).filter((item) => {
        return this.getPure(value).indexOf(item.value) > -1
      }).length
      if (matchCount < this.getPure(value).length) {
        value = []
      }
    }
    var datas = []
    const max = this.fixedColumns || 8
    for (var i = 0; i < max; i++) {
      if (i === 0) {
        datas.push(this.getFirstColumn())
      } else {
        // 没有数据时,取得上一级的第一个
        if (!value[i]) {
          if (typeof datas[i - 1][0] === 'undefined') {
            break
          } else {
            const topValue = datas[i - 1][0].value
            datas.push(this.getChildren(topValue))
          }
        } else {
          datas.push(this.getChildren(value[i - 1]))
        }
      }
    }
    const list = datas.filter((item) => {
      return item.length > 0
    })
    // correct the column
    this.count = list.length
    return list
  }
}

export default Manager


================================================
FILE: src/components/picker/index.vue
================================================
<template>
  <div class="vux-picker">
    <flexbox :gutter="0">
      <flexbox-item v-for="(one, index) in props_data" style="margin-left:0;">
        <div class="vux-picker-item" :id="'vux-picker-' + uuid + '-' + index"></div>
      </flexbox-item>
    </flexbox>
  </div>
</template>

<script>
import Scroller from './scroller'
import { Flexbox, FlexboxItem } from '../flexbox'
import Manager from './chain'

export default {
  components: {
    Flexbox,
    FlexboxItem
  },
  created () {
    this.props_data=this.data
    this.props_value=this.value
    if (this.columns !== 0) {
      const length = this.columns
      this.store = new Manager(this.props_data, length, this.fixedColumns)
      this.props_data = this.store.getColumns(this.props_value)
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.render(this.props_data, this.value)
    })
  },
  props: {
    data: {
      type: Array
    },
    columns: {
      type: Number,
      default: 0
    },
    fixedColumns: {
      type: Number,
      default: 0
    },
    value: Array,
    itemClass: {
      type: String,
      default: 'scroller-item'
    }
  },
  methods: {
    getId (i) {
      return `#vux-picker-${this.uuid}-${i}`
    },
    render (data, value) {
      this.count = this.props_data.length
      const _this = this
      if (!data || !data.length) {
        return
      }
      let count = this.props_data.length
      // set first item as value
      if (value.length < count) {
        for (let i = 0; i < count; i++) {
          // _this.value.$set(i, data[i][0].value || data[i][0])
          _this.$set( _this.value, i, data[i][0].value || data[i][0] )
        }
      }

      for (let i = 0; i < data.length; i++) {
        /**
        * Still don't know why this happens
        */
        if (!document.querySelector(_this.getId(i))) {
          return
        }

        _this.scroller[i] && _this.scroller[i].destroy()
        _this.scroller[i] = new Scroller(_this.getId(i), {
          data: data[i],
          defaultValue: value[i] || data[i][0].value,
          itemClass: _this.item_class,
          onSelect (value) {
            // _this.value.$set(i, value)
            _this.$set(_this.value,i,value)
            if (!this.columns || (this.columns && _this.getValue().length === _this.store.count)) {
              _this.$emit('on-change', _this.getValue())
            }
            if (_this.columns !== 0) {
              _this.renderChain(i + 1)
            }
          }
        })
        if (_this.value) {
          _this.scroller[i].select(value[i])
        }
      }
    },
    renderChain (i) {
      if (!this.columns) {
        return
      }

      // do not render for last scroller
      if (i > this.count - 1) {
        return
      }

      const _this = this
      let ID = this.getId(i)
      // destroy old one
      this.scroller[i].destroy()
      let list = this.store.getChildren(_this.getValue()[i - 1])
      this.scroller[i] = new Scroller(ID, {
        data: list,
        itemClass: _this.item_class,
        onSelect (value) {
          // _this.value.$set(i, value)
          _this.$set(_this.props_value,i,value)
          _this.$emit('on-change', _this.getValue())
          _this.renderChain(i + 1)
        }
      })
      // this.value.$set(i, list[0].value)
      this.$set(this.props_value,i,list[0].value)
      this.renderChain(i + 1)
    },
    getValue () {
      let data = []
      for (let i = 0; i < this.props_data.length; i++) {
        if (this.scroller[i]) {
          data.push(this.scroller[i].value)
        } else {
          return []
        }
      }
      return data
    },
    emitValueChange (val) {
      if (!this.columns || (this.columns && val.length === this.store.count)) {
        this.$emit('on-change', val)
      }
    }
  },
  data () {
    return {
      scroller: [],
      count: 0,
      uuid: Math.random().toString(36).substring(3, 8),
      props_data:[],
      props_value:[]
    }
  },
  watch: {
    value(val){
      this.props_value=val
    },
    props_value (val, oldVal) {
      // render all the scroller for chain datas
      if (this.columns !== 0) {
        if (val.length > 0) {
          if (JSON.stringify(val) !== JSON.stringify(oldVal)) {
            this.props_data = this.store.getColumns(val)
            this.$nextTick(function () {
              this.render(this.props_data, val)
            })
          }
        }
      } else {
        for (let i = 0; i < val.length; i++) {
          if (this.scroller[i] && this.scroller[i].value !== val[i]) {
            this.scroller[i].select(val[i])
          }
        }
      }
    },
    data(newData){
      this.props_data=newData
    },
    props_data (newData) {
      if (Object.prototype.toString.call(newData[0]) === '[object Array]') {
        this.$nextTick(() => {
          this.render(newData, this.props_value)
          // emit on-change after rerender
          this.$nextTick(() => {
            this.emitValueChange(this.getValue())

            if (JSON.stringify(this.getValue()) !== JSON.stringify(this.props_value)) {
              if (!this.columns || (this.columns && this.getValue().length === this.store.count)) {
                this.props_value = this.getValue()
              }
            }
          })
        })
      } else {
        if (this.columns !== 0) {
          if (!newData.length) {
            return
          }
          const length = this.columns
          this.store = new Manager(newData, length, this.fixedColumns)
          this.props_data = this.store.getColumns(this.props_value)
        }
      }
    }
  },
  beforeDestroy () {
    for (let i = 0; i < this.count; i++) {
      this.scroller[i].destroy()
      this.scroller[i] = null
    }
  }
}
</script>

<style>
@import './scroller.css';
</style>



================================================
FILE: src/components/picker/metas.yml
================================================


================================================
FILE: src/components/picker/scroller.css
================================================
.scroller-component {
  display: block;
  position: relative;
  height: 238px;
  overflow: hidden;
  width: 100%;
}

.scroller-content {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 1;
}

.scroller-mask {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  margin: 0 auto;
  width: 100%;
  z-index: 3;
  background-image:
    -webkit-linear-gradient(top, rgba(255,255,255,0.95), rgba(255,255,255,0.6)),
    -webkit-linear-gradient(bottom, rgba(255,255,255,0.95), rgba(255,255,255,0.6));
  background-image:
    linear-gradient(to bottom, rgba(255,255,255,0.95), rgba(255,255,255,0.6)),
    linear-gradient(to top, rgba(255,255,255,0.95), rgba(255,255,255,0.6));
  background-position: top, bottom;
  background-size: 100% 102px;
  background-repeat: no-repeat;
}

.scroller-item {
  text-align: center;
  font-size: 16px;
  height: 34px;
  line-height: 34px;
  color: #000;
}

.scroller-indicator {
  width: 100%;
  height: 34px;
  position: absolute;
  left: 0;
  top: 102px;
  z-index: 3;
  background-image:
    -webkit-linear-gradient(top, #d0d0d0, #d0d0d0, transparent, transparent),
    -webkit-linear-gradient(bottom, #d0d0d0, #d0d0d0, transparent, transparent);
  background-image:
    linear-gradient(to bottom, #d0d0d0, #d0d0d0, transparent, transparent),
    linear-gradient(to top, #d0d0d0, #d0d0d0, transparent, transparent);
  background-position: top, bottom;
  background-size: 100% 1px;
  background-repeat: no-repeat;
}
.scroller-item {
  line-clamp: 1;
  -webkit-line-clamp: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}

================================================
FILE: src/components/picker/scroller.js
================================================
/*
 * Anima Scroller
 * Based Zynga Scroller (http://github.com/zynga/scroller)
 * Copyright 2011, Zynga Inc.
 * Licensed under the MIT License.
 * https://raw.github.com/zynga/scroller/master/MIT-LICENSE.txt
 */
const TEMPLATE = `
<div class="scroller-component" data-role="component">
  <div class="scroller-mask" data-role="mask"></div>
  <div class="scroller-indicator" data-role="indicator"></div>
  <div class="scroller-content" data-role="content"></div>
</div>
`

import Animate from './animate'
import { getElement, getComputedStyle, easeOutCubic, easeInOutCubic } from './util'

var Scroller = function (container, options) {
  var self = this

  options = options || {}

  self.options = {
    itemClass: 'scroller-item',
    onSelect () {},
    defaultValue: 0,
    data: []
  }

  for (var key in options) {
    if (options[key] !== undefined) {
      self.options[key] = options[key]
    }
  }

  self.__container = getElement(container)

  var tempContainer = document.createElement('div')
  tempContainer.innerHTML = options.template || TEMPLATE

  var component = self.__component = tempContainer.querySelector('[data-role=component]')
  var content = self.__content = component.querySelector('[data-role=content]')
  var indicator = component.querySelector('[data-role=indicator]')

  var data = self.options.data
  var html = ''
  if (data.length && data[0].constructor === Object) {
    data.forEach(function (row) {
      html += '<div class="' + self.options.itemClass + '" data-value="' + row.value + '">' + row.name + '</div>'
    })
  } else {
    data.forEach(function (val) {
      html += '<div class="' + self.options.itemClass + '" data-value="' + val + '">' + val + '</div>'
    })
  }
  content.innerHTML = html

  self.__container.appendChild(component)

  self.__itemHeight = parseInt(getComputedStyle(indicator, 'height'), 10)

  self.__callback = options.callback || function (top) {
    content.style.webkitTransform = 'translate3d(0, ' + (-top) + 'px, 0)'
  }

  var rect = component.getBoundingClientRect()

  self.__clientTop = (rect.top + component.clientTop) || 0

  self.__setDimensions(component.clientHeight, content.offsetHeight)

  if (component.clientHeight === 0) {
    self.__setDimensions(parseInt(getComputedStyle(component, 'height'), 10), 204)
  }
  self.select(self.options.defaultValue, false)

  component.addEventListener('touchstart', function (e) {
    if (e.target.tagName.match(/input|textarea|select/i)) {
      return
    }
    e.preventDefault()
    self.__doTouchStart(e.touches, e.timeStamp)
  }, false)

  component.addEventListener('touchmove', function (e) {
    self.__doTouchMove(e.touches, e.timeStamp)
  }, false)

  component.addEventListener('touchend', function (e) {
    self.__doTouchEnd(e.timeStamp)
  }, false)
}

var members = {
  value: null,
  __prevValue: null,
  __isSingleTouch: false,
  __isTracking: false,
  __didDecelerationComplete: false,
  __isGesturing: false,
  __isDragging: false,
  __isDecelerating: false,
  __isAnimating: false,
  __clientTop: 0,
  __clientHeight: 0,
  __contentHeight: 0,
  __itemHeight: 0,
  __scrollTop: 0,
  __minScrollTop: 0,
  __maxScrollTop: 0,
  __scheduledTop: 0,
  __lastTouchTop: null,
  __lastTouchMove: null,
  __positions: null,
  __minDecelerationScrollTop: null,
  __maxDecelerationScrollTop: null,
  __decelerationVelocityY: null,

  __setDimensions (clientHeight, contentHeight) {
    var self = this

    self.__clientHeight = clientHeight
    self.__contentHeight = contentHeight

    var totalItemCount = self.options.data.length
    var clientItemCount = Math.round(self.__clientHeight / self.__itemHeight)

    self.__minScrollTop = -self.__itemHeight * (clientItemCount / 2)
    self.__maxScrollTop = self.__minScrollTop + totalItemCount * self.__itemHeight - 0.1
  },

  selectByIndex (index, animate) {
    var self = this
    if (index < 0 || index > self.__content.childElementCount - 1) {
      return
    }
    self.__scrollTop = self.__minScrollTop + index * self.__itemHeight

    self.scrollTo(self.__scrollTop, animate)

    self.__selectItem(self.__content.children[index])
  },

  select (value, animate) {
    var self = this

    var children = self.__content.children
    for (var i = 0, len = children.length; i < len; i++) {
      if (children[i].dataset.value === value) {
        self.selectByIndex(i, animate)
        return
      }
    }

    self.selectByIndex(0, animate)
  },

  getValue () {
    return this.value
  },

  scrollTo (top, animate) {
    var self = this

    animate = (animate === undefined) ? true : animate

    if (self.__isDecelerating) {
      Animate.stop(self.__isDecelerating)
      self.__isDecelerating = false
    }

    top = Math.round(top / self.__itemHeight) * self.__itemHeight
    top = Math.max(Math.min(self.__maxScrollTop, top), self.__minScrollTop)

    if (top === self.__scrollTop || !animate) {
      self.__publish(top)
      self.__scrollingComplete()
      return
    }
    self.__publish(top, 250)
  },

  destroy () {
    this.__component.parentNode && this.__component.parentNode.removeChild(this.__component)
  },

  __selectItem (selectedItem) {
    var self = this

    var selectedItemClass = self.options.itemClass + '-selected'
    var lastSelectedElem = self.__content.querySelector('.' + selectedItemClass)
    if (lastSelectedElem) {
      lastSelectedElem.classList.remove(selectedItemClass)
    }
    selectedItem.classList.add(selectedItemClass)

    if (self.value !== null) {
      self.__prevValue = self.value
    }

    self.value = selectedItem.dataset.value
  },

  __scrollingComplete () {
    var self = this

    var index = Math.round((self.__scrollTop - self.__minScrollTop - self.__itemHeight / 2) / self.__itemHeight)

    self.__selectItem(self.__content.children[index])

    if (self.__prevValue !== null && self.__prevValue !== self.value) {
      self.options.onSelect(self.value)
    }
  },

  __doTouchStart (touches, timeStamp) {
    var self = this

    if (touches.length == null) {
      throw new Error('Invalid touch list: ' + touches)
    }
    if (timeStamp instanceof Date) {
      timeStamp = timeStamp.valueOf()
    }
    if (typeof timeStamp !== 'number') {
      throw new Error('Invalid timestamp value: ' + timeStamp)
    }

    self.__interruptedAnimation = true

    if (self.__isDecelerating) {
      Animate.stop(self.__isDecelerating)
      self.__isDecelerating = false
      self.__interruptedAnimation = true
    }

    if (self.__isAnimating) {
      Animate.stop(self.__isAnimating)
      self.__isAnimating = false
      self.__interruptedAnimation = true
    }

    // Use center point when dealing with two fingers
    var currentTouchTop
    var isSingleTouch = touches.length === 1
    if (isSingleTouch) {
      currentTouchTop = touches[0].pageY
    } else {
      currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2
    }

    self.__initialTouchTop = currentTouchTop
    self.__lastTouchTop = currentTouchTop
    self.__lastTouchMove = timeStamp
    self.__lastScale = 1
    self.__enableScrollY = !isSingleTouch
    self.__isTracking = true
    self.__didDecelerationComplete = false
    self.__isDragging = !isSingleTouch
    self.__isSingleTouch = isSingleTouch
    self.__positions = []
  },

  __doTouchMove (touches, timeStamp, scale) {
    var self = this

    if (touches.length == null) {
      throw new Error('Invalid touch list: ' + touches)
    }
    if (timeStamp instanceof Date) {
      timeStamp = timeStamp.valueOf()
    }
    if (typeof timeStamp !== 'number') {
      throw new Error('Invalid timestamp value: ' + timeStamp)
    }

    // Ignore event when tracking is not enabled (event might be outside of element)
    if (!self.__isTracking) {
      return
    }

    var currentTouchTop

    // Compute move based around of center of fingers
    if (touches.length === 2) {
      currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2
    } else {
      currentTouchTop = touches[0].pageY
    }

    var positions = self.__positions

    // Are we already is dragging mode?
    if (self.__isDragging) {
      var moveY = currentTouchTop - self.__lastTouchTop
      var scrollTop = self.__scrollTop

      if (self.__enableScrollY) {
        scrollTop -= moveY

        var minScrollTop = self.__minScrollTop
        var maxScrollTop = self.__maxScrollTop

        if (scrollTop > maxScrollTop || scrollTop < minScrollTop) {
          // Slow down on the edges
          if (scrollTop > maxScrollTop) {
            scrollTop = maxScrollTop
          } else {
            scrollTop = minScrollTop
          }
        }
      }

      // Keep list from growing infinitely (holding min 10, max 20 measure points)
      if (positions.length > 40) {
        positions.splice(0, 20)
      }

      // Track scroll movement for decleration
      positions.push(scrollTop, timeStamp)

      // Sync scroll position
      self.__publish(scrollTop)

      // Otherwise figure out whether we are switching into dragging mode now.
    } else {
      var minimumTrackingForScroll = 0
      var minimumTrackingForDrag = 5

      var distanceY = Math.abs(currentTouchTop - self.__initialTouchTop)

      self.__enableScrollY = distanceY >= minimumTrackingForScroll

      positions.push(self.__scrollTop, timeStamp)

      self.__isDragging = self.__enableScrollY && (distanceY >= minimumTrackingForDrag)

      if (self.__isDragging) {
        self.__interruptedAnimation = false
      }
    }

    // Update last touch positions and time stamp for next event
    self.__lastTouchTop = currentTouchTop
    self.__lastTouchMove = timeStamp
    self.__lastScale = scale
  },

  __doTouchEnd (timeStamp) {
    var self = this

    if (timeStamp instanceof Date) {
      timeStamp = timeStamp.valueOf()
    }
    if (typeof timeStamp !== 'number') {
      throw new Error('Invalid timestamp value: ' + timeStamp)
    }

    // Ignore event when tracking is not enabled (no touchstart event on element)
    // This is required as this listener ('touchmove') sits on the document and not on the element itself.
    if (!self.__isTracking) {
      return
    }

    // Not touching anymore (when two finger hit the screen there are two touch end events)
    self.__isTracking = false

    // Be sure to reset the dragging flag now. Here we also detect whether
    // the finger has moved fast enough to switch into a deceleration animation.
    if (self.__isDragging) {
      // Reset dragging flag
      self.__isDragging = false

      // Start deceleration
      // Verify that the last move detected was in some relevant time frame
      if (self.__isSingleTouch && (timeStamp - self.__lastTouchMove) <= 100) {
        // Then figure out what the scroll position was about 100ms ago
        var positions = self.__positions
        var endPos = positions.length - 1
        var startPos = endPos

        // Move pointer to position measured 100ms ago
        for (var i = endPos; i > 0 && positions[i] > (self.__lastTouchMove - 100); i -= 2) {
          startPos = i
        }

        // If start and stop position is identical in a 100ms timeframe,
        // we cannot compute any useful deceleration.
        if (startPos !== endPos) {
          // Compute relative movement between these two points
          var timeOffset = positions[endPos] - positions[startPos]
          var movedTop = self.__scrollTop - positions[startPos - 1]

          // Based on 50ms compute the movement to apply for each render step
          self.__decelerationVelocityY = movedTop / timeOffset * (1000 / 60)

          // How much velocity is required to start the deceleration
          var minVelocityToStartDeceleration = 4

          // Verify that we have enough velocity to start deceleration
          if (Math.abs(self.__decelerationVelocityY) > minVelocityToStartDeceleration) {
            self.__startDeceleration(timeStamp)
          }
        }
      }
    }

    if (!self.__isDecelerating) {
      self.scrollTo(self.__scrollTop)
    }

    // Fully cleanup list
    self.__positions.length = 0
  },

  // Applies the scroll position to the content element
  __publish (top, animationDuration) {
    var self = this

    // Remember whether we had an animation, then we try to continue based on the current "drive" of the animation
    var wasAnimating = self.__isAnimating
    if (wasAnimating) {
      Animate.stop(wasAnimating)
      self.__isAnimating = false
    }

    if (animationDuration) {
      // Keep scheduled positions for scrollBy functionality
      self.__scheduledTop = top

      var oldTop = self.__scrollTop
      var diffTop = top - oldTop

      var step = function (percent, now, render) {
        self.__scrollTop = oldTop + (diffTop * percent)
        // Push values out
        if (self.__callback) {
          self.__callback(self.__scrollTop)
        }
      }

      var verify = function (id) {
        return self.__isAnimating === id
      }

      var completed = function (renderedFramesPerSecond, animationId, wasFinished) {
        if (animationId === self.__isAnimating) {
          self.__isAnimating = false
        }
        if (self.__didDecelerationComplete || wasFinished) {
          self.__scrollingComplete()
        }
      }

      // When continuing based on previous animation we choose an ease-out animation instead of ease-in-out
      self.__isAnimating = Animate.start(step, verify, completed, animationDuration, wasAnimating ? easeOutCubic : easeInOutCubic)
    } else {
      self.__scheduledTop = self.__scrollTop = top
      // Push values out
      if (self.__callback) {
        self.__callback(top)
      }
    }
  },

  // Called when a touch sequence end and the speed of the finger was high enough to switch into deceleration mode.
  __startDeceleration (timeStamp) {
    var self = this

    self.__minDecelerationScrollTop = self.__minScrollTop
    self.__maxDecelerationScrollTop = self.__maxScrollTop

    // Wrap class method
    var step = function (percent, now, render) {
      self.__stepThroughDeceleration(render)
    }

    // How much velocity is required to keep the deceleration running
    var minVelocityToKeepDecelerating = 0.5

    // Detect whether it's still worth to continue animating steps
    // If we are already slow enough to not being user perceivable anymore, we stop the whole process here.
    var verify = function () {
      var shouldContinue = Math.abs(self.__decelerationVelocityY) >= minVelocityToKeepDecelerating
      if (!shouldContinue) {
        self.__didDecelerationComplete = true
      }
      return shouldContinue
    }

    var completed = function (renderedFramesPerSecond, animationId, wasFinished) {
      self.__isDecelerating = false
      if (self.__scrollTop <= self.__minScrollTop || self.__scrollTop >= self.__maxScrollTop) {
        self.scrollTo(self.__scrollTop)
        return
      }
      if (self.__didDecelerationComplete) {
        self.__scrollingComplete()
      }
    }

    // Start animation and switch on flag
    self.__isDecelerating = Animate.start(step, verify, completed)
  },

  // Called on every step of the animation
  __stepThroughDeceleration (render) {
    var self = this

    var scrollTop = self.__scrollTop + self.__decelerationVelocityY

    var scrollTopFixed = Math.max(Math.min(self.__maxDecelerationScrollTop, scrollTop), self.__minDecelerationScrollTop)
    if (scrollTopFixed !== scrollTop) {
    
Download .txt
gitextract_ozu3psze/

├── .babelrc
├── .editorconfig
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── build/
│   ├── build.js
│   ├── check-versions.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config/
│   ├── dev.env.js
│   ├── index.js
│   ├── prod.env.js
│   └── test.env.js
├── index.html
├── package.json
├── src/
│   ├── App.vue
│   ├── Home.vue
│   ├── Wechat.vue
│   ├── components/
│   │   ├── actionsheet/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── alert/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── badge/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── blur/
│   │   │   ├── blur.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── box/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── button-tab/
│   │   │   ├── button-tab-item.vue
│   │   │   ├── button-tab.vue
│   │   │   ├── index.js
│   │   │   └── metas.yml
│   │   ├── calendar/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── card/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── cell/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── check-icon/
│   │   │   └── index.vue
│   │   ├── checker/
│   │   │   ├── checker-item.vue
│   │   │   ├── checker.vue
│   │   │   ├── index.js
│   │   │   └── metas.yml
│   │   ├── checklist/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   └── object-filter.js
│   │   ├── circle/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── clocker/
│   │   │   ├── clocker.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── color-picker/
│   │   │   └── index.vue
│   │   ├── confirm/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── countdown/
│   │   │   └── index.vue
│   │   ├── countup/
│   │   │   └── index.vue
│   │   ├── datetime/
│   │   │   ├── datetimepicker.js
│   │   │   ├── format.js
│   │   │   ├── index.vue
│   │   │   └── util.js
│   │   ├── dev-tip/
│   │   │   └── index.vue
│   │   ├── dialog/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── divider/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── flexbox/
│   │   │   ├── flexbox-item.vue
│   │   │   ├── flexbox.vue
│   │   │   └── index.js
│   │   ├── fullpage/
│   │   │   ├── DemoBasic.vue
│   │   │   ├── index.vue
│   │   │   └── lib.js
│   │   ├── group/
│   │   │   ├── component.json
│   │   │   ├── index.md
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── group-title/
│   │   │   └── index.vue
│   │   ├── icon/
│   │   │   ├── component.json
│   │   │   ├── index.md
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── index.js
│   │   ├── inline-calendar/
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   ├── props.js
│   │   │   └── util.js
│   │   ├── inline-desc/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── inline-x-number/
│   │   │   └── index.vue
│   │   ├── loading/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── masker/
│   │   │   ├── converter.js
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── number-roller/
│   │   │   ├── index.vue
│   │   │   └── lib.js
│   │   ├── orientation/
│   │   │   ├── index.js
│   │   │   └── orientation.js
│   │   ├── panel/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── picker/
│   │   │   ├── animate.js
│   │   │   ├── chain.js
│   │   │   ├── index.vue
│   │   │   ├── metas.yml
│   │   │   ├── scroller.css
│   │   │   ├── scroller.js
│   │   │   └── util.js
│   │   ├── popover/
│   │   │   ├── DemoIndex.vue
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── popup/
│   │   │   ├── index.vue
│   │   │   └── popup.js
│   │   ├── popup-picker/
│   │   │   └── index.vue
│   │   ├── previewer/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── progress/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── qrcode/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── radio/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── range/
│   │   │   ├── index.vue
│   │   │   ├── powerange.less
│   │   │   └── range/
│   │   │       └── lib/
│   │   │           ├── horizontal.js
│   │   │           ├── lib/
│   │   │           │   ├── classes.js
│   │   │           │   ├── closest-num.js
│   │   │           │   ├── closest.js
│   │   │           │   ├── delegate.js
│   │   │           │   ├── emitter.js
│   │   │           │   ├── event.js
│   │   │           │   ├── events.js
│   │   │           │   ├── indexof.js
│   │   │           │   ├── matches-selector.js
│   │   │           │   ├── mouse.js
│   │   │           │   ├── percentage-calc.js
│   │   │           │   ├── query.js
│   │   │           │   └── super.js
│   │   │           ├── main.js
│   │   │           └── powerange.js
│   │   ├── rater/
│   │   │   └── index.vue
│   │   ├── scroller/
│   │   │   └── index.vue
│   │   ├── search/
│   │   │   └── index.vue
│   │   ├── selector/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── shake/
│   │   │   └── index.vue
│   │   ├── spinner/
│   │   │   ├── index.vue
│   │   │   ├── requestAnimationFrame.js
│   │   │   └── spinner.js
│   │   ├── step/
│   │   │   ├── index.js
│   │   │   ├── step-item.vue
│   │   │   └── step.vue
│   │   ├── sticky/
│   │   │   ├── index.vue
│   │   │   └── sticky.js
│   │   ├── swiper/
│   │   │   ├── index.vue
│   │   │   └── swiper.js
│   │   ├── swiper-item/
│   │   │   └── index.vue
│   │   ├── tab/
│   │   │   ├── index.js
│   │   │   ├── tab-item.vue
│   │   │   └── tab.vue
│   │   ├── tabbar/
│   │   │   ├── component.json
│   │   │   ├── index.js
│   │   │   ├── metas.yml
│   │   │   ├── tabbar-item.vue
│   │   │   └── tabbar.vue
│   │   ├── timeline/
│   │   │   ├── index.js
│   │   │   ├── timeline-item.vue
│   │   │   └── timeline.vue
│   │   ├── tip/
│   │   │   └── index.vue
│   │   ├── toast/
│   │   │   ├── component.json
│   │   │   └── index.vue
│   │   ├── video/
│   │   │   ├── index.vue
│   │   │   ├── zy.media.css
│   │   │   └── zy.media.js
│   │   ├── view-box/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── wechat-emotion/
│   │   │   └── index.vue
│   │   ├── x-address/
│   │   │   ├── data/
│   │   │   │   └── compress.js
│   │   │   ├── index.vue
│   │   │   ├── list.json
│   │   │   └── metas.yml
│   │   ├── x-button/
│   │   │   ├── component.json
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── x-header/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   ├── x-img/
│   │   │   └── index.vue
│   │   ├── x-input/
│   │   │   └── index.vue
│   │   ├── x-number/
│   │   │   └── index.vue
│   │   ├── x-switch/
│   │   │   ├── index.vue
│   │   │   └── metas.yml
│   │   └── x-textarea/
│   │       ├── component.json
│   │       ├── index.vue
│   │       └── metas.yml
│   ├── demos/
│   │   ├── 1px.vue
│   │   ├── Actionsheet.vue
│   │   ├── Address.vue
│   │   ├── Alert.vue
│   │   ├── Badge.vue
│   │   ├── Blur.vue
│   │   ├── Button-tab.vue
│   │   ├── Calendar.vue
│   │   ├── Card.vue
│   │   ├── Cell.vue
│   │   ├── Center.vue
│   │   ├── Checker.vue
│   │   ├── Checklist.vue
│   │   ├── Circle.vue
│   │   ├── Clocker.vue
│   │   ├── Close.vue
│   │   ├── Color-picker.vue
│   │   ├── Comment.vue
│   │   ├── Confirm.vue
│   │   ├── Countdown.vue
│   │   ├── Countup.vue
│   │   ├── Date-formatter.vue
│   │   ├── Datetime.vue
│   │   ├── Demo.vue
│   │   ├── Device.vue
│   │   ├── Dialog.vue
│   │   ├── Divider.vue
│   │   ├── Donate.vue
│   │   ├── Flexbox.vue
│   │   ├── Icon-loading.vue
│   │   ├── Icon.vue
│   │   ├── Inline-calendar-start-date.vue
│   │   ├── Inline-calendar.vue
│   │   ├── Input.vue
│   │   ├── Inview.vue
│   │   ├── Issue189.vue
│   │   ├── Issue414.vue
│   │   ├── Issue461.vue
│   │   ├── Loading.vue
│   │   ├── Masker.vue
│   │   ├── Number-roller.vue
│   │   ├── Number.vue
│   │   ├── Orientation.vue
│   │   ├── Panel.vue
│   │   ├── Picker.vue
│   │   ├── Popup-picker.vue
│   │   ├── Popup.vue
│   │   ├── Previewer.vue
│   │   ├── Progress.vue
│   │   ├── Pulldown.vue
│   │   ├── PulldownPullup.vue
│   │   ├── Pullup.vue
│   │   ├── Qrcode.vue
│   │   ├── Radio.vue
│   │   ├── Range.vue
│   │   ├── Rater.vue
│   │   ├── Reddot.vue
│   │   ├── Scroller-full.vue
│   │   ├── Scroller-header.vue
│   │   ├── Scroller-swiper.vue
│   │   ├── Scroller.vue
│   │   ├── Search-static.vue
│   │   ├── Search.vue
│   │   ├── Selector.vue
│   │   ├── Shake.vue
│   │   ├── Spinner.vue
│   │   ├── Step.vue
│   │   ├── Sticky.vue
│   │   ├── Swiper.vue
│   │   ├── Switch.vue
│   │   ├── Tab.vue
│   │   ├── Tabbar.vue
│   │   ├── TabbarLink.vue
│   │   ├── Test.vue
│   │   ├── Textarea.vue
│   │   ├── Thanks.vue
│   │   ├── Timeline.vue
│   │   ├── Tip.vue
│   │   ├── Toast.vue
│   │   ├── Wechat-emotion.vue
│   │   ├── X-button.vue
│   │   ├── X-header.vue
│   │   ├── X-img-scroller.vue
│   │   ├── XImg.vue
│   │   └── style.css
│   ├── directives/
│   │   ├── click-outside/
│   │   │   └── index.js
│   │   └── inview/
│   │       ├── index.js
│   │       └── inview.js
│   ├── filters/
│   │   ├── array2String.js
│   │   ├── friendly-time.js
│   │   ├── name2value.js
│   │   └── value2name.js
│   ├── libs/
│   │   ├── base.js
│   │   ├── eventor.js
│   │   ├── mixin_uuid.js
│   │   ├── router.js
│   │   └── trim.js
│   ├── main.js
│   ├── mixins/
│   │   └── multi-items.js
│   ├── pages/
│   │   └── home/
│   │       └── home.vue
│   ├── plugins/
│   │   ├── alert/
│   │   │   └── index.js
│   │   ├── device/
│   │   │   └── index.js
│   │   └── toast/
│   │       └── index.js
│   ├── routers/
│   │   └── router.js
│   ├── styles/
│   │   ├── 1px.less
│   │   ├── center.less
│   │   ├── close.less
│   │   ├── index.less
│   │   ├── index.vue
│   │   ├── loading.less
│   │   ├── reddot.less
│   │   ├── reset.less
│   │   ├── tap.less
│   │   ├── transition.less
│   │   ├── variable.less
│   │   └── weui/
│   │       ├── base/
│   │       │   ├── fn.less
│   │       │   ├── mixin/
│   │       │   │   ├── mobile.less
│   │       │   │   ├── setArrow.less
│   │       │   │   ├── setChecked.less
│   │       │   │   ├── setOnepx.less
│   │       │   │   └── text.less
│   │       │   ├── reset.less
│   │       │   └── variable/
│   │       │       ├── global.less
│   │       │       ├── monokai.less
│   │       │       ├── weui_button.less
│   │       │       ├── weui_cell.less
│   │       │       ├── weui_grid.less
│   │       │       ├── weui_msg.less
│   │       │       └── weui_progress.less
│   │       ├── icon/
│   │       │   ├── weui_font.less
│   │       │   └── weui_icon_font.less
│   │       ├── weui.less
│   │       └── widget/
│   │           ├── weui_button/
│   │           │   ├── weui_btn_default.less
│   │           │   ├── weui_btn_disabled.less
│   │           │   ├── weui_btn_global.less
│   │           │   ├── weui_btn_plain.less
│   │           │   ├── weui_btn_primary.less
│   │           │   ├── weui_btn_warn.less
│   │           │   └── weui_button.less
│   │           ├── weui_cell/
│   │           │   ├── weui_access.less
│   │           │   ├── weui_cell_global.less
│   │           │   ├── weui_check/
│   │           │   │   ├── weui_check_common.less
│   │           │   │   ├── weui_checkbox.less
│   │           │   │   └── weui_radio.less
│   │           │   ├── weui_check.less
│   │           │   ├── weui_form/
│   │           │   │   ├── weui_form_common.less
│   │           │   │   ├── weui_select.less
│   │           │   │   ├── weui_select_after.less
│   │           │   │   ├── weui_select_before.less
│   │           │   │   └── weui_vcode.less
│   │           │   ├── weui_form.less
│   │           │   ├── weui_switch.less
│   │           │   └── weui_uploader.less
│   │           ├── weui_grid/
│   │           │   └── weui_grid.less
│   │           ├── weui_media_box/
│   │           │   └── weui_media_box.less
│   │           ├── weui_page/
│   │           │   ├── weui_article.less
│   │           │   └── weui_msg.less
│   │           ├── weui_panel/
│   │           │   └── weui_panel.less
│   │           ├── weui_progress/
│   │           │   └── weui_progress.less
│   │           ├── weui_searchbar/
│   │           │   └── weui_searchbar.less
│   │           ├── weui_tab/
│   │           │   ├── navbar.less
│   │           │   ├── tabbar.less
│   │           │   ├── weui_tab.less
│   │           │   └── weui_tab_tabbar.less
│   │           └── weui_tips/
│   │               ├── weui_actionsheet.less
│   │               ├── weui_dialog.less
│   │               ├── weui_mask.less
│   │               └── weui_toast.less
│   ├── vuex/
│   │   └── store.js
│   └── yi.vue
├── static/
│   └── .gitkeep
└── test/
    ├── e2e/
    │   ├── custom-assertions/
    │   │   └── elementCount.js
    │   ├── nightwatch.conf.js
    │   ├── runner.js
    │   └── specs/
    │       └── test.js
    └── unit/
        ├── .eslintrc
        ├── index.js
        ├── karma.conf.js
        └── specs/
            └── Hello.spec.js
Download .txt
SYMBOL INDEX (212 symbols across 42 files)

FILE: build/utils.js
  function generateLoaders (line 15) | function generateLoaders (loaders) {

FILE: src/components/blur/blur.js
  method createElement (line 67) | createElement (name, attrs) {
  method setAttr (line 77) | setAttr (element, attrs) {
  function getStyle (line 263) | function getStyle (ele, prop) {

FILE: src/components/clocker/clocker.js
  function parseDateString (line 17) | function parseDateString (dateString) {
  function escapedRegExp (line 51) | function escapedRegExp (str) {
  function strftime (line 57) | function strftime (offsetObject) {
  function pluralize (line 104) | function pluralize (format, count) {
  function splitNumber (line 123) | function splitNumber (number) {
  method start (line 146) | start () {
  method stop (line 157) | stop () {
  method toggle (line 163) | toggle () {
  method pause (line 171) | pause () {
  method resume (line 174) | resume () {
  method remove (line 177) | remove () {
  method setFinalDate (line 181) | setFinalDate (value) {
  method getOffset (line 185) | getOffset () {
  method update (line 200) | update () {
  method _dispatchEvent (line 222) | _dispatchEvent (eventName) {

FILE: src/components/datetime/datetimepicker.js
  constant MASK_TEMPLATE (line 4) | const MASK_TEMPLATE = '<div class="dp-mask"></div>'
  constant TEMPLATE (line 6) | const TEMPLATE = `<div class="dp-container">
  method onSelect (line 53) | onSelect () {}
  method onConfirm (line 54) | onConfirm () {}
  method onClear (line 55) | onClear () {}
  method onShow (line 56) | onShow () {}
  method onHide (line 57) | onHide () {}
  function renderScroller (line 63) | function renderScroller (el, data, value, fn) {
  function showMask (line 72) | function showMask () {
  function hideMask (line 89) | function hideMask () {
  function DatetimePicker (line 102) | function DatetimePicker (config) {
  method _show (line 125) | _show (newValueMap) {
  method show (line 139) | show (value) {
  method _makeData (line 232) | _makeData (type, year, month) {
  method _setDayScroller (line 271) | _setDayScroller (year, month, day) {
  method find (line 284) | find (selector) {
  method hide (line 288) | hide () {
  method select (line 302) | select (type, value) {
  method destroy (line 306) | destroy () {
  method getValue (line 314) | getValue () {
  method confirm (line 339) | confirm () {
  method clear (line 351) | clear () {

FILE: src/components/datetime/util.js
  function each (line 3) | function each (obj, fn) {
  function trimZero (line 13) | function trimZero (val) {
  function addZero (line 21) | function addZero (val) {
  function isLeapYear (line 26) | function isLeapYear (year) {
  function getMaxDay (line 30) | function getMaxDay (year, month) {
  function parseRow (line 39) | function parseRow (tmpl, value) {
  function parseDate (line 44) | function parseDate (format, value) {
  function getElement (line 63) | function getElement (expr) {
  function toElement (line 67) | function toElement (html) {
  function removeElement (line 73) | function removeElement (el) {

FILE: src/components/fullpage/lib.js
  constant BOX_CLASS (line 8) | const BOX_CLASS = 'vux-fullpage-box'
  constant ANIM_CLASS (line 9) | const ANIM_CLASS = 'vux-fullpage-box-anim'
  constant ITEM_CLASS (line 10) | const ITEM_CLASS = 'vux-fullpage-item'
  constant DIR_CLASS (line 11) | const DIR_CLASS = 'vux-fullpage-dir'
  function touchmove (line 27) | function touchmove (e) {
  function fix (line 31) | function fix (cur, pagesLength, loop) {
  function move (line 43) | function move (ele, dir, dist) {
  function init (line 52) | function init (option) {
  function Fullpage (line 92) | function Fullpage (ele, option) {

FILE: src/components/inline-calendar/props.js
  method default (line 8) | default () {
  method default (line 44) | default () {

FILE: src/components/inline-calendar/util.js
  function zero (line 3) | function zero (n) {
  function splitValue (line 7) | function splitValue (value) {
  function getPrevTime (line 16) | function getPrevTime (year, month) {
  function getNextTime (line 30) | function getNextTime (year, month) {
  function getTime (line 44) | function getTime (str) {
  function isBetween (line 51) | function isBetween (value, start, end) {
  function getDays (line 58) | function getDays ({year, month, value, isRange = false, rangeBegin, rang...

FILE: src/components/masker/converter.js
  function toRGB (line 7) | function toRGB (color) {
  function toHex (line 12) | function toHex (red, green, blue) {

FILE: src/components/number-roller/lib.js
  method constructor (line 2) | constructor (opts) {
  method roll (line 18) | roll (n) {
  method setWidth (line 57) | setWidth (n) {

FILE: src/components/orientation/index.js
  method bind (line 6) | bind () {
  method update (line 22) | update () {
  method unbind (line 24) | unbind () {

FILE: src/components/orientation/orientation.js
  function merge (line 25) | function merge (s) {
  function bind (line 49) | function bind (fn, context) {
  function Orientation (line 61) | function Orientation () {

FILE: src/components/picker/animate.js
  method stop (line 51) | stop (id) {
  method isRunning (line 60) | isRunning (id) {
  method start (line 65) | start (stepCallback, verifyCallback, completedCallback, duration, easing...

FILE: src/components/picker/chain.js
  method constructor (line 4) | constructor (data, count, fixedColumns) {
  method getChildren (line 12) | getChildren (value) {
  method getFirstColumn (line 18) | getFirstColumn () {
  method getPure (line 24) | getPure (obj) {
  method getColumns (line 28) | getColumns (value) {

FILE: src/components/picker/scroller.js
  constant TEMPLATE (line 8) | const TEMPLATE = `
  method onSelect (line 26) | onSelect () {}
  method __setDimensions (line 120) | __setDimensions (clientHeight, contentHeight) {
  method selectByIndex (line 133) | selectByIndex (index, animate) {
  method select (line 145) | select (value, animate) {
  method getValue (line 159) | getValue () {
  method scrollTo (line 163) | scrollTo (top, animate) {
  method destroy (line 184) | destroy () {
  method __selectItem (line 188) | __selectItem (selectedItem) {
  method __scrollingComplete (line 205) | __scrollingComplete () {
  method __doTouchStart (line 217) | __doTouchStart (touches, timeStamp) {
  method __doTouchMove (line 265) | __doTouchMove (touches, timeStamp, scale) {
  method __doTouchEnd (line 350) | __doTouchEnd (timeStamp) {
  method __publish (line 418) | __publish (top, animationDuration) {
  method __startDeceleration (line 468) | __startDeceleration (timeStamp) {
  method __stepThroughDeceleration (line 508) | __stepThroughDeceleration (render) {

FILE: src/components/picker/util.js
  function getElement (line 1) | function getElement (expr) {
  function getComputedStyle (line 5) | function getComputedStyle (el, key) {
  function easeOutCubic (line 12) | function easeOutCubic (pos) {
  function easeInOutCubic (line 16) | function easeInOutCubic (pos) {

FILE: src/components/range/range/lib/horizontal.js
  function getWidth (line 28) | function getWidth (el) {
  function Horizontal (line 36) | function Horizontal () {

FILE: src/components/range/range/lib/lib/classes.js
  function ClassList (line 38) | function ClassList (el) {

FILE: src/components/range/range/lib/lib/closest.js
  function closest (line 21) | function closest (el, selector, scope) {

FILE: src/components/range/range/lib/lib/emitter.js
  function Emitter (line 14) | function Emitter (obj) {
  function mixin (line 26) | function mixin (obj) {
  function on (line 60) | function on () {

FILE: src/components/range/range/lib/lib/events.js
  function Events (line 24) | function Events (el, obj) {
  function parse (line 169) | function parse (event) {

FILE: src/components/range/range/lib/lib/matches-selector.js
  function match (line 34) | function match (el, selector) {

FILE: src/components/range/range/lib/lib/mouse.js
  function Mouse (line 24) | function Mouse (el, obj) {
  function up (line 46) | function up (e) {
  function move (line 54) | function move (e) {

FILE: src/components/range/range/lib/lib/query.js
  function one (line 1) | function one (selector, el) {

FILE: src/components/range/range/lib/lib/super.js
  function super_ (line 29) | function super_ () {

FILE: src/components/range/range/lib/main.js
  function Powerange (line 26) | function Powerange (element, options) {

FILE: src/components/range/range/lib/powerange.js
  method callback (line 14) | callback () {}

FILE: src/components/spinner/spinner.js
  function createSvgElement (line 36) | function createSvgElement (tagName, data, parent, spinnerName) {
  function setSvgAttribute (line 59) | function setSvgAttribute (ele, k, v) {
  function animationValues (line 63) | function animationValues (strValues, i) {
  method fn (line 75) | fn (i, spinnerName) {
  method fn (line 118) | fn (i) {
  method fn (line 143) | fn (i) {
  method fn (line 183) | fn (i) {
  method fn (line 219) | fn (i) {
  method fn (line 265) | fn (i) {
  method android (line 337) | android (ele) {
  function easeInOutCubic (line 392) | function easeInOutCubic (t, c) {
  function start (line 414) | function start () {

FILE: src/components/sticky/sticky.js
  function gtIOS6 (line 4) | function gtIOS6 () {
  function isSupportSticky (line 11) | function isSupportSticky () {

FILE: src/components/swiper/swiper.js
  class Swiper (line 4) | class Swiper {
    method constructor (line 5) | constructor (options) {
    method _auto (line 45) | _auto () {
    method updateItemWidth (line 55) | updateItemWidth () {
    method stop (line 60) | stop () {
    method _loop (line 64) | _loop () {
    method _onResize (line 68) | _onResize () {
    method _init (line 80) | _init () {
    method _initPosition (line 95) | _initPosition () {
    method _movePosition (line 101) | _movePosition (position) {
    method _setOffset (line 112) | _setOffset () {
    method _setTransition (line 121) | _setTransition (duration) {
    method _setTransfrom (line 130) | _setTransfrom (offset) {
    method _bind (line 144) | _bind () {
    method _loopTwoItems (line 207) | _loopTwoItems () {
    method _loopRender (line 222) | _loopRender () {
    method _loopEvent (line 236) | _loopEvent (num) {
    method getDistance (line 246) | getDistance (distance) {
    method _moveIndex (line 260) | _moveIndex (num) {
    method _activate (line 269) | _activate (index) {
    method go (line 279) | go (index) {
    method next (line 296) | next () {
    method move (line 301) | move (num) {
    method on (line 306) | on (event, callback) {
    method _itemDestoy (line 317) | _itemDestoy () {
    method destroy (line 322) | destroy () {

FILE: src/components/video/zy.media.js
  function _css (line 110) | function _css(el, property) {
  function _hasClass (line 115) | function _hasClass(el, token) {
  function _addClass (line 120) | function _addClass(el, token) {
  function _removeClass (line 129) | function _removeClass(el, token) {
  function timeFormat (line 138) | function timeFormat(time, options) {
  function isInFullScreenMode (line 162) | function isInFullScreenMode() {
  function getTypeFromFileExtension (line 167) | function getTypeFromFileExtension(url) {
  function getType (line 195) | function getType(url, type) {
  function detectType (line 212) | function detectType(media, options, src) {
  function togglePlayPause (line 565) | function togglePlayPause(s) {

FILE: src/directives/inview/index.js
  method update (line 3) | update (option) {
  method unbind (line 20) | unbind () {}

FILE: src/directives/inview/inview.js
  function InView (line 26) | function InView (el, callback, className) {
  function throttle (line 56) | function throttle (fn, threshhold, scope) {
  function hasClass (line 79) | function hasClass (el, name) {
  function addClass (line 83) | function addClass (el, name) {
  function removeClass (line 90) | function removeClass (el, name) {
  function addEvent (line 101) | function addEvent (el, name, fn) {
  function getScrollTop (line 109) | function getScrollTop () {
  function isInView (line 120) | function isInView (obj) {

FILE: src/libs/base.js
  method created (line 11) | created () {
  method dirty (line 15) | dirty () {
  method invalid (line 18) | invalid () {
  method setTouched (line 23) | setTouched () {
  method value (line 28) | value (newVal) {
  method data (line 38) | data () {

FILE: src/libs/eventor.js
  function Events (line 19) | function Events () {
  function copyProto (line 159) | function copyProto (key) {
  function triggerEvents (line 168) | function triggerEvents (list, args, context) {
  function isFunction (line 191) | function isFunction (func) {

FILE: src/libs/mixin_uuid.js
  method created (line 2) | created () {

FILE: src/libs/router.js
  function go (line 1) | function go (url, $router) {
  function getUrl (line 11) | function getUrl (url, $router) {

FILE: src/main.js
  function saveDemoScrollTop (line 64) | function saveDemoScrollTop () {

FILE: src/mixins/multi-items.js
  method mounted (line 2) | mounted() {
  method updateIndex (line 6) | updateIndex() {
  method index (line 25) | index(val, oldVal) {
  method data (line 30) | data() {
  method mounted (line 44) | mounted() {
  method beforeDestroy (line 47) | beforeDestroy() {
  method onItemClick (line 54) | onItemClick() {
  method selected (line 63) | selected(val) {
  method data (line 71) | data() {

FILE: src/plugins/alert/index.js
  method install (line 7) | install (vue) {

FILE: src/plugins/toast/index.js
  method install (line 7) | install (vue, options) {

FILE: src/vuex/store.js
  method UPDATE_LOADING (line 13) | UPDATE_LOADING (state, status) {
  method UPDATE_DIRECTION (line 16) | UPDATE_DIRECTION (state, direction) {
Condensed preview — 385 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,123K chars).
[
  {
    "path": ".babelrc",
    "chars": 99,
    "preview": "{\n  \t\"presets\": [\"es2015\", \"stage-2\"],\n  \t\"plugins\": [\"transform-runtime\"],\n  \t\"comments\": false\n}\n"
  },
  {
    "path": ".editorconfig",
    "chars": 147,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".gitignore",
    "chars": 120,
    "preview": ".DS_Store\nnode_modules/\ndist/\nnpm-debug.log\ntest/unit/coverage\ntest/e2e/reports\nselenium-debug.log\nnode_modules/\n.idea/\n"
  },
  {
    "path": ".npmrc",
    "chars": 159,
    "preview": "sass_binary_site=https://npm.taobao.org/mirrors/node-sass/\nphantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/\nre"
  },
  {
    "path": "LICENSE",
    "chars": 1057,
    "preview": "MIT License\n\nCopyright (c) 2016 \n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this s"
  },
  {
    "path": "README.md",
    "chars": 1146,
    "preview": "# vux-2.0\n根据vux-https://github.com/airyland/vux 修改升级的2.0\n\n## Docs\n\n+ [中文文档](https://jinhuiwong.gitbooks.io/vuxx/content/"
  },
  {
    "path": "build/build.js",
    "chars": 897,
    "preview": "// https://github.com/shelljs/shelljs\nrequire('./check-versions')()\nrequire('shelljs/global')\nenv.NODE_ENV = 'production"
  },
  {
    "path": "build/check-versions.js",
    "chars": 1182,
    "preview": "var semver = require('semver')\nvar chalk = require('chalk')\nvar packageConfig = require('../package.json')\nvar exec = fu"
  },
  {
    "path": "build/dev-client.js",
    "chars": 245,
    "preview": "/* eslint-disable */\nrequire('eventsource-polyfill')\nvar hotClient = require('webpack-hot-middleware/client?noInfo=true&"
  },
  {
    "path": "build/dev-server.js",
    "chars": 2527,
    "preview": "require('./check-versions')();\nvar config = require('../config');\nif (!process.env.NODE_ENV) process.env.NODE_ENV = conf"
  },
  {
    "path": "build/utils.js",
    "chars": 1951,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar ExtractTextPlugin = require('extract-text-webpack-plugi"
  },
  {
    "path": "build/webpack.base.conf.js",
    "chars": 2322,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar utils = require('./utils')\nvar projectRoot = path.resol"
  },
  {
    "path": "build/webpack.dev.conf.js",
    "chars": 1143,
    "preview": "var config = require('../config')\nvar webpack = require('webpack')\nvar merge = require('webpack-merge')\nvar utils = requ"
  },
  {
    "path": "build/webpack.prod.conf.js",
    "chars": 3273,
    "preview": "var path = require('path')\nvar config = require('../config')\nvar utils = require('./utils')\nvar webpack = require('webpa"
  },
  {
    "path": "config/dev.env.js",
    "chars": 139,
    "preview": "var merge = require('webpack-merge')\nvar prodEnv = require('./prod.env')\n\nmodule.exports = merge(prodEnv, {\n  NODE_ENV: "
  },
  {
    "path": "config/index.js",
    "chars": 1163,
    "preview": "// see http://vuejs-templates.github.io/webpack for documentation.\nvar path = require('path')\n\nmodule.exports = {\n  buil"
  },
  {
    "path": "config/prod.env.js",
    "chars": 48,
    "preview": "module.exports = {\n  NODE_ENV: '\"production\"'\n}\n"
  },
  {
    "path": "config/test.env.js",
    "chars": 132,
    "preview": "var merge = require('webpack-merge')\nvar devEnv = require('./dev.env')\n\nmodule.exports = merge(devEnv, {\n  NODE_ENV: '\"t"
  },
  {
    "path": "index.html",
    "chars": 437,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width,initial"
  },
  {
    "path": "package.json",
    "chars": 3209,
    "preview": "{\n  \"name\": \"vuxx\",\n  \"version\": \"0.1.7\",\n  \"description\": \"vux2.0 project\",\n  \"author\": \"wong <405176029@qq.com>\",\n  \"r"
  },
  {
    "path": "src/App.vue",
    "chars": 5281,
    "preview": "<template>\n  <div style=\"height:100%;\">\n    <!-- <loading :show=\"isLoading\" position=\"absolute\"></loading> -->\n    <load"
  },
  {
    "path": "src/Home.vue",
    "chars": 2142,
    "preview": "<template>\n  <div>\n    <div class=\"center\">\n      <svg style=\"width:60px;height:60px;\" version=\"1.1\" id=\"图形\" xmlns=\"http"
  },
  {
    "path": "src/Wechat.vue",
    "chars": 1202,
    "preview": "<template>\n  <div>\n    <group>\n      <cell title=\"接收新消息通知\" value=\"已启用\"></cell>\n    </group>\n    <tip>如果你要关闭或开启微信的新消息通知,请"
  },
  {
    "path": "src/components/actionsheet/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/actionsheet/index.vue",
    "chars": 2805,
    "preview": "<template>\n  <div class=\"vux-actionsheet\">\n    <div class=\"weui_mask_transition\" :class=\"{'weui_fade_toggle': props_show"
  },
  {
    "path": "src/components/actionsheet/metas.yml",
    "chars": 794,
    "preview": "props:\n  show:\n    en: if show the component\n    zh-CN: 是否显示\n  show-cancel:\n    en: if show the cancel menu\n    zh-CN: 是"
  },
  {
    "path": "src/components/alert/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/alert/index.vue",
    "chars": 1646,
    "preview": "<template>\n  <div class=\"vux-alert\">\n    <input style=\"display:none\" v-model=\"props_show\">\n    <x-dialog\n    class=\"weui"
  },
  {
    "path": "src/components/alert/metas.yml",
    "chars": 485,
    "preview": "extends:\n  - Dialog\nwhen:\n  -\n    - en: Show some information that user should pay attention to and should be closed onl"
  },
  {
    "path": "src/components/badge/index.vue",
    "chars": 554,
    "preview": "<template>\n  <span v-text=\"text\" :class=\"['vux-badge', {'vux-badge-single': text.length === 1}]\"></span>\n</template>\n\n<s"
  },
  {
    "path": "src/components/badge/metas.yml",
    "chars": 58,
    "preview": "props:\n  text:\n    en: text of the Badge\n    zh-CN: 显示的文字\n"
  },
  {
    "path": "src/components/blur/blur.js",
    "chars": 8369,
    "preview": "/* Image Blur plugin, author @msurguy\n\n Usage:\n\n Create a set of elements that follows the following HTML structure:\n\n <"
  },
  {
    "path": "src/components/blur/index.vue",
    "chars": 1606,
    "preview": "<template>\n  <div :style=\"{height: height + 'px',position: 'relative', overflow: 'hidden'}\">\n    <slot></slot>\n  </div>\n"
  },
  {
    "path": "src/components/blur/metas.yml",
    "chars": 434,
    "preview": "tips:\n  -\n    - en: If the component renders slowly on your target platform, you can try `css3 blur filter`\n    - zh-CN:"
  },
  {
    "path": "src/components/box/index.vue",
    "chars": 142,
    "preview": "<template>\n  <div :style=\"{margin:gap}\"><slot></slot></div>\n</template>\n\n<script>\nexport default {\n  props: {\n    gap: S"
  },
  {
    "path": "src/components/box/metas.yml",
    "chars": 168,
    "preview": "intro:\n  en: a small component for lazy persons who don't want to write less code\n  zh-CN: 为div设置margin值,懒人才需要的组件\nprops:"
  },
  {
    "path": "src/components/button-tab/button-tab-item.vue",
    "chars": 1472,
    "preview": "<template>\n  <a class=\"vux-button-tab-item\" :class=\"classes\" href=\"javascript:\" :style=\"style\" @click=\"onItemClick\">\n   "
  },
  {
    "path": "src/components/button-tab/button-tab.vue",
    "chars": 2462,
    "preview": "<template>\n  <div class=\"vux-button-group\">\n    <slot></slot>\n  </div>\n</template>\n\n<script>\n\nexport default {\n  mounted"
  },
  {
    "path": "src/components/button-tab/index.js",
    "chars": 124,
    "preview": "import ButtonTab from './button-tab'\nimport ButtonTabItem from './button-tab-item'\n\nexport {\n  ButtonTab,\n  ButtonTabIte"
  },
  {
    "path": "src/components/button-tab/metas.yml",
    "chars": 197,
    "preview": "button-tab:\n  props:\n    index:\n      zh-CN: 当前选中索引值,从0开始\n    height:\n      zh-CN: 高度值\nbutton-tab-item:\n  props:\n    sel"
  },
  {
    "path": "src/components/calendar/index.vue",
    "chars": 1493,
    "preview": "<template>\n<div>\n  <cell :title=\"title\" primary=\"content\" :value=\"props_value\" @click=\"onClick\" is-link></cell>\n  <popup"
  },
  {
    "path": "src/components/calendar/metas.yml",
    "chars": 207,
    "preview": "extends:\n  - inline-calendar\n  - popup\n  - cell\nintro:\n  zh-CN: 扩展自inline-calendar, 相关属性可查看inline-calendar文档\nprops:\n  va"
  },
  {
    "path": "src/components/card/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/card/index.vue",
    "chars": 871,
    "preview": "<template>\n\t<div class=\"weui_panel weui_panel_access\">\n    <div class=\"weui_panel_hd\" v-if=\"header && header.title\" v-ht"
  },
  {
    "path": "src/components/card/metas.yml",
    "chars": 306,
    "preview": "props:\n  header.title:\n    zh-CN: 头部标题,不指定则不显示\n  footer.title:\n    zh-CN: 底部标题,不指定则不显示\n  footer.link:\n    zh-CN: 底部链接,普通"
  },
  {
    "path": "src/components/cell/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/cell/index.vue",
    "chars": 1674,
    "preview": "<template>\n  <div class=\"weui_cell\" :class=\"{'vux-tap-active': isLink || !!link}\" @click=\"onClick\">\n    <div class=\"weui"
  },
  {
    "path": "src/components/cell/metas.yml",
    "chars": 946,
    "preview": "props:\n  title:\n    en: label text\n    zh-CN: 左边标题文字\n  value:\n    en: right text\n    zh-CN: 右侧文字,复杂的样式布局请使用slot\n  inline"
  },
  {
    "path": "src/components/check-icon/index.vue",
    "chars": 845,
    "preview": "<template>\n  <div class=\"vux-check-icon\" @click=\"value = !value\">\n    <icon type=\"success\" v-show=\"type === 'default' &&"
  },
  {
    "path": "src/components/checker/checker-item.vue",
    "chars": 1937,
    "preview": "<template>\n  <div class=\"vux-checker-item\" :class=\"classNames\" @click=\"select\">\n    <slot></slot>\n  </div>\n</template>\n\n"
  },
  {
    "path": "src/components/checker/checker.vue",
    "chars": 639,
    "preview": "<template>\n  <div class=\"vux-checker-box\">\n    <slot></slot>\n  </div>\n</template>\n\n<script>\nexport default {\n  props: {\n"
  },
  {
    "path": "src/components/checker/index.js",
    "chars": 110,
    "preview": "import Checker from './checker'\nimport CheckerItem from './checker-item'\n\nexport {\n  Checker,\n  CheckerItem\n}\n"
  },
  {
    "path": "src/components/checker/metas.yml",
    "chars": 479,
    "preview": "checker:\n  props:\n    default-item-class:\n      zh-CN: 默认class\n    selected-item-class:\n      zh-CN: 选中样式\n    disabled-i"
  },
  {
    "path": "src/components/checklist/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/checklist/index.vue",
    "chars": 3778,
    "preview": "<template>\n<div>\n  <div v-show=\"title\" class=\"weui_cells_title\">{{title}}</div>\n  <div class=\"weui_cells weui_cells_chec"
  },
  {
    "path": "src/components/checklist/metas.yml",
    "chars": 319,
    "preview": "props:\n  value:\n    zh-CN: 表单值\n  title:\n    zh-CN: 标题\n  required:\n    zh-CN: 是否为必填\n  options:\n    zh-CN: 选项列表,可以为`[{name"
  },
  {
    "path": "src/components/checklist/object-filter.js",
    "chars": 193,
    "preview": "export const getValue = function (item) {\n  return typeof item === 'object' ? item.value : item\n}\n\nexport const getKey ="
  },
  {
    "path": "src/components/circle/index.vue",
    "chars": 1671,
    "preview": "<template>\n  <div class=\"vux-circle\">\n    <svg viewBox=\"0 0 100 100\">\n      <path :d=\"pathString\" :stroke=\"trailColor\" :"
  },
  {
    "path": "src/components/circle/metas.yml",
    "chars": 164,
    "preview": "props:\n  stroke-width:\n    zh-CN: 线条宽度\n  stoke-color:\n    zh-CN: 线条颜色\n  trail-width:\n    zh-CN: 背景线条宽度\n  trail-color:\n  "
  },
  {
    "path": "src/components/clocker/clocker.js",
    "chars": 6658,
    "preview": "// https://github.com/MoeKit/clocker\nvar instances = []\nvar matchers = []\n// Miliseconds\nmatchers.push(/^[0-9]*$/.source"
  },
  {
    "path": "src/components/clocker/index.vue",
    "chars": 1527,
    "preview": "<template>\n  <div style=\"display:inline-block;\">\n    <span v-if=\"showTimeString\">{{timeString}}</span>\n    <div class=\"v"
  },
  {
    "path": "src/components/clocker/metas.yml",
    "chars": 348,
    "preview": "props:\n  time:\n    en: the end time\n    zh-CN: 结束时间\n  format:\n    en: the result format\n    zh-CN: 显示格式\nevents:\n  on-tic"
  },
  {
    "path": "src/components/color-picker/index.vue",
    "chars": 2246,
    "preview": "<template>\n  <div class=\"vux-color-picker\">\n    <input style=\"display:none\" v-model=\"props_value\">\n    <flexbox>\n      <"
  },
  {
    "path": "src/components/confirm/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/confirm/index.vue",
    "chars": 1913,
    "preview": "<template>\n  <div>\n    <x-dialog class=\"weui_dialog_confirm\"\n    :show=\"props_show\"\n    :mask-transition=\"maskTransition"
  },
  {
    "path": "src/components/confirm/metas.yml",
    "chars": 681,
    "preview": "tags:\n  en:\n    - message\n    - confirm\n  zh-CN:\n    - 消息提示\n    - 确认\nprops:\n  show:\n    en: visibility of the component\n"
  },
  {
    "path": "src/components/countdown/index.vue",
    "chars": 1299,
    "preview": "<template>\n  <span>{{props_time}}<input style=\"display:none\" v-model=\"props_time\"></span>\n</template>\n\n<script>\nexport d"
  },
  {
    "path": "src/components/countup/index.vue",
    "chars": 766,
    "preview": "<template>\n  <span>{{startVal}}</span>\n</template>\n\n<script>\nimport Countup from 'countup'\n\nexport default {\n  mounted ("
  },
  {
    "path": "src/components/datetime/datetimepicker.js",
    "chars": 8998,
    "preview": "import Scroller from '../picker/scroller'\nimport { each, trimZero, addZero, getMaxDay, parseRow, parseDate, getElement, "
  },
  {
    "path": "src/components/datetime/format.js",
    "chars": 1021,
    "preview": "module.exports = function (date, fmt = 'YYYY-MM-DD HH:mm:ss') {\n  var o = {\n    'M+': date.getMonth() + 1,\n    'D+': dat"
  },
  {
    "path": "src/components/datetime/index.vue",
    "chars": 5324,
    "preview": "<template>\n  <a class=\"weui_cell\" href=\"javascript:\">\n    <input style=\"display:none\" v-model=\"props_value\">\n    <div cl"
  },
  {
    "path": "src/components/datetime/util.js",
    "chars": 1728,
    "preview": "import formater from './format'\n\nexport function each (obj, fn) {\n  for (var key in obj) {\n    if (obj.hasOwnProperty(ke"
  },
  {
    "path": "src/components/dev-tip/index.vue",
    "chars": 217,
    "preview": "<template>\n  <div class=\"vux-dev-tip\">\n    <slot></slot>\n  </div>\n</template>\n\n<style>\n.vux-dev-tip {\n  padding:5px 10px"
  },
  {
    "path": "src/components/dialog/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/dialog/index.vue",
    "chars": 1543,
    "preview": "<template>\n  <div class=\"weui_dialog_alert fix_ios_fixed\" @touchmove=\"onTouchMove\" v-show=\"props_show\">\n    <transition "
  },
  {
    "path": "src/components/divider/index.vue",
    "chars": 1880,
    "preview": "<template>\n  <p class=\"vux-divider\">\n    <slot></slot>\n  </p>\n</template>\n\n<style>\n.vux-divider {\n  display: table;\n  wh"
  },
  {
    "path": "src/components/divider/metas.yml",
    "chars": 190,
    "preview": "tips:\n  -\n    en: cannot custom line color for the moment\n    zh-CN: 暂时不可定义分割线颜色\nslots:\n  default:\n    en: divider title"
  },
  {
    "path": "src/components/flexbox/flexbox-item.vue",
    "chars": 1149,
    "preview": "<template>\n  <div class=\"vux-flexbox-item\" :style=\"style\">\n    <slot></slot>\n  </div>\n</template>\n\n<script>\nconst prefix"
  },
  {
    "path": "src/components/flexbox/flexbox.vue",
    "chars": 1242,
    "preview": "<template>\n  <div class=\"vux-flexbox\" :class=\"{'vux-flex-col': orient === 'vertical', 'vux-flex-row': orient === 'horizo"
  },
  {
    "path": "src/components/flexbox/index.js",
    "chars": 110,
    "preview": "import Flexbox from './flexbox'\nimport FlexboxItem from './flexbox-item'\n\nexport {\n  Flexbox,\n  FlexboxItem\n}\n"
  },
  {
    "path": "src/components/fullpage/DemoBasic.vue",
    "chars": 824,
    "preview": "<template>\n  <div>\n    <fullpage\n    class=\"fullpage-demo\"\n    drag\n    :start=\"0\"\n    :duration=\"100\"\n    @on-change=\"o"
  },
  {
    "path": "src/components/fullpage/index.vue",
    "chars": 1428,
    "preview": "<template>\n  <div>\n    <slot></slot>\n  </div>\n</template>\n\n<script>\nimport Fullpage from './lib'\n\nexport default {\n  rea"
  },
  {
    "path": "src/components/fullpage/lib.js",
    "chars": 6463,
    "preview": "/*!\n * zepto.fullpage.js v0.5.0 (https://github.com/yanhaijing/zepto.fullpage)\n * API https://github.com/yanhaijing/zept"
  },
  {
    "path": "src/components/group/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/group/index.md",
    "chars": 191,
    "preview": "[zh-CN]\n`Group`是一个特殊的表单`wrapper`组件,主要用于将表单分组,单个表单元素也算一组。所以常见的`行内`组件都`必须`作为`Group`的子组件。\n\n包括:\n\n+ Cell\n+ XInput\n+ XTextarea"
  },
  {
    "path": "src/components/group/index.vue",
    "chars": 727,
    "preview": "<template>\n  <div>\n    <div class=\"weui_cells_title\" v-if=\"title\" :style=\"{color:titleColor}\" v-html=\"title\"></div>\n    "
  },
  {
    "path": "src/components/group/metas.yml",
    "chars": 571,
    "preview": "props:\n  title:\n    en: group title\n    zh-CN:分组标题\n  titleColor:\n    en: group title's color\n    zh-CN: 分组标题文字颜色\n  label"
  },
  {
    "path": "src/components/group-title/index.vue",
    "chars": 83,
    "preview": "<template>\n  <div class=\"weui_cells_title\">\n    <slot></slot>\n  </div>\n</template>\n"
  },
  {
    "path": "src/components/icon/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/icon/index.md",
    "chars": 782,
    "preview": "```\n<template>\n  <div>\n    <icon type=\"success\"></icon>\n    <icon type=\"info\"></icon>\n    <icon type=\"info_circle\"></ico"
  },
  {
    "path": "src/components/icon/index.vue",
    "chars": 379,
    "preview": "<template>\n  <i :class=\"className\"></i>\n</template>\n\n<script>\nexport default {\n  props: {\n    type: String\n  },\n  comput"
  },
  {
    "path": "src/components/icon/metas.yml",
    "chars": 58,
    "preview": "props:\n  type:\n    en: icon name\n    zh-CN: 图标名字,可选值见demo\n"
  },
  {
    "path": "src/components/index.js",
    "chars": 3751,
    "preview": "/* only for building vux.css */\nimport Style from '../styles/index.vue' // eslint-disable-line\n\nimport Radio from './rad"
  },
  {
    "path": "src/components/inline-calendar/index.vue",
    "chars": 9326,
    "preview": "<template>\n  <div class=\"inline-calendar\" :class=\"{'is-weekend-highlight': highlightWeekend}\">\n    <div class=\"calendar-"
  },
  {
    "path": "src/components/inline-calendar/metas.yml",
    "chars": 928,
    "preview": "props:\n  value:\n    en:\n    zh-CN: 当前选中日期,双向绑定,默认为空,即选中当天日期\n  render-month:\n    en:\n    zh-CN: 指定渲染日期,如 [2018, 8]\n  star"
  },
  {
    "path": "src/components/inline-calendar/props.js",
    "chars": 1053,
    "preview": "export default () => ({\n  value: {\n    type: String,\n    default: ''\n  },\n  renderMonth: {\n    type: Array, // [2018, 8]"
  },
  {
    "path": "src/components/inline-calendar/util.js",
    "chars": 4625,
    "preview": "import format from '../datetime/format'\n\nexport function zero (n) {\n  return n < 10 ? '0' + n : n\n}\n\nexport function spl"
  },
  {
    "path": "src/components/inline-desc/index.vue",
    "chars": 145,
    "preview": "<template>\n  <span class=\"vux-label-desc\"><slot></slot></span>\n</template>\n\n<style>\n.vux-label-desc {\n  font-size:14px;\n"
  },
  {
    "path": "src/components/inline-desc/metas.yml",
    "chars": 152,
    "preview": "intro:\n  en: it is the child component of cell, you cannot use it alone\n  zh-CN: cell的子组件,不能单独使用\nslots:\n  default:\n    e"
  },
  {
    "path": "src/components/inline-x-number/index.vue",
    "chars": 2229,
    "preview": "<template>\n  <div>\n    <a @click=\"sub\" class=\"vux-number-selector vux-number-selector-sub\":class=\"{'vux-number-disabled'"
  },
  {
    "path": "src/components/loading/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/loading/index.vue",
    "chars": 3193,
    "preview": "<template>\n  <div class=\"weui_loading_toast\" v-show=\"show\">\n    <div class=\"weui_mask_transparent\"></div>\n    <div class"
  },
  {
    "path": "src/components/loading/metas.yml",
    "chars": 296,
    "preview": "props:\n  show:\n    en: visibility of the component\n    zh-CN: 显示状态\n  text:\n    en: loading text\n    zh-CN: 提示文字\n  positi"
  },
  {
    "path": "src/components/masker/converter.js",
    "chars": 335,
    "preview": "/*!\n * HEX <=> RGB Conversion\n * Copyright(c) 2011 Daniel Lamb <daniellmb.com>\n * MIT Licensed\n */\n\nexport function toRG"
  },
  {
    "path": "src/components/masker/index.vue",
    "chars": 777,
    "preview": "<template>\n  <div class=\"vux-masker-box\">\n    <slot></slot>\n    <div class=\"vux-masker\" :style=\"style\">\n      <slot name"
  },
  {
    "path": "src/components/masker/metas.yml",
    "chars": 317,
    "preview": "props:\n  color:\n    en: the mask's color in rgb format, for example, '0, 0, 0'\n    zh-CN: 遮罩颜色,rgb值,'0, 0, 0'\n  opacity:"
  },
  {
    "path": "src/components/number-roller/index.vue",
    "chars": 623,
    "preview": "<template>\n  <div style=\"height:100px;font-size:100px;\"></div>\n</template>\n\n<script>\nimport Roller from './lib'\n\nexport "
  },
  {
    "path": "src/components/number-roller/lib.js",
    "chars": 2228,
    "preview": "const Roller = class {\n  constructor (opts) {\n    this.container = typeof opts.container === 'string' ? document.querySe"
  },
  {
    "path": "src/components/orientation/index.js",
    "chars": 593,
    "preview": "/**\n * v-orientaion=\"landscape\" v-orientaion=\"portrait\"\n */\nimport Orientation from './orientation'\nexport default {\n  b"
  },
  {
    "path": "src/components/orientation/orientation.js",
    "chars": 4480,
    "preview": "/**\n * 横竖屏切换监听器\n * @author ningzbruc@gmail.com\n * @gitbub http://gitbub.com/kingback/orientation/\n * @date 2014-01-15\n *"
  },
  {
    "path": "src/components/panel/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/panel/index.vue",
    "chars": 2494,
    "preview": "<template>\n  <div class=\"weui_panel weui_panel_access\">\n    <div class=\"weui_panel_hd\" v-if=\"header\" @click=\"onClickHead"
  },
  {
    "path": "src/components/picker/animate.js",
    "chars": 4136,
    "preview": "const time = Date.now || function () {\n  return +new Date()\n}\n\nlet running = {}\nlet counter = 1\nlet desiredFrames = 60\nl"
  },
  {
    "path": "src/components/picker/chain.js",
    "chars": 1560,
    "preview": "import filter from 'array-filter'\n\nconst Manager = class {\n  constructor (data, count, fixedColumns) {\n    this.data = d"
  },
  {
    "path": "src/components/picker/index.vue",
    "chars": 5827,
    "preview": "<template>\n  <div class=\"vux-picker\">\n    <flexbox :gutter=\"0\">\n      <flexbox-item v-for=\"(one, index) in props_data\" s"
  },
  {
    "path": "src/components/picker/metas.yml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/components/picker/scroller.css",
    "chars": 1578,
    "preview": ".scroller-component {\n  display: block;\n  position: relative;\n  height: 238px;\n  overflow: hidden;\n  width: 100%;\n}\n\n.sc"
  },
  {
    "path": "src/components/picker/scroller.js",
    "chars": 15944,
    "preview": "/*\n * Anima Scroller\n * Based Zynga Scroller (http://github.com/zynga/scroller)\n * Copyright 2011, Zynga Inc.\n * License"
  },
  {
    "path": "src/components/picker/util.js",
    "chars": 575,
    "preview": "export function getElement (expr) {\n  return (typeof expr === 'string') ? document.querySelector(expr) : expr\n}\n\nexport "
  },
  {
    "path": "src/components/popover/DemoIndex.vue",
    "chars": 1275,
    "preview": "<template>\n  <div>\n    <popover placement=\"top\" style=\"margin: 20px;\" @on-show=\"onShow\" @on-hide=\"onHide\">\n      <div sl"
  },
  {
    "path": "src/components/popover/index.vue",
    "chars": 4345,
    "preview": "<template>\n  <div v-click-outside=\"onClickedOutside\">\n    <span ref=\"trigger\">\n      <slot>\n      </slot>\n    </span>\n  "
  },
  {
    "path": "src/components/popover/metas.yml",
    "chars": 614,
    "preview": "keywords:\n  - popover\n  - float menu\n  - tooltip\n  - 弹窗\n  - 菜单\nprops:\n  content:\n    en: content of the popover\n    zh-C"
  },
  {
    "path": "src/components/popup/index.vue",
    "chars": 2944,
    "preview": "<template>\n    <transition  name=\"vux-popup\" >\n      <div v-show=\"props_show\" :style=\"{height:height}\" class=\"vux-popup "
  },
  {
    "path": "src/components/popup/popup.js",
    "chars": 2835,
    "preview": "// not a good way but works well\nwindow.__$vuxPopups = window.__$vuxPopups || {}\nconst popupDialog = function (option) {"
  },
  {
    "path": "src/components/popup-picker/index.vue",
    "chars": 4484,
    "preview": "<template>\n  <div>\n    <cell v-show=\"showCell\" :title=\"title\" primary=\"content\" is-link :inline-desc=\"inlineDesc\" @click"
  },
  {
    "path": "src/components/previewer/component.json",
    "chars": 47,
    "preview": "{\n\t\"tags\": [\"swipephoto\", \"swipe\", \"preview\"]\n}"
  },
  {
    "path": "src/components/previewer/index.vue",
    "chars": 3287,
    "preview": "<template>\n  <!-- Root element of PhotoSwipe. Must have class pswp. -->\n  <div class=\"pswp vux-previewer\" tabindex=\"-1\" "
  },
  {
    "path": "src/components/progress/index.vue",
    "chars": 737,
    "preview": "<template>\n  <div class=\"weui_progress\">\n    <div class=\"weui_progress_bar\">\n      <div class=\"weui_progress_inner_bar j"
  },
  {
    "path": "src/components/progress/metas.yml",
    "chars": 240,
    "preview": "props:\n  percent:\n    en: percent of the progress, 0-100\n    zh-CN: 进度值,0到100\n  show-cancel:\n    en: if show the cancel "
  },
  {
    "path": "src/components/qrcode/index.vue",
    "chars": 1985,
    "preview": "<template>\n  <canvas\n  :style=\"{height: size, width: size}\"\n  :height=\"size\"\n  :width=\"size\"></canvas>\n</template>\n\n<scr"
  },
  {
    "path": "src/components/qrcode/metas.yml",
    "chars": 134,
    "preview": "props:\n  value:\n    zh-CN: 编码内容,如果为链接,请保证有http(s)协议名\n  size:\n    zh-CN: 尺寸大小\n  bg-color:\n    zh-CN: 背景颜色\n  fg-color:\n   "
  },
  {
    "path": "src/components/radio/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/radio/index.vue",
    "chars": 2625,
    "preview": "<template>\n  <div class=\"weui_cells_radio\">\n    <label class=\"weui_cell weui_cell_radio weui_check_label\" :for=\"'radio_'"
  },
  {
    "path": "src/components/range/index.vue",
    "chars": 2417,
    "preview": "<template>\n  <div class=\"vux-range-input-box\" style=\"position:relative;margin-right:30px;margin-left:50px;\">\n    <input "
  },
  {
    "path": "src/components/range/powerange.less",
    "chars": 1120,
    "preview": "/**\n *\n * Main stylesheet for Powerange.\n * http://abpetkov.github.io/powerange/\n *\n */\n\n/**\n * Horizontal slider style "
  },
  {
    "path": "src/components/range/range/lib/horizontal.js",
    "chars": 2780,
    "preview": "/**\n * External dependencies.\n *\n */\n\nvar inherits = require('./lib/super')\nvar closest = require('./lib/closest-num')\nv"
  },
  {
    "path": "src/components/range/range/lib/lib/classes.js",
    "chars": 3269,
    "preview": "/**\n * Module dependencies.\n */\n\nvar index = require('./indexof')\n\n/**\n * Whitespace regexp.\n */\n\nvar re = /\\s+/\n\n/**\n *"
  },
  {
    "path": "src/components/range/range/lib/lib/closest-num.js",
    "chars": 705,
    "preview": "/**\n * Closest-num 0.0.1\n * https://github.com/abpetkov/closest-num\n *\n * Author: Alexander Petkov\n * https://github.com"
  },
  {
    "path": "src/components/range/range/lib/lib/closest.js",
    "chars": 522,
    "preview": "/**\n * Module Dependencies\n */\n\nvar matches = require('./matches-selector')\n\n/**\n * Export `closest`\n */\n\nmodule.exports"
  },
  {
    "path": "src/components/range/range/lib/lib/delegate.js",
    "chars": 931,
    "preview": "/**\n * Module dependencies.\n */\n\nvar closest = require('./closest')\nvar event = require('./event')\n\n/**\n * Delegate even"
  },
  {
    "path": "src/components/range/range/lib/lib/emitter.js",
    "chars": 2945,
    "preview": "\n/**\n * Expose `Emitter`.\n */\n\nmodule.exports = Emitter\n\n/**\n * Initialize a new `Emitter`.\n *\n * @api public\n */\n\nfunct"
  },
  {
    "path": "src/components/range/range/lib/lib/event.js",
    "chars": 811,
    "preview": "var bind = window.addEventListener ? 'addEventListener' : 'attachEvent'\nvar unbind = window.removeEventListener ? 'remov"
  },
  {
    "path": "src/components/range/range/lib/lib/events.js",
    "chars": 3465,
    "preview": "/**\n * Module dependencies.\n */\n\nvar events = require('./event')\nvar delegate = require('./delegate')\n\n/**\n * Expose `Ev"
  },
  {
    "path": "src/components/range/range/lib/lib/indexof.js",
    "chars": 174,
    "preview": "module.exports = function (arr, obj) {\n  if (arr.indexOf) return arr.indexOf(obj)\n  for (var i = 0; i < arr.length; ++i)"
  },
  {
    "path": "src/components/range/range/lib/lib/matches-selector.js",
    "chars": 752,
    "preview": "/**\n * Module dependencies.\n */\n\nvar query = require('./query')\n\n/**\n * Element prototype.\n */\n\nvar proto = Element.prot"
  },
  {
    "path": "src/components/range/range/lib/lib/mouse.js",
    "chars": 1235,
    "preview": "\n/**\n * dependencies.\n */\n\nvar emitter = require('./emitter')\nvar event = require('./event')\n\n/**\n * export `Mouse`\n */\n"
  },
  {
    "path": "src/components/range/range/lib/lib/percentage-calc.js",
    "chars": 979,
    "preview": "\n/**\n * Percentage-Calc 0.0.1\n * https://github.com/abpetkov/percentage-calc\n *\n * Authored by Alexander Petkov\n * https"
  },
  {
    "path": "src/components/range/range/lib/lib/query.js",
    "chars": 490,
    "preview": "function one (selector, el) {\n  return el.querySelector(selector)\n}\n\nexports = module.exports = function (selector, el) "
  },
  {
    "path": "src/components/range/range/lib/lib/super.js",
    "chars": 2703,
    "preview": "/**\n * slice\n */\n\nvar slice = Array.prototype.slice\n\n/**\n * Primary export\n */\n\nvar exports = module.exports = super_\n\n/"
  },
  {
    "path": "src/components/range/range/lib/main.js",
    "chars": 6533,
    "preview": "/**\n * External dependencies.\n *\n */\n\nvar mouse = require('./lib/mouse')\nvar events = require('./lib/events')\nvar classe"
  },
  {
    "path": "src/components/range/range/lib/powerange.js",
    "chars": 573,
    "preview": "/**\n * Require classes.\n */\n\nvar Horizontal = require('./horizontal')\n\n/**\n * Set default values.\n *\n * @api public\n */\n"
  },
  {
    "path": "src/components/rater/index.vue",
    "chars": 2826,
    "preview": "<template>\n  <div class=\"vux-rater\">\n    <input v-model=\"props_value\" style=\"display:none\">\n    <a class=\"vux-rater-box\""
  },
  {
    "path": "src/components/scroller/index.vue",
    "chars": 8125,
    "preview": "<template>\n  <div :style=\"styles\">\n    <div class=\"xs-container\">\n      <slot></slot>\n      <slot name=\"pulldown\"></slot"
  },
  {
    "path": "src/components/search/index.vue",
    "chars": 3615,
    "preview": "<template>\n  <div class=\"vux-search-box\" :class=\"{'vux-search-fixed':isFixed}\" :style=\"{top: isFixed ? top : ''}\">\n    <"
  },
  {
    "path": "src/components/selector/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/selector/index.vue",
    "chars": 2332,
    "preview": "<template>\n  <div class=\"weui_cell\" :class=\"{'weui_select_after':title, 'weui_cell_select':!readonly}\">\n    <div class=\""
  },
  {
    "path": "src/components/selector/metas.yml",
    "chars": 103,
    "preview": "tips:\n  -\n    - en: key should be a `String` if you use key=>value\n    - zh-CN: 选项的key必须是字符串,使用数字会出现问题\n"
  },
  {
    "path": "src/components/shake/index.vue",
    "chars": 797,
    "preview": "<template>\n  <div style=\"display:none\"></div>\n</template>\n\n<script>\nimport Shake from 'shake.js'\nexport default {\n  prop"
  },
  {
    "path": "src/components/spinner/index.vue",
    "chars": 1183,
    "preview": "<template>\n  <span class=\"vux-spinner\" :class=\"className\"></span>\n</template>\n\n<script>\nimport Spinner from './spinner'\n"
  },
  {
    "path": "src/components/spinner/requestAnimationFrame.js",
    "chars": 808,
    "preview": "var lastTime = 0\nvar vendors = ['webkit', 'moz']\nfor (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++"
  },
  {
    "path": "src/components/spinner/spinner.js",
    "chars": 8831,
    "preview": "/**\n* http://ionicframework.com/docs/api/directive/ionSpinner/\n*/\n\nimport './requestAnimationFrame'\n\nvar TRANSLATE32 = '"
  },
  {
    "path": "src/components/step/index.js",
    "chars": 92,
    "preview": "import Step from './step'\nimport StepItem from './step-item'\n\nexport {\n  Step,\n  StepItem\n}\n"
  },
  {
    "path": "src/components/step/step-item.vue",
    "chars": 1837,
    "preview": "<template>\n<div class=\"vux-step-item\" :class=\" { 'vux-step-item-with-tail' : !props_stepLast} \">\n  <div :class=\"'vux-ste"
  },
  {
    "path": "src/components/step/step.vue",
    "chars": 2434,
    "preview": "<template>\n\t<div class=\"vux-step\">\n    <slot></slot>\n\t</div>\n</template>\n\n<script>\n\nexport default {\n  props: {\n    curr"
  },
  {
    "path": "src/components/sticky/index.vue",
    "chars": 299,
    "preview": "<template>\n  <div><slot></slot></div>\n</template>\n\n<script>\nimport sticky from './sticky'\n\nexport default {\n  mounted ()"
  },
  {
    "path": "src/components/sticky/sticky.js",
    "chars": 1161,
    "preview": "// http://efe.baidu.com/blog/position-sticky/\n\n// 检测iOS版本大于等于6\nfunction gtIOS6 () {\n  var userAgent = window.navigator.u"
  },
  {
    "path": "src/components/swiper/index.vue",
    "chars": 5832,
    "preview": "<template>\n  <div class=\"vux-slider\">\n    <input v-model=\"props_index\" style=\"display:none\">\n    <div class=\"vux-swiper\""
  },
  {
    "path": "src/components/swiper/swiper.js",
    "chars": 9550,
    "preview": "import arrayFrom from 'array-from'\nimport objectAssign from 'object-assign'\n\nclass Swiper {\n  constructor (options) {\n  "
  },
  {
    "path": "src/components/swiper-item/index.vue",
    "chars": 278,
    "preview": "<template>\n  <div class=\"vux-swiper-item\"><slot></slot></div>\n</template>\n\n<script>\nexport default {\n  mounted () {\n    "
  },
  {
    "path": "src/components/tab/index.js",
    "chars": 86,
    "preview": "import Tab from './tab'\nimport TabItem from './tab-item'\n\nexport {\n  Tab,\n  TabItem\n}\n"
  },
  {
    "path": "src/components/tab/tab-item.vue",
    "chars": 1504,
    "preview": "<template>\n  <div class=\"vux-tab-item\" :class=\"[props_selected ? activeClass : '', {'vux-tab-selected': props_selected}]"
  },
  {
    "path": "src/components/tab/tab.vue",
    "chars": 3958,
    "preview": "<template>\n  <div class=\"vux-tab\" :class=\"{'vux-tab-no-animate': !animate}\">\n    <input v-model=\"props_index\" style=\"dis"
  },
  {
    "path": "src/components/tabbar/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/tabbar/index.js",
    "chars": 104,
    "preview": "import Tabbar from './tabbar'\nimport TabbarItem from './tabbar-item'\n\nexport {\n  Tabbar,\n  TabbarItem\n}\n"
  },
  {
    "path": "src/components/tabbar/metas.yml",
    "chars": 903,
    "preview": "tabbar:\n  props:\n    icon-class:\n      en: icon's classname\n      zh-CN: 图标的class名\n  slots:\n    default:\n      en: main "
  },
  {
    "path": "src/components/tabbar/tabbar-item.vue",
    "chars": 1401,
    "preview": "<template>\n  <a href=\"javascript:;\" class=\"weui_tabbar_item\" :class=\"{'weui_bar_item_on': $parent.props_index === index}"
  },
  {
    "path": "src/components/tabbar/tabbar.vue",
    "chars": 1771,
    "preview": "<template>\n  <div class=\"weui_tabbar\">\n    <slot></slot>\n  </div>\n</template>\n\n<script>\n\nexport default {\n    mounted(){"
  },
  {
    "path": "src/components/timeline/index.js",
    "chars": 126,
    "preview": "import Timeline from './timeline'\nimport TimelineItem from './timeline-item'\n\nmodule.exports = {\n  Timeline,\n  TimelineI"
  },
  {
    "path": "src/components/timeline/timeline-item.vue",
    "chars": 1081,
    "preview": "<template>\n\t<li class=\"vux-timeline-item\">\n\t\t<div :class=\"['vux-timeline-item-color', {'vux-timeline-item-head': !isFirs"
  },
  {
    "path": "src/components/timeline/timeline.vue",
    "chars": 1541,
    "preview": "<template>\n\t<div class=\"vux-timeline\">\n\t\t<ul>\n\t\t\t<slot></slot>\n\t\t</ul>\n\t</div>\n</template>\n\n<script>\nexport default {\n  "
  },
  {
    "path": "src/components/tip/index.vue",
    "chars": 448,
    "preview": "<template>\n  <div class=\"vux-group-tip\" :style=\"{'text-align':align}\">\n    <slot></slot>\n  </div>\n</template>\n\n<script>\n"
  },
  {
    "path": "src/components/toast/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/toast/index.vue",
    "chars": 2452,
    "preview": "<template>\n  <div class=\"vux-toast\">\n    <!-- 此处input只做双向数据绑定用(props 的value 属性必须有)-->\n    <input v-model=\"props_show\" st"
  },
  {
    "path": "src/components/video/index.vue",
    "chars": 511,
    "preview": "<template>\n  <div class=\"zy_media\">\n    <video :poster=\"cover\" data-config='{\"mediaTitle\": \"《疯狂动物城》--腾讯视频\"}'>\n        <s"
  },
  {
    "path": "src/components/video/zy.media.css",
    "chars": 5660,
    "preview": "body { margin: 0 }\n\n/* zy.media style */\n.zy_media { background: #000; position: relative }\n.zy_media video, .zy_media a"
  },
  {
    "path": "src/components/video/zy.media.js",
    "chars": 25323,
    "preview": "/*\n *\n * zy.media.js\n * HTML5 <video> and <audio> native player\n *\n * Copyright 2016, iReader FE(掌阅书城研发--前端组)\n * License"
  },
  {
    "path": "src/components/view-box/index.vue",
    "chars": 325,
    "preview": "<template>\n  <div class=\"weui_tab\">\n    <slot name=\"header\"></slot>\n    <div class=\"weui_tab_bd vux-fix-safari-overflow-"
  },
  {
    "path": "src/components/view-box/metas.yml",
    "chars": 230,
    "preview": "intro:\n  zh-CN: 该组件为100%高布局,在safari中会出现滚动时无法自动隐藏url工具栏和底部栏的问题。\nslots:\n  header:\n    zh-CN: 顶部区域,如果要使用统一的XHeader,可以使用该slo"
  },
  {
    "path": "src/components/wechat-emotion/index.vue",
    "chars": 1994,
    "preview": "<template>\n  <div class=\"vux-emotion\"><slot style=\"display:none;\"></slot></div>\n</template>\n\n<script>\n// gif https://res"
  },
  {
    "path": "src/components/x-address/data/compress.js",
    "chars": 756,
    "preview": "\"use strict\"\nconst list = require('china-area-data')\nlet rs = []\n\nfor (var i in list) {\n  for (var j in list[i]) {\n    v"
  },
  {
    "path": "src/components/x-address/index.vue",
    "chars": 1497,
    "preview": "<template>\n  <div>\n      <popup-picker :fixed-columns=\"hideDistrict ? 2 : 0\" :columns=\"3\" :data=\"list\" :title=\"title\" :v"
  },
  {
    "path": "src/components/x-address/list.json",
    "chars": 296364,
    "preview": "[\n    {\n        \"name\": \"北京市\",\n        \"value\": \"110000\"\n    },\n    {\n        \"name\": \"天津市\",\n        \"value\": \"120000\"\n "
  },
  {
    "path": "src/components/x-address/metas.yml",
    "chars": 449,
    "preview": "extends:\n  - popup-picker\nprops:\n  raw-value:\n    zh-CN: 初始化时绑定的数据是否为文本类型,即非id,组件内部会转换为id。如果是异步初始化,只能使用id赋值。\n  title:\n  "
  },
  {
    "path": "src/components/x-button/component.json",
    "chars": 38,
    "preview": "{\n  \"vux\": {\n    \"is_weui\": true\n  }\n}"
  },
  {
    "path": "src/components/x-button/index.vue",
    "chars": 741,
    "preview": "<template>\n    <button class=\"weui_btn\" :class=\"classes\" :disabled=\"disabled\" @click=\"onclick\">\n      {{text}}<slot></sl"
  },
  {
    "path": "src/components/x-button/metas.yml",
    "chars": 432,
    "preview": "props:\n  type:\n    en:\n    zh-CN: 按钮类型,可选值为 `default,primary,warn`\n  disabled:\n    en: if disable the button\n    zh-CN: "
  },
  {
    "path": "src/components/x-header/index.vue",
    "chars": 3651,
    "preview": "<template>\n  <div class=\"vux-header\">\n    <div class=\"vux-header-left\">\n      <transition v-bind:name=\"transition\"><a cl"
  },
  {
    "path": "src/components/x-header/metas.yml",
    "chars": 730,
    "preview": "props:\n  left-options.showBack:\n    en: if show back text\n    zh-CN: 是否显示返回文字\n  left-options.backText:\n    en: the back "
  },
  {
    "path": "src/components/x-img/index.vue",
    "chars": 1667,
    "preview": "<template>\n  <img :src=\"defaultSrc\" class=\"vux-x-img\" :class=\"cls\"/>\n</template>\n\n<script>\nimport Blazy from 'vux-blazy'"
  },
  {
    "path": "src/components/x-input/index.vue",
    "chars": 7272,
    "preview": "<template>\n\t<div class=\"weui_cell\" :class=\"{'weui_cell_warn': !valid}\">\n    <div class=\"weui_cell_hd\">\n      <label clas"
  }
]

// ... and 185 more files (download for full content)

About this extraction

This page contains the full source code of the jinhuiWong/vux-2.0 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 385 files (953.4 KB), approximately 327.8k tokens, and a symbol index with 212 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!