Repository: youzan/vant-weapp
Branch: dev
Commit: 7a7d43757ed1
Files: 1892
Total size: 2.6 MB
Directory structure:
gitextract_stysbeow/
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitee/
│ └── ISSUE_TEMPLATE.zh-CN.md
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── config.yml
│ │ ├── template-1-bug-report-vant.zh-CN.yml
│ │ └── template-3-feature-request-vant.zh-CN.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ ├── pr-labeler.yml
│ └── workflows/
│ ├── deploy-site.yml
│ ├── pr-label.yaml
│ ├── release-tag.yml
│ └── test.yml
├── .gitignore
├── .husky/
│ ├── .gitignore
│ ├── commit-msg
│ └── pre-commit
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .stylelintrc
├── LICENSE
├── README.md
├── babel.config.js
├── build/
│ ├── compiler.js
│ ├── dev.mjs
│ ├── release.sh
│ └── upload.js
├── dist/
│ ├── action-sheet/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── area/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── button/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── calendar/
│ │ ├── calendar.wxml
│ │ ├── components/
│ │ │ ├── header/
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── index.json
│ │ │ │ ├── index.wxml
│ │ │ │ └── index.wxss
│ │ │ └── month/
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ ├── index.wxs
│ │ │ └── index.wxss
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── utils.d.ts
│ │ ├── utils.js
│ │ └── utils.wxs
│ ├── card/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── cascader/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── cell/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── cell-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── checkbox/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── checkbox-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── circle/
│ │ ├── canvas.d.ts
│ │ ├── canvas.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── col/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── collapse/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── collapse-item/
│ │ ├── animate.d.ts
│ │ ├── animate.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── common/
│ │ ├── color.d.ts
│ │ ├── color.js
│ │ ├── component.d.ts
│ │ ├── component.js
│ │ ├── index.wxss
│ │ ├── relation.d.ts
│ │ ├── relation.js
│ │ ├── style/
│ │ │ ├── clearfix.wxss
│ │ │ ├── ellipsis.wxss
│ │ │ ├── hairline.wxss
│ │ │ ├── mixins/
│ │ │ │ ├── clearfix.wxss
│ │ │ │ ├── ellipsis.wxss
│ │ │ │ └── hairline.wxss
│ │ │ └── var.wxss
│ │ ├── utils.d.ts
│ │ ├── utils.js
│ │ ├── validator.d.ts
│ │ ├── validator.js
│ │ ├── version.d.ts
│ │ └── version.js
│ ├── config-provider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── count-down/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── utils.d.ts
│ │ └── utils.js
│ ├── datetime-picker/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── definitions/
│ │ ├── index.d.ts
│ │ └── index.js
│ ├── dialog/
│ │ ├── dialog.d.ts
│ │ ├── dialog.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── divider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── dropdown-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ └── shared.js
│ ├── dropdown-menu/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── empty/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── field/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── input.wxml
│ │ ├── props.d.ts
│ │ ├── props.js
│ │ ├── textarea.wxml
│ │ ├── types.d.ts
│ │ └── types.js
│ ├── goods-action/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── goods-action-button/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── goods-action-icon/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── grid/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── grid-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── icon/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── image/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── index-anchor/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── index-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── info/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── loading/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── mixins/
│ │ ├── basic.d.ts
│ │ ├── basic.js
│ │ ├── button.d.ts
│ │ ├── button.js
│ │ ├── link.d.ts
│ │ ├── link.js
│ │ ├── page-scroll.d.ts
│ │ ├── page-scroll.js
│ │ ├── touch.d.ts
│ │ ├── touch.js
│ │ ├── transition.d.ts
│ │ └── transition.js
│ ├── nav-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── notice-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── notify/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── notify.d.ts
│ │ └── notify.js
│ ├── overlay/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ └── overlay.wxml
│ ├── panel/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── picker/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ ├── shared.js
│ │ └── toolbar.wxml
│ ├── picker-column/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── popup/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ └── popup.wxml
│ ├── progress/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── radio/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── radio-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── rate/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── row/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── search/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── share-sheet/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── options.d.ts
│ │ ├── options.js
│ │ ├── options.json
│ │ ├── options.wxml
│ │ ├── options.wxs
│ │ └── options.wxss
│ ├── sidebar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── sidebar-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── skeleton/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── slider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── stepper/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── steps/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── sticky/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── submit-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── swipe-cell/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── switch/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tab/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabbar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabbar-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabs/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tag/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── toast/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── toast.d.ts
│ │ └── toast.js
│ ├── transition/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tree-select/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── uploader/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ ├── shared.js
│ │ ├── utils.d.ts
│ │ └── utils.js
│ └── wxs/
│ ├── add-unit.wxs
│ ├── array.wxs
│ ├── bem.wxs
│ ├── memoize.wxs
│ ├── object.wxs
│ ├── style.wxs
│ └── utils.wxs
├── docs/
│ └── markdown/
│ ├── changelog.md
│ ├── custom-style.md
│ ├── home.md
│ ├── quickstart.md
│ └── theme.md
├── example/
│ ├── app.js
│ ├── app.json
│ ├── app.wxss
│ ├── common/
│ │ └── page.js
│ ├── components/
│ │ ├── demo-block/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ ├── demo-home/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ └── demo-home-nav/
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── config.js
│ ├── database_area.json
│ ├── functions/
│ │ └── foo/
│ │ ├── index.js
│ │ └── package.json
│ ├── pages/
│ │ ├── action-sheet/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── area/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── button/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── calendar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── card/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── cascader/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── cell/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── checkbox/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── circle/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── col/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── collapse/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── config-provider/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── count-down/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── dashboard/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── datetime-picker/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── dialog/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── divider/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── dropdown-menu/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── empty/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── field/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── goods-action/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── grid/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── icon/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── image/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── index-bar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── loading/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── nav-bar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── notice-bar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── notify/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── overlay/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── panel/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── picker/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── popup/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ ├── progress/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── radio/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── rate/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ ├── search/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── share-sheet/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── sidebar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ ├── skeleton/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── slider/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── stepper/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── steps/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── sticky/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ └── index.wxss
│ │ ├── submit-bar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── swipe-cell/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── switch/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── tab/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── tabbar/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── tag/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── toast/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── transition/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── tree-select/
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ └── uploader/
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── project.config.json
│ └── sitemap.json
├── jest.config.js
├── lib/
│ ├── action-sheet/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── area/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── button/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── calendar/
│ │ ├── calendar.wxml
│ │ ├── components/
│ │ │ ├── header/
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── index.json
│ │ │ │ ├── index.wxml
│ │ │ │ └── index.wxss
│ │ │ └── month/
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.wxml
│ │ │ ├── index.wxs
│ │ │ └── index.wxss
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── utils.d.ts
│ │ ├── utils.js
│ │ └── utils.wxs
│ ├── card/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── cascader/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── cell/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── cell-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── checkbox/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── checkbox-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── circle/
│ │ ├── canvas.d.ts
│ │ ├── canvas.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── col/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── collapse/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── collapse-item/
│ │ ├── animate.d.ts
│ │ ├── animate.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── common/
│ │ ├── color.d.ts
│ │ ├── color.js
│ │ ├── component.d.ts
│ │ ├── component.js
│ │ ├── index.wxss
│ │ ├── relation.d.ts
│ │ ├── relation.js
│ │ ├── style/
│ │ │ ├── clearfix.wxss
│ │ │ ├── ellipsis.wxss
│ │ │ ├── hairline.wxss
│ │ │ ├── mixins/
│ │ │ │ ├── clearfix.wxss
│ │ │ │ ├── ellipsis.wxss
│ │ │ │ └── hairline.wxss
│ │ │ └── var.wxss
│ │ ├── utils.d.ts
│ │ ├── utils.js
│ │ ├── validator.d.ts
│ │ ├── validator.js
│ │ ├── version.d.ts
│ │ └── version.js
│ ├── config-provider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── count-down/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── utils.d.ts
│ │ └── utils.js
│ ├── datetime-picker/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── definitions/
│ │ ├── index.d.ts
│ │ └── index.js
│ ├── dialog/
│ │ ├── dialog.d.ts
│ │ ├── dialog.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── divider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── dropdown-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ └── shared.js
│ ├── dropdown-menu/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── empty/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── field/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── input.wxml
│ │ ├── props.d.ts
│ │ ├── props.js
│ │ ├── textarea.wxml
│ │ ├── types.d.ts
│ │ └── types.js
│ ├── goods-action/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── goods-action-button/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── goods-action-icon/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── grid/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── grid-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── icon/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── image/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── index-anchor/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── index-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── info/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── loading/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── mixins/
│ │ ├── basic.d.ts
│ │ ├── basic.js
│ │ ├── button.d.ts
│ │ ├── button.js
│ │ ├── link.d.ts
│ │ ├── link.js
│ │ ├── page-scroll.d.ts
│ │ ├── page-scroll.js
│ │ ├── touch.d.ts
│ │ ├── touch.js
│ │ ├── transition.d.ts
│ │ └── transition.js
│ ├── nav-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── notice-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── notify/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── notify.d.ts
│ │ └── notify.js
│ ├── overlay/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ └── overlay.wxml
│ ├── panel/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── picker/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ ├── shared.js
│ │ └── toolbar.wxml
│ ├── picker-column/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── popup/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ └── popup.wxml
│ ├── progress/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── radio/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── radio-group/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── rate/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── row/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── search/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── share-sheet/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── options.d.ts
│ │ ├── options.js
│ │ ├── options.json
│ │ ├── options.wxml
│ │ ├── options.wxs
│ │ └── options.wxss
│ ├── sidebar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── sidebar-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── skeleton/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── slider/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── stepper/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── steps/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── sticky/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── submit-bar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── swipe-cell/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── switch/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tab/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabbar/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabbar-item/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── tabs/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tag/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── toast/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── toast.d.ts
│ │ └── toast.js
│ ├── transition/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── tree-select/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── index.wxss
│ ├── uploader/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── index.wxss
│ │ ├── shared.d.ts
│ │ ├── shared.js
│ │ ├── utils.d.ts
│ │ └── utils.js
│ └── wxs/
│ ├── add-unit.wxs
│ ├── array.wxs
│ ├── bem.wxs
│ ├── memoize.wxs
│ ├── object.wxs
│ ├── style.wxs
│ └── utils.wxs
├── package.json
├── packages/
│ ├── action-sheet/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── area/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── button/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ ├── demo.spec.ts
│ │ └── index.spec.ts
│ ├── calendar/
│ │ ├── README.md
│ │ ├── calendar.wxml
│ │ ├── components/
│ │ │ ├── header/
│ │ │ │ ├── index.json
│ │ │ │ ├── index.less
│ │ │ │ ├── index.ts
│ │ │ │ └── index.wxml
│ │ │ └── month/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ ├── index.wxml
│ │ │ └── index.wxs
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ ├── index.wxml
│ │ │ └── index.wxs
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ ├── utils.ts
│ │ └── utils.wxs
│ ├── card/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── cascader/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── cell/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── cell-group/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── checkbox/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── checkbox-group/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── circle/
│ │ ├── README.md
│ │ ├── canvas.ts
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── col/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── collapse/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── collapse-item/
│ │ ├── animate.ts
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── common/
│ │ ├── README.md
│ │ ├── color.ts
│ │ ├── component.ts
│ │ ├── index.less
│ │ ├── relation.ts
│ │ ├── style/
│ │ │ ├── clearfix.less
│ │ │ ├── ellipsis.less
│ │ │ ├── hairline.less
│ │ │ ├── mixins/
│ │ │ │ ├── clearfix.less
│ │ │ │ ├── ellipsis.less
│ │ │ │ └── hairline.less
│ │ │ └── var.less
│ │ ├── utils.ts
│ │ ├── validator.ts
│ │ └── version.ts
│ ├── config-provider/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── count-down/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ └── utils.ts
│ ├── datetime-picker/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── definitions/
│ │ └── index.ts
│ ├── dialog/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── dialog.ts
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── divider/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── dropdown-item/
│ │ ├── dropdown-item.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── shared.ts
│ ├── dropdown-menu/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── empty/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── field/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── input.wxml
│ │ ├── props.ts
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ ├── textarea.wxml
│ │ └── types.ts
│ ├── goods-action/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── goods-action-button/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── goods-action-icon/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── grid/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── grid-item/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── icon/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── image/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── index-anchor/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── index-bar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── info/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── loading/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── mixins/
│ │ ├── basic.ts
│ │ ├── button.ts
│ │ ├── link.ts
│ │ ├── page-scroll.ts
│ │ ├── touch.ts
│ │ └── transition.ts
│ ├── nav-bar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── notice-bar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── notify/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── notify.ts
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── overlay/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── overlay.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── panel/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── picker/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── shared.ts
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ └── toolbar.wxml
│ ├── picker-column/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── popup/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── popup.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── progress/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── radio/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── radio-group/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── rate/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── row/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── search/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── share-sheet/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── options.json
│ │ ├── options.less
│ │ ├── options.ts
│ │ ├── options.wxml
│ │ ├── options.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── sidebar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── sidebar-item/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── skeleton/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── slider/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── stepper/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── steps/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── sticky/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── submit-bar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── swipe-cell/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── switch/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ ├── demo.spec.ts.snap
│ │ │ └── index.spec.ts.snap
│ │ ├── demo.spec.ts
│ │ └── index.spec.ts
│ ├── tab/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── tabbar/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── tabbar-item/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ └── index.wxml
│ ├── tabs/
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ └── index.wxs
│ ├── tag/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── toast/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ └── toast.ts
│ ├── transition/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── tree-select/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ └── test/
│ │ ├── __snapshots__/
│ │ │ └── demo.spec.ts.snap
│ │ └── demo.spec.ts
│ ├── uploader/
│ │ ├── README.md
│ │ ├── demo/
│ │ │ ├── index.json
│ │ │ ├── index.ts
│ │ │ └── index.wxml
│ │ ├── index.json
│ │ ├── index.less
│ │ ├── index.ts
│ │ ├── index.wxml
│ │ ├── index.wxs
│ │ ├── shared.ts
│ │ ├── test/
│ │ │ ├── __snapshots__/
│ │ │ │ └── demo.spec.ts.snap
│ │ │ └── demo.spec.ts
│ │ └── utils.ts
│ └── wxs/
│ ├── add-unit.wxs
│ ├── array.wxs
│ ├── bem.wxs
│ ├── memoize.wxs
│ ├── object.wxs
│ ├── style.wxs
│ └── utils.wxs
├── postcss.config.js
├── rsbuild.config.ts
├── tsconfig.example.json
├── tsconfig.json
├── tsconfig.lib.json
└── vant.config.mjs
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.wxml]
indent_size = 2
[*.wxss]
indent_size = 2
[*.js]
indent_size = 2
[*.json]
indent_size = 2
================================================
FILE: .eslintignore
================================================
lib
dist
example/dist
node_modules
================================================
FILE: .eslintrc
================================================
{
"root": true,
"globals": {
"getApp": false,
"getCurrentPages": false,
"Page": false,
"Component": false,
"App": false,
"wx": false,
"Behavior": false
},
"extends": ["@vant"]
}
================================================
FILE: .gitee/ISSUE_TEMPLATE.zh-CN.md
================================================
你好,请使用下面的链接创建 issue 以帮助我们更快的排查问题,不规范的 issue 会被关闭,感谢配合。
http://vant-ui.github.io/vant-issue-generater?repo=VantWeapp
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [chenjiahan, nemo-shen]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/template-1-bug-report-vant.zh-CN.yml
================================================
name: 我要反馈 Vant Weapp 的 Bug
description: 通过标准模板进行 Bug 反馈
title: "[Bug Report] 请在此填写标题"
labels: ["bug: need confirm"]
body:
- type: markdown
attributes:
value: |
在提交 Bug 报告前,请注意:
- 确认你的问题无法通过官方文档得到解决。
- 确认你搜索过 [历史 issue](https://github.com/youzan/vant-weapp/issues),并且没有发现同样的问题。
- 如果不是反馈 Bug,请到 [Discussions 讨论区](https://github.com/youzan/vant-weapp/discussions) 发帖。
- type: textarea
id: reproduce
attributes:
label: 重现链接
description: 请提供一个尽可能简单的微信小程序代码片段协助我们排查,这可以更快的帮助我们定位问题,解决 issue。
validations:
required: true
- type: input
id: version
attributes:
label: Vant Weapp 版本
description: 你正在使用的 Vant Weapp 版本是多少?(请填写 node_modules/@vant/weapp/package.json 里实际安装的版本)
placeholder: 比如 1.10.5
validations:
required: true
- type: textarea
id: description
attributes:
label: 描述一下你遇到的问题。
placeholder: 比如:弹窗无法展示、日历组件报错
validations:
required: true
- type: textarea
id: reproduce-steps
attributes:
label: 重现步骤
description: 请提供一个最简单的操作步骤,方便我们快速重现问题。
placeholder: |
比如:
1. 点击按钮
2. 弹窗无法展示
validations:
required: true
- type: input
id: browsers
attributes:
label: 设备/浏览器
description: 在哪些设备/浏览器上能重现这个问题?
================================================
FILE: .github/ISSUE_TEMPLATE/template-3-feature-request-vant.zh-CN.yml
================================================
name: 我想要一个 Vant Weapp 的新功能
description: 通过标准模板描述一下你的功能需求。
title: "[Feature Request] 请在此填写标题"
labels: ["feature: need confirm"]
body:
- type: markdown
attributes:
value: |
在提交功能需求前,请注意:
- 确认这是一个通用功能,并且无法通过现有的 API 或 Slot 实现。
- 确认你搜索过 [历史 issue](https://github.com/youzan/vant-weapp/issues),并且没有发现同样的需求。
- 可以先到 [Discussions 讨论区](https://github.com/youzan/vant-weapp/discussions) 发帖,讨论一下需求是否合理。
- type: textarea
id: description
attributes:
label: 这个功能解决了什么问题?
description: 请尽可能详细地说明这个功能的使用场景。
validations:
required: true
- type: textarea
id: api
attributes:
label: 你期望的 API 是什么样子的?
description: 描述一下这个新功能的 API,并提供一些代码示例。
placeholder: |
```xml
```
validations:
required: true
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
### Pull Request 标题规则
type(ComponentName?):commit message
示例:
- docs: fix typo in quickstart
- build: optimize build speed
- fix(Button): incorrect style
- feat(Button): add color prop
可选择的类型:
- fix
- feat
- docs
- perf
- test
- types
- build
- chore
- refactor
- breaking change
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 10
ignore:
- dependency-name: miniprogram-api-typings
versions:
- 3.3.2
================================================
FILE: .github/pr-labeler.yml
================================================
"change: feat":
- "/^(feat|types|style)/"
"change: fix":
- "/^fix/"
"change: perf":
- "/^perf/"
"change: breaking":
- "/^breaking change/"
"change: docs":
- "/^docs/"
================================================
FILE: .github/workflows/deploy-site.yml
================================================
name: Deploy Site
on:
push:
branches: [dev]
paths:
- 'docs/**/*.md'
- 'packages/**/*.md'
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2
with:
ref: 'dev'
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Build Site
run: npx --no-install vant-cli build-site
- name: Deploy for GitHub 🚀
uses: JamesIves/github-pages-deploy-action@v4.6.0
with:
branch: gh-pages
folder: site-dist
token: ${{ secrets.VANT_UI_TOKEN }}
repository-name: vant-ui/vant-ui.github.io
target-folder: vant-weapp
# enable single-commit to reduce the repo size
single-commit: true
clean: true
clean-exclude: |
0.x
================================================
FILE: .github/workflows/pr-label.yaml
================================================
name: PR Labeler
on:
pull_request_target:
types:
- opened
- edited
jobs:
change-labeling:
name: Labeling for changes
runs-on: ubuntu-latest
steps:
- uses: github/issue-labeler@v3.4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: .github/pr-labeler.yml
enable-versioned-regex: 0
include-title: 1
sync-labels: 1
================================================
FILE: .github/workflows/release-tag.yml
================================================
name: Create Release Tag
on:
push:
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
build:
name: Create Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Create Release for Tag
id: release_tag
uses: ncipollo/release-action@v1
with:
generateReleaseNotes: "true"
body: |
> 请访问 [更新日志](https://vant-ui.github.io/vant-weapp/#/changelog) 了解所有更新。
================================================
FILE: .github/workflows/test.yml
================================================
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '18.x'
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Run linter
run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: szenius/set-timezone@v1.0
with:
timezoneLinux: "Asia/Shanghai"
timezoneMacos: "Asia/Shanghai"
timezoneWindows: "China Standard Time"
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '18.x'
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Run test cases
run: npm test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '18.x'
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Build
run: npm run build:lib
================================================
FILE: .gitignore
================================================
*.log*
.cache
.DS_Store
.idea
.vscode
node_modules
site-dist
docs/dist
example/dist
.history
changelog.generated.md
package-lock.json
build/private.wx1c01b35002d3ba14.key
project.private.config.json
================================================
FILE: .husky/.gitignore
================================================
_
================================================
FILE: .husky/commit-msg
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install vant-cli commit-lint $1
================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install lint-staged
================================================
FILE: .npmrc
================================================
registry=https://registry.npmjs.org
================================================
FILE: .prettierignore
================================================
lib
dist
================================================
FILE: .prettierrc
================================================
{
"singleQuote": true,
"proseWrap": "never"
}
================================================
FILE: .stylelintrc
================================================
{
"extends": [
"@vant/stylelint-config"
],
"rules": {
"unit-no-unknown": [
true,
{
"ignoreUnits": "/rpx/"
}
],
"selector-type-no-unknown": [
true,
{
"ignoreTypes": [
"/page/"
]
}
]
}
}
================================================
FILE: LICENSE
================================================
Copyright 2016-present Youzan
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
================================================
轻量、可靠的小程序 UI 组件库
🔥 文档网站(国内)
🔥 文档网站(GitHub)
🚀 Vue 版
---
### 介绍
Vant 是一个**轻量、可靠的移动端组件库**,于 2017 年开源。
目前 Vant 官方提供了 [Vue 2 版本](https://vant-ui.github.io/vant/v2/)、[Vue 3 版本](https://vant-ui.github.io/vant/)和[微信小程序版本](http://vant-ui.github.io/vant-weapp/),并由社区团队维护 [React 版本](https://github.com/3lang3/react-vant)和[支付宝小程序版本](https://github.com/ant-move/Vant-Aliapp)。
## 预览
扫描下方小程序二维码,体验组件库示例。注意:因微信审核机制限制,目前示例小程序不是最新版本,可以 clone 代码到本地开发工具预览
## 使用之前
使用 Vant Weapp 前,请确保你已经学习过微信官方的 [小程序简易教程](https://developers.weixin.qq.com/miniprogram/dev/framework/) 和 [自定义组件介绍](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/)。
## 安装
### 方式一. 通过 npm 安装 (推荐)
小程序已经支持使用 npm 安装第三方包,详见 [npm 支持](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html?search-key=npm)
```bash
# 通过 npm 安装
npm i @vant/weapp -S --production
# 通过 yarn 安装
yarn add @vant/weapp --production
# 安装 0.x 版本
npm i vant-weapp -S --production
```
### 方式二. 下载代码
直接通过 git 下载 Vant Weapp 源代码,并将 `dist` 目录拷贝到自己的项目中。
```bash
git clone https://github.com/youzan/vant-weapp.git
```
## 使用组件
以按钮组件为例,只需要在 json 文件中引入按钮对应的自定义组件即可
```json
{
"usingComponents": {
"van-button": "/path/to/vant-weapp/dist/button/index"
}
}
```
接着就可以在 wxml 中直接使用组件
```html
按钮
```
## 在开发者工具中预览
```bash
# 安装项目依赖
npm install
# 执行组件编译
npm run dev
```
打开[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html),把`vant-weapp/example`目录添加进去就可以预览示例了。
PS:关于 `van-area` Area 省市区选择组件,地区数据初始化可以直接在云开发环境中导入`vant-weapp/example/database_area.JSON` 文件使用。
## 基础库版本
Vant Weapp 最低支持到小程序基础库 2.6.5 版本。
## 链接
- [文档网站(GitHub)](https://vant-ui.github.io/vant-weapp/)
- [文档网站(国内)](https://vant.pro/vant-weapp/)
- [意见反馈](https://github.com/youzan/vant-weapp/issues)
- [设计资源](https://vant-ui.github.io/vant/#/zh-CN/design)
- [更新日志](https://vant-ui.github.io/vant-weapp/#/changelog)
- [官方示例](https://github.com/vant-ui/vant-demo)
## 核心团队
以下是 Vant 和 Vant Weapp 的核心贡献者们:
| [](https://github.com/chenjiahan/) | [](https://github.com/cookfront/) | [](https://github.com/w91/) | [](https://github.com/pangxie1991/) | [](https://github.com/rex-zsd/) | [](https://github.com/nemo-shen/) |
| :-: | :-: | :-: | :-: | :-: | :-: |
| [chenjiahan](https://github.com/chenjiahan/) | [cookfront](https://github.com/cookfront/) | [wangnaiyi](https://github.com/w91/) | [pangxie](https://github.com/pangxie1991/) | [rex-zsd](https://github.com/rex-zsd/) | [nemo-shen](https://github.com/nemo-shen/) |
| [](https://github.com/Lindysen/) | [](https://github.com/JakeLaoyu/) | [](https://github.com/landluck/) | [](https://github.com/wjw-gavin/) | [](https://github.com/inottn/) | [](https://github.com/zhousg/) |
| :-: | :-: | :-: | :-: | :-: | :-: |
| [Lindysen](https://github.com/Lindysen/) | [JakeLaoyu](https://github.com/JakeLaoyu/) | [landluck](https://github.com/landluck/) | [wjw-gavin](https://github.com/wjw-gavin/) | [inottn](https://github.com/inottn/) | [zhousg](https://github.com/zhousg/) |
## 贡献者们
感谢以下小伙伴们为 Vant Weapp 发展做出的贡献:
## 开源协议
本项目基于 [MIT](https://zh.wikipedia.org/wiki/MIT%E8%A8%B1%E5%8F%AF%E8%AD%89)协议,请自由地享受和参与开源。
================================================
FILE: babel.config.js
================================================
module.exports = {
presets: [
[
'@babel/preset-env',
{
loose: true,
modules: false,
},
],
],
env: {
test: {
presets: ['@babel/preset-typescript'],
plugins: ['@babel/plugin-transform-modules-commonjs'],
},
},
};
================================================
FILE: build/compiler.js
================================================
const fs = require('fs');
const gulp = require('gulp');
const path = require('path');
const less = require('gulp-less');
const insert = require('gulp-insert');
const rename = require('gulp-rename');
const postcss = require('gulp-postcss');
const ts = require('gulp-typescript');
const util = require('util');
const merge2 = require('merge2');
const exec = util.promisify(require('child_process').exec);
const src = path.resolve(__dirname, '../packages');
const icons = path.resolve(__dirname, '../node_modules/@vant/icons');
const libConfig = path.resolve(__dirname, '../tsconfig.lib.json');
const esConfig = path.resolve(__dirname, '../tsconfig.json');
const exampleConfig = path.resolve(__dirname, '../tsconfig.example.json');
const libDir = path.resolve(__dirname, '../lib');
const esDir = path.resolve(__dirname, '../dist');
const exampleDistDir = path.resolve(__dirname, '../example/dist');
const examplePagesDir = path.resolve(__dirname, '../example/pages');
const exampleAppJsonPath = path.resolve(__dirname, '../example/app.json');
const baseCssPath = path.resolve(__dirname, '../packages/common/index.wxss');
const lessCompiler = (dist) =>
function compileLess() {
const srcPath = [`${src}/**/*.less`];
if ([esDir, libDir].indexOf(dist) !== -1) {
srcPath.push(`!${src}/**/demo/**/*.less`);
}
return gulp
.src(srcPath)
.pipe(less())
.pipe(postcss())
.pipe(
insert.transform((contents, file) => {
if (!file.path.includes('packages' + path.sep + 'common')) {
const relativePath = path
.relative(
path.normalize(`${file.path}${path.sep}..`),
baseCssPath
)
.replace(/\\/g, '/');
contents = `@import '${relativePath}';${contents}`;
}
return contents;
})
)
.pipe(rename({ extname: '.wxss' }))
.pipe(gulp.dest(dist));
};
const tsCompiler = (dist, config) =>
function compileTs() {
const tsProject = ts.createProject(config, {
declaration: true,
});
const tsResult = tsProject.src().pipe(tsProject());
return merge2(
tsResult.js
.pipe(
insert.transform((contents, file) => {
if (dist === exampleDistDir && file.path.includes(`${path.sep}demo${path.sep}`)) {
const iconConfig = '@vant/icons/src/config';
contents = contents.replace(
iconConfig,
path.relative(
path.dirname(file.path),
`${exampleDistDir}/${iconConfig}`
).replace(/\\/g, '/')
);
}
return contents;
})
)
.pipe(gulp.dest(dist)),
tsResult.dts.pipe(gulp.dest(dist))
);
};
const copier = (dist, ext) =>
function copy() {
const srcPath = [`${src}/**/*.${ext}`];
if ([esDir, libDir].indexOf(dist) !== -1) {
srcPath.push(`!${src}/**/demo/**/*.${ext}`);
}
return gulp
.src(srcPath)
.pipe(
insert.transform((contents, file) => {
if (ext === 'json' && file.path.includes(`${path.sep}demo${path.sep}`) ) {
contents = contents.replace('/example', '');
}
return contents;
})
)
.pipe(gulp.dest(dist));
};
const staticCopier = (dist) =>
gulp.parallel(
copier(dist, 'wxml'),
copier(dist, 'wxs'),
copier(dist, 'json')
);
const cleaner = (path) =>
function clean() {
return exec(`npx rimraf ${path}`);
};
const tasks = [
['buildEs', esDir, esConfig],
['buildLib', libDir, libConfig],
].reduce((prev, [name, ...args]) => {
prev[name] = gulp.series(
cleaner(...args),
gulp.parallel(
tsCompiler(...args),
lessCompiler(...args),
staticCopier(...args)
)
);
return prev;
}, {});
tasks.buildExample = gulp.series(
cleaner(exampleDistDir),
gulp.parallel(
tsCompiler(exampleDistDir, exampleConfig),
lessCompiler(exampleDistDir),
staticCopier(exampleDistDir),
() =>
gulp
.src(`${icons}/**/*`)
.pipe(gulp.dest(`${exampleDistDir}/@vant/icons`)),
() => {
const appJson = JSON.parse(fs.readFileSync(exampleAppJsonPath));
const excludePages = ['pages/dashboard/index'];
appJson.pages
.filter((page) => page.indexOf(excludePages) === -1)
.forEach((path) => {
const component = path.replace(/(pages\/|\/index)/g, '');
const writeFiles = [
{
path: `${examplePagesDir}/${component}/index.js`,
contents: "import Page from '../../common/page';\n\nPage();",
},
{
path: `${examplePagesDir}/${component}/index.wxml`,
contents: ``,
},
];
writeFiles.forEach((writeFile) => {
fs.access(writeFile.path, fs.constants.F_OK, (fileNotExists) => {
if (fileNotExists) {
fs.writeFile(writeFile.path, writeFile.contents, (err) => {
if (err) {
throw err;
}
});
}
});
});
});
},
() => {
gulp.watch(`${src}/**/*.less`, lessCompiler(exampleDistDir));
gulp.watch(`${src}/**/*.wxml`, copier(exampleDistDir, 'wxml'));
gulp.watch(`${src}/**/*.wxs`, copier(exampleDistDir, 'wxs'));
gulp.watch(`${src}/**/*.ts`, tsCompiler(exampleDistDir, exampleConfig));
gulp.watch(`${src}/**/*.json`, copier(exampleDistDir, 'json'));
}
)
);
module.exports = tasks;
================================================
FILE: build/dev.mjs
================================================
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import { dev } from '@vant/cli/lib/commands/dev.js';
import { exec } from 'child_process';
const __dirname = dirname(fileURLToPath(import.meta.url));
const gulpConfig = resolve(__dirname, './compiler.js');
async function run() {
await dev();
const p = exec(`npx gulp -f ${gulpConfig} buildExample --color`);
p.stdout.on('data', (stdout) => console.info(stdout));
p.stderr.on('data', (stderr) => console.info(stderr));
}
run();
================================================
FILE: build/release.sh
================================================
#!/usr/bin/env sh
set -e
echo "Enter release version: "
read VERSION
read -p "Releasing $VERSION - are you sure? (y/n)" -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
# build
npm run build:lib
if [[ `git status --porcelain` ]];
then
git add -A
git commit -am "build: compile $VERSION"
fi
# commit
npm version $VERSION --message "release: $VERSION"
# publish
git push origin dev
git push origin refs/tags/v$VERSION
if [[ $VERSION =~ [beta] ]]
then
npm publish --tag beta
else
npm publish
fi
fi
================================================
FILE: build/upload.js
================================================
const ci = require('miniprogram-ci');
const path = require('path');
const config = require('../example/project.config.json');
const package = require('../package.json');
const project = new ci.Project({
appid: config.appid,
type: 'miniProgram',
projectPath: path.join(__dirname, '../example'),
privateKeyPath: path.join(__dirname, './private.wx1c01b35002d3ba14.key'),
ignores: ['node_modules/**/*'],
});
ci.upload({
project,
version: package.version,
desc: package.description,
setting: config.setting,
});
================================================
FILE: dist/action-sheet/index.d.ts
================================================
export {};
================================================
FILE: dist/action-sheet/index.js
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
classes: ['list-class'],
mixins: [button],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100,
},
actions: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
const item = actions[index];
if (item) {
this.$emit('select', item);
if (closeOnClickAction) {
this.onClose();
}
if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: item.getUserProfileDesc || ' ',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
});
================================================
FILE: dist/action-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: dist/action-sheet/index.wxml
================================================
{{ description }}
{{ cancelText }}
================================================
FILE: dist/action-sheet/index.wxss
================================================
@import '../common/index.wxss';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}
================================================
FILE: dist/area/index.d.ts
================================================
export {};
================================================
FILE: dist/area/index.js
================================================
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
import { requestAnimationFrame } from '../common/utils';
const EMPTY_CODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
type: Boolean,
value: true,
}, value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
},
}, areaList: {
type: Object,
value: {},
observer: 'setValues',
}, columnsNum: {
type: null,
value: 3,
}, columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
},
});
},
} }),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {},
},
mounted() {
requestAnimationFrame(() => {
this.setValues();
});
},
methods: {
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel(event) {
this.emit('cancel', event.detail);
},
onConfirm(event) {
const { index } = event.detail;
let { value } = event.detail;
value = this.parseValues(value);
this.emit('confirm', { value, index });
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
parseValues(values) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
if (value &&
(!value.code || value.name === columnsPlaceholder[index])) {
return Object.assign(Object.assign({}, value), { code: '', name: '' });
}
return value;
});
},
onChange(event) {
var _a;
const { index, picker, value } = event.detail;
this.code = value[index].code;
(_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
this.$emit('change', {
picker,
values: this.parseValues(picker.getValues()),
index,
});
});
},
getConfig(type) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
if (type !== 'province' && !code) {
return [];
}
const { typeToColumnsPlaceholder } = this.data;
const list = this.getConfig(type);
let result = Object.keys(list).map((code) => ({
code,
name: list[code],
}));
if (code != null) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter((item) => item.code.indexOf(code) === 0);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill = type === 'province'
? ''
: type === 'city'
? EMPTY_CODE.slice(2, 4)
: EMPTY_CODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type],
});
}
return result;
},
getIndex(type, code) {
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
const list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (let i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues() {
const picker = this.getPicker();
if (!picker) {
return;
}
let code = this.code || this.getDefaultCode();
const provinceList = this.getList('province');
const cityList = this.getList('city', code.slice(0, 2));
const stack = [];
const indexes = [];
const { columnsNum } = this.data;
if (columnsNum >= 1) {
stack.push(picker.setColumnValues(0, provinceList, false));
indexes.push(this.getIndex('province', code));
}
if (columnsNum >= 2) {
stack.push(picker.setColumnValues(1, cityList, false));
indexes.push(this.getIndex('city', code));
if (cityList.length && code.slice(2, 4) === '00') {
[{ code }] = cityList;
}
}
if (columnsNum === 3) {
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
indexes.push(this.getIndex('county', code));
}
return Promise.all(stack)
.catch(() => { })
.then(() => picker.setIndexes(indexes))
.catch(() => { });
},
getDefaultCode() {
const { columnsPlaceholder } = this.data;
if (columnsPlaceholder.length) {
return EMPTY_CODE;
}
const countyCodes = Object.keys(this.getConfig('county'));
if (countyCodes[0]) {
return countyCodes[0];
}
const cityCodes = Object.keys(this.getConfig('city'));
if (cityCodes[0]) {
return cityCodes[0];
}
return '';
},
getValues() {
const picker = this.getPicker();
if (!picker) {
return [];
}
return this.parseValues(picker.getValues().filter((value) => !!value));
},
getDetail() {
const values = this.getValues();
const area = {
code: '',
country: '',
province: '',
city: '',
county: '',
};
if (!values.length) {
return area;
}
const names = values.map((item) => item.name);
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
}
else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset(code) {
this.code = code || '';
return this.setValues();
},
},
});
================================================
FILE: dist/area/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: dist/area/index.wxml
================================================
================================================
FILE: dist/area/index.wxs
================================================
/* eslint-disable */
function displayColumns(columns, columnsNum) {
return columns.slice(0, +columnsNum);
}
module.exports = {
displayColumns: displayColumns,
};
================================================
FILE: dist/area/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: dist/button/index.d.ts
================================================
export {};
================================================
FILE: dist/button/index.js
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { canIUseFormFieldButton } from '../common/version';
const mixins = [button];
if (canIUseFormFieldButton()) {
mixins.push('wx://form-field-button');
}
VantComponent({
mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick(event) {
this.$emit('click', event);
const { canIUseGetUserProfile, openType, getUserProfileDesc, lang, } = this.data;
if (openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: getUserProfileDesc || ' ',
lang: lang || 'en',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
},
},
});
================================================
FILE: dist/button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: dist/button/index.wxml
================================================
================================================
FILE: dist/button/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return data.customStyle;
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style([properties, data.customStyle]);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: dist/button/index.wxss
================================================
@import '../common/index.wxss';.van-button{-webkit-text-size-adjust:100%;align-items:center;-webkit-appearance:none;border-radius:var(--button-border-radius,2px);box-sizing:border-box;display:inline-flex;font-size:var(--button-default-font-size,16px);height:var(--button-default-height,44px);justify-content:center;line-height:var(--button-line-height,20px);padding:0;position:relative;text-align:center;transition:opacity .2s;vertical-align:middle}.van-button:before{background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";height:100%;left:50%;opacity:0;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{background:var(--button-default-background-color,#fff);border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0);color:var(--button-default-color,#323233)}.van-button--primary{background:var(--button-primary-background-color,#07c160);border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160);color:var(--button-primary-color,#fff)}.van-button--info{background:var(--button-info-background-color,#1989fa);border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa);color:var(--button-info-color,#fff)}.van-button--danger{background:var(--button-danger-background-color,#ee0a24);border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24);color:var(--button-danger-color,#fff)}.van-button--warning{background:var(--button-warning-background-color,#ff976a);border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a);color:var(--button-warning-color,#fff)}.van-button--plain{background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:var(--button-warning-background-color,#ff976a)}.van-button--large{height:var(--button-large-height,50px);width:100%}.van-button--normal{font-size:var(--button-normal-font-size,14px);padding:0 15px}.van-button--small{font-size:var(--button-small-font-size,12px);height:var(--button-small-height,30px);min-width:var(--button-small-min-width,60px);padding:0 var(--padding-xs,8px)}.van-button--mini{display:inline-block;font-size:var(--button-mini-font-size,10px);height:var(--button-mini-height,22px);min-width:var(--button-mini-min-width,50px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:flex;width:100%}.van-button--round{border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{line-height:inherit!important;min-width:1em;vertical-align:top}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-color:inherit;border-radius:calc(var(--button-border-radius, 2px)*2);border-width:1px}.van-button--hairline.van-button--round:after{border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
================================================
FILE: dist/calendar/calendar.wxml
================================================
================================================
FILE: dist/calendar/components/header/index.d.ts
================================================
export {};
================================================
FILE: dist/calendar/components/header/index.js
================================================
import { VantComponent } from '../../../common/component';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
firstDayOfWeek: {
type: Number,
observer: 'initWeekDay',
},
},
data: {
weekdays: [],
},
created() {
this.initWeekDay();
},
methods: {
initWeekDay() {
const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
const firstDayOfWeek = this.data.firstDayOfWeek || 0;
this.setData({
weekdays: [
...defaultWeeks.slice(firstDayOfWeek, 7),
...defaultWeeks.slice(0, firstDayOfWeek),
],
});
},
onClickSubtitle(event) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: dist/calendar/components/header/index.json
================================================
{
"component": true
}
================================================
FILE: dist/calendar/components/header/index.wxml
================================================
================================================
FILE: dist/calendar/components/header/index.wxss
================================================
@import '../../../common/index.wxss';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}
================================================
FILE: dist/calendar/components/month/index.d.ts
================================================
export interface Day {
date: Date;
type: string;
text: number;
bottomInfo?: string;
}
================================================
FILE: dist/calendar/components/month/index.js
================================================
import { VantComponent } from '../../../common/component';
import { getMonthEndDay, compareDay, getPrevDay, getNextDay, } from '../../utils';
VantComponent({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: null,
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: null,
observer: 'setDays',
},
firstDayOfWeek: {
type: Number,
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [],
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays() {
const days = [];
const startDate = new Date(this.data.date);
const year = startDate.getFullYear();
const month = startDate.getMonth();
const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
for (let day = 1; day <= totalDay; day++) {
const date = new Date(year, month, day);
const type = this.getDayType(date);
let config = {
date,
type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days });
},
getMultipleDayType(day) {
const { currentDate } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const isSelected = (date) => currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
const nextDay = getNextDay(day);
const prevSelected = isSelected(prevDay);
const nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType(day) {
const { currentDate, allowSameDay } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const [startDay, endDay] = currentDate;
if (!startDay) {
return '';
}
const compareToStart = compareDay(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
const compareToEnd = compareDay(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
return '';
},
getDayType(day) {
const { type, minDate, maxDate, currentDate } = this.data;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
return '';
},
getBottomInfo(type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});
================================================
FILE: dist/calendar/components/month/index.json
================================================
{
"component": true
}
================================================
FILE: dist/calendar/components/month/index.wxml
================================================
{{ computed.formatMonthTitle(date) }}
{{ computed.getMark(date) }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
================================================
FILE: dist/calendar/components/month/index.wxs
================================================
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
var style = [];
var current = getDate(date).getDay() || 7;
var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
current === 7 && firstDayOfWeek === 0 ? 0 :
(current - firstDayOfWeek);
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'start-end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};
================================================
FILE: dist/calendar/components/month/index.wxss
================================================
@import '../../../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:100%}.van-calendar__month-title{font-size:var(--calendar-month-title-font-size,14px);font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__days{display:flex;flex-wrap:wrap;position:relative;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:var(--calendar-month-mark-font-size,160px);left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:0}.van-calendar__day,.van-calendar__selected-day{align-items:center;display:flex;justify-content:center;text-align:center}.van-calendar__day{font-size:var(--calendar-day-font-size,16px);height:var(--calendar-day-height,64px);position:relative;width:14.285%}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{background-color:var(--calendar-range-edge-background-color,#ee0a24);color:var(--calendar-range-edge-color,#fff)}.van-calendar__day--start{border-radius:4px 0 0 4px}.van-calendar__day--end{border-radius:0 4px 4px 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px}.van-calendar__day--middle{color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{background-color:currentColor;bottom:0;content:"";left:0;opacity:var(--calendar-range-middle-background-opacity,.1);position:absolute;right:0;top:0}.van-calendar__day--disabled{color:var(--calendar-day-disabled-color,#c8c9cc);cursor:default}.van-calendar__bottom-info,.van-calendar__top-info{font-size:var(--calendar-info-font-size,10px);left:0;line-height:var(--calendar-info-line-height,14px);position:absolute;right:0}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;color:var(--calendar-selected-day-color,#fff);height:var(--calendar-selected-day-size,54px);width:var(--calendar-selected-day-size,54px)}
================================================
FILE: dist/calendar/index.d.ts
================================================
export {};
================================================
FILE: dist/calendar/index.js
================================================
import { VantComponent } from '../common/component';
import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
import Toast from '../toast/toast';
import { requestAnimationFrame } from '../common/utils';
const initialMinDate = getToday().getTime();
const initialMaxDate = (() => {
const now = getToday();
return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
})();
const getTime = (date) => date instanceof Date ? date.getTime() : date;
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
confirmDisabledText: {
type: String,
value: '确定',
},
rangePrompt: String,
showRangePrompt: {
type: Boolean,
value: true,
},
defaultDate: {
type: null,
value: getToday().getTime(),
observer(val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: Number,
value: initialMinDate,
},
maxDate: {
type: Number,
value: initialMaxDate,
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: null,
value: ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: null,
value: null,
},
minRange: {
type: Number,
value: 1,
},
firstDayOfWeek: {
type: Number,
value: 0,
},
readonly: Boolean,
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
subtitle: '',
currentDate: null,
scrollIntoView: '',
},
watch: {
minDate() {
this.initRect();
},
maxDate() {
this.initRect();
},
},
created() {
this.setData({
currentDate: this.getInitialDate(this.data.defaultDate),
});
},
mounted() {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset() {
this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) });
this.scrollIntoView();
},
initRect() {
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', (res) => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
}
});
},
limitDateRange(date, minDate = null, maxDate = null) {
minDate = minDate || this.data.minDate;
maxDate = maxDate || this.data.maxDate;
if (compareDay(date, minDate) === -1) {
return minDate;
}
if (compareDay(date, maxDate) === 1) {
return maxDate;
}
return date;
},
getInitialDate(defaultDate = null) {
const { type, minDate, maxDate, allowSameDay } = this.data;
if (!defaultDate)
return [];
const now = getToday().getTime();
if (type === 'range') {
if (!Array.isArray(defaultDate)) {
defaultDate = [];
}
const [startDay, endDay] = defaultDate || [];
const startDate = getTime(startDay || now);
const start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : getPrevDay(new Date(maxDate)).getTime());
const date = getTime(endDay || now);
const end = this.limitDateRange(date, allowSameDay ? date : getNextDay(new Date(minDate)).getTime());
return [start, end];
}
if (type === 'multiple') {
if (Array.isArray(defaultDate)) {
return defaultDate.map((date) => this.limitDateRange(date));
}
return [this.limitDateRange(now)];
}
if (!defaultDate || Array.isArray(defaultDate)) {
defaultDate = now;
}
return this.limitDateRange(defaultDate);
},
scrollIntoView() {
requestAnimationFrame(() => {
const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
if (!currentDate)
return;
// @ts-ignore
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoView: `month${index}` });
return true;
}
return false;
});
});
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onClickDay(event) {
if (this.data.readonly) {
return;
}
let { date } = event.detail;
const { type, currentDate, allowSameDay } = this.data;
if (type === 'range') {
// @ts-ignore
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
const { days } = this.selectComponent('.month').data;
days.some((day, index) => {
const isDisabled = day.type === 'disabled' &&
getTime(startDay) < getTime(day.date) &&
getTime(day.date) < getTime(date);
if (isDisabled) {
({ date } = days[index - 1]);
}
return isDisabled;
});
this.select([startDay, date], true);
}
else if (compareToStart === -1) {
this.select([date, null]);
}
else if (allowSameDay) {
this.select([date, date], true);
}
}
else {
this.select([date, null]);
}
}
else if (type === 'multiple') {
let selectedIndex;
// @ts-ignore
const selected = currentDate.some((dateItem, index) => {
const equal = compareDay(dateItem, date) === 0;
if (equal) {
selectedIndex = index;
}
return equal;
});
if (selected) {
// @ts-ignore
const cancelDate = currentDate.splice(selectedIndex, 1);
this.setData({ currentDate });
this.unselect(cancelDate);
}
else {
// @ts-ignore
this.select([...currentDate, date]);
}
}
else {
this.select(date, true);
}
},
unselect(dateArray) {
const date = dateArray[0];
if (date) {
this.$emit('unselect', copyDates(date));
}
},
select(date, complete) {
if (complete && this.data.type === 'range') {
const valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
getDayByOffset(date[0], this.data.maxRange - 1),
]);
}
else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit(date) {
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', copyDates(date));
},
checkRange(date) {
const { maxRange, rangePrompt, showRangePrompt } = this.data;
if (maxRange && calcDateNum(date) > maxRange) {
if (showRangePrompt) {
Toast({
context: this,
message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
});
}
this.$emit('over-range');
return false;
}
return true;
},
onConfirm() {
if (this.data.type === 'range' &&
!this.checkRange(this.data.currentDate)) {
return;
}
wx.nextTick(() => {
// @ts-ignore
this.$emit('confirm', copyDates(this.data.currentDate));
});
},
onClickSubtitle(event) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: dist/calendar/index.json
================================================
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index",
"van-toast": "../toast/index"
}
}
================================================
FILE: dist/calendar/index.wxml
================================================
================================================
FILE: dist/calendar/index.wxs
================================================
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate, minRange) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return currentDate.length < minRange;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};
================================================
FILE: dist/calendar/index.wxss
================================================
@import '../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,90%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}
================================================
FILE: dist/calendar/utils.d.ts
================================================
export declare const ROW_HEIGHT = 64;
export declare function formatMonthTitle(date: Date): string;
export declare function compareMonth(date1: Date | number, date2: Date | number): 0 | 1 | -1;
export declare function compareDay(day1: Date | number, day2: Date | number): 0 | 1 | -1;
export declare function getDayByOffset(date: Date, offset: number): Date;
export declare function getPrevDay(date: Date): Date;
export declare function getNextDay(date: Date): Date;
export declare function getToday(): Date;
export declare function calcDateNum(date: [Date, Date]): number;
export declare function copyDates(dates: Date | Date[]): Date | Date[];
export declare function getMonthEndDay(year: number, month: number): number;
export declare function getMonths(minDate: number, maxDate: number): number[];
================================================
FILE: dist/calendar/utils.js
================================================
export const ROW_HEIGHT = 64;
export function formatMonthTitle(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return `${date.getFullYear()}年${date.getMonth() + 1}月`;
}
export function compareMonth(date1, date2) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
const year1 = date1.getFullYear();
const year2 = date2.getFullYear();
const month1 = date1.getMonth();
const month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
export function compareDay(day1, day2) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
const compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
const date1 = day1.getDate();
const date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
export function getDayByOffset(date, offset) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
export function getPrevDay(date) {
return getDayByOffset(date, -1);
}
export function getNextDay(date) {
return getDayByOffset(date, 1);
}
export function getToday() {
const today = new Date();
today.setHours(0, 0, 0, 0);
return today;
}
export function calcDateNum(date) {
const day1 = new Date(date[0]).getTime();
const day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
export function copyDates(dates) {
if (Array.isArray(dates)) {
return dates.map((date) => {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
export function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
export function getMonths(minDate, maxDate) {
const months = [];
const cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}
================================================
FILE: dist/calendar/utils.wxs
================================================
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};
================================================
FILE: dist/card/index.d.ts
================================================
export {};
================================================
FILE: dist/card/index.js
================================================
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class',
],
mixins: [link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit',
},
currency: {
type: String,
value: '¥',
},
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
onClickThumb() {
this.jumpLink('thumbLink');
},
},
});
================================================
FILE: dist/card/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}
================================================
FILE: dist/card/index.wxml
================================================
================================================
FILE: dist/card/index.wxss
================================================
@import '../common/index.wxss';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}
================================================
FILE: dist/cascader/index.d.ts
================================================
export {};
================================================
FILE: dist/cascader/index.js
================================================
import { VantComponent } from '../common/component';
var FieldName;
(function (FieldName) {
FieldName["TEXT"] = "text";
FieldName["VALUE"] = "value";
FieldName["CHILDREN"] = "children";
})(FieldName || (FieldName = {}));
const defaultFieldNames = {
text: FieldName.TEXT,
value: FieldName.VALUE,
children: FieldName.CHILDREN,
};
VantComponent({
props: {
title: String,
value: {
type: String,
},
placeholder: {
type: String,
value: '请选择',
},
activeColor: {
type: String,
value: '#1989fa',
},
options: {
type: Array,
value: [],
},
swipeable: {
type: Boolean,
value: false,
},
closeable: {
type: Boolean,
value: true,
},
ellipsis: {
type: Boolean,
value: true,
},
showHeader: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
fieldNames: {
type: Object,
value: defaultFieldNames,
observer: 'updateFieldNames',
},
useTitleSlot: Boolean,
},
data: {
tabs: [],
activeTab: 0,
textKey: FieldName.TEXT,
valueKey: FieldName.VALUE,
childrenKey: FieldName.CHILDREN,
innerValue: '',
},
watch: {
options() {
this.updateTabs();
},
value(newVal) {
this.updateValue(newVal);
},
},
created() {
this.updateTabs();
},
methods: {
updateValue(val) {
if (val !== undefined) {
const values = this.data.tabs.map((tab) => tab.selected && tab.selected[this.data.valueKey]);
if (values.indexOf(val) > -1) {
return;
}
}
this.innerValue = val;
this.updateTabs();
},
updateFieldNames() {
const { text = 'text', value = 'value', children = 'children', } = this.data.fieldNames || defaultFieldNames;
this.setData({
textKey: text,
valueKey: value,
childrenKey: children,
});
},
getSelectedOptionsByValue(options, value) {
for (let i = 0; i < options.length; i++) {
const option = options[i];
if (option[this.data.valueKey] === value) {
return [option];
}
if (option[this.data.childrenKey]) {
const selectedOptions = this.getSelectedOptionsByValue(option[this.data.childrenKey], value);
if (selectedOptions) {
return [option, ...selectedOptions];
}
}
}
},
updateTabs() {
const { options } = this.data;
const { innerValue } = this;
if (!options.length) {
return;
}
if (innerValue !== undefined) {
const selectedOptions = this.getSelectedOptionsByValue(options, innerValue);
if (selectedOptions) {
let optionsCursor = options;
const tabs = selectedOptions.map((option) => {
const tab = {
options: optionsCursor,
selected: option,
};
const next = optionsCursor.find((item) => item[this.data.valueKey] === option[this.data.valueKey]);
if (next) {
optionsCursor = next[this.data.childrenKey];
}
return tab;
});
if (optionsCursor) {
tabs.push({
options: optionsCursor,
selected: null,
});
}
this.setData({
tabs,
});
wx.nextTick(() => {
this.setData({
activeTab: tabs.length - 1,
});
});
return;
}
}
this.setData({
tabs: [
{
options,
selected: null,
},
],
activeTab: 0,
});
},
onClose() {
this.$emit('close');
},
onClickTab(e) {
const { index: tabIndex, title } = e.detail;
this.$emit('click-tab', { title, tabIndex });
this.setData({
activeTab: tabIndex,
});
},
// 选中
onSelect(e) {
const { option, tabIndex } = e.currentTarget.dataset;
if (option && option.disabled) {
return;
}
const { valueKey, childrenKey } = this.data;
let { tabs } = this.data;
tabs[tabIndex].selected = option;
if (tabs.length > tabIndex + 1) {
tabs = tabs.slice(0, tabIndex + 1);
}
if (option[childrenKey]) {
const nextTab = {
options: option[childrenKey],
selected: null,
};
if (tabs[tabIndex + 1]) {
tabs[tabIndex + 1] = nextTab;
}
else {
tabs.push(nextTab);
}
wx.nextTick(() => {
this.setData({
activeTab: tabIndex + 1,
});
});
}
this.setData({
tabs,
});
const selectedOptions = tabs.map((tab) => tab.selected).filter(Boolean);
const value = option[valueKey];
const params = {
value,
tabIndex,
selectedOptions,
};
this.innerValue = value;
this.$emit('change', params);
if (!option[childrenKey]) {
this.$emit('finish', params);
}
},
},
});
================================================
FILE: dist/cascader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-tab": "../tab/index",
"van-tabs": "../tabs/index"
}
}
================================================
FILE: dist/cascader/index.wxml
================================================
{{ option[textKey] }}
================================================
FILE: dist/cascader/index.wxs
================================================
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function isSelected(tab, valueKey, option) {
return tab.selected && tab.selected[valueKey] === option[valueKey]
}
function optionClass(tab, valueKey, option) {
return utils.bem('cascader__option', { selected: isSelected(tab, valueKey, option), disabled: option.disabled })
}
function optionStyle(data) {
var color = data.option.color || (isSelected(data.tab, data.valueKey, data.option) ? data.activeColor : undefined);
return style({
color
});
}
module.exports = {
isSelected: isSelected,
optionClass: optionClass,
optionStyle: optionStyle,
};
================================================
FILE: dist/cascader/index.wxss
================================================
@import '../common/index.wxss';.van-cascader__header{align-items:center;display:flex;height:48px;justify-content:space-between;padding:0 16px}.van-cascader__title{font-size:16px;font-weight:600;line-height:20px}.van-cascader__close-icon{color:#c8c9cc;font-size:22px;height:22px}.van-cascader__tabs-wrap{height:48px!important;padding:0 8px}.van-cascader__tab{color:#323233!important;flex:none!important;font-weight:600!important;padding:0 8px!important}.van-cascader__tab--unselected{color:#969799!important;font-weight:400!important}.van-cascader__option{align-items:center;cursor:pointer;display:flex;font-size:14px;justify-content:space-between;line-height:20px;padding:10px 16px}.van-cascader__option:active{background-color:#f2f3f5}.van-cascader__option--selected{color:#1989fa;font-weight:600}.van-cascader__option--disabled{color:#c8c9cc;cursor:not-allowed}.van-cascader__option--disabled:active{background-color:initial}.van-cascader__options{-webkit-overflow-scrolling:touch;box-sizing:border-box;height:384px;overflow-y:auto;padding-top:6px}
================================================
FILE: dist/cell/index.d.ts
================================================
export {};
================================================
FILE: dist/cell/index.js
================================================
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class',
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: dist/cell/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/cell/index.wxml
================================================
{{ title }}
{{ label }}
{{ value }}
================================================
FILE: dist/cell/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};
================================================
FILE: dist/cell/index.wxss
================================================
@import '../common/index.wxss';.van-cell{background-color:var(--cell-background-color,#fff);box-sizing:border-box;color:var(--cell-text-color,#323233);display:flex;font-size:var(--cell-font-size,14px);line-height:var(--cell-line-height,24px);padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);position:relative;width:100%}.van-cell:after{border-bottom:1px solid #ebedf0;bottom:0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:16px;transform:scaleY(.5);transform-origin:center}.van-cell--borderless:after{display:none}.van-cell-group{background-color:var(--cell-background-color,#fff)}.van-cell__label{color:var(--cell-label-color,#969799);font-size:var(--cell-label-font-size,12px);line-height:var(--cell-label-line-height,18px);margin-top:var(--cell-label-margin-top,3px)}.van-cell__value{color:var(--cell-value-color,#969799);overflow:hidden;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{align-items:center;display:flex;font-size:var(--cell-icon-size,16px);height:var(--cell-line-height,24px)}.van-cell__left-icon-wrap{margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{color:var(--cell-right-icon-color,#969799);margin-left:var(--padding-base,4px)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{color:var(--cell-required-color,#ee0a24);content:"*";font-size:var(--cell-font-size,14px);left:var(--padding-xs,8px);position:absolute}.van-cell--center{align-items:center}.van-cell--large{padding-bottom:var(--cell-large-vertical-padding,12px);padding-top:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:var(--cell-large-label-font-size,14px)}
================================================
FILE: dist/cell-group/index.d.ts
================================================
export {};
================================================
FILE: dist/cell-group/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
inset: Boolean,
},
});
================================================
FILE: dist/cell-group/index.json
================================================
{
"component": true
}
================================================
FILE: dist/cell-group/index.wxml
================================================
{{ title }}
================================================
FILE: dist/cell-group/index.wxss
================================================
@import '../common/index.wxss';.van-cell-group--inset{border-radius:var(--cell-group-inset-border-radius,8px);margin:var(--cell-group-inset-padding,0 16px);overflow:hidden}.van-cell-group__title{color:var(--cell-group-title-color,#969799);font-size:var(--cell-group-title-font-size,14px);line-height:var(--cell-group-title-line-height,16px);padding:var(--cell-group-title-padding,16px 16px 8px)}.van-cell-group__title--inset{padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)}
================================================
FILE: dist/checkbox/index.d.ts
================================================
export {};
================================================
FILE: dist/checkbox/index.js
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
function emit(target, value) {
target.$emit('input', value);
target.$emit('change', value);
}
VantComponent({
field: true,
relation: useParent('checkbox-group'),
classes: ['icon-class', 'label-class'],
props: {
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
direction: 'vertical',
},
methods: {
emitChange(value) {
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
emit(this, value);
}
},
toggle() {
const { parentDisabled, disabled, value } = this.data;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel() {
const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
setParentValue(parent, value) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
const { max } = parent.data;
if (value) {
if (max && parentValue.length >= max) {
return;
}
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
emit(parent, parentValue);
}
}
else {
const index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
},
},
});
================================================
FILE: dist/checkbox/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/checkbox/index.wxml
================================================
================================================
FILE: dist/checkbox/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = {
'font-size': addUnit(iconSize),
};
if (checkedColor && value && !disabled && !parentDisabled) {
styles['border-color'] = checkedColor;
styles['background-color'] = checkedColor;
}
return style(styles);
}
module.exports = {
iconStyle: iconStyle,
};
================================================
FILE: dist/checkbox/index.wxss
================================================
@import '../common/index.wxss';.van-checkbox{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{flex:none}.van-checkbox__icon{align-items:center;border:1px solid var(--checkbox-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--checkbox-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--checkbox-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:var(--checkbox-checked-icon-color,#1989fa);color:#fff}.van-checkbox__icon--disabled{background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;color:var(--checkbox-label-color,#323233);padding-left:var(--checkbox-label-margin,10px)}.van-checkbox__label--left{float:left;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
================================================
FILE: dist/checkbox-group/index.d.ts
================================================
export {};
================================================
FILE: dist/checkbox-group/index.js
================================================
import { useChildren } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: useChildren('checkbox', function (target) {
this.updateChild(target);
}),
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren',
},
direction: {
type: String,
value: 'vertical',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => this.updateChild(child));
},
updateChild(child) {
const { value, disabled, direction } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled,
direction,
});
},
},
});
================================================
FILE: dist/checkbox-group/index.json
================================================
{
"component": true
}
================================================
FILE: dist/checkbox-group/index.wxml
================================================
================================================
FILE: dist/checkbox-group/index.wxss
================================================
@import '../common/index.wxss';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap}
================================================
FILE: dist/circle/canvas.d.ts
================================================
///
type CanvasContext = WechatMiniprogram.CanvasContext;
export declare function adaptor(ctx: CanvasContext & Record): CanvasContext;
export {};
================================================
FILE: dist/circle/canvas.js
================================================
export function adaptor(ctx) {
// @ts-ignore
return Object.assign(ctx, {
setStrokeStyle(val) {
ctx.strokeStyle = val;
},
setLineWidth(val) {
ctx.lineWidth = val;
},
setLineCap(val) {
ctx.lineCap = val;
},
setFillStyle(val) {
ctx.fillStyle = val;
},
setFontSize(val) {
ctx.font = String(val);
},
setGlobalAlpha(val) {
ctx.globalAlpha = val;
},
setLineJoin(val) {
ctx.lineJoin = val;
},
setTextAlign(val) {
ctx.textAlign = val;
},
setMiterLimit(val) {
ctx.miterLimit = val;
},
setShadow(offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline(val) {
ctx.textBaseline = val;
},
createCircularGradient() { },
draw() { },
});
}
================================================
FILE: dist/circle/index.d.ts
================================================
export {};
================================================
FILE: dist/circle/index.js
================================================
import { BLUE, WHITE } from '../common/color';
import { VantComponent } from '../common/component';
import { getSystemInfoSync } from '../common/utils';
import { isObj } from '../common/validator';
import { canIUseCanvas2d } from '../common/version';
import { adaptor } from './canvas';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round',
},
value: {
type: Number,
value: 0,
observer: 'reRender',
},
speed: {
type: Number,
value: 50,
},
size: {
type: Number,
value: 100,
observer() {
this.drawCircle(this.currentValue);
},
},
fill: String,
layerColor: {
type: String,
value: WHITE,
},
color: {
type: null,
value: BLUE,
observer() {
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
},
type: {
type: String,
value: '',
},
strokeWidth: {
type: Number,
value: 4,
},
clockwise: {
type: Boolean,
value: true,
},
},
data: {
hoverColor: BLUE,
},
methods: {
getContext() {
const { type, size } = this.data;
if (type === '' || !canIUseCanvas2d()) {
const ctx = wx.createCanvasContext('van-circle', this);
return Promise.resolve(ctx);
}
const dpr = getSystemInfoSync().pixelRatio;
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(this)
.select('#van-circle')
.node()
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext(type);
if (!this.inited) {
this.inited = true;
canvas.width = size * dpr;
canvas.height = size * dpr;
ctx.scale(dpr, dpr);
}
resolve(adaptor(ctx));
});
});
},
setHoverColor() {
const { color, size } = this.data;
if (isObj(color)) {
return this.getContext().then((context) => {
if (!context)
return;
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
this.hoverColor = LinearColor;
});
}
this.hoverColor = color;
return Promise.resolve();
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const { size } = this.data;
this.getContext().then((context) => {
if (!context)
return;
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
});
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearMockInterval();
this.currentValue = this.currentValue || 0;
const run = () => {
this.interval = setTimeout(() => {
if (this.currentValue !== value) {
if (Math.abs(this.currentValue - value) < STEP) {
this.currentValue = value;
}
else if (this.currentValue < value) {
this.currentValue += STEP;
}
else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
run();
}
else {
this.clearMockInterval();
}
}, 1000 / speed);
};
run();
},
clearMockInterval() {
if (this.interval) {
clearTimeout(this.interval);
this.interval = null;
}
},
},
mounted() {
this.currentValue = this.data.value;
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
destroyed() {
this.clearMockInterval();
},
});
================================================
FILE: dist/circle/index.json
================================================
{
"component": true
}
================================================
FILE: dist/circle/index.wxml
================================================
{{ text }}
================================================
FILE: dist/circle/index.wxss
================================================
@import '../common/index.wxss';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}
================================================
FILE: dist/col/index.d.ts
================================================
export {};
================================================
FILE: dist/col/index.js
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('row'),
props: {
span: Number,
offset: Number,
},
});
================================================
FILE: dist/col/index.json
================================================
{
"component": true
}
================================================
FILE: dist/col/index.wxml
================================================
================================================
FILE: dist/col/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'padding-right': addUnit(data.gutter / 2),
'padding-left': addUnit(data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/col/index.wxss
================================================
@import '../common/index.wxss';.van-col{box-sizing:border-box;float:left}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
================================================
FILE: dist/collapse/index.d.ts
================================================
export {};
================================================
FILE: dist/collapse/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('collapse-item'),
props: {
value: {
type: null,
observer: 'updateExpanded',
},
accordion: {
type: Boolean,
observer: 'updateExpanded',
},
border: {
type: Boolean,
value: true,
},
},
methods: {
updateExpanded() {
this.children.forEach((child) => {
child.updateExpanded();
});
},
switch(name, expanded) {
const { accordion, value } = this.data;
const changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
}
else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
}
else {
this.$emit('close', changeItem);
}
this.$emit('change', name);
this.$emit('input', name);
},
},
});
================================================
FILE: dist/collapse/index.json
================================================
{
"component": true
}
================================================
FILE: dist/collapse/index.wxml
================================================
================================================
FILE: dist/collapse/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: dist/collapse-item/animate.d.ts
================================================
///
export declare function setContentAnimate(context: WechatMiniprogram.Component.TrivialInstance, expanded: boolean, mounted: boolean): void;
================================================
FILE: dist/collapse-item/animate.js
================================================
import { getRect } from '../common/utils';
function useAnimation(context, expanded, mounted, height) {
const animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
}
else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
export function setContentAnimate(context, expanded, mounted) {
getRect(context, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height) => {
useAnimation(context, expanded, mounted, height);
});
}
================================================
FILE: dist/collapse-item/index.d.ts
================================================
export {};
================================================
FILE: dist/collapse-item/index.js
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { setContentAnimate } from './animate';
VantComponent({
classes: ['title-class', 'content-class'],
relation: useParent('collapse'),
props: {
size: String,
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true,
},
isLink: {
type: Boolean,
value: true,
},
},
data: {
expanded: false,
parentBorder: true,
},
mounted() {
this.updateExpanded();
this.mounted = true;
},
methods: {
updateExpanded() {
if (!this.parent) {
return;
}
const { value, accordion, border } = this.parent.data;
const { children = [] } = this.parent;
const { name } = this.data;
const index = children.indexOf(this);
const currentName = name == null ? index : name;
const expanded = accordion
? value === currentName
: (value || []).some((name) => name === currentName);
if (expanded !== this.data.expanded) {
setContentAnimate(this, expanded, this.mounted);
}
this.setData({ index, expanded, parentBorder: border });
},
onClick() {
if (this.data.disabled) {
return;
}
const { name, expanded } = this.data;
const index = this.parent.children.indexOf(this);
const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
},
},
});
================================================
FILE: dist/collapse-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: dist/collapse-item/index.wxml
================================================
================================================
FILE: dist/collapse-item/index.wxss
================================================
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{transform:rotate(90deg);transition:transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{background-color:var(--collapse-item-content-background-color,#fff);color:var(--collapse-item-content-text-color,#969799);font-size:var(--collapse-item-content-font-size,13px);line-height:var(--collapse-item-content-line-height,1.5);padding:var(--collapse-item-content-padding,15px)}
================================================
FILE: dist/common/color.d.ts
================================================
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
================================================
FILE: dist/common/color.js
================================================
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
================================================
FILE: dist/common/component.d.ts
================================================
///
import { VantComponentOptions } from 'definitions/index';
declare function VantComponent(vantOptions: VantComponentOptions): void;
export { VantComponent };
================================================
FILE: dist/common/component.js
================================================
import { basic } from '../mixins/basic';
function mapKeys(source, target, map) {
Object.keys(map).forEach((key) => {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent(vantOptions) {
const options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
watch: 'observers',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
destroyed: 'detached',
classes: 'externalClasses',
});
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// add relations
const { relation } = vantOptions;
if (relation) {
options.relations = relation.relations;
options.behaviors.push(relation.mixin);
}
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true,
};
Component(options);
}
export { VantComponent };
================================================
FILE: dist/common/index.wxss
================================================
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
================================================
FILE: dist/common/relation.d.ts
================================================
///
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export {};
================================================
FILE: dist/common/relation.js
================================================
export function useParent(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'ancestor',
linked() {
onEffect && onEffect.call(this);
},
linkChanged() {
onEffect && onEffect.call(this);
},
unlinked() {
onEffect && onEffect.call(this);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'parent', {
get: () => this.getRelationNodes(path)[0],
});
Object.defineProperty(this, 'index', {
// @ts-ignore
get: () => { var _a, _b; return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.indexOf(this); },
});
},
}),
};
}
export function useChildren(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'descendant',
linked(target) {
onEffect && onEffect.call(this, target);
},
linkChanged(target) {
onEffect && onEffect.call(this, target);
},
unlinked(target) {
onEffect && onEffect.call(this, target);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'children', {
get: () => this.getRelationNodes(path) || [],
});
},
}),
};
}
================================================
FILE: dist/common/style/clearfix.wxss
================================================
.van-clearfix:after{clear:both;content:"";display:table}
================================================
FILE: dist/common/style/ellipsis.wxss
================================================
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
================================================
FILE: dist/common/style/hairline.wxss
================================================
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
================================================
FILE: dist/common/style/mixins/clearfix.wxss
================================================
================================================
FILE: dist/common/style/mixins/ellipsis.wxss
================================================
================================================
FILE: dist/common/style/mixins/hairline.wxss
================================================
================================================
FILE: dist/common/style/var.wxss
================================================
================================================
FILE: dist/common/utils.d.ts
================================================
///
///
///
///
///
export { isDef } from './validator';
export { getSystemInfoSync } from './version';
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(cb: (...args: any[]) => void): void;
export declare function addUnit(value?: string | number): string | undefined;
export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout;
export declare function pickExclude(obj: unknown, keys: string[]): {};
export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise;
export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise;
export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void;
export declare function toPromise(promiseLike: Promise | unknown): Promise;
export declare function addNumber(num1: any, num2: any): number;
export declare const clamp: (num: any, min: any, max: any) => number;
export declare function getCurrentPage(): T & WechatMiniprogram.OptionalInterface & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods & WechatMiniprogram.Page.Data & WechatMiniprogram.IAnyObject;
export declare const isPC: boolean;
export declare const isWxWork: boolean;
================================================
FILE: dist/common/utils.js
================================================
import { isDef, isNumber, isPlainObject, isPromise } from './validator';
import { canIUseGroupSetData, canIUseNextTick, getSystemInfoSync, } from './version';
export { isDef } from './validator';
export { getSystemInfoSync } from './version';
export function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
export function nextTick(cb) {
if (canIUseNextTick()) {
wx.nextTick(cb);
}
else {
setTimeout(() => {
cb();
}, 1000 / 30);
}
}
export function addUnit(value) {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
export function requestAnimationFrame(cb) {
return setTimeout(() => {
cb();
}, 1000 / 30);
}
export function pickExclude(obj, keys) {
if (!isPlainObject(obj)) {
return {};
}
return Object.keys(obj).reduce((prev, key) => {
if (!keys.includes(key)) {
prev[key] = obj[key];
}
return prev;
}, {});
}
export function getRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.select(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function getAllRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.selectAll(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function groupSetData(context, cb) {
if (canIUseGroupSetData()) {
context.groupSetData(cb);
}
else {
cb();
}
}
export function toPromise(promiseLike) {
if (isPromise(promiseLike)) {
return promiseLike;
}
return Promise.resolve(promiseLike);
}
// 浮点数精度处理
export function addNumber(num1, num2) {
const cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
// 限制value在[min, max]之间
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
export function getCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export const isPC = ['mac', 'windows'].includes(getSystemInfoSync().platform);
// 是否企业微信
export const isWxWork = getSystemInfoSync().environment === 'wxwork';
================================================
FILE: dist/common/validator.d.ts
================================================
export declare function isFunction(val: unknown): val is Function;
export declare function isPlainObject(val: unknown): val is Record;
export declare function isPromise(val: unknown): val is Promise;
export declare function isDef(value: unknown): boolean;
export declare function isObj(x: unknown): x is Record;
export declare function isNumber(value: string): boolean;
export declare function isBoolean(value: unknown): value is boolean;
export declare function isImageUrl(url: string): boolean;
export declare function isVideoUrl(url: string): boolean;
================================================
FILE: dist/common/validator.js
================================================
// eslint-disable-next-line @typescript-eslint/ban-types
export function isFunction(val) {
return typeof val === 'function';
}
export function isPlainObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
export function isPromise(val) {
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
}
export function isDef(value) {
return value !== undefined && value !== null;
}
export function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
export function isNumber(value) {
return /^\d+(\.\d+)?$/.test(value);
}
export function isBoolean(value) {
return typeof value === 'boolean';
}
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
export function isImageUrl(url) {
return IMAGE_REGEXP.test(url);
}
export function isVideoUrl(url) {
return VIDEO_REGEXP.test(url);
}
================================================
FILE: dist/common/version.d.ts
================================================
///
interface WxWorkSystemInfo extends WechatMiniprogram.SystemInfo {
environment?: 'wxwork';
}
interface SystemInfo extends WxWorkSystemInfo, WechatMiniprogram.SystemInfo {
}
export declare function getSystemInfoSync(): SystemInfo;
export declare function canIUseModel(): boolean;
export declare function canIUseFormFieldButton(): boolean;
export declare function canIUseAnimate(): boolean;
export declare function canIUseGroupSetData(): boolean;
export declare function canIUseNextTick(): boolean;
export declare function canIUseCanvas2d(): boolean;
export declare function canIUseGetUserProfile(): boolean;
export {};
================================================
FILE: dist/common/version.js
================================================
let systemInfo;
export function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo;
}
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
function gte(version) {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, version) >= 0;
}
export function canIUseModel() {
return gte('2.9.3');
}
export function canIUseFormFieldButton() {
return gte('2.10.3');
}
export function canIUseAnimate() {
return gte('2.9.0');
}
export function canIUseGroupSetData() {
return gte('2.4.0');
}
export function canIUseNextTick() {
try {
return wx.canIUse('nextTick');
}
catch (e) {
return gte('2.7.1');
}
}
export function canIUseCanvas2d() {
return gte('2.9.0');
}
export function canIUseGetUserProfile() {
return !!wx.getUserProfile;
}
================================================
FILE: dist/config-provider/index.d.ts
================================================
export {};
================================================
FILE: dist/config-provider/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
themeVars: {
type: Object,
value: {},
},
},
});
================================================
FILE: dist/config-provider/index.json
================================================
{
"component": true
}
================================================
FILE: dist/config-provider/index.wxml
================================================
================================================
FILE: dist/config-provider/index.wxs
================================================
/* eslint-disable */
var object = require('../wxs/object.wxs');
var style = require('../wxs/style.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
.replace(getRegExp("^-"), '');
return newWord;
}
function mapThemeVarsToCSSVars(themeVars) {
var cssVars = {};
object.keys(themeVars).forEach(function (key) {
var cssVarsKey = '--' + kebabCase(key);
cssVars[cssVarsKey] = themeVars[key];
});
return style(cssVars);
}
module.exports = {
kebabCase: kebabCase,
mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
};
================================================
FILE: dist/count-down/index.d.ts
================================================
export {};
================================================
FILE: dist/count-down/index.js
================================================
import { VantComponent } from '../common/component';
import { isSameSecond, parseFormat, parseTimeData } from './utils';
function simpleTick(fn) {
return setTimeout(fn, 30);
}
VantComponent({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset',
},
format: {
type: String,
value: 'HH:mm:ss',
},
autoStart: {
type: Boolean,
value: true,
},
},
data: {
timeData: parseTimeData(0),
formattedTime: '0',
},
destroyed() {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start() {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause() {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset() {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick() {
if (this.data.millisecond) {
this.microTick();
}
else {
this.macroTick();
}
},
microTick() {
this.tid = simpleTick(() => {
this.setRemain(this.getRemain());
if (this.remain !== 0) {
this.microTick();
}
});
},
macroTick() {
this.tid = simpleTick(() => {
const remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain !== 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
const timeData = parseTimeData(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: parseFormat(this.data.format, timeData),
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
},
});
================================================
FILE: dist/count-down/index.json
================================================
{
"component": true
}
================================================
FILE: dist/count-down/index.wxml
================================================
{{ formattedTime }}
================================================
FILE: dist/count-down/index.wxss
================================================
@import '../common/index.wxss';.van-count-down{color:var(--count-down-text-color,#323233);font-size:var(--count-down-font-size,14px);line-height:var(--count-down-line-height,20px)}
================================================
FILE: dist/count-down/utils.d.ts
================================================
export type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
export declare function parseTimeData(time: number): TimeData;
export declare function parseFormat(format: string, timeData: TimeData): string;
export declare function isSameSecond(time1: number, time2: number): boolean;
================================================
FILE: dist/count-down/utils.js
================================================
function padZero(num, targetLength = 2) {
let str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
export function parseTimeData(time) {
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
days,
hours,
minutes,
seconds,
milliseconds,
};
}
export function parseFormat(format, timeData) {
const { days } = timeData;
let { hours, minutes, seconds, milliseconds } = timeData;
if (format.indexOf('DD') === -1) {
hours += days * 24;
}
else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
}
else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
}
else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
}
else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
================================================
FILE: dist/datetime-picker/index.d.ts
================================================
export {};
================================================
FILE: dist/datetime-picker/index.js
================================================
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pickerProps } from '../picker/shared';
const currentYear = new Date().getFullYear();
function isValidDate(date) {
return isDef(date) && !isNaN(new Date(date).getTime());
}
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function padZero(val) {
return `00${val}`.slice(-2);
}
function times(n, iteratee) {
let index = -1;
const result = Array(n < 0 ? 0 : n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
function getTrueValue(formattedValue) {
if (formattedValue === undefined) {
formattedValue = '1';
}
while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1);
}
return parseInt(formattedValue, 10);
}
function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
const defaultFormatter = (type, value) => value;
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { value: {
type: null,
observer: 'updateValue',
}, filter: null, type: {
type: String,
value: 'datetime',
observer: 'updateValue',
}, showToolbar: {
type: Boolean,
value: true,
}, formatter: {
type: null,
value: defaultFormatter,
}, minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime(),
observer: 'updateValue',
}, maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime(),
observer: 'updateValue',
}, minHour: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxHour: {
type: Number,
value: 23,
observer: 'updateValue',
}, minMinute: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxMinute: {
type: Number,
value: 59,
observer: 'updateValue',
} }),
data: {
innerValue: Date.now(),
columns: [],
},
methods: {
updateValue() {
const { data } = this;
const val = this.correctValue(data.value);
const isEqual = val === data.innerValue;
this.updateColumnValue(val).then(() => {
if (!isEqual) {
this.$emit('input', val);
}
});
},
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this;
const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
const { formatter = defaultFormatter } = this.data;
const results = this.getOriginColumns().map((column) => ({
values: column.values.map((value) => formatter(column.type, value)),
}));
return this.set({ columns: results });
},
getOriginColumns() {
const { filter } = this.data;
const results = this.getRanges().map(({ type, range }) => {
let values = times(range[1] - range[0] + 1, (index) => {
const value = range[0] + index;
return type === 'year' ? `${value}` : padZero(value);
});
if (filter) {
values = filter(type, values);
}
return { type, values };
});
return results;
},
getRanges() {
const { data } = this;
if (data.type === 'time') {
return [
{
type: 'hour',
range: [data.minHour, data.maxHour],
},
{
type: 'minute',
range: [data.minMinute, data.maxMinute],
},
];
}
const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', data.innerValue);
const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', data.innerValue);
const result = [
{
type: 'year',
range: [minYear, maxYear],
},
{
type: 'month',
range: [minMonth, maxMonth],
},
{
type: 'day',
range: [minDate, maxDate],
},
{
type: 'hour',
range: [minHour, maxHour],
},
{
type: 'minute',
range: [minMinute, maxMinute],
},
];
if (data.type === 'date')
result.splice(3, 2);
if (data.type === 'year-month')
result.splice(2, 3);
return result;
},
correctValue(value) {
const { data } = this;
// validate value
const isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) {
value = data.minDate;
}
else if (!isDateType && !value) {
const { minHour } = data;
value = `${padZero(minHour)}:00`;
}
// time type
if (!isDateType) {
let [hour, minute] = value.split(':');
hour = padZero(range(hour, data.minHour, data.maxHour));
minute = padZero(range(minute, data.minMinute, data.maxMinute));
return `${hour}:${minute}`;
}
// date type
value = Math.max(value, data.minDate);
value = Math.min(value, data.maxDate);
return value;
},
getBoundary(type, innerValue) {
const value = new Date(innerValue);
const boundary = new Date(this.data[`${type}Date`]);
const year = boundary.getFullYear();
let month = 1;
let date = 1;
let hour = 0;
let minute = 0;
if (type === 'max') {
month = 12;
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
hour = 23;
minute = 59;
}
if (value.getFullYear() === year) {
month = boundary.getMonth() + 1;
if (value.getMonth() + 1 === month) {
date = boundary.getDate();
if (value.getDate() === date) {
hour = boundary.getHours();
if (value.getHours() === hour) {
minute = boundary.getMinutes();
}
}
}
}
return {
[`${type}Year`]: year,
[`${type}Month`]: month,
[`${type}Date`]: date,
[`${type}Hour`]: hour,
[`${type}Minute`]: minute,
};
},
onCancel() {
this.$emit('cancel');
},
onConfirm() {
this.$emit('confirm', this.data.innerValue);
},
onChange() {
const { data } = this;
let value;
const picker = this.getPicker();
const originColumns = this.getOriginColumns();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1]
.values[indexes[1]]}`;
}
else {
const indexes = picker.getIndexes();
const values = indexes.map((value, index) => originColumns[index].values[value]);
const year = getTrueValue(values[0]);
const month = getTrueValue(values[1]);
const maxDate = getMonthEndDay(year, month);
let date = getTrueValue(values[2]);
if (data.type === 'year-month') {
date = 1;
}
date = date > maxDate ? maxDate : date;
let hour = 0;
let minute = 0;
if (data.type === 'datetime') {
hour = getTrueValue(values[3]);
minute = getTrueValue(values[4]);
}
value = new Date(year, month - 1, date, hour, minute);
}
value = this.correctValue(value);
this.updateColumnValue(value).then(() => {
this.$emit('input', value);
this.$emit('change', picker);
});
},
updateColumnValue(value) {
let values = [];
const { type } = this.data;
const formatter = this.data.formatter || defaultFormatter;
const picker = this.getPicker();
if (type === 'time') {
const pair = value.split(':');
values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
}
else {
const date = new Date(value);
values = [
formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1)),
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
if (type === 'datetime') {
values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
}
}
return this.set({ innerValue: value })
.then(() => this.updateColumns())
.then(() => picker.setValues(values));
},
},
created() {
const innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(() => {
this.$emit('input', innerValue);
});
},
});
================================================
FILE: dist/datetime-picker/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: dist/datetime-picker/index.wxml
================================================
================================================
FILE: dist/datetime-picker/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: dist/definitions/index.d.ts
================================================
///
interface VantComponentInstance {
parent: WechatMiniprogram.Component.TrivialInstance;
children: WechatMiniprogram.Component.TrivialInstance[];
index: number;
$emit: (name: string, detail?: unknown, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
setView: (value: Record, callback?: () => void) => void;
}
export type VantComponentOptions = {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props;
relation?: {
relations: Record;
mixin: string;
};
watch?: Record any>;
methods?: Methods;
beforeCreate?: () => void;
created?: () => void;
mounted?: () => void;
destroyed?: () => void;
} & ThisType, Props, Methods> & Record>;
export {};
================================================
FILE: dist/definitions/index.js
================================================
export {};
================================================
FILE: dist/dialog/dialog.d.ts
================================================
///
///
export type Action = 'confirm' | 'cancel' | 'overlay';
type DialogContext = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
interface DialogOptions {
lang?: string;
show?: boolean;
title?: string;
width?: string | number | null;
zIndex?: number;
theme?: string;
context?: (() => DialogContext) | DialogContext;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
/**
* @deprecated use custom-class instead
*/
className?: string;
customStyle?: string;
transition?: string;
/**
* @deprecated use beforeClose instead
*/
asyncClose?: boolean;
beforeClose?: null | ((action: Action) => Promise | void);
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
showMessageCard?: boolean;
sendMessagePath?: string;
sendMessageTitle?: string;
confirmButtonText?: string;
cancelButtonText?: string;
showConfirmButton?: boolean;
showCancelButton?: boolean;
closeOnClickOverlay?: boolean;
confirmButtonOpenType?: string;
}
declare const Dialog: {
(options: DialogOptions): Promise;
alert(options: DialogOptions): Promise;
confirm(options: DialogOptions): Promise;
close(): void;
stopLoading(): void;
currentOptions: DialogOptions;
defaultOptions: DialogOptions;
setDefaultOptions(options: DialogOptions): void;
resetDefaultOptions(): void;
};
export default Dialog;
================================================
FILE: dist/dialog/dialog.js
================================================
let queue = [];
const defaultOptions = {
show: false,
title: '',
width: null,
theme: 'default',
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
asyncClose: false,
beforeClose: null,
transition: 'scale',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: '',
};
let currentOptions = Object.assign({}, defaultOptions);
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Dialog = (options) => {
options = Object.assign(Object.assign({}, currentOptions), options);
return new Promise((resolve, reject) => {
const context = (typeof options.context === 'function'
? options.context()
: options.context) || getContext();
const dialog = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (dialog) {
dialog.setData(Object.assign({ callback: (action, instance) => {
action === 'confirm' ? resolve(instance) : reject(instance);
} }, options));
wx.nextTick(() => {
dialog.setData({ show: true });
});
queue.push(dialog);
}
else {
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
}
});
};
Dialog.alert = (options) => Dialog(options);
Dialog.confirm = (options) => Dialog(Object.assign({ showCancelButton: true }, options));
Dialog.close = () => {
queue.forEach((dialog) => {
dialog.close();
});
queue = [];
};
Dialog.stopLoading = () => {
queue.forEach((dialog) => {
dialog.stopLoading();
});
};
Dialog.currentOptions = currentOptions;
Dialog.defaultOptions = defaultOptions;
Dialog.setDefaultOptions = (options) => {
currentOptions = Object.assign(Object.assign({}, currentOptions), options);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions = () => {
currentOptions = Object.assign({}, defaultOptions);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions();
export default Dialog;
================================================
FILE: dist/dialog/index.d.ts
================================================
export {};
================================================
FILE: dist/dialog/index.js
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { GRAY, RED } from '../common/color';
import { toPromise } from '../common/utils';
VantComponent({
mixins: [button],
classes: ['cancle-button-class', 'confirm-button-class'],
props: {
show: {
type: Boolean,
observer(show) {
!show && this.stopLoading();
},
},
title: String,
message: String,
theme: {
type: String,
value: 'default',
},
confirmButtonId: String,
className: String,
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
beforeClose: null,
overlayStyle: String,
useSlot: Boolean,
useTitleSlot: Boolean,
useConfirmButtonSlot: Boolean,
useCancelButtonSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: null,
zIndex: {
type: Number,
value: 2000,
},
confirmButtonText: {
type: String,
value: '确认',
},
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonColor: {
type: String,
value: RED,
},
cancelButtonColor: {
type: String,
value: GRAY,
},
showConfirmButton: {
type: Boolean,
value: true,
},
overlay: {
type: Boolean,
value: true,
},
transition: {
type: String,
value: 'scale',
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
loading: {
confirm: false,
cancel: false,
},
callback: (() => { }),
},
methods: {
onConfirm() {
this.handleAction('confirm');
},
onCancel() {
this.handleAction('cancel');
},
onClickOverlay() {
this.close('overlay');
},
close(action) {
this.setData({ show: false });
this.closeAction = action;
},
onAfterLeave() {
const { closeAction: action } = this;
this.$emit('close', action);
const { callback } = this.data;
if (callback) {
callback(action, this);
}
},
stopLoading() {
this.setData({
loading: {
confirm: false,
cancel: false,
},
});
},
handleAction(action) {
this.$emit(action, { dialog: this });
const { asyncClose, beforeClose } = this.data;
if (!asyncClose && !beforeClose) {
this.close(action);
return;
}
this.setData({
[`loading.${action}`]: true,
});
if (beforeClose) {
toPromise(beforeClose(action)).then((value) => {
if (value) {
this.close(action);
}
else {
this.stopLoading();
}
});
}
},
},
});
================================================
FILE: dist/dialog/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-button": "../button/index",
"van-goods-action": "../goods-action/index",
"van-goods-action-button": "../goods-action-button/index"
}
}
================================================
FILE: dist/dialog/index.wxml
================================================
{{ message }}
{{ cancelButtonText }}
{{ confirmButtonText }}
================================================
FILE: dist/dialog/index.wxss
================================================
@import '../common/index.wxss';.van-dialog{background-color:var(--dialog-background-color,#fff);border-radius:var(--dialog-border-radius,16px);font-size:var(--dialog-font-size,16px);overflow:hidden;top:45%!important;width:var(--dialog-width,320px)}@media (max-width:321px){.van-dialog{width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-weight:var(--dialog-header-font-weight,500);line-height:var(--dialog-header-line-height,24px);padding-top:var(--dialog-header-padding-top,24px);text-align:center}.van-dialog__header--isolated{padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{-webkit-overflow-scrolling:touch;font-size:var(--dialog-message-font-size,14px);line-height:var(--dialog-message-line-height,20px);max-height:var(--dialog-message-max-height,60vh);overflow-y:auto;padding:var(--dialog-message-padding,24px);text-align:center}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--hasTitle{color:var(--dialog-has-title-message-text-color,#646566);padding-top:var(--dialog-has-title-message-padding-top,8px)}.van-dialog__message--round-button{color:#323233;padding-bottom:16px}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__message--justify{text-align:justify}.van-dialog__footer{display:flex}.van-dialog__footer--round-button{padding:8px 24px 16px!important;position:relative!important}.van-dialog__button{flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;transform:translate3d(-50%,-50%,0) scale(.9)}
================================================
FILE: dist/divider/index.d.ts
================================================
export {};
================================================
FILE: dist/divider/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: Boolean,
hairline: Boolean,
contentPosition: String,
fontSize: String,
borderColor: String,
textColor: String,
customStyle: String,
},
});
================================================
FILE: dist/divider/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: dist/divider/index.wxml
================================================
================================================
FILE: dist/divider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
'border-color': data.borderColor,
color: data.textColor,
'font-size': addUnit(data.fontSize),
},
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/divider/index.wxss
================================================
@import '../common/index.wxss';.van-divider{align-items:center;border:0 solid var(--divider-border-color,#ebedf0);color:var(--divider-text-color,#969799);display:flex;font-size:var(--divider-font-size,14px);line-height:var(--divider-line-height,24px);margin:var(--divider-margin,16px 0)}.van-divider:after,.van-divider:before{border-color:inherit;border-style:inherit;border-width:1px 0 0;box-sizing:border-box;display:block;flex:1;height:1px}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:var(--divider-content-right-width,10%)}
================================================
FILE: dist/dropdown-item/index.d.ts
================================================
export {};
================================================
FILE: dist/dropdown-item/index.js
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
classes: ['item-title-class'],
field: true,
relation: useParent('dropdown-menu', function () {
this.updateDataFromParent();
}),
props: {
value: {
type: null,
observer: 'rerender',
},
title: {
type: String,
observer: 'rerender',
},
disabled: Boolean,
titleClass: {
type: String,
observer: 'rerender',
},
options: {
type: Array,
value: [],
observer: 'rerender',
},
popupStyle: String,
useBeforeToggle: {
type: Boolean,
value: false,
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: '',
safeAreaTabBar: false,
},
methods: {
rerender() {
wx.nextTick(() => {
var _a;
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData();
});
},
updateDataFromParent() {
if (this.parent) {
const { overlay, duration, activeColor, closeOnClickOverlay, direction, safeAreaTabBar, } = this.parent.data;
this.setData({
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
safeAreaTabBar,
});
}
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
this.setData({ showWrapper: false });
},
onOptionTap(event) {
const { option } = event.currentTarget.dataset;
const { value } = option;
const shouldEmitChange = this.data.value !== value;
this.setData({ showPopup: false, value });
this.$emit('close');
this.rerender();
if (shouldEmitChange) {
this.$emit('change', value);
}
},
toggle(show, options = {}) {
const { showPopup } = this.data;
if (typeof show !== 'boolean') {
show = !showPopup;
}
if (show === showPopup) {
return;
}
this.onBeforeToggle(show).then((status) => {
var _a;
if (!status) {
return;
}
this.setData({
transition: !options.immediate,
showPopup: show,
});
if (show) {
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then((wrapperStyle) => {
this.setData({ wrapperStyle, showWrapper: true });
this.rerender();
});
}
else {
this.rerender();
}
});
},
onBeforeToggle(status) {
const { useBeforeToggle } = this.data;
if (!useBeforeToggle) {
return Promise.resolve(true);
}
return new Promise((resolve) => {
this.$emit('before-toggle', {
status,
callback: (value) => resolve(value),
});
});
},
},
});
================================================
FILE: dist/dropdown-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/dropdown-item/index.wxml
================================================
{{ item.text }}
================================================
FILE: dist/dropdown-item/index.wxss
================================================
@import '../common/index.wxss';.van-dropdown-item{left:0;overflow:hidden;position:fixed;right:0}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:var(--dropdown-menu-option-active-color,#ee0a24)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
================================================
FILE: dist/dropdown-item/shared.d.ts
================================================
export interface Option {
text: string;
value: string | number;
icon: string;
}
================================================
FILE: dist/dropdown-item/shared.js
================================================
export {};
================================================
FILE: dist/dropdown-menu/index.d.ts
================================================
export {};
================================================
FILE: dist/dropdown-menu/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { addUnit, getRect, getSystemInfoSync } from '../common/utils';
let ARRAY = [];
VantComponent({
field: true,
classes: ['title-class'],
relation: useChildren('dropdown-item', function () {
this.updateItemListData();
}),
props: {
activeColor: {
type: String,
observer: 'updateChildrenData',
},
overlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
zIndex: {
type: Number,
value: 10,
},
duration: {
type: Number,
value: 200,
observer: 'updateChildrenData',
},
direction: {
type: String,
value: 'down',
observer: 'updateChildrenData',
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
closeOnClickOutside: {
type: Boolean,
value: true,
},
},
data: {
itemListData: [],
},
beforeCreate() {
const { windowHeight } = getSystemInfoSync();
this.windowHeight = windowHeight;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
updateItemListData() {
this.setData({
itemListData: this.children.map((child) => child.data),
});
},
updateChildrenData() {
this.children.forEach((child) => {
child.updateDataFromParent();
});
},
toggleItem(active) {
this.children.forEach((item, index) => {
const { showPopup } = item.data;
if (index === active) {
item.toggle();
}
else if (showPopup) {
item.toggle(false, { immediate: true });
}
});
},
close() {
this.children.forEach((child) => {
child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle() {
const { zIndex, direction } = this.data;
return getRect(this, '.van-dropdown-menu').then((rect) => {
const { top = 0, bottom = 0 } = rect;
const offset = direction === 'down' ? bottom : this.windowHeight - top;
let wrapperStyle = `z-index: ${zIndex};`;
if (direction === 'down') {
wrapperStyle += `top: ${addUnit(offset)};`;
}
else {
wrapperStyle += `bottom: ${addUnit(offset)};`;
}
return wrapperStyle;
});
},
onTitleTap(event) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (!child.data.disabled) {
ARRAY.forEach((menuItem) => {
if (menuItem &&
menuItem.data.closeOnClickOutside &&
menuItem !== this) {
menuItem.close();
}
});
this.toggleItem(index);
}
},
},
});
================================================
FILE: dist/dropdown-menu/index.json
================================================
{
"component": true
}
================================================
FILE: dist/dropdown-menu/index.wxml
================================================
================================================
FILE: dist/dropdown-menu/index.wxs
================================================
/* eslint-disable */
function displayTitle(item) {
if (item.title) {
return item.title;
}
var match = item.options.filter(function(option) {
return option.value === item.value;
});
var displayTitle = match.length ? match[0].text : '';
return displayTitle;
}
module.exports = {
displayTitle: displayTitle
};
================================================
FILE: dist/dropdown-menu/index.wxss
================================================
@import '../common/index.wxss';.van-dropdown-menu{background-color:var(--dropdown-menu-background-color,#fff);box-shadow:var(--dropdown-menu-box-shadow,0 2px 12px hsla(210,1%,40%,.12));display:flex;height:var(--dropdown-menu-height,50px);-webkit-user-select:none;user-select:none}.van-dropdown-menu__item{align-items:center;display:flex;flex:1;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{box-sizing:border-box;color:var(--dropdown-menu-title-text-color,#323233);font-size:var(--dropdown-menu-title-font-size,15px);line-height:var(--dropdown-menu-title-line-height,18px);max-width:100%;padding:var(--dropdown-menu-title-padding,0 24px 0 8px);position:relative}.van-dropdown-menu__title:after{border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;content:"";margin-top:-5px;opacity:.8;position:absolute;right:11px;top:50%;transform:rotate(-45deg)}.van-dropdown-menu__title--active{color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;transform:rotate(135deg)}
================================================
FILE: dist/empty/index.d.ts
================================================
export {};
================================================
FILE: dist/empty/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
description: String,
image: {
type: String,
value: 'default',
},
},
});
================================================
FILE: dist/empty/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: dist/empty/index.wxml
================================================
{{ description }}
================================================
FILE: dist/empty/index.wxs
================================================
/* eslint-disable */
var PRESETS = ['error', 'search', 'default', 'network'];
function imageUrl(image) {
if (PRESETS.indexOf(image) !== -1) {
return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png';
}
return image;
}
module.exports = {
imageUrl: imageUrl,
};
================================================
FILE: dist/empty/index.wxss
================================================
@import '../common/index.wxss';.van-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:32px 0}.van-empty__image{height:160px;width:160px}.van-empty__image:empty{display:none}.van-empty__image__img{height:100%;width:100%}.van-empty__image:not(:empty)+.van-empty__image{display:none}.van-empty__description{color:#969799;font-size:14px;line-height:20px;margin-top:16px;padding:0 60px}.van-empty__description:empty,.van-empty__description:not(:empty)+.van-empty__description{display:none}.van-empty__bottom{margin-top:24px}
================================================
FILE: dist/field/index.d.ts
================================================
export {};
================================================
FILE: dist/field/index.js
================================================
import { nextTick } from '../common/utils';
import { VantComponent } from '../common/component';
import { commonProps, inputProps, textareaProps } from './props';
VantComponent({
field: true,
classes: ['input-class', 'right-icon-class', 'label-class'],
props: Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), inputProps), textareaProps), { size: String, icon: String, label: String, error: Boolean, center: Boolean, isLink: Boolean, leftIcon: String, rightIcon: String, autosize: null, required: Boolean, iconClass: String, clickable: Boolean, inputAlign: String, customStyle: String, errorMessage: String, arrowDirection: String, showWordLimit: Boolean, errorMessageAlign: String, readonly: {
type: Boolean,
observer: 'setShowClear',
}, clearable: {
type: Boolean,
observer: 'setShowClear',
}, clearTrigger: {
type: String,
value: 'focus',
}, border: {
type: Boolean,
value: true,
}, titleWidth: {
type: String,
value: '6.2em',
}, clearIcon: {
type: String,
value: 'clear',
}, extraEventParams: {
type: Boolean,
value: false,
} }),
data: {
focused: false,
innerValue: '',
showClear: false,
},
watch: {
value(value) {
if (value !== this.value) {
this.setData({ innerValue: value });
this.value = value;
this.setShowClear();
}
},
clearTrigger() {
this.setShowClear();
},
},
created() {
this.value = this.data.value;
this.setData({ innerValue: this.value });
},
methods: {
formatValue(value) {
const { maxlength } = this.data;
if (maxlength !== -1 && value.length > maxlength) {
return value.slice(0, maxlength);
}
return value;
},
onInput(event) {
const { value = '' } = event.detail || {};
const formatValue = this.formatValue(value);
this.value = formatValue;
this.setShowClear();
return this.emitChange(Object.assign(Object.assign({}, event.detail), { value: formatValue }));
},
onFocus(event) {
this.focused = true;
this.setShowClear();
this.$emit('focus', event.detail);
},
onBlur(event) {
this.focused = false;
this.setShowClear();
this.$emit('blur', event.detail);
},
onClickIcon() {
this.$emit('click-icon');
},
onClickInput(event) {
this.$emit('click-input', event.detail);
},
onClear() {
this.setData({ innerValue: '' });
this.value = '';
this.setShowClear();
nextTick(() => {
this.emitChange({ value: '' });
this.$emit('clear', '');
});
},
onConfirm(event) {
const { value = '' } = event.detail || {};
this.value = value;
this.setShowClear();
this.$emit('confirm', value);
},
setValue(value) {
this.value = value;
this.setShowClear();
if (value === '') {
this.setData({ innerValue: '' });
}
this.emitChange({ value });
},
onLineChange(event) {
this.$emit('linechange', event.detail);
},
onKeyboardHeightChange(event) {
this.$emit('keyboardheightchange', event.detail);
},
onBindNicknameReview(event) {
this.$emit('nicknamereview', event.detail);
},
emitChange(detail) {
const { extraEventParams } = this.data;
this.setData({ value: detail.value });
let result;
const data = extraEventParams
? Object.assign(Object.assign({}, detail), { callback: (data) => {
result = data;
} }) : detail.value;
this.$emit('input', data);
this.$emit('change', data);
return result;
},
setShowClear() {
const { clearable, readonly, clearTrigger } = this.data;
const { focused, value } = this;
let showClear = false;
if (clearable && !readonly) {
const hasValue = !!value;
const trigger = clearTrigger === 'always' || (clearTrigger === 'focus' && focused);
showClear = hasValue && trigger;
}
this.setView({ showClear });
},
noop() { },
},
});
================================================
FILE: dist/field/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/field/index.wxml
================================================
================================================
FILE: dist/field/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function inputStyle(autosize) {
if (autosize && autosize.constructor === 'Object') {
return style({
'min-height': addUnit(autosize.minHeight),
'max-height': addUnit(autosize.maxHeight),
});
}
return '';
}
module.exports = {
inputStyle: inputStyle,
};
================================================
FILE: dist/field/index.wxss
================================================
@import '../common/index.wxss';.van-field{--cell-icon-size:var(--field-icon-size,16px)}.van-field__label{color:var(--field-label-color,#646566)}.van-field__label--disabled{color:var(--field-disabled-text-color,#c8c9cc)}.van-field__body{align-items:center;display:flex}.van-field__body--textarea{box-sizing:border-box;line-height:1.2em;min-height:var(--cell-line-height,24px);padding:3.6px 0}.van-field__control:empty+.van-field__control{display:block}.van-field__control{background-color:initial;border:0;box-sizing:border-box;color:var(--field-input-text-color,#323233);display:none;height:var(--cell-line-height,24px);line-height:inherit;margin:0;min-height:var(--cell-line-height,24px);padding:0;position:relative;resize:none;text-align:left;width:100%}.van-field__control:empty{display:none}.van-field__control--textarea{height:var(--field-text-area-min-height,18px);min-height:var(--field-text-area-min-height,18px)}.van-field__control--error{color:var(--field-input-error-text-color,#ee0a24)}.van-field__control--disabled{background-color:initial;color:var(--field-input-disabled-text-color,#c8c9cc);opacity:1}.van-field__control--center{text-align:center}.van-field__control--right{text-align:right}.van-field__control--custom{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__placeholder{color:var(--field-placeholder-text-color,#c8c9cc);left:0;pointer-events:none;position:absolute;right:0;top:0}.van-field__placeholder--error{color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;margin-right:calc(var(--padding-xs, 8px)*-1);padding:0 var(--padding-xs,8px);vertical-align:middle}.van-field__button,.van-field__clear-root,.van-field__icon-container{flex-shrink:0}.van-field__clear-root{color:var(--field-clear-icon-color,#c8c9cc);font-size:var(--field-clear-icon-size,16px)}.van-field__icon-container{color:var(--field-icon-container-color,#969799);font-size:var(--field-icon-size,16px)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{color:var(--field-error-message-color,#ee0a24);display:block;font-size:var(--field-error-message-text-font-size,12px);text-align:left}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{color:var(--field-word-limit-color,#646566);font-size:var(--field-word-limit-font-size,12px);line-height:var(--field-word-limit-line-height,16px);margin-top:var(--padding-base,4px);text-align:right}.van-field__word-num{display:inline}.van-field__word-num--full{color:var(--field-word-num-full-color,#ee0a24)}
================================================
FILE: dist/field/input.wxml
================================================
================================================
FILE: dist/field/props.d.ts
================================================
///
export declare const commonProps: WechatMiniprogram.Component.PropertyOption;
export declare const inputProps: WechatMiniprogram.Component.PropertyOption;
export declare const textareaProps: WechatMiniprogram.Component.PropertyOption;
================================================
FILE: dist/field/props.js
================================================
export const commonProps = {
value: String,
placeholder: String,
placeholderStyle: String,
placeholderClass: String,
disabled: Boolean,
maxlength: {
type: Number,
value: -1,
},
cursorSpacing: {
type: Number,
value: 50,
},
autoFocus: Boolean,
focus: Boolean,
cursor: {
type: Number,
value: -1,
},
selectionStart: {
type: Number,
value: -1,
},
selectionEnd: {
type: Number,
value: -1,
},
adjustPosition: {
type: Boolean,
value: true,
},
holdKeyboard: Boolean,
};
export const inputProps = {
type: {
type: String,
value: 'text',
},
password: Boolean,
confirmType: String,
confirmHold: Boolean,
alwaysEmbed: Boolean,
};
export const textareaProps = {
autoHeight: Boolean,
fixed: Boolean,
showConfirmBar: {
type: Boolean,
value: true,
},
disableDefaultPadding: {
type: Boolean,
value: true,
},
};
================================================
FILE: dist/field/textarea.wxml
================================================
================================================
FILE: dist/field/types.d.ts
================================================
export interface InputDetails {
/** 输入框内容 */
value: string;
/** 光标位置 */
cursor?: number;
/** keyCode 为键值 (目前工具还不支持返回keyCode参数) `2.1.0` 起支持 */
keyCode?: number;
}
================================================
FILE: dist/field/types.js
================================================
export {};
================================================
FILE: dist/goods-action/index.d.ts
================================================
export {};
================================================
FILE: dist/goods-action/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('goods-action-button', function () {
this.children.forEach((item) => {
item.updateStyle();
});
}),
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
});
================================================
FILE: dist/goods-action/index.json
================================================
{
"component": true
}
================================================
FILE: dist/goods-action/index.wxml
================================================
================================================
FILE: dist/goods-action/index.wxss
================================================
@import '../common/index.wxss';.van-goods-action{align-items:center;background-color:var(--goods-action-background-color,#fff);bottom:0;box-sizing:initial;display:flex;height:var(--goods-action-height,50px);left:0;position:fixed;right:0}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
================================================
FILE: dist/goods-action-button/index.d.ts
================================================
export {};
================================================
FILE: dist/goods-action-button/index.js
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
mixins: [link, button],
relation: useParent('goods-action'),
props: {
text: String,
color: String,
size: {
type: String,
value: 'normal',
},
loading: Boolean,
disabled: Boolean,
plain: Boolean,
type: {
type: String,
value: 'danger',
},
customStyle: {
type: String,
value: '',
},
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
updateStyle() {
if (this.parent == null) {
return;
}
const { index } = this;
const { children = [] } = this.parent;
this.setData({
isFirst: index === 0,
isLast: index === children.length - 1,
});
},
},
});
================================================
FILE: dist/goods-action-button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
================================================
FILE: dist/goods-action-button/index.wxml
================================================
{{ text }}
================================================
FILE: dist/goods-action-button/index.wxss
================================================
@import '../common/index.wxss';:host{flex:1}.van-goods-action-button{--button-warning-background-color:var(--goods-action-button-warning-color,linear-gradient(to right,#ffd01e,#ff8917));--button-danger-background-color:var(--goods-action-button-danger-color,linear-gradient(to right,#ff6034,#ee0a24));--button-default-height:var(--goods-action-button-height,40px);--button-line-height:var(--goods-action-button-line-height,20px);--button-plain-background-color:var(--goods-action-button-plain-color,#fff);--button-border-width:0;display:block}.van-goods-action-button--first{--button-border-radius:999px 0 0 var(--goods-action-button-border-radius,999px);margin-left:5px}.van-goods-action-button--last{--button-border-radius:0 999px var(--goods-action-button-border-radius,999px) 0;margin-right:5px}.van-goods-action-button--first.van-goods-action-button--last{--button-border-radius:var(--goods-action-button-border-radius,999px)}.van-goods-action-button--plain{--button-border-width:1px}.van-goods-action-button__inner{font-weight:var(--font-weight-bold,500)!important;width:100%}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
================================================
FILE: dist/goods-action-icon/index.d.ts
================================================
export {};
================================================
FILE: dist/goods-action-icon/index.js
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
classes: ['icon-class', 'text-class', 'info-class'],
mixins: [link, button],
props: {
text: String,
dot: Boolean,
info: String,
icon: String,
size: String,
color: String,
classPrefix: {
type: String,
value: 'van-icon',
},
disabled: Boolean,
loading: Boolean,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: dist/goods-action-icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-button": "../button/index"
}
}
================================================
FILE: dist/goods-action-icon/index.wxml
================================================
{{ text }}
================================================
FILE: dist/goods-action-icon/index.wxss
================================================
@import '../common/index.wxss';.van-goods-action-icon{border:none!important;color:var(--goods-action-icon-text-color,#646566)!important;display:flex!important;flex-direction:column;font-size:var(--goods-action-icon-font-size,10px)!important;height:var(--goods-action-icon-height,50px)!important;justify-content:center!important;line-height:1!important;min-width:var(--goods-action-icon-width,48px)}.van-goods-action-icon__icon{color:var(--goods-action-icon-color,#323233);display:flex;font-size:var(--goods-action-icon-size,18px);margin:0 auto 5px}
================================================
FILE: dist/grid/index.d.ts
================================================
export {};
================================================
FILE: dist/grid/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('grid-item'),
props: {
square: {
type: Boolean,
observer: 'updateChildren',
},
gutter: {
type: null,
value: 0,
observer: 'updateChildren',
},
clickable: {
type: Boolean,
observer: 'updateChildren',
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren',
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
direction: {
type: String,
observer: 'updateChildren',
},
iconSize: {
type: String,
observer: 'updateChildren',
},
reverse: {
type: Boolean,
value: false,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => {
child.updateStyle();
});
},
},
});
================================================
FILE: dist/grid/index.json
================================================
{
"component": true
}
================================================
FILE: dist/grid/index.wxml
================================================
================================================
FILE: dist/grid/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'padding-left': addUnit(data.gutter),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/grid/index.wxss
================================================
@import '../common/index.wxss';.van-grid{box-sizing:border-box;overflow:hidden;position:relative}
================================================
FILE: dist/grid-item/index.d.ts
================================================
export {};
================================================
FILE: dist/grid-item/index.js
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { link } from '../mixins/link';
VantComponent({
relation: useParent('grid'),
classes: ['content-class', 'icon-class', 'text-class'],
mixins: [link],
props: {
icon: String,
iconColor: String,
iconPrefix: {
type: String,
value: 'van-icon',
},
dot: Boolean,
info: null,
badge: null,
text: String,
useSlot: Boolean,
},
data: {
viewStyle: '',
},
mounted() {
this.updateStyle();
},
methods: {
updateStyle() {
if (!this.parent) {
return;
}
const { data, children } = this.parent;
const { columnNum, border, square, gutter, clickable, center, direction, reverse, iconSize, } = data;
this.setData({
center,
border,
square,
gutter,
clickable,
direction,
reverse,
iconSize,
index: children.indexOf(this),
columnNum,
});
},
onClick() {
this.$emit('click');
this.jumpLink();
},
},
});
================================================
FILE: dist/grid-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/grid-item/index.wxml
================================================
{{ text }}
================================================
FILE: dist/grid-item/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapperStyle(data) {
var width = 100 / data.columnNum + '%';
return style({
width: width,
'padding-top': data.square ? width : null,
'padding-right': addUnit(data.gutter),
'margin-top':
data.index >= data.columnNum && !data.square
? addUnit(data.gutter)
: null,
});
}
function contentStyle(data) {
return data.square
? style({
right: addUnit(data.gutter),
bottom: addUnit(data.gutter),
height: 'auto',
})
: '';
}
module.exports = {
wrapperStyle: wrapperStyle,
contentStyle: contentStyle,
};
================================================
FILE: dist/grid-item/index.wxss
================================================
@import '../common/index.wxss';.van-grid-item{box-sizing:border-box;float:left;position:relative}.van-grid-item--square{height:0}.van-grid-item__content{background-color:var(--grid-item-content-background-color,#fff);box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:var(--grid-item-content-padding,16px 8px)}.van-grid-item__content:after{border-width:0 1px 1px 0;z-index:1}.van-grid-item__content--surround:after{border-width:1px}.van-grid-item__content--center{align-items:center;justify-content:center}.van-grid-item__content--square{left:0;position:absolute;right:0;top:0}.van-grid-item__content--horizontal{flex-direction:row}.van-grid-item__content--horizontal .van-grid-item__text{margin:0 0 0 8px}.van-grid-item__content--reverse{flex-direction:column-reverse}.van-grid-item__content--reverse .van-grid-item__text{margin:0 0 8px}.van-grid-item__content--horizontal.van-grid-item__content--reverse{flex-direction:row-reverse}.van-grid-item__content--horizontal.van-grid-item__content--reverse .van-grid-item__text{margin:0 8px 0 0}.van-grid-item__content--clickable:active{background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{align-items:center;display:flex;font-size:var(--grid-item-icon-size,26px);height:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:var(--grid-item-text-color,#646566);font-size:var(--grid-item-text-font-size,12px)}.van-grid-item__icon+.van-grid-item__text{margin-top:8px}
================================================
FILE: dist/icon/index.d.ts
================================================
export {};
================================================
FILE: dist/icon/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['info-class'],
props: {
dot: Boolean,
info: null,
size: null,
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon',
},
name: String,
},
methods: {
onClick() {
this.$emit('click');
},
},
});
================================================
FILE: dist/icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: dist/icon/index.wxml
================================================
================================================
FILE: dist/icon/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isImage(name) {
return name.indexOf('/') !== -1;
}
function rootClass(data) {
var classes = ['custom-class'];
if (data.classPrefix !== 'van-icon') {
classes.push('van-icon--custom')
}
if (data.classPrefix != null) {
classes.push(data.classPrefix);
}
if (isImage(data.name)) {
classes.push('van-icon--image');
} else if (data.classPrefix != null) {
classes.push(data.classPrefix + '-' + data.name);
}
return classes.join(' ');
}
function rootStyle(data) {
return style([
{
color: data.color,
'font-size': addUnit(data.size),
},
data.customStyle,
]);
}
module.exports = {
isImage: isImage,
rootClass: rootClass,
rootStyle: rootStyle,
};
================================================
FILE: dist/icon/index.wxss
================================================
@import '../common/index.wxss';.van-icon{text-rendering:auto;-webkit-font-smoothing:antialiased;font:normal normal normal 14px/1 vant-icon;font:normal normal normal 14px/1 var(--van-icon-font-family,"vant-icon");font-size:inherit;position:relative}.van-icon,.van-icon:before{display:inline-block}.van-icon-contact:before{content:"\e753"}.van-icon-notes:before{content:"\e63c"}.van-icon-records:before{content:"\e63d"}.van-icon-cash-back-record:before{content:"\e63e"}.van-icon-newspaper:before{content:"\e63f"}.van-icon-discount:before{content:"\e640"}.van-icon-completed:before{content:"\e641"}.van-icon-user:before{content:"\e642"}.van-icon-description:before{content:"\e643"}.van-icon-list-switch:before{content:"\e6ad"}.van-icon-list-switching:before{content:"\e65a"}.van-icon-link-o:before{content:"\e751"}.van-icon-miniprogram-o:before{content:"\e752"}.van-icon-qq:before{content:"\e74e"}.van-icon-wechat-moments:before{content:"\e74f"}.van-icon-weibo:before{content:"\e750"}.van-icon-cash-o:before{content:"\e74d"}.van-icon-guide-o:before{content:"\e74c"}.van-icon-invitation:before{content:"\e6d6"}.van-icon-shield-o:before{content:"\e74b"}.van-icon-exchange:before{content:"\e6af"}.van-icon-eye:before{content:"\e6b0"}.van-icon-enlarge:before{content:"\e6b1"}.van-icon-expand-o:before{content:"\e6b2"}.van-icon-eye-o:before{content:"\e6b3"}.van-icon-expand:before{content:"\e6b4"}.van-icon-filter-o:before{content:"\e6b5"}.van-icon-fire:before{content:"\e6b6"}.van-icon-fail:before{content:"\e6b7"}.van-icon-failure:before{content:"\e6b8"}.van-icon-fire-o:before{content:"\e6b9"}.van-icon-flag-o:before{content:"\e6ba"}.van-icon-font:before{content:"\e6bb"}.van-icon-font-o:before{content:"\e6bc"}.van-icon-gem-o:before{content:"\e6bd"}.van-icon-flower-o:before{content:"\e6be"}.van-icon-gem:before{content:"\e6bf"}.van-icon-gift-card:before{content:"\e6c0"}.van-icon-friends:before{content:"\e6c1"}.van-icon-friends-o:before{content:"\e6c2"}.van-icon-gold-coin:before{content:"\e6c3"}.van-icon-gold-coin-o:before{content:"\e6c4"}.van-icon-good-job-o:before{content:"\e6c5"}.van-icon-gift:before{content:"\e6c6"}.van-icon-gift-o:before{content:"\e6c7"}.van-icon-gift-card-o:before{content:"\e6c8"}.van-icon-good-job:before{content:"\e6c9"}.van-icon-home-o:before{content:"\e6ca"}.van-icon-goods-collect:before{content:"\e6cb"}.van-icon-graphic:before{content:"\e6cc"}.van-icon-goods-collect-o:before{content:"\e6cd"}.van-icon-hot-o:before{content:"\e6ce"}.van-icon-info:before{content:"\e6cf"}.van-icon-hotel-o:before{content:"\e6d0"}.van-icon-info-o:before{content:"\e6d1"}.van-icon-hot-sale-o:before{content:"\e6d2"}.van-icon-hot:before{content:"\e6d3"}.van-icon-like:before{content:"\e6d4"}.van-icon-idcard:before{content:"\e6d5"}.van-icon-like-o:before{content:"\e6d7"}.van-icon-hot-sale:before{content:"\e6d8"}.van-icon-location-o:before{content:"\e6d9"}.van-icon-location:before{content:"\e6da"}.van-icon-label:before{content:"\e6db"}.van-icon-lock:before{content:"\e6dc"}.van-icon-label-o:before{content:"\e6dd"}.van-icon-map-marked:before{content:"\e6de"}.van-icon-logistics:before{content:"\e6df"}.van-icon-manager:before{content:"\e6e0"}.van-icon-more:before{content:"\e6e1"}.van-icon-live:before{content:"\e6e2"}.van-icon-manager-o:before{content:"\e6e3"}.van-icon-medal:before{content:"\e6e4"}.van-icon-more-o:before{content:"\e6e5"}.van-icon-music-o:before{content:"\e6e6"}.van-icon-music:before{content:"\e6e7"}.van-icon-new-arrival-o:before{content:"\e6e8"}.van-icon-medal-o:before{content:"\e6e9"}.van-icon-new-o:before{content:"\e6ea"}.van-icon-free-postage:before{content:"\e6eb"}.van-icon-newspaper-o:before{content:"\e6ec"}.van-icon-new-arrival:before{content:"\e6ed"}.van-icon-minus:before{content:"\e6ee"}.van-icon-orders-o:before{content:"\e6ef"}.van-icon-new:before{content:"\e6f0"}.van-icon-paid:before{content:"\e6f1"}.van-icon-notes-o:before{content:"\e6f2"}.van-icon-other-pay:before{content:"\e6f3"}.van-icon-pause-circle:before{content:"\e6f4"}.van-icon-pause:before{content:"\e6f5"}.van-icon-pause-circle-o:before{content:"\e6f6"}.van-icon-peer-pay:before{content:"\e6f7"}.van-icon-pending-payment:before{content:"\e6f8"}.van-icon-passed:before{content:"\e6f9"}.van-icon-plus:before{content:"\e6fa"}.van-icon-phone-circle-o:before{content:"\e6fb"}.van-icon-phone-o:before{content:"\e6fc"}.van-icon-printer:before{content:"\e6fd"}.van-icon-photo-fail:before{content:"\e6fe"}.van-icon-phone:before{content:"\e6ff"}.van-icon-photo-o:before{content:"\e700"}.van-icon-play-circle:before{content:"\e701"}.van-icon-play:before{content:"\e702"}.van-icon-phone-circle:before{content:"\e703"}.van-icon-point-gift-o:before{content:"\e704"}.van-icon-point-gift:before{content:"\e705"}.van-icon-play-circle-o:before{content:"\e706"}.van-icon-shrink:before{content:"\e707"}.van-icon-photo:before{content:"\e708"}.van-icon-qr:before{content:"\e709"}.van-icon-qr-invalid:before{content:"\e70a"}.van-icon-question-o:before{content:"\e70b"}.van-icon-revoke:before{content:"\e70c"}.van-icon-replay:before{content:"\e70d"}.van-icon-service:before{content:"\e70e"}.van-icon-question:before{content:"\e70f"}.van-icon-search:before{content:"\e710"}.van-icon-refund-o:before{content:"\e711"}.van-icon-service-o:before{content:"\e712"}.van-icon-scan:before{content:"\e713"}.van-icon-share:before{content:"\e714"}.van-icon-send-gift-o:before{content:"\e715"}.van-icon-share-o:before{content:"\e716"}.van-icon-setting:before{content:"\e717"}.van-icon-points:before{content:"\e718"}.van-icon-photograph:before{content:"\e719"}.van-icon-shop:before{content:"\e71a"}.van-icon-shop-o:before{content:"\e71b"}.van-icon-shop-collect-o:before{content:"\e71c"}.van-icon-shop-collect:before{content:"\e71d"}.van-icon-smile:before{content:"\e71e"}.van-icon-shopping-cart-o:before{content:"\e71f"}.van-icon-sign:before{content:"\e720"}.van-icon-sort:before{content:"\e721"}.van-icon-star-o:before{content:"\e722"}.van-icon-smile-comment-o:before{content:"\e723"}.van-icon-stop:before{content:"\e724"}.van-icon-stop-circle-o:before{content:"\e725"}.van-icon-smile-o:before{content:"\e726"}.van-icon-star:before{content:"\e727"}.van-icon-success:before{content:"\e728"}.van-icon-stop-circle:before{content:"\e729"}.van-icon-records-o:before{content:"\e72a"}.van-icon-shopping-cart:before{content:"\e72b"}.van-icon-tosend:before{content:"\e72c"}.van-icon-todo-list:before{content:"\e72d"}.van-icon-thumb-circle-o:before{content:"\e72e"}.van-icon-thumb-circle:before{content:"\e72f"}.van-icon-umbrella-circle:before{content:"\e730"}.van-icon-underway:before{content:"\e731"}.van-icon-upgrade:before{content:"\e732"}.van-icon-todo-list-o:before{content:"\e733"}.van-icon-tv-o:before{content:"\e734"}.van-icon-underway-o:before{content:"\e735"}.van-icon-user-o:before{content:"\e736"}.van-icon-vip-card-o:before{content:"\e737"}.van-icon-vip-card:before{content:"\e738"}.van-icon-send-gift:before{content:"\e739"}.van-icon-wap-home:before{content:"\e73a"}.van-icon-wap-nav:before{content:"\e73b"}.van-icon-volume-o:before{content:"\e73c"}.van-icon-video:before{content:"\e73d"}.van-icon-wap-home-o:before{content:"\e73e"}.van-icon-volume:before{content:"\e73f"}.van-icon-warning:before{content:"\e740"}.van-icon-weapp-nav:before{content:"\e741"}.van-icon-wechat-pay:before{content:"\e742"}.van-icon-warning-o:before{content:"\e743"}.van-icon-wechat:before{content:"\e744"}.van-icon-setting-o:before{content:"\e745"}.van-icon-youzan-shield:before{content:"\e746"}.van-icon-warn-o:before{content:"\e747"}.van-icon-smile-comment:before{content:"\e748"}.van-icon-user-circle-o:before{content:"\e749"}.van-icon-video-o:before{content:"\e74a"}.van-icon-add-square:before{content:"\e65c"}.van-icon-add:before{content:"\e65d"}.van-icon-arrow-down:before{content:"\e65e"}.van-icon-arrow-up:before{content:"\e65f"}.van-icon-arrow:before{content:"\e660"}.van-icon-after-sale:before{content:"\e661"}.van-icon-add-o:before{content:"\e662"}.van-icon-alipay:before{content:"\e663"}.van-icon-ascending:before{content:"\e664"}.van-icon-apps-o:before{content:"\e665"}.van-icon-aim:before{content:"\e666"}.van-icon-award:before{content:"\e667"}.van-icon-arrow-left:before{content:"\e668"}.van-icon-award-o:before{content:"\e669"}.van-icon-audio:before{content:"\e66a"}.van-icon-bag-o:before{content:"\e66b"}.van-icon-balance-list:before{content:"\e66c"}.van-icon-back-top:before{content:"\e66d"}.van-icon-bag:before{content:"\e66e"}.van-icon-balance-pay:before{content:"\e66f"}.van-icon-balance-o:before{content:"\e670"}.van-icon-bar-chart-o:before{content:"\e671"}.van-icon-bars:before{content:"\e672"}.van-icon-balance-list-o:before{content:"\e673"}.van-icon-birthday-cake-o:before{content:"\e674"}.van-icon-bookmark:before{content:"\e675"}.van-icon-bill:before{content:"\e676"}.van-icon-bell:before{content:"\e677"}.van-icon-browsing-history-o:before{content:"\e678"}.van-icon-browsing-history:before{content:"\e679"}.van-icon-bookmark-o:before{content:"\e67a"}.van-icon-bulb-o:before{content:"\e67b"}.van-icon-bullhorn-o:before{content:"\e67c"}.van-icon-bill-o:before{content:"\e67d"}.van-icon-calendar-o:before{content:"\e67e"}.van-icon-brush-o:before{content:"\e67f"}.van-icon-card:before{content:"\e680"}.van-icon-cart-o:before{content:"\e681"}.van-icon-cart-circle:before{content:"\e682"}.van-icon-cart-circle-o:before{content:"\e683"}.van-icon-cart:before{content:"\e684"}.van-icon-cash-on-deliver:before{content:"\e685"}.van-icon-cash-back-record-o:before{content:"\e686"}.van-icon-cashier-o:before{content:"\e687"}.van-icon-chart-trending-o:before{content:"\e688"}.van-icon-certificate:before{content:"\e689"}.van-icon-chat:before{content:"\e68a"}.van-icon-clear:before{content:"\e68b"}.van-icon-chat-o:before{content:"\e68c"}.van-icon-checked:before{content:"\e68d"}.van-icon-clock:before{content:"\e68e"}.van-icon-clock-o:before{content:"\e68f"}.van-icon-close:before{content:"\e690"}.van-icon-closed-eye:before{content:"\e691"}.van-icon-circle:before{content:"\e692"}.van-icon-cluster-o:before{content:"\e693"}.van-icon-column:before{content:"\e694"}.van-icon-comment-circle-o:before{content:"\e695"}.van-icon-cluster:before{content:"\e696"}.van-icon-comment:before{content:"\e697"}.van-icon-comment-o:before{content:"\e698"}.van-icon-comment-circle:before{content:"\e699"}.van-icon-completed-o:before{content:"\e69a"}.van-icon-credit-pay:before{content:"\e69b"}.van-icon-coupon:before{content:"\e69c"}.van-icon-debit-pay:before{content:"\e69d"}.van-icon-coupon-o:before{content:"\e69e"}.van-icon-contact-o:before{content:"\e69f"}.van-icon-descending:before{content:"\e6a0"}.van-icon-desktop-o:before{content:"\e6a1"}.van-icon-diamond-o:before{content:"\e6a2"}.van-icon-description-o:before{content:"\e6a3"}.van-icon-delete:before{content:"\e6a4"}.van-icon-diamond:before{content:"\e6a5"}.van-icon-delete-o:before{content:"\e6a6"}.van-icon-cross:before{content:"\e6a7"}.van-icon-edit:before{content:"\e6a8"}.van-icon-ellipsis:before{content:"\e6a9"}.van-icon-down:before{content:"\e6aa"}.van-icon-discount-o:before{content:"\e6ab"}.van-icon-ecard-pay:before{content:"\e6ac"}.van-icon-envelop-o:before{content:"\e6ae"}@font-face{font-display:auto;font-family:vant-icon;font-style:normal;font-weight:400;src:url(//at.alicdn.com/t/c/font_2553510_kfwma2yq1rs.woff2?t=1694918397022) format("woff2"),url(//at.alicdn.com/t/c/font_2553510_kfwma2yq1rs.woff?t=1694918397022) format("woff")}:host{align-items:center;display:inline-flex;justify-content:center}.van-icon--custom{position:relative}.van-icon--image{height:1em;width:1em}.van-icon__image{height:100%;width:100%}.van-icon__info{z-index:1}
================================================
FILE: dist/image/index.d.ts
================================================
export {};
================================================
FILE: dist/image/index.js
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
mixins: [button],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: {
type: String,
observer() {
this.setData({
error: false,
loading: true,
});
},
},
round: Boolean,
width: null,
height: null,
radius: null,
lazyLoad: Boolean,
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
fit: {
type: String,
value: 'fill',
},
webp: {
type: Boolean,
value: false,
},
showError: {
type: Boolean,
value: true,
},
showLoading: {
type: Boolean,
value: true,
},
},
data: {
error: false,
loading: true,
viewStyle: '',
},
methods: {
onLoad(event) {
this.setData({
loading: false,
});
this.$emit('load', event.detail);
},
onError(event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
},
},
});
================================================
FILE: dist/image/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: dist/image/index.wxml
================================================
================================================
FILE: dist/image/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
width: addUnit(data.width),
height: addUnit(data.height),
'border-radius': addUnit(data.radius),
},
data.radius ? 'overflow: hidden' : null,
]);
}
var FIT_MODE_MAP = {
none: 'center',
fill: 'scaleToFill',
cover: 'aspectFill',
contain: 'aspectFit',
widthFix: 'widthFix',
heightFix: 'heightFix',
};
function mode(fit) {
return FIT_MODE_MAP[fit];
}
module.exports = {
rootStyle: rootStyle,
mode: mode,
};
================================================
FILE: dist/image/index.wxss
================================================
@import '../common/index.wxss';.van-image{display:inline-block;position:relative;vertical-align:top}.van-image--round{border-radius:50%;overflow:hidden}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;height:100%;width:100%}.van-image__error,.van-image__loading{align-items:center;background-color:var(--image-placeholder-background-color,#f7f8fa);color:var(--image-placeholder-text-color,#969799);display:flex;flex-direction:column;font-size:var(--image-placeholder-font-size,14px);justify-content:center;left:0;position:absolute;top:0}.van-image__loading-icon{color:var(--image-loading-icon-color,#dcdee0);font-size:var(--image-loading-icon-size,32px)!important}.van-image__error-icon{color:var(--image-error-icon-color,#dcdee0);font-size:var(--image-error-icon-size,32px)!important}
================================================
FILE: dist/index-anchor/index.d.ts
================================================
export {};
================================================
FILE: dist/index-anchor/index.js
================================================
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
relation: useParent('index-bar'),
props: {
useSlot: Boolean,
index: null,
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: '',
},
methods: {
scrollIntoView(scrollTop) {
getRect(this, '.van-index-anchor-wrapper').then((rect) => {
wx.pageScrollTo({
duration: 0,
scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
});
});
},
},
});
================================================
FILE: dist/index-anchor/index.json
================================================
{
"component": true
}
================================================
FILE: dist/index-anchor/index.wxml
================================================
{{ index }}
================================================
FILE: dist/index-anchor/index.wxss
================================================
@import '../common/index.wxss';.van-index-anchor{background-color:var(--index-anchor-background-color,transparent);color:var(--index-anchor-text-color,#323233);font-size:var(--index-anchor-font-size,14px);font-weight:var(--index-anchor-font-weight,500);line-height:var(--index-anchor-line-height,32px);padding:var(--index-anchor-padding,0 16px)}.van-index-anchor--active{background-color:var(--index-anchor-active-background-color,#fff);color:var(--index-anchor-active-text-color,#07c160);left:0;right:0}
================================================
FILE: dist/index-bar/index.d.ts
================================================
export {};
================================================
FILE: dist/index-bar/index.js
================================================
import { GREEN } from '../common/color';
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect, isDef } from '../common/utils';
import { pageScrollMixin } from '../mixins/page-scroll';
const indexList = () => {
const indexList = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
VantComponent({
relation: useChildren('index-anchor', function () {
this.updateData();
}),
props: {
sticky: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
highlightColor: {
type: String,
value: GREEN,
},
stickyOffsetTop: {
type: Number,
value: 0,
},
indexList: {
type: Array,
value: indexList(),
},
},
mixins: [
pageScrollMixin(function (event) {
this.scrollTop = (event === null || event === void 0 ? void 0 : event.scrollTop) || 0;
this.onScroll();
}),
],
data: {
activeAnchorIndex: null,
showSidebar: false,
},
created() {
this.scrollTop = 0;
},
methods: {
updateData() {
wx.nextTick(() => {
if (this.timer != null) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
this.setData({
showSidebar: !!this.children.length,
});
this.setRect().then(() => {
this.onScroll();
});
}, 0);
});
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect(),
]);
},
setAnchorsRect() {
return Promise.all(this.children.map((anchor) => getRect(anchor, '.van-index-anchor-wrapper').then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top + this.scrollTop,
});
})));
},
setListRect() {
return getRect(this, '.van-index-bar').then((rect) => {
if (!isDef(rect)) {
return;
}
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop,
});
});
},
setSiderbarRect() {
return getRect(this, '.van-index-bar__sidebar').then((res) => {
if (!isDef(res)) {
return;
}
this.sidebar = {
height: res.height,
top: res.top,
};
});
},
setDiffData({ target, data }) {
const diffData = {};
Object.keys(data).forEach((key) => {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect(anchor) {
return getRect(anchor, '.van-index-anchor-wrapper').then((rect) => ({
height: rect.height,
top: rect.top,
}));
},
getActiveAnchorIndex() {
const { children, scrollTop } = this;
const { sticky, stickyOffsetTop } = this.data;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const { children = [], scrollTop } = this;
if (!children.length) {
return;
}
const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
const active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active,
},
});
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = `
color: ${highlightColor};
`;
if (isActiveAnchorSticky) {
wrapperStyle = `
height: ${children[index].height}px;
`;
anchorStyle = `
position: fixed;
top: ${stickyOffsetTop}px;
z-index: ${zIndex};
color: ${highlightColor};
`;
}
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
wrapperStyle,
},
});
}
else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop = index === children.length - 1
? this.top
: children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = `
position: relative;
transform: translate3d(0, ${translateY}px, 0);
z-index: ${zIndex};
color: ${highlightColor};
`;
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
},
});
}
else {
this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
},
});
}
});
}
},
onClick(event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove(event) {
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
}
else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop() {
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find((item) => item.data.index === this.data.indexList[index]);
if (anchor) {
anchor.scrollIntoView(this.scrollTop);
this.$emit('select', anchor.data.index);
}
},
},
});
================================================
FILE: dist/index-bar/index.json
================================================
{
"component": true
}
================================================
FILE: dist/index-bar/index.wxml
================================================
================================================
FILE: dist/index-bar/index.wxss
================================================
@import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{display:flex;flex-direction:column;position:fixed;right:0;text-align:center;top:50%;transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-size:var(--index-bar-index-font-size,10px);font-weight:500;line-height:var(--index-bar-index-line-height,14px);padding:0 var(--padding-base,4px) 0 var(--padding-md,16px)}
================================================
FILE: dist/info/index.d.ts
================================================
export {};
================================================
FILE: dist/info/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
dot: Boolean,
info: null,
customStyle: String,
},
});
================================================
FILE: dist/info/index.json
================================================
{
"component": true
}
================================================
FILE: dist/info/index.wxml
================================================
{{ dot ? '' : info }}
================================================
FILE: dist/info/index.wxss
================================================
@import '../common/index.wxss';.van-info{align-items:center;background-color:var(--info-background-color,#ee0a24);border:var(--info-border-width,1px) solid #fff;border-radius:var(--info-size,16px);box-sizing:border-box;color:var(--info-color,#fff);display:inline-flex;font-family:var(--info-font-family,-apple-system-font,Helvetica Neue,Arial,sans-serif);font-size:var(--info-font-size,12px);font-weight:var(--info-font-weight,500);height:var(--info-size,16px);justify-content:center;min-width:var(--info-size,16px);padding:var(--info-padding,0 3px);position:absolute;right:0;top:0;transform:translate(50%,-50%);transform-origin:100%;white-space:nowrap}.van-info--dot{background-color:var(--info-dot-color,#ee0a24);border-radius:100%;height:var(--info-dot-size,8px);min-width:0;width:var(--info-dot-size,8px)}
================================================
FILE: dist/loading/index.d.ts
================================================
export {};
================================================
FILE: dist/loading/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
color: String,
vertical: Boolean,
type: {
type: String,
value: 'circular',
},
size: String,
textSize: String,
},
data: {
array12: Array.from({ length: 12 }),
},
});
================================================
FILE: dist/loading/index.json
================================================
{
"component": true
}
================================================
FILE: dist/loading/index.wxml
================================================
================================================
FILE: dist/loading/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function spinnerStyle(data) {
return style({
color: data.color,
width: addUnit(data.size),
height: addUnit(data.size),
});
}
function textStyle(data) {
return style({
'font-size': addUnit(data.textSize),
});
}
module.exports = {
spinnerStyle: spinnerStyle,
textStyle: textStyle,
};
================================================
FILE: dist/loading/index.wxss
================================================
@import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{align-items:center;color:var(--loading-spinner-color,#c8c9cc);display:inline-flex;justify-content:center}.van-loading__spinner{animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;box-sizing:border-box;height:var(--loading-spinner-size,30px);max-height:100%;max-width:100%;position:relative;width:var(--loading-spinner-size,30px)}.van-loading__spinner--spinner{animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-radius:100%;border-top-color:initial}.van-loading__text{color:var(--loading-text-color,#969799);font-size:var(--loading-text-font-size,14px);line-height:var(--loading-text-line-height,20px);margin-left:var(--padding-xs,8px)}.van-loading__text:empty{display:none}.van-loading--vertical{flex-direction:column}.van-loading--vertical .van-loading__text{margin:var(--padding-xs,8px) 0 0}.van-loading__dot{height:100%;left:0;position:absolute;top:0;width:100%}.van-loading__dot:before{background-color:currentColor;border-radius:40%;content:" ";display:block;height:25%;margin:0 auto;width:2px}.van-loading__dot:first-of-type{opacity:1;transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;transform:rotate(1turn)}@keyframes van-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
================================================
FILE: dist/mixins/basic.d.ts
================================================
export declare const basic: string;
================================================
FILE: dist/mixins/basic.js
================================================
export const basic = Behavior({
methods: {
$emit(name, detail, options) {
this.triggerEvent(name, detail, options);
},
set(data) {
this.setData(data);
return new Promise((resolve) => wx.nextTick(resolve));
},
// high performance setData
setView(data, callback) {
const target = {};
let hasChange = false;
Object.keys(data).forEach((key) => {
if (data[key] !== this.data[key]) {
target[key] = data[key];
hasChange = true;
}
});
if (hasChange) {
return this.setData(target, callback);
}
return callback && callback();
},
},
});
================================================
FILE: dist/mixins/button.d.ts
================================================
export declare const button: string;
================================================
FILE: dist/mixins/button.js
================================================
import { canIUseGetUserProfile } from '../common/version';
export const button = Behavior({
externalClasses: ['hover-class'],
properties: {
id: String,
buttonId: String,
lang: String,
businessId: Number,
sessionFrom: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean,
appParameter: String,
ariaLabel: String,
openType: String,
getUserProfileDesc: String,
},
data: {
canIUseGetUserProfile: canIUseGetUserProfile(),
},
methods: {
onGetUserInfo(event) {
this.triggerEvent('getuserinfo', event.detail);
},
onContact(event) {
this.triggerEvent('contact', event.detail);
},
onGetPhoneNumber(event) {
this.triggerEvent('getphonenumber', event.detail);
},
onGetRealTimePhoneNumber(event) {
this.triggerEvent('getrealtimephonenumber', event.detail);
},
onError(event) {
this.triggerEvent('error', event.detail);
},
onLaunchApp(event) {
this.triggerEvent('launchapp', event.detail);
},
onOpenSetting(event) {
this.triggerEvent('opensetting', event.detail);
},
onAgreePrivacyAuthorization(event) {
this.triggerEvent('agreeprivacyauthorization', event.detail);
},
onChooseAvatar(event) {
this.triggerEvent('chooseavatar', event.detail);
},
},
});
================================================
FILE: dist/mixins/link.d.ts
================================================
export declare const link: string;
================================================
FILE: dist/mixins/link.js
================================================
export const link = Behavior({
properties: {
url: String,
linkType: {
type: String,
value: 'navigateTo',
},
},
methods: {
jumpLink(urlKey = 'url') {
const url = this.data[urlKey];
if (url) {
if (this.data.linkType === 'navigateTo' &&
getCurrentPages().length > 9) {
wx.redirectTo({ url });
}
else {
wx[this.data.linkType]({ url });
}
}
},
},
});
================================================
FILE: dist/mixins/page-scroll.d.ts
================================================
///
///
type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
type Scroller = (this: WechatMiniprogram.Component.TrivialInstance, event?: IPageScrollOption) => void;
export declare function pageScrollMixin(scroller: Scroller): string;
export {};
================================================
FILE: dist/mixins/page-scroll.js
================================================
import { isFunction } from '../common/validator';
import { getCurrentPage, isDef } from '../common/utils';
function onPageScroll(event) {
const { vanPageScroller = [] } = getCurrentPage();
vanPageScroller.forEach((scroller) => {
if (typeof scroller === 'function') {
// @ts-ignore
scroller(event);
}
});
}
export function pageScrollMixin(scroller) {
return Behavior({
attached() {
const page = getCurrentPage();
if (!isDef(page)) {
return;
}
const _scroller = scroller.bind(this);
const { vanPageScroller = [] } = page;
if (isFunction(page.onPageScroll) && page.onPageScroll !== onPageScroll) {
vanPageScroller.push(page.onPageScroll.bind(page));
}
vanPageScroller.push(_scroller);
page.vanPageScroller = vanPageScroller;
page.onPageScroll = onPageScroll;
this._scroller = _scroller;
},
detached() {
const page = getCurrentPage();
if (!isDef(page) || !isDef(page.vanPageScroller)) {
return;
}
const { vanPageScroller } = page;
const index = vanPageScroller.findIndex((v) => v === this._scroller);
if (index > -1) {
page.vanPageScroller.splice(index, 1);
}
this._scroller = undefined;
},
});
}
================================================
FILE: dist/mixins/touch.d.ts
================================================
export declare const touch: string;
================================================
FILE: dist/mixins/touch.js
================================================
// @ts-nocheck
const MIN_DISTANCE = 10;
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
export const touch = Behavior({
methods: {
resetTouchStatus() {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
touchStart(event) {
this.resetTouchStatus();
const touch = event.touches[0];
this.startX = touch.clientX;
this.startY = touch.clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction =
this.direction || getDirection(this.offsetX, this.offsetY);
},
},
});
================================================
FILE: dist/mixins/transition.d.ts
================================================
export declare function transition(showDefaultValue: boolean): string;
================================================
FILE: dist/mixins/transition.js
================================================
// @ts-nocheck
import { requestAnimationFrame } from '../common/utils';
import { isObj } from '../common/validator';
const getClassNames = (name) => ({
enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
});
export function transition(showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
// @ts-ignore
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow',
},
// @ts-ignore
duration: {
type: null,
value: 300,
},
name: {
type: String,
value: 'fade',
},
},
data: {
type: '',
inited: false,
display: false,
},
ready() {
if (this.data.show === true) {
this.observeShow(true, false);
}
},
methods: {
observeShow(value, old) {
if (value === old) {
return;
}
value ? this.enureEnter() : this.enureLeave();
},
enureEnter() {
if (this.enterPromise)
return;
this.enterPromise = new Promise((resolve) => this.enter(resolve));
},
enureLeave() {
const { enterPromise } = this;
if (!enterPromise)
return;
enterPromise
.then(() => new Promise((resolve) => this.leave(resolve)))
.then(() => {
this.enterPromise = null;
});
},
enter(resolve) {
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.enter : duration;
if (this.status === 'enter') {
return;
}
this.status = 'enter';
this.$emit('before-enter');
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.$emit('enter');
this.setData({
inited: true,
display: true,
classes: classNames.enter,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.transitionEnded = false;
this.setData({ classes: classNames['enter-to'] });
resolve();
});
});
},
leave(resolve) {
if (!this.data.display) {
return;
}
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.leave : duration;
this.status = 'leave';
this.$emit('before-leave');
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.$emit('leave');
this.setData({
classes: classNames.leave,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.transitionEnded = false;
setTimeout(() => {
this.onTransitionEnd();
resolve();
}, currentDuration);
this.setData({ classes: classNames['leave-to'] });
});
});
},
onTransitionEnd() {
if (this.transitionEnded) {
return;
}
this.transitionEnded = true;
this.$emit(`after-${this.status}`);
const { show, display } = this.data;
if (!show && display) {
this.setData({ display: false });
}
},
},
});
}
================================================
FILE: dist/nav-bar/index.d.ts
================================================
export {};
================================================
FILE: dist/nav-bar/index.js
================================================
import { VantComponent } from '../common/component';
import { getRect, getSystemInfoSync } from '../common/utils';
VantComponent({
classes: ['title-class'],
props: {
title: String,
fixed: {
type: Boolean,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
leftText: String,
rightText: String,
customStyle: String,
leftArrow: Boolean,
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetTop: {
type: Boolean,
value: true,
},
},
data: {
height: 46,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({
statusBarHeight,
height: 46 + statusBarHeight,
});
},
mounted() {
this.setHeight();
},
methods: {
onClickLeft() {
this.$emit('click-left');
},
onClickRight() {
this.$emit('click-right');
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-nav-bar').then((res) => {
if (res && 'height' in res) {
this.setData({ height: res.height });
}
});
});
},
},
});
================================================
FILE: dist/nav-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/nav-bar/index.wxml
================================================
{{ leftText }}
{{ title }}
{{ rightText }}
================================================
FILE: dist/nav-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function barStyle(data) {
return style({
'z-index': data.zIndex,
'padding-top': data.safeAreaInsetTop ? data.statusBarHeight + 'px' : 0,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: dist/nav-bar/index.wxss
================================================
@import '../common/index.wxss';.van-nav-bar{background-color:var(--nav-bar-background-color,#fff);box-sizing:initial;height:var(--nav-bar-height,46px);line-height:var(--nav-bar-height,46px);position:relative;text-align:center;-webkit-user-select:none;user-select:none}.van-nav-bar__content{height:100%;position:relative}.van-nav-bar__text{color:var(--nav-bar-text-color,#1989fa);display:inline-block;margin:0 calc(var(--padding-md, 16px)*-1);padding:0 var(--padding-md,16px);vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:var(--nav-bar-icon-color,#1989fa)!important;font-size:var(--nav-bar-arrow-size,16px)!important;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{left:0;position:fixed;top:0;width:100%}.van-nav-bar__title{color:var(--nav-bar-title-text-color,#323233);font-size:var(--nav-bar-title-font-size,16px);font-weight:var(--font-weight-bold,500);margin:0 auto;max-width:60%}.van-nav-bar__left,.van-nav-bar__right{align-items:center;bottom:0;display:flex;font-size:var(--font-size-md,14px);position:absolute;top:0}.van-nav-bar__left{left:var(--padding-md,16px)}.van-nav-bar__right{right:var(--padding-md,16px)}
================================================
FILE: dist/notice-bar/index.d.ts
================================================
export {};
================================================
FILE: dist/notice-bar/index.js
================================================
import { VantComponent } from '../common/component';
import { getRect, requestAnimationFrame } from '../common/utils';
VantComponent({
props: {
text: {
type: String,
value: '',
observer: 'init',
},
mode: {
type: String,
value: '',
},
url: {
type: String,
value: '',
},
openType: {
type: String,
value: 'navigate',
},
delay: {
type: Number,
value: 1,
},
speed: {
type: Number,
value: 60,
observer: 'init',
},
scrollable: null,
leftIcon: {
type: String,
value: '',
},
color: String,
backgroundColor: String,
background: String,
wrapable: Boolean,
},
data: {
show: true,
},
created() {
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear',
});
},
destroyed() {
this.timer && clearTimeout(this.timer);
},
mounted() {
this.init();
},
methods: {
init() {
requestAnimationFrame(() => {
Promise.all([
getRect(this, '.van-notice-bar__content'),
getRect(this, '.van-notice-bar__wrap'),
]).then((rects) => {
const [contentRect, wrapRect] = rects;
const { scrollable } = this.data;
if (contentRect == null ||
wrapRect == null ||
!contentRect.width ||
!wrapRect.width ||
scrollable === false) {
return;
}
if (scrollable || wrapRect.width < contentRect.width) {
this.initAnimation(wrapRect.width, contentRect.width);
this.scroll(true);
}
});
});
},
initAnimation(warpWidth, contentWidth) {
const { speed, delay } = this.data;
this.wrapWidth = warpWidth;
this.contentWidth = contentWidth;
// begin 0
this.contentDuration = (contentWidth / speed) * 1000;
// begin -wrapWidth
this.duration = ((warpWidth + contentWidth) / speed) * 1000;
this.animation = wx.createAnimation({
duration: this.contentDuration,
timingFunction: 'linear',
delay,
});
},
scroll(isInit = false) {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({
animationData: this.resetAnimation
.translateX(isInit ? 0 : this.wrapWidth)
.step()
.export(),
});
const duration = isInit ? this.contentDuration : this.duration;
requestAnimationFrame(() => {
this.setData({
animationData: this.animation
.translateX(-this.contentWidth)
.step({ duration })
.export(),
});
});
this.timer = setTimeout(() => {
this.scroll();
}, duration + this.data.delay);
},
onClickIcon(event) {
if (this.data.mode === 'closeable') {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({ show: false });
this.$emit('close', event.detail);
}
},
onClick(event) {
this.$emit('click', event);
},
},
});
================================================
FILE: dist/notice-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/notice-bar/index.wxml
================================================
{{ text }}
================================================
FILE: dist/notice-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
color: data.color,
'background-color': data.backgroundColor,
background: data.background,
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/notice-bar/index.wxss
================================================
@import '../common/index.wxss';.van-notice-bar{align-items:center;background-color:var(--notice-bar-background-color,#fffbe8);color:var(--notice-bar-text-color,#ed6a0c);display:flex;font-size:var(--notice-bar-font-size,14px);height:var(--notice-bar-height,40px);line-height:var(--notice-bar-line-height,24px);padding:var(--notice-bar-padding,0 16px)}.van-notice-bar--withicon{padding-right:40px;position:relative}.van-notice-bar--wrapable{height:auto;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{align-items:center;display:flex;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:var(--notice-bar-icon-size,16px);min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;right:15px;top:10px}.van-notice-bar__wrap{flex:1;height:var(--notice-bar-line-height,24px);overflow:hidden;position:relative}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
================================================
FILE: dist/notify/index.d.ts
================================================
export {};
================================================
FILE: dist/notify/index.js
================================================
import { VantComponent } from '../common/component';
import { WHITE } from '../common/color';
import { getSystemInfoSync } from '../common/utils';
VantComponent({
props: {
message: String,
background: String,
type: {
type: String,
value: 'danger',
},
color: {
type: String,
value: WHITE,
},
duration: {
type: Number,
value: 3000,
},
zIndex: {
type: Number,
value: 110,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
top: null,
},
data: {
show: false,
onOpened: null,
onClose: null,
onClick: null,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({ statusBarHeight });
},
methods: {
show() {
const { duration, onOpened } = this.data;
clearTimeout(this.timer);
this.setData({ show: true });
wx.nextTick(onOpened);
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
const { onClose } = this.data;
clearTimeout(this.timer);
this.setData({ show: false });
wx.nextTick(onClose);
},
onTap(event) {
const { onClick } = this.data;
if (onClick) {
onClick(event.detail);
}
},
},
});
================================================
FILE: dist/notify/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: dist/notify/index.wxml
================================================
{{ message }}
================================================
FILE: dist/notify/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'z-index': data.zIndex,
top: addUnit(data.top),
});
}
function notifyStyle(data) {
return style({
background: data.background,
color: data.color,
});
}
module.exports = {
rootStyle: rootStyle,
notifyStyle: notifyStyle,
};
================================================
FILE: dist/notify/index.wxss
================================================
@import '../common/index.wxss';.van-notify{word-wrap:break-word;font-size:var(--notify-font-size,14px);line-height:var(--notify-line-height,20px);padding:var(--notify-padding,6px 15px);text-align:center}.van-notify__container{box-sizing:border-box;left:0;position:fixed;top:0;width:100%}.van-notify--primary{background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:var(--notify-warning-background-color,#ff976a)}
================================================
FILE: dist/notify/notify.d.ts
================================================
interface NotifyOptions {
type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string;
zIndex?: number;
top?: number;
message: string;
context?: any;
duration?: number;
selector?: string;
background?: string;
safeAreaInsetTop?: boolean;
onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
declare function Notify(options: NotifyOptions | string): any;
declare namespace Notify {
var clear: (options?: NotifyOptions | undefined) => void;
var setDefaultOptions: (options: NotifyOptions) => void;
var resetDefaultOptions: () => void;
}
export default Notify;
================================================
FILE: dist/notify/notify.js
================================================
import { WHITE } from '../common/color';
const defaultOptions = {
selector: '#van-notify',
type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
top: 0,
color: WHITE,
safeAreaInsetTop: false,
onClick: () => { },
onOpened: () => { },
onClose: () => { },
};
let currentOptions = Object.assign({}, defaultOptions);
function parseOptions(message) {
if (message == null) {
return {};
}
return typeof message === 'string' ? { message } : message;
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export default function Notify(options) {
options = Object.assign(Object.assign({}, currentOptions), parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (notify) {
notify.setData(options);
notify.show();
return notify;
}
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
Notify.clear = function (options) {
options = Object.assign(Object.assign({}, defaultOptions), parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
if (notify) {
notify.hide();
}
};
Notify.setDefaultOptions = (options) => {
Object.assign(currentOptions, options);
};
Notify.resetDefaultOptions = () => {
currentOptions = Object.assign({}, defaultOptions);
};
================================================
FILE: dist/overlay/index.d.ts
================================================
export {};
================================================
FILE: dist/overlay/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
customStyle: String,
duration: {
type: null,
value: 300,
},
zIndex: {
type: Number,
value: 1,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClick() {
this.$emit('click');
},
// for prevent touchmove
noop() { },
},
});
================================================
FILE: dist/overlay/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: dist/overlay/index.wxml
================================================
================================================
FILE: dist/overlay/index.wxss
================================================
@import '../common/index.wxss';.van-overlay{background-color:var(--overlay-background-color,rgba(0,0,0,.7));height:100%;left:0;position:fixed;top:0;width:100%}
================================================
FILE: dist/overlay/overlay.wxml
================================================
================================================
FILE: dist/panel/index.d.ts
================================================
export {};
================================================
FILE: dist/panel/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['header-class', 'footer-class'],
props: {
desc: String,
title: String,
status: String,
},
});
================================================
FILE: dist/panel/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: dist/panel/index.wxml
================================================
================================================
FILE: dist/panel/index.wxss
================================================
@import '../common/index.wxss';.van-panel{background:var(--panel-background-color,#fff)}.van-panel__header-value{color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:var(--panel-footer-padding,8px 16px)}.van-panel__footer:empty{display:none}
================================================
FILE: dist/picker/index.d.ts
================================================
export {};
================================================
FILE: dist/picker/index.js
================================================
import { VantComponent } from '../common/component';
import { pickerProps } from './shared';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
type: String,
value: 'text',
}, toolbarPosition: {
type: String,
value: 'top',
}, defaultIndex: {
type: Number,
value: 0,
}, columns: {
type: Array,
value: [],
observer(columns = []) {
this.simple = columns.length && !columns[0].values;
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => { });
}
},
} }),
beforeCreate() {
Object.defineProperty(this, 'children', {
get: () => this.selectAllComponents('.van-picker__column') || [],
});
},
methods: {
noop() { },
setColumns() {
const { data } = this;
const columns = this.simple ? [{ values: data.columns }] : data.columns;
const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
return Promise.all(stack);
},
emit(event) {
const { type } = event.currentTarget.dataset;
if (this.simple) {
this.$emit(type, {
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
}
else {
this.$emit(type, {
value: this.getValues(),
index: this.getIndexes(),
});
}
},
onChange(event) {
if (this.simple) {
this.$emit('change', {
picker: this,
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
}
else {
this.$emit('change', {
picker: this,
value: this.getValues(),
index: event.currentTarget.dataset.index,
});
}
},
// get column instance by index
getColumn(index) {
return this.children[index];
},
// get column value by index
getColumnValue(index) {
const column = this.getColumn(index);
return column && column.getValue();
},
// set column value by index
setColumnValue(index, value) {
const column = this.getColumn(index);
if (column == null) {
return Promise.reject(new Error('setColumnValue: 对应列不存在'));
}
return column.setValue(value);
},
// get column option index by column index
getColumnIndex(columnIndex) {
return (this.getColumn(columnIndex) || {}).data.currentIndex;
},
// set column option index by column index
setColumnIndex(columnIndex, optionIndex) {
const column = this.getColumn(columnIndex);
if (column == null) {
return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
}
return column.setIndex(optionIndex);
},
// get options of column by index
getColumnValues(index) {
return (this.children[index] || {}).data.options;
},
// set options of column by index
setColumnValues(index, options, needReset = true) {
const column = this.children[index];
if (column == null) {
return Promise.reject(new Error('setColumnValues: 对应列不存在'));
}
const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) {
return Promise.resolve();
}
return column.set({ options }).then(() => {
if (needReset) {
column.setIndex(0);
}
});
},
// get values of all columns
getValues() {
return this.children.map((child) => child.getValue());
},
// set values of all columns
setValues(values) {
const stack = values.map((value, index) => this.setColumnValue(index, value));
return Promise.all(stack);
},
// get indexes of all columns
getIndexes() {
return this.children.map((child) => child.data.currentIndex);
},
// set indexes of all columns
setIndexes(indexes) {
const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
return Promise.all(stack);
},
},
});
================================================
FILE: dist/picker/index.json
================================================
{
"component": true,
"usingComponents": {
"picker-column": "../picker-column/index",
"loading": "../loading/index"
}
}
================================================
FILE: dist/picker/index.wxml
================================================
================================================
FILE: dist/picker/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
var array = require('../wxs/array.wxs');
function columnsStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function maskStyle(data) {
return style({
'background-size':
'100% ' + addUnit((data.itemHeight * (data.visibleItemCount - 1)) / 2),
});
}
function frameStyle(data) {
return style({
height: addUnit(data.itemHeight),
});
}
function columns(columns) {
if (!array.isArray(columns)) {
return [];
}
if (columns.length && !columns[0].values) {
return [{ values: columns }];
}
return columns;
}
module.exports = {
columnsStyle: columnsStyle,
frameStyle: frameStyle,
maskStyle: maskStyle,
columns: columns,
};
================================================
FILE: dist/picker/index.wxss
================================================
@import '../common/index.wxss';.van-picker{-webkit-text-size-adjust:100%;background-color:var(--picker-background-color,#fff);overflow:hidden;position:relative;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:flex;height:var(--picker-toolbar-height,44px);justify-content:space-between;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{font-size:var(--picker-action-font-size,14px);padding:var(--picker-action-padding,0 16px)}.van-picker__cancel--hover,.van-picker__confirm--hover{opacity:.7}.van-picker__confirm{color:var(--picker-confirm-action-color,#576b95)}.van-picker__cancel{color:var(--picker-cancel-action-color,#969799)}.van-picker__title{font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);max-width:50%;text-align:center}.van-picker__columns{display:flex;position:relative}.van-picker__column{flex:1 1;width:0}.van-picker__loading{align-items:center;background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9));bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:4}.van-picker__mask{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-position:top,bottom;background-repeat:no-repeat;height:100%;left:0;top:0;width:100%;z-index:2}.van-picker__frame,.van-picker__mask{pointer-events:none;position:absolute}.van-picker__frame{left:16px;right:16px;top:50%;transform:translateY(-50%);z-index:1}
================================================
FILE: dist/picker/shared.d.ts
================================================
export declare const pickerProps: {
title: StringConstructor;
loading: BooleanConstructor;
showToolbar: BooleanConstructor;
cancelButtonText: {
type: StringConstructor;
value: string;
};
confirmButtonText: {
type: StringConstructor;
value: string;
};
visibleItemCount: {
type: NumberConstructor;
value: number;
};
itemHeight: {
type: NumberConstructor;
value: number;
};
};
================================================
FILE: dist/picker/shared.js
================================================
export const pickerProps = {
title: String,
loading: Boolean,
showToolbar: Boolean,
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonText: {
type: String,
value: '确认',
},
visibleItemCount: {
type: Number,
value: 6,
},
itemHeight: {
type: Number,
value: 44,
},
};
================================================
FILE: dist/picker/toolbar.wxml
================================================
{{ cancelButtonText }}
{{
title
}}
{{ confirmButtonText }}
================================================
FILE: dist/picker-column/index.d.ts
================================================
export {};
================================================
FILE: dist/picker-column/index.js
================================================
import { VantComponent } from '../common/component';
import { range } from '../common/utils';
import { isObj } from '../common/validator';
const DEFAULT_DURATION = 200;
VantComponent({
classes: ['active-class'],
props: {
valueKey: String,
className: String,
itemHeight: Number,
visibleItemCount: Number,
initialOptions: {
type: Array,
value: [],
},
defaultIndex: {
type: Number,
value: 0,
observer(value) {
this.setIndex(value);
},
},
},
data: {
startY: 0,
offset: 0,
duration: 0,
startOffset: 0,
options: [],
currentIndex: 0,
},
created() {
const { defaultIndex, initialOptions } = this.data;
this.set({
currentIndex: defaultIndex,
options: initialOptions,
}).then(() => {
this.setIndex(defaultIndex);
});
},
methods: {
getCount() {
return this.data.options.length;
},
onTouchStart(event) {
this.setData({
startY: event.touches[0].clientY,
startOffset: this.data.offset,
duration: 0,
});
},
onTouchMove(event) {
const { data } = this;
const deltaY = event.touches[0].clientY - data.startY;
this.setData({
offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
});
},
onTouchEnd() {
const { data } = this;
if (data.offset !== data.startOffset) {
this.setData({ duration: DEFAULT_DURATION });
const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
this.setIndex(index, true);
}
},
onClickItem(event) {
const { index } = event.currentTarget.dataset;
this.setIndex(index, true);
},
adjustIndex(index) {
const { data } = this;
const count = this.getCount();
index = range(index, 0, count);
for (let i = index; i < count; i++) {
if (!this.isDisabled(data.options[i]))
return i;
}
for (let i = index - 1; i >= 0; i--) {
if (!this.isDisabled(data.options[i]))
return i;
}
},
isDisabled(option) {
return isObj(option) && option.disabled;
},
getOptionText(option) {
const { data } = this;
return isObj(option) && data.valueKey in option
? option[data.valueKey]
: option;
},
setIndex(index, userAction) {
const { data } = this;
index = this.adjustIndex(index) || 0;
const offset = -index * data.itemHeight;
if (index !== data.currentIndex) {
return this.set({ offset, currentIndex: index }).then(() => {
userAction && this.$emit('change', index);
});
}
return this.set({ offset });
},
setValue(value) {
const { options } = this.data;
for (let i = 0; i < options.length; i++) {
if (this.getOptionText(options[i]) === value) {
return this.setIndex(i);
}
}
return Promise.resolve();
},
getValue() {
const { data } = this;
return data.options[data.currentIndex];
},
},
});
================================================
FILE: dist/picker-column/index.json
================================================
{
"component": true
}
================================================
FILE: dist/picker-column/index.wxml
================================================
{{ computed.optionText(option, valueKey) }}
================================================
FILE: dist/picker-column/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function optionText(option, valueKey) {
return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
}
function rootStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function wrapperStyle(data) {
var offset = addUnit(
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
);
return style({
transition: 'transform ' + data.duration + 'ms',
'line-height': addUnit(data.itemHeight),
transform: 'translate3d(0, ' + offset + ', 0)',
});
}
module.exports = {
optionText: optionText,
rootStyle: rootStyle,
wrapperStyle: wrapperStyle,
};
================================================
FILE: dist/picker-column/index.wxss
================================================
@import '../common/index.wxss';.van-picker-column{color:var(--picker-option-text-color,#000);font-size:var(--picker-option-font-size,16px);overflow:hidden;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{color:var(--picker-option-selected-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}
================================================
FILE: dist/popup/index.d.ts
================================================
export {};
================================================
FILE: dist/popup/index.js
================================================
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
'close-icon-class',
],
mixins: [transition(false)],
props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: {
type: String,
observer: 'observeClass',
},
zIndex: {
type: Number,
value: 100,
},
overlay: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
closeIconPosition: {
type: String,
value: 'top-right',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
position: {
type: String,
value: 'center',
observer: 'observeClass',
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
created() {
this.observeClass();
},
methods: {
onClickCloseIcon() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
},
observeClass() {
const { transition, position, duration } = this.data;
const updateData = {
name: transition || position,
};
if (transition === 'none') {
updateData.duration = 0;
this.originDuration = duration;
}
else if (this.originDuration != null) {
updateData.duration = this.originDuration;
}
this.setData(updateData);
},
},
});
================================================
FILE: dist/popup/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index"
}
}
================================================
FILE: dist/popup/index.wxml
================================================
================================================
FILE: dist/popup/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function popupStyle(data) {
return style([
{
'z-index': data.zIndex,
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
popupStyle: popupStyle,
};
================================================
FILE: dist/popup/index.wxss
================================================
@import '../common/index.wxss';.van-popup{-webkit-overflow-scrolling:touch;animation:ease both;background-color:var(--popup-background-color,#fff);box-sizing:border-box;max-height:100%;overflow-y:auto;position:fixed;transition-timing-function:ease}.van-popup--center{left:50%;top:50%;transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:var(--popup-round-border-radius,16px)}.van-popup--top{left:0;top:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--right{right:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0}.van-popup--left{left:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--bottom.van-popup--safeTabBar,.van-popup--top.van-popup--safeTabBar{bottom:var(--tabbar-height,50px)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{color:var(--popup-close-icon-color,#969799);font-size:var(--popup-close-icon-size,18px);position:absolute;z-index:var(--popup-close-icon-z-index,1)}.van-popup__close-icon--top-left{left:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{right:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:var(--popup-close-icon-margin,16px);left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{bottom:var(--popup-close-icon-margin,16px);right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,transform}.van-scale-enter,.van-scale-leave-to{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:transform}.van-bottom-enter,.van-bottom-leave-to{transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{transform:translate3d(100%,-50%,0)}
================================================
FILE: dist/popup/popup.wxml
================================================
================================================
FILE: dist/progress/index.d.ts
================================================
export {};
================================================
FILE: dist/progress/index.js
================================================
import { VantComponent } from '../common/component';
import { BLUE } from '../common/color';
import { getRect } from '../common/utils';
VantComponent({
props: {
inactive: Boolean,
percentage: {
type: Number,
observer: 'setLeft',
},
pivotText: String,
pivotColor: String,
trackColor: String,
showPivot: {
type: Boolean,
value: true,
},
color: {
type: String,
value: BLUE,
},
textColor: {
type: String,
value: '#fff',
},
strokeWidth: {
type: null,
value: 4,
},
},
data: {
right: 0,
},
mounted() {
this.setLeft();
},
methods: {
setLeft() {
Promise.all([
getRect(this, '.van-progress'),
getRect(this, '.van-progress__pivot'),
]).then(([portion, pivot]) => {
if (portion && pivot) {
this.setData({
right: (pivot.width * (this.data.percentage - 100)) / 100,
});
}
});
},
},
});
================================================
FILE: dist/progress/index.json
================================================
{
"component": true
}
================================================
FILE: dist/progress/index.wxml
================================================
{{ computed.pivotText(pivotText, percentage) }}
================================================
FILE: dist/progress/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function pivotText(pivotText, percentage) {
return pivotText || percentage + '%';
}
function rootStyle(data) {
return style({
'height': data.strokeWidth ? utils.addUnit(data.strokeWidth) : '',
'background': data.trackColor,
});
}
function portionStyle(data) {
return style({
background: data.inactive ? '#cacaca' : data.color,
width: data.percentage ? data.percentage + '%' : '',
});
}
function pivotStyle(data) {
return style({
color: data.textColor,
right: data.right + 'px',
background: data.pivotColor ? data.pivotColor : data.inactive ? '#cacaca' : data.color,
});
}
module.exports = {
pivotText: pivotText,
rootStyle: rootStyle,
portionStyle: portionStyle,
pivotStyle: pivotStyle,
};
================================================
FILE: dist/progress/index.wxss
================================================
@import '../common/index.wxss';.van-progress{background:var(--progress-background-color,#ebedf0);border-radius:var(--progress-height,4px);height:var(--progress-height,4px);position:relative}.van-progress__portion{background:var(--progress-color,#1989fa);border-radius:inherit;height:100%;left:0;position:absolute}.van-progress__pivot{background-color:var(--progress-pivot-background-color,#1989fa);border-radius:1em;box-sizing:border-box;color:var(--progress-pivot-text-color,#fff);font-size:var(--progress-pivot-font-size,10px);line-height:var(--progress-pivot-line-height,1.6);min-width:3.6em;padding:var(--progress-pivot-padding,0 5px);position:absolute;text-align:center;top:50%;transform:translateY(-50%);word-break:keep-all}
================================================
FILE: dist/radio/index.d.ts
================================================
export {};
================================================
FILE: dist/radio/index.js
================================================
import { canIUseModel } from '../common/version';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
field: true,
relation: useParent('radio-group', function () {
this.updateFromParent();
}),
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
direction: '',
parentDisabled: false,
},
methods: {
updateFromParent() {
if (!this.parent) {
return;
}
const { value, disabled: parentDisabled, direction } = this.parent.data;
this.setData({
value,
direction,
parentDisabled,
});
},
emitChange(value) {
const instance = this.parent || this;
instance.$emit('input', value);
instance.$emit('change', value);
if (canIUseModel()) {
instance.setData({ value });
}
},
onChange() {
if (!this.data.disabled && !this.data.parentDisabled) {
this.emitChange(this.data.name);
}
},
onClickLabel() {
const { disabled, parentDisabled, labelDisabled, name } = this.data;
if (!(disabled || parentDisabled) && !labelDisabled) {
this.emitChange(name);
}
},
},
});
================================================
FILE: dist/radio/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/radio/index.wxml
================================================
================================================
FILE: dist/radio/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(data) {
var styles = {
'font-size': addUnit(data.iconSize),
};
if (
data.checkedColor &&
!(data.disabled || data.parentDisabled) &&
data.value === data.name
) {
styles['border-color'] = data.checkedColor;
styles['background-color'] = data.checkedColor;
}
return style(styles);
}
function iconCustomStyle(data) {
return style({
'line-height': addUnit(data.iconSize),
'font-size': '.8em',
display: 'block',
});
}
module.exports = {
iconStyle: iconStyle,
iconCustomStyle: iconCustomStyle,
};
================================================
FILE: dist/radio/index.wxss
================================================
@import '../common/index.wxss';.van-radio{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{flex:none}.van-radio--horizontal{margin-right:var(--padding-sm,12px)}.van-radio__icon{align-items:center;border:1px solid var(--radio-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--radio-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--radio-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{background-color:var(--radio-checked-icon-color,#1989fa);border-color:var(--radio-checked-icon-color,#1989fa);color:#fff}.van-radio__icon--disabled{background-color:var(--radio-disabled-background-color,#ebedf0);border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;color:var(--radio-label-color,#323233);line-height:var(--radio-size,20px);padding-left:var(--radio-label-margin,10px)}.van-radio__label--left{float:left;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
================================================
FILE: dist/radio-group/index.d.ts
================================================
export {};
================================================
FILE: dist/radio-group/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
field: true,
relation: useChildren('radio'),
props: {
value: {
type: null,
observer: 'updateChildren',
},
direction: String,
disabled: {
type: Boolean,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => child.updateFromParent());
},
},
});
================================================
FILE: dist/radio-group/index.json
================================================
{
"component": true
}
================================================
FILE: dist/radio-group/index.wxml
================================================
================================================
FILE: dist/radio-group/index.wxss
================================================
@import '../common/index.wxss';.van-radio-group--horizontal{display:flex;flex-wrap:wrap}
================================================
FILE: dist/rate/index.d.ts
================================================
export {};
================================================
FILE: dist/rate/index.js
================================================
import { getAllRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['icon-class'],
props: {
value: {
type: Number,
observer(value) {
if (value !== this.data.innerValue) {
this.setData({ innerValue: value });
}
},
},
readonly: Boolean,
disabled: Boolean,
allowHalf: Boolean,
size: null,
icon: {
type: String,
value: 'star',
},
voidIcon: {
type: String,
value: 'star-o',
},
color: String,
voidColor: String,
disabledColor: String,
count: {
type: Number,
value: 5,
observer(value) {
this.setData({ innerCountArray: Array.from({ length: value }) });
},
},
gutter: null,
touchable: {
type: Boolean,
value: true,
},
},
data: {
innerValue: 0,
innerCountArray: Array.from({ length: 5 }),
},
methods: {
onSelect(event) {
const { data } = this;
const { score } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) {
this.setData({ innerValue: score + 1 });
if (canIUseModel()) {
this.setData({ value: score + 1 });
}
wx.nextTick(() => {
this.$emit('input', score + 1);
this.$emit('change', score + 1);
});
}
},
onTouchMove(event) {
const { touchable } = this.data;
if (!touchable)
return;
const { clientX } = event.touches[0];
getAllRect(this, '.van-rate__icon').then((list) => {
const target = list
.sort((cur, next) => cur.dataset.score - next.dataset.score)
.find((item) => clientX >= item.left && clientX <= item.right);
if (target != null) {
this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
}
});
},
},
});
================================================
FILE: dist/rate/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/rate/index.wxml
================================================
================================================
FILE: dist/rate/index.wxss
================================================
@import '../common/index.wxss';.van-rate{display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{padding:0 var(--rate-horizontal-padding,2px);position:relative}.van-rate__item:not(:last-child){padding-right:var(--rate-icon-gutter,4px)}.van-rate__icon{color:var(--rate-icon-void-color,#c8c9cc);display:block;font-size:var(--rate-icon-size,20px);height:100%}.van-rate__icon--half{left:var(--rate-horizontal-padding,2px);overflow:hidden;position:absolute;top:0;width:.5em}.van-rate__icon--full,.van-rate__icon--half{color:var(--rate-icon-full-color,#ee0a24)}.van-rate__icon--disabled{color:var(--rate-icon-disabled-color,#c8c9cc)}
================================================
FILE: dist/row/index.d.ts
================================================
export {};
================================================
FILE: dist/row/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('col', function (target) {
const { gutter } = this.data;
if (gutter) {
target.setData({ gutter });
}
}),
props: {
gutter: {
type: Number,
observer: 'setGutter',
},
},
methods: {
setGutter() {
this.children.forEach((col) => {
col.setData(this.data);
});
},
},
});
================================================
FILE: dist/row/index.json
================================================
{
"component": true
}
================================================
FILE: dist/row/index.wxml
================================================
================================================
FILE: dist/row/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'margin-right': addUnit(-data.gutter / 2),
'margin-left': addUnit(-data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/row/index.wxss
================================================
@import '../common/index.wxss';.van-row:after{clear:both;content:"";display:table}
================================================
FILE: dist/search/index.d.ts
================================================
export {};
================================================
FILE: dist/search/index.js
================================================
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
value: {
type: String,
value: '',
},
label: String,
focus: Boolean,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search',
},
rightIcon: String,
placeholder: String,
placeholderStyle: String,
actionText: {
type: String,
value: '取消',
},
background: {
type: String,
value: '#ffffff',
},
maxlength: {
type: Number,
value: -1,
},
shape: {
type: String,
value: 'square',
},
clearable: {
type: Boolean,
value: true,
},
clearTrigger: {
type: String,
value: 'focus',
},
clearIcon: {
type: String,
value: 'clear',
},
cursorSpacing: {
type: Number,
value: 0,
},
},
methods: {
onChange(event) {
if (canIUseModel()) {
this.setData({ value: event.detail });
}
this.$emit('change', event.detail);
},
onCancel() {
/**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* https://github.com/youzan/vant-weapp/issues/1768
*/
setTimeout(() => {
if (canIUseModel()) {
this.setData({ value: '' });
}
this.$emit('cancel');
this.$emit('change', '');
}, 200);
},
onSearch(event) {
this.$emit('search', event.detail);
},
onFocus(event) {
this.$emit('focus', event.detail);
},
onBlur(event) {
this.$emit('blur', event.detail);
},
onClear(event) {
this.$emit('clear', event.detail);
},
onClickInput(event) {
this.$emit('click-input', event.detail);
},
},
});
================================================
FILE: dist/search/index.json
================================================
{
"component": true,
"usingComponents": {
"van-field": "../field/index"
}
}
================================================
FILE: dist/search/index.wxml
================================================
{{ label }}
{{ actionText }}
================================================
FILE: dist/search/index.wxss
================================================
@import '../common/index.wxss';.van-search{align-items:center;box-sizing:border-box;display:flex;padding:var(--search-padding,10px 12px)}.van-search__content{background-color:var(--search-background-color,#f7f8fa);border-radius:2px;display:flex;flex:1;padding-left:var(--padding-sm,12px)}.van-search__content--round{border-radius:999px}.van-search__label{color:var(--search-label-color,#323233);font-size:var(--search-label-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-label-padding,0 5px)}.van-search__field{flex:1}.van-search__field__left-icon{color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{color:var(--search-action-text-color,#323233);font-size:var(--search-action-font-size,14px);line-height:var(--search-input-height,34px)}.van-search__action--hover{background-color:#f2f3f5}.van-search__action-button{padding:var(--search-action-padding,0 8px)}
================================================
FILE: dist/share-sheet/index.d.ts
================================================
export {};
================================================
FILE: dist/share-sheet/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
// whether to show popup
show: Boolean,
// overlay custom style
overlayStyle: String,
// z-index
zIndex: {
type: Number,
value: 100,
},
title: String,
cancelText: {
type: String,
value: '取消',
},
description: String,
options: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
duration: {
type: null,
value: 300,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClickOverlay() {
this.$emit('click-overlay');
},
onCancel() {
this.onClose();
this.$emit('cancel');
},
onSelect(event) {
this.$emit('select', event.detail);
},
onClose() {
this.$emit('close');
},
},
});
================================================
FILE: dist/share-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"options": "./options"
}
}
================================================
FILE: dist/share-sheet/index.wxml
================================================
================================================
FILE: dist/share-sheet/index.wxs
================================================
/* eslint-disable */
function isMulti(options) {
if (options == null || options[0] == null) {
return false;
}
return "Array" === options.constructor && "Array" === options[0].constructor;
}
module.exports = {
isMulti: isMulti
};
================================================
FILE: dist/share-sheet/index.wxss
================================================
@import '../common/index.wxss';.van-share-sheet__header{padding:12px 16px 4px;text-align:center}.van-share-sheet__title{color:#323233;font-size:14px;font-weight:400;line-height:20px;margin-top:8px}.van-share-sheet__title:empty,.van-share-sheet__title:not(:empty)+.van-share-sheet__title{display:none}.van-share-sheet__description{color:#969799;display:block;font-size:12px;line-height:16px;margin-top:8px}.van-share-sheet__description:empty,.van-share-sheet__description:not(:empty)+.van-share-sheet__description{display:none}.van-share-sheet__cancel{background:#fff;border:none;box-sizing:initial;display:block;font-size:16px;height:auto;line-height:48px;padding:0;text-align:center;width:100%}.van-share-sheet__cancel:before{background-color:#f7f8fa;content:" ";display:block;height:8px}.van-share-sheet__cancel:after{display:none}.van-share-sheet__cancel:active{background-color:#f2f3f5}
================================================
FILE: dist/share-sheet/options.d.ts
================================================
export {};
================================================
FILE: dist/share-sheet/options.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
options: Array,
showBorder: Boolean,
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const option = this.data.options[index];
this.$emit('select', Object.assign(Object.assign({}, option), { index }));
},
},
});
================================================
FILE: dist/share-sheet/options.json
================================================
{
"component": true
}
================================================
FILE: dist/share-sheet/options.wxml
================================================
================================================
FILE: dist/share-sheet/options.wxs
================================================
/* eslint-disable */
var PRESET_ICONS = ['qq', 'link', 'weibo', 'wechat', 'poster', 'qrcode', 'weapp-qrcode', 'wechat-moments'];
function getIconURL(icon) {
if (PRESET_ICONS.indexOf(icon) !== -1) {
return 'https://img.yzcdn.cn/vant/share-sheet-' + icon + '.png';
}
return icon;
}
module.exports = {
getIconURL: getIconURL,
};
================================================
FILE: dist/share-sheet/options.wxss
================================================
@import '../common/index.wxss';.van-share-sheet__options{-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto;overflow-y:visible;padding:16px 0 16px 8px;position:relative}.van-share-sheet__options--border:before{border-top:1px solid #ebedf0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:0;top:0;transform:scaleY(.5);transform-origin:center}.van-share-sheet__options::-webkit-scrollbar{height:0}.van-share-sheet__option{align-items:center;display:flex;flex-direction:column;-webkit-user-select:none;user-select:none}.van-share-sheet__option:active{opacity:.7}.van-share-sheet__button{background-color:initial;border:0;height:auto;line-height:inherit;padding:0}.van-share-sheet__button:after{border:0}.van-share-sheet__icon{height:48px;margin:0 16px;width:48px}.van-share-sheet__name{color:#646566;font-size:12px;margin-top:8px;padding:0 4px}.van-share-sheet__option-description{color:#c8c9cc;font-size:12px;padding:0 4px}
================================================
FILE: dist/sidebar/index.d.ts
================================================
export {};
================================================
FILE: dist/sidebar/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('sidebar-item', function () {
this.setActive(this.data.activeKey);
}),
props: {
activeKey: {
type: Number,
value: 0,
observer: 'setActive',
},
},
beforeCreate() {
this.currentActive = -1;
},
methods: {
setActive(activeKey) {
const { children, currentActive } = this;
if (!children.length) {
return Promise.resolve();
}
this.currentActive = activeKey;
const stack = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
},
},
});
================================================
FILE: dist/sidebar/index.json
================================================
{
"component": true
}
================================================
FILE: dist/sidebar/index.wxml
================================================
================================================
FILE: dist/sidebar/index.wxss
================================================
@import '../common/index.wxss';.van-sidebar{width:var(--sidebar-width,80px)}
================================================
FILE: dist/sidebar-item/index.d.ts
================================================
export {};
================================================
FILE: dist/sidebar-item/index.js
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
classes: ['active-class', 'disabled-class'],
relation: useParent('sidebar'),
props: {
dot: Boolean,
badge: null,
info: null,
title: String,
disabled: Boolean,
},
methods: {
onClick() {
const { parent } = this;
if (!parent || this.data.disabled) {
return;
}
const index = parent.children.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(selected) {
return this.setData({ selected });
},
},
});
================================================
FILE: dist/sidebar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: dist/sidebar-item/index.wxml
================================================
================================================
FILE: dist/sidebar-item/index.wxss
================================================
@import '../common/index.wxss';.van-sidebar-item{background-color:var(--sidebar-background-color,#f7f8fa);border-left:3px solid transparent;box-sizing:border-box;color:var(--sidebar-text-color,#323233);display:block;font-size:var(--sidebar-font-size,14px);line-height:var(--sidebar-line-height,20px);overflow:hidden;padding:var(--sidebar-padding,20px 12px 20px 8px);-webkit-user-select:none;user-select:none}.van-sidebar-item__text{display:inline-block;position:relative;word-break:break-all}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{border-color:var(--sidebar-selected-border-color,#ee0a24);color:var(--sidebar-selected-text-color,#323233);font-weight:var(--sidebar-selected-font-weight,500)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:var(--sidebar-disabled-text-color,#c8c9cc)}
================================================
FILE: dist/skeleton/index.d.ts
================================================
export {};
================================================
FILE: dist/skeleton/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['avatar-class', 'title-class', 'row-class'],
props: {
row: {
type: Number,
value: 0,
observer(value) {
this.setData({ rowArray: Array.from({ length: value }) });
},
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true,
},
animate: {
type: Boolean,
value: true,
},
avatarSize: {
type: String,
value: '32px',
},
avatarShape: {
type: String,
value: 'round',
},
titleWidth: {
type: String,
value: '40%',
},
rowWidth: {
type: null,
value: '100%',
observer(val) {
this.setData({ isArray: val instanceof Array });
},
},
},
data: {
isArray: false,
rowArray: [],
},
});
================================================
FILE: dist/skeleton/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: dist/skeleton/index.wxml
================================================
================================================
FILE: dist/skeleton/index.wxss
================================================
@import '../common/index.wxss';.van-skeleton{box-sizing:border-box;display:flex;padding:var(--skeleton-padding,0 16px);width:100%}.van-skeleton__avatar{background-color:var(--skeleton-avatar-background-color,#f2f3f5);flex-shrink:0;margin-right:var(--padding-md,16px)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{background-color:var(--skeleton-row-background-color,#f2f3f5);height:var(--skeleton-row-height,16px)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{animation:van-skeleton-blink 1.2s ease-in-out infinite}@keyframes van-skeleton-blink{50%{opacity:.6}}
================================================
FILE: dist/slider/index.d.ts
================================================
export {};
================================================
FILE: dist/slider/index.js
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { canIUseModel } from '../common/version';
import { getRect, addUnit, nextTick, addNumber, clamp } from '../common/utils';
const DRAG_STATUS = {
START: 'start',
MOVING: 'moving',
END: 'end',
};
VantComponent({
mixins: [touch],
props: {
range: Boolean,
disabled: Boolean,
useButtonSlot: Boolean,
activeColor: String,
inactiveColor: String,
max: {
type: Number,
value: 100,
},
min: {
type: Number,
value: 0,
},
step: {
type: Number,
value: 1,
},
value: {
type: null,
value: 0,
observer(val) {
if (val !== this.value) {
this.updateValue(val);
}
},
},
vertical: Boolean,
barHeight: null,
},
created() {
this.updateValue(this.data.value);
},
methods: {
onTouchStart(event) {
if (this.data.disabled)
return;
const { index } = event.currentTarget.dataset;
if (typeof index === 'number') {
this.buttonIndex = index;
}
this.touchStart(event);
this.startValue = this.format(this.value);
this.newValue = this.value;
if (this.isRange(this.newValue)) {
this.startValue = this.newValue.map((val) => this.format(val));
}
else {
this.startValue = this.format(this.newValue);
}
this.dragStatus = DRAG_STATUS.START;
},
onTouchMove(event) {
if (this.data.disabled)
return;
if (this.dragStatus === DRAG_STATUS.START) {
this.$emit('drag-start');
}
this.touchMove(event);
this.dragStatus = DRAG_STATUS.MOVING;
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const delta = vertical ? this.deltaY : this.deltaX;
const total = vertical ? rect.height : rect.width;
const diff = (delta / total) * this.getRange();
if (this.isRange(this.startValue)) {
this.newValue[this.buttonIndex] =
this.startValue[this.buttonIndex] + diff;
}
else {
this.newValue = this.startValue + diff;
}
this.updateValue(this.newValue, false, true);
});
},
onTouchEnd() {
if (this.data.disabled)
return;
if (this.dragStatus === DRAG_STATUS.MOVING) {
this.dragStatus = DRAG_STATUS.END;
nextTick(() => {
this.updateValue(this.newValue, true);
this.$emit('drag-end');
});
}
},
onClick(event) {
if (this.data.disabled)
return;
const { min } = this.data;
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const touch = event.touches[0];
const delta = vertical
? touch.clientY - rect.top
: touch.clientX - rect.left;
const total = vertical ? rect.height : rect.width;
const value = Number(min) + (delta / total) * this.getRange();
if (this.isRange(this.value)) {
const [left, right] = this.value;
const middle = (left + right) / 2;
if (value <= middle) {
this.updateValue([value, right], true);
}
else {
this.updateValue([left, value], true);
}
}
else {
this.updateValue(value, true);
}
});
},
isRange(val) {
const { range } = this.data;
return range && Array.isArray(val);
},
handleOverlap(value) {
if (value[0] > value[1]) {
return value.slice(0).reverse();
}
return value;
},
updateValue(value, end, drag) {
if (this.isRange(value)) {
value = this.handleOverlap(value).map((val) => this.format(val));
}
else {
value = this.format(value);
}
this.value = value;
const { vertical } = this.data;
const mainAxis = vertical ? 'height' : 'width';
this.setData({
wrapperStyle: `
background: ${this.data.inactiveColor || ''};
${vertical ? 'width' : 'height'}: ${addUnit(this.data.barHeight) || ''};
`,
barStyle: `
${mainAxis}: ${this.calcMainAxis()};
left: ${vertical ? 0 : this.calcOffset()};
top: ${vertical ? this.calcOffset() : 0};
${drag ? 'transition: none;' : ''}
`,
});
if (drag) {
this.$emit('drag', { value });
}
if (end) {
this.$emit('change', value);
}
if ((drag || end) && canIUseModel()) {
this.setData({ value });
}
},
getScope() {
return Number(this.data.max) - Number(this.data.min);
},
getRange() {
const { max, min } = this.data;
return max - min;
},
getOffsetWidth(current, min) {
const scope = this.getScope();
// 避免最小值小于最小step时出现负数情况
return `${Math.max(((current - min) * 100) / scope, 0)}%`;
},
// 计算选中条的长度百分比
calcMainAxis() {
const { value } = this;
const { min } = this.data;
if (this.isRange(value)) {
return this.getOffsetWidth(value[1], value[0]);
}
return this.getOffsetWidth(value, Number(min));
},
// 计算选中条的开始位置的偏移量
calcOffset() {
const { value } = this;
const { min } = this.data;
const scope = this.getScope();
if (this.isRange(value)) {
return `${((value[0] - Number(min)) * 100) / scope}%`;
}
return '0%';
},
format(value) {
const min = +this.data.min;
const max = +this.data.max;
const step = +this.data.step;
value = clamp(value, min, max);
const diff = Math.round((value - min) / step) * step;
return addNumber(min, diff);
},
},
});
================================================
FILE: dist/slider/index.json
================================================
{
"component": true
}
================================================
FILE: dist/slider/index.wxml
================================================
================================================
FILE: dist/slider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function barStyle(barHeight, activeColor) {
return style({
height: addUnit(barHeight),
background: activeColor,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: dist/slider/index.wxss
================================================
@import '../common/index.wxss';.van-slider{background-color:var(--slider-inactive-background-color,#ebedf0);border-radius:999px;height:var(--slider-bar-height,2px);position:relative}.van-slider:before{bottom:calc(var(--padding-xs, 8px)*-1);content:"";left:0;position:absolute;right:0;top:calc(var(--padding-xs, 8px)*-1)}.van-slider__bar{background-color:var(--slider-active-background-color,#1989fa);border-radius:inherit;height:100%;position:relative;transition:all .2s;width:100%}.van-slider__button{background-color:var(--slider-button-background-color,#fff);border-radius:var(--slider-button-border-radius,50%);box-shadow:var(--slider-button-box-shadow,0 1px 2px rgba(0,0,0,.5));height:var(--slider-button-height,24px);width:var(--slider-button-width,24px)}.van-slider__button-wrapper,.van-slider__button-wrapper-right{position:absolute;right:0;top:50%;transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper-left{left:0;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.van-slider--disabled{opacity:var(--slider-disabled-opacity,.5)}.van-slider--vertical{display:inline-block;height:100%;width:var(--slider-bar-height,2px)}.van-slider--vertical .van-slider__button-wrapper,.van-slider--vertical .van-slider__button-wrapper-right{bottom:0;right:50%;top:auto;transform:translate3d(50%,50%,0)}.van-slider--vertical .van-slider__button-wrapper-left{left:auto;right:50%;top:0;transform:translate3d(50%,-50%,0)}.van-slider--vertical:before{bottom:0;left:-8px;right:-8px;top:0}
================================================
FILE: dist/stepper/index.d.ts
================================================
export {};
================================================
FILE: dist/stepper/index.js
================================================
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
const LONG_PRESS_START_TIME = 600;
const LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1, num2) {
const cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
function equal(value1, value2) {
return String(value1) === String(value2);
}
VantComponent({
field: true,
classes: ['input-class', 'plus-class', 'minus-class'],
props: {
value: {
type: null,
},
integer: {
type: Boolean,
observer: 'check',
},
disabled: Boolean,
inputWidth: String,
buttonSize: String,
asyncChange: Boolean,
disableInput: Boolean,
decimalLength: {
type: Number,
value: null,
observer: 'check',
},
min: {
type: null,
value: 1,
observer: 'check',
},
max: {
type: null,
value: Number.MAX_SAFE_INTEGER,
observer: 'check',
},
step: {
type: null,
value: 1,
},
showPlus: {
type: Boolean,
value: true,
},
showMinus: {
type: Boolean,
value: true,
},
disablePlus: Boolean,
disableMinus: Boolean,
longPress: {
type: Boolean,
value: true,
},
theme: String,
alwaysEmbed: Boolean,
},
data: {
currentValue: '',
},
watch: {
value() {
this.observeValue();
},
},
created() {
this.setData({
currentValue: this.format(this.data.value).newValue,
});
},
methods: {
observeValue() {
const { value } = this.data;
this.setData({ currentValue: this.format(value).newValue });
},
check() {
const { newValue } = this.format(this.data.currentValue);
if (!equal(newValue, this.data.currentValue)) {
this.setData({ currentValue: newValue });
}
},
isDisabled(type) {
const { disabled, disablePlus, disableMinus, currentValue, max, min } = this.data;
if (type === 'plus') {
return disabled || disablePlus || +currentValue >= +max;
}
return disabled || disableMinus || +currentValue <= +min;
},
onFocus(event) {
this.$emit('focus', event.detail);
},
onBlur(event) {
const data = this.format(event.detail.value);
this.setData({ currentValue: data.newValue });
this.emitChange(data);
this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value: +data.newValue }));
},
// filter illegal characters
filter(value) {
value = String(value).replace(/[^0-9.-]/g, '');
if (this.data.integer && value.indexOf('.') !== -1) {
value = value.split('.')[0];
}
return value;
},
format(value) {
// filter illegal characters and format integer
const safeValue = this.filter(value);
// format range
const rangeValue = Math.max(Math.min(this.data.max, +safeValue), this.data.min);
// format decimal
const newValue = isDef(this.data.decimalLength)
? rangeValue.toFixed(this.data.decimalLength)
: String(rangeValue);
return { value, newValue };
},
onInput(event) {
const { value = '' } = event.detail || {};
// allow input to be empty
if (value === '') {
return;
}
const formatted = this.format(value);
this.emitChange(formatted);
},
emitChange(data) {
const { value, newValue } = data;
if (!this.data.asyncChange) {
// fix when input 11. parsed to 11, unable to enter decimal
this.setData({ currentValue: +value === +newValue ? value : newValue });
}
this.$emit('change', +newValue);
},
onChange() {
const { type } = this;
if (this.isDisabled(type)) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = this.format(String(add(+this.data.currentValue, diff)));
this.emitChange(value);
this.$emit(type);
},
longPressStep() {
this.longPressTimer = setTimeout(() => {
this.onChange();
this.longPressStep();
}, LONG_PRESS_INTERVAL);
},
onTap(event) {
const { type } = event.currentTarget.dataset;
this.type = type;
this.onChange();
},
onTouchStart(event) {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
const { type } = event.currentTarget.dataset;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(() => {
this.isLongPress = true;
this.onChange();
this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onTouchEnd() {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
},
},
});
================================================
FILE: dist/stepper/index.json
================================================
{
"component": true
}
================================================
FILE: dist/stepper/index.wxml
================================================
================================================
FILE: dist/stepper/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function buttonStyle(data) {
return style({
width: addUnit(data.buttonSize),
height: addUnit(data.buttonSize),
});
}
function inputStyle(data) {
return style({
width: addUnit(data.inputWidth),
height: addUnit(data.buttonSize),
});
}
module.exports = {
buttonStyle: buttonStyle,
inputStyle: inputStyle,
};
================================================
FILE: dist/stepper/index.wxss
================================================
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{background-color:var(--stepper-background-color,#f2f3f5);border:0;box-sizing:border-box;color:var(--stepper-button-icon-color,#323233);display:inline-block;height:var(--stepper-input-height,28px);margin:1px;padding:var(--padding-base,4px);position:relative;vertical-align:middle;width:var(--stepper-input-height,28px)}.van-stepper__minus:before,.van-stepper__plus:before{height:1px;width:9px}.van-stepper__minus:after,.van-stepper__plus:after{height:9px;width:1px}.van-stepper__minus:empty.van-stepper__minus:after,.van-stepper__minus:empty.van-stepper__minus:before,.van-stepper__minus:empty.van-stepper__plus:after,.van-stepper__minus:empty.van-stepper__plus:before,.van-stepper__plus:empty.van-stepper__minus:after,.van-stepper__plus:empty.van-stepper__minus:before,.van-stepper__plus:empty.van-stepper__plus:after,.van-stepper__plus:empty.van-stepper__plus:before{background-color:currentColor;bottom:0;content:"";left:0;margin:auto;position:absolute;right:0;top:0}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0 0 var(--stepper-border-radius,var(--stepper-border-radius,4px))}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 var(--stepper-border-radius,var(--stepper-border-radius,4px)) var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0}.van-stepper--round .van-stepper__input{background-color:initial!important}.van-stepper--round .van-stepper__minus,.van-stepper--round .van-stepper__plus{border-radius:100%}.van-stepper--round .van-stepper__minus:active,.van-stepper--round .van-stepper__plus:active{opacity:.7}.van-stepper--round .van-stepper__minus--disabled,.van-stepper--round .van-stepper__minus--disabled:active,.van-stepper--round .van-stepper__plus--disabled,.van-stepper--round .van-stepper__plus--disabled:active{opacity:.3}.van-stepper--round .van-stepper__plus{background-color:#ee0a24;color:#fff}.van-stepper--round .van-stepper__minus{background-color:#fff;border:1px solid #ee0a24;color:#ee0a24}.van-stepper__input{-webkit-appearance:none;background-color:var(--stepper-background-color,#f2f3f5);border:0;border-radius:0;border-width:1px 0;box-sizing:border-box;color:var(--stepper-input-text-color,#323233);display:inline-block;font-size:var(--stepper-input-font-size,14px);height:var(--stepper-input-height,28px);margin:1px;min-height:0;padding:1px;text-align:center;vertical-align:middle;width:var(--stepper-input-width,32px)}.van-stepper__input--disabled{background-color:var(--stepper-input-disabled-background-color,#f2f3f5);color:var(--stepper-input-disabled-text-color,#c8c9cc)}
================================================
FILE: dist/steps/index.d.ts
================================================
export {};
================================================
FILE: dist/steps/index.js
================================================
import { VantComponent } from '../common/component';
import { GREEN, GRAY_DARK } from '../common/color';
VantComponent({
classes: ['desc-class'],
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal',
},
activeColor: {
type: String,
value: GREEN,
},
inactiveColor: {
type: String,
value: GRAY_DARK,
},
activeIcon: {
type: String,
value: 'checked',
},
inactiveIcon: String,
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
this.$emit('click-step', index);
},
},
});
================================================
FILE: dist/steps/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/steps/index.wxml
================================================
{{ item.text }}
{{ item.desc }}
function get(index, active) {
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return 'inactive';
}
module.exports = get;
================================================
FILE: dist/steps/index.wxss
================================================
@import '../common/index.wxss';.van-steps{background-color:var(--steps-background-color,#fff);overflow:hidden}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{display:flex;overflow:hidden;position:relative}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{color:var(--step-text-color,#969799);flex:1;font-size:var(--step-font-size,14px);position:relative}.van-step--finish{color:var(--step-finish-text-color,#323233)}.van-step__circle{background-color:var(--step-circle-color,#969799);border-radius:50%;height:var(--step-circle-size,5px);width:var(--step-circle-size,5px)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{bottom:0;position:absolute;right:0;top:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;transform:none}.van-step--horizontal:last-child .van-step__circle-container{padding:0 0 0 8px;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{background-color:#fff;bottom:6px;padding:0 var(--padding-xs,8px);position:absolute;transform:translate3d(-50%,50%,0);z-index:1}.van-step--horizontal .van-step__title{display:inline-block;font-size:var(--step-horizontal-title-font-size,12px);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{background-color:var(--step-line-color,#ebedf0);bottom:6px;height:1px;left:0;position:absolute;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical{line-height:18px;padding:10px 10px 10px 0}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{background-color:#fff;content:"";height:20px;left:-15px;position:absolute;top:0;width:1px;z-index:1}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{left:-14px;position:absolute;top:19px;transform:translate3d(-50%,-50%,0);z-index:2}.van-step--vertical .van-step__icon{background-color:var(--steps-background-color,#fff);font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical .van-step__line{background-color:var(--step-line-color,#ebedf0);height:100%;transform:translate3d(-50%,0,0);width:1px;z-index:1}
================================================
FILE: dist/sticky/index.d.ts
================================================
export {};
================================================
FILE: dist/sticky/index.js
================================================
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pageScrollMixin } from '../mixins/page-scroll';
const ROOT_ELEMENT = '.van-sticky';
VantComponent({
props: {
zIndex: {
type: Number,
value: 99,
},
offsetTop: {
type: Number,
value: 0,
observer: 'onScroll',
},
disabled: {
type: Boolean,
observer: 'onScroll',
},
container: {
type: null,
observer: 'onScroll',
},
scrollTop: {
type: null,
observer(val) {
this.onScroll({ scrollTop: val });
},
},
},
mixins: [
pageScrollMixin(function (event) {
if (this.data.scrollTop != null) {
return;
}
this.onScroll(event);
}),
],
data: {
height: 0,
fixed: false,
transform: 0,
},
mounted() {
this.onScroll();
},
methods: {
onScroll({ scrollTop } = {}) {
const { container, offsetTop, disabled } = this.data;
if (disabled) {
this.setDataAfterDiff({
fixed: false,
transform: 0,
});
return;
}
this.scrollTop = scrollTop || this.scrollTop;
if (typeof container === 'function') {
Promise.all([getRect(this, ROOT_ELEMENT), this.getContainerRect()])
.then(([root, container]) => {
if (offsetTop + root.height > container.height + container.top) {
this.setDataAfterDiff({
fixed: false,
transform: container.height - root.height,
});
}
else if (offsetTop >= root.top) {
this.setDataAfterDiff({
fixed: true,
height: root.height,
transform: 0,
});
}
else {
this.setDataAfterDiff({ fixed: false, transform: 0 });
}
})
.catch(() => { });
return;
}
getRect(this, ROOT_ELEMENT).then((root) => {
if (!isDef(root) || (!root.width && !root.height)) {
return;
}
if (offsetTop >= root.top) {
this.setDataAfterDiff({ fixed: true, height: root.height });
this.transform = 0;
}
else {
this.setDataAfterDiff({ fixed: false });
}
});
},
setDataAfterDiff(data) {
wx.nextTick(() => {
const diff = Object.keys(data).reduce((prev, key) => {
if (data[key] !== this.data[key]) {
prev[key] = data[key];
}
return prev;
}, {});
if (Object.keys(diff).length > 0) {
this.setData(diff);
}
this.$emit('scroll', {
scrollTop: this.scrollTop,
isFixed: data.fixed || this.data.fixed,
});
});
},
getContainerRect() {
const nodesRef = this.data.container();
if (!nodesRef) {
return Promise.reject(new Error('not found container'));
}
return new Promise((resolve) => nodesRef.boundingClientRect(resolve).exec());
},
},
});
================================================
FILE: dist/sticky/index.json
================================================
{
"component": true
}
================================================
FILE: dist/sticky/index.wxml
================================================
================================================
FILE: dist/sticky/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapStyle(data) {
return style({
transform: data.transform
? 'translate3d(0, ' + data.transform + 'px, 0)'
: '',
top: data.fixed ? addUnit(data.offsetTop) : '',
'z-index': data.zIndex,
});
}
function containerStyle(data) {
return style({
height: data.fixed ? addUnit(data.height) : '',
'z-index': data.zIndex,
});
}
module.exports = {
wrapStyle: wrapStyle,
containerStyle: containerStyle,
};
================================================
FILE: dist/sticky/index.wxss
================================================
@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{left:0;position:fixed;right:0}
================================================
FILE: dist/submit-bar/index.d.ts
================================================
export {};
================================================
FILE: dist/submit-bar/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['bar-class', 'price-class', 'button-class'],
props: {
tip: {
type: null,
observer: 'updateTip',
},
tipIcon: String,
type: Number,
price: {
type: null,
observer: 'updatePrice',
},
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥',
},
buttonType: {
type: String,
value: 'danger',
},
decimalLength: {
type: Number,
value: 2,
observer: 'updatePrice',
},
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
updatePrice() {
const { price, decimalLength } = this.data;
const priceStrArr = typeof price === 'number' &&
(price / 100).toFixed(decimalLength).split('.');
this.setData({
hasPrice: typeof price === 'number',
integerStr: priceStrArr && priceStrArr[0],
decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
});
},
updateTip() {
this.setData({ hasTip: typeof this.data.tip === 'string' });
},
onSubmit(event) {
this.$emit('submit', event.detail);
},
},
});
================================================
FILE: dist/submit-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/submit-bar/index.wxml
================================================
{{ tip }}
{{ label || '合计:' }}
{{ currency }}
{{ integerStr }}{{decimalStr}}
{{ suffixLabel }}
{{ loading ? '' : buttonText }}
================================================
FILE: dist/submit-bar/index.wxss
================================================
@import '../common/index.wxss';.van-submit-bar{background-color:var(--submit-bar-background-color,#fff);bottom:0;left:0;position:fixed;-webkit-user-select:none;user-select:none;width:100%;z-index:var(--submit-bar-z-index,100)}.van-submit-bar__tip{background-color:var(--submit-bar-tip-background-color,#fff7cc);color:var(--submit-bar-tip-color,#f56723);font-size:var(--submit-bar-tip-font-size,12px);line-height:var(--submit-bar-tip-line-height,1.5);padding:var(--submit-bar-tip-padding,10px)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{margin-right:4px;vertical-align:middle}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{align-items:center;background-color:var(--submit-bar-background-color,#fff);display:flex;font-size:var(--submit-bar-text-font-size,14px);height:var(--submit-bar-height,50px);justify-content:flex-end;padding:var(--submit-bar-padding,0 16px)}.van-submit-bar__safe{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}.van-submit-bar__text{color:var(--submit-bar-text-color,#323233);flex:1;font-weight:var(--font-weight-bold,500);padding-right:var(--padding-sm,12px);text-align:right}.van-submit-bar__price{color:var(--submit-bar-price-color,#ee0a24);font-size:var(--submit-bar-price-font-size,12px);font-weight:var(--font-weight-bold,500)}.van-submit-bar__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:20px}.van-submit-bar__currency{font-size:var(--submit-bar-currency-font-size,12px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{--button-default-height:var(--submit-bar-button-height,40px)!important;--button-line-height:var(--submit-bar-button-height,40px)!important;font-weight:var(--font-weight-bold,500);width:var(--submit-bar-button-width,110px)}
================================================
FILE: dist/swipe-cell/index.d.ts
================================================
export {};
================================================
FILE: dist/swipe-cell/index.js
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { range } from '../common/utils';
const THRESHOLD = 0.3;
let ARRAY = [];
VantComponent({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0,
observer(leftWidth = 0) {
if (this.offset > 0) {
this.swipeMove(leftWidth);
}
},
},
rightWidth: {
type: Number,
value: 0,
observer(rightWidth = 0) {
if (this.offset < 0) {
this.swipeMove(-rightWidth);
}
},
},
asyncClose: Boolean,
name: {
type: null,
value: '',
},
},
mixins: [touch],
data: {
catchMove: false,
wrapperStyle: '',
},
created() {
this.offset = 0;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
open(position) {
const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
this.$emit('open', {
position,
name: this.data.name,
});
},
close() {
this.swipeMove(0);
},
swipeMove(offset = 0) {
this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
const transform = `translate3d(${this.offset}px, 0, 0)`;
const transition = this.dragging
? 'none'
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.setData({
wrapperStyle: `
-webkit-transform: ${transform};
-webkit-transition: ${transition};
transform: ${transform};
transition: ${transition};
`,
});
},
swipeLeaveTransition() {
const { leftWidth, rightWidth } = this.data;
const { offset } = this;
if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
this.open('right');
}
else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
this.open('left');
}
else {
this.swipeMove(0);
}
this.setData({ catchMove: false });
},
startDrag(event) {
if (this.data.disabled) {
return;
}
this.startOffset = this.offset;
this.touchStart(event);
},
noop() { },
onDrag(event) {
if (this.data.disabled) {
return;
}
this.touchMove(event);
if (this.direction !== 'horizontal') {
return;
}
this.dragging = true;
ARRAY.filter((item) => item !== this && item.offset !== 0).forEach((item) => item.close());
this.setData({ catchMove: true });
this.swipeMove(this.startOffset + this.deltaX);
},
endDrag() {
if (this.data.disabled) {
return;
}
this.dragging = false;
this.swipeLeaveTransition();
},
onClick(event) {
const { key: position = 'outside' } = event.currentTarget.dataset;
this.$emit('click', position);
if (!this.offset) {
return;
}
if (this.data.asyncClose) {
this.$emit('close', {
position,
instance: this,
name: this.data.name,
});
}
else {
this.swipeMove(0);
}
},
},
});
================================================
FILE: dist/swipe-cell/index.json
================================================
{
"component": true
}
================================================
FILE: dist/swipe-cell/index.wxml
================================================
================================================
FILE: dist/swipe-cell/index.wxss
================================================
@import '../common/index.wxss';.van-swipe-cell{overflow:hidden;position:relative}.van-swipe-cell__left,.van-swipe-cell__right{height:100%;position:absolute;top:0}.van-swipe-cell__left{left:0;transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;transform:translate3d(100%,0,0)}
================================================
FILE: dist/switch/index.d.ts
================================================
export {};
================================================
FILE: dist/switch/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['node-class'],
props: {
checked: null,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '30',
},
activeValue: {
type: null,
value: true,
},
inactiveValue: {
type: null,
value: false,
},
},
methods: {
onClick() {
const { activeValue, inactiveValue, disabled, loading } = this.data;
if (disabled || loading) {
return;
}
const checked = this.data.checked === activeValue;
const value = checked ? inactiveValue : activeValue;
this.$emit('input', value);
this.$emit('change', value);
},
},
});
================================================
FILE: dist/switch/index.json
================================================
{
"component": true,
"usingComponents": {
"van-loading": "../loading/index"
}
}
================================================
FILE: dist/switch/index.wxml
================================================
================================================
FILE: dist/switch/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
var currentColor = data.checked === data.activeValue ? data.activeColor : data.inactiveColor;
return style({
'font-size': addUnit(data.size),
'background-color': currentColor,
});
}
var BLUE = '#1989fa';
var GRAY_DARK = '#969799';
function loadingColor(data) {
return data.checked === data.activeValue
? data.activeColor || BLUE
: data.inactiveColor || GRAY_DARK;
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: dist/switch/index.wxss
================================================
@import '../common/index.wxss';.van-switch{background-color:var(--switch-background-color,#fff);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:var(--switch-node-size,1em);box-sizing:initial;display:inline-block;height:var(--switch-height,1em);position:relative;transition:background-color var(--switch-transition-duration,.3s);width:var(--switch-width,2em)}.van-switch__node{background-color:var(--switch-node-background-color,#fff);border-radius:100%;box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));height:var(--switch-node-size,1em);left:0;position:absolute;top:0;transition:var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);width:var(--switch-node-size,1em);z-index:var(--switch-node-z-index,1)}.van-switch__loading{height:50%;left:25%;position:absolute!important;top:25%;width:50%}.van-switch--on{background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:var(--switch-disabled-opacity,.4)}
================================================
FILE: dist/tab/index.d.ts
================================================
export {};
================================================
FILE: dist/tab/index.js
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('tabs'),
props: {
dot: {
type: Boolean,
observer: 'update',
},
info: {
type: null,
observer: 'update',
},
title: {
type: String,
observer: 'update',
},
disabled: {
type: Boolean,
observer: 'update',
},
titleStyle: {
type: String,
observer: 'update',
},
name: {
type: null,
value: '',
},
},
data: {
active: false,
},
methods: {
getComputedName() {
if (this.data.name !== '') {
return this.data.name;
}
return this.index;
},
updateRender(active, parent) {
const { data: parentData } = parent;
this.inited = this.inited || active;
this.setData({
active,
shouldRender: this.inited || !parentData.lazyRender,
shouldShow: active || parentData.animated,
});
},
update() {
if (this.parent) {
this.parent.updateTabs();
}
},
},
});
================================================
FILE: dist/tab/index.json
================================================
{
"component": true
}
================================================
FILE: dist/tab/index.wxml
================================================
================================================
FILE: dist/tab/index.wxss
================================================
@import '../common/index.wxss';:host{box-sizing:border-box;flex-shrink:0;width:100%}.van-tab__pane{-webkit-overflow-scrolling:touch;box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
================================================
FILE: dist/tabbar/index.d.ts
================================================
export {};
================================================
FILE: dist/tabbar/index.js
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect } from '../common/utils';
VantComponent({
relation: useChildren('tabbar-item', function () {
this.updateChildren();
}),
props: {
active: {
type: null,
observer: 'updateChildren',
},
activeColor: {
type: String,
observer: 'updateChildren',
},
inactiveColor: {
type: String,
observer: 'updateChildren',
},
fixed: {
type: Boolean,
value: true,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
data: {
height: 50,
},
methods: {
updateChildren() {
const { children } = this;
if (!Array.isArray(children) || !children.length) {
return;
}
children.forEach((child) => child.updateFromParent());
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-tabbar').then((res) => {
this.setData({ height: res.height });
});
});
},
},
});
================================================
FILE: dist/tabbar/index.json
================================================
{
"component": true
}
================================================
FILE: dist/tabbar/index.wxml
================================================
================================================
FILE: dist/tabbar/index.wxss
================================================
@import '../common/index.wxss';.van-tabbar{background-color:var(--tabbar-background-color,#fff);box-sizing:initial;display:flex;height:var(--tabbar-height,50px);width:100%}.van-tabbar--fixed{bottom:0;left:0;position:fixed}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
================================================
FILE: dist/tabbar-item/index.d.ts
================================================
export {};
================================================
FILE: dist/tabbar-item/index.js
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
props: {
info: null,
name: null,
icon: String,
dot: Boolean,
url: {
type: String,
value: '',
},
linkType: {
type: String,
value: 'redirectTo',
},
iconPrefix: {
type: String,
value: 'van-icon',
},
},
relation: useParent('tabbar'),
data: {
active: false,
activeColor: '',
inactiveColor: '',
},
methods: {
onClick() {
const { parent } = this;
if (parent) {
const index = parent.children.indexOf(this);
const active = this.data.name || index;
if (active !== this.data.active) {
parent.$emit('change', active);
}
}
const { url, linkType } = this.data;
if (url && wx[linkType]) {
return wx[linkType]({ url });
}
this.$emit('click');
},
updateFromParent() {
const { parent } = this;
if (!parent) {
return;
}
const index = parent.children.indexOf(this);
const parentData = parent.data;
const { data } = this;
const active = (data.name || index) === parentData.active;
const patch = {};
if (active !== data.active) {
patch.active = active;
}
if (parentData.activeColor !== data.activeColor) {
patch.activeColor = parentData.activeColor;
}
if (parentData.inactiveColor !== data.inactiveColor) {
patch.inactiveColor = parentData.inactiveColor;
}
if (Object.keys(patch).length > 0) {
this.setData(patch);
}
},
},
});
================================================
FILE: dist/tabbar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-info": "../info/index"
}
}
================================================
FILE: dist/tabbar-item/index.wxml
================================================
================================================
FILE: dist/tabbar-item/index.wxss
================================================
@import '../common/index.wxss';:host{flex:1}.van-tabbar-item{align-items:center;color:var(--tabbar-item-text-color,#646566);display:flex;flex-direction:column;font-size:var(--tabbar-item-font-size,12px);height:100%;justify-content:center;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{font-size:var(--tabbar-item-icon-size,22px);margin-bottom:var(--tabbar-item-margin-bottom,4px);position:relative}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
================================================
FILE: dist/tabs/index.d.ts
================================================
export {};
================================================
FILE: dist/tabs/index.js
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { getAllRect, getRect, groupSetData, nextTick, requestAnimationFrame, } from '../common/utils';
import { isDef } from '../common/validator';
import { useChildren } from '../common/relation';
VantComponent({
mixins: [touch],
classes: [
'nav-class',
'tab-class',
'tab-active-class',
'line-class',
'wrap-class',
],
relation: useChildren('tab', function () {
this.updateTabs();
}),
props: {
sticky: Boolean,
border: Boolean,
swipeable: Boolean,
titleActiveColor: String,
titleInactiveColor: String,
color: String,
animated: {
type: Boolean,
observer() {
this.children.forEach((child, index) => child.updateRender(index === this.data.currentIndex, this));
},
},
lineWidth: {
type: null,
value: 40,
observer: 'resize',
},
lineHeight: {
type: null,
value: -1,
},
active: {
type: null,
value: 0,
observer(name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
},
},
type: {
type: String,
value: 'line',
},
ellipsis: {
type: Boolean,
value: true,
},
duration: {
type: Number,
value: 0.3,
},
zIndex: {
type: Number,
value: 1,
},
swipeThreshold: {
type: Number,
value: 5,
observer(value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis,
});
},
},
offsetTop: {
type: Number,
value: 0,
},
lazyRender: {
type: Boolean,
value: true,
},
useBeforeChange: {
type: Boolean,
value: false,
},
},
data: {
tabs: [],
scrollLeft: 0,
scrollable: false,
currentIndex: 0,
container: null,
skipTransition: true,
scrollWithAnimation: false,
lineOffsetLeft: 0,
inited: false,
},
mounted() {
requestAnimationFrame(() => {
this.swiping = true;
this.setData({
container: () => this.createSelectorQuery().select('.van-tabs'),
});
this.resize();
this.scrollIntoView();
});
},
methods: {
updateTabs() {
const { children = [], data } = this;
this.setData({
tabs: children.map((child) => child.data),
scrollable: this.children.length > data.swipeThreshold || !data.ellipsis,
});
this.setCurrentIndexByName(data.active || this.getCurrentName());
},
trigger(eventName, child) {
const { currentIndex } = this.data;
const data = this.getChildData(currentIndex, child);
if (!isDef(data)) {
return;
}
this.$emit(eventName, data);
},
onTap(event) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (child.data.disabled) {
this.trigger('disabled', child);
return;
}
this.onBeforeChange(index).then(() => {
this.setCurrentIndex(index);
nextTick(() => {
this.trigger('click');
});
});
},
// correct the index of active tab
setCurrentIndexByName(name) {
const { children = [] } = this;
const matched = children.filter((child) => child.getComputedName() === name);
if (matched.length) {
this.setCurrentIndex(matched[0].index);
}
},
setCurrentIndex(currentIndex) {
const { data, children = [] } = this;
if (!isDef(currentIndex) ||
currentIndex >= children.length ||
currentIndex < 0) {
return;
}
groupSetData(this, () => {
children.forEach((item, index) => {
const active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, this);
}
});
});
if (currentIndex === data.currentIndex) {
if (!data.inited) {
this.resize();
}
return;
}
const shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex });
requestAnimationFrame(() => {
this.resize();
this.scrollIntoView();
});
nextTick(() => {
this.trigger('input');
if (shouldEmitChange) {
this.trigger('change');
}
});
},
getCurrentName() {
const activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
}
},
resize() {
if (this.data.type !== 'line') {
return;
}
const { currentIndex, ellipsis, skipTransition } = this.data;
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__line'),
]).then(([rects = [], lineRect]) => {
const rect = rects[currentIndex];
if (rect == null) {
return;
}
let lineOffsetLeft = rects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
lineOffsetLeft +=
(rect.width - lineRect.width) / 2 + (ellipsis ? 0 : 8);
this.setData({ lineOffsetLeft, inited: true });
this.swiping = true;
if (skipTransition) {
// waiting transition end
setTimeout(() => {
this.setData({ skipTransition: false });
}, this.data.duration);
}
});
},
// scroll active tab into view
scrollIntoView() {
const { currentIndex, scrollable, scrollWithAnimation } = this.data;
if (!scrollable) {
return;
}
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__nav'),
]).then(([tabRects, navRect]) => {
const tabRect = tabRects[currentIndex];
const offsetLeft = tabRects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
});
if (!scrollWithAnimation) {
nextTick(() => {
this.setData({ scrollWithAnimation: true });
});
}
});
},
onTouchScroll(event) {
this.$emit('scroll', event.detail);
},
onTouchStart(event) {
if (!this.data.swipeable)
return;
this.swiping = true;
this.touchStart(event);
},
onTouchMove(event) {
if (!this.data.swipeable || !this.swiping)
return;
this.touchMove(event);
},
// watch swipe touch end
onTouchEnd() {
if (!this.data.swipeable || !this.swiping)
return;
const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
const index = this.getAvaiableTab(deltaX);
if (index !== -1) {
this.onBeforeChange(index).then(() => this.setCurrentIndex(index));
}
}
this.swiping = false;
},
getAvaiableTab(direction) {
const { tabs, currentIndex } = this.data;
const step = direction > 0 ? -1 : 1;
for (let i = step; currentIndex + i < tabs.length && currentIndex + i >= 0; i += step) {
const index = currentIndex + i;
if (index >= 0 &&
index < tabs.length &&
tabs[index] &&
!tabs[index].disabled) {
return index;
}
}
return -1;
},
onBeforeChange(index) {
const { useBeforeChange } = this.data;
if (!useBeforeChange) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
this.$emit('before-change', Object.assign(Object.assign({}, this.getChildData(index)), { callback: (status) => (status ? resolve() : reject()) }));
});
},
getChildData(index, child) {
const currentChild = child || this.children[index];
if (!isDef(currentChild)) {
return;
}
return {
index: currentChild.index,
name: currentChild.getComputedName(),
title: currentChild.data.title,
};
},
},
});
================================================
FILE: dist/tabs/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index",
"van-sticky": "../sticky/index"
}
}
================================================
FILE: dist/tabs/index.wxml
================================================
{{ item.title }}
================================================
FILE: dist/tabs/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(data) {
var titleColor = data.active
? data.titleActiveColor
: data.titleInactiveColor;
var ellipsis = data.scrollable && data.ellipsis;
// card theme color
if (data.type === 'card') {
return style({
'border-color': data.color,
'background-color': !data.disabled && data.active ? data.color : null,
color: titleColor || (!data.disabled && !data.active ? data.color : null),
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
return style({
color: titleColor,
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
function navStyle(color, type) {
return style({
'border-color': type === 'card' && color ? color : null,
});
}
function trackStyle(data) {
if (!data.animated) {
return '';
}
return style({
left: -100 * data.currentIndex + '%',
'transition-duration': data.duration + 's',
'-webkit-transition-duration': data.duration + 's',
});
}
function lineStyle(data) {
return style({
width: utils.addUnit(data.lineWidth),
opacity: data.inited ? 1 : 0,
transform: 'translateX(' + data.lineOffsetLeft + 'px)',
'-webkit-transform': 'translateX(' + data.lineOffsetLeft + 'px)',
'background-color': data.color,
height: data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'border-radius':
data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'transition-duration': !data.skipTransition ? data.duration + 's' : null,
'-webkit-transition-duration': !data.skipTransition
? data.duration + 's'
: null,
});
}
module.exports = {
tabClass: tabClass,
tabStyle: tabStyle,
trackStyle: trackStyle,
lineStyle: lineStyle,
navStyle: navStyle,
};
================================================
FILE: dist/tabs/index.wxss
================================================
@import '../common/index.wxss';.van-tabs{-webkit-tap-highlight-color:transparent;position:relative}.van-tabs__wrap{display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{flex:0 0 22%}.van-tabs__wrap--scrollable .van-tab--complete{flex:1 0 auto!important;padding:0 12px}.van-tabs__wrap--scrollable .van-tabs__nav--complete{padding-left:8px;padding-right:8px}.van-tabs__scroll{background-color:var(--tabs-nav-background-color,#fff);overflow:auto}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{border:1px solid var(--tabs-default-color,#ee0a24);border-radius:2px;box-sizing:border-box;margin:0 var(--padding-md,16px);width:calc(100% - var(--padding-md, 16px)*2)}.van-tabs__scroll::-webkit-scrollbar{display:none}.van-tabs__nav{display:flex;position:relative;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:var(--tabs-card-height,30px)}.van-tabs__nav--card .van-tab{border-right:1px solid var(--tabs-default-color,#ee0a24);color:var(--tabs-default-color,#ee0a24);line-height:calc(var(--tabs-card-height, 30px) - 2px)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{background-color:var(--tabs-default-color,#ee0a24);color:#fff}.van-tabs__nav--card .van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{background-color:var(--tabs-bottom-bar-color,#ee0a24);border-radius:var(--tabs-bottom-bar-height,3px);bottom:0;height:var(--tabs-bottom-bar-height,3px);left:0;opacity:0;position:absolute;z-index:1}.van-tabs__track{height:100%;position:relative;width:100%}.van-tabs__track--animated{display:flex;transition-property:left}.van-tabs__content{overflow:hidden}.van-tabs--line{height:var(--tabs-line-height,44px)}.van-tabs--card{height:var(--tabs-card-height,30px)}.van-tab{box-sizing:border-box;color:var(--tab-text-color,#646566);cursor:pointer;flex:1;font-size:var(--tab-font-size,14px);line-height:var(--tabs-line-height,44px);min-width:0;padding:0 5px;position:relative;text-align:center}.van-tab--active{color:var(--tab-active-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab__title__info{position:relative!important;top:-1px!important;transform:translateX(0)!important}
================================================
FILE: dist/tag/index.d.ts
================================================
export {};
================================================
FILE: dist/tag/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
size: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String,
type: {
type: String,
value: 'default',
},
closeable: Boolean,
},
methods: {
onClose() {
this.$emit('close');
},
},
});
================================================
FILE: dist/tag/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: dist/tag/index.wxml
================================================
================================================
FILE: dist/tag/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style({
'background-color': data.plain ? '' : data.color,
color: data.textColor || data.plain ? data.textColor || data.color : '',
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/tag/index.wxss
================================================
@import '../common/index.wxss';.van-tag{align-items:center;border-radius:var(--tag-border-radius,2px);color:var(--tag-text-color,#fff);display:inline-flex;font-size:var(--tag-font-size,12px);line-height:var(--tag-line-height,16px);padding:var(--tag-padding,0 4px);position:relative}.van-tag--default{background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:var(--tag-danger-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:var(--tag-danger-color,#ee0a24)}.van-tag--primary{background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:var(--tag-plain-background-color,#fff)}.van-tag--plain:before{border:1px solid;border-radius:inherit;bottom:0;content:"";left:0;pointer-events:none;position:absolute;right:0;top:0}.van-tag--medium{padding:var(--tag-medium-padding,2px 6px)}.van-tag--large{border-radius:var(--tag-large-border-radius,4px);font-size:var(--tag-large-font-size,14px);padding:var(--tag-large-padding,4px 8px)}.van-tag--mark{border-radius:0 var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) 0}.van-tag--mark:after{content:"";display:block;width:2px}.van-tag--round{border-radius:var(--tag-round-border-radius,999px)}.van-tag__close{margin-left:2px;min-width:1em}
================================================
FILE: dist/toast/index.d.ts
================================================
export {};
================================================
FILE: dist/toast/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000,
},
type: {
type: String,
value: 'text',
},
loadingType: {
type: String,
value: 'circular',
},
position: {
type: String,
value: 'middle',
},
},
methods: {
// for prevent touchmove
noop() { },
},
});
================================================
FILE: dist/toast/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index",
"van-overlay": "../overlay/index",
"van-transition": "../transition/index"
}
}
================================================
FILE: dist/toast/index.wxml
================================================
{{ message }}
{{ message }}
================================================
FILE: dist/toast/index.wxss
================================================
@import '../common/index.wxss';.van-toast{word-wrap:break-word;align-items:center;background-color:var(--toast-background-color,rgba(0,0,0,.7));border-radius:var(--toast-border-radius,8px);box-sizing:initial;color:var(--toast-text-color,#fff);display:flex;flex-direction:column;font-size:var(--toast-font-size,14px);justify-content:center;line-height:var(--toast-line-height,20px);white-space:pre-wrap}.van-toast__container{left:50%;max-width:var(--toast-max-width,70%);position:fixed;top:50%;transform:translate(-50%,-50%);width:-webkit-fit-content;width:fit-content}.van-toast--text{min-width:var(--toast-text-min-width,96px);padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{min-height:var(--toast-default-min-height,88px);padding:var(--toast-default-padding,16px);width:var(--toast-default-width,88px)}.van-toast--icon .van-toast__icon{font-size:var(--toast-icon-size,36px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{transform:translateY(-30vh)}.van-toast--bottom{transform:translateY(30vh)}
================================================
FILE: dist/toast/toast.d.ts
================================================
///
///
type ToastMessage = string | number;
type ToastContext = WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
interface ToastOptions {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: (() => ToastContext) | ToastContext;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
onClose?: () => void;
}
declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance | undefined;
declare namespace Toast {
var loading: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var success: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var fail: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var clear: () => void;
var setDefaultOptions: (options: ToastOptions) => void;
var resetDefaultOptions: () => void;
}
export default Toast;
================================================
FILE: dist/toast/toast.js
================================================
import { isObj } from '../common/validator';
const defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 2000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast',
};
let queue = [];
let currentOptions = Object.assign({}, defaultOptions);
function parseOptions(message) {
return isObj(message) ? message : { message };
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
function Toast(toastOptions) {
const options = Object.assign(Object.assign({}, currentOptions), parseOptions(toastOptions));
const context = (typeof options.context === 'function'
? options.context()
: options.context) || getContext();
const toast = context.selectComponent(options.selector);
if (!toast) {
console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
return;
}
delete options.context;
delete options.selector;
toast.clear = () => {
toast.setData({ show: false });
if (options.onClose) {
options.onClose();
}
};
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration != null && options.duration > 0) {
toast.timer = setTimeout(() => {
toast.clear();
queue = queue.filter((item) => item !== toast);
}, options.duration);
}
return toast;
}
const createMethod = (type) => (options) => Toast(Object.assign({ type }, parseOptions(options)));
Toast.loading = createMethod('loading');
Toast.success = createMethod('success');
Toast.fail = createMethod('fail');
Toast.clear = () => {
queue.forEach((toast) => {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = (options) => {
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = () => {
currentOptions = Object.assign({}, defaultOptions);
};
export default Toast;
================================================
FILE: dist/transition/index.d.ts
================================================
export {};
================================================
FILE: dist/transition/index.js
================================================
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
],
mixins: [transition(true)],
});
================================================
FILE: dist/transition/index.json
================================================
{
"component": true
}
================================================
FILE: dist/transition/index.wxml
================================================
================================================
FILE: dist/transition/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style([
{
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: dist/transition/index.wxss
================================================
@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:transform}.van-slide-up-enter,.van-slide-up-leave-to{transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{transform:translate3d(100%,0,0)}
================================================
FILE: dist/tree-select/index.d.ts
================================================
export {};
================================================
FILE: dist/tree-select/index.js
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'main-item-class',
'content-item-class',
'main-active-class',
'content-active-class',
'main-disabled-class',
'content-disabled-class',
],
props: {
items: {
type: Array,
observer: 'updateSubItems',
},
activeId: null,
mainActiveIndex: {
type: Number,
value: 0,
observer: 'updateSubItems',
},
height: {
type: null,
value: 300,
},
max: {
type: Number,
value: Infinity,
},
selectedIcon: {
type: String,
value: 'success',
},
},
data: {
subItems: [],
},
methods: {
// 当一个子项被选择时
onSelectItem(event) {
const { item } = event.currentTarget.dataset;
const isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
const isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
const isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav(event) {
const index = event.detail;
const item = this.data.items[index];
if (!item.disabled) {
this.$emit('click-nav', { index });
}
},
// 更新子项列表
updateSubItems() {
const { items, mainActiveIndex } = this.data;
const { children = [] } = items[mainActiveIndex] || {};
this.setData({ subItems: children });
},
},
});
================================================
FILE: dist/tree-select/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
}
}
================================================
FILE: dist/tree-select/index.wxml
================================================
{{ item.text }}
================================================
FILE: dist/tree-select/index.wxs
================================================
/* eslint-disable */
var array = require('../wxs/array.wxs');
function isActive (activeList, itemId) {
if (array.isArray(activeList)) {
return activeList.indexOf(itemId) > -1;
}
return activeList === itemId;
}
module.exports.isActive = isActive;
================================================
FILE: dist/tree-select/index.wxss
================================================
@import '../common/index.wxss';.van-tree-select{display:flex;font-size:var(--tree-select-font-size,14px);position:relative;-webkit-user-select:none;user-select:none}.van-tree-select__nav{--sidebar-padding:12px 8px 12px 12px;background-color:var(--tree-select-nav-background-color,#f7f8fa);flex:1}.van-tree-select__nav__inner{height:100%;width:100%!important}.van-tree-select__content{background-color:var(--tree-select-content-background-color,#fff);flex:2}.van-tree-select__item{font-weight:700;line-height:var(--tree-select-item-height,44px);padding:0 32px 0 var(--padding-md,16px);position:relative}.van-tree-select__item--active{color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;right:var(--padding-md,16px);top:50%;transform:translateY(-50%)}
================================================
FILE: dist/uploader/index.d.ts
================================================
export {};
================================================
FILE: dist/uploader/index.js
================================================
import { VantComponent } from '../common/component';
import { isBoolean, isPromise } from '../common/validator';
import { imageProps, mediaProps, messageFileProps, videoProps } from './shared';
import { chooseFile, isImageFile, isVideoFile } from './utils';
VantComponent({
props: Object.assign(Object.assign(Object.assign(Object.assign({ disabled: Boolean, multiple: Boolean, uploadText: String, useBeforeRead: Boolean, afterRead: null, beforeRead: null, previewSize: {
type: null,
value: 80,
}, name: {
type: null,
value: '',
}, accept: {
type: String,
value: 'image',
}, fileList: {
type: Array,
value: [],
observer: 'formatFileList',
}, maxSize: {
type: Number,
value: Number.MAX_VALUE,
}, maxCount: {
type: Number,
value: 100,
}, deletable: {
type: Boolean,
value: true,
}, showUpload: {
type: Boolean,
value: true,
}, previewImage: {
type: Boolean,
value: true,
}, previewFullImage: {
type: Boolean,
value: true,
}, videoFit: {
type: String,
value: 'contain',
}, imageFit: {
type: String,
value: 'scaleToFill',
}, uploadIcon: {
type: String,
value: 'photograph',
} }, imageProps), videoProps), mediaProps), messageFileProps),
data: {
lists: [],
isInCount: true,
},
methods: {
formatFileList() {
const { fileList = [], maxCount } = this.data;
const lists = fileList.map((item) => (Object.assign(Object.assign({}, item), { isImage: isImageFile(item), isVideo: isVideoFile(item), deletable: isBoolean(item.deletable) ? item.deletable : true })));
this.setData({ lists, isInCount: lists.length < maxCount });
},
getDetail(index) {
return {
name: this.data.name,
index: index == null ? this.data.fileList.length : index,
};
},
startUpload() {
const { maxCount, multiple, lists, disabled } = this.data;
if (disabled)
return;
chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length }))
.then((res) => {
this.onBeforeRead(multiple ? res : res[0]);
})
.catch((error) => {
this.$emit('error', error);
});
},
onBeforeRead(file) {
const { beforeRead, useBeforeRead } = this.data;
let res = true;
if (typeof beforeRead === 'function') {
res = beforeRead(file, this.getDetail());
}
if (useBeforeRead) {
res = new Promise((resolve, reject) => {
this.$emit('before-read', Object.assign(Object.assign({ file }, this.getDetail()), { callback: (ok) => {
ok ? resolve() : reject();
} }));
});
}
if (!res) {
return;
}
if (isPromise(res)) {
res.then((data) => this.onAfterRead(data || file));
}
else {
this.onAfterRead(file);
}
},
onAfterRead(file) {
const { maxSize, afterRead } = this.data;
const oversize = Array.isArray(file)
? file.some((item) => item.size > maxSize)
: file.size > maxSize;
if (oversize) {
this.$emit('oversize', Object.assign({ file }, this.getDetail()));
return;
}
if (typeof afterRead === 'function') {
afterRead(file, this.getDetail());
}
this.$emit('after-read', Object.assign({ file }, this.getDetail()));
},
deleteItem(event) {
const { index } = event.currentTarget.dataset;
this.$emit('delete', Object.assign(Object.assign({}, this.getDetail(index)), { file: this.data.fileList[index] }));
},
onPreviewImage(event) {
if (!this.data.previewFullImage)
return;
const { index } = event.currentTarget.dataset;
const { lists, showmenu } = this.data;
const item = lists[index];
wx.previewImage({
urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
current: item.url,
showmenu,
fail() {
wx.showToast({ title: '预览图片失败', icon: 'none' });
},
});
},
onPreviewVideo(event) {
if (!this.data.previewFullImage)
return;
const { index } = event.currentTarget.dataset;
const { lists } = this.data;
const sources = [];
const current = lists.reduce((sum, cur, curIndex) => {
if (!isVideoFile(cur)) {
return sum;
}
sources.push(Object.assign(Object.assign({}, cur), { type: 'video' }));
if (curIndex < index) {
sum++;
}
return sum;
}, 0);
wx.previewMedia({
sources,
current,
fail() {
wx.showToast({ title: '预览视频失败', icon: 'none' });
},
});
},
onPreviewFile(event) {
if (!this.data.previewFile)
return;
const { index } = event.currentTarget.dataset;
wx.openDocument({
filePath: this.data.lists[index].url,
showMenu: true,
});
},
onClickPreview(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.lists[index];
this.$emit('click-preview', Object.assign(Object.assign({}, item), this.getDetail(index)));
},
},
});
================================================
FILE: dist/uploader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: dist/uploader/index.wxml
================================================
{{ item.name || item.url }}
{{ item.message }}
{{ uploadText }}
================================================
FILE: dist/uploader/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function sizeStyle(data) {
return "Array" === data.previewSize.constructor ? style({
width: addUnit(data.previewSize[0]),
height: addUnit(data.previewSize[1]),
}) : style({
width: addUnit(data.previewSize),
height: addUnit(data.previewSize),
});
}
module.exports = {
sizeStyle: sizeStyle,
};
================================================
FILE: dist/uploader/index.wxss
================================================
@import '../common/index.wxss';.van-uploader{display:inline-block;position:relative}.van-uploader__wrapper{display:flex;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{align-items:center;background-color:var(--uploader-upload-background-color,#f7f8fa);box-sizing:border-box;display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;margin:0 8px 8px 0;position:relative;width:var(--uploader-size,80px)}.van-uploader__upload:active{background-color:var(--uploader-upload-active-color,#f2f3f5)}.van-uploader__upload-icon{color:var(--uploader-icon-color,#dcdee0);font-size:var(--uploader-icon-size,24px)}.van-uploader__upload-text{color:var(--uploader-text-color,#969799);font-size:var(--uploader-text-font-size,12px);margin-top:var(--padding-xs,8px)}.van-uploader__upload--disabled{opacity:var(--uploader-disabled-opacity,.5)}.van-uploader__preview{cursor:pointer;margin:0 8px 8px 0;position:relative}.van-uploader__preview-image{display:block;height:var(--uploader-size,80px);overflow:hidden;width:var(--uploader-size,80px)}.van-uploader__preview-delete,.van-uploader__preview-delete:after{height:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;width:var(--uploader-delete-icon-size,14px)}.van-uploader__preview-delete:after{background-color:var(--uploader-delete-background-color,rgba(0,0,0,.7));border-radius:0 0 0 12px;content:""}.van-uploader__preview-delete-icon{color:var(--uploader-delete-color,#fff);font-size:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;transform:scale(.7) translate(10%,-10%);z-index:1}.van-uploader__file{align-items:center;background-color:var(--uploader-file-background-color,#f7f8fa);display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;width:var(--uploader-size,80px)}.van-uploader__file-icon{color:var(--uploader-file-icon-color,#646566);font-size:var(--uploader-file-icon-size,20px)}.van-uploader__file-name{box-sizing:border-box;color:var(--uploader-file-name-text-color,#646566);font-size:var(--uploader-file-name-font-size,12px);margin-top:var(--uploader-file-name-margin-top,8px);padding:var(--uploader-file-name-padding,0 4px);text-align:center;width:100%}.van-uploader__mask{align-items:center;background-color:var(--uploader-mask-background-color,rgba(50,50,51,.88));bottom:0;color:#fff;display:flex;flex-direction:column;justify-content:center;left:0;position:absolute;right:0;top:0}.van-uploader__mask-icon{font-size:var(--uploader-mask-icon-size,22px)}.van-uploader__mask-message{font-size:var(--uploader-mask-message-font-size,12px);line-height:var(--uploader-mask-message-line-height,14px);margin-top:6px;padding:0 var(--padding-base,4px)}.van-uploader__loading{color:var(--uploader-loading-icon-color,#fff)!important;height:var(--uploader-loading-icon-size,22px);width:var(--uploader-loading-icon-size,22px)}
================================================
FILE: dist/uploader/shared.d.ts
================================================
export declare const imageProps: {
sizeType: {
type: ArrayConstructor;
value: string[];
};
capture: {
type: ArrayConstructor;
value: string[];
};
showmenu: {
type: BooleanConstructor;
value: boolean;
};
};
export declare const videoProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
compressed: {
type: BooleanConstructor;
value: boolean;
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
referrerPolicy: {
type: StringConstructor;
value: string;
};
};
export declare const mediaProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
mediaType: {
type: ArrayConstructor;
value: string[];
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
};
export declare const messageFileProps: {
extension: null;
previewFile: {
type: BooleanConstructor;
value: boolean;
};
};
================================================
FILE: dist/uploader/shared.js
================================================
// props for image
export const imageProps = {
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
capture: {
type: Array,
value: ['album', 'camera'],
},
showmenu: {
type: Boolean,
value: true,
},
};
// props for video
export const videoProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
referrerPolicy: {
type: String,
value: 'no-referrer',
},
};
// props for media
export const mediaProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
mediaType: {
type: Array,
value: ['image', 'video', 'mix'],
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
};
// props for file
export const messageFileProps = {
extension: null,
previewFile: {
type: Boolean,
value: true,
},
};
================================================
FILE: dist/uploader/utils.d.ts
================================================
export interface File {
url: string;
size?: number;
name?: string;
type: string;
duration?: number;
time?: number;
isImage?: boolean;
isVideo?: boolean;
}
export declare function isImageFile(item: File): boolean;
export declare function isVideoFile(item: File): boolean;
export declare function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, mediaType, extension, }: {
accept: any;
multiple: any;
capture: any;
compressed: any;
maxDuration: any;
sizeType: any;
camera: any;
maxCount: any;
mediaType: any;
extension: any;
}): Promise;
================================================
FILE: dist/uploader/utils.js
================================================
import { pickExclude, isPC, isWxWork } from '../common/utils';
import { isImageUrl, isVideoUrl } from '../common/validator';
export function isImageFile(item) {
if (item.isImage != null) {
return item.isImage;
}
if (item.type) {
return item.type === 'image';
}
if (item.url) {
return isImageUrl(item.url);
}
return false;
}
export function isVideoFile(item) {
if (item.isVideo != null) {
return item.isVideo;
}
if (item.type) {
return item.type === 'video';
}
if (item.url) {
return isVideoUrl(item.url);
}
return false;
}
function formatImage(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { type: 'image', url: item.tempFilePath || item.path, thumb: item.tempFilePath || item.path })));
}
function formatVideo(res) {
return [
Object.assign(Object.assign({}, pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg'])), { type: 'video', url: res.tempFilePath, thumb: res.thumbTempFilePath }),
];
}
function formatMedia(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['fileType', 'thumbTempFilePath', 'tempFilePath'])), { type: item.fileType, url: item.tempFilePath, thumb: item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath })));
}
function formatFile(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { url: item.path })));
}
export function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, mediaType, extension, }) {
return new Promise((resolve, reject) => {
switch (accept) {
case 'image':
if (isPC || isWxWork) {
wx.chooseImage({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
sizeType,
success: (res) => resolve(formatImage(res)),
fail: reject,
});
}
else {
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType: ['image'],
sourceType: capture,
maxDuration,
sizeType,
camera,
success: (res) => resolve(formatImage(res)),
fail: reject,
});
}
break;
case 'media':
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType,
sourceType: capture,
maxDuration,
sizeType,
camera,
success: (res) => resolve(formatMedia(res)),
fail: reject,
});
break;
case 'video':
wx.chooseVideo({
sourceType: capture,
compressed,
maxDuration,
camera,
success: (res) => resolve(formatVideo(res)),
fail: reject,
});
break;
default:
wx.chooseMessageFile(Object.assign(Object.assign({ count: multiple ? maxCount : 1, type: accept }, (extension ? { extension } : {})), { success: (res) => resolve(formatFile(res)), fail: reject }));
break;
}
});
}
================================================
FILE: dist/wxs/add-unit.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
function addUnit(value) {
if (value == null) {
return undefined;
}
return REGEXP.test('' + value) ? value + 'px' : value;
}
module.exports = addUnit;
================================================
FILE: dist/wxs/array.wxs
================================================
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
================================================
FILE: dist/wxs/bem.wxs
================================================
/* eslint-disable */
var array = require('./array.wxs');
var object = require('./object.wxs');
var PREFIX = 'van-';
function join(name, mods) {
name = PREFIX + name;
mods = mods.map(function(mod) {
return name + '--' + mod;
});
mods.unshift(name);
return mods.join(' ');
}
function traversing(mods, conf) {
if (!conf) {
return;
}
if (typeof conf === 'string' || typeof conf === 'number') {
mods.push(conf);
} else if (array.isArray(conf)) {
conf.forEach(function(item) {
traversing(mods, item);
});
} else if (typeof conf === 'object') {
object.keys(conf).forEach(function(key) {
conf[key] && mods.push(key);
});
}
}
function bem(name, conf) {
var mods = [];
traversing(mods, conf);
return join(name, mods);
}
module.exports = bem;
================================================
FILE: dist/wxs/memoize.wxs
================================================
/**
* Simple memoize
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
*/
/* eslint-disable */
function isPrimitive(value) {
var type = typeof value;
return (
type === 'boolean' ||
type === 'number' ||
type === 'string' ||
type === 'undefined' ||
value === null
);
}
// mock simple fn.call in wxs
function call(fn, args) {
if (args.length === 2) {
return fn(args[0], args[1]);
}
if (args.length === 1) {
return fn(args[0]);
}
return fn();
}
function serializer(args) {
if (args.length === 1 && isPrimitive(args[0])) {
return args[0];
}
var obj = {};
for (var i = 0; i < args.length; i++) {
obj['key' + i] = args[i];
}
return JSON.stringify(obj);
}
function memoize(fn) {
var cache = {};
return function() {
var key = serializer(arguments);
if (cache[key] === undefined) {
cache[key] = call(fn, arguments);
}
return cache[key];
};
}
module.exports = memoize;
================================================
FILE: dist/wxs/object.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('{|}|"', 'g');
function keys(obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[0];
});
}
module.exports.keys = keys;
================================================
FILE: dist/wxs/style.wxs
================================================
/* eslint-disable */
var object = require('./object.wxs');
var array = require('./array.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
return newWord;
}
function style(styles) {
if (array.isArray(styles)) {
return styles
.filter(function (item) {
return item != null && item !== '';
})
.map(function (item) {
return style(item);
})
.join(';');
}
if ('Object' === styles.constructor) {
return object
.keys(styles)
.filter(function (key) {
return styles[key] != null && styles[key] !== '';
})
.map(function (key) {
return [kebabCase(key), [styles[key]]].join(':');
})
.join(';');
}
return styles;
}
module.exports = style;
================================================
FILE: dist/wxs/utils.wxs
================================================
/* eslint-disable */
var bem = require('./bem.wxs');
var memoize = require('./memoize.wxs');
var addUnit = require('./add-unit.wxs');
module.exports = {
bem: memoize(bem),
memoize: memoize,
addUnit: addUnit
};
================================================
FILE: docs/markdown/changelog.md
================================================
# 更新日志
### [v1.11.7](https://github.com/youzan/vant-weapp/compare/v1.11.6...v1.11.7)
`2024-10-14`
**Bug Fixes**
- notice-bar: 修复滚动速度不一致的问题 [#5910](https://github.com/youzan/vant-weapp/pull/5910)
- uploader: 修复 `referrer-policy` 属性无效的问题 [#5909](https://github.com/youzan/vant-weapp/pull/5909)
- stepper: 修复 `stepper` 组件无法输入小数的问题 [#5908](https://github.com/youzan/vant-weapp/pull/5908)
- dialog: 防止嵌套对话框意外关闭 [#5907](https://github.com/youzan/vant-weapp/pull/5907)
- steps: 解决最后一个节点描述为空时的对齐问题 [#5906](https://github.com/youzan/vant-weapp/pull/5906)
- collapse: 确保 `border` 属性正确关闭底部边框 [#5905](https://github.com/youzan/vant-weapp/pull/5905)
- image: 修复图片底部额外空白的问题 [#5904](https://github.com/youzan/vant-weapp/pull/5904)
**Feature**
- cascader: 增加 `ellipsis` 属性支持 [#5806](https://github.com/youzan/vant-weapp/pull/5806)
- uploader: 增加 `preview-file` 属性支持 [#5828](https://github.com/youzan/vant-weapp/pull/5828)
**Document**
- 添加新的文档站点 URL [#5810](https://github.com/youzan/vant-weapp/pull/5810)
- 设置旧域名的重定向 [#5811](https://github.com/youzan/vant-weapp/pull/5811)
**Build**
- 使用 GitHub 生成 changelog [#5800](https://github.com/youzan/vant-weapp/pull/5800)
- 更新 @vant/cli 到 v7 [#5801](https://github.com/youzan/vant-weapp/pull/5801)
- 将 `ws` 从 7.5.6 升级到 7.5.10 [#5823](https://github.com/youzan/vant-weapp/pull/5823)
- 将 `rollup` 从 4.18.0 升级到 4.22.4 [#5897](https://github.com/youzan/vant-weapp/pull/5897)
### [v1.11.6](https://github.com/youzan/vant-weapp/compare/v1.11.5...v1.11.6)
`2024-05-14`
**Bug Fixes**
- Cascader: 修复显示错误在 value 值清空的情况下 [#5760](https://github.com/youzan/vant-weapp/issues/5760)
- Field: 修复清除按钮显示错误在 value 默认有值的情况下 [#5792](https://github.com/youzan/vant-weapp/issues/5792)
**Document**
- Button: 补全 hover-class 属性 [ebba3b](https://github.com/youzan/vant-weapp/commit/ebba3b14a133769e7b04b7a48667cbc777c280c4)
- Stepper: 修复 onChange 事件示例代码错误 [#5778](https://github.com/youzan/vant-weapp/issues/5778)
**Feature**
- Uploader: 新增 referrer-policy 属性支持 [#5770](https://github.com/youzan/vant-weapp/issues/5770)
### [v1.11.5](https://github.com/youzan/vant-weapp/compare/v1.11.4...v1.11.5)
`2024-04-15`
**Bug Fixes**
- Transition: 修复 observeDuration 方法未实现导致的报错 [#5743](https://github.com/youzan/vant-weapp/issues/5743)
- van-stepper: 修复在设置 max 属性后 onChange 结果不受限制 [#5741](https://github.com/youzan/vant-weapp/issues/5741)
**Feature**
- input: 新增 nicknamereview 事件支持 [#5758](https://github.com/youzan/vant-weapp/issues/5758)
**Document**
- docs(quickstart): 删除不需要的引导步骤 [#5744](https://github.com/youzan/vant-weapp/pull/5744)
### [v1.11.4](https://github.com/youzan/vant-weapp/compare/v1.11.3...v1.11.4)
`2024-01-22`
**Bug Fixes**
- Transition: 修复 popup 在特定情况下无法关闭 [#5707](https://github.com/youzan/vant-weapp/issues/5707)
### [v1.11.3](https://github.com/youzan/vant-weapp/compare/v1.11.2...v1.11.3)
`2024-01-16`
**Bug Fixes**
- Cascader: 修复 title slot 不生效 [#5676](https://github.com/youzan/vant-weapp/issues/5676)
- Transition: 修复 transition 多次触发 enter 时异常 [#5699](https://github.com/youzan/vant-weapp/issues/5699)
**Feature**
- Calendar、ActionSheet、Dialog、ShareSheet: 增加 root-portal 属性支持 [#5680](https://github.com/youzan/vant-weapp/issues/5680)
- goods-action-button: 增加 custom-style 属性支持 [#5659](https://github.com/youzan/vant-weapp/issues/5659)
- Upload: 增加 mix mediaType 支持 [#5690](https://github.com/youzan/vant-weapp/issues/5690)
### [v1.11.2](https://github.com/youzan/vant-weapp/compare/v1.11.1...v1.11.2)
`2023-12-05`
**Bug Fixes**
- dialog/goods-action-button: 修复 dialog、goods-action-button 组件缺少 getRealTimePhoneNumber 事件 [#5633](https://github.com/youzan/vant-weapp/issues/5633)
- upload: 修复企业微信下图片无法上传 [#5581](https://github.com/youzan/vant-weapp/issues/5581)
- calendar/input/textarea/popup: 修复 skyline 模式下组件报错问题 [#5650](https://github.com/youzan/vant-weapp/issues/5650)
**Document**
- area: 订正 columns-num 只支持 number 类型. [#5631](https://github.com/youzan/vant-weapp/issues/5631)
### [v1.11.1](https://github.com/youzan/vant-weapp/compare/v1.11.0...v1.11.1)
`2023-10-10`
**Feature**
- icon: update @vant/icon to v3.0.1 [#5583](https://github.com/youzan/vant-weapp/issues/5583)
### [v1.11.0](https://github.com/youzan/vant-weapp/compare/v1.10.25...v1.11.0)
`2023-09-18`
**Bug Fixes**
- calendar: 修复 calendar 调用 reset 方法时丢失默认值 [#5546](https://github.com/youzan/vant-weapp/issues/5546)
- van-notice-bar: 修复 delay 属性不生效问题 [#5547](https://github.com/youzan/vant-weapp/issues/5547)
**Document**
- skeleton: 修复 custom class 文档缺失 [#5548](https://github.com/youzan/vant-weapp/issues/5548)
**Feature**
- icon: 升级 @vant/icon 到 [3.0.0](https://github.com/youzan/vant/blob/main/packages/vant-icons/CHANGELOG.md) [#5561](https://github.com/youzan/vant-weapp/issues/5561)
### [v1.10.25](https://github.com/youzan/vant-weapp/compare/v1.10.24...v1.10.25)
`2023-08-30`
**Document**
- slider: 修复 use-button-slot 文档错误 [#5534](https://github.com/youzan/vant-weapp/issues/5534)
**Feature**
- button: 增加 button-id 属性 和 agreePrivacyAuthorization 事件支持 [#5533](https://github.com/youzan/vant-weapp/issues/5533)
### [v1.10.24](https://github.com/youzan/vant-weapp/compare/v1.10.23...v1.10.24)
`2023-08-25`
**Bug Fixes**
- calendar: 增加 limit date 监听 [#5520](https://github.com/youzan/vant-weapp/issues/5520)
**Feature**
- button: 增加 agreePrivacyAuthorization open-type 支持 [#5527](https://github.com/youzan/vant-weapp/issues/5527)
### [v1.10.23](https://github.com/youzan/vant-weapp/compare/v1.10.22...v1.10.23)
`2023-07-28`
**Feature**
- dialog: 增加 confirm/cancel button slot 支持 [#5502](https://github.com/youzan/vant-weapp/issues/5502)
- Search: 增加 cursor-spacing 属性支持 [#5498](https://github.com/youzan/vant-weapp/issues/5498)
### [v1.10.22](https://github.com/youzan/vant-weapp/compare/v1.10.21...v1.10.22)
`2023-07-24`
**Bug Fixes**
- field: 修复 error message 居中错误 [#5482](https://github.com/youzan/vant-weapp/issues/5482)
- GoodsAction: 修复自定义 icon 时样式错误 [#5496](https://github.com/youzan/vant-weapp/issues/5496)
- sticky: 修复渲染位置错误再 transition 中 [#5483](https://github.com/youzan/vant-weapp/issues/5483)
### [v1.10.21](https://github.com/youzan/vant-weapp/compare/v1.10.20...v1.10.21)
`2023-07-10`
**Bug Fixes**
- uploader: 修复无法唤起选择图片框在 PC 下 [#5477](https://github.com/youzan/vant-weapp/issues/5477)
**Feature**
- button: 增加 getRealtimePhoneNumber 支持 [#5471](https://github.com/youzan/vant-weapp/issues/5471)
- calendar: 增加 default-date 为 null 支持 [#5395](https://github.com/youzan/vant-weapp/issues/5395)
- dialog: 增加确认/取消按钮外部样式类支持 [#5478](https://github.com/youzan/vant-weapp/issues/5478)
- field: 增加自定义样式类支持 [#5476](https://github.com/youzan/vant-weapp/issues/5476)
- field: 扩大 input 点击区域支持 [#5479](https://github.com/youzan/vant-weapp/issues/5479)
- Upload: 增加 videoFit 属性支持 [#5475](https://github.com/youzan/vant-weapp/issues/5475)
### [v1.10.20](https://github.com/youzan/vant-weapp/compare/v1.10.19...v1.10.20)
`2023-07-03`
**Bug Fixes**
- calendar: 修复无法选择同一天在 range 模式下 [#5451](https://github.com/youzan/vant-weapp/issues/5451)
- slider: 修复小数精度丢失问题 [#5444](https://github.com/youzan/vant-weapp/issues/5444)
**Document**
- add @inottn and @zhousg to core team [#5453](https://github.com/youzan/vant-weapp/issues/5453)
- popup: 修复文档缺失 close-icon-position 属性 [#5389](https://github.com/youzan/vant-weapp/pull/5389)
- dialog: 修复示例代码错误问题 [#5389](https://github.com/youzan/vant-weapp/pull/5389)
**Feature**
- goods-action-icon: 增加 size 属性 [#5457](https://github.com/youzan/vant-weapp/issues/5457)
- goods-action-icon: 增加 info-class 自定义样式类 [#5457](https://github.com/youzan/vant-weapp/issues/5457)
- icon: 增加 info-class 自定义样式类 [#5458](https://github.com/youzan/vant-weapp/issues/5458)
### [v1.10.19](https://github.com/youzan/vant-weapp/compare/v1.10.18...v1.10.19)
`2023-05-19`
**Bug Fixes**
- calendar: 修复日历月份标题不同步问题 [#5381](https://github.com/youzan/vant-weapp/pull/5381)
- cascader: 修复选中项目缺失和 fieldNames 不生效问题 [#5182](https://github.com/youzan/vant-weapp/pull/5185)
- cascader: 修复异步数据视图不更新问题 [#5380](https://github.com/youzan/vant-weapp/pull/5380)
- tab: 修复异步数据情况选中线向右偏移问题 [#5135](https://github.com/youzan/vant-weapp/issues/5135)
### [v1.10.18](https://github.com/youzan/vant-weapp/compare/v1.10.17...v1.10.18)
`2023-05-08`
**Bug Fixes**
- steps: 修复在竖向模式下 icon 被覆盖的问题 [#5329](https://github.com/youzan/vant-weapp/issues/5329)
- tabs: 修复 tab 较多时,slot 无法正常显示问题 [#4700](https://github.com/youzan/vant-weapp/issues/4700)
**Feature**
- field: input/change 事件增加 callback 参数 [#5345](https://github.com/youzan/vant-weapp/issues/5345)
- goods-action: goods-action-button 增加 size 属性 [#5347](https://github.com/youzan/vant-weapp/issues/5347)
### [v1.10.17](https://github.com/youzan/vant-weapp/compare/v1.10.16...v1.10.17)
`2023-05-04`
**Bug Fixes**
- icon: 修复定位样式错误在外部传入 custom-class 的情况下 [#5335](https://github.com/youzan/vant-weapp/issues/5335)
- tab: 修复 tab 被嵌套时,内部 tab 样式错误问题 [#5200](https://github.com/youzan/vant-weapp/issues/5200)
- Uploader: 替换 wx.chooseImage 为 wx.chooseMedia 解决选择图片页面刷新问题 [#5343](https://github.com/youzan/vant-weapp/issues/5343)
- van-field: 修复安卓设备下 textarea maxlength 限制不生效问题 [#5308](https://github.com/youzan/vant-weapp/issues/5308)
### [v1.10.16](https://github.com/youzan/vant-weapp/compare/v1.10.15...v1.10.16)
`2023-04-18`
**Bug Fixes**
- icon: 修复显示异常在自定义图标的模式下 [#5320](https://github.com/youzan/vant-weapp/issues/5320)
- stepper: 修复最大值在设置字符串下功能错误问题 [#5295](https://github.com/youzan/vant-weapp/issues/5295)
- tabs: 修复在部分设备下 info 样式错误问题 [#5318](https://github.com/youzan/vant-weapp/issues/5318)
### [v1.10.15](https://github.com/youzan/vant-weapp/compare/v1.10.14...v1.10.15)
`2023-04-03`
**Bug Fixes**
- calendar: 修复在 allow-same-day 和 不显示 confirm 按钮时 confirm 丢失问题 [db8981](https://github.com/youzan/vant-weapp/commit/db89819f9e3537435ac5fcc52f680affd9255c6b)
**Feature**
- van-goods-action-icon: 增加 color 属性支持 [4fd22f](https://github.com/youzan/vant-weapp/commit/4fd22f0a6b6b5ebcc37807ed3c85c3b40bd60e0c)
**hotfix**
- rate: 修复在覆盖半个星时覆盖高度不够问题 [#5294](https://github.com/youzan/vant-weapp/issues/5294)
### [v1.10.14](https://github.com/youzan/vant-weapp/compare/v1.10.13...v1.10.14)
`2023-02-27`
**Bug Fixes**
- icon: 修复在自定义 icon 时丢失 dot 组件 [#5253](https://github.com/youzan/vant-weapp/issues/5253)
**Document**
- 增加 @landluck and @wjw-gavin 到核心团队 [#5252](https://github.com/youzan/vant-weapp/issues/5252)
**Feature**
- dropdown-item: 增加 root-portal 属性支持 [#5256](https://github.com/youzan/vant-weapp/issues/5256)
- dropdown-menu: 增加 safe-area-tab-bar 属性支持 [#5257](https://github.com/youzan/vant-weapp/issues/5257)
- overlay: 增加 root-portal 属性支持 [#5255](https://github.com/youzan/vant-weapp/issues/5255)
- popup: 增加 root-portal 属性支持 [#5254](https://github.com/youzan/vant-weapp/issues/5254)
### [v1.10.13](https://github.com/youzan/vant-weapp/compare/v1.10.12...v1.10.13)
`2023-02-13`
**Bug Fixes**
- calendar: 修复 calendar 组件安全区域传参未传递给 popup 组件的问题 [db7957](https://github.com/youzan/vant-weapp/commit/db79570d98537db669730aa66d3fb3932ded4737)
- cascader: 修复 cascader 组件 onClickTab 事件没有同步 activeTab 的值导致选择异常的问题 [92ae4a](https://github.com/youzan/vant-weapp/commit/92ae4a29c0b99aa65be6a71004b795ae2650f37c)
- stepper: 修复 always-embed 申明两次警告问题 [#5231](https://github.com/youzan/vant-weapp/issues/5231)
- stepper: 修复 onblur 时在值变更的情况下 change 事件没有触发 [#5227](https://github.com/youzan/vant-weapp/issues/5227)
**Feature**
- calendar: 增加 min-range 属性支持在 multiple 模式下 [#5230](https://github.com/youzan/vant-weapp/issues/5230)
- popup: 增加 safe-area-tab-bar 属性支持 [#5194](https://github.com/youzan/vant-weapp/issues/5194)
- tabbar-item: 增加 url link-type 属性支持 [#5232](https://github.com/youzan/vant-weapp/issues/5232)
- uploader: 增加 showmenu 属性支持 [#5229](https://github.com/youzan/vant-weapp/issues/5229)
### [v1.10.12](https://github.com/youzan/vant-weapp/compare/v1.10.11...v1.10.12)
`2023-01-16`
**Bug Fixes**
- calendar: 修复在 allow-same-day 情况下初始不能选择同一天 [#5193](https://github.com/youzan/vant-weapp/issues/5193)
- stepper: 修复在 async change 情况下外部无法更新 input 值 [#5191](https://github.com/youzan/vant-weapp/issues/5191)
**Document**
- docs(action-sheet): 修复 close-on-click-overlay 初始值书写错误 [b2fabe](https://github.com/youzan/vant-weapp/commit/b2fabe6b2b72ce1734b9123b00e78a854111d240)
**Feature**
- dropdown-menu: 增加 use-before-toggle 属性支持 [#5190](https://github.com/youzan/vant-weapp/issues/5190)
- field: 增加 extra-event-params 属性支持 [#5184](https://github.com/youzan/vant-weapp/issues/5184)
### [v1.10.11](https://github.com/youzan/vant-weapp/compare/v1.10.10...v1.10.11)
`2023-01-03`
**Bug Fixes**
- stepper: 修复显示错误的值在 blur 的情况下 [#5158](https://github.com/youzan/vant-weapp/issues/5158)
- steps: 修复额外的间距在垂直方向的情况下 [#5166](https://github.com/youzan/vant-weapp/issues/5166)
- transition: 修复 enter 时间触发多次的问题 [#5157](https://github.com/youzan/vant-weapp/issues/5157)
**Feature**
- image: 增加 webp 属性支持 [#5163](https://github.com/youzan/vant-weapp/issues/5163)
- uploader: 增加 extension 属性支持 [a80767](https://github.com/youzan/vant-weapp/commit/a80767e9c1699a9b15fb9d4bb1b552ef3fc5c8dc)
### [v1.10.10](https://github.com/youzan/vant-weapp/compare/v1.10.9...v1.10.10)
`2022-12-16`
**Bug Fixes**
- dialog: 修复在没有底部按钮时存在额外的白线 [#5141](https://github.com/youzan/vant-weapp/issues/5141)
- dropdown: 修复文案超出限制后箭头样式问题 [#5145](https://github.com/youzan/vant-weapp/issues/5145)
- button: 修复 demo 示例缺失 button 组件引入 [8ec17c](https://github.com/youzan/vant-weapp/commit/8ec17cc87da28b9f3caa5293c3710ee927eaa210)
- search: 优化取消按钮的点击区域 [#5148](https://github.com/youzan/vant-weapp/issues/5148)
- uploader: 修复无法预览视频问题 [#5142](https://github.com/youzan/vant-weapp/issues/5142)
**Document**
- cascader: 增加 cascader 文档链接 [4bb9e6](https://github.com/youzan/vant-weapp/commit/4bb9e625381dee97fbe2e6d3c1602365ab2c41c5)
- uploader: 优化 thumb 字段文案描述 [af7493](https://github.com/youzan/vant-weapp/commit/af74936bdc9a665dfdd024a2e85be66fabf3133d)
**Feature**
- tab: 新增 before-change 属性支持 [#5139](https://github.com/youzan/vant-weapp/issues/5139)
### [v1.10.9](https://github.com/youzan/vant-weapp/compare/v1.10.8...v1.10.9)
`2022-12-12`
**Bug Fixes**
- slider: 修复文档示例值错误 [#5128](https://github.com/youzan/vant-weapp/issues/5128)
- tab: 修复在开启微信工具热更新时出现堆栈溢出问题 [#5125](https://github.com/youzan/vant-weapp/issues/5125)
- transition: 修复页面切后台后无法触发 transition 相关组件更新 [#5131](https://github.com/youzan/vant-weapp/issues/5131)
**Feature**
- cascader: 新增 cascader 组件 [#4992](https://github.com/youzan/vant-weapp/issues/4992)
### [v1.10.8](https://github.com/youzan/vant-weapp/compare/v1.10.7...v1.10.8)
`2022-11-29`
**Bug Fixes**
- slider: 修复快速滑动时 value 可能错误问题 [#5112](https://github.com/youzan/vant-weapp/issues/5112)
- tabs: 修复初始化加载时选中状态动画问题 [#5115](https://github.com/youzan/vant-weapp/issues/5115)
**Document**
- Calendar: 修复示例代码错误问题 [c55c78](https://github.com/youzan/vant-weapp/commit/c55c785a9ed67e0801c693d61b1e7e691bd19cf1)
- fix(stepper): 修复 stepper blur 事件失焦时会触发 change 事件 [8b441d](https://github.com/youzan/vant-weapp/commit/8b441de1a6a0d439913d6a582d954331ff17e1fa)
**Feature**
- dialog: 增加 custom-class 属性支持 [#5102](https://github.com/youzan/vant-weapp/issues/5102)
- uploader: 增加 media-type 属性支持 [#5113](https://github.com/youzan/vant-weapp/issues/5113)
### [v1.10.7](https://github.com/youzan/vant-weapp/compare/v1.10.6...v1.10.7)
`2022-11-18`
**Bug Fixes**
- search: 增加 value 默认 props 定义 [697746](https://github.com/youzan/vant-weapp/commit/697746fb470e9e16476f3fe95c15e4448ca9d686)
**Document**
- collapse: 增加 right-icon 额外使用说明 [d39b35](https://github.com/youzan/vant-weapp/commit/d39b35fc3a1d4b913d7b94bb45b3e861e3cee79e)
**Feature**
- action-sheet: 增加自定义样式能力支持 [#5097](https://github.com/youzan/vant-weapp/issues/5097)
- dropdown-menu: 增加多个自定义样式能力支持 [#5099](https://github.com/youzan/vant-weapp/issues/5099)
### [v1.10.6](https://github.com/youzan/vant-weapp/compare/v1.10.5...v1.10.6)
`2022-11-06`
**Bug Fixes**
- van-tabs: 修复插件内使用 van-tabs 切换 tab 报错的问题 [#5073](https://github.com/youzan/vant-weapp/issues/5073)
- button: 修复 button 在 disabeld 或 loading 时能触发 active 状态问题 [#5084](https://github.com/youzan/vant-weapp/issues/5084)
- mixin: 修复 page-scroll mixin 函数监听没有收回问题 [#5086](https://github.com/youzan/vant-weapp/issues/5086)
- overlay: 修复 custom-class 不生效问题 [#5083](https://github.com/youzan/vant-weapp/issues/5083)
- slider: 修复 slider 在 value 小于 step 无法滑动问题 [#5079](https://github.com/youzan/vant-weapp/issues/5079)
**Feature**
- Dialog: option context 支持传入函数 [#5043](https://github.com/youzan/vant-weapp/issues/5043)
### [v1.10.5](https://github.com/youzan/vant-weapp/compare/v1.10.4...v1.10.5)
`2022-09-07`
**Feature**
- Dialog: messageAlign 属性支持传 justify [#5034](https://github.com/youzan/vant-weapp/issues/5034)
- Notify: 支持 setDefaultOptions 和 resetDefaultOptions 方法 [#5028](https://github.com/youzan/vant-weapp/issues/5028)
- toast: context 选项支持传入函数 [#5022](https://github.com/youzan/vant-weapp/issues/5022)
**Bug Fixes**
- Calendar: 修复 getDay 和 getUTCDay 有时间差,导致星期错位的问题 [#4883](https://github.com/youzan/vant-weapp/issues/4883)
### [v1.10.4](https://github.com/youzan/vant-weapp/compare/v1.10.3...v1.10.4)
`2022-07-23`
**Feature**
- Button: 新增 chooseavatar 事件 [#4976](https://github.com/youzan/vant-weapp/issues/4976)
**Bug Fixes**
- NavBar: 修复因 `box-sizing: border-box` 导致导航栏高度不正确问题 [#4969](https://github.com/youzan/vant-weapp/issues/4969)
### [v1.10.3](https://github.com/youzan/vant-weapp/compare/v1.10.2...v1.10.3)
`2022-05-02`
**Feature**
- Area: 新增 show-toolbar 属性 [#4752](https://github.com/youzan/vant-weapp/issues/4752)
- CollapseItem: 新增 size 属性 [#4829](https://github.com/youzan/vant-weapp/issues/4829)
- uploader: preview-size 属性类型支持 Array 自定义宽高 [#4798](https://github.com/youzan/vant-weapp/issues/4798)
**Bug Fixes**
- Calendar: 修复设置 maxDate 和 minDate 后,周几显示不正确的问题 [#4742](https://github.com/youzan/vant-weapp/issues/4742)
- NoticeBar: 修复无法从初始最左侧位置开始滚动的问题 [#4746](https://github.com/youzan/vant-weapp/issues/4746)
### [v1.10.2](https://github.com/youzan/vant-weapp/compare/v1.10.1...v1.10.2)
`2022-01-11`
**Bug Fixes**
- build: 修复编译时 dts 文件丢失 [#4741](https://github.com/youzan/vant-weapp/issues/4741)
- Calendar: 修复 row-height 样式问题 [#4733](https://github.com/youzan/vant-weapp/issues/4733)
- ShareSheet: 修复 点击文字 时 未触发小程序开放能力 [#4739](https://github.com/youzan/vant-weapp/pull/4739)
### [v1.10.1](https://github.com/youzan/vant-weapp/compare/v1.10.0...v1.10.1)
`2022-01-04`
**Bug Fixes**
- NoticeBar: 移除 默认 icon 尺寸 [#4692](https://github.com/youzan/vant-weapp/issues/4692)
- Tab: 修复 滑动失效问题 [#4715](https://github.com/youzan/vant-weapp/issues/4715)
**Document**
- quickstart: 增加 用户隐私保护 说明 [#4711](https://github.com/youzan/vant-weapp/issues/4711)
**Feature**
- GoodsAction: 增加 GoodsActionIcon 组件的 class-prefix 属性 [#4712](https://github.com/youzan/vant-weapp/issues/4712)
### [v1.10.0](https://github.com/youzan/vant-weapp/compare/v1.9.2...v1.10.0)
`2021-12-21`
**Bug Fixes**
- page-scroll: 修复当 vanPageScroller 为 undefined 时报错 [#4640](https://github.com/youzan/vant-weapp/issues/4640)
- Switch: 修复当使用 active-value 时 自定义颜色失效 [#4645](https://github.com/youzan/vant-weapp/issues/4645)
- Toast: 修复当 type 为 success/error 时 toast 样式不正确 [#4587](https://github.com/youzan/vant-weapp/issues/4587)
**Document**
- NoticeBar: 修复文档中 单位标识 错误 [#4641](https://github.com/youzan/vant-weapp/issues/4641)
**Feature**
- Stepper: 新增 always-embed 属性 [#4678](https://github.com/youzan/vant-weapp/issues/4678)
### [v1.9.2](https://github.com/youzan/vant-weapp/compare/v1.9.1...v1.9.2)
`2021-10-28`
**Bug Fixes**
- Calendar: 选择最小可选日期范围 [#4569](https://github.com/youzan/vant-weapp/issues/4569)
- Collapse: 修复多次点击失效问题 [#4567](https://github.com/youzan/vant-weapp/issues/4567)
- Tab: 修复卡片模式标签页样式问题 [#4582](https://github.com/youzan/vant-weapp/issues/4582)
- Tab: 修复多指滑动多个标签问题 [#4539](https://github.com/youzan/vant-weapp/issues/4539)
**Feature**
- DropdownMenu: 新增 --dropdown-menu-box-shadow CssVariable [#4565](https://github.com/youzan/vant-weapp/issues/4565)
- DropdownMenu: 新增 custom-class [#4583](https://github.com/youzan/vant-weapp/issues/4583)
- Field: 新增 always-embed 属性 [#4571](https://github.com/youzan/vant-weapp/issues/4571)
- Toast: 支持 html type [#4581](https://github.com/youzan/vant-weapp/issues/4581)
### [v1.9.1](https://github.com/youzan/vant-weapp/compare/v1.9.0...v1.9.1)
`2021-09-29`
**Bug Fixes**
- CheckBox: 移除无用方法 [#4527](https://github.com/youzan/vant-weapp/issues/4527)
- Slider: 修复 vertical 属性导致点击无效问题 [#4532](https://github.com/youzan/vant-weapp/issues/4532)
**Document**
- Calendar: Day 数据结构增加 className 属性说明 [#4524](https://github.com/youzan/vant-weapp/issues/4524)
**Feature**
- Calendar: 增加 readonly 属性 [#4529](https://github.com/youzan/vant-weapp/issues/4529)
### [v1.9.0](https://github.com/youzan/vant-weapp/compare/v1.8.7...v1.9.0)
`2021-09-27`
**Bug Fixes**
- Slider: 移除 theme mixin [#4520](https://github.com/youzan/vant-weapp/issues/4520)
- Tab: 修复初始位置不正确问题 [#4521](https://github.com/youzan/vant-weapp/issues/4521)
**Document**
- ActionSheet: 添加 show 属性说明 [#4518](https://github.com/youzan/vant-weapp/issues/4518)
**Feature**
- Slider: 添加 vertical 属性 [#4486](https://github.com/youzan/vant-weapp/issues/4486)
**Performance**
- 移除 CSS variables 兼容代码 [#4487](https://github.com/youzan/vant-weapp/issues/4487)
### [v1.8.7](https://github.com/youzan/vant-weapp/compare/v1.8.6...v1.8.7)
`2021-09-22`
**Features**
- Icons: 新增 guide-o 图标 [#4507](https://github.com/youzan/vant-weapp/issues/4507)
### [1.8.6](https://github.com/youzan/vant-weapp/compare/v1.8.5...v1.8.6)
`2021-09-20`
**Features**
- Calendar: 新增 confirmDisabledText 默认文案 [#4490](https://github.com/youzan/vant-weapp/issues/4490)) ([8629da1](https://github.com/youzan/vant-weapp/commit/8629da1b75bb50e2f0a99905de90fd85015fb785)
**Bug Fixes**
- 移除 optionalTypes [#4501](https://github.com/youzan/vant-weapp/issues/4501)) ([3afe10c](https://github.com/youzan/vant-weapp/commit/3afe10c0f929e5c6b0f32ca34de9dc8d05c8c016)
- Docs: 修复文档错误 [#4489](https://github.com/youzan/vant-weapp/issues/4489)
### [1.8.5](https://github.com/youzan/vant-weapp/compare/v1.8.4...v1.8.5)
`2021-09-15`
**Bug Fixes**
- Calendar: 修复超出选择范围 toast 提示一直存在问题 [#4474](https://github.com/youzan/vant-weapp/issues/4474)
- page-scroll: 修复 isDef 取反问题 [#4488](https://github.com/youzan/vant-weapp/issues/4488)
### [1.8.4](https://github.com/youzan/vant-weapp/compare/v1.8.3...v1.8.4)
`2021-09-07`
**Bug Fixes**
- page-scroll: 修复 getCurrentPage 为空时报错 [#4458](https://github.com/youzan/vant-weapp/issues/4458)
**Features**
- Field: 新增 clear-trigger 属性 [#4461](https://github.com/youzan/vant-weapp/issues/4461)
- Search: 新增 clear-icon 属性 [#4463](https://github.com/youzan/vant-weapp/issues/4463)
- Search: 新增 clear-trigger 属性 [9e17b13](https://github.com/youzan/vant-weapp/commit/9e17b13164e57ff09140d755870853f702a89a39)
- Slider: 新增 range 属性 [#4442](https://github.com/youzan/vant-weapp/issues/4442)
### [v1.8.3](https://github.com/youzan/vant-weapp/compare/v1.8.2...v1.8.3)
`2021-08-30`
**Bug Fixes**
- Calendar: 修复 default-date 属性失效问题 [#4430](https://github.com/youzan/vant-weapp/issues/4430)
- ShareSheet: 调整 overlayStyle 属性类型为 string [8c408e2](https://github.com/youzan/vant-weapp/commit/8c408e23030e65a0baf62f0b21fb8ed3f2c9df67)
- Stepper: 调整 minus/plus slots 位置 [#4427](https://github.com/youzan/vant-weapp/issues/4427)
- Sticky: 修复 root 为 null 时,读取 root.top 报错问题 [#4433](https://github.com/youzan/vant-weapp/issues/4433)
- Calendar: 调整 minDate 和 maxDate 传值类型为 Number [37d8e69](https://github.com/youzan/vant-weapp/commit/37d8e697c9e3d985b926f68553b8afbb5c0a0569)
**Features**
- Popup: 新增 lock-scroll 属性 [#4384](https://github.com/youzan/vant-weapp/issues/4384)
**Performance Improvements**
- Radio: label 的 margin-left 改为 padding-left,增大可点击区域,增强用户体验 [#4165](https://github.com/youzan/vant-weapp/issues/4165)
### [v1.8.2](https://github.com/youzan/vant-weapp/compare/v1.8.1...v1.8.2)
`2021-08-18`
**Bug Fixes**
- Calendar: 修复 template 引用路径不是相对路径的问题 [7f7cf6](https://github.com/youzan/vant-weapp/commit/7f7cf62ee0f675ad6b86d41f70b23336e7ddc7a1)
- Field: 修复 template 引用路径不是相对路径的问题 [6dd42a](https://github.com/youzan/vant-weapp/commit/6dd42a0473578e26e5f5f96158959e56689f68b6)
### [v1.8.1](https://github.com/youzan/vant-weapp/compare/v1.8.0...v1.8.1)
`2021-08-18`
**Feature**
- Calendar: 新增 click-subtitle 事件 [#4385](https://github.com/youzan/vant-weapp/issues/4385)
- Circle: 使用 setTimeout 代替 setInterval [#4401](https://github.com/youzan/vant-weapp/issues/4401)
**Bug Fixes**
- Picker: 修复 template 引用路径不是相对路径的问题 [#4408](https://github.com/youzan/vant-weapp/issues/4408)
### [v1.8.0](https://github.com/youzan/vant-weapp/compare/v1.7.2...v1.8.0)
`2021-08-11`
**Feature**
- Overlay: 新增 lock-scroll 属性 [#4383](https://github.com/youzan/vant-weapp/issues/4383)
- search: 新增 click-input 事件 [#4357](https://github.com/youzan/vant-weapp/issues/4357)
**Performance**
- 移除了 iOS8 相关的 polyfill,减少包体积 [#4395](https://github.com/youzan/vant-weapp/issues/4395)
### [v1.7.2](https://github.com/youzan/vant-weapp/compare/v1.7.1...v1.7.2)
`2021-07-19`
**Bug Fixes**
- Calendar: 初始日期设置为当前日期 [#4339](https://github.com/youzan/vant-weapp/issues/4339)
**Features**
- Cell: CellGroup 新增 inset 属性 [#4341](https://github.com/youzan/vant-weapp/issues/4341)
- Search: 新增 click-input 事件 [#4337](https://github.com/youzan/vant-weapp/issues/4337)
### [1.7.1](https://github.com/youzan/vant-weapp/tree/v1.7.1)
`2021-07-06`
**Bug Fixes**
- Col: 修复样式问题 [#4322](https://github.com/youzan/vant-weapp/issues/4322)
- Grid: 增加 icon-prefix 属性默认值 [#4318](https://github.com/youzan/vant-weapp/issues/4318)
- IndexBar: 修复当索引列表为空时报错 [#4310](https://github.com/youzan/vant-weapp/issues/4310)
### [1.7.0](https://github.com/youzan/vant-weapp/tree/v1.7.0)
`2021-07-04`
**Bug Fixes**
- Button: 修复 type 为 getUserInfo & wx.getUserProfile 可用时 lang 参数失效 [#4250](https://github.com/youzan/vant-weapp/issues/4250)
- ShareSheet: 新增内置 icon `weapp-qrcode` `wechat-moments` [#4256](https://github.com/youzan/vant-weapp/issues/4256)
**Features**
- Checkbox: 增加 direction 属性,设置排列方向 [#4265](https://github.com/youzan/vant-weapp/issues/4265)
- ConfigProvider: 增加全局配置组件 [#4279](https://github.com/youzan/vant-weapp/issues/4279)
- Grid: 增加 reverse 属性,支持文本&图片位置互换 [#4280](https://github.com/youzan/vant-weapp/issues/4280)
- GridItem: 增加 icon-prefix 属性,支持第三方字体 [#4276](https://github.com/youzan/vant-weapp/issues/4276)
- Rate: 增加更多 css 变量 [#4297](https://github.com/youzan/vant-weapp/issues/4297)
- Slider: 增加更多 css 变量 [#4305](https://github.com/youzan/vant-weapp/issues/4305)
**Improvements**
- wxs style 方法支持驼峰变量命名,以便能更好的在 wxml 中使用 [#4281](https://github.com/youzan/vant-weapp/issues/4281)
### [1.6.9](https://github.com/youzan/vant-weapp/tree/v1.6.9)
`2021-06-06`
**Bug Fixes**
- DatetimePicker: 修复 动态设置 min-hour min-date 显示不正确 [#4245](https://github.com/youzan/vant-weapp/issues/4245)
- Tabs: 修复 tab 数量较多时滚动距离不正确 [#4202](https://github.com/youzan/vant-weapp/issues/4202)
- Uploader: 修复 demo 中 beforeRead 报错 [#4235](https://github.com/youzan/vant-weapp/issues/4235)
### [1.6.9-beta.2](https://github.com/youzan/vant-weapp/tree/v1.6.9-beta.2)
`2021-05-22`
**Bug Fixes**
- Button: 修复 open-type 不生效 [#4222](https://github.com/youzan/vant-weapp/issues/4222)
- Calendar: 修复 allow-same-day 开启时 custom-color 属性无效 [#4200](https://github.com/youzan/vant-weapp/issues/4200)
- Circle: 修复 value 是小数时抖动的情况 [#4152](https://github.com/youzan/vant-weapp/issues/4152)
- NoticeBar: 调整滚动行为 [#4201](https://github.com/youzan/vant-weapp/issues/4201)
- NoticeBar: 修复不正确的滚动速度 [cde3876](https://github.com/youzan/vant-weapp/commit/cde3876fb0742cacf3e481a8eb2b487dabc8709e)
- Radio: 支持动态设置 disabled [#4191](https://github.com/youzan/vant-weapp/issues/4191)
- Rate: 支持滑动选择半星 [#4195](https://github.com/youzan/vant-weapp/issues/4195)
**Features**
- Calendar: 增加 first-day-of-week 属性,设置周起始日 [#4211](https://github.com/youzan/vant-weapp/issues/4211)
- Calendar: 增加 show-range-prompt 属性和 over-range 事件,设置是否展示提示文案 [#4212](https://github.com/youzan/vant-weapp/issues/4212)
- Icons: 图标库迁移至 iconfont.cn [#4219](https://github.com/youzan/vant-weapp/issues/4219)
- OpenType: 支持 getUserProfile [#4203](https://github.com/youzan/vant-weapp/issues/4203)
- Panel: 移除 useFooterSlot [#4205](https://github.com/youzan/vant-weapp/issues/4205)
### [1.6.8](https://github.com/youzan/vant-weapp/tree/v1.6.8)
`2021-02-26`
**Features**
- NoticeBar: 新增默认插槽 ([#4048](https://github.com/youzan/vant-weapp/pull/4048))
- Stepper: 新增 theme 属性,支持圆形风格 ([#4049](https://github.com/youzan/vant-weapp/pull/4049))
- Stepper: 新增 plus & minus 插槽 ([#4049](https://github.com/youzan/vant-weapp/pull/4049))
**Bug Fixes**
- Checkbox: 修复 label-position 属性无效 ([#4036](https://github.com/youzan/vant-weapp/pull/4036))
- Dialog: 修复 beforeClose 方法类型定义 ([#4019](https://github.com/youzan/vant-weapp/pull/4019))
**Improvements**
- Circle: 当内置 canvas 不支持同层渲染时降级至默认 type ([#4050](https://github.com/youzan/vant-weapp/pull/4050))
### [1.6.7](https://github.com/youzan/vant-weapp/tree/v1.6.7)
`2021-01-27`
**Features**
- Radio: 新增 `direction` 属性 ([#4007](https://github.com/youzan/vant-weapp/issues/4007))
**Bug Fixes**
- Icons: 修复部分地区图标不显示 ([#4012](https://github.com/youzan/vant-weapp/issues/4012))
- Transition: 修复默认设置 `show` 属性为 `true` 时不生效 ([#4005](https://github.com/youzan/vant-weapp/issues/4005))
### [1.6.6](https://github.com/youzan/vant-weapp/tree/v1.6.6)
`2021-01-21`
**Features**
- Uploader: 支持文件预览 ([#3975](https://github.com/youzan/vant-weapp/pull/3975))
**Bug Fixes**
- Picker: 修复标题栏无法显示 ([#3973](https://github.com/youzan/vant-weapp/pull/3973))
**Improvements**
- Calendar: 优化模板代码 ([#3972](https://github.com/youzan/vant-weapp/pull/3972))
### [1.6.5](https://github.com/youzan/vant-weapp/tree/v1.6.5)
`2021-01-19`
**Features**
- Field: 新增 input 插槽 ([#3932](https://github.com/youzan/vant-weapp/pull/3932))
- Field: 新增 click-input 事件 ([#3932](https://github.com/youzan/vant-weapp/pull/3932))
- Icon: 新增 delete-o、sort、font、font-o、revoke 图标 ([#3881](https://github.com/youzan/vant-weapp/pull/3881))
**Bug Fixes**
- Button: 修复 custom-style 属性不生效 ([#3903](https://github.com/youzan/vant-weapp/pull/3903))
- Dialog: 修复 close-on-click-overlay 属性不生效 ([#3913](https://github.com/youzan/vant-weapp/pull/3913))
**Improvements**
- Cell: 优化性能 ([#3888](https://github.com/youzan/vant-weapp/issues/3888))
- Col: 优化性能 ([#3886](https://github.com/youzan/vant-weapp/issues/3886))
- Divider: 优化性能 ([#3887](https://github.com/youzan/vant-weapp/issues/3887))
- Empty: 优化性能 ([#3933](https://github.com/youzan/vant-weapp/issues/3933))
- Loading: 优化性能 ([#3892](https://github.com/youzan/vant-weapp/issues/3892))
- Notice-bar: 优化性能 ([#3891](https://github.com/youzan/vant-weapp/issues/3891))
- Notify: 优化性能 ([#3893](https://github.com/youzan/vant-weapp/issues/3893))
- Picker: 优化性能 ([#3949](https://github.com/youzan/vant-weapp/issues/3949))
- Stepper: 优化性能 ([#3890](https://github.com/youzan/vant-weapp/issues/3890))
- Sticky: 优化性能 ([#3879](https://github.com/youzan/vant-weapp/issues/3879))
- SwipeCell: 优化性能 ([#3928](https://github.com/youzan/vant-weapp/issues/3928))
- Switch: 优化性能 ([#3889](https://github.com/youzan/vant-weapp/issues/3889))
- Tag: 优化性能 ([#3894](https://github.com/youzan/vant-weapp/issues/3894))
- Transition: 优化性能 ([#3895](https://github.com/youzan/vant-weapp/issues/3895))
- Uploader: 优化性能 ([#3897](https://github.com/youzan/vant-weapp/issues/3897))
### [1.6.4](https://github.com/youzan/vant-weapp/tree/v1.6.4)
`2020-12-18`
**Improvements**
- Tab: 优化粘性布局时的渲染性能 ([#3875](https://github.com/youzan/vant-weapp/pull/3875))
- Grid: 使用 wxs 优化性能 ([#3839](https://github.com/youzan/vant-weapp/pull/3868))
- Image: 使用 wxs 优化性能 ([#3839](https://github.com/youzan/vant-weapp/pull/3868))
- Button: 使用 wxs 优化性能 ([#3839](https://github.com/youzan/vant-weapp/pull/3839))
- Icon: 减少代码体积 ([#3839](https://github.com/youzan/vant-weapp/pull/3868))
- Checkbox: 减少代码体积 ([#3839](https://github.com/youzan/vant-weapp/pull/3868))
- Slider: 减少代码体积 ([#3839](https://github.com/youzan/vant-weapp/pull/3868))
**Bug Fixes**
- Calendar: 修复在 phone 设备上选择日期后显示错误 ([#3833](https://github.com/youzan/vant-weapp/pull/3833))
- GoodsAction: 修复部分设备上高度异常 ([#3865](https://github.com/youzan/vant-weapp/pull/3865))
- Slider: 修复设置 `max` `min` 时滑动不均匀 ([#3876](https://github.com/youzan/vant-weapp/pull/3876))
- Tab: 修复切换时内容区闪烁的问题 ([#3866](https://github.com/youzan/vant-weapp/pull/3866))
### [1.6.3](https://github.com/youzan/vant-weapp/tree/v1.6.3)
`2020-12-09`
**Features**
- Dialog: 新增 `beforeClose` 属性 ([#3815](https://github.com/youzan/vant-weapp/pull/3815))
- uploader: 新增若干 CSS 变量 ([#3797](https://github.com/youzan/vant-weapp/pull/3797))
- Aarea: 支持不传入 `county_list` 数据 ([#3824](https://github.com/youzan/vant-weapp/pull/3824))
- Tab: 新增 `resize` 方法 ([#3827](https://github.com/youzan/vant-weapp/pull/3827))
**Improvements**
- Collapse: 使用 animate 提升动画性能 ([#3826](https://github.com/youzan/vant-weapp/pull/3826))
- Tab: 优化样式拼装性能 ([#3827](https://github.com/youzan/vant-weapp/pull/3827))
**Bug Fixes**
- Field: 修复输入中文时显示字数暂时超出 maxlength ([#3802](https://github.com/youzan/vant-weapp/pull/3802))
- Info: 修复样式错误 ([#3823](https://github.com/youzan/vant-weapp/pull/3823))
- NavBar: 修复动态渲染时组件报错 ([#3822](https://github.com/youzan/vant-weapp/pull/3822))
- Progress: 修复 `percentage` 为 0 时样式异常 ([#3808](https://github.com/youzan/vant-weapp/pull/3808))
### [1.6.2](https://github.com/youzan/vant-weapp/tree/v1.6.2)
`2020-11-29`
**Features**
- Tabbar: 新增 `placeholder` `icon-prefix` 属性 ([#3792](https://github.com/youzan/vant-weapp/pull/3792))
**Bug Fixes**
- DatetimePicker: 修复 `type=year-month` 时选择出现报错 ([#3783](https://github.com/youzan/vant-weapp/pull/3783))
- Info: 修复部分安卓设备中文案不完全居中 ([#3778](https://github.com/youzan/vant-weapp/pull/3778))
- Tab: 修复 `ellipsis` 为 `false` 时下划线位置不正确 ([#3777](https://github.com/youzan/vant-weapp/pull/3777))
- Notify: 修复组件未全局居中 ([#3751](https://github.com/youzan/vant-weapp/pull/3751))
**Improvements**
- Icon: 使用 wxs 优化性能 ([#3791](https://github.com/youzan/vant-weapp/pull/3791))
### [1.6.1](https://github.com/youzan/vant-weapp/tree/v1.6.1)
`2020-11-12`
**Bug Fixes**
- Field: 修复未传入 `label` 属性时仍渲染 label [#3756](https://github.com/youzan/vant-weapp/pull/3756)
- Picker: 修复 confirm、cancel 事件报错 [#3755](https://github.com/youzan/vant-weapp/pull/3755)
### [1.6.0](https://github.com/youzan/vant-weapp/tree/v1.6.0)
`2020-11-11`
**Features**
- SwipeCell: 新增外部样式类 `custom-class` [#3678](https://github.com/youzan/vant-weapp/pull/3678)
- ActionSheet: 调整取消文字颜色至 @gray-7 [#3719](https://github.com/youzan/vant-weapp/pull/3719)
- ActionSheet: 调整顶部栏样式 [#3720](https://github.com/youzan/vant-weapp/pull/3720)
- ActionSheet: 调整加载图标大小至 22px [#3718](https://github.com/youzan/vant-weapp/pull/3718)
- ActionSheet: 调整描述文字样式 [#3726](https://github.com/youzan/vant-weapp/pull/3726)
- Cell: 调整图标外边距至 4px [#3721](https://github.com/youzan/vant-weapp/pull/3721)
- DropdownMenu: 增加默认阴影 [#3723](https://github.com/youzan/vant-weapp/pull/3723)
- DropdownMenu: 调整选中态默认颜色至 #ee0a24 [#3725](https://github.com/youzan/vant-weapp/pull/3725)
- Image: 调整图标大小至 36px [#3724](https://github.com/youzan/vant-weapp/pull/3724)
- Popup: 调整圆角至 16px [#3713](https://github.com/youzan/vant-weapp/pull/3713)
- Search: 调整左侧内边距至 12px [#3716](https://github.com/youzan/vant-weapp/pull/3716)
- Sidebar: 调整宽度至 85px [#3722](https://github.com/youzan/vant-weapp/pull/3722)
- TabbarItem: 调整图标大小至 22px [#3717](https://github.com/youzan/vant-weapp/pull/3717)
**Bug Fixes**
- Field: 修复使用 `label` 属性时 `label-class` 样式类不生效 [#3729](https://github.com/youzan/vant-weapp/pull/3729)
- NoticeBar: 修复内容较短时开启 `scrollable` 不生效 [#3727](https://github.com/youzan/vant-weapp/pull/3727)
- SidebarItem: 修复长数字不换行的问题 [#3714](https://github.com/youzan/vant-weapp/pull/3714)
- Tag: 默认字体加入 miui [#3715](https://github.com/youzan/vant-weapp/pull/3715)
### [1.5.2](https://github.com/youzan/vant-weapp/tree/v1.5.2)
`2020-10-15`
**Features**
- Uploader: 标准化 file-list 与事件参数 [#3673](https://github.com/youzan/vant-weapp/pull/3673)
- Uploader: 新增 thumb,支持缩略图展示 [#3673](https://github.com/youzan/vant-weapp/pull/3673)
- GoodsAction: 新增若干 CSS 变量 [#3654](https://github.com/youzan/vant-weapp/pull/3654)
- 移动 @types/wechat-miniprogram 至 dependencies [#3654](https://github.com/youzan/vant-weapp/pull/3674)
**Bug Fixes**
- Button: 修复细边框样式问题 [#3653](https://github.com/youzan/vant-weapp/pull/3653)
- Tab: 重构动画实现,不再使用 `transform` [#3668](https://github.com/youzan/vant-weapp/pull/3668)
### [1.5.1](https://github.com/youzan/vant-weapp/tree/v1.5.1)
`2020-09-29`
**Features**
- Card: 新增 `origin-price` `tag` 插槽 [#3645](https://github.com/youzan/vant-weapp/pull/3645)
- ShareSheet: 调整默认 z-index 至 100 [#3575](https://github.com/youzan/vant-weapp/pull/3575)
- ShareSheet: 新增 item 属性 openType [#3575](https://github.com/youzan/vant-weapp/pull/3575)
- Uploader: 扩大删除按钮点击区域 [#3631](https://github.com/youzan/vant-weapp/pull/3631)
**Bug Fixes**
- Uploader: 支持预览视频 [#3594](https://github.com/youzan/vant-weapp/pull/3594)
- Dialog: 调整类型定义 [#3630](https://github.com/youzan/vant-weapp/pull/3630)
- NavBar: 修复 CSS 变量 --nav-bar-icon-color 不生效 [#3643](https://github.com/youzan/vant-weapp/pull/3643)
- NavBar: 修复未设置 title 时样式异常 [#3643](https://github.com/youzan/vant-weapp/pull/3643)
- Tab: 修复 line-width 属性不支持 string [#3628](https://github.com/youzan/vant-weapp/pull/3628)
### [1.5.0](https://github.com/youzan/vant-weapp/tree/v1.5.0)
`2020-08-27`
**Features**
- ShareSheet: 新增组件 [#3559](https://github.com/youzan/vant-weapp/pull/3559)
- Icons: 升级 @vant/icons 至 v1.2.5 [#3539](https://github.com/youzan/vant-weapp/pull/3539)
- sidebar: 新增 badge 属性 [#3564](https://github.com/youzan/vant-weapp/pull/3564)
- Tabs: 调整默认 line-width 至 40px [#3518](https://github.com/youzan/vant-weapp/pull/3518)
- Tabs: 去除默认边框 [#3519](https://github.com/youzan/vant-weapp/pull/3519)
- TreeSelect: 新增 selected-icon 属性 [#3565](https://github.com/youzan/vant-weapp/pull/3565)
- TreeSelect: 支持 badge、dot 显示 [#3565](https://github.com/youzan/vant-weapp/pull/3565)
**Bug Fixes**
- collapse: 修复嵌套在 popup 等组件中时默认展开无效 [#3562](https://github.com/youzan/vant-weapp/pull/3562)
- empty: 修复 image、description 插槽不生效 [#3563](https://github.com/youzan/vant-weapp/pull/3563)
### [1.4.4](https://github.com/youzan/vant-weapp/tree/v1.4.4)
`2020-08-12`
**Bug Fixes**
- Transition: 重构组件以修复卡顿问题 [#3498](https://github.com/youzan/vant-weapp/pull/3498)
- Icon: 修复数字未对齐 [#3501](https://github.com/youzan/vant-weapp/pull/3501)
- Tab: 修复可滚动时下划线位置错误 [#3511](https://github.com/youzan/vant-weapp/pull/3511)
### [v1.4.3](https://github.com/youzan/vant-weapp/tree/v1.4.3)
`2020-08-07`
**Features**
- Dialog: 增加圆角按钮样式 [#3476](https://github.com/youzan/vant-weapp/pull/3476)
- Cell: 调整下划线位置 [#3487](https://github.com/youzan/vant-weapp/pull/3487)
- Tab: 调整默认滚动阈值至 5 个、优化样式 [#3459](https://github.com/youzan/vant-weapp/pull/3459)
### [v1.4.2](https://github.com/youzan/vant-weapp/tree/v1.4.2)
`2020-08-03`
**Features**
- Toast: 优化样式 [#3451](https://github.com/youzan/vant-weapp/pull/3451)
- Tag: 优化样式 [#3465](https://github.com/youzan/vant-weapp/pull/3465)
**Bug Fixes**
- Calendar: 修复超出 max-range 时未显示 Toast [#3466](https://github.com/youzan/vant-weapp/pull/3466)
- Tab: 修复手势滚动可切换至禁用项 [#3467](https://github.com/youzan/vant-weapp/pull/3467)
### [v1.4.1](https://github.com/youzan/vant-weapp/tree/v1.4.1)
`2020-07-28`
**Features**
- Picker: 调整默认可见的选项个数为 6 个 [#3418](https://github.com/youzan/vant-weapp/pull/3418)
- Toast: 调整圆角为 8px [#3419](https://github.com/youzan/vant-weapp/pull/3419)
**Bug Fixes**
- Slider: 修复点击会触发 drag 事件 [#3415](https://github.com/youzan/vant-weapp/pull/3415)
- Area: 修复中间列无法滚动 [#3443](https://github.com/youzan/vant-weapp/pull/3443)
### [v1.4.0](https://github.com/youzan/vant-weapp/tree/v1.4.0)
`2020-07-17`
**Features**
- Empty: 新增 Empty 组件 [\#3327](https://github.com/youzan/vant-weapp/pull/3327)
- NoticeBar: 新增 background 属性 [\#3388](https://github.com/youzan/vant-weapp/pull/3388)
- NoticeBar: 新增 close 事件 [\#3388](https://github.com/youzan/vant-weapp/pull/3388)
- GridItem: 新增 icon-color 属性 [\#3386](https://github.com/youzan/vant-weapp/pull/3386)
- NavBar: 现在 custom-style 将影响根节点[\#3371](https://github.com/youzan/vant-weapp/pull/3371)
- Cell: 新增 title-style 属性, fix Field label width [\#3370](https://github.com/youzan/vant-weapp/pull/3370)
- Uploader: 更新 failed 图标 [\#3359](https://github.com/youzan/vant-weapp/pull/3359)
- Uploader: 更新删除图标样式 [\#3385](https://github.com/youzan/vant-weapp/pull/3385)
- Uploader: 移除圆角样式 [\#3384](https://github.com/youzan/vant-weapp/pull/3384)
- Field: 更新禁用态样式 [\#3358](https://github.com/youzan/vant-weapp/pull/3358)
- Field: 更新 label 样式 [\#3357](https://github.com/youzan/vant-weapp/pull/3357)
- Picker: 调整 action button 样式 [\#3316](https://github.com/youzan/vant-weapp/pull/3316)
**Bug Fixes**
- Collapse: 使用 animation 重构动画部分逻辑以修复动画卡顿 [\#3401](https://github.com/youzan/vant-weapp/pull/3401)
- Uploader: 修复 loading 样式错误、调整 previewSize 属性默认值 [\#3317](https://github.com/youzan/vant-weapp/pull/3317)
- Area: 修复低版本基础库下 columns-num 设置为 1 或 2 时真机环境报错 [\#3318](https://github.com/youzan/vant-weapp/pull/3318)
- DatetimePicker: 修复使用 formatter 时,事件返回值可能不正确 [\#3352](https://github.com/youzan/vant-weapp/pull/3352)
- Field: 修复 textarea 模式下 label 与 value 不在同一水平线上 [\#3383](https://github.com/youzan/vant-weapp/pull/3383)
- Dialog: show dialog after class ready [\#3374](https://github.com/youzan/vant-weapp/pull/3374)
- Calendar: confirm-disabled-text 属性增加默认值 [\#3394](https://github.com/youzan/vant-weapp/pull/3394)
### [v1.3.3](https://github.com/youzan/vant-weapp/tree/v1.3.3)
`2020-06-24`
**Features**
- steps: 为每一项增加 inactiveIcon、activeIcon 属性 [\#3315](https://github.com/youzan/vant-weapp/pull/3315)
- field: 增加外部样式类 label-class [\#3311](https://github.com/youzan/vant-weapp/pull/3311)
- field: 现在总会从内部 set value 值 [\#3313](https://github.com/youzan/vant-weapp/pull/3313)
- uploader: 为每一项增加 deletable 属性 [\#3270](https://github.com/youzan/vant-weapp/pull/3270)
- uploader: 扩大删除图标的可点击区域 [\#3265](https://github.com/youzan/vant-weapp/pull/3265)
**Bug Fixes**
- tabbar: 修复 iphone-se 上高度异常 [\#3314](https://github.com/youzan/vant-weapp/pull/3314)
- grid: 修复 text 与 icon 同时设置时样式异常 [\#3310](https://github.com/youzan/vant-weapp/pull/3310)
- calendar: 修复多选模式下 default-date 属性不生效 [\#3284](https://github.com/youzan/vant-weapp/pull/3284)
- circle: 修复 type="2d" 时无法动态变更 value [\#3264](https://github.com/youzan/vant-weapp/pull/3264)
- nav-bar: 修复未设置 left-text 时左侧图标样式异常 [\#3263](https://github.com/youzan/vant-weapp/pull/3263)
### [v1.3.2](https://github.com/youzan/vant-weapp/tree/v1.3.2)
`2020-06-04`
**Features**
- button: 新增 form-type 属性 [\#3208](https://github.com/youzan/vant-weapp/pull/3208)
- grid: 新增 icon-size、badge 属性 [\#3236](https://github.com/youzan/vant-weapp/pull/3236)
- grid: 新增 direction 属性 [\#3192](https://github.com/youzan/vant-weapp/pull/3192)
**Bug Fixes**
- Grid: 修复开启 `square` 时横、纵向间距不同 [\#3231](https://github.com/youzan/vant-weapp/pull/3231)
- uploader: 修复点击删除图标时触发 click-preview 事件 [\#3230](https://github.com/youzan/vant-weapp/pull/3230)
- circle: 修复 `type="2d"` 不生效 [\#3228](https://github.com/youzan/vant-weapp/pull/3228)
- calendar: 修复在选择区间时,点击确定报错 [\#3195](https://github.com/youzan/vant-weapp/pull/3195)
- tag: 修复 css 变量名拼写错误 [\#3191](https://github.com/youzan/vant-weapp/pull/3191)
### [v1.3.1](https://github.com/youzan/vant-weapp/tree/v1.3.1)
`2020-05-24`
**Features**
- Button: 新增 class-prefix 属性 [\#3159](https://github.com/youzan/vant-weapp/pull/3159)
- Collapse: 新增 open、close 事件 [\#3176](https://github.com/youzan/vant-weapp/pull/3176)
**Bug Fixes**
- 修复控制台提示选择器错误的问题 [\#3137](https://github.com/youzan/vant-weapp/pull/3137)
- 修复 GoodsActionButton 在某些情况下报错的问题 [\#3145](https://github.com/youzan/vant-weapp/pull/3145)
### [v1.3.0](https://github.com/youzan/vant-weapp/tree/v1.3.0)
`2020-05-08`
#### 支持简易双向绑定
1.3.0 中,我们为数个表单组件支持了简易双向绑定,涉及组件有
Slider [\#3107](https://github.com/youzan/vant-weapp/pull/3107)
Search [\#3106](https://github.com/youzan/vant-weapp/pull/3106)
Rate [\#3105](https://github.com/youzan/vant-weapp/pull/3105)
**Features**
- sticky: 新增 scroll-top 属性 [\#3115](https://github.com/youzan/vant-weapp/pull/3115)
- button: 新增 dataset 属性 [\#3075](https://github.com/youzan/vant-weapp/pull/3075)
- uploader: 所有类型都会触发 click-preview 事件 [\#3071](https://github.com/youzan/vant-weapp/pull/3071)
- Uploader: 属性 accept 新增值 media [\#3047](https://github.com/youzan/vant-weapp/pull/3047)
- feat: 新增基础 font-family [\#3061](https://github.com/youzan/vant-weapp/pull/3061)
- submit-bar: 使用另一个 view 实现 safe-area-inset-bottom 以避免样式冲突 [\#3104](https://github.com/youzan/vant-weapp/pull/3104)
**Bug Fixes**
- dialog: 修复 title 多余空格的问题 [\#3069](https://github.com/youzan/vant-weapp/pull/3069)
- tab: 修复 tab 个数多时显示滚动条 [\#3072](https://github.com/youzan/vant-weapp/pull/3072)
- Sticky: 修复使用组件时页面 onPageScroll 失效 [\#3092](https://github.com/youzan/vant-weapp/pull/3092)
- button: 修复 disabled 属性对 open-type 类型的按钮无效 [\#3076](https://github.com/youzan/vant-weapp/pull/3076)
### [v1.2.2](https://github.com/youzan/vant-weapp/tree/v1.2.2)
`2020-04-21`
**Features**
- GoodsActionButton: 新增 CSS 变量 goods-action-line-height [\#3037](https://github.com/youzan/vant-weapp/pull/3037)
- Calendar: 选择区间大于 range 时自动选中最大范围 [\#3026](https://github.com/youzan/vant-weapp/pull/3026)
- Notify: 新增 top 属性 [\#3018](https://github.com/youzan/vant-weapp/pull/3018)
**Bug Fixes**
- Field: 修复未设置 autosize 时 wxs 报错 [\#3038](https://github.com/youzan/vant-weapp/pull/3038)
- Field: 避免设置 showClear 为 undefined [\#3012](https://github.com/youzan/vant-weapp/pull/3012)
### [v1.2.1](https://github.com/youzan/vant-weapp/tree/v1.2.1)
`2020-04-12`
**Features**
- Field: 支持小程序双向绑定 [\#2986](https://github.com/youzan/vant-weapp/pull/2986)
- Calendar: 多选模式下新增 unselect 事件 [\#2990](https://github.com/youzan/vant-weapp/pull/2990)
**Bug Fixes**
- IndexBar: 移除 scroll-top 属性 [\#2999](https://github.com/youzan/vant-weapp/pull/2999)
- Uploader: 修复图片后缀名为大写时未正常识别 [\#2987](https://github.com/youzan/vant-weapp/pull/2987)
- Field: 修复 autosize 属性 设置 max-height 不生效 [\#3007](https://github.com/youzan/vant-weapp/pull/3007)
### [v1.2.0](https://github.com/youzan/vant-weapp/tree/v1.2.0)
`2020-04-04`
**Features**
- TreeSelect: 更新 nav 背景色 [\#2952](https://github.com/youzan/vant-weapp/pull/2952)
- Sticky: 使用 page scroll 重构组件 [\#2950](https://github.com/youzan/vant-weapp/pull/2950)
- Field: 新增 auto-focus、disable-default-padding、cursor 属性 [\#2936](https://github.com/youzan/vant-weapp/pull/2936)
- Field: 新增 linechange、keyboardheightchange 事件 [\#2936](https://github.com/youzan/vant-weapp/pull/2936)
- Uploader: 支持显示上传状态 [\#2929](https://github.com/youzan/vant-weapp/pull/2929)
- Image: mode 属性新增 widthFix、heightFix [\#2908](https://github.com/youzan/vant-weapp/pull/2908)
- Canvas: 新增 type 属性 [\#2906](https://github.com/youzan/vant-weapp/pull/2906)
- NavBar: 新增 placeholder 属性 [\#2896](https://github.com/youzan/vant-weapp/pull/2896)
**Bug Fixes**
- Field: 修复输入过快时输入框内容不断回退 [\#2936](https://github.com/youzan/vant-weapp/pull/2936)
- Calendar: 修复 show-confirm 为 true 时组件初始化报错 [\#2951](https://github.com/youzan/vant-weapp/pull/2951)
- Tab: 修复 type 为 card 时 color 对边框无效 [\#2941](https://github.com/youzan/vant-weapp/pull/2941)
### [v1.1.0](https://github.com/youzan/vant-weapp/tree/v1.1.0)
`2020-03-21`
**Features**
- 新增 Calendar 日历组件 [\#2894](https://github.com/youzan/vant-weapp/pull/2894)
- Grid: 新增外部样式类 custom-class、content-class、icon-class、text-class [\#2882](https://github.com/youzan/vant-weapp/pull/2882)
- Steps: 新增 click 事件 [\#2874](https://github.com/youzan/vant-weapp/pull/2874)
- SideBar: 新增 title 插槽 [\#2873](https://github.com/youzan/vant-weapp/pull/2873)
- Uploader: 新增 upload-icon 属性 [\#2869](https://github.com/youzan/vant-weapp/pull/2869)
- Uploader: 新增 show-upload 属性 [\#2868](https://github.com/youzan/vant-weapp/pull/2868)
- Uploader: 更新样式、调整事件触发顺序与 vant 一致 [\#2886](https://github.com/youzan/vant-weapp/pull/2886)
- Field: 新增 show-word-limit 属性 [\#2856](https://github.com/youzan/vant-weapp/pull/2856)
- Field: autosize 属性支持传入对象,指定 maxHeight 与 minHeight [\#2856](https://github.com/youzan/vant-weapp/pull/2856)
- Field: 新增若干 CSS 变量 [\#2856](https://github.com/youzan/vant-weapp/pull/2856)
**Bug Fixes**
- Button: 移除 lang 属性默认值 [\#2883](https://github.com/youzan/vant-weapp/pull/2883)
- Button: 修复 disabled 属性对原生事件无效 [\#2878](https://github.com/youzan/vant-weapp/pull/2878)
### [v1.0.7](https://github.com/youzan/vant-weapp/tree/v1.0.7)
`2020-03-04`
**Features**
- DropdownItem: 新增 `popupStyle` 属性 [\#2804](https://github.com/youzan/vant-weapp/pull/2804)
- DropdownItem: 新增 `open` `close` `opened` `closed` 事件 [\#2804](https://github.com/youzan/vant-weapp/pull/2804)
- Card: 新增 `price` `num` 插槽 [\#2787](https://github.com/youzan/vant-weapp/pull/2787)
- Card: 新增 `origin-price-class` 外部样式类 [\#2787](https://github.com/youzan/vant-weapp/pull/2787)
**Bug Fixes**
- Tab: 修复内容项高度不同时粘性布局异常 [\#2817](https://github.com/youzan/vant-weapp/pull/2817)
- Picker: 修复未选中项样式未置灰 [\#2816](https://github.com/youzan/vant-weapp/pull/2816)
- GoodsActionButton: 修复仅使用一个 button 时样式异常 [\#2808](https://github.com/youzan/vant-weapp/pull/2808)
- Radio: `name`类型与`value`统一 [\#2801](https://github.com/youzan/vant-weapp/pull/2801)
- Uploader: 修复文档错误 [\#2777](https://github.com/youzan/vant-weapp/pull/2777)
### [v1.0.6](https://github.com/youzan/vant-weapp/tree/v1.0.6)
`2020-02-24`
**Features**
- GoodsActionButton: 新增默认 slot [\#2779](https://github.com/youzan/vant-weapp/pull/2779)
- SubmitBar: 更新圆角样式 [\#2755](https://github.com/youzan/vant-weapp/pull/2755)
- Card: 更新样式 [\#2754](https://github.com/youzan/vant-weapp/pull/2754)
- 优化 relation 部分代码 [\#2760](https://github.com/youzan/vant-weapp/pull/2760)
**Bug Fixes**
- DropdownItem: 修复点击选项时不触发`close`事件 [\#2766](https://github.com/youzan/vant-weapp/pull/2766)
- GoodsActionButton: 修复低版本基础库下的样式问题 [\#2762](https://github.com/youzan/vant-weapp/pull/2762)
- Tabs: 修复点击禁用项时事件参数错误 [\#2758](https://github.com/youzan/vant-weapp/pull/2758)
- Checkbox: 修复动态设置`disabled`属性无效 [\#2748](https://github.com/youzan/vant-weapp/pull/2748)
- Button: add loading color when plain is true [\#2746](https://github.com/youzan/vant-weapp/pull/2746)
- Radio: 修复`label-disabled`文档错误 [\#2763](https://github.com/youzan/vant-weapp/pull/2763)
### [v1.0.5](https://github.com/youzan/vant-weapp/tree/v1.0.5)
`2020-02-07`
**Features**
- ActionSheet: actions 支持更多 openType [\#2715](https://github.com/youzan/vant-weapp/pull/2715)
- Uploader: 新增开始`disabled`时的组件样式 [\#2720](https://github.com/youzan/vant-weapp/pull/2720)
- Icon: 调整示例小程序页面与 vant 对齐 [\#2728](https://github.com/youzan/vant-weapp/pull/2728)
- 示例小程序首页与 vant 对齐 [\#2729](https://github.com/youzan/vant-weapp/pull/2729)
- 完善快速上手文档,增加 npm 构建说明 [\#2726](https://github.com/youzan/vant-weapp/pull/2726)
**Bug Fixes**
- Radio: 修复`disabled`属性不生效 [\#2711](https://github.com/youzan/vant-weapp/pull/2711)
- Tab: 修复`animated`属性无法动态切换 [\#2712](https://github.com/youzan/vant-weapp/pull/2712)
- Circle: 修正文档错误,`size`属性不支持`string`类型 [\#2694](https://github.com/youzan/vant-weapp/pull/2694)
- 修正文档默认 slot 名称为 default 的错误 [\#2726](https://github.com/youzan/vant-weapp/pull/2726)
- TreeSelect: 修正文档示例代码标签闭合错误 [\#2710](https://github.com/youzan/vant-weapp/pull/2710)
### [v1.0.4](https://github.com/youzan/vant-weapp/tree/v1.0.4)
`2020-01-21`
**Features**
- Stepper: 新增 disable-long-press 属性 [\#2691](https://github.com/youzan/vant-weapp/pull/2691)
- quickstart: 快速上手新增关闭 style v2 说明 [\#2704](https://github.com/youzan/vant-weapp/pull/2704)
- Search: 新增 background、disabled、input-align 文档示例 [\#2698](https://github.com/youzan/vant-weapp/pull/2698)
- Icon: 文档新增图标文字加载失败说明 [\#2681](https://github.com/youzan/vant-weapp/pull/2681)
**Bug Fixes**
- Sticky: 修复真机上页面滚动缓慢时无法吸顶/取消吸顶 [\#2703](https://github.com/youzan/vant-weapp/pull/2703)
- DropdownItem: 修复 wx:key 警告 [\#2670](https://github.com/youzan/vant-weapp/pull/2670)
- IndexBar: 文档修复组件引入路径错误 [\#2689](https://github.com/youzan/vant-weapp/pull/2689)
- 升级依赖版本以避免安全警告 [\#2680](https://github.com/youzan/vant-weapp/pull/2680)
### [v1.0.3](https://github.com/youzan/vant-weapp/tree/v1.0.3)
`2020-01-09`
**Features**
- npm 包默认输出 es5 版本代码 [\#2639](https://github.com/youzan/vant-weapp/pull/2639)
- Steps: 新增外部样式类 desc-class [\#2630](https://github.com/youzan/vant-weapp/pull/2630)
**Bug Fixes**
- Tab: 解决动态添加选项时,顺序错乱和下划线长度不变的问题 [\#2663](https://github.com/youzan/vant-weapp/pull/2663)
- NavBar: 修复返回图标未居中的问题 [\#2633](https://github.com/youzan/vant-weapp/pull/2633)
### [v1.0.2](https://github.com/youzan/vant-weapp/tree/v1.0.2)
`2019-12-31`
**Features**
- Skeleton: 新增外部样式类` row-class``avatar-class``title-class ` [\#2612](https://github.com/youzan/vant-weapp/pull/2612)
- SwipeCell: 支持动态修改`width`属性 [\#2607](https://github.com/youzan/vant-weapp/pull/2607)
- Uploader: 新增` camera``compressed``maxDuration `属性 [\#2584](https://github.com/youzan/vant-weapp/pull/2584)
**Improvements**
- Tab: 优化弹性滚动效果 [\#2606](https://github.com/youzan/vant-weapp/pull/2606)
**Bug Fixes**
- IndexBar: 修复字母未全部定义时 click 事件报错 [\#2605](https://github.com/youzan/vant-weapp/pull/2605)
- Field: 修复点击清除图标后下一次点击无效 [\#2602](https://github.com/youzan/vant-weapp/pull/2602)
### [v1.0.1](https://github.com/youzan/vant-weapp/tree/v1.0.1)
`2019-12-23`
**Features**
- Uploader: 新增 sizeType 属性 [\#2563](https://github.com/youzan/vant-weapp/pull/2563)
- GoodsActionButton: 新增 plain 属性 [\#2559](https://github.com/youzan/vant-weapp/pull/2559)
- Uploader: 去除 use-slot 属性 [\#2551](https://github.com/youzan/vant-weapp/pull/2551)
- 新增样式覆盖说明文档 [\#2566](https://github.com/youzan/vant-weapp/pull/2566)
**Improvements**
- 使用 nextTick 优化部分异步逻辑 [\#2561](https://github.com/youzan/vant-weapp/pull/2561)
- wxs 新增 addUnit 方法以减少 setData 调用次数 [\#2550](https://github.com/youzan/vant-weapp/pull/2550)
**Bug Fixes**
- Tag: 修复未依赖 van-icon 组件 [\#2579](https://github.com/youzan/vant-weapp/pull/2579)
- Notify: 修复 safeAreaInsetTop 不生效 [\#2558](https://github.com/youzan/vant-weapp/pull/2558)
- Uploader: 修复 capture 属性不生效 [\#2551](https://github.com/youzan/vant-weapp/pull/2551)
### [v1.0.0](https://github.com/youzan/vant-weapp/tree/v1.0.0)
`2019-12-11`
#### 主要变动
- npm 包名由 vant-weapp 重命名为 @vant/weapp
- 增加十一个新组件
- 增加数十个 API
- 所有组件支持通过`CSS自定义属性`自定义样式
- 使用`env()`重构 iOS 安全区域适配
- 调整部分 API 命名,废除少量 API
#### 新组件
在 Vant Weapp 1.0 版本中,我们新增了 11 个实用的基础组件:
- Grid 宫格,用于展示内容或进行页面导航
- Image 图片,增强版的 Image 标签,支持图片懒加载与加载失败提示
- Circle 环形进度条,告知用户当前的状态和进度
- Overaly 遮罩层,用于强调特定的页面元素,并阻止用户进行其他操作
- Divider 分割线,区隔内容的分割线
- Sticky 粘性布局,与 CSS 中`position: sticky`属性实现的效果类似
- Skeleton 骨架屏,在待加载区域展示的占位区块,提供界面加载过程中的过渡效果
- IndexBar 索引栏,通讯录中的字母索引栏,用于长列表快速索引
- Uploader 文件上传,上传一个或多个文件
- CountDown 倒计时,用于显示活动倒计时、短信验证码等
- DropdownMenu 下拉菜单,用于列表的分类选择、筛选及排序

#### 样式定制
在 1.0 迭代计划确定之初,我们就不断思考这样一个问题 -- 该如何给用户提供动态切换主题样式的功能呢?
微信小程序的环境是非常特殊的。不具有动态加载代码的机制,同时微信又限制了代码的主包大小和总大小。传统的基于预设的样式定制过于臃肿,不再适合微信小程序的环境。
微信小程序自定义组件的组件模型相当于一个简化版的 [Shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=zh-CN),幸运的是,小程序也支持了 [CSS 自定义属性](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties) 的特性。最终,我们基于 CSS 自定义属性设计了样式定制的方案,开发者使用灵活、方便,组件维护也更简单。
从 1.0 版本开始,Vant Weapp 中的所有组件都支持通过 [CSS 组定义属性](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties) 进行样式定制,具体使用姿势可查看[相关文档](/vant-weapp/#/theme)

#### 不兼容更新
1.0 版本中包含少量不兼容更新,主要是命名调整和移除个别属性。对于正在使用 0.x 版本的项目,请按照下方的列表依次检查,大部分项目可以无痛升级。
##### Badge
- `BadgeGroup`重命名为`Sidebar`
- `Badge`重命名为`SlidebarItem`
- `active`属性重命名为`activeKey`
##### Notify
- `text`选项重命名为`message`
- `backgroundColor`选项重命名为`background`
##### Popup
- 去除`transitionend`事件,新增 6 个事件
##### SwitchCell
- 移除了`SwitchCell`组件,可以使用`Cell`和`Switch`组件代替
##### Transition
- 去除`transitionend`事件,新增 6 个事件
---
#### 新特性
##### ActionSheet
- 新增`click-overlay`事件
- 新增`close-on-click-action`属性
- 新增`color`属性
- 新增`description`属性
- 新增`round`属性
##### Area
- 新增`columns-placeholder`属性
- `reset`方法支持传入`code`参数
##### Button
- 新增`loading-type`属性
- `color`属性支持渐变色
- 切换`disabled`时增加过渡效果
##### Checkbox
- 新增`icon-size`属性
##### Color
- 基础红色更新为`#ee0a24`
##### DatetimePicker
- 新增`filter`属性
##### Dialog
- 优化文字换行
- 新增`title`插槽
- 新增`confirm-button-color`属性
- 新增`cancel-button-color`属性
- 新增`width`属性
- 新增`overlay-style`属性
##### Field
- 新增`clickable`属性
- 新增`arrow-direction`属性
- 新增`hold-keyboard`属性
##### GoodsActionButton
- 新增`color`属性
- 样式升级为圆角风格
##### GoodsActionIcon
- 新增`icon`插槽
- 新增`dot`属性
##### GridItem
- 新增`info`属性
- 新增`dot`属性
##### Icon
- 新增`dot`属性
- 新增`down`图标
- 新增`wap-hone`实底风格图标
- 支持`number`类型的`size`属性
##### Loading
- 支持`number`类型的`size`属性
##### NoticeBar
- 阻止关闭图标点击事件冒泡
##### Notify
- 新增`clear`方法
##### Popup
- 新增`round`属性
- 新增`closeable`属性
- 新增`close-icon`属性
- 新增`close-icon-position`属性
##### Progress
- 新增`stroke-width`属性
##### Radio
- 新增`icon-size`属性
##### Rate
- 优化手势判断
- 新增`gutter`属性
- 新增`touchable`属性
- 支持`string`类型的`size`属性
##### Search
- 新增`action-text`属性
- 新增`left-icon`插槽
- 新增`right-icon`插槽
##### SlidebarItem
- 新增`dot`属性
##### Slider
- 新增`drag-start`事件
- 新增`drag-end`事件
- 支持传入任意范围的`max`和`min`属性
- 支持`number`类型的`bar-height`属性
- 增加滑动动画
- 增大点击区域
##### SwipeCell
- 新增`name`属性
- 新增`open`事件
- 支持打开状态互斥
##### Switch
- 加载图标的颜色会跟随开关状态变化
##### Stepper
- 支持长按手势
- 新增`input-width`属性
- 新增`button-size`属性
- 新增`decimalLength`属性
- 新增 disablePlus、disableMinus 属性
##### Steps
- 新增`active-icon`属性
- 新增`inactive-icon`属性
##### Tabs
- 使用 Sticky 组件重构吸顶实现
- 新增`name`属性
- 新增`line-height`属性
- 新增`ellipsis`属性
- 新增`lazy-render`属性
- `line-width`属性支持`String`类型
- 增加云开发结合示例
##### TreeSelect
- 新增`max`属性
- 新增`content`插槽
================================================
FILE: docs/markdown/custom-style.md
================================================
# 样式覆盖
### 介绍
Vant Weapp 基于微信小程序的机制,为开发者提供了以下 3 种修改组件样式的方法
### 解除样式隔离
样式隔离的相关背景知识请查阅[微信小程序文档](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F%E9%9A%94%E7%A6%BB)
Vant Weapp 的所有组件都开启了`addGlobalClass: true`以接受外部样式的影响,可以使用如下 2 种方式覆盖组件样式
> 在页面中使用 Vant Weapp 组件时,可直接在页面的样式文件中覆盖样式
```html
主要按钮
```
```css
/* page.wxss */
.van-button--primary {
font-size: 20px;
background-color: pink;
}
```
> 在自定义组件中使用 Vant Weapp 组件时,需开启`styleIsolation: 'shared'`选项
```html
主要按钮
```
```js
Component({
options: {
styleIsolation: 'shared',
},
});
```
```css
.van-button--primary {
font-size: 20px;
background-color: pink;
}
```
### 使用外部样式类
外部样式类的相关知识背景请查阅[微信小程序文档](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E5%A4%96%E9%83%A8%E6%A0%B7%E5%BC%8F%E7%B1%BB)
Vant Weapp 开放了大量的外部样式类供开发者使用,具体的样式类名称可查阅对应组件的“外部样式类”部分。
需要注意的是普通样式类和外部样式类的优先级是未定义的,因此使用时请添加`!important`以保证外部样式类的优先级。
```html
```
```css
.cell-title {
color: pink !important;
font-size: 20px !important;
}
.cell-value {
color: green !important;
font-size: 12px !important;
}
```
### 使用 CSS 变量
Vant Weapp 为部分 CSS 属性开放了基于 CSS 属性的定制方案。
相较于 解除样式隔离 和 使用外部样式类,这种方案支持在页面或应用级别对多个组件的样式做批量修改以进行主题样式的定制。
当然,用它来修改单个组件的部分样式也是绰绰有余的。具体的使用方法请查阅[定制主题](#/theme)
================================================
FILE: docs/markdown/home.md
================================================
Vant Weapp
轻量、可靠的小程序 UI 组件库
### 介绍
Vant 是一个**轻量、可靠的移动端组件库**,于 2017 年开源。
目前 Vant 官方提供了 [Vue 2 版本](/vant/v2/)、[Vue 3 版本](/vant/)和[微信小程序版本](/vant-weapp/),并由社区团队维护 [React 版本](https://github.com/3lang3/react-vant)和[支付宝小程序版本](https://github.com/ant-move/Vant-Aliapp)。
### 预览
扫描下方小程序二维码,体验组件库示例:
> Tips: 为了便于预览组件效果,本文档的右侧内嵌了 H5 版的 Vant 页面作为参考。在实际使用中,个别组件的表现可能与小程序上的表现有差异,请以实际效果为准。
### 快速上手
请参考 [快速上手](#/quickstart)。
### 链接
- [意见反馈](https://github.com/youzan/vant-weapp/issues)
- [设计资源](/vant/#/zh-CN/design)
- [更新日志](/vant-weapp/#/changelog)
- [官方示例](https://github.com/vant-ui/vant-demo)
## 贡献
### 核心团队
以下是 Vant 和 Vant Weapp 的核心贡献者们:
| [](https://github.com/chenjiahan/) | [](https://github.com/cookfront/) | [](https://github.com/w91/) | [](https://github.com/pangxie1991/) | [](https://github.com/rex-zsd/) | [](https://github.com/nemo-shen/) |
| :-: | :-: | :-: | :-: | :-: | :-: |
| [chenjiahan](https://github.com/chenjiahan/) | [cookfront](https://github.com/cookfront/) | [wangnaiyi](https://github.com/w91/) | [pangxie](https://github.com/pangxie1991/) | [rex-zsd](https://github.com/rex-zsd/) | [nemo-shen](https://github.com/nemo-shen/) |
| [](https://github.com/Lindysen/) | [](https://github.com/JakeLaoyu/) | [](https://github.com/landluck/) | [](https://github.com/wjw-gavin/) | [](https://github.com/inottn/) | [](https://github.com/zhousg/) |
| :-: | :-: | :-: | :-: | :-: | :-: |
| [Lindysen](https://github.com/Lindysen/) | [JakeLaoyu](https://github.com/JakeLaoyu/) | [landluck](https://github.com/landluck/) | [wjw-gavin](https://github.com/wjw-gavin/) | [inottn](https://github.com/inottn/) | [zhousg](https://github.com/zhousg/) |
### 贡献者们
感谢以下小伙伴们为 Vant Weapp 发展做出的贡献:
### 贡献代码
使用过程中发现任何问题都可以提 [Issue](https://github.com/youzan/vant-weapp/issues) 给我们,当然,我们也非常欢迎你给我们发 [PR](https://github.com/youzan/vant-weapp/pulls)。
### 开源协议
本项目基于 [MIT](https://zh.wikipedia.org/wiki/MIT%E8%A8%B1%E5%8F%AF%E8%AD%89) 协议,请自由地享受和参与开源。
================================================
FILE: docs/markdown/quickstart.md
================================================
# 快速上手
### 背景知识
使用 Vant Weapp 前,请确保你已经学习过微信官方的 [小程序简易教程](https://developers.weixin.qq.com/miniprogram/dev/framework/) 和 [自定义组件介绍](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/)。
## 安装
### 步骤一 通过 npm 安装
> 使用 npm 构建前,请先阅读微信官方的 [npm 支持](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html)
```bash
# 通过 npm 安装
npm i @vant/weapp -S --production
# 通过 yarn 安装
yarn add @vant/weapp --production
# 安装 0.x 版本
npm i vant-weapp -S --production
```
### 步骤二 修改 app.json
将 app.json 中的 `"style": "v2"` 去除,小程序的[新版基础组件](https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#style)强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
### 步骤三 构建 npm 包
打开微信开发者工具,点击 **工具 -> 构建 npm**,并勾选 **使用 npm 模块** 选项,构建完成后,即可引入组件。
### 步骤四 typescript 支持
如果你使用 typescript 开发小程序,还需要做如下操作,以获得顺畅的开发体验。
#### 安装 miniprogram-api-typings
```bash
# 通过 npm 安装
npm i -D miniprogram-api-typings
# 通过 yarn 安装
yarn add -D miniprogram-api-typings
```
#### 在 tsconfig.json 中增加如下配置,以防止 tsc 编译报错。
请将`path/to/node_modules/@vant/weapp`修改为项目的 `node_modules` 中 @vant/weapp 所在的目录。
```json
{
...
"compilerOptions": {
...
"baseUrl": ".",
"types": ["miniprogram-api-typings"],
"paths": {
"@vant/weapp/*": ["path/to/node_modules/@vant/weapp/dist/*"]
},
"lib": ["ES6"]
}
}
```
### 示例工程
我们提供了一个[示例工程](https://github.com/vant-ui/vant-demo),示例工程会帮助你了解如下内容:
- 基于 Vant Weapp 搭建小程序应用
- 样式覆盖方案
## 使用
### 引入组件
以 Button 组件为例,只需要在`app.json`或`index.json`中配置 Button 对应的路径即可。
所有组件文档中的引入路径均以 npm 安装为例,如果你是通过下载源代码的方式使用 @vant/weapp,请将路径修改为项目中 @vant/weapp 所在的目录。
```json
// 通过 npm 安装
// app.json
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
```
```json
// 通过下载源码使用 es6版本
// app.json
"usingComponents": {
"van-button": "path/to/@vant/weapp/dist/button/index"
}
```
```json
// 通过下载源码使用 es5版本
// app.json
"usingComponents": {
"van-button": "path/to/@vant/weapp/lib/button/index"
}
```
### 使用组件
引入组件后,可以在 wxml 中直接使用组件
```xml
按钮
```
## 其他
### 在开发者工具中预览示例小程序
```bash
# 将项目克隆到本地
git clone git@github.com:youzan/vant-weapp.git
# 安装项目依赖
cd vant-weapp && npm install
# 执行组件编译
npm run dev
```
接着打开微信开发者工具,导入`example`目录的项目就可以预览示例了。
### 关于用户隐私保护指引
@vant/weapp 部分组件使用了微信提供的接口,其中部分接口涉及获取用户隐私信息。
例如 `` 使用了微信提供的选择用户相册中图片接口`(wx.chooseImage)`。
当小程序引入 @vant/weapp 并发布时,
根据微信[《用户隐私保护指引填写说明》](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/),
如检测到代码中存在涉及用户隐私信息接口则需填写用户隐私保护指引信息,如已填写则无需重复填写。
================================================
FILE: docs/markdown/theme.md
================================================
# 定制主题
### 背景知识
小程序基于 [Shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=zh-cn) 来实现自定义组件,所以 Vant Weapp 使用与之配套的 [CSS 变量](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties) 来实现定制主题。链接中的内容可以帮助你对这两个概念有基本的认识,避免许多不必要的困扰。
CSS 变量 的兼容性要求可以在 [这里](https://caniuse.com/#feat=css-variables) 查看。对于不支持 CSS 变量 的设备,定制主题将不会生效,不过不必担心,默认样式仍会生效。
### 样式变量
定制使用的 CSS 变量 与 Less 变量 同名,下面是一些基本的样式变量,所有可用的颜色变量请参考 [配置文件](https://github.com/youzan/vant-weapp/blob/dev/packages/common/style/var.less)。
```less
// Component Colors
@text-color: #323233;
@border-color: #ebedf0;
@active-color: #f2f3f5;
@background-color: #f8f8f8;
@background-color-light: #fafafa;
```
## 定制方法
### 定制单个组件的主题样式
> 在 wxss 中为组件设置 CSS 变量
```html
默认按钮
```
```less
.my-button {
--button-border-radius: 10px;
--button-default-color: #f2f3f5;
}
```
> 或通过 style 属性来设置 CSS 变量,这使你能够轻松实现主题的动态切换
```html
默认按钮
```
```js
Page({
data: {
buttonStyle: `
--button-border-radius: 10px;
--button-default-color: green;
`,
},
onLoad() {
setTimeout(() => {
this.setData({
buttonStyle: `
--button-border-radius: 2px;
--button-default-color: pink;
`,
});
}, 2000);
},
});
```
### 定制多个组件的主题样式
> 与单个组件的定制方式类似,只需用一个 container 节点包裹住需要定制的组件,并将 CSS 变量 设置在 container 节点上
```html
默认按钮
```
```js
import Toast from '@vant/weapp/toast/toast';
Page({
onClick() {
Toast('我是提示文案,建议不超过十五字~');
},
});
```
```less
.container {
--button-border-radius: 10px;
--button-default-color: #f2f3f5;
--toast-max-width: 100px;
--toast-background-color: pink;
}
```
### 定制全局主题样式
> 在 app.wxss 中,写入 CSS 变量,即可对全局生效
```less
page {
--button-border-radius: 10px;
--button-default-color: #f2f3f5;
--toast-max-width: 100px;
--toast-background-color: pink;
}
```
================================================
FILE: example/app.js
================================================
App({
globalData: {},
onLaunch() {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力');
} else {
wx.cloud.init({
env: 'production-7dtfw'
});
}
}
});
================================================
FILE: example/app.json
================================================
{
"pages": [
"pages/dashboard/index",
"pages/action-sheet/index",
"pages/button/index",
"pages/card/index",
"pages/cell/index",
"pages/col/index",
"pages/count-down/index",
"pages/dialog/index",
"pages/field/index",
"pages/icon/index",
"pages/image/index",
"pages/loading/index",
"pages/nav-bar/index",
"pages/notice-bar/index",
"pages/notify/index",
"pages/panel/index",
"pages/popup/index",
"pages/progress/index",
"pages/stepper/index",
"pages/steps/index",
"pages/sticky/index",
"pages/switch/index",
"pages/search/index",
"pages/slider/index",
"pages/sidebar/index",
"pages/tab/index",
"pages/tabbar/index",
"pages/tag/index",
"pages/toast/index",
"pages/transition/index",
"pages/tree-select/index",
"pages/area/index",
"pages/submit-bar/index",
"pages/radio/index",
"pages/checkbox/index",
"pages/goods-action/index",
"pages/swipe-cell/index",
"pages/uploader/index",
"pages/datetime-picker/index",
"pages/rate/index",
"pages/collapse/index",
"pages/picker/index",
"pages/overlay/index",
"pages/circle/index",
"pages/grid/index",
"pages/dropdown-menu/index",
"pages/index-bar/index",
"pages/skeleton/index",
"pages/divider/index",
"pages/empty/index",
"pages/calendar/index",
"pages/share-sheet/index",
"pages/config-provider/index",
"pages/cascader/index"
],
"window": {
"navigationBarBackgroundColor": "#f8f8f8",
"navigationBarTitleText": "Vant Weapp",
"navigationBarTextStyle": "black",
"backgroundTextStyle": "dark",
"backgroundColor": "#f8f8f8"
},
"usingComponents": {
"demo-block": "./components/demo-block/index",
"van-action-sheet-demo": "./dist/action-sheet/demo/index",
"van-area-demo": "./dist/area/demo/index",
"van-button-demo": "./dist/button/demo/index",
"van-card-demo": "./dist/card/demo/index",
"van-cell-demo": "./dist/cell/demo/index",
"van-checkbox-demo": "./dist/checkbox/demo/index",
"van-col-demo": "./dist/col/demo/index",
"van-count-down-demo": "./dist/count-down/demo/index",
"van-dialog-demo": "./dist/dialog/demo/index",
"van-divider-demo": "./dist/divider/demo/index",
"van-empty-demo": "./dist/empty/demo/index",
"van-field-demo": "./dist/field/demo/index",
"van-goods-action-demo": "./dist/goods-action/demo/index",
"van-icon-demo": "./dist/icon/demo/index",
"van-image-demo": "./dist/image/demo/index",
"van-loading-demo": "./dist/loading/demo/index",
"van-nav-bar-demo": "./dist/nav-bar/demo/index",
"van-notice-bar-demo": "./dist/notice-bar/demo/index",
"van-notify-demo": "./dist/notify/demo/index",
"van-panel-demo": "./dist/panel/demo/index",
"van-popup-demo": "./dist/popup/demo/index",
"van-progress-demo": "./dist/progress/demo/index",
"van-radio-demo": "./dist/radio/demo/index",
"van-search-demo": "./dist/search/demo/index",
"van-sidebar-demo": "./dist/sidebar/demo/index",
"van-slider-demo": "./dist/slider/demo/index",
"van-stepper-demo": "./dist/stepper/demo/index",
"van-steps-demo": "./dist/steps/demo/index",
"van-sticky-demo": "./dist/sticky/demo/index",
"van-submit-bar-demo": "./dist/submit-bar/demo/index",
"van-swipe-cell-demo": "./dist/swipe-cell/demo/index",
"van-uploader-demo": "./dist/uploader/demo/index",
"van-switch-demo": "./dist/switch/demo/index",
"van-tab-demo": "./dist/tab/demo/index",
"van-tabbar-demo": "./dist/tabbar/demo/index",
"van-tag-demo": "./dist/tag/demo/index",
"van-toast-demo": "./dist/toast/demo/index",
"van-transition-demo": "./dist/transition/demo/index",
"van-tree-select-demo": "./dist/tree-select/demo/index",
"van-datetime-picker-demo": "./dist/datetime-picker/demo/index",
"van-rate-demo": "./dist/rate/demo/index",
"van-collapse-demo": "./dist/collapse/demo/index",
"van-picker-demo": "./dist/picker/demo/index",
"van-overlay-demo": "./dist/overlay/demo/index",
"van-circle-demo": "./dist/circle/demo/index",
"van-index-bar-demo": "./dist/index-bar/demo/index",
"van-grid-demo": "./dist/grid/demo/index",
"van-dropdown-menu-demo": "./dist/dropdown-menu/demo/index",
"van-skeleton-demo": "./dist/skeleton/demo/index",
"van-calendar-demo": "./dist/calendar/demo/index",
"van-share-sheet-demo": "./dist/share-sheet/demo/index",
"van-config-provider-demo": "./dist/config-provider/demo/index",
"van-cascader-demo": "./dist/cascader/demo/index"
},
"sitemapLocation": "sitemap.json"
}
================================================
FILE: example/app.wxss
================================================
page {
box-sizing: border-box;
min-height: 100vh;
padding: 0 0 100rpx;
color: #323233;
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',
sans-serif;
background: #f7f8fa;
-webkit-font-smoothing: antialiased;
}
.demo-margin-left {
margin-left: 10px;
}
.demo-margin-right {
margin-right: 10px;
}
.demo-margin-bottom {
display: block;
margin-bottom: 15px;
}
================================================
FILE: example/common/page.js
================================================
export default function(options = {}) {
return Page({
onShareAppMessage() {
return {
title: 'Vant Weapp 组件库演示'
};
},
...options
});
}
================================================
FILE: example/components/demo-block/index.js
================================================
Component({
properties: {
title: String,
padding: Boolean,
card: Boolean,
},
externalClasses: ['custom-class'],
});
================================================
FILE: example/components/demo-block/index.json
================================================
{
"component": true
}
================================================
FILE: example/components/demo-block/index.wxml
================================================
{{ title }}
================================================
FILE: example/components/demo-block/index.wxss
================================================
@import '../../dist/common/index.wxss';
.demo-block__title {
margin: 0;
padding: 20px 15px 15px;
color: rgba(69, 90, 100, 0.6);
font-weight: 400;
font-size: 14px;
}
.demo-block__card {
overflow: hidden;
border-radius: 8px;
}
.demo-block--padding {
padding: 0 15px;
}
.demo-block--padding .demo-block__title {
padding-left: 0;
}
================================================
FILE: example/components/demo-home/index.js
================================================
import list from '../../config';
Component({
data: {
list,
},
});
================================================
FILE: example/components/demo-home/index.json
================================================
{
"component": true,
"usingComponents": {
"demo-home-nav": "../demo-home-nav/index"
}
}
================================================
FILE: example/components/demo-home/index.wxml
================================================
Vant Weapp
轻量、可靠的小程序 UI 组件库
================================================
FILE: example/components/demo-home/index.wxss
================================================
.demo-home {
box-sizing: border-box;
width: 100%;
min-height: 100vh;
padding: 46px 20px 20px;
background: #fff;
}
.demo-home__title,
.demo-home__desc {
padding-left: 16px;
font-weight: normal;
line-height: 1;
user-select: none;
}
.demo-home__title {
margin: 0 0 16px;
font-size: 32px;
}
.demo-home__image,
.demo-home__text {
display: inline-block;
vertical-align: middle;
}
.demo-home__image {
width: 32px;
height: 32px;
}
.demo-home__text {
margin-left: 16px;
font-weight: 500;
}
.demo-home__title .demo-home--small {
font-size: 24px;
}
.demo-home__desc {
margin: 0 0 40px;
color: rgba(69, 90, 100, 0.6);
font-size: 14px;
}
================================================
FILE: example/components/demo-home-nav/index.js
================================================
Component({
properties: {
group: Object,
},
methods: {
onClick(event) {
const { url } = event.target.dataset;
if (getCurrentPages().length > 9) {
wx.redirectTo({ url });
} else {
wx.navigateTo({ url });
}
},
},
});
================================================
FILE: example/components/demo-home-nav/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../../dist/icon/index"
}
}
================================================
FILE: example/components/demo-home-nav/index.wxml
================================================
{{ group.groupName }}
{{ item.title }}
================================================
FILE: example/components/demo-home-nav/index.wxss
================================================
.demo-home-nav__title {
margin: 24px 0 8px 16px;
color: rgba(69, 90, 100, 0.6);
font-size: 14px;
}
.demo-home-nav__block {
position: relative;
display: flex;
margin: 0 0 12px;
padding-left: 20px;
color: #323233;
font-weight: 500;
font-size: 14px;
line-height: 40px;
background: #f7f8fa;
border-radius: 99px;
transition: background 0.3s;
}
.demo-home-nav__block:hover {
background: darken(#f7f8fa, 3%);
}
.demo-home-nav__block:active {
background: darken(#f7f8fa, 6%);
}
.demo-home-nav__icon {
position: absolute !important;
top: 50%;
right: 16px;
width: 16px;
height: 16px;
margin-top: -8px;
color: rgb(182, 195, 210);
font-weight: 900 !important;
}
================================================
FILE: example/config.js
================================================
export default [
{
groupName: '基础组件',
icon: 'https://img.yzcdn.cn/vant/basic-0401.svg',
list: [
{
path: '/button',
title: 'Button 按钮',
},
{
path: '/cell',
title: 'Cell 单元格',
},
{
path: '/config-provider',
title: 'ConfigProvider 全局配置',
},
{
path: '/icon',
title: 'Icon 图标',
},
{
path: '/image',
title: 'Image 图片',
},
{
path: '/col',
title: 'Layout 布局',
},
{
path: '/popup',
title: 'Popup 弹出层',
},
{
path: '/transition',
title: 'Transition 动画',
},
],
},
{
groupName: '表单组件',
icon: 'https://img.yzcdn.cn/vant/form-0401.svg',
list: [
{
path: '/calendar',
title: 'Calendar 日历',
},
{
path: '/cascader',
title: 'Cascader 级联选择',
},
{
path: '/checkbox',
title: 'Checkbox 复选框',
},
{
path: '/datetime-picker',
title: 'DatetimePicker 时间选择',
},
{
path: '/field',
title: 'Field 输入框',
},
{
path: '/picker',
title: 'Picker 选择器',
},
{
path: '/radio',
title: 'Radio 单选框',
},
{
path: '/rate',
title: 'Rate 评分',
},
{
path: '/search',
title: 'Search 搜索',
},
{
path: '/slider',
title: 'Slider 滑块',
},
{
path: '/stepper',
title: 'Stepper 步进器',
},
{
path: '/switch',
title: 'Switch 开关',
},
{
path: '/uploader',
title: 'Uploader 文件上传',
},
],
},
{
groupName: '反馈组件',
icon: 'passed',
list: [
{
path: '/action-sheet',
title: 'ActionSheet 动作面板',
},
{
path: '/dialog',
title: 'Dialog 弹出框',
},
{
path: '/dropdown-menu',
title: 'DropdownMenu 下拉菜单',
},
{
path: '/loading',
title: 'Loading 加载',
},
{
path: '/notify',
title: 'Notify 消息通知',
},
{
path: '/overlay',
title: 'Overlay 遮罩层',
},
{
path: '/share-sheet',
title: 'ShareSheet 分享面板',
},
{
path: '/swipe-cell',
title: 'SwipeCell 滑动单元格',
},
{
path: '/toast',
title: 'Toast 轻提示',
},
],
},
{
groupName: '展示组件',
icon: 'photo-o',
list: [
{
path: '/circle',
title: 'Circle 进度条',
},
{
path: '/collapse',
title: 'Collapse 折叠面板',
},
{
path: '/count-down',
title: 'CountDown 倒计时',
},
{
path: '/divider',
title: 'Divider 分割线',
},
{
path: '/empty',
title: 'Empty 空状态',
},
{
path: '/notice-bar',
title: 'NoticeBar 通知栏',
},
{
path: '/panel',
title: 'Panel 面板',
},
{
path: '/progress',
title: 'Progress 进度条',
},
{
path: '/skeleton',
title: 'Skeleton 骨架屏',
},
{
path: '/steps',
title: 'Steps 步骤条',
},
{
path: '/sticky',
title: 'Sticky 粘性布局',
},
{
path: '/tag',
title: 'Tag 标记',
},
{
path: '/tree-select',
title: 'TreeSelect 分类选择',
},
],
},
{
groupName: '导航组件',
icon: 'https://img.yzcdn.cn/vant/nav-0401.svg',
list: [
{
path: '/grid',
title: 'Grid 宫格',
},
{
path: '/index-bar',
title: 'IndexBar 索引栏',
},
{
path: '/sidebar',
title: 'Sidebar 侧边导航',
},
{
path: '/nav-bar',
title: 'NavBar 导航栏',
},
{
path: '/tab',
title: 'Tab 标签页',
},
{
path: '/tabbar',
title: 'Tabbar 标签栏',
},
],
},
{
groupName: '业务组件',
icon: 'ellipsis',
list: [
{
path: '/area',
title: 'Area 省市区选择',
},
{
path: '/card',
title: 'Card 商品卡片',
},
{
path: '/submit-bar',
title: 'SubmitBar 提交订单栏',
},
{
path: '/goods-action',
title: 'GoodsAction 商品导航',
},
],
},
];
================================================
FILE: example/database_area.json
================================================
{"_id":"5e847ab25ebe5e8d00ff446445d71b47",
"province_list":{
"110000":"北京市",
"120000":"天津市",
"130000":"河北省",
"140000":"山西省",
"150000":"内蒙古自治区",
"210000":"辽宁省",
"220000":"吉林省",
"230000":"黑龙江省",
"310000":"上海市",
"320000":"江苏省",
"330000":"浙江省",
"340000":"安徽省",
"350000":"福建省",
"360000":"江西省",
"370000":"山东省",
"410000":"河南省",
"420000":"湖北省",
"430000":"湖南省",
"440000":"广东省",
"450000":"广西壮族自治区",
"460000":"海南省",
"500000":"重庆市",
"510000":"四川省",
"520000":"贵州省",
"530000":"云南省",
"540000":"西藏自治区",
"610000":"陕西省",
"620000":"甘肃省",
"630000":"青海省",
"640000":"宁夏回族自治区",
"650000":"新疆维吾尔自治区",
"710000":"台湾省",
"810000":"香港特别行政区",
"820000":"澳门特别行政区",
"900000":"海外"
},
"city_list":{
"110100":"北京市",
"120100":"天津市",
"130100":"石家庄市",
"130200":"唐山市",
"130300":"秦皇岛市",
"130400":"邯郸市",
"130500":"邢台市",
"130600":"保定市",
"130700":"张家口市",
"130800":"承德市",
"130900":"沧州市",
"131000":"廊坊市",
"131100":"衡水市",
"140100":"太原市",
"140200":"大同市",
"140300":"阳泉市",
"140400":"长治市",
"140500":"晋城市",
"140600":"朔州市",
"140700":"晋中市",
"140800":"运城市",
"140900":"忻州市",
"141000":"临汾市",
"141100":"吕梁市",
"150100":"呼和浩特市",
"150200":"包头市",
"150300":"乌海市",
"150400":"赤峰市",
"150500":"通辽市",
"150600":"鄂尔多斯市",
"150700":"呼伦贝尔市",
"150800":"巴彦淖尔市",
"150900":"乌兰察布市",
"152200":"兴安盟",
"152500":"锡林郭勒盟",
"152900":"阿拉善盟",
"210100":"沈阳市",
"210200":"大连市",
"210300":"鞍山市",
"210400":"抚顺市",
"210500":"本溪市",
"210600":"丹东市",
"210700":"锦州市",
"210800":"营口市",
"210900":"阜新市",
"211000":"辽阳市",
"211100":"盘锦市",
"211200":"铁岭市",
"211300":"朝阳市",
"211400":"葫芦岛市",
"220100":"长春市",
"220200":"吉林市",
"220300":"四平市",
"220400":"辽源市",
"220500":"通化市",
"220600":"白山市",
"220700":"松原市",
"220800":"白城市",
"222400":"延边朝鲜族自治州",
"230100":"哈尔滨市",
"230200":"齐齐哈尔市",
"230300":"鸡西市",
"230400":"鹤岗市",
"230500":"双鸭山市",
"230600":"大庆市",
"230700":"伊春市",
"230800":"佳木斯市",
"230900":"七台河市",
"231000":"牡丹江市",
"231100":"黑河市",
"231200":"绥化市",
"232700":"大兴安岭地区",
"310100":"上海市",
"320100":"南京市",
"320200":"无锡市",
"320300":"徐州市",
"320400":"常州市",
"320500":"苏州市",
"320600":"南通市",
"320700":"连云港市",
"320800":"淮安市",
"320900":"盐城市",
"321000":"扬州市",
"321100":"镇江市",
"321200":"泰州市",
"321300":"宿迁市",
"330100":"杭州市",
"330200":"宁波市",
"330300":"温州市",
"330400":"嘉兴市",
"330500":"湖州市",
"330600":"绍兴市",
"330700":"金华市",
"330800":"衢州市",
"330900":"舟山市",
"331000":"台州市",
"331100":"丽水市",
"340100":"合肥市",
"340200":"芜湖市",
"340300":"蚌埠市",
"340400":"淮南市",
"340500":"马鞍山市",
"340600":"淮北市",
"340700":"铜陵市",
"340800":"安庆市",
"341000":"黄山市",
"341100":"滁州市",
"341200":"阜阳市",
"341300":"宿州市",
"341500":"六安市",
"341600":"亳州市",
"341700":"池州市",
"341800":"宣城市",
"350100":"福州市",
"350200":"厦门市",
"350300":"莆田市",
"350400":"三明市",
"350500":"泉州市",
"350600":"漳州市",
"350700":"南平市",
"350800":"龙岩市",
"350900":"宁德市",
"360100":"南昌市",
"360200":"景德镇市",
"360300":"萍乡市",
"360400":"九江市",
"360500":"新余市",
"360600":"鹰潭市",
"360700":"赣州市",
"360800":"吉安市",
"360900":"宜春市",
"361000":"抚州市",
"361100":"上饶市",
"370100":"济南市",
"370200":"青岛市",
"370300":"淄博市",
"370400":"枣庄市",
"370500":"东营市",
"370600":"烟台市",
"370700":"潍坊市",
"370800":"济宁市",
"370900":"泰安市",
"371000":"威海市",
"371100":"日照市",
"371300":"临沂市",
"371400":"德州市",
"371500":"聊城市",
"371600":"滨州市",
"371700":"菏泽市",
"410100":"郑州市",
"410200":"开封市",
"410300":"洛阳市",
"410400":"平顶山市",
"410500":"安阳市",
"410600":"鹤壁市",
"410700":"新乡市",
"410800":"焦作市",
"410900":"濮阳市",
"411000":"许昌市",
"411100":"漯河市",
"411200":"三门峡市",
"411300":"南阳市",
"411400":"商丘市",
"411500":"信阳市",
"411600":"周口市",
"411700":"驻马店市",
"419000":"省直辖县",
"420100":"武汉市",
"420200":"黄石市",
"420300":"十堰市",
"420500":"宜昌市",
"420600":"襄阳市",
"420700":"鄂州市",
"420800":"荆门市",
"420900":"孝感市",
"421000":"荆州市",
"421100":"黄冈市",
"421200":"咸宁市",
"421300":"随州市",
"422800":"恩施土家族苗族自治州",
"429000":"省直辖县",
"430100":"长沙市",
"430200":"株洲市",
"430300":"湘潭市",
"430400":"衡阳市",
"430500":"邵阳市",
"430600":"岳阳市",
"430700":"常德市",
"430800":"张家界市",
"430900":"益阳市",
"431000":"郴州市",
"431100":"永州市",
"431200":"怀化市",
"431300":"娄底市",
"433100":"湘西土家族苗族自治州",
"440100":"广州市",
"440200":"韶关市",
"440300":"深圳市",
"440400":"珠海市",
"440500":"汕头市",
"440600":"佛山市",
"440700":"江门市",
"440800":"湛江市",
"440900":"茂名市",
"441200":"肇庆市",
"441300":"惠州市",
"441400":"梅州市",
"441500":"汕尾市",
"441600":"河源市",
"441700":"阳江市",
"441800":"清远市",
"441900":"东莞市",
"442000":"中山市",
"445100":"潮州市",
"445200":"揭阳市",
"445300":"云浮市",
"450100":"南宁市",
"450200":"柳州市",
"450300":"桂林市",
"450400":"梧州市",
"450500":"北海市",
"450600":"防城港市",
"450700":"钦州市",
"450800":"贵港市",
"450900":"玉林市",
"451000":"百色市",
"451100":"贺州市",
"451200":"河池市",
"451300":"来宾市",
"451400":"崇左市",
"460100":"海口市",
"460200":"三亚市",
"460300":"三沙市",
"460400":"儋州市",
"469000":"省直辖县",
"500100":"重庆市",
"500200":"县",
"510100":"成都市",
"510300":"自贡市",
"510400":"攀枝花市",
"510500":"泸州市",
"510600":"德阳市",
"510700":"绵阳市",
"510800":"广元市",
"510900":"遂宁市",
"511000":"内江市",
"511100":"乐山市",
"511300":"南充市",
"511400":"眉山市",
"511500":"宜宾市",
"511600":"广安市",
"511700":"达州市",
"511800":"雅安市",
"511900":"巴中市",
"512000":"资阳市",
"513200":"阿坝藏族羌族自治州",
"513300":"甘孜藏族自治州",
"513400":"凉山彝族自治州",
"520100":"贵阳市",
"520200":"六盘水市",
"520300":"遵义市",
"520400":"安顺市",
"520500":"毕节市",
"520600":"铜仁市",
"522300":"黔西南布依族苗族自治州",
"522600":"黔东南苗族侗族自治州",
"522700":"黔南布依族苗族自治州",
"530100":"昆明市",
"530300":"曲靖市",
"530400":"玉溪市",
"530500":"保山市",
"530600":"昭通市",
"530700":"丽江市",
"530800":"普洱市",
"530900":"临沧市",
"532300":"楚雄彝族自治州",
"532500":"红河哈尼族彝族自治州",
"532600":"文山壮族苗族自治州",
"532800":"西双版纳傣族自治州",
"532900":"大理白族自治州",
"533100":"德宏傣族景颇族自治州",
"533300":"怒江傈僳族自治州",
"533400":"迪庆藏族自治州",
"540100":"拉萨市",
"540200":"日喀则市",
"540300":"昌都市",
"540400":"林芝市",
"540500":"山南市",
"540600":"那曲市",
"542500":"阿里地区",
"610100":"西安市",
"610200":"铜川市",
"610300":"宝鸡市",
"610400":"咸阳市",
"610500":"渭南市",
"610600":"延安市",
"610700":"汉中市",
"610800":"榆林市",
"610900":"安康市",
"611000":"商洛市",
"620100":"兰州市",
"620200":"嘉峪关市",
"620300":"金昌市",
"620400":"白银市",
"620500":"天水市",
"620600":"武威市",
"620700":"张掖市",
"620800":"平凉市",
"620900":"酒泉市",
"621000":"庆阳市",
"621100":"定西市",
"621200":"陇南市",
"622900":"临夏回族自治州",
"623000":"甘南藏族自治州",
"630100":"西宁市",
"630200":"海东市",
"632200":"海北藏族自治州",
"632300":"黄南藏族自治州",
"632500":"海南藏族自治州",
"632600":"果洛藏族自治州",
"632700":"玉树藏族自治州",
"632800":"海西蒙古族藏族自治州",
"640100":"银川市",
"640200":"石嘴山市",
"640300":"吴忠市",
"640400":"固原市",
"640500":"中卫市",
"650100":"乌鲁木齐市",
"650200":"克拉玛依市",
"650400":"吐鲁番市",
"650500":"哈密市",
"652300":"昌吉回族自治州",
"652700":"博尔塔拉蒙古自治州",
"652800":"巴音郭楞蒙古自治州",
"652900":"阿克苏地区",
"653000":"克孜勒苏柯尔克孜自治州",
"653100":"喀什地区",
"653200":"和田地区",
"654000":"伊犁哈萨克自治州",
"654200":"塔城地区",
"654300":"阿勒泰地区",
"659000":"自治区直辖县级行政区划",
"710100":"台北市",
"710200":"高雄市",
"710300":"台南市",
"710400":"台中市",
"710500":"金门县",
"710600":"南投县",
"710700":"基隆市",
"710800":"新竹市",
"710900":"嘉义市",
"711100":"新北市",
"711200":"宜兰县",
"711300":"新竹县",
"711400":"桃园县",
"711500":"苗栗县",
"711700":"彰化县",
"711900":"嘉义县",
"712100":"云林县",
"712400":"屏东县",
"712500":"台东县",
"712600":"花莲县",
"712700":"澎湖县",
"712800":"连江县",
"810100":"香港岛",
"810200":"九龙",
"810300":"新界",
"820100":"澳门半岛",
"820200":"离岛",
"900400":"阿富汗",
"900800":"阿尔巴尼亚",
"901000":"南极洲",
"901200":"阿尔及利亚",
"901600":"美属萨摩亚",
"902000":"安道尔",
"902400":"安哥拉",
"902800":"安提瓜和巴布达",
"903100":"阿塞拜疆",
"903200":"阿根廷",
"903600":"澳大利亚",
"904000":"奥地利",
"904400":"巴哈马",
"904800":"巴林",
"905000":"孟加拉",
"905100":"亚美尼亚",
"905200":"巴巴多斯",
"905600":"比利时",
"906000":"百慕大",
"906400":"不丹",
"906800":"玻利维亚",
"907000":"波黑",
"907200":"博茨瓦纳",
"907400":"布韦岛",
"907600":"巴西",
"908400":"伯利兹",
"908600":"英属印度洋领地",
"909000":"所罗门群岛",
"909200":"英属维尔京群岛",
"909600":"文莱",
"910000":"保加利亚",
"910400":"缅甸",
"910800":"布隆迪",
"911200":"白俄罗斯",
"911600":"柬埔寨",
"912000":"喀麦隆",
"912400":"加拿大",
"913200":"佛得角",
"913600":"开曼群岛",
"914000":"中非",
"914400":"斯里兰卡",
"914800":"乍得",
"915200":"智利",
"916200":"圣诞岛",
"916600":"科科斯群岛",
"917000":"哥伦比亚",
"917400":"科摩罗",
"917500":"马约特",
"917800":"刚果(布)",
"918000":"刚果(金)",
"918400":"库克群岛",
"918800":"哥斯达黎加",
"919100":"克罗地亚",
"919200":"古巴",
"919600":"塞浦路斯",
"920300":"捷克",
"920400":"贝宁",
"920800":"丹麦",
"921200":"多米尼克",
"921400":"多米尼加",
"921800":"厄瓜多尔",
"922200":"萨尔瓦多",
"922600":"赤道几内亚",
"923100":"埃塞俄比亚",
"923200":"厄立特里亚",
"923300":"爱沙尼亚",
"923400":"法罗群岛",
"923800":"马尔维纳斯群岛(福克兰)",
"923900":"南乔治亚岛和南桑威奇群岛",
"924200":"斐济群岛",
"924600":"芬兰",
"924800":"奥兰群岛",
"925000":"法国",
"925400":"法属圭亚那",
"925800":"法属波利尼西亚",
"926000":"法属南部领地",
"926200":"吉布提",
"926600":"加蓬",
"926800":"格鲁吉亚",
"927000":"冈比亚",
"927500":"巴勒斯坦",
"927600":"德国",
"928800":"加纳",
"929200":"直布罗陀",
"929600":"基里巴斯",
"930000":"希腊",
"930400":"格陵兰",
"930800":"格林纳达",
"931200":"瓜德罗普",
"931600":"关岛",
"932000":"危地马拉",
"932400":"几内亚",
"932800":"圭亚那",
"933200":"海地",
"933400":"赫德岛和麦克唐纳群岛",
"933600":"梵蒂冈",
"934000":"洪都拉斯",
"934800":"匈牙利",
"935200":"冰岛",
"935600":"印度",
"936000":"印尼",
"936400":"伊朗",
"936800":"伊拉克",
"937200":"爱尔兰",
"937600":"以色列",
"938000":"意大利",
"938400":"科特迪瓦",
"938800":"牙买加",
"939200":"日本",
"939800":"哈萨克斯坦",
"940000":"约旦",
"940400":"肯尼亚",
"940800":"朝鲜(北朝鲜)",
"941000":"韩国",
"941400":"科威特",
"941700":"吉尔吉斯斯坦",
"941800":"老挝",
"942200":"黎巴嫩",
"942600":"莱索托",
"942800":"拉脱维亚",
"943000":"利比里亚",
"943400":"利比亚",
"943800":"列支敦士登",
"944000":"立陶宛",
"944200":"卢森堡",
"945000":"马达加斯加",
"945400":"马拉维",
"945800":"马来西亚",
"946200":"马尔代夫",
"946600":"马里",
"947000":"马耳他",
"947400":"马提尼克",
"947800":"毛里塔尼亚",
"948000":"毛里求斯",
"948400":"墨西哥",
"949200":"摩纳哥",
"949600":"蒙古国",
"949800":"摩尔多瓦",
"949900":"黑山",
"950000":"蒙塞拉特岛",
"950400":"摩洛哥",
"950800":"莫桑比克",
"951200":"阿曼",
"951600":"纳米比亚",
"952000":"瑙鲁",
"952400":"尼泊尔",
"952800":"荷兰",
"953300":"阿鲁巴",
"953500":"荷兰加勒比区",
"954000":"新喀里多尼亚",
"954800":"瓦努阿图",
"955400":"新西兰",
"955800":"尼加拉瓜",
"956200":"尼日尔",
"956600":"尼日利亚",
"957000":"纽埃",
"957400":"诺福克岛",
"957800":"挪威",
"958000":"北马里亚纳群岛",
"958100":"美国本土外小岛屿",
"958300":"密克罗尼西亚联邦",
"958400":"马绍尔群岛",
"958500":"帕劳",
"958600":"巴基斯坦",
"959100":"巴拿马",
"959800":"巴布亚新几内亚",
"960000":"巴拉圭",
"960400":"秘鲁",
"960800":"菲律宾",
"961200":"皮特凯恩群岛",
"961600":"波兰",
"962000":"葡萄牙",
"962400":"几内亚比绍",
"962600":"东帝汶",
"963000":"波多黎各",
"963400":"卡塔尔",
"963800":"留尼汪",
"964200":"罗马尼亚",
"964300":"俄罗斯",
"964600":"卢旺达",
"965200":"圣巴泰勒米岛",
"965400":"圣赫勒拿",
"965900":"圣基茨和尼维斯",
"966000":"安圭拉",
"966200":"圣卢西亚",
"966300":"法属圣马丁",
"966600":"圣皮埃尔和密克隆",
"967000":"圣文森特和格林纳丁斯",
"967400":"圣马力诺",
"967800":"圣多美和普林西比",
"968200":"沙特阿拉伯",
"968600":"塞内加尔",
"968800":"塞尔维亚",
"969000":"塞舌尔",
"969400":"塞拉利昂",
"970200":"新加坡",
"970300":"斯洛伐克",
"970400":"越南",
"970500":"斯洛文尼亚",
"970600":"索马里",
"971000":"南非",
"971600":"津巴布韦",
"972400":"西班牙",
"972800":"南苏丹",
"972900":"苏丹",
"973200":"西撒哈拉",
"974000":"苏里南",
"974400":"斯瓦尔巴群岛和扬马延岛",
"974800":"斯威士兰",
"975200":"瑞典",
"975600":"瑞士",
"976000":"叙利亚",
"976200":"塔吉克斯坦",
"976400":"泰国",
"976800":"多哥",
"977200":"托克劳",
"977600":"汤加",
"978000":"特立尼达和多巴哥",
"978400":"阿联酋",
"978800":"突尼斯",
"979200":"土耳其",
"979500":"土库曼斯坦",
"979600":"特克斯和凯科斯群岛",
"979800":"图瓦卢",
"980000":"乌干达",
"980400":"乌克兰",
"980700":"马其顿",
"981800":"埃及",
"982600":"英国",
"983100":"根西岛",
"983200":"泽西岛",
"983300":"马恩岛",
"983400":"坦桑尼亚",
"984000":"美国",
"985000":"美属维尔京群岛",
"985400":"布基纳法索",
"985800":"乌拉圭",
"986000":"乌兹别克斯坦",
"986200":"委内瑞拉",
"987600":"瓦利斯和富图纳",
"988200":"萨摩亚",
"988700":"也门",
"989400":"赞比亚"
},
"county_list":{
"110101":"东城区",
"110102":"西城区",
"110105":"朝阳区",
"110106":"丰台区",
"110107":"石景山区",
"110108":"海淀区",
"110109":"门头沟区",
"110111":"房山区",
"110112":"通州区",
"110113":"顺义区",
"110114":"昌平区",
"110115":"大兴区",
"110116":"怀柔区",
"110117":"平谷区",
"110118":"密云区",
"110119":"延庆区",
"120101":"和平区",
"120102":"河东区",
"120103":"河西区",
"120104":"南开区",
"120105":"河北区",
"120106":"红桥区",
"120110":"东丽区",
"120111":"西青区",
"120112":"津南区",
"120113":"北辰区",
"120114":"武清区",
"120115":"宝坻区",
"120116":"滨海新区",
"120117":"宁河区",
"120118":"静海区",
"120119":"蓟州区",
"130102":"长安区",
"130104":"桥西区",
"130105":"新华区",
"130107":"井陉矿区",
"130108":"裕华区",
"130109":"藁城区",
"130110":"鹿泉区",
"130111":"栾城区",
"130121":"井陉县",
"130123":"正定县",
"130125":"行唐县",
"130126":"灵寿县",
"130127":"高邑县",
"130128":"深泽县",
"130129":"赞皇县",
"130130":"无极县",
"130131":"平山县",
"130132":"元氏县",
"130133":"赵县",
"130181":"辛集市",
"130183":"晋州市",
"130184":"新乐市",
"130202":"路南区",
"130203":"路北区",
"130204":"古冶区",
"130205":"开平区",
"130207":"丰南区",
"130208":"丰润区",
"130209":"曹妃甸区",
"130224":"滦南县",
"130225":"乐亭县",
"130227":"迁西县",
"130229":"玉田县",
"130281":"遵化市",
"130283":"迁安市",
"130284":"滦州市",
"130302":"海港区",
"130303":"山海关区",
"130304":"北戴河区",
"130306":"抚宁区",
"130321":"青龙满族自治县",
"130322":"昌黎县",
"130324":"卢龙县",
"130390":"经济技术开发区",
"130402":"邯山区",
"130403":"丛台区",
"130404":"复兴区",
"130406":"峰峰矿区",
"130407":"肥乡区",
"130408":"永年区",
"130423":"临漳县",
"130424":"成安县",
"130425":"大名县",
"130426":"涉县",
"130427":"磁县",
"130430":"邱县",
"130431":"鸡泽县",
"130432":"广平县",
"130433":"馆陶县",
"130434":"魏县",
"130435":"曲周县",
"130481":"武安市",
"130502":"桥东区",
"130503":"桥西区",
"130521":"邢台县",
"130522":"临城县",
"130523":"内丘县",
"130524":"柏乡县",
"130525":"隆尧县",
"130526":"任县",
"130527":"南和县",
"130528":"宁晋县",
"130529":"巨鹿县",
"130530":"新河县",
"130531":"广宗县",
"130532":"平乡县",
"130533":"威县",
"130534":"清河县",
"130535":"临西县",
"130581":"南宫市",
"130582":"沙河市",
"130602":"竞秀区",
"130606":"莲池区",
"130607":"满城区",
"130608":"清苑区",
"130609":"徐水区",
"130623":"涞水县",
"130624":"阜平县",
"130626":"定兴县",
"130627":"唐县",
"130628":"高阳县",
"130629":"容城县",
"130630":"涞源县",
"130631":"望都县",
"130632":"安新县",
"130633":"易县",
"130634":"曲阳县",
"130635":"蠡县",
"130636":"顺平县",
"130637":"博野县",
"130638":"雄县",
"130681":"涿州市",
"130682":"定州市",
"130683":"安国市",
"130684":"高碑店市",
"130702":"桥东区",
"130703":"桥西区",
"130705":"宣化区",
"130706":"下花园区",
"130708":"万全区",
"130709":"崇礼区",
"130722":"张北县",
"130723":"康保县",
"130724":"沽源县",
"130725":"尚义县",
"130726":"蔚县",
"130727":"阳原县",
"130728":"怀安县",
"130730":"怀来县",
"130731":"涿鹿县",
"130732":"赤城县",
"130802":"双桥区",
"130803":"双滦区",
"130804":"鹰手营子矿区",
"130821":"承德县",
"130822":"兴隆县",
"130824":"滦平县",
"130825":"隆化县",
"130826":"丰宁满族自治县",
"130827":"宽城满族自治县",
"130828":"围场满族蒙古族自治县",
"130881":"平泉市",
"130902":"新华区",
"130903":"运河区",
"130921":"沧县",
"130922":"青县",
"130923":"东光县",
"130924":"海兴县",
"130925":"盐山县",
"130926":"肃宁县",
"130927":"南皮县",
"130928":"吴桥县",
"130929":"献县",
"130930":"孟村回族自治县",
"130981":"泊头市",
"130982":"任丘市",
"130983":"黄骅市",
"130984":"河间市",
"131002":"安次区",
"131003":"广阳区",
"131022":"固安县",
"131023":"永清县",
"131024":"香河县",
"131025":"大城县",
"131026":"文安县",
"131028":"大厂回族自治县",
"131081":"霸州市",
"131082":"三河市",
"131090":"开发区",
"131102":"桃城区",
"131103":"冀州区",
"131121":"枣强县",
"131122":"武邑县",
"131123":"武强县",
"131124":"饶阳县",
"131125":"安平县",
"131126":"故城县",
"131127":"景县",
"131128":"阜城县",
"131182":"深州市",
"140105":"小店区",
"140106":"迎泽区",
"140107":"杏花岭区",
"140108":"尖草坪区",
"140109":"万柏林区",
"140110":"晋源区",
"140121":"清徐县",
"140122":"阳曲县",
"140123":"娄烦县",
"140181":"古交市",
"140212":"新荣区",
"140213":"平城区",
"140214":"云冈区",
"140215":"云州区",
"140221":"阳高县",
"140222":"天镇县",
"140223":"广灵县",
"140224":"灵丘县",
"140225":"浑源县",
"140226":"左云县",
"140302":"城区",
"140303":"矿区",
"140311":"郊区",
"140321":"平定县",
"140322":"盂县",
"140403":"潞州区",
"140404":"上党区",
"140405":"屯留区",
"140406":"潞城区",
"140423":"襄垣县",
"140425":"平顺县",
"140426":"黎城县",
"140427":"壶关县",
"140428":"长子县",
"140429":"武乡县",
"140430":"沁县",
"140431":"沁源县",
"140502":"城区",
"140521":"沁水县",
"140522":"阳城县",
"140524":"陵川县",
"140525":"泽州县",
"140581":"高平市",
"140602":"朔城区",
"140603":"平鲁区",
"140621":"山阴县",
"140622":"应县",
"140623":"右玉县",
"140681":"怀仁市",
"140702":"榆次区",
"140721":"榆社县",
"140722":"左权县",
"140723":"和顺县",
"140724":"昔阳县",
"140725":"寿阳县",
"140726":"太谷县",
"140727":"祁县",
"140728":"平遥县",
"140729":"灵石县",
"140781":"介休市",
"140802":"盐湖区",
"140821":"临猗县",
"140822":"万荣县",
"140823":"闻喜县",
"140824":"稷山县",
"140825":"新绛县",
"140826":"绛县",
"140827":"垣曲县",
"140828":"夏县",
"140829":"平陆县",
"140830":"芮城县",
"140881":"永济市",
"140882":"河津市",
"140902":"忻府区",
"140921":"定襄县",
"140922":"五台县",
"140923":"代县",
"140924":"繁峙县",
"140925":"宁武县",
"140926":"静乐县",
"140927":"神池县",
"140928":"五寨县",
"140929":"岢岚县",
"140930":"河曲县",
"140931":"保德县",
"140932":"偏关县",
"140981":"原平市",
"141002":"尧都区",
"141021":"曲沃县",
"141022":"翼城县",
"141023":"襄汾县",
"141024":"洪洞县",
"141025":"古县",
"141026":"安泽县",
"141027":"浮山县",
"141028":"吉县",
"141029":"乡宁县",
"141030":"大宁县",
"141031":"隰县",
"141032":"永和县",
"141033":"蒲县",
"141034":"汾西县",
"141081":"侯马市",
"141082":"霍州市",
"141102":"离石区",
"141121":"文水县",
"141122":"交城县",
"141123":"兴县",
"141124":"临县",
"141125":"柳林县",
"141126":"石楼县",
"141127":"岚县",
"141128":"方山县",
"141129":"中阳县",
"141130":"交口县",
"141181":"孝义市",
"141182":"汾阳市",
"150102":"新城区",
"150103":"回民区",
"150104":"玉泉区",
"150105":"赛罕区",
"150121":"土默特左旗",
"150122":"托克托县",
"150123":"和林格尔县",
"150124":"清水河县",
"150125":"武川县",
"150202":"东河区",
"150203":"昆都仑区",
"150204":"青山区",
"150205":"石拐区",
"150206":"白云鄂博矿区",
"150207":"九原区",
"150221":"土默特右旗",
"150222":"固阳县",
"150223":"达尔罕茂明安联合旗",
"150302":"海勃湾区",
"150303":"海南区",
"150304":"乌达区",
"150402":"红山区",
"150403":"元宝山区",
"150404":"松山区",
"150421":"阿鲁科尔沁旗",
"150422":"巴林左旗",
"150423":"巴林右旗",
"150424":"林西县",
"150425":"克什克腾旗",
"150426":"翁牛特旗",
"150428":"喀喇沁旗",
"150429":"宁城县",
"150430":"敖汉旗",
"150502":"科尔沁区",
"150521":"科尔沁左翼中旗",
"150522":"科尔沁左翼后旗",
"150523":"开鲁县",
"150524":"库伦旗",
"150525":"奈曼旗",
"150526":"扎鲁特旗",
"150581":"霍林郭勒市",
"150602":"东胜区",
"150603":"康巴什区",
"150621":"达拉特旗",
"150622":"准格尔旗",
"150623":"鄂托克前旗",
"150624":"鄂托克旗",
"150625":"杭锦旗",
"150626":"乌审旗",
"150627":"伊金霍洛旗",
"150702":"海拉尔区",
"150703":"扎赉诺尔区",
"150721":"阿荣旗",
"150722":"莫力达瓦达斡尔族自治旗",
"150723":"鄂伦春自治旗",
"150724":"鄂温克族自治旗",
"150725":"陈巴尔虎旗",
"150726":"新巴尔虎左旗",
"150727":"新巴尔虎右旗",
"150781":"满洲里市",
"150782":"牙克石市",
"150783":"扎兰屯市",
"150784":"额尔古纳市",
"150785":"根河市",
"150802":"临河区",
"150821":"五原县",
"150822":"磴口县",
"150823":"乌拉特前旗",
"150824":"乌拉特中旗",
"150825":"乌拉特后旗",
"150826":"杭锦后旗",
"150902":"集宁区",
"150921":"卓资县",
"150922":"化德县",
"150923":"商都县",
"150924":"兴和县",
"150925":"凉城县",
"150926":"察哈尔右翼前旗",
"150927":"察哈尔右翼中旗",
"150928":"察哈尔右翼后旗",
"150929":"四子王旗",
"150981":"丰镇市",
"152201":"乌兰浩特市",
"152202":"阿尔山市",
"152221":"科尔沁右翼前旗",
"152222":"科尔沁右翼中旗",
"152223":"扎赉特旗",
"152224":"突泉县",
"152501":"二连浩特市",
"152502":"锡林浩特市",
"152522":"阿巴嘎旗",
"152523":"苏尼特左旗",
"152524":"苏尼特右旗",
"152525":"东乌珠穆沁旗",
"152526":"西乌珠穆沁旗",
"152527":"太仆寺旗",
"152528":"镶黄旗",
"152529":"正镶白旗",
"152530":"正蓝旗",
"152531":"多伦县",
"152921":"阿拉善左旗",
"152922":"阿拉善右旗",
"152923":"额济纳旗",
"210102":"和平区",
"210103":"沈河区",
"210104":"大东区",
"210105":"皇姑区",
"210106":"铁西区",
"210111":"苏家屯区",
"210112":"浑南区",
"210113":"沈北新区",
"210114":"于洪区",
"210115":"辽中区",
"210123":"康平县",
"210124":"法库县",
"210181":"新民市",
"210190":"经济技术开发区",
"210202":"中山区",
"210203":"西岗区",
"210204":"沙河口区",
"210211":"甘井子区",
"210212":"旅顺口区",
"210213":"金州区",
"210214":"普兰店区",
"210224":"长海县",
"210281":"瓦房店市",
"210283":"庄河市",
"210302":"铁东区",
"210303":"铁西区",
"210304":"立山区",
"210311":"千山区",
"210321":"台安县",
"210323":"岫岩满族自治县",
"210381":"海城市",
"210390":"高新区",
"210402":"新抚区",
"210403":"东洲区",
"210404":"望花区",
"210411":"顺城区",
"210421":"抚顺县",
"210422":"新宾满族自治县",
"210423":"清原满族自治县",
"210502":"平山区",
"210503":"溪湖区",
"210504":"明山区",
"210505":"南芬区",
"210521":"本溪满族自治县",
"210522":"桓仁满族自治县",
"210602":"元宝区",
"210603":"振兴区",
"210604":"振安区",
"210624":"宽甸满族自治县",
"210681":"东港市",
"210682":"凤城市",
"210702":"古塔区",
"210703":"凌河区",
"210711":"太和区",
"210726":"黑山县",
"210727":"义县",
"210781":"凌海市",
"210782":"北镇市",
"210793":"经济技术开发区",
"210802":"站前区",
"210803":"西市区",
"210804":"鲅鱼圈区",
"210811":"老边区",
"210881":"盖州市",
"210882":"大石桥市",
"210902":"海州区",
"210903":"新邱区",
"210904":"太平区",
"210905":"清河门区",
"210911":"细河区",
"210921":"阜新蒙古族自治县",
"210922":"彰武县",
"211002":"白塔区",
"211003":"文圣区",
"211004":"宏伟区",
"211005":"弓长岭区",
"211011":"太子河区",
"211021":"辽阳县",
"211081":"灯塔市",
"211102":"双台子区",
"211103":"兴隆台区",
"211104":"大洼区",
"211122":"盘山县",
"211202":"银州区",
"211204":"清河区",
"211221":"铁岭县",
"211223":"西丰县",
"211224":"昌图县",
"211281":"调兵山市",
"211282":"开原市",
"211302":"双塔区",
"211303":"龙城区",
"211321":"朝阳县",
"211322":"建平县",
"211324":"喀喇沁左翼蒙古族自治县",
"211381":"北票市",
"211382":"凌源市",
"211402":"连山区",
"211403":"龙港区",
"211404":"南票区",
"211421":"绥中县",
"211422":"建昌县",
"211481":"兴城市",
"220102":"南关区",
"220103":"宽城区",
"220104":"朝阳区",
"220105":"二道区",
"220106":"绿园区",
"220112":"双阳区",
"220113":"九台区",
"220122":"农安县",
"220182":"榆树市",
"220183":"德惠市",
"220192":"经济技术开发区",
"220202":"昌邑区",
"220203":"龙潭区",
"220204":"船营区",
"220211":"丰满区",
"220221":"永吉县",
"220281":"蛟河市",
"220282":"桦甸市",
"220283":"舒兰市",
"220284":"磐石市",
"220302":"铁西区",
"220303":"铁东区",
"220322":"梨树县",
"220323":"伊通满族自治县",
"220381":"公主岭市",
"220382":"双辽市",
"220402":"龙山区",
"220403":"西安区",
"220421":"东丰县",
"220422":"东辽县",
"220502":"东昌区",
"220503":"二道江区",
"220521":"通化县",
"220523":"辉南县",
"220524":"柳河县",
"220581":"梅河口市",
"220582":"集安市",
"220602":"浑江区",
"220605":"江源区",
"220621":"抚松县",
"220622":"靖宇县",
"220623":"长白朝鲜族自治县",
"220681":"临江市",
"220702":"宁江区",
"220721":"前郭尔罗斯蒙古族自治县",
"220722":"长岭县",
"220723":"乾安县",
"220781":"扶余市",
"220802":"洮北区",
"220821":"镇赉县",
"220822":"通榆县",
"220881":"洮南市",
"220882":"大安市",
"222401":"延吉市",
"222402":"图们市",
"222403":"敦化市",
"222404":"珲春市",
"222405":"龙井市",
"222406":"和龙市",
"222424":"汪清县",
"222426":"安图县",
"230102":"道里区",
"230103":"南岗区",
"230104":"道外区",
"230108":"平房区",
"230109":"松北区",
"230110":"香坊区",
"230111":"呼兰区",
"230112":"阿城区",
"230113":"双城区",
"230123":"依兰县",
"230124":"方正县",
"230125":"宾县",
"230126":"巴彦县",
"230127":"木兰县",
"230128":"通河县",
"230129":"延寿县",
"230183":"尚志市",
"230184":"五常市",
"230202":"龙沙区",
"230203":"建华区",
"230204":"铁锋区",
"230205":"昂昂溪区",
"230206":"富拉尔基区",
"230207":"碾子山区",
"230208":"梅里斯达斡尔族区",
"230221":"龙江县",
"230223":"依安县",
"230224":"泰来县",
"230225":"甘南县",
"230227":"富裕县",
"230229":"克山县",
"230230":"克东县",
"230231":"拜泉县",
"230281":"讷河市",
"230302":"鸡冠区",
"230303":"恒山区",
"230304":"滴道区",
"230305":"梨树区",
"230306":"城子河区",
"230307":"麻山区",
"230321":"鸡东县",
"230381":"虎林市",
"230382":"密山市",
"230402":"向阳区",
"230403":"工农区",
"230404":"南山区",
"230405":"兴安区",
"230406":"东山区",
"230407":"兴山区",
"230421":"萝北县",
"230422":"绥滨县",
"230502":"尖山区",
"230503":"岭东区",
"230505":"四方台区",
"230506":"宝山区",
"230521":"集贤县",
"230522":"友谊县",
"230523":"宝清县",
"230524":"饶河县",
"230602":"萨尔图区",
"230603":"龙凤区",
"230604":"让胡路区",
"230605":"红岗区",
"230606":"大同区",
"230621":"肇州县",
"230622":"肇源县",
"230623":"林甸县",
"230624":"杜尔伯特蒙古族自治县",
"230702":"伊春区",
"230703":"南岔区",
"230704":"友好区",
"230705":"西林区",
"230706":"翠峦区",
"230707":"新青区",
"230708":"美溪区",
"230709":"金山屯区",
"230710":"五营区",
"230711":"乌马河区",
"230712":"汤旺河区",
"230713":"带岭区",
"230714":"乌伊岭区",
"230715":"红星区",
"230716":"上甘岭区",
"230722":"嘉荫县",
"230781":"铁力市",
"230803":"向阳区",
"230804":"前进区",
"230805":"东风区",
"230811":"郊区",
"230822":"桦南县",
"230826":"桦川县",
"230828":"汤原县",
"230881":"同江市",
"230882":"富锦市",
"230883":"抚远市",
"230902":"新兴区",
"230903":"桃山区",
"230904":"茄子河区",
"230921":"勃利县",
"231002":"东安区",
"231003":"阳明区",
"231004":"爱民区",
"231005":"西安区",
"231025":"林口县",
"231081":"绥芬河市",
"231083":"海林市",
"231084":"宁安市",
"231085":"穆棱市",
"231086":"东宁市",
"231102":"爱辉区",
"231121":"嫩江县",
"231123":"逊克县",
"231124":"孙吴县",
"231181":"北安市",
"231182":"五大连池市",
"231202":"北林区",
"231221":"望奎县",
"231222":"兰西县",
"231223":"青冈县",
"231224":"庆安县",
"231225":"明水县",
"231226":"绥棱县",
"231281":"安达市",
"231282":"肇东市",
"231283":"海伦市",
"232701":"漠河市",
"232721":"呼玛县",
"232722":"塔河县",
"232790":"松岭区",
"232791":"呼中区",
"232792":"加格达奇区",
"232793":"新林区",
"310101":"黄浦区",
"310104":"徐汇区",
"310105":"长宁区",
"310106":"静安区",
"310107":"普陀区",
"310109":"虹口区",
"310110":"杨浦区",
"310112":"闵行区",
"310113":"宝山区",
"310114":"嘉定区",
"310115":"浦东新区",
"310116":"金山区",
"310117":"松江区",
"310118":"青浦区",
"310120":"奉贤区",
"310151":"崇明区",
"320102":"玄武区",
"320104":"秦淮区",
"320105":"建邺区",
"320106":"鼓楼区",
"320111":"浦口区",
"320113":"栖霞区",
"320114":"雨花台区",
"320115":"江宁区",
"320116":"六合区",
"320117":"溧水区",
"320118":"高淳区",
"320205":"锡山区",
"320206":"惠山区",
"320211":"滨湖区",
"320213":"梁溪区",
"320214":"新吴区",
"320281":"江阴市",
"320282":"宜兴市",
"320302":"鼓楼区",
"320303":"云龙区",
"320305":"贾汪区",
"320311":"泉山区",
"320312":"铜山区",
"320321":"丰县",
"320322":"沛县",
"320324":"睢宁县",
"320381":"新沂市",
"320382":"邳州市",
"320391":"工业园区",
"320402":"天宁区",
"320404":"钟楼区",
"320411":"新北区",
"320412":"武进区",
"320413":"金坛区",
"320481":"溧阳市",
"320505":"虎丘区",
"320506":"吴中区",
"320507":"相城区",
"320508":"姑苏区",
"320509":"吴江区",
"320581":"常熟市",
"320582":"张家港市",
"320583":"昆山市",
"320585":"太仓市",
"320590":"工业园区",
"320591":"高新区",
"320602":"崇川区",
"320611":"港闸区",
"320612":"通州区",
"320623":"如东县",
"320681":"启东市",
"320682":"如皋市",
"320684":"海门市",
"320685":"海安市",
"320691":"高新区",
"320703":"连云区",
"320706":"海州区",
"320707":"赣榆区",
"320722":"东海县",
"320723":"灌云县",
"320724":"灌南县",
"320803":"淮安区",
"320804":"淮阴区",
"320812":"清江浦区",
"320813":"洪泽区",
"320826":"涟水县",
"320830":"盱眙县",
"320831":"金湖县",
"320890":"经济开发区",
"320902":"亭湖区",
"320903":"盐都区",
"320904":"大丰区",
"320921":"响水县",
"320922":"滨海县",
"320923":"阜宁县",
"320924":"射阳县",
"320925":"建湖县",
"320981":"东台市",
"321002":"广陵区",
"321003":"邗江区",
"321012":"江都区",
"321023":"宝应县",
"321081":"仪征市",
"321084":"高邮市",
"321090":"经济开发区",
"321102":"京口区",
"321111":"润州区",
"321112":"丹徒区",
"321181":"丹阳市",
"321182":"扬中市",
"321183":"句容市",
"321202":"海陵区",
"321203":"高港区",
"321204":"姜堰区",
"321281":"兴化市",
"321282":"靖江市",
"321283":"泰兴市",
"321302":"宿城区",
"321311":"宿豫区",
"321322":"沭阳县",
"321323":"泗阳县",
"321324":"泗洪县",
"330102":"上城区",
"330103":"下城区",
"330104":"江干区",
"330105":"拱墅区",
"330106":"西湖区",
"330108":"滨江区",
"330109":"萧山区",
"330110":"余杭区",
"330111":"富阳区",
"330112":"临安区",
"330122":"桐庐县",
"330127":"淳安县",
"330182":"建德市",
"330203":"海曙区",
"330205":"江北区",
"330206":"北仑区",
"330211":"镇海区",
"330212":"鄞州区",
"330213":"奉化区",
"330225":"象山县",
"330226":"宁海县",
"330281":"余姚市",
"330282":"慈溪市",
"330302":"鹿城区",
"330303":"龙湾区",
"330304":"瓯海区",
"330305":"洞头区",
"330324":"永嘉县",
"330326":"平阳县",
"330327":"苍南县",
"330328":"文成县",
"330329":"泰顺县",
"330381":"瑞安市",
"330382":"乐清市",
"330402":"南湖区",
"330411":"秀洲区",
"330421":"嘉善县",
"330424":"海盐县",
"330481":"海宁市",
"330482":"平湖市",
"330483":"桐乡市",
"330502":"吴兴区",
"330503":"南浔区",
"330521":"德清县",
"330522":"长兴县",
"330523":"安吉县",
"330602":"越城区",
"330603":"柯桥区",
"330604":"上虞区",
"330624":"新昌县",
"330681":"诸暨市",
"330683":"嵊州市",
"330702":"婺城区",
"330703":"金东区",
"330723":"武义县",
"330726":"浦江县",
"330727":"磐安县",
"330781":"兰溪市",
"330782":"义乌市",
"330783":"东阳市",
"330784":"永康市",
"330802":"柯城区",
"330803":"衢江区",
"330822":"常山县",
"330824":"开化县",
"330825":"龙游县",
"330881":"江山市",
"330902":"定海区",
"330903":"普陀区",
"330921":"岱山县",
"330922":"嵊泗县",
"331002":"椒江区",
"331003":"黄岩区",
"331004":"路桥区",
"331022":"三门县",
"331023":"天台县",
"331024":"仙居县",
"331081":"温岭市",
"331082":"临海市",
"331083":"玉环市",
"331102":"莲都区",
"331121":"青田县",
"331122":"缙云县",
"331123":"遂昌县",
"331124":"松阳县",
"331125":"云和县",
"331126":"庆元县",
"331127":"景宁畲族自治县",
"331181":"龙泉市",
"340102":"瑶海区",
"340103":"庐阳区",
"340104":"蜀山区",
"340111":"包河区",
"340121":"长丰县",
"340122":"肥东县",
"340123":"肥西县",
"340124":"庐江县",
"340181":"巢湖市",
"340190":"高新技术开发区",
"340191":"经济技术开发区",
"340202":"镜湖区",
"340203":"弋江区",
"340207":"鸠江区",
"340208":"三山区",
"340221":"芜湖县",
"340222":"繁昌县",
"340223":"南陵县",
"340225":"无为县",
"340302":"龙子湖区",
"340303":"蚌山区",
"340304":"禹会区",
"340311":"淮上区",
"340321":"怀远县",
"340322":"五河县",
"340323":"固镇县",
"340402":"大通区",
"340403":"田家庵区",
"340404":"谢家集区",
"340405":"八公山区",
"340406":"潘集区",
"340421":"凤台县",
"340422":"寿县",
"340503":"花山区",
"340504":"雨山区",
"340506":"博望区",
"340521":"当涂县",
"340522":"含山县",
"340523":"和县",
"340602":"杜集区",
"340603":"相山区",
"340604":"烈山区",
"340621":"濉溪县",
"340705":"铜官区",
"340706":"义安区",
"340711":"郊区",
"340722":"枞阳县",
"340802":"迎江区",
"340803":"大观区",
"340811":"宜秀区",
"340822":"怀宁县",
"340824":"潜山县",
"340825":"太湖县",
"340826":"宿松县",
"340827":"望江县",
"340828":"岳西县",
"340881":"桐城市",
"341002":"屯溪区",
"341003":"黄山区",
"341004":"徽州区",
"341021":"歙县",
"341022":"休宁县",
"341023":"黟县",
"341024":"祁门县",
"341102":"琅琊区",
"341103":"南谯区",
"341122":"来安县",
"341124":"全椒县",
"341125":"定远县",
"341126":"凤阳县",
"341181":"天长市",
"341182":"明光市",
"341202":"颍州区",
"341203":"颍东区",
"341204":"颍泉区",
"341221":"临泉县",
"341222":"太和县",
"341225":"阜南县",
"341226":"颍上县",
"341282":"界首市",
"341302":"埇桥区",
"341321":"砀山县",
"341322":"萧县",
"341323":"灵璧县",
"341324":"泗县",
"341390":"经济开发区",
"341502":"金安区",
"341503":"裕安区",
"341504":"叶集区",
"341522":"霍邱县",
"341523":"舒城县",
"341524":"金寨县",
"341525":"霍山县",
"341602":"谯城区",
"341621":"涡阳县",
"341622":"蒙城县",
"341623":"利辛县",
"341702":"贵池区",
"341721":"东至县",
"341722":"石台县",
"341723":"青阳县",
"341802":"宣州区",
"341821":"郎溪县",
"341822":"广德县",
"341823":"泾县",
"341824":"绩溪县",
"341825":"旌德县",
"341881":"宁国市",
"350102":"鼓楼区",
"350103":"台江区",
"350104":"仓山区",
"350105":"马尾区",
"350111":"晋安区",
"350112":"长乐区",
"350121":"闽侯县",
"350122":"连江县",
"350123":"罗源县",
"350124":"闽清县",
"350125":"永泰县",
"350128":"平潭县",
"350181":"福清市",
"350203":"思明区",
"350205":"海沧区",
"350206":"湖里区",
"350211":"集美区",
"350212":"同安区",
"350213":"翔安区",
"350302":"城厢区",
"350303":"涵江区",
"350304":"荔城区",
"350305":"秀屿区",
"350322":"仙游县",
"350402":"梅列区",
"350403":"三元区",
"350421":"明溪县",
"350423":"清流县",
"350424":"宁化县",
"350425":"大田县",
"350426":"尤溪县",
"350427":"沙县",
"350428":"将乐县",
"350429":"泰宁县",
"350430":"建宁县",
"350481":"永安市",
"350502":"鲤城区",
"350503":"丰泽区",
"350504":"洛江区",
"350505":"泉港区",
"350521":"惠安县",
"350524":"安溪县",
"350525":"永春县",
"350526":"德化县",
"350527":"金门县",
"350581":"石狮市",
"350582":"晋江市",
"350583":"南安市",
"350602":"芗城区",
"350603":"龙文区",
"350622":"云霄县",
"350623":"漳浦县",
"350624":"诏安县",
"350625":"长泰县",
"350626":"东山县",
"350627":"南靖县",
"350628":"平和县",
"350629":"华安县",
"350681":"龙海市",
"350702":"延平区",
"350703":"建阳区",
"350721":"顺昌县",
"350722":"浦城县",
"350723":"光泽县",
"350724":"松溪县",
"350725":"政和县",
"350781":"邵武市",
"350782":"武夷山市",
"350783":"建瓯市",
"350802":"新罗区",
"350803":"永定区",
"350821":"长汀县",
"350823":"上杭县",
"350824":"武平县",
"350825":"连城县",
"350881":"漳平市",
"350902":"蕉城区",
"350921":"霞浦县",
"350922":"古田县",
"350923":"屏南县",
"350924":"寿宁县",
"350925":"周宁县",
"350926":"柘荣县",
"350981":"福安市",
"350982":"福鼎市",
"360102":"东湖区",
"360103":"西湖区",
"360104":"青云谱区",
"360105":"湾里区",
"360111":"青山湖区",
"360112":"新建区",
"360121":"南昌县",
"360123":"安义县",
"360124":"进贤县",
"360190":"经济技术开发区",
"360192":"高新区",
"360202":"昌江区",
"360203":"珠山区",
"360222":"浮梁县",
"360281":"乐平市",
"360302":"安源区",
"360313":"湘东区",
"360321":"莲花县",
"360322":"上栗县",
"360323":"芦溪县",
"360402":"濂溪区",
"360403":"浔阳区",
"360404":"柴桑区",
"360423":"武宁县",
"360424":"修水县",
"360425":"永修县",
"360426":"德安县",
"360428":"都昌县",
"360429":"湖口县",
"360430":"彭泽县",
"360481":"瑞昌市",
"360482":"共青城市",
"360483":"庐山市",
"360490":"经济技术开发区",
"360502":"渝水区",
"360521":"分宜县",
"360602":"月湖区",
"360603":"余江区",
"360681":"贵溪市",
"360702":"章贡区",
"360703":"南康区",
"360704":"赣县区",
"360722":"信丰县",
"360723":"大余县",
"360724":"上犹县",
"360725":"崇义县",
"360726":"安远县",
"360727":"龙南县",
"360728":"定南县",
"360729":"全南县",
"360730":"宁都县",
"360731":"于都县",
"360732":"兴国县",
"360733":"会昌县",
"360734":"寻乌县",
"360735":"石城县",
"360781":"瑞金市",
"360802":"吉州区",
"360803":"青原区",
"360821":"吉安县",
"360822":"吉水县",
"360823":"峡江县",
"360824":"新干县",
"360825":"永丰县",
"360826":"泰和县",
"360827":"遂川县",
"360828":"万安县",
"360829":"安福县",
"360830":"永新县",
"360881":"井冈山市",
"360902":"袁州区",
"360921":"奉新县",
"360922":"万载县",
"360923":"上高县",
"360924":"宜丰县",
"360925":"靖安县",
"360926":"铜鼓县",
"360981":"丰城市",
"360982":"樟树市",
"360983":"高安市",
"361002":"临川区",
"361003":"东乡区",
"361021":"南城县",
"361022":"黎川县",
"361023":"南丰县",
"361024":"崇仁县",
"361025":"乐安县",
"361026":"宜黄县",
"361027":"金溪县",
"361028":"资溪县",
"361030":"广昌县",
"361102":"信州区",
"361103":"广丰区",
"361121":"上饶县",
"361123":"玉山县",
"361124":"铅山县",
"361125":"横峰县",
"361126":"弋阳县",
"361127":"余干县",
"361128":"鄱阳县",
"361129":"万年县",
"361130":"婺源县",
"361181":"德兴市",
"370102":"历下区",
"370103":"市中区",
"370104":"槐荫区",
"370105":"天桥区",
"370112":"历城区",
"370113":"长清区",
"370114":"章丘区",
"370115":"济阳区",
"370116":"莱芜区",
"370117":"钢城区",
"370124":"平阴县",
"370126":"商河县",
"370190":"高新区",
"370202":"市南区",
"370203":"市北区",
"370211":"黄岛区",
"370212":"崂山区",
"370213":"李沧区",
"370214":"城阳区",
"370215":"即墨区",
"370281":"胶州市",
"370283":"平度市",
"370285":"莱西市",
"370290":"开发区",
"370302":"淄川区",
"370303":"张店区",
"370304":"博山区",
"370305":"临淄区",
"370306":"周村区",
"370321":"桓台县",
"370322":"高青县",
"370323":"沂源县",
"370402":"市中区",
"370403":"薛城区",
"370404":"峄城区",
"370405":"台儿庄区",
"370406":"山亭区",
"370481":"滕州市",
"370502":"东营区",
"370503":"河口区",
"370505":"垦利区",
"370522":"利津县",
"370523":"广饶县",
"370602":"芝罘区",
"370611":"福山区",
"370612":"牟平区",
"370613":"莱山区",
"370634":"长岛县",
"370681":"龙口市",
"370682":"莱阳市",
"370683":"莱州市",
"370684":"蓬莱市",
"370685":"招远市",
"370686":"栖霞市",
"370687":"海阳市",
"370690":"开发区",
"370702":"潍城区",
"370703":"寒亭区",
"370704":"坊子区",
"370705":"奎文区",
"370724":"临朐县",
"370725":"昌乐县",
"370781":"青州市",
"370782":"诸城市",
"370783":"寿光市",
"370784":"安丘市",
"370785":"高密市",
"370786":"昌邑市",
"370790":"开发区",
"370791":"高新区",
"370811":"任城区",
"370812":"兖州区",
"370826":"微山县",
"370827":"鱼台县",
"370828":"金乡县",
"370829":"嘉祥县",
"370830":"汶上县",
"370831":"泗水县",
"370832":"梁山县",
"370881":"曲阜市",
"370883":"邹城市",
"370890":"高新区",
"370902":"泰山区",
"370911":"岱岳区",
"370921":"宁阳县",
"370923":"东平县",
"370982":"新泰市",
"370983":"肥城市",
"371002":"环翠区",
"371003":"文登区",
"371082":"荣成市",
"371083":"乳山市",
"371091":"经济技术开发区",
"371102":"东港区",
"371103":"岚山区",
"371121":"五莲县",
"371122":"莒县",
"371302":"兰山区",
"371311":"罗庄区",
"371312":"河东区",
"371321":"沂南县",
"371322":"郯城县",
"371323":"沂水县",
"371324":"兰陵县",
"371325":"费县",
"371326":"平邑县",
"371327":"莒南县",
"371328":"蒙阴县",
"371329":"临沭县",
"371402":"德城区",
"371403":"陵城区",
"371422":"宁津县",
"371423":"庆云县",
"371424":"临邑县",
"371425":"齐河县",
"371426":"平原县",
"371427":"夏津县",
"371428":"武城县",
"371481":"乐陵市",
"371482":"禹城市",
"371502":"东昌府区",
"371521":"阳谷县",
"371522":"莘县",
"371523":"茌平县",
"371524":"东阿县",
"371525":"冠县",
"371526":"高唐县",
"371581":"临清市",
"371602":"滨城区",
"371603":"沾化区",
"371621":"惠民县",
"371622":"阳信县",
"371623":"无棣县",
"371625":"博兴县",
"371681":"邹平市",
"371702":"牡丹区",
"371703":"定陶区",
"371721":"曹县",
"371722":"单县",
"371723":"成武县",
"371724":"巨野县",
"371725":"郓城县",
"371726":"鄄城县",
"371728":"东明县",
"410102":"中原区",
"410103":"二七区",
"410104":"管城回族区",
"410105":"金水区",
"410106":"上街区",
"410108":"惠济区",
"410122":"中牟县",
"410181":"巩义市",
"410182":"荥阳市",
"410183":"新密市",
"410184":"新郑市",
"410185":"登封市",
"410190":"高新技术开发区",
"410191":"经济技术开发区",
"410202":"龙亭区",
"410203":"顺河回族区",
"410204":"鼓楼区",
"410205":"禹王台区",
"410212":"祥符区",
"410221":"杞县",
"410222":"通许县",
"410223":"尉氏县",
"410225":"兰考县",
"410302":"老城区",
"410303":"西工区",
"410304":"瀍河回族区",
"410305":"涧西区",
"410306":"吉利区",
"410311":"洛龙区",
"410322":"孟津县",
"410323":"新安县",
"410324":"栾川县",
"410325":"嵩县",
"410326":"汝阳县",
"410327":"宜阳县",
"410328":"洛宁县",
"410329":"伊川县",
"410381":"偃师市",
"410402":"新华区",
"410403":"卫东区",
"410404":"石龙区",
"410411":"湛河区",
"410421":"宝丰县",
"410422":"叶县",
"410423":"鲁山县",
"410425":"郏县",
"410481":"舞钢市",
"410482":"汝州市",
"410502":"文峰区",
"410503":"北关区",
"410505":"殷都区",
"410506":"龙安区",
"410522":"安阳县",
"410523":"汤阴县",
"410526":"滑县",
"410527":"内黄县",
"410581":"林州市",
"410590":"开发区",
"410602":"鹤山区",
"410603":"山城区",
"410611":"淇滨区",
"410621":"浚县",
"410622":"淇县",
"410702":"红旗区",
"410703":"卫滨区",
"410704":"凤泉区",
"410711":"牧野区",
"410721":"新乡县",
"410724":"获嘉县",
"410725":"原阳县",
"410726":"延津县",
"410727":"封丘县",
"410728":"长垣县",
"410781":"卫辉市",
"410782":"辉县市",
"410802":"解放区",
"410803":"中站区",
"410804":"马村区",
"410811":"山阳区",
"410821":"修武县",
"410822":"博爱县",
"410823":"武陟县",
"410825":"温县",
"410882":"沁阳市",
"410883":"孟州市",
"410902":"华龙区",
"410922":"清丰县",
"410923":"南乐县",
"410926":"范县",
"410927":"台前县",
"410928":"濮阳县",
"411002":"魏都区",
"411003":"建安区",
"411024":"鄢陵县",
"411025":"襄城县",
"411081":"禹州市",
"411082":"长葛市",
"411102":"源汇区",
"411103":"郾城区",
"411104":"召陵区",
"411121":"舞阳县",
"411122":"临颍县",
"411202":"湖滨区",
"411203":"陕州区",
"411221":"渑池县",
"411224":"卢氏县",
"411281":"义马市",
"411282":"灵宝市",
"411302":"宛城区",
"411303":"卧龙区",
"411321":"南召县",
"411322":"方城县",
"411323":"西峡县",
"411324":"镇平县",
"411325":"内乡县",
"411326":"淅川县",
"411327":"社旗县",
"411328":"唐河县",
"411329":"新野县",
"411330":"桐柏县",
"411381":"邓州市",
"411402":"梁园区",
"411403":"睢阳区",
"411421":"民权县",
"411422":"睢县",
"411423":"宁陵县",
"411424":"柘城县",
"411425":"虞城县",
"411426":"夏邑县",
"411481":"永城市",
"411502":"浉河区",
"411503":"平桥区",
"411521":"罗山县",
"411522":"光山县",
"411523":"新县",
"411524":"商城县",
"411525":"固始县",
"411526":"潢川县",
"411527":"淮滨县",
"411528":"息县",
"411602":"川汇区",
"411621":"扶沟县",
"411622":"西华县",
"411623":"商水县",
"411624":"沈丘县",
"411625":"郸城县",
"411626":"淮阳县",
"411627":"太康县",
"411628":"鹿邑县",
"411681":"项城市",
"411690":"经济开发区",
"411702":"驿城区",
"411721":"西平县",
"411722":"上蔡县",
"411723":"平舆县",
"411724":"正阳县",
"411725":"确山县",
"411726":"泌阳县",
"411727":"汝南县",
"411728":"遂平县",
"411729":"新蔡县",
"419001":"济源市",
"420102":"江岸区",
"420103":"江汉区",
"420104":"硚口区",
"420105":"汉阳区",
"420106":"武昌区",
"420107":"青山区",
"420111":"洪山区",
"420112":"东西湖区",
"420113":"汉南区",
"420114":"蔡甸区",
"420115":"江夏区",
"420116":"黄陂区",
"420117":"新洲区",
"420202":"黄石港区",
"420203":"西塞山区",
"420204":"下陆区",
"420205":"铁山区",
"420222":"阳新县",
"420281":"大冶市",
"420302":"茅箭区",
"420303":"张湾区",
"420304":"郧阳区",
"420322":"郧西县",
"420323":"竹山县",
"420324":"竹溪县",
"420325":"房县",
"420381":"丹江口市",
"420502":"西陵区",
"420503":"伍家岗区",
"420504":"点军区",
"420505":"猇亭区",
"420506":"夷陵区",
"420525":"远安县",
"420526":"兴山县",
"420527":"秭归县",
"420528":"长阳土家族自治县",
"420529":"五峰土家族自治县",
"420581":"宜都市",
"420582":"当阳市",
"420583":"枝江市",
"420590":"经济开发区",
"420602":"襄城区",
"420606":"樊城区",
"420607":"襄州区",
"420624":"南漳县",
"420625":"谷城县",
"420626":"保康县",
"420682":"老河口市",
"420683":"枣阳市",
"420684":"宜城市",
"420702":"梁子湖区",
"420703":"华容区",
"420704":"鄂城区",
"420802":"东宝区",
"420804":"掇刀区",
"420822":"沙洋县",
"420881":"钟祥市",
"420882":"京山市",
"420902":"孝南区",
"420921":"孝昌县",
"420922":"大悟县",
"420923":"云梦县",
"420981":"应城市",
"420982":"安陆市",
"420984":"汉川市",
"421002":"沙市区",
"421003":"荆州区",
"421022":"公安县",
"421023":"监利县",
"421024":"江陵县",
"421081":"石首市",
"421083":"洪湖市",
"421087":"松滋市",
"421102":"黄州区",
"421121":"团风县",
"421122":"红安县",
"421123":"罗田县",
"421124":"英山县",
"421125":"浠水县",
"421126":"蕲春县",
"421127":"黄梅县",
"421181":"麻城市",
"421182":"武穴市",
"421202":"咸安区",
"421221":"嘉鱼县",
"421222":"通城县",
"421223":"崇阳县",
"421224":"通山县",
"421281":"赤壁市",
"421303":"曾都区",
"421321":"随县",
"421381":"广水市",
"422801":"恩施市",
"422802":"利川市",
"422822":"建始县",
"422823":"巴东县",
"422825":"宣恩县",
"422826":"咸丰县",
"422827":"来凤县",
"422828":"鹤峰县",
"429004":"仙桃市",
"429005":"潜江市",
"429006":"天门市",
"429021":"神农架林区",
"430102":"芙蓉区",
"430103":"天心区",
"430104":"岳麓区",
"430105":"开福区",
"430111":"雨花区",
"430112":"望城区",
"430121":"长沙县",
"430181":"浏阳市",
"430182":"宁乡市",
"430202":"荷塘区",
"430203":"芦淞区",
"430204":"石峰区",
"430211":"天元区",
"430212":"渌口区",
"430223":"攸县",
"430224":"茶陵县",
"430225":"炎陵县",
"430281":"醴陵市",
"430302":"雨湖区",
"430304":"岳塘区",
"430321":"湘潭县",
"430381":"湘乡市",
"430382":"韶山市",
"430405":"珠晖区",
"430406":"雁峰区",
"430407":"石鼓区",
"430408":"蒸湘区",
"430412":"南岳区",
"430421":"衡阳县",
"430422":"衡南县",
"430423":"衡山县",
"430424":"衡东县",
"430426":"祁东县",
"430481":"耒阳市",
"430482":"常宁市",
"430502":"双清区",
"430503":"大祥区",
"430511":"北塔区",
"430521":"邵东县",
"430522":"新邵县",
"430523":"邵阳县",
"430524":"隆回县",
"430525":"洞口县",
"430527":"绥宁县",
"430528":"新宁县",
"430529":"城步苗族自治县",
"430581":"武冈市",
"430602":"岳阳楼区",
"430603":"云溪区",
"430611":"君山区",
"430621":"岳阳县",
"430623":"华容县",
"430624":"湘阴县",
"430626":"平江县",
"430681":"汨罗市",
"430682":"临湘市",
"430702":"武陵区",
"430703":"鼎城区",
"430721":"安乡县",
"430722":"汉寿县",
"430723":"澧县",
"430724":"临澧县",
"430725":"桃源县",
"430726":"石门县",
"430781":"津市市",
"430802":"永定区",
"430811":"武陵源区",
"430821":"慈利县",
"430822":"桑植县",
"430902":"资阳区",
"430903":"赫山区",
"430921":"南县",
"430922":"桃江县",
"430923":"安化县",
"430981":"沅江市",
"431002":"北湖区",
"431003":"苏仙区",
"431021":"桂阳县",
"431022":"宜章县",
"431023":"永兴县",
"431024":"嘉禾县",
"431025":"临武县",
"431026":"汝城县",
"431027":"桂东县",
"431028":"安仁县",
"431081":"资兴市",
"431102":"零陵区",
"431103":"冷水滩区",
"431121":"祁阳县",
"431122":"东安县",
"431123":"双牌县",
"431124":"道县",
"431125":"江永县",
"431126":"宁远县",
"431127":"蓝山县",
"431128":"新田县",
"431129":"江华瑶族自治县",
"431202":"鹤城区",
"431221":"中方县",
"431222":"沅陵县",
"431223":"辰溪县",
"431224":"溆浦县",
"431225":"会同县",
"431226":"麻阳苗族自治县",
"431227":"新晃侗族自治县",
"431228":"芷江侗族自治县",
"431229":"靖州苗族侗族自治县",
"431230":"通道侗族自治县",
"431281":"洪江市",
"431302":"娄星区",
"431321":"双峰县",
"431322":"新化县",
"431381":"冷水江市",
"431382":"涟源市",
"433101":"吉首市",
"433122":"泸溪县",
"433123":"凤凰县",
"433124":"花垣县",
"433125":"保靖县",
"433126":"古丈县",
"433127":"永顺县",
"433130":"龙山县",
"440103":"荔湾区",
"440104":"越秀区",
"440105":"海珠区",
"440106":"天河区",
"440111":"白云区",
"440112":"黄埔区",
"440113":"番禺区",
"440114":"花都区",
"440115":"南沙区",
"440117":"从化区",
"440118":"增城区",
"440203":"武江区",
"440204":"浈江区",
"440205":"曲江区",
"440222":"始兴县",
"440224":"仁化县",
"440229":"翁源县",
"440232":"乳源瑶族自治县",
"440233":"新丰县",
"440281":"乐昌市",
"440282":"南雄市",
"440303":"罗湖区",
"440304":"福田区",
"440305":"南山区",
"440306":"宝安区",
"440307":"龙岗区",
"440308":"盐田区",
"440309":"龙华区",
"440310":"坪山区",
"440311":"光明区",
"440402":"香洲区",
"440403":"斗门区",
"440404":"金湾区",
"440507":"龙湖区",
"440511":"金平区",
"440512":"濠江区",
"440513":"潮阳区",
"440514":"潮南区",
"440515":"澄海区",
"440523":"南澳县",
"440604":"禅城区",
"440605":"南海区",
"440606":"顺德区",
"440607":"三水区",
"440608":"高明区",
"440703":"蓬江区",
"440704":"江海区",
"440705":"新会区",
"440781":"台山市",
"440783":"开平市",
"440784":"鹤山市",
"440785":"恩平市",
"440802":"赤坎区",
"440803":"霞山区",
"440804":"坡头区",
"440811":"麻章区",
"440823":"遂溪县",
"440825":"徐闻县",
"440881":"廉江市",
"440882":"雷州市",
"440883":"吴川市",
"440890":"经济技术开发区",
"440902":"茂南区",
"440904":"电白区",
"440981":"高州市",
"440982":"化州市",
"440983":"信宜市",
"441202":"端州区",
"441203":"鼎湖区",
"441204":"高要区",
"441223":"广宁县",
"441224":"怀集县",
"441225":"封开县",
"441226":"德庆县",
"441284":"四会市",
"441302":"惠城区",
"441303":"惠阳区",
"441322":"博罗县",
"441323":"惠东县",
"441324":"龙门县",
"441402":"梅江区",
"441403":"梅县区",
"441422":"大埔县",
"441423":"丰顺县",
"441424":"五华县",
"441426":"平远县",
"441427":"蕉岭县",
"441481":"兴宁市",
"441502":"城区",
"441521":"海丰县",
"441523":"陆河县",
"441581":"陆丰市",
"441602":"源城区",
"441621":"紫金县",
"441622":"龙川县",
"441623":"连平县",
"441624":"和平县",
"441625":"东源县",
"441702":"江城区",
"441704":"阳东区",
"441721":"阳西县",
"441781":"阳春市",
"441802":"清城区",
"441803":"清新区",
"441821":"佛冈县",
"441823":"阳山县",
"441825":"连山壮族瑶族自治县",
"441826":"连南瑶族自治县",
"441881":"英德市",
"441882":"连州市",
"441901":"中堂镇",
"441903":"南城街道办事处",
"441904":"长安镇",
"441905":"东坑镇",
"441906":"樟木头镇",
"441907":"莞城街道办事处",
"441908":"石龙镇",
"441909":"桥头镇",
"441910":"万江街道办事处",
"441911":"麻涌镇",
"441912":"虎门镇",
"441913":"谢岗镇",
"441914":"石碣镇",
"441915":"茶山镇",
"441916":"东城街道办事处",
"441917":"洪梅镇",
"441918":"道滘镇",
"441919":"高埗镇",
"441920":"企石镇",
"441921":"凤岗镇",
"441922":"大岭山镇",
"441923":"松山湖管委会",
"441924":"清溪镇",
"441925":"望牛墩镇",
"441926":"厚街镇",
"441927":"常平镇",
"441928":"寮步镇",
"441929":"石排镇",
"441930":"横沥镇",
"441931":"塘厦镇",
"441932":"黄江镇",
"441933":"大朗镇",
"441934":"东莞港",
"441935":"东莞生态园",
"441990":"沙田镇",
"442001":"南头镇",
"442002":"神湾镇",
"442003":"东凤镇",
"442004":"五桂山街道办事处",
"442005":"黄圃镇",
"442006":"小榄镇",
"442007":"石岐区街道办事处",
"442008":"横栏镇",
"442009":"三角镇",
"442010":"三乡镇",
"442011":"港口镇",
"442012":"沙溪镇",
"442013":"板芙镇",
"442015":"东升镇",
"442016":"阜沙镇",
"442017":"民众镇",
"442018":"东区街道办事处",
"442019":"火炬开发区街道办事处",
"442020":"西区街道办事处",
"442021":"南区街道办事处",
"442022":"古镇镇",
"442023":"坦洲镇",
"442024":"大涌镇",
"442025":"南朗镇",
"445102":"湘桥区",
"445103":"潮安区",
"445122":"饶平县",
"445202":"榕城区",
"445203":"揭东区",
"445222":"揭西县",
"445224":"惠来县",
"445281":"普宁市",
"445302":"云城区",
"445303":"云安区",
"445321":"新兴县",
"445322":"郁南县",
"445381":"罗定市",
"450102":"兴宁区",
"450103":"青秀区",
"450105":"江南区",
"450107":"西乡塘区",
"450108":"良庆区",
"450109":"邕宁区",
"450110":"武鸣区",
"450123":"隆安县",
"450124":"马山县",
"450125":"上林县",
"450126":"宾阳县",
"450127":"横县",
"450202":"城中区",
"450203":"鱼峰区",
"450204":"柳南区",
"450205":"柳北区",
"450206":"柳江区",
"450222":"柳城县",
"450223":"鹿寨县",
"450224":"融安县",
"450225":"融水苗族自治县",
"450226":"三江侗族自治县",
"450302":"秀峰区",
"450303":"叠彩区",
"450304":"象山区",
"450305":"七星区",
"450311":"雁山区",
"450312":"临桂区",
"450321":"阳朔县",
"450323":"灵川县",
"450324":"全州县",
"450325":"兴安县",
"450326":"永福县",
"450327":"灌阳县",
"450328":"龙胜各族自治县",
"450329":"资源县",
"450330":"平乐县",
"450332":"恭城瑶族自治县",
"450381":"荔浦市",
"450403":"万秀区",
"450405":"长洲区",
"450406":"龙圩区",
"450421":"苍梧县",
"450422":"藤县",
"450423":"蒙山县",
"450481":"岑溪市",
"450502":"海城区",
"450503":"银海区",
"450512":"铁山港区",
"450521":"合浦县",
"450602":"港口区",
"450603":"防城区",
"450621":"上思县",
"450681":"东兴市",
"450702":"钦南区",
"450703":"钦北区",
"450721":"灵山县",
"450722":"浦北县",
"450802":"港北区",
"450803":"港南区",
"450804":"覃塘区",
"450821":"平南县",
"450881":"桂平市",
"450902":"玉州区",
"450903":"福绵区",
"450921":"容县",
"450922":"陆川县",
"450923":"博白县",
"450924":"兴业县",
"450981":"北流市",
"451002":"右江区",
"451021":"田阳县",
"451022":"田东县",
"451023":"平果县",
"451024":"德保县",
"451026":"那坡县",
"451027":"凌云县",
"451028":"乐业县",
"451029":"田林县",
"451030":"西林县",
"451031":"隆林各族自治县",
"451081":"靖西市",
"451102":"八步区",
"451103":"平桂区",
"451121":"昭平县",
"451122":"钟山县",
"451123":"富川瑶族自治县",
"451202":"金城江区",
"451203":"宜州区",
"451221":"南丹县",
"451222":"天峨县",
"451223":"凤山县",
"451224":"东兰县",
"451225":"罗城仫佬族自治县",
"451226":"环江毛南族自治县",
"451227":"巴马瑶族自治县",
"451228":"都安瑶族自治县",
"451229":"大化瑶族自治县",
"451302":"兴宾区",
"451321":"忻城县",
"451322":"象州县",
"451323":"武宣县",
"451324":"金秀瑶族自治县",
"451381":"合山市",
"451402":"江州区",
"451421":"扶绥县",
"451422":"宁明县",
"451423":"龙州县",
"451424":"大新县",
"451425":"天等县",
"451481":"凭祥市",
"460105":"秀英区",
"460106":"龙华区",
"460107":"琼山区",
"460108":"美兰区",
"460202":"海棠区",
"460203":"吉阳区",
"460204":"天涯区",
"460205":"崖州区",
"460321":"西沙群岛",
"460322":"南沙群岛",
"460323":"中沙群岛的岛礁及其海域",
"460401":"那大镇",
"460402":"和庆镇",
"460403":"南丰镇",
"460404":"大成镇",
"460405":"雅星镇",
"460406":"兰洋镇",
"460407":"光村镇",
"460408":"木棠镇",
"460409":"海头镇",
"460410":"峨蔓镇",
"460411":"王五镇",
"460412":"白马井镇",
"460413":"中和镇",
"460414":"排浦镇",
"460415":"东成镇",
"460416":"新州镇",
"460417":"洋浦经济开发区",
"460418":"华南热作学院",
"469001":"五指山市",
"469002":"琼海市",
"469005":"文昌市",
"469006":"万宁市",
"469007":"东方市",
"469021":"定安县",
"469022":"屯昌县",
"469023":"澄迈县",
"469024":"临高县",
"469025":"白沙黎族自治县",
"469026":"昌江黎族自治县",
"469027":"乐东黎族自治县",
"469028":"陵水黎族自治县",
"469029":"保亭黎族苗族自治县",
"469030":"琼中黎族苗族自治县",
"500101":"万州区",
"500102":"涪陵区",
"500103":"渝中区",
"500104":"大渡口区",
"500105":"江北区",
"500106":"沙坪坝区",
"500107":"九龙坡区",
"500108":"南岸区",
"500109":"北碚区",
"500110":"綦江区",
"500111":"大足区",
"500112":"渝北区",
"500113":"巴南区",
"500114":"黔江区",
"500115":"长寿区",
"500116":"江津区",
"500117":"合川区",
"500118":"永川区",
"500119":"南川区",
"500120":"璧山区",
"500151":"铜梁区",
"500152":"潼南区",
"500153":"荣昌区",
"500154":"开州区",
"500155":"梁平区",
"500156":"武隆区",
"500229":"城口县",
"500230":"丰都县",
"500231":"垫江县",
"500233":"忠县",
"500235":"云阳县",
"500236":"奉节县",
"500237":"巫山县",
"500238":"巫溪县",
"500240":"石柱土家族自治县",
"500241":"秀山土家族苗族自治县",
"500242":"酉阳土家族苗族自治县",
"500243":"彭水苗族土家族自治县",
"510104":"锦江区",
"510105":"青羊区",
"510106":"金牛区",
"510107":"武侯区",
"510108":"成华区",
"510112":"龙泉驿区",
"510113":"青白江区",
"510114":"新都区",
"510115":"温江区",
"510116":"双流区",
"510117":"郫都区",
"510121":"金堂县",
"510129":"大邑县",
"510131":"蒲江县",
"510132":"新津县",
"510181":"都江堰市",
"510182":"彭州市",
"510183":"邛崃市",
"510184":"崇州市",
"510185":"简阳市",
"510191":"高新区",
"510302":"自流井区",
"510303":"贡井区",
"510304":"大安区",
"510311":"沿滩区",
"510321":"荣县",
"510322":"富顺县",
"510402":"东区",
"510403":"西区",
"510411":"仁和区",
"510421":"米易县",
"510422":"盐边县",
"510502":"江阳区",
"510503":"纳溪区",
"510504":"龙马潭区",
"510521":"泸县",
"510522":"合江县",
"510524":"叙永县",
"510525":"古蔺县",
"510603":"旌阳区",
"510604":"罗江区",
"510623":"中江县",
"510681":"广汉市",
"510682":"什邡市",
"510683":"绵竹市",
"510703":"涪城区",
"510704":"游仙区",
"510705":"安州区",
"510722":"三台县",
"510723":"盐亭县",
"510725":"梓潼县",
"510726":"北川羌族自治县",
"510727":"平武县",
"510781":"江油市",
"510791":"高新区",
"510802":"利州区",
"510811":"昭化区",
"510812":"朝天区",
"510821":"旺苍县",
"510822":"青川县",
"510823":"剑阁县",
"510824":"苍溪县",
"510903":"船山区",
"510904":"安居区",
"510921":"蓬溪县",
"510922":"射洪县",
"510923":"大英县",
"511002":"市中区",
"511011":"东兴区",
"511024":"威远县",
"511025":"资中县",
"511083":"隆昌市",
"511102":"市中区",
"511111":"沙湾区",
"511112":"五通桥区",
"511113":"金口河区",
"511123":"犍为县",
"511124":"井研县",
"511126":"夹江县",
"511129":"沐川县",
"511132":"峨边彝族自治县",
"511133":"马边彝族自治县",
"511181":"峨眉山市",
"511302":"顺庆区",
"511303":"高坪区",
"511304":"嘉陵区",
"511321":"南部县",
"511322":"营山县",
"511323":"蓬安县",
"511324":"仪陇县",
"511325":"西充县",
"511381":"阆中市",
"511402":"东坡区",
"511403":"彭山区",
"511421":"仁寿县",
"511423":"洪雅县",
"511424":"丹棱县",
"511425":"青神县",
"511502":"翠屏区",
"511503":"南溪区",
"511504":"叙州区",
"511523":"江安县",
"511524":"长宁县",
"511525":"高县",
"511526":"珙县",
"511527":"筠连县",
"511528":"兴文县",
"511529":"屏山县",
"511602":"广安区",
"511603":"前锋区",
"511621":"岳池县",
"511622":"武胜县",
"511623":"邻水县",
"511681":"华蓥市",
"511702":"通川区",
"511703":"达川区",
"511722":"宣汉县",
"511723":"开江县",
"511724":"大竹县",
"511725":"渠县",
"511781":"万源市",
"511802":"雨城区",
"511803":"名山区",
"511822":"荥经县",
"511823":"汉源县",
"511824":"石棉县",
"511825":"天全县",
"511826":"芦山县",
"511827":"宝兴县",
"511902":"巴州区",
"511903":"恩阳区",
"511921":"通江县",
"511922":"南江县",
"511923":"平昌县",
"512002":"雁江区",
"512021":"安岳县",
"512022":"乐至县",
"513201":"马尔康市",
"513221":"汶川县",
"513222":"理县",
"513223":"茂县",
"513224":"松潘县",
"513225":"九寨沟县",
"513226":"金川县",
"513227":"小金县",
"513228":"黑水县",
"513230":"壤塘县",
"513231":"阿坝县",
"513232":"若尔盖县",
"513233":"红原县",
"513301":"康定市",
"513322":"泸定县",
"513323":"丹巴县",
"513324":"九龙县",
"513325":"雅江县",
"513326":"道孚县",
"513327":"炉霍县",
"513328":"甘孜县",
"513329":"新龙县",
"513330":"德格县",
"513331":"白玉县",
"513332":"石渠县",
"513333":"色达县",
"513334":"理塘县",
"513335":"巴塘县",
"513336":"乡城县",
"513337":"稻城县",
"513338":"得荣县",
"513401":"西昌市",
"513422":"木里藏族自治县",
"513423":"盐源县",
"513424":"德昌县",
"513425":"会理县",
"513426":"会东县",
"513427":"宁南县",
"513428":"普格县",
"513429":"布拖县",
"513430":"金阳县",
"513431":"昭觉县",
"513432":"喜德县",
"513433":"冕宁县",
"513434":"越西县",
"513435":"甘洛县",
"513436":"美姑县",
"513437":"雷波县",
"520102":"南明区",
"520103":"云岩区",
"520111":"花溪区",
"520112":"乌当区",
"520113":"白云区",
"520115":"观山湖区",
"520121":"开阳县",
"520122":"息烽县",
"520123":"修文县",
"520181":"清镇市",
"520201":"钟山区",
"520203":"六枝特区",
"520221":"水城县",
"520281":"盘州市",
"520302":"红花岗区",
"520303":"汇川区",
"520304":"播州区",
"520322":"桐梓县",
"520323":"绥阳县",
"520324":"正安县",
"520325":"道真仡佬族苗族自治县",
"520326":"务川仡佬族苗族自治县",
"520327":"凤冈县",
"520328":"湄潭县",
"520329":"余庆县",
"520330":"习水县",
"520381":"赤水市",
"520382":"仁怀市",
"520402":"西秀区",
"520403":"平坝区",
"520422":"普定县",
"520423":"镇宁布依族苗族自治县",
"520424":"关岭布依族苗族自治县",
"520425":"紫云苗族布依族自治县",
"520502":"七星关区",
"520521":"大方县",
"520522":"黔西县",
"520523":"金沙县",
"520524":"织金县",
"520525":"纳雍县",
"520526":"威宁彝族回族苗族自治县",
"520527":"赫章县",
"520602":"碧江区",
"520603":"万山区",
"520621":"江口县",
"520622":"玉屏侗族自治县",
"520623":"石阡县",
"520624":"思南县",
"520625":"印江土家族苗族自治县",
"520626":"德江县",
"520627":"沿河土家族自治县",
"520628":"松桃苗族自治县",
"522301":"兴义市",
"522302":"兴仁市",
"522323":"普安县",
"522324":"晴隆县",
"522325":"贞丰县",
"522326":"望谟县",
"522327":"册亨县",
"522328":"安龙县",
"522601":"凯里市",
"522622":"黄平县",
"522623":"施秉县",
"522624":"三穗县",
"522625":"镇远县",
"522626":"岑巩县",
"522627":"天柱县",
"522628":"锦屏县",
"522629":"剑河县",
"522630":"台江县",
"522631":"黎平县",
"522632":"榕江县",
"522633":"从江县",
"522634":"雷山县",
"522635":"麻江县",
"522636":"丹寨县",
"522701":"都匀市",
"522702":"福泉市",
"522722":"荔波县",
"522723":"贵定县",
"522725":"瓮安县",
"522726":"独山县",
"522727":"平塘县",
"522728":"罗甸县",
"522729":"长顺县",
"522730":"龙里县",
"522731":"惠水县",
"522732":"三都水族自治县",
"530102":"五华区",
"530103":"盘龙区",
"530111":"官渡区",
"530112":"西山区",
"530113":"东川区",
"530114":"呈贡区",
"530115":"晋宁区",
"530124":"富民县",
"530125":"宜良县",
"530126":"石林彝族自治县",
"530127":"嵩明县",
"530128":"禄劝彝族苗族自治县",
"530129":"寻甸回族彝族自治县",
"530181":"安宁市",
"530302":"麒麟区",
"530303":"沾益区",
"530304":"马龙区",
"530322":"陆良县",
"530323":"师宗县",
"530324":"罗平县",
"530325":"富源县",
"530326":"会泽县",
"530381":"宣威市",
"530402":"红塔区",
"530403":"江川区",
"530422":"澄江县",
"530423":"通海县",
"530424":"华宁县",
"530425":"易门县",
"530426":"峨山彝族自治县",
"530427":"新平彝族傣族自治县",
"530428":"元江哈尼族彝族傣族自治县",
"530502":"隆阳区",
"530521":"施甸县",
"530523":"龙陵县",
"530524":"昌宁县",
"530581":"腾冲市",
"530602":"昭阳区",
"530621":"鲁甸县",
"530622":"巧家县",
"530623":"盐津县",
"530624":"大关县",
"530625":"永善县",
"530626":"绥江县",
"530627":"镇雄县",
"530628":"彝良县",
"530629":"威信县",
"530681":"水富市",
"530702":"古城区",
"530721":"玉龙纳西族自治县",
"530722":"永胜县",
"530723":"华坪县",
"530724":"宁蒗彝族自治县",
"530802":"思茅区",
"530821":"宁洱哈尼族彝族自治县",
"530822":"墨江哈尼族自治县",
"530823":"景东彝族自治县",
"530824":"景谷傣族彝族自治县",
"530825":"镇沅彝族哈尼族拉祜族自治县",
"530826":"江城哈尼族彝族自治县",
"530827":"孟连傣族拉祜族佤族自治县",
"530828":"澜沧拉祜族自治县",
"530829":"西盟佤族自治县",
"530902":"临翔区",
"530921":"凤庆县",
"530922":"云县",
"530923":"永德县",
"530924":"镇康县",
"530925":"双江拉祜族佤族布朗族傣族自治县",
"530926":"耿马傣族佤族自治县",
"530927":"沧源佤族自治县",
"532301":"楚雄市",
"532322":"双柏县",
"532323":"牟定县",
"532324":"南华县",
"532325":"姚安县",
"532326":"大姚县",
"532327":"永仁县",
"532328":"元谋县",
"532329":"武定县",
"532331":"禄丰县",
"532501":"个旧市",
"532502":"开远市",
"532503":"蒙自市",
"532504":"弥勒市",
"532523":"屏边苗族自治县",
"532524":"建水县",
"532525":"石屏县",
"532527":"泸西县",
"532528":"元阳县",
"532529":"红河县",
"532530":"金平苗族瑶族傣族自治县",
"532531":"绿春县",
"532532":"河口瑶族自治县",
"532601":"文山市",
"532622":"砚山县",
"532623":"西畴县",
"532624":"麻栗坡县",
"532625":"马关县",
"532626":"丘北县",
"532627":"广南县",
"532628":"富宁县",
"532801":"景洪市",
"532822":"勐海县",
"532823":"勐腊县",
"532901":"大理市",
"532922":"漾濞彝族自治县",
"532923":"祥云县",
"532924":"宾川县",
"532925":"弥渡县",
"532926":"南涧彝族自治县",
"532927":"巍山彝族回族自治县",
"532928":"永平县",
"532929":"云龙县",
"532930":"洱源县",
"532931":"剑川县",
"532932":"鹤庆县",
"533102":"瑞丽市",
"533103":"芒市",
"533122":"梁河县",
"533123":"盈江县",
"533124":"陇川县",
"533301":"泸水市",
"533323":"福贡县",
"533324":"贡山独龙族怒族自治县",
"533325":"兰坪白族普米族自治县",
"533401":"香格里拉市",
"533422":"德钦县",
"533423":"维西傈僳族自治县",
"540102":"城关区",
"540103":"堆龙德庆区",
"540104":"达孜区",
"540121":"林周县",
"540122":"当雄县",
"540123":"尼木县",
"540124":"曲水县",
"540127":"墨竹工卡县",
"540202":"桑珠孜区",
"540221":"南木林县",
"540222":"江孜县",
"540223":"定日县",
"540224":"萨迦县",
"540225":"拉孜县",
"540226":"昂仁县",
"540227":"谢通门县",
"540228":"白朗县",
"540229":"仁布县",
"540230":"康马县",
"540231":"定结县",
"540232":"仲巴县",
"540233":"亚东县",
"540234":"吉隆县",
"540235":"聂拉木县",
"540236":"萨嘎县",
"540237":"岗巴县",
"540302":"卡若区",
"540321":"江达县",
"540322":"贡觉县",
"540323":"类乌齐县",
"540324":"丁青县",
"540325":"察雅县",
"540326":"八宿县",
"540327":"左贡县",
"540328":"芒康县",
"540329":"洛隆县",
"540330":"边坝县",
"540402":"巴宜区",
"540421":"工布江达县",
"540422":"米林县",
"540423":"墨脱县",
"540424":"波密县",
"540425":"察隅县",
"540426":"朗县",
"540502":"乃东区",
"540521":"扎囊县",
"540522":"贡嘎县",
"540523":"桑日县",
"540524":"琼结县",
"540525":"曲松县",
"540526":"措美县",
"540527":"洛扎县",
"540528":"加查县",
"540529":"隆子县",
"540530":"错那县",
"540531":"浪卡子县",
"540602":"色尼区",
"540621":"嘉黎县",
"540622":"比如县",
"540623":"聂荣县",
"540624":"安多县",
"540625":"申扎县",
"540626":"索县",
"540627":"班戈县",
"540628":"巴青县",
"540629":"尼玛县",
"540630":"双湖县",
"542521":"普兰县",
"542522":"札达县",
"542523":"噶尔县",
"542524":"日土县",
"542525":"革吉县",
"542526":"改则县",
"542527":"措勤县",
"610102":"新城区",
"610103":"碑林区",
"610104":"莲湖区",
"610111":"灞桥区",
"610112":"未央区",
"610113":"雁塔区",
"610114":"阎良区",
"610115":"临潼区",
"610116":"长安区",
"610117":"高陵区",
"610118":"鄠邑区",
"610122":"蓝田县",
"610124":"周至县",
"610202":"王益区",
"610203":"印台区",
"610204":"耀州区",
"610222":"宜君县",
"610302":"渭滨区",
"610303":"金台区",
"610304":"陈仓区",
"610322":"凤翔县",
"610323":"岐山县",
"610324":"扶风县",
"610326":"眉县",
"610327":"陇县",
"610328":"千阳县",
"610329":"麟游县",
"610330":"凤县",
"610331":"太白县",
"610402":"秦都区",
"610403":"杨陵区",
"610404":"渭城区",
"610422":"三原县",
"610423":"泾阳县",
"610424":"乾县",
"610425":"礼泉县",
"610426":"永寿县",
"610428":"长武县",
"610429":"旬邑县",
"610430":"淳化县",
"610431":"武功县",
"610481":"兴平市",
"610482":"彬州市",
"610502":"临渭区",
"610503":"华州区",
"610522":"潼关县",
"610523":"大荔县",
"610524":"合阳县",
"610525":"澄城县",
"610526":"蒲城县",
"610527":"白水县",
"610528":"富平县",
"610581":"韩城市",
"610582":"华阴市",
"610602":"宝塔区",
"610603":"安塞区",
"610621":"延长县",
"610622":"延川县",
"610623":"子长县",
"610625":"志丹县",
"610626":"吴起县",
"610627":"甘泉县",
"610628":"富县",
"610629":"洛川县",
"610630":"宜川县",
"610631":"黄龙县",
"610632":"黄陵县",
"610702":"汉台区",
"610703":"南郑区",
"610722":"城固县",
"610723":"洋县",
"610724":"西乡县",
"610725":"勉县",
"610726":"宁强县",
"610727":"略阳县",
"610728":"镇巴县",
"610729":"留坝县",
"610730":"佛坪县",
"610802":"榆阳区",
"610803":"横山区",
"610822":"府谷县",
"610824":"靖边县",
"610825":"定边县",
"610826":"绥德县",
"610827":"米脂县",
"610828":"佳县",
"610829":"吴堡县",
"610830":"清涧县",
"610831":"子洲县",
"610881":"神木市",
"610902":"汉滨区",
"610921":"汉阴县",
"610922":"石泉县",
"610923":"宁陕县",
"610924":"紫阳县",
"610925":"岚皋县",
"610926":"平利县",
"610927":"镇坪县",
"610928":"旬阳县",
"610929":"白河县",
"611002":"商州区",
"611021":"洛南县",
"611022":"丹凤县",
"611023":"商南县",
"611024":"山阳县",
"611025":"镇安县",
"611026":"柞水县",
"620102":"城关区",
"620103":"七里河区",
"620104":"西固区",
"620105":"安宁区",
"620111":"红古区",
"620121":"永登县",
"620122":"皋兰县",
"620123":"榆中县",
"620201":"市辖区",
"620290":"雄关区",
"620291":"长城区",
"620292":"镜铁区",
"620293":"新城镇",
"620294":"峪泉镇",
"620295":"文殊镇",
"620302":"金川区",
"620321":"永昌县",
"620402":"白银区",
"620403":"平川区",
"620421":"靖远县",
"620422":"会宁县",
"620423":"景泰县",
"620502":"秦州区",
"620503":"麦积区",
"620521":"清水县",
"620522":"秦安县",
"620523":"甘谷县",
"620524":"武山县",
"620525":"张家川回族自治县",
"620602":"凉州区",
"620621":"民勤县",
"620622":"古浪县",
"620623":"天祝藏族自治县",
"620702":"甘州区",
"620721":"肃南裕固族自治县",
"620722":"民乐县",
"620723":"临泽县",
"620724":"高台县",
"620725":"山丹县",
"620802":"崆峒区",
"620821":"泾川县",
"620822":"灵台县",
"620823":"崇信县",
"620825":"庄浪县",
"620826":"静宁县",
"620881":"华亭市",
"620902":"肃州区",
"620921":"金塔县",
"620922":"瓜州县",
"620923":"肃北蒙古族自治县",
"620924":"阿克塞哈萨克族自治县",
"620981":"玉门市",
"620982":"敦煌市",
"621002":"西峰区",
"621021":"庆城县",
"621022":"环县",
"621023":"华池县",
"621024":"合水县",
"621025":"正宁县",
"621026":"宁县",
"621027":"镇原县",
"621102":"安定区",
"621121":"通渭县",
"621122":"陇西县",
"621123":"渭源县",
"621124":"临洮县",
"621125":"漳县",
"621126":"岷县",
"621202":"武都区",
"621221":"成县",
"621222":"文县",
"621223":"宕昌县",
"621224":"康县",
"621225":"西和县",
"621226":"礼县",
"621227":"徽县",
"621228":"两当县",
"622901":"临夏市",
"622921":"临夏县",
"622922":"康乐县",
"622923":"永靖县",
"622924":"广河县",
"622925":"和政县",
"622926":"东乡族自治县",
"622927":"积石山保安族东乡族撒拉族自治县",
"623001":"合作市",
"623021":"临潭县",
"623022":"卓尼县",
"623023":"舟曲县",
"623024":"迭部县",
"623025":"玛曲县",
"623026":"碌曲县",
"623027":"夏河县",
"630102":"城东区",
"630103":"城中区",
"630104":"城西区",
"630105":"城北区",
"630121":"大通回族土族自治县",
"630122":"湟中县",
"630123":"湟源县",
"630202":"乐都区",
"630203":"平安区",
"630222":"民和回族土族自治县",
"630223":"互助土族自治县",
"630224":"化隆回族自治县",
"630225":"循化撒拉族自治县",
"632221":"门源回族自治县",
"632222":"祁连县",
"632223":"海晏县",
"632224":"刚察县",
"632321":"同仁县",
"632322":"尖扎县",
"632323":"泽库县",
"632324":"河南蒙古族自治县",
"632521":"共和县",
"632522":"同德县",
"632523":"贵德县",
"632524":"兴海县",
"632525":"贵南县",
"632621":"玛沁县",
"632622":"班玛县",
"632623":"甘德县",
"632624":"达日县",
"632625":"久治县",
"632626":"玛多县",
"632701":"玉树市",
"632722":"杂多县",
"632723":"称多县",
"632724":"治多县",
"632725":"囊谦县",
"632726":"曲麻莱县",
"632801":"格尔木市",
"632802":"德令哈市",
"632803":"茫崖市",
"632821":"乌兰县",
"632822":"都兰县",
"632823":"天峻县",
"640104":"兴庆区",
"640105":"西夏区",
"640106":"金凤区",
"640121":"永宁县",
"640122":"贺兰县",
"640181":"灵武市",
"640202":"大武口区",
"640205":"惠农区",
"640221":"平罗县",
"640302":"利通区",
"640303":"红寺堡区",
"640323":"盐池县",
"640324":"同心县",
"640381":"青铜峡市",
"640402":"原州区",
"640422":"西吉县",
"640423":"隆德县",
"640424":"泾源县",
"640425":"彭阳县",
"640502":"沙坡头区",
"640521":"中宁县",
"640522":"海原县",
"650102":"天山区",
"650103":"沙依巴克区",
"650104":"新市区",
"650105":"水磨沟区",
"650106":"头屯河区",
"650107":"达坂城区",
"650109":"米东区",
"650121":"乌鲁木齐县",
"650202":"独山子区",
"650203":"克拉玛依区",
"650204":"白碱滩区",
"650205":"乌尔禾区",
"650402":"高昌区",
"650421":"鄯善县",
"650422":"托克逊县",
"650502":"伊州区",
"650521":"巴里坤哈萨克自治县",
"650522":"伊吾县",
"652301":"昌吉市",
"652302":"阜康市",
"652323":"呼图壁县",
"652324":"玛纳斯县",
"652325":"奇台县",
"652327":"吉木萨尔县",
"652328":"木垒哈萨克自治县",
"652701":"博乐市",
"652702":"阿拉山口市",
"652722":"精河县",
"652723":"温泉县",
"652801":"库尔勒市",
"652822":"轮台县",
"652823":"尉犁县",
"652824":"若羌县",
"652825":"且末县",
"652826":"焉耆回族自治县",
"652827":"和静县",
"652828":"和硕县",
"652829":"博湖县",
"652901":"阿克苏市",
"652922":"温宿县",
"652923":"库车县",
"652924":"沙雅县",
"652925":"新和县",
"652926":"拜城县",
"652927":"乌什县",
"652928":"阿瓦提县",
"652929":"柯坪县",
"653001":"阿图什市",
"653022":"阿克陶县",
"653023":"阿合奇县",
"653024":"乌恰县",
"653101":"喀什市",
"653121":"疏附县",
"653122":"疏勒县",
"653123":"英吉沙县",
"653124":"泽普县",
"653125":"莎车县",
"653126":"叶城县",
"653127":"麦盖提县",
"653128":"岳普湖县",
"653129":"伽师县",
"653130":"巴楚县",
"653131":"塔什库尔干塔吉克自治县",
"653201":"和田市",
"653221":"和田县",
"653222":"墨玉县",
"653223":"皮山县",
"653224":"洛浦县",
"653225":"策勒县",
"653226":"于田县",
"653227":"民丰县",
"654002":"伊宁市",
"654003":"奎屯市",
"654004":"霍尔果斯市",
"654021":"伊宁县",
"654022":"察布查尔锡伯自治县",
"654023":"霍城县",
"654024":"巩留县",
"654025":"新源县",
"654026":"昭苏县",
"654027":"特克斯县",
"654028":"尼勒克县",
"654201":"塔城市",
"654202":"乌苏市",
"654221":"额敏县",
"654223":"沙湾县",
"654224":"托里县",
"654225":"裕民县",
"654226":"和布克赛尔蒙古自治县",
"654301":"阿勒泰市",
"654321":"布尔津县",
"654322":"富蕴县",
"654323":"福海县",
"654324":"哈巴河县",
"654325":"青河县",
"654326":"吉木乃县",
"659001":"石河子市",
"659002":"阿拉尔市",
"659003":"图木舒克市",
"659004":"五家渠市",
"659005":"北屯市",
"659006":"铁门关市",
"659007":"双河市",
"659008":"可克达拉市",
"659009":"昆玉市",
"710101":"中正区",
"710102":"大同区",
"710103":"中山区",
"710104":"松山区",
"710105":"大安区",
"710106":"万华区",
"710107":"信义区",
"710108":"士林区",
"710109":"北投区",
"710110":"内湖区",
"710111":"南港区",
"710112":"文山区",
"710199":"其它区",
"710201":"新兴区",
"710202":"前金区",
"710203":"芩雅区",
"710204":"盐埕区",
"710205":"鼓山区",
"710206":"旗津区",
"710207":"前镇区",
"710208":"三民区",
"710209":"左营区",
"710210":"楠梓区",
"710211":"小港区",
"710241":"苓雅区",
"710242":"仁武区",
"710243":"大社区",
"710244":"冈山区",
"710245":"路竹区",
"710246":"阿莲区",
"710247":"田寮区",
"710248":"燕巢区",
"710249":"桥头区",
"710250":"梓官区",
"710251":"弥陀区",
"710252":"永安区",
"710253":"湖内区",
"710254":"凤山区",
"710255":"大寮区",
"710256":"林园区",
"710257":"鸟松区",
"710258":"大树区",
"710259":"旗山区",
"710260":"美浓区",
"710261":"六龟区",
"710262":"内门区",
"710263":"杉林区",
"710264":"甲仙区",
"710265":"桃源区",
"710266":"那玛夏区",
"710267":"茂林区",
"710268":"茄萣区",
"710299":"其它区",
"710301":"中西区",
"710302":"东区",
"710303":"南区",
"710304":"北区",
"710305":"安平区",
"710306":"安南区",
"710339":"永康区",
"710340":"归仁区",
"710341":"新化区",
"710342":"左镇区",
"710343":"玉井区",
"710344":"楠西区",
"710345":"南化区",
"710346":"仁德区",
"710347":"关庙区",
"710348":"龙崎区",
"710349":"官田区",
"710350":"麻豆区",
"710351":"佳里区",
"710352":"西港区",
"710353":"七股区",
"710354":"将军区",
"710355":"学甲区",
"710356":"北门区",
"710357":"新营区",
"710358":"后壁区",
"710359":"白河区",
"710360":"东山区",
"710361":"六甲区",
"710362":"下营区",
"710363":"柳营区",
"710364":"盐水区",
"710365":"善化区",
"710366":"大内区",
"710367":"山上区",
"710368":"新市区",
"710369":"安定区",
"710399":"其它区",
"710401":"中区",
"710402":"东区",
"710403":"南区",
"710404":"西区",
"710405":"北区",
"710406":"北屯区",
"710407":"西屯区",
"710408":"南屯区",
"710431":"太平区",
"710432":"大里区",
"710433":"雾峰区",
"710434":"乌日区",
"710435":"丰原区",
"710436":"后里区",
"710437":"石冈区",
"710438":"东势区",
"710439":"和平区",
"710440":"新社区",
"710441":"潭子区",
"710442":"大雅区",
"710443":"神冈区",
"710444":"大肚区",
"710445":"沙鹿区",
"710446":"龙井区",
"710447":"梧栖区",
"710448":"清水区",
"710449":"大甲区",
"710450":"外埔区",
"710451":"大安区",
"710499":"其它区",
"710507":"金沙镇",
"710508":"金湖镇",
"710509":"金宁乡",
"710510":"金城镇",
"710511":"烈屿乡",
"710512":"乌坵乡",
"710614":"南投市",
"710615":"中寮乡",
"710616":"草屯镇",
"710617":"国姓乡",
"710618":"埔里镇",
"710619":"仁爱乡",
"710620":"名间乡",
"710621":"集集镇",
"710622":"水里乡",
"710623":"鱼池乡",
"710624":"信义乡",
"710625":"竹山镇",
"710626":"鹿谷乡",
"710701":"仁爱区",
"710702":"信义区",
"710703":"中正区",
"710704":"中山区",
"710705":"安乐区",
"710706":"暖暖区",
"710707":"七堵区",
"710799":"其它区",
"710801":"东区",
"710802":"北区",
"710803":"香山区",
"710899":"其它区",
"710901":"东区",
"710902":"西区",
"710999":"其它区",
"711130":"万里区",
"711132":"板桥区",
"711133":"汐止区",
"711134":"深坑区",
"711135":"石碇区",
"711136":"瑞芳区",
"711137":"平溪区",
"711138":"双溪区",
"711139":"贡寮区",
"711140":"新店区",
"711141":"坪林区",
"711142":"乌来区",
"711143":"永和区",
"711144":"中和区",
"711145":"土城区",
"711146":"三峡区",
"711147":"树林区",
"711148":"莺歌区",
"711149":"三重区",
"711150":"新庄区",
"711151":"泰山区",
"711152":"林口区",
"711153":"芦洲区",
"711154":"五股区",
"711155":"八里区",
"711156":"淡水区",
"711157":"三芝区",
"711158":"石门区",
"711287":"宜兰市",
"711288":"头城镇",
"711289":"礁溪乡",
"711290":"壮围乡",
"711291":"员山乡",
"711292":"罗东镇",
"711293":"三星乡",
"711294":"大同乡",
"711295":"五结乡",
"711296":"冬山乡",
"711297":"苏澳镇",
"711298":"南澳乡",
"711299":"钓鱼台",
"711387":"竹北市",
"711388":"湖口乡",
"711389":"新丰乡",
"711390":"新埔镇",
"711391":"关西镇",
"711392":"芎林乡",
"711393":"宝山乡",
"711394":"竹东镇",
"711395":"五峰乡",
"711396":"横山乡",
"711397":"尖石乡",
"711398":"北埔乡",
"711399":"峨眉乡",
"711414":"中坜区",
"711415":"平镇区",
"711417":"杨梅区",
"711418":"新屋区",
"711419":"观音区",
"711420":"桃园区",
"711421":"龟山区",
"711422":"八德区",
"711423":"大溪区",
"711425":"大园区",
"711426":"芦竹区",
"711487":"中坜市",
"711488":"平镇市",
"711489":"龙潭乡",
"711490":"杨梅市",
"711491":"新屋乡",
"711492":"观音乡",
"711493":"桃园市",
"711494":"龟山乡",
"711495":"八德市",
"711496":"大溪镇",
"711497":"复兴乡",
"711498":"大园乡",
"711499":"芦竹乡",
"711520":"头份市",
"711582":"竹南镇",
"711583":"头份镇",
"711584":"三湾乡",
"711585":"南庄乡",
"711586":"狮潭乡",
"711587":"后龙镇",
"711588":"通霄镇",
"711589":"苑里镇",
"711590":"苗栗市",
"711591":"造桥乡",
"711592":"头屋乡",
"711593":"公馆乡",
"711594":"大湖乡",
"711595":"泰安乡",
"711596":"铜锣乡",
"711597":"三义乡",
"711598":"西湖乡",
"711599":"卓兰镇",
"711736":"员林市",
"711774":"彰化市",
"711775":"芬园乡",
"711776":"花坛乡",
"711777":"秀水乡",
"711778":"鹿港镇",
"711779":"福兴乡",
"711780":"线西乡",
"711781":"和美镇",
"711782":"伸港乡",
"711783":"员林镇",
"711784":"社头乡",
"711785":"永靖乡",
"711786":"埔心乡",
"711787":"溪湖镇",
"711788":"大村乡",
"711789":"埔盐乡",
"711790":"田中镇",
"711791":"北斗镇",
"711792":"田尾乡",
"711793":"埤头乡",
"711794":"溪州乡",
"711795":"竹塘乡",
"711796":"二林镇",
"711797":"大城乡",
"711798":"芳苑乡",
"711799":"二水乡",
"711982":"番路乡",
"711983":"梅山乡",
"711984":"竹崎乡",
"711985":"阿里山乡",
"711986":"中埔乡",
"711987":"大埔乡",
"711988":"水上乡",
"711989":"鹿草乡",
"711990":"太保市",
"711991":"朴子市",
"711992":"东石乡",
"711993":"六脚乡",
"711994":"新港乡",
"711995":"民雄乡",
"711996":"大林镇",
"711997":"溪口乡",
"711998":"义竹乡",
"711999":"布袋镇",
"712180":"斗南镇",
"712181":"大埤乡",
"712182":"虎尾镇",
"712183":"土库镇",
"712184":"褒忠乡",
"712185":"东势乡",
"712186":"台西乡",
"712187":"仑背乡",
"712188":"麦寮乡",
"712189":"斗六市",
"712190":"林内乡",
"712191":"古坑乡",
"712192":"莿桐乡",
"712193":"西螺镇",
"712194":"二仑乡",
"712195":"北港镇",
"712196":"水林乡",
"712197":"口湖乡",
"712198":"四湖乡",
"712199":"元长乡",
"712451":"崁顶乡",
"712467":"屏东市",
"712468":"三地门乡",
"712469":"雾台乡",
"712470":"玛家乡",
"712471":"九如乡",
"712472":"里港乡",
"712473":"高树乡",
"712474":"盐埔乡",
"712475":"长治乡",
"712476":"麟洛乡",
"712477":"竹田乡",
"712478":"内埔乡",
"712479":"万丹乡",
"712480":"潮州镇",
"712481":"泰武乡",
"712482":"来义乡",
"712483":"万峦乡",
"712484":"莰顶乡",
"712485":"新埤乡",
"712486":"南州乡",
"712487":"林边乡",
"712488":"东港镇",
"712489":"琉球乡",
"712490":"佳冬乡",
"712491":"新园乡",
"712492":"枋寮乡",
"712493":"枋山乡",
"712494":"春日乡",
"712495":"狮子乡",
"712496":"车城乡",
"712497":"牡丹乡",
"712498":"恒春镇",
"712499":"满州乡",
"712584":"台东市",
"712585":"绿岛乡",
"712586":"兰屿乡",
"712587":"延平乡",
"712588":"卑南乡",
"712589":"鹿野乡",
"712590":"关山镇",
"712591":"海端乡",
"712592":"池上乡",
"712593":"东河乡",
"712594":"成功镇",
"712595":"长滨乡",
"712596":"金峰乡",
"712597":"大武乡",
"712598":"达仁乡",
"712599":"太麻里乡",
"712686":"花莲市",
"712687":"新城乡",
"712688":"太鲁阁",
"712689":"秀林乡",
"712690":"吉安乡",
"712691":"寿丰乡",
"712692":"凤林镇",
"712693":"光复乡",
"712694":"丰滨乡",
"712695":"瑞穗乡",
"712696":"万荣乡",
"712697":"玉里镇",
"712698":"卓溪乡",
"712699":"富里乡",
"712794":"马公市",
"712795":"西屿乡",
"712796":"望安乡",
"712797":"七美乡",
"712798":"白沙乡",
"712799":"湖西乡",
"712896":"南竿乡",
"712897":"北竿乡",
"712898":"东引乡",
"712899":"莒光乡",
"810101":"中西区",
"810102":"湾仔区",
"810103":"东区",
"810104":"南区",
"810201":"九龙城区",
"810202":"油尖旺区",
"810203":"深水埗区",
"810204":"黄大仙区",
"810205":"观塘区",
"810301":"北区",
"810302":"大埔区",
"810303":"沙田区",
"810304":"西贡区",
"810305":"元朗区",
"810306":"屯门区",
"810307":"荃湾区",
"810308":"葵青区",
"810309":"离岛区",
"820101":"澳门半岛",
"820201":"离岛"
}
}
================================================
FILE: example/functions/foo/index.js
================================================
// 这是一个测试用的云函数
const cloud = require('wx-server-sdk');
cloud.init();
// 云函数入口函数
exports.main = async event => {
const wxContext = cloud.getWXContext();
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID
};
};
================================================
FILE: example/functions/foo/package.json
================================================
{
"name": "foo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"wx-server-sdk": "latest"
}
}
================================================
FILE: example/pages/action-sheet/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/action-sheet/index.json
================================================
{
"navigationBarTitleText": "ActionSheet 动作面板"
}
================================================
FILE: example/pages/action-sheet/index.wxml
================================================
================================================
FILE: example/pages/area/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/area/index.json
================================================
{
"navigationBarTitleText": "Area 省市区选择"
}
================================================
FILE: example/pages/area/index.wxml
================================================
================================================
FILE: example/pages/button/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/button/index.json
================================================
{
"navigationBarTitleText": "Button 按钮"
}
================================================
FILE: example/pages/button/index.wxml
================================================
================================================
FILE: example/pages/calendar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/calendar/index.json
================================================
{
"navigationBarTitleText": "Calendar 日历"
}
================================================
FILE: example/pages/calendar/index.wxml
================================================
================================================
FILE: example/pages/card/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/card/index.json
================================================
{
"navigationBarTitleText": "Card 商品卡片"
}
================================================
FILE: example/pages/card/index.wxml
================================================
================================================
FILE: example/pages/cascader/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/cascader/index.json
================================================
{
"navigationBarTitleText": "Cascader 级联选择"
}
================================================
FILE: example/pages/cascader/index.wxml
================================================
================================================
FILE: example/pages/cell/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/cell/index.json
================================================
{
"navigationBarTitleText": "Cell 单元格"
}
================================================
FILE: example/pages/cell/index.wxml
================================================
================================================
FILE: example/pages/checkbox/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/checkbox/index.json
================================================
{
"navigationBarTitleText": "Checkbox 复选框"
}
================================================
FILE: example/pages/checkbox/index.wxml
================================================
================================================
FILE: example/pages/circle/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/circle/index.json
================================================
{
"navigationBarTitleText": "Circle 进度条"
}
================================================
FILE: example/pages/circle/index.wxml
================================================
================================================
FILE: example/pages/col/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/col/index.json
================================================
{
"navigationBarTitleText": "Layout 布局"
}
================================================
FILE: example/pages/col/index.wxml
================================================
================================================
FILE: example/pages/collapse/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/collapse/index.json
================================================
{
"navigationBarTitleText": "Collapse 折叠面板"
}
================================================
FILE: example/pages/collapse/index.wxml
================================================
================================================
FILE: example/pages/config-provider/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/config-provider/index.json
================================================
{
"navigationBarTitleText": "ConfigProvider 全局配置"
}
================================================
FILE: example/pages/config-provider/index.wxml
================================================
================================================
FILE: example/pages/count-down/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/count-down/index.json
================================================
{
"navigationBarTitleText": "CountDown 倒计时"
}
================================================
FILE: example/pages/count-down/index.wxml
================================================
================================================
FILE: example/pages/dashboard/index.js
================================================
import list from '../../config';
import Page from '../../common/page';
Page({
data: {
list,
},
});
================================================
FILE: example/pages/dashboard/index.json
================================================
{
"navigationBarTitleText": "Vant Weapp",
"usingComponents": {
"demo-home": "../../components/demo-home/index"
}
}
================================================
FILE: example/pages/dashboard/index.wxml
================================================
================================================
FILE: example/pages/datetime-picker/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/datetime-picker/index.json
================================================
{
"navigationBarTitleText": "DatetimePicker 时间选择"
}
================================================
FILE: example/pages/datetime-picker/index.wxml
================================================
================================================
FILE: example/pages/dialog/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/dialog/index.json
================================================
{
"navigationBarTitleText": "Dialog 弹出框"
}
================================================
FILE: example/pages/dialog/index.wxml
================================================
================================================
FILE: example/pages/divider/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/divider/index.json
================================================
{
"navigationBarTitleText": "Divider 分割线"
}
================================================
FILE: example/pages/divider/index.wxml
================================================
================================================
FILE: example/pages/dropdown-menu/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/dropdown-menu/index.json
================================================
{
"navigationBarTitleText": "Dropdown Menu"
}
================================================
FILE: example/pages/dropdown-menu/index.wxml
================================================
================================================
FILE: example/pages/empty/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/empty/index.json
================================================
{
"navigationBarTitleText": "Empty 空状态"
}
================================================
FILE: example/pages/empty/index.wxml
================================================
================================================
FILE: example/pages/field/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/field/index.json
================================================
{
"navigationBarTitleText": "Field 输入框"
}
================================================
FILE: example/pages/field/index.wxml
================================================
================================================
FILE: example/pages/goods-action/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/goods-action/index.json
================================================
{
"navigationBarTitleText": "GoodsAction 商品导航"
}
================================================
FILE: example/pages/goods-action/index.wxml
================================================
================================================
FILE: example/pages/grid/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/grid/index.json
================================================
{
"navigationBarTitleText": "Grid 宫格"
}
================================================
FILE: example/pages/grid/index.wxml
================================================
================================================
FILE: example/pages/icon/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/icon/index.json
================================================
{
"navigationBarTitleText": "Icon 图标"
}
================================================
FILE: example/pages/icon/index.wxml
================================================
================================================
FILE: example/pages/image/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/image/index.json
================================================
{
"navigationBarTitleText": "Image 图片"
}
================================================
FILE: example/pages/image/index.wxml
================================================
================================================
FILE: example/pages/index-bar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/index-bar/index.json
================================================
{
"navigationBarTitleText": "IndexBar 索引栏"
}
================================================
FILE: example/pages/index-bar/index.wxml
================================================
================================================
FILE: example/pages/loading/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/loading/index.json
================================================
{
"navigationBarTitleText": "Loading 加载"
}
================================================
FILE: example/pages/loading/index.wxml
================================================
================================================
FILE: example/pages/nav-bar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/nav-bar/index.json
================================================
{
"navigationBarTitleText": "NavBar 导航栏"
}
================================================
FILE: example/pages/nav-bar/index.wxml
================================================
================================================
FILE: example/pages/notice-bar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/notice-bar/index.json
================================================
{
"navigationBarTitleText": "NoticeBar 通知栏"
}
================================================
FILE: example/pages/notice-bar/index.wxml
================================================
================================================
FILE: example/pages/notify/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/notify/index.json
================================================
{
"navigationBarTitleText": "Notify 消息通知"
}
================================================
FILE: example/pages/notify/index.wxml
================================================
================================================
FILE: example/pages/overlay/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/overlay/index.json
================================================
{
"navigationBarTitleText": "Overlay 遮罩层"
}
================================================
FILE: example/pages/overlay/index.wxml
================================================
================================================
FILE: example/pages/panel/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/panel/index.json
================================================
{
"navigationBarTitleText": "Panel 面板"
}
================================================
FILE: example/pages/panel/index.wxml
================================================
================================================
FILE: example/pages/picker/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/picker/index.json
================================================
{
"navigationBarTitleText": "Picker 选择器"
}
================================================
FILE: example/pages/picker/index.wxml
================================================
================================================
FILE: example/pages/popup/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/popup/index.json
================================================
{
"navigationBarTitleText": "Popup 弹出层"
}
================================================
FILE: example/pages/popup/index.wxml
================================================
================================================
FILE: example/pages/popup/index.wxss
================================================
:host {
font-size: 16px;
}
================================================
FILE: example/pages/progress/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/progress/index.json
================================================
{
"navigationBarTitleText": "Progress 进度条"
}
================================================
FILE: example/pages/progress/index.wxml
================================================
================================================
FILE: example/pages/radio/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/radio/index.json
================================================
{
"navigationBarTitleText": "Radio 单选框"
}
================================================
FILE: example/pages/radio/index.wxml
================================================
================================================
FILE: example/pages/rate/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/rate/index.json
================================================
{
"navigationBarTitleText": "Rate 评分"
}
================================================
FILE: example/pages/rate/index.wxml
================================================
================================================
FILE: example/pages/rate/index.wxss
================================================
================================================
FILE: example/pages/search/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/search/index.json
================================================
{
"navigationBarTitleText": "Search 搜索"
}
================================================
FILE: example/pages/search/index.wxml
================================================
================================================
FILE: example/pages/share-sheet/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/share-sheet/index.json
================================================
{
"navigationBarTitleText": "ShareSheet 分享面板"
}
================================================
FILE: example/pages/share-sheet/index.wxml
================================================
================================================
FILE: example/pages/sidebar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/sidebar/index.json
================================================
{
"navigationBarTitleText": "Sidebar 侧边导航"
}
================================================
FILE: example/pages/sidebar/index.wxml
================================================
================================================
FILE: example/pages/sidebar/index.wxss
================================================
page {
background-color: #fff;
}
================================================
FILE: example/pages/skeleton/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/skeleton/index.json
================================================
{
"navigationBarTitleText": "Skeleton 骨架屏"
}
================================================
FILE: example/pages/skeleton/index.wxml
================================================
================================================
FILE: example/pages/slider/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/slider/index.json
================================================
{
"navigationBarTitleText": "Slider 滑块"
}
================================================
FILE: example/pages/slider/index.wxml
================================================
================================================
FILE: example/pages/stepper/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/stepper/index.json
================================================
{
"navigationBarTitleText": "Stepper 步进器"
}
================================================
FILE: example/pages/stepper/index.wxml
================================================
================================================
FILE: example/pages/steps/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/steps/index.json
================================================
{
"navigationBarTitleText": "Steps 步骤条"
}
================================================
FILE: example/pages/steps/index.wxml
================================================
================================================
FILE: example/pages/sticky/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/sticky/index.json
================================================
{
"navigationBarTitleText": "Sticky 粘性布局"
}
================================================
FILE: example/pages/sticky/index.wxml
================================================
================================================
FILE: example/pages/sticky/index.wxss
================================================
page {
height: 200vh;
}
================================================
FILE: example/pages/submit-bar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/submit-bar/index.json
================================================
{
"navigationBarTitleText": "SubmitBar 提交订单栏"
}
================================================
FILE: example/pages/submit-bar/index.wxml
================================================
================================================
FILE: example/pages/swipe-cell/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/swipe-cell/index.json
================================================
{
"navigationBarTitleText": "SwipeCell 滑动单元格"
}
================================================
FILE: example/pages/swipe-cell/index.wxml
================================================
================================================
FILE: example/pages/switch/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/switch/index.json
================================================
{
"navigationBarTitleText": "Switch 开关"
}
================================================
FILE: example/pages/switch/index.wxml
================================================
================================================
FILE: example/pages/tab/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/tab/index.json
================================================
{
"navigationBarTitleText": "Tab 标签页"
}
================================================
FILE: example/pages/tab/index.wxml
================================================
================================================
FILE: example/pages/tabbar/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/tabbar/index.json
================================================
{
"navigationBarTitleText": "Tabbar 标签栏"
}
================================================
FILE: example/pages/tabbar/index.wxml
================================================
================================================
FILE: example/pages/tag/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/tag/index.json
================================================
{
"navigationBarTitleText": "Tag 标记"
}
================================================
FILE: example/pages/tag/index.wxml
================================================
================================================
FILE: example/pages/toast/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/toast/index.json
================================================
{
"navigationBarTitleText": "Toast 轻提示"
}
================================================
FILE: example/pages/toast/index.wxml
================================================
================================================
FILE: example/pages/transition/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/transition/index.json
================================================
{
"navigationBarTitleText": "Transition 动画"
}
================================================
FILE: example/pages/transition/index.wxml
================================================
================================================
FILE: example/pages/tree-select/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/tree-select/index.json
================================================
{
"navigationBarTitleText": "TreeSelect 分类选择"
}
================================================
FILE: example/pages/tree-select/index.wxml
================================================
================================================
FILE: example/pages/uploader/index.js
================================================
import Page from '../../common/page';
Page();
================================================
FILE: example/pages/uploader/index.json
================================================
{
"navigationBarTitleText": "Uploader 文件上传"
}
================================================
FILE: example/pages/uploader/index.wxml
================================================
================================================
FILE: example/pages/uploader/index.wxss
================================================
page {
background-color: #fff;
}
================================================
FILE: example/project.config.json
================================================
{
"description": "项目配置文件",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"urlCheck": false,
"es6": true,
"enhance": true,
"postcss": false,
"preloadBackgroundData": false,
"minified": true,
"newFeature": false,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"uglifyFileName": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": false,
"lazyloadPlaceholderEnable": false,
"useMultiFrameRuntime": true,
"useApiHook": true,
"useApiHostProcess": false,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"enableEngineNative": false,
"useIsolateContext": true,
"userConfirmedBundleSwitch": false,
"packNpmManually": false,
"packNpmRelationList": [],
"minifyWXSS": true,
"showES6CompileOption": false,
"ignoreUploadUnusedFiles": true,
"condition": false
},
"compileType": "miniprogram",
"libVersion": "2.27.3",
"appid": "wx1c01b35002d3ba14",
"projectname": "vant-weapp",
"condition": {
"miniprogram": {
"list": [
{
"name": "button",
"pathName": "pages/button/index",
"query": ""
},
{
"name": "loading",
"pathName": "pages/loading/index",
"query": ""
},
{
"name": "icon",
"pathName": "pages/icon/index",
"query": ""
},
{
"name": "layout",
"pathName": "pages/col/index",
"query": ""
},
{
"name": "cell",
"pathName": "pages/cell/index",
"query": ""
},
{
"name": "config-provider",
"pathName": "pages/config-provider/index",
"query": ""
},
{
"name": "card",
"pathName": "pages/card/index",
"query": ""
},
{
"name": "stepper",
"pathName": "pages/stepper/index",
"query": ""
},
{
"name": "switch",
"pathName": "pages/switch/index",
"query": ""
},
{
"name": "tag",
"pathName": "pages/tag/index",
"query": ""
},
{
"name": "notice-bar",
"pathName": "pages/notice-bar/index",
"query": ""
},
{
"name": "tree-select",
"pathName": "pages/tree-select/index",
"query": ""
},
{
"name": "select",
"pathName": "pages/select/index",
"query": ""
},
{
"name": "field",
"pathName": "pages/field/index",
"query": ""
},
{
"name": "sidebar",
"pathName": "pages/sidebar/index",
"query": "",
"scene": null
},
{
"name": "panel",
"pathName": "pages/panel/index",
"query": ""
},
{
"name": "popup",
"pathName": "pages/popup/index",
"query": ""
},
{
"name": "action-sheet",
"pathName": "pages/action-sheet/index",
"query": ""
},
{
"name": "steps",
"pathName": "pages/steps/index",
"query": ""
},
{
"name": "search",
"pathName": "pages/search/index",
"query": ""
},
{
"name": "nav-bar",
"pathName": "pages/nav-bar/index",
"query": ""
},
{
"name": "notify",
"pathName": "pages/notify/index",
"query": ""
},
{
"name": "toast",
"pathName": "pages/toast/index",
"query": ""
},
{
"name": "tabbar",
"pathName": "pages/tabbar/index",
"query": ""
},
{
"name": "transition",
"pathName": "pages/transition/index",
"query": ""
},
{
"name": "slider",
"pathName": "pages/slider/index",
"query": ""
},
{
"name": "progress",
"pathName": "pages/progress/index",
"query": ""
},
{
"name": "area",
"pathName": "pages/area/index",
"query": ""
},
{
"name": "tab",
"pathName": "pages/tab/index",
"query": ""
},
{
"name": "dialog",
"pathName": "pages/dialog/index",
"query": ""
},
{
"name": "submit-bar",
"pathName": "pages/submit-bar/index",
"query": ""
},
{
"name": "checkbox",
"pathName": "pages/checkbox/index",
"query": ""
},
{
"name": "goods-action",
"pathName": "pages/goods-action/index",
"query": ""
},
{
"name": "radio",
"pathName": "pages/radio/index",
"query": ""
},
{
"name": "swipe-cell",
"pathName": "pages/swipe-cell/index",
"query": ""
},
{
"name": "rate",
"pathName": "pages/rate/index",
"query": ""
},
{
"name": "collapse",
"pathName": "pages/collapse/index",
"query": ""
},
{
"name": "datetime-picker",
"pathName": "pages/datetime-picker/index",
"query": ""
},
{
"name": "sticky",
"pathName": "pages/sticky/index",
"query": "",
"scene": null
},
{
"name": "picker",
"pathName": "pages/picker/index",
"query": "",
"scene": null
},
{
"name": "overlay",
"pathName": "pages/overlay/index",
"query": "",
"scene": null
},
{
"name": "circle",
"pathName": "pages/circle/index",
"query": "",
"scene": null
},
{
"name": "grid",
"pathName": "pages/grid/index",
"query": "",
"scene": null
},
{
"name": "count-down",
"pathName": "pages/count-down/index",
"query": "",
"scene": null
},
{
"name": "image",
"pathName": "pages/image/index",
"query": "",
"scene": null
},
{
"name": "skeleton",
"pathName": "pages/skeleton/index",
"query": "",
"scene": null
},
{
"name": "uploader",
"pathName": "pages/uploader/index",
"query": "",
"scene": null
},
{
"name": "dropdown-menu",
"pathName": "pages/dropdown-menu/index",
"query": "",
"scene": null
},
{
"name": "calendar",
"pathName": "pages/calendar/index",
"query": "",
"scene": null
},
{
"name": "index-bar",
"pathName": "pages/index-bar/index",
"query": "",
"scene": null
},
{
"name": "empty",
"pathName": "pages/empty/index",
"query": "",
"scene": null
},
{
"name": "share-sheet",
"pathName": "pages/share-sheet/index",
"query": "",
"scene": null
},
{
"name": "col",
"pathName": "pages/col/index",
"query": "",
"scene": null
},
{
"name": "divider",
"pathName": "pages/divider/index",
"query": "",
"scene": null
},
{
"name": "cascader",
"pathName": "pages/cascader/index",
"query": "",
"scene": null
}
]
}
},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}
================================================
FILE: example/sitemap.json
================================================
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
================================================
FILE: jest.config.js
================================================
module.exports = {
bail: 1,
verbose: true,
testEnvironment: 'jsdom',
testURL: 'https://jest.test',
moduleFileExtensions: ['js', 'ts'],
testMatch: ['/packages/**/test/**/*.spec.{js,ts}'],
transformIgnorePatterns: ["/node_modules/(?!@vant/)"],
transform: {
"^.+\\.js?$": "babel-jest", // Adding this line solved the issue
"^.+\\.ts?$": "ts-jest"
},
collectCoverageFrom: [
'/packages/**/*.{js,ts}',
'!**/test/**'
],
preset: "ts-jest",
snapshotSerializers: ['miniprogram-simulate/jest-snapshot-plugin']
}
================================================
FILE: lib/action-sheet/index.d.ts
================================================
export {};
================================================
FILE: lib/action-sheet/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var button_1 = require("../mixins/button");
(0, component_1.VantComponent)({
classes: ['list-class'],
mixins: [button_1.button],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100,
},
actions: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onSelect: function (event) {
var _this = this;
var index = event.currentTarget.dataset.index;
var _a = this.data, actions = _a.actions, closeOnClickAction = _a.closeOnClickAction, canIUseGetUserProfile = _a.canIUseGetUserProfile;
var item = actions[index];
if (item) {
this.$emit('select', item);
if (closeOnClickAction) {
this.onClose();
}
if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: item.getUserProfileDesc || ' ',
complete: function (userProfile) {
_this.$emit('getuserinfo', userProfile);
},
});
}
}
},
onCancel: function () {
this.$emit('cancel');
},
onClose: function () {
this.$emit('close');
},
onClickOverlay: function () {
this.$emit('click-overlay');
this.onClose();
},
},
});
================================================
FILE: lib/action-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: lib/action-sheet/index.wxml
================================================
{{ description }}
{{ cancelText }}
================================================
FILE: lib/action-sheet/index.wxss
================================================
@import '../common/index.wxss';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}
================================================
FILE: lib/area/index.d.ts
================================================
export {};
================================================
FILE: lib/area/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var shared_1 = require("../picker/shared");
var utils_1 = require("../common/utils");
var EMPTY_CODE = '000000';
(0, component_1.VantComponent)({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: __assign(__assign({}, shared_1.pickerProps), { showToolbar: {
type: Boolean,
value: true,
}, value: {
type: String,
observer: function (value) {
this.code = value;
this.setValues();
},
}, areaList: {
type: Object,
value: {},
observer: 'setValues',
}, columnsNum: {
type: null,
value: 3,
}, columnsPlaceholder: {
type: Array,
observer: function (val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
},
});
},
} }),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {},
},
mounted: function () {
var _this = this;
(0, utils_1.requestAnimationFrame)(function () {
_this.setValues();
});
},
methods: {
getPicker: function () {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel: function (event) {
this.emit('cancel', event.detail);
},
onConfirm: function (event) {
var index = event.detail.index;
var value = event.detail.value;
value = this.parseValues(value);
this.emit('confirm', { value: value, index: index });
},
emit: function (type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
parseValues: function (values) {
var columnsPlaceholder = this.data.columnsPlaceholder;
return values.map(function (value, index) {
if (value &&
(!value.code || value.name === columnsPlaceholder[index])) {
return __assign(__assign({}, value), { code: '', name: '' });
}
return value;
});
},
onChange: function (event) {
var _this = this;
var _a;
var _b = event.detail, index = _b.index, picker = _b.picker, value = _b.value;
this.code = value[index].code;
(_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(function () {
_this.$emit('change', {
picker: picker,
values: _this.parseValues(picker.getValues()),
index: index,
});
});
},
getConfig: function (type) {
var areaList = this.data.areaList;
return (areaList && areaList["".concat(type, "_list")]) || {};
},
getList: function (type, code) {
if (type !== 'province' && !code) {
return [];
}
var typeToColumnsPlaceholder = this.data.typeToColumnsPlaceholder;
var list = this.getConfig(type);
var result = Object.keys(list).map(function (code) { return ({
code: code,
name: list[code],
}); });
if (code != null) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter(function (item) { return item.code.indexOf(code) === 0; });
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
var codeFill = type === 'province'
? ''
: type === 'city'
? EMPTY_CODE.slice(2, 4)
: EMPTY_CODE.slice(4, 6);
result.unshift({
code: "".concat(code).concat(codeFill),
name: typeToColumnsPlaceholder[type],
});
}
return result;
},
getIndex: function (type, code) {
var compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
var list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (var i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues: function () {
var picker = this.getPicker();
if (!picker) {
return;
}
var code = this.code || this.getDefaultCode();
var provinceList = this.getList('province');
var cityList = this.getList('city', code.slice(0, 2));
var stack = [];
var indexes = [];
var columnsNum = this.data.columnsNum;
if (columnsNum >= 1) {
stack.push(picker.setColumnValues(0, provinceList, false));
indexes.push(this.getIndex('province', code));
}
if (columnsNum >= 2) {
stack.push(picker.setColumnValues(1, cityList, false));
indexes.push(this.getIndex('city', code));
if (cityList.length && code.slice(2, 4) === '00') {
code = cityList[0].code;
}
}
if (columnsNum === 3) {
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
indexes.push(this.getIndex('county', code));
}
return Promise.all(stack)
.catch(function () { })
.then(function () { return picker.setIndexes(indexes); })
.catch(function () { });
},
getDefaultCode: function () {
var columnsPlaceholder = this.data.columnsPlaceholder;
if (columnsPlaceholder.length) {
return EMPTY_CODE;
}
var countyCodes = Object.keys(this.getConfig('county'));
if (countyCodes[0]) {
return countyCodes[0];
}
var cityCodes = Object.keys(this.getConfig('city'));
if (cityCodes[0]) {
return cityCodes[0];
}
return '';
},
getValues: function () {
var picker = this.getPicker();
if (!picker) {
return [];
}
return this.parseValues(picker.getValues().filter(function (value) { return !!value; }));
},
getDetail: function () {
var values = this.getValues();
var area = {
code: '',
country: '',
province: '',
city: '',
county: '',
};
if (!values.length) {
return area;
}
var names = values.map(function (item) { return item.name; });
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
}
else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset: function (code) {
this.code = code || '';
return this.setValues();
},
},
});
================================================
FILE: lib/area/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: lib/area/index.wxml
================================================
================================================
FILE: lib/area/index.wxs
================================================
/* eslint-disable */
function displayColumns(columns, columnsNum) {
return columns.slice(0, +columnsNum);
}
module.exports = {
displayColumns: displayColumns,
};
================================================
FILE: lib/area/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: lib/button/index.d.ts
================================================
export {};
================================================
FILE: lib/button/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var button_1 = require("../mixins/button");
var version_1 = require("../common/version");
var mixins = [button_1.button];
if ((0, version_1.canIUseFormFieldButton)()) {
mixins.push('wx://form-field-button');
}
(0, component_1.VantComponent)({
mixins: mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick: function (event) {
var _this = this;
this.$emit('click', event);
var _a = this.data, canIUseGetUserProfile = _a.canIUseGetUserProfile, openType = _a.openType, getUserProfileDesc = _a.getUserProfileDesc, lang = _a.lang;
if (openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: getUserProfileDesc || ' ',
lang: lang || 'en',
complete: function (userProfile) {
_this.$emit('getuserinfo', userProfile);
},
});
}
},
},
});
================================================
FILE: lib/button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: lib/button/index.wxml
================================================
================================================
FILE: lib/button/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return data.customStyle;
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style([properties, data.customStyle]);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: lib/button/index.wxss
================================================
@import '../common/index.wxss';.van-button{-webkit-text-size-adjust:100%;align-items:center;-webkit-appearance:none;border-radius:var(--button-border-radius,2px);box-sizing:border-box;display:inline-flex;font-size:var(--button-default-font-size,16px);height:var(--button-default-height,44px);justify-content:center;line-height:var(--button-line-height,20px);padding:0;position:relative;text-align:center;transition:opacity .2s;vertical-align:middle}.van-button:before{background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";height:100%;left:50%;opacity:0;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{background:var(--button-default-background-color,#fff);border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0);color:var(--button-default-color,#323233)}.van-button--primary{background:var(--button-primary-background-color,#07c160);border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160);color:var(--button-primary-color,#fff)}.van-button--info{background:var(--button-info-background-color,#1989fa);border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa);color:var(--button-info-color,#fff)}.van-button--danger{background:var(--button-danger-background-color,#ee0a24);border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24);color:var(--button-danger-color,#fff)}.van-button--warning{background:var(--button-warning-background-color,#ff976a);border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a);color:var(--button-warning-color,#fff)}.van-button--plain{background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:var(--button-warning-background-color,#ff976a)}.van-button--large{height:var(--button-large-height,50px);width:100%}.van-button--normal{font-size:var(--button-normal-font-size,14px);padding:0 15px}.van-button--small{font-size:var(--button-small-font-size,12px);height:var(--button-small-height,30px);min-width:var(--button-small-min-width,60px);padding:0 var(--padding-xs,8px)}.van-button--mini{display:inline-block;font-size:var(--button-mini-font-size,10px);height:var(--button-mini-height,22px);min-width:var(--button-mini-min-width,50px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:flex;width:100%}.van-button--round{border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{line-height:inherit!important;min-width:1em;vertical-align:top}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-color:inherit;border-radius:calc(var(--button-border-radius, 2px)*2);border-width:1px}.van-button--hairline.van-button--round:after{border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
================================================
FILE: lib/calendar/calendar.wxml
================================================
================================================
FILE: lib/calendar/components/header/index.d.ts
================================================
export {};
================================================
FILE: lib/calendar/components/header/index.js
================================================
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../../../common/component");
(0, component_1.VantComponent)({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
firstDayOfWeek: {
type: Number,
observer: 'initWeekDay',
},
},
data: {
weekdays: [],
},
created: function () {
this.initWeekDay();
},
methods: {
initWeekDay: function () {
var defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
var firstDayOfWeek = this.data.firstDayOfWeek || 0;
this.setData({
weekdays: __spreadArray(__spreadArray([], defaultWeeks.slice(firstDayOfWeek, 7), true), defaultWeeks.slice(0, firstDayOfWeek), true),
});
},
onClickSubtitle: function (event) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: lib/calendar/components/header/index.json
================================================
{
"component": true
}
================================================
FILE: lib/calendar/components/header/index.wxml
================================================
================================================
FILE: lib/calendar/components/header/index.wxss
================================================
@import '../../../common/index.wxss';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}
================================================
FILE: lib/calendar/components/month/index.d.ts
================================================
export interface Day {
date: Date;
type: string;
text: number;
bottomInfo?: string;
}
================================================
FILE: lib/calendar/components/month/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../../../common/component");
var utils_1 = require("../../utils");
(0, component_1.VantComponent)({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: null,
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: null,
observer: 'setDays',
},
firstDayOfWeek: {
type: Number,
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [],
},
methods: {
onClick: function (event) {
var index = event.currentTarget.dataset.index;
var item = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays: function () {
var days = [];
var startDate = new Date(this.data.date);
var year = startDate.getFullYear();
var month = startDate.getMonth();
var totalDay = (0, utils_1.getMonthEndDay)(startDate.getFullYear(), startDate.getMonth() + 1);
for (var day = 1; day <= totalDay; day++) {
var date = new Date(year, month, day);
var type = this.getDayType(date);
var config = {
date: date,
type: type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days: days });
},
getMultipleDayType: function (day) {
var currentDate = this.data.currentDate;
if (!Array.isArray(currentDate)) {
return '';
}
var isSelected = function (date) {
return currentDate.some(function (item) { return (0, utils_1.compareDay)(item, date) === 0; });
};
if (isSelected(day)) {
var prevDay = (0, utils_1.getPrevDay)(day);
var nextDay = (0, utils_1.getNextDay)(day);
var prevSelected = isSelected(prevDay);
var nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType: function (day) {
var _a = this.data, currentDate = _a.currentDate, allowSameDay = _a.allowSameDay;
if (!Array.isArray(currentDate)) {
return '';
}
var startDay = currentDate[0], endDay = currentDate[1];
if (!startDay) {
return '';
}
var compareToStart = (0, utils_1.compareDay)(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
var compareToEnd = (0, utils_1.compareDay)(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
return '';
},
getDayType: function (day) {
var _a = this.data, type = _a.type, minDate = _a.minDate, maxDate = _a.maxDate, currentDate = _a.currentDate;
if ((0, utils_1.compareDay)(day, minDate) < 0 || (0, utils_1.compareDay)(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return (0, utils_1.compareDay)(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
return '';
},
getBottomInfo: function (type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});
================================================
FILE: lib/calendar/components/month/index.json
================================================
{
"component": true
}
================================================
FILE: lib/calendar/components/month/index.wxml
================================================
{{ computed.formatMonthTitle(date) }}
{{ computed.getMark(date) }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
================================================
FILE: lib/calendar/components/month/index.wxs
================================================
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
var style = [];
var current = getDate(date).getDay() || 7;
var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
current === 7 && firstDayOfWeek === 0 ? 0 :
(current - firstDayOfWeek);
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'start-end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};
================================================
FILE: lib/calendar/components/month/index.wxss
================================================
@import '../../../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:100%}.van-calendar__month-title{font-size:var(--calendar-month-title-font-size,14px);font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__days{display:flex;flex-wrap:wrap;position:relative;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:var(--calendar-month-mark-font-size,160px);left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:0}.van-calendar__day,.van-calendar__selected-day{align-items:center;display:flex;justify-content:center;text-align:center}.van-calendar__day{font-size:var(--calendar-day-font-size,16px);height:var(--calendar-day-height,64px);position:relative;width:14.285%}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{background-color:var(--calendar-range-edge-background-color,#ee0a24);color:var(--calendar-range-edge-color,#fff)}.van-calendar__day--start{border-radius:4px 0 0 4px}.van-calendar__day--end{border-radius:0 4px 4px 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px}.van-calendar__day--middle{color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{background-color:currentColor;bottom:0;content:"";left:0;opacity:var(--calendar-range-middle-background-opacity,.1);position:absolute;right:0;top:0}.van-calendar__day--disabled{color:var(--calendar-day-disabled-color,#c8c9cc);cursor:default}.van-calendar__bottom-info,.van-calendar__top-info{font-size:var(--calendar-info-font-size,10px);left:0;line-height:var(--calendar-info-line-height,14px);position:absolute;right:0}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;color:var(--calendar-selected-day-color,#fff);height:var(--calendar-selected-day-size,54px);width:var(--calendar-selected-day-size,54px)}
================================================
FILE: lib/calendar/index.d.ts
================================================
export {};
================================================
FILE: lib/calendar/index.js
================================================
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var utils_1 = require("./utils");
var toast_1 = __importDefault(require("../toast/toast"));
var utils_2 = require("../common/utils");
var initialMinDate = (0, utils_1.getToday)().getTime();
var initialMaxDate = (function () {
var now = (0, utils_1.getToday)();
return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
})();
var getTime = function (date) {
return date instanceof Date ? date.getTime() : date;
};
(0, component_1.VantComponent)({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer: function (val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
confirmDisabledText: {
type: String,
value: '确定',
},
rangePrompt: String,
showRangePrompt: {
type: Boolean,
value: true,
},
defaultDate: {
type: null,
value: (0, utils_1.getToday)().getTime(),
observer: function (val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: Number,
value: initialMinDate,
},
maxDate: {
type: Number,
value: initialMaxDate,
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: null,
value: utils_1.ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: null,
value: null,
},
minRange: {
type: Number,
value: 1,
},
firstDayOfWeek: {
type: Number,
value: 0,
},
readonly: Boolean,
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
subtitle: '',
currentDate: null,
scrollIntoView: '',
},
watch: {
minDate: function () {
this.initRect();
},
maxDate: function () {
this.initRect();
},
},
created: function () {
this.setData({
currentDate: this.getInitialDate(this.data.defaultDate),
});
},
mounted: function () {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset: function () {
this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) });
this.scrollIntoView();
},
initRect: function () {
var _this = this;
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
var contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', function (res) {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
_this.setData({ subtitle: (0, utils_1.formatMonthTitle)(res.dataset.date) });
}
});
},
limitDateRange: function (date, minDate, maxDate) {
if (minDate === void 0) { minDate = null; }
if (maxDate === void 0) { maxDate = null; }
minDate = minDate || this.data.minDate;
maxDate = maxDate || this.data.maxDate;
if ((0, utils_1.compareDay)(date, minDate) === -1) {
return minDate;
}
if ((0, utils_1.compareDay)(date, maxDate) === 1) {
return maxDate;
}
return date;
},
getInitialDate: function (defaultDate) {
var _this = this;
if (defaultDate === void 0) { defaultDate = null; }
var _a = this.data, type = _a.type, minDate = _a.minDate, maxDate = _a.maxDate, allowSameDay = _a.allowSameDay;
if (!defaultDate)
return [];
var now = (0, utils_1.getToday)().getTime();
if (type === 'range') {
if (!Array.isArray(defaultDate)) {
defaultDate = [];
}
var _b = defaultDate || [], startDay = _b[0], endDay = _b[1];
var startDate = getTime(startDay || now);
var start = this.limitDateRange(startDate, minDate, allowSameDay ? startDate : (0, utils_1.getPrevDay)(new Date(maxDate)).getTime());
var date = getTime(endDay || now);
var end = this.limitDateRange(date, allowSameDay ? date : (0, utils_1.getNextDay)(new Date(minDate)).getTime());
return [start, end];
}
if (type === 'multiple') {
if (Array.isArray(defaultDate)) {
return defaultDate.map(function (date) { return _this.limitDateRange(date); });
}
return [this.limitDateRange(now)];
}
if (!defaultDate || Array.isArray(defaultDate)) {
defaultDate = now;
}
return this.limitDateRange(defaultDate);
},
scrollIntoView: function () {
var _this = this;
(0, utils_2.requestAnimationFrame)(function () {
var _a = _this.data, currentDate = _a.currentDate, type = _a.type, show = _a.show, poppable = _a.poppable, minDate = _a.minDate, maxDate = _a.maxDate;
if (!currentDate)
return;
// @ts-ignore
var targetDate = type === 'single' ? currentDate : currentDate[0];
var displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
var months = (0, utils_1.getMonths)(minDate, maxDate);
months.some(function (month, index) {
if ((0, utils_1.compareMonth)(month, targetDate) === 0) {
_this.setData({ scrollIntoView: "month".concat(index) });
return true;
}
return false;
});
});
},
onOpen: function () {
this.$emit('open');
},
onOpened: function () {
this.$emit('opened');
},
onClose: function () {
this.$emit('close');
},
onClosed: function () {
this.$emit('closed');
},
onClickDay: function (event) {
if (this.data.readonly) {
return;
}
var date = event.detail.date;
var _a = this.data, type = _a.type, currentDate = _a.currentDate, allowSameDay = _a.allowSameDay;
if (type === 'range') {
// @ts-ignore
var startDay_1 = currentDate[0], endDay = currentDate[1];
if (startDay_1 && !endDay) {
var compareToStart = (0, utils_1.compareDay)(date, startDay_1);
if (compareToStart === 1) {
var days_1 = this.selectComponent('.month').data.days;
days_1.some(function (day, index) {
var isDisabled = day.type === 'disabled' &&
getTime(startDay_1) < getTime(day.date) &&
getTime(day.date) < getTime(date);
if (isDisabled) {
(date = days_1[index - 1].date);
}
return isDisabled;
});
this.select([startDay_1, date], true);
}
else if (compareToStart === -1) {
this.select([date, null]);
}
else if (allowSameDay) {
this.select([date, date], true);
}
}
else {
this.select([date, null]);
}
}
else if (type === 'multiple') {
var selectedIndex_1;
// @ts-ignore
var selected = currentDate.some(function (dateItem, index) {
var equal = (0, utils_1.compareDay)(dateItem, date) === 0;
if (equal) {
selectedIndex_1 = index;
}
return equal;
});
if (selected) {
// @ts-ignore
var cancelDate = currentDate.splice(selectedIndex_1, 1);
this.setData({ currentDate: currentDate });
this.unselect(cancelDate);
}
else {
// @ts-ignore
this.select(__spreadArray(__spreadArray([], currentDate, true), [date], false));
}
}
else {
this.select(date, true);
}
},
unselect: function (dateArray) {
var date = dateArray[0];
if (date) {
this.$emit('unselect', (0, utils_1.copyDates)(date));
}
},
select: function (date, complete) {
if (complete && this.data.type === 'range') {
var valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
(0, utils_1.getDayByOffset)(date[0], this.data.maxRange - 1),
]);
}
else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit: function (date) {
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', (0, utils_1.copyDates)(date));
},
checkRange: function (date) {
var _a = this.data, maxRange = _a.maxRange, rangePrompt = _a.rangePrompt, showRangePrompt = _a.showRangePrompt;
if (maxRange && (0, utils_1.calcDateNum)(date) > maxRange) {
if (showRangePrompt) {
(0, toast_1.default)({
context: this,
message: rangePrompt || "\u9009\u62E9\u5929\u6570\u4E0D\u80FD\u8D85\u8FC7 ".concat(maxRange, " \u5929"),
});
}
this.$emit('over-range');
return false;
}
return true;
},
onConfirm: function () {
var _this = this;
if (this.data.type === 'range' &&
!this.checkRange(this.data.currentDate)) {
return;
}
wx.nextTick(function () {
// @ts-ignore
_this.$emit('confirm', (0, utils_1.copyDates)(_this.data.currentDate));
});
},
onClickSubtitle: function (event) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: lib/calendar/index.json
================================================
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index",
"van-toast": "../toast/index"
}
}
================================================
FILE: lib/calendar/index.wxml
================================================
================================================
FILE: lib/calendar/index.wxs
================================================
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate, minRange) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return currentDate.length < minRange;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};
================================================
FILE: lib/calendar/index.wxss
================================================
@import '../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,90%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}
================================================
FILE: lib/calendar/utils.d.ts
================================================
export declare const ROW_HEIGHT = 64;
export declare function formatMonthTitle(date: Date): string;
export declare function compareMonth(date1: Date | number, date2: Date | number): 0 | 1 | -1;
export declare function compareDay(day1: Date | number, day2: Date | number): 0 | 1 | -1;
export declare function getDayByOffset(date: Date, offset: number): Date;
export declare function getPrevDay(date: Date): Date;
export declare function getNextDay(date: Date): Date;
export declare function getToday(): Date;
export declare function calcDateNum(date: [Date, Date]): number;
export declare function copyDates(dates: Date | Date[]): Date | Date[];
export declare function getMonthEndDay(year: number, month: number): number;
export declare function getMonths(minDate: number, maxDate: number): number[];
================================================
FILE: lib/calendar/utils.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMonths = exports.getMonthEndDay = exports.copyDates = exports.calcDateNum = exports.getToday = exports.getNextDay = exports.getPrevDay = exports.getDayByOffset = exports.compareDay = exports.compareMonth = exports.formatMonthTitle = exports.ROW_HEIGHT = void 0;
exports.ROW_HEIGHT = 64;
function formatMonthTitle(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return "".concat(date.getFullYear(), "\u5E74").concat(date.getMonth() + 1, "\u6708");
}
exports.formatMonthTitle = formatMonthTitle;
function compareMonth(date1, date2) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
exports.compareMonth = compareMonth;
function compareDay(day1, day2) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
var compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
var date1 = day1.getDate();
var date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
exports.compareDay = compareDay;
function getDayByOffset(date, offset) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
exports.getDayByOffset = getDayByOffset;
function getPrevDay(date) {
return getDayByOffset(date, -1);
}
exports.getPrevDay = getPrevDay;
function getNextDay(date) {
return getDayByOffset(date, 1);
}
exports.getNextDay = getNextDay;
function getToday() {
var today = new Date();
today.setHours(0, 0, 0, 0);
return today;
}
exports.getToday = getToday;
function calcDateNum(date) {
var day1 = new Date(date[0]).getTime();
var day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
exports.calcDateNum = calcDateNum;
function copyDates(dates) {
if (Array.isArray(dates)) {
return dates.map(function (date) {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
exports.copyDates = copyDates;
function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
exports.getMonthEndDay = getMonthEndDay;
function getMonths(minDate, maxDate) {
var months = [];
var cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}
exports.getMonths = getMonths;
================================================
FILE: lib/calendar/utils.wxs
================================================
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};
================================================
FILE: lib/card/index.d.ts
================================================
export {};
================================================
FILE: lib/card/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var link_1 = require("../mixins/link");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class',
],
mixins: [link_1.link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit',
},
currency: {
type: String,
value: '¥',
},
},
methods: {
updatePrice: function () {
var price = this.data.price;
var priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? ".".concat(priceArr[1]) : '',
});
},
onClickThumb: function () {
this.jumpLink('thumbLink');
},
},
});
================================================
FILE: lib/card/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}
================================================
FILE: lib/card/index.wxml
================================================
================================================
FILE: lib/card/index.wxss
================================================
@import '../common/index.wxss';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}
================================================
FILE: lib/cascader/index.d.ts
================================================
export {};
================================================
FILE: lib/cascader/index.js
================================================
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var FieldName;
(function (FieldName) {
FieldName["TEXT"] = "text";
FieldName["VALUE"] = "value";
FieldName["CHILDREN"] = "children";
})(FieldName || (FieldName = {}));
var defaultFieldNames = {
text: FieldName.TEXT,
value: FieldName.VALUE,
children: FieldName.CHILDREN,
};
(0, component_1.VantComponent)({
props: {
title: String,
value: {
type: String,
},
placeholder: {
type: String,
value: '请选择',
},
activeColor: {
type: String,
value: '#1989fa',
},
options: {
type: Array,
value: [],
},
swipeable: {
type: Boolean,
value: false,
},
closeable: {
type: Boolean,
value: true,
},
ellipsis: {
type: Boolean,
value: true,
},
showHeader: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
fieldNames: {
type: Object,
value: defaultFieldNames,
observer: 'updateFieldNames',
},
useTitleSlot: Boolean,
},
data: {
tabs: [],
activeTab: 0,
textKey: FieldName.TEXT,
valueKey: FieldName.VALUE,
childrenKey: FieldName.CHILDREN,
innerValue: '',
},
watch: {
options: function () {
this.updateTabs();
},
value: function (newVal) {
this.updateValue(newVal);
},
},
created: function () {
this.updateTabs();
},
methods: {
updateValue: function (val) {
var _this = this;
if (val !== undefined) {
var values = this.data.tabs.map(function (tab) { return tab.selected && tab.selected[_this.data.valueKey]; });
if (values.indexOf(val) > -1) {
return;
}
}
this.innerValue = val;
this.updateTabs();
},
updateFieldNames: function () {
var _a = this.data.fieldNames || defaultFieldNames, _b = _a.text, text = _b === void 0 ? 'text' : _b, _c = _a.value, value = _c === void 0 ? 'value' : _c, _d = _a.children, children = _d === void 0 ? 'children' : _d;
this.setData({
textKey: text,
valueKey: value,
childrenKey: children,
});
},
getSelectedOptionsByValue: function (options, value) {
for (var i = 0; i < options.length; i++) {
var option = options[i];
if (option[this.data.valueKey] === value) {
return [option];
}
if (option[this.data.childrenKey]) {
var selectedOptions = this.getSelectedOptionsByValue(option[this.data.childrenKey], value);
if (selectedOptions) {
return __spreadArray([option], selectedOptions, true);
}
}
}
},
updateTabs: function () {
var _this = this;
var options = this.data.options;
var innerValue = this.innerValue;
if (!options.length) {
return;
}
if (innerValue !== undefined) {
var selectedOptions = this.getSelectedOptionsByValue(options, innerValue);
if (selectedOptions) {
var optionsCursor_1 = options;
var tabs_1 = selectedOptions.map(function (option) {
var tab = {
options: optionsCursor_1,
selected: option,
};
var next = optionsCursor_1.find(function (item) { return item[_this.data.valueKey] === option[_this.data.valueKey]; });
if (next) {
optionsCursor_1 = next[_this.data.childrenKey];
}
return tab;
});
if (optionsCursor_1) {
tabs_1.push({
options: optionsCursor_1,
selected: null,
});
}
this.setData({
tabs: tabs_1,
});
wx.nextTick(function () {
_this.setData({
activeTab: tabs_1.length - 1,
});
});
return;
}
}
this.setData({
tabs: [
{
options: options,
selected: null,
},
],
activeTab: 0,
});
},
onClose: function () {
this.$emit('close');
},
onClickTab: function (e) {
var _a = e.detail, tabIndex = _a.index, title = _a.title;
this.$emit('click-tab', { title: title, tabIndex: tabIndex });
this.setData({
activeTab: tabIndex,
});
},
// 选中
onSelect: function (e) {
var _this = this;
var _a = e.currentTarget.dataset, option = _a.option, tabIndex = _a.tabIndex;
if (option && option.disabled) {
return;
}
var _b = this.data, valueKey = _b.valueKey, childrenKey = _b.childrenKey;
var tabs = this.data.tabs;
tabs[tabIndex].selected = option;
if (tabs.length > tabIndex + 1) {
tabs = tabs.slice(0, tabIndex + 1);
}
if (option[childrenKey]) {
var nextTab = {
options: option[childrenKey],
selected: null,
};
if (tabs[tabIndex + 1]) {
tabs[tabIndex + 1] = nextTab;
}
else {
tabs.push(nextTab);
}
wx.nextTick(function () {
_this.setData({
activeTab: tabIndex + 1,
});
});
}
this.setData({
tabs: tabs,
});
var selectedOptions = tabs.map(function (tab) { return tab.selected; }).filter(Boolean);
var value = option[valueKey];
var params = {
value: value,
tabIndex: tabIndex,
selectedOptions: selectedOptions,
};
this.innerValue = value;
this.$emit('change', params);
if (!option[childrenKey]) {
this.$emit('finish', params);
}
},
},
});
================================================
FILE: lib/cascader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-tab": "../tab/index",
"van-tabs": "../tabs/index"
}
}
================================================
FILE: lib/cascader/index.wxml
================================================
{{ option[textKey] }}
================================================
FILE: lib/cascader/index.wxs
================================================
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function isSelected(tab, valueKey, option) {
return tab.selected && tab.selected[valueKey] === option[valueKey]
}
function optionClass(tab, valueKey, option) {
return utils.bem('cascader__option', { selected: isSelected(tab, valueKey, option), disabled: option.disabled })
}
function optionStyle(data) {
var color = data.option.color || (isSelected(data.tab, data.valueKey, data.option) ? data.activeColor : undefined);
return style({
color
});
}
module.exports = {
isSelected: isSelected,
optionClass: optionClass,
optionStyle: optionStyle,
};
================================================
FILE: lib/cascader/index.wxss
================================================
@import '../common/index.wxss';.van-cascader__header{align-items:center;display:flex;height:48px;justify-content:space-between;padding:0 16px}.van-cascader__title{font-size:16px;font-weight:600;line-height:20px}.van-cascader__close-icon{color:#c8c9cc;font-size:22px;height:22px}.van-cascader__tabs-wrap{height:48px!important;padding:0 8px}.van-cascader__tab{color:#323233!important;flex:none!important;font-weight:600!important;padding:0 8px!important}.van-cascader__tab--unselected{color:#969799!important;font-weight:400!important}.van-cascader__option{align-items:center;cursor:pointer;display:flex;font-size:14px;justify-content:space-between;line-height:20px;padding:10px 16px}.van-cascader__option:active{background-color:#f2f3f5}.van-cascader__option--selected{color:#1989fa;font-weight:600}.van-cascader__option--disabled{color:#c8c9cc;cursor:not-allowed}.van-cascader__option--disabled:active{background-color:initial}.van-cascader__options{-webkit-overflow-scrolling:touch;box-sizing:border-box;height:384px;overflow-y:auto;padding-top:6px}
================================================
FILE: lib/cell/index.d.ts
================================================
export {};
================================================
FILE: lib/cell/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var link_1 = require("../mixins/link");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class',
],
mixins: [link_1.link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick: function (event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: lib/cell/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/cell/index.wxml
================================================
{{ title }}
{{ label }}
{{ value }}
================================================
FILE: lib/cell/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};
================================================
FILE: lib/cell/index.wxss
================================================
@import '../common/index.wxss';.van-cell{background-color:var(--cell-background-color,#fff);box-sizing:border-box;color:var(--cell-text-color,#323233);display:flex;font-size:var(--cell-font-size,14px);line-height:var(--cell-line-height,24px);padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);position:relative;width:100%}.van-cell:after{border-bottom:1px solid #ebedf0;bottom:0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:16px;transform:scaleY(.5);transform-origin:center}.van-cell--borderless:after{display:none}.van-cell-group{background-color:var(--cell-background-color,#fff)}.van-cell__label{color:var(--cell-label-color,#969799);font-size:var(--cell-label-font-size,12px);line-height:var(--cell-label-line-height,18px);margin-top:var(--cell-label-margin-top,3px)}.van-cell__value{color:var(--cell-value-color,#969799);overflow:hidden;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{align-items:center;display:flex;font-size:var(--cell-icon-size,16px);height:var(--cell-line-height,24px)}.van-cell__left-icon-wrap{margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{color:var(--cell-right-icon-color,#969799);margin-left:var(--padding-base,4px)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{color:var(--cell-required-color,#ee0a24);content:"*";font-size:var(--cell-font-size,14px);left:var(--padding-xs,8px);position:absolute}.van-cell--center{align-items:center}.van-cell--large{padding-bottom:var(--cell-large-vertical-padding,12px);padding-top:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:var(--cell-large-label-font-size,14px)}
================================================
FILE: lib/cell-group/index.d.ts
================================================
export {};
================================================
FILE: lib/cell-group/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
inset: Boolean,
},
});
================================================
FILE: lib/cell-group/index.json
================================================
{
"component": true
}
================================================
FILE: lib/cell-group/index.wxml
================================================
{{ title }}
================================================
FILE: lib/cell-group/index.wxss
================================================
@import '../common/index.wxss';.van-cell-group--inset{border-radius:var(--cell-group-inset-border-radius,8px);margin:var(--cell-group-inset-padding,0 16px);overflow:hidden}.van-cell-group__title{color:var(--cell-group-title-color,#969799);font-size:var(--cell-group-title-font-size,14px);line-height:var(--cell-group-title-line-height,16px);padding:var(--cell-group-title-padding,16px 16px 8px)}.van-cell-group__title--inset{padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)}
================================================
FILE: lib/checkbox/index.d.ts
================================================
export {};
================================================
FILE: lib/checkbox/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var relation_1 = require("../common/relation");
var component_1 = require("../common/component");
function emit(target, value) {
target.$emit('input', value);
target.$emit('change', value);
}
(0, component_1.VantComponent)({
field: true,
relation: (0, relation_1.useParent)('checkbox-group'),
classes: ['icon-class', 'label-class'],
props: {
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
direction: 'vertical',
},
methods: {
emitChange: function (value) {
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
emit(this, value);
}
},
toggle: function () {
var _a = this.data, parentDisabled = _a.parentDisabled, disabled = _a.disabled, value = _a.value;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel: function () {
var _a = this.data, labelDisabled = _a.labelDisabled, parentDisabled = _a.parentDisabled, disabled = _a.disabled, value = _a.value;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
setParentValue: function (parent, value) {
var parentValue = parent.data.value.slice();
var name = this.data.name;
var max = parent.data.max;
if (value) {
if (max && parentValue.length >= max) {
return;
}
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
emit(parent, parentValue);
}
}
else {
var index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
},
},
});
================================================
FILE: lib/checkbox/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/checkbox/index.wxml
================================================
================================================
FILE: lib/checkbox/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = {
'font-size': addUnit(iconSize),
};
if (checkedColor && value && !disabled && !parentDisabled) {
styles['border-color'] = checkedColor;
styles['background-color'] = checkedColor;
}
return style(styles);
}
module.exports = {
iconStyle: iconStyle,
};
================================================
FILE: lib/checkbox/index.wxss
================================================
@import '../common/index.wxss';.van-checkbox{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{flex:none}.van-checkbox__icon{align-items:center;border:1px solid var(--checkbox-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--checkbox-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--checkbox-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:var(--checkbox-checked-icon-color,#1989fa);color:#fff}.van-checkbox__icon--disabled{background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;color:var(--checkbox-label-color,#323233);padding-left:var(--checkbox-label-margin,10px)}.van-checkbox__label--left{float:left;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
================================================
FILE: lib/checkbox-group/index.d.ts
================================================
export {};
================================================
FILE: lib/checkbox-group/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var relation_1 = require("../common/relation");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
field: true,
relation: (0, relation_1.useChildren)('checkbox', function (target) {
this.updateChild(target);
}),
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren',
},
direction: {
type: String,
value: 'vertical',
},
},
methods: {
updateChildren: function () {
var _this = this;
this.children.forEach(function (child) { return _this.updateChild(child); });
},
updateChild: function (child) {
var _a = this.data, value = _a.value, disabled = _a.disabled, direction = _a.direction;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled,
direction: direction,
});
},
},
});
================================================
FILE: lib/checkbox-group/index.json
================================================
{
"component": true
}
================================================
FILE: lib/checkbox-group/index.wxml
================================================
================================================
FILE: lib/checkbox-group/index.wxss
================================================
@import '../common/index.wxss';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap}
================================================
FILE: lib/circle/canvas.d.ts
================================================
///
type CanvasContext = WechatMiniprogram.CanvasContext;
export declare function adaptor(ctx: CanvasContext & Record): CanvasContext;
export {};
================================================
FILE: lib/circle/canvas.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.adaptor = void 0;
function adaptor(ctx) {
// @ts-ignore
return Object.assign(ctx, {
setStrokeStyle: function (val) {
ctx.strokeStyle = val;
},
setLineWidth: function (val) {
ctx.lineWidth = val;
},
setLineCap: function (val) {
ctx.lineCap = val;
},
setFillStyle: function (val) {
ctx.fillStyle = val;
},
setFontSize: function (val) {
ctx.font = String(val);
},
setGlobalAlpha: function (val) {
ctx.globalAlpha = val;
},
setLineJoin: function (val) {
ctx.lineJoin = val;
},
setTextAlign: function (val) {
ctx.textAlign = val;
},
setMiterLimit: function (val) {
ctx.miterLimit = val;
},
setShadow: function (offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline: function (val) {
ctx.textBaseline = val;
},
createCircularGradient: function () { },
draw: function () { },
});
}
exports.adaptor = adaptor;
================================================
FILE: lib/circle/index.d.ts
================================================
export {};
================================================
FILE: lib/circle/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var color_1 = require("../common/color");
var component_1 = require("../common/component");
var utils_1 = require("../common/utils");
var validator_1 = require("../common/validator");
var version_1 = require("../common/version");
var canvas_1 = require("./canvas");
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
var PERIMETER = 2 * Math.PI;
var BEGIN_ANGLE = -Math.PI / 2;
var STEP = 1;
(0, component_1.VantComponent)({
props: {
text: String,
lineCap: {
type: String,
value: 'round',
},
value: {
type: Number,
value: 0,
observer: 'reRender',
},
speed: {
type: Number,
value: 50,
},
size: {
type: Number,
value: 100,
observer: function () {
this.drawCircle(this.currentValue);
},
},
fill: String,
layerColor: {
type: String,
value: color_1.WHITE,
},
color: {
type: null,
value: color_1.BLUE,
observer: function () {
var _this = this;
this.setHoverColor().then(function () {
_this.drawCircle(_this.currentValue);
});
},
},
type: {
type: String,
value: '',
},
strokeWidth: {
type: Number,
value: 4,
},
clockwise: {
type: Boolean,
value: true,
},
},
data: {
hoverColor: color_1.BLUE,
},
methods: {
getContext: function () {
var _this = this;
var _a = this.data, type = _a.type, size = _a.size;
if (type === '' || !(0, version_1.canIUseCanvas2d)()) {
var ctx = wx.createCanvasContext('van-circle', this);
return Promise.resolve(ctx);
}
var dpr = (0, utils_1.getSystemInfoSync)().pixelRatio;
return new Promise(function (resolve) {
wx.createSelectorQuery()
.in(_this)
.select('#van-circle')
.node()
.exec(function (res) {
var canvas = res[0].node;
var ctx = canvas.getContext(type);
if (!_this.inited) {
_this.inited = true;
canvas.width = size * dpr;
canvas.height = size * dpr;
ctx.scale(dpr, dpr);
}
resolve((0, canvas_1.adaptor)(ctx));
});
});
},
setHoverColor: function () {
var _this = this;
var _a = this.data, color = _a.color, size = _a.size;
if ((0, validator_1.isObj)(color)) {
return this.getContext().then(function (context) {
if (!context)
return;
var LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort(function (a, b) { return parseFloat(a) - parseFloat(b); })
.map(function (key) {
return LinearColor.addColorStop(parseFloat(key) / 100, color[key]);
});
_this.hoverColor = LinearColor;
});
}
this.hoverColor = color;
return Promise.resolve();
},
presetCanvas: function (context, strokeStyle, beginAngle, endAngle, fill) {
var _a = this.data, strokeWidth = _a.strokeWidth, lineCap = _a.lineCap, clockwise = _a.clockwise, size = _a.size;
var position = size / 2;
var radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle: function (context) {
var _a = this.data, layerColor = _a.layerColor, fill = _a.fill;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle: function (context, formatValue) {
var clockwise = this.data.clockwise;
// 结束角度
var progress = PERIMETER * (formatValue / 100);
var endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle: function (currentValue) {
var _this = this;
var size = this.data.size;
this.getContext().then(function (context) {
if (!context)
return;
context.clearRect(0, 0, size, size);
_this.renderLayerCircle(context);
var formatValue = format(currentValue);
if (formatValue !== 0) {
_this.renderHoverCircle(context, formatValue);
}
context.draw();
});
},
reRender: function () {
var _this = this;
// tofector 动画暂时没有想到好的解决方案
var _a = this.data, value = _a.value, speed = _a.speed;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearMockInterval();
this.currentValue = this.currentValue || 0;
var run = function () {
_this.interval = setTimeout(function () {
if (_this.currentValue !== value) {
if (Math.abs(_this.currentValue - value) < STEP) {
_this.currentValue = value;
}
else if (_this.currentValue < value) {
_this.currentValue += STEP;
}
else {
_this.currentValue -= STEP;
}
_this.drawCircle(_this.currentValue);
run();
}
else {
_this.clearMockInterval();
}
}, 1000 / speed);
};
run();
},
clearMockInterval: function () {
if (this.interval) {
clearTimeout(this.interval);
this.interval = null;
}
},
},
mounted: function () {
var _this = this;
this.currentValue = this.data.value;
this.setHoverColor().then(function () {
_this.drawCircle(_this.currentValue);
});
},
destroyed: function () {
this.clearMockInterval();
},
});
================================================
FILE: lib/circle/index.json
================================================
{
"component": true
}
================================================
FILE: lib/circle/index.wxml
================================================
{{ text }}
================================================
FILE: lib/circle/index.wxss
================================================
@import '../common/index.wxss';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}
================================================
FILE: lib/col/index.d.ts
================================================
export {};
================================================
FILE: lib/col/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var relation_1 = require("../common/relation");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
relation: (0, relation_1.useParent)('row'),
props: {
span: Number,
offset: Number,
},
});
================================================
FILE: lib/col/index.json
================================================
{
"component": true
}
================================================
FILE: lib/col/index.wxml
================================================
================================================
FILE: lib/col/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'padding-right': addUnit(data.gutter / 2),
'padding-left': addUnit(data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/col/index.wxss
================================================
@import '../common/index.wxss';.van-col{box-sizing:border-box;float:left}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
================================================
FILE: lib/collapse/index.d.ts
================================================
export {};
================================================
FILE: lib/collapse/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('collapse-item'),
props: {
value: {
type: null,
observer: 'updateExpanded',
},
accordion: {
type: Boolean,
observer: 'updateExpanded',
},
border: {
type: Boolean,
value: true,
},
},
methods: {
updateExpanded: function () {
this.children.forEach(function (child) {
child.updateExpanded();
});
},
switch: function (name, expanded) {
var _a = this.data, accordion = _a.accordion, value = _a.value;
var changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter(function (activeName) { return activeName !== name; });
}
else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
}
else {
this.$emit('close', changeItem);
}
this.$emit('change', name);
this.$emit('input', name);
},
},
});
================================================
FILE: lib/collapse/index.json
================================================
{
"component": true
}
================================================
FILE: lib/collapse/index.wxml
================================================
================================================
FILE: lib/collapse/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: lib/collapse-item/animate.d.ts
================================================
///
export declare function setContentAnimate(context: WechatMiniprogram.Component.TrivialInstance, expanded: boolean, mounted: boolean): void;
================================================
FILE: lib/collapse-item/animate.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setContentAnimate = void 0;
var utils_1 = require("../common/utils");
function useAnimation(context, expanded, mounted, height) {
var animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
}
else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
function setContentAnimate(context, expanded, mounted) {
(0, utils_1.getRect)(context, '.van-collapse-item__content')
.then(function (rect) { return rect.height; })
.then(function (height) {
useAnimation(context, expanded, mounted, height);
});
}
exports.setContentAnimate = setContentAnimate;
================================================
FILE: lib/collapse-item/index.d.ts
================================================
export {};
================================================
FILE: lib/collapse-item/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var animate_1 = require("./animate");
(0, component_1.VantComponent)({
classes: ['title-class', 'content-class'],
relation: (0, relation_1.useParent)('collapse'),
props: {
size: String,
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true,
},
isLink: {
type: Boolean,
value: true,
},
},
data: {
expanded: false,
parentBorder: true,
},
mounted: function () {
this.updateExpanded();
this.mounted = true;
},
methods: {
updateExpanded: function () {
if (!this.parent) {
return;
}
var _a = this.parent.data, value = _a.value, accordion = _a.accordion, border = _a.border;
var _b = this.parent.children, children = _b === void 0 ? [] : _b;
var name = this.data.name;
var index = children.indexOf(this);
var currentName = name == null ? index : name;
var expanded = accordion
? value === currentName
: (value || []).some(function (name) { return name === currentName; });
if (expanded !== this.data.expanded) {
(0, animate_1.setContentAnimate)(this, expanded, this.mounted);
}
this.setData({ index: index, expanded: expanded, parentBorder: border });
},
onClick: function () {
if (this.data.disabled) {
return;
}
var _a = this.data, name = _a.name, expanded = _a.expanded;
var index = this.parent.children.indexOf(this);
var currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
},
},
});
================================================
FILE: lib/collapse-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: lib/collapse-item/index.wxml
================================================
================================================
FILE: lib/collapse-item/index.wxss
================================================
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{transform:rotate(90deg);transition:transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{background-color:var(--collapse-item-content-background-color,#fff);color:var(--collapse-item-content-text-color,#969799);font-size:var(--collapse-item-content-font-size,13px);line-height:var(--collapse-item-content-line-height,1.5);padding:var(--collapse-item-content-padding,15px)}
================================================
FILE: lib/common/color.d.ts
================================================
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
================================================
FILE: lib/common/color.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GRAY_DARK = exports.GRAY = exports.ORANGE = exports.GREEN = exports.WHITE = exports.BLUE = exports.RED = void 0;
exports.RED = '#ee0a24';
exports.BLUE = '#1989fa';
exports.WHITE = '#fff';
exports.GREEN = '#07c160';
exports.ORANGE = '#ff976a';
exports.GRAY = '#323233';
exports.GRAY_DARK = '#969799';
================================================
FILE: lib/common/component.d.ts
================================================
///
import { VantComponentOptions } from 'definitions/index';
declare function VantComponent(vantOptions: VantComponentOptions): void;
export { VantComponent };
================================================
FILE: lib/common/component.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VantComponent = void 0;
var basic_1 = require("../mixins/basic");
function mapKeys(source, target, map) {
Object.keys(map).forEach(function (key) {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent(vantOptions) {
var options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
watch: 'observers',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
destroyed: 'detached',
classes: 'externalClasses',
});
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic_1.basic);
// add relations
var relation = vantOptions.relation;
if (relation) {
options.relations = relation.relations;
options.behaviors.push(relation.mixin);
}
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true,
};
Component(options);
}
exports.VantComponent = VantComponent;
================================================
FILE: lib/common/index.wxss
================================================
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
================================================
FILE: lib/common/relation.d.ts
================================================
///
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export {};
================================================
FILE: lib/common/relation.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useChildren = exports.useParent = void 0;
function useParent(name, onEffect) {
var _a;
var path = "../".concat(name, "/index");
return {
relations: (_a = {},
_a[path] = {
type: 'ancestor',
linked: function () {
onEffect && onEffect.call(this);
},
linkChanged: function () {
onEffect && onEffect.call(this);
},
unlinked: function () {
onEffect && onEffect.call(this);
},
},
_a),
mixin: Behavior({
created: function () {
var _this = this;
Object.defineProperty(this, 'parent', {
get: function () { return _this.getRelationNodes(path)[0]; },
});
Object.defineProperty(this, 'index', {
// @ts-ignore
get: function () { var _a, _b; return (_b = (_a = _this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.indexOf(_this); },
});
},
}),
};
}
exports.useParent = useParent;
function useChildren(name, onEffect) {
var _a;
var path = "../".concat(name, "/index");
return {
relations: (_a = {},
_a[path] = {
type: 'descendant',
linked: function (target) {
onEffect && onEffect.call(this, target);
},
linkChanged: function (target) {
onEffect && onEffect.call(this, target);
},
unlinked: function (target) {
onEffect && onEffect.call(this, target);
},
},
_a),
mixin: Behavior({
created: function () {
var _this = this;
Object.defineProperty(this, 'children', {
get: function () { return _this.getRelationNodes(path) || []; },
});
},
}),
};
}
exports.useChildren = useChildren;
================================================
FILE: lib/common/style/clearfix.wxss
================================================
.van-clearfix:after{clear:both;content:"";display:table}
================================================
FILE: lib/common/style/ellipsis.wxss
================================================
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
================================================
FILE: lib/common/style/hairline.wxss
================================================
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
================================================
FILE: lib/common/style/mixins/clearfix.wxss
================================================
================================================
FILE: lib/common/style/mixins/ellipsis.wxss
================================================
================================================
FILE: lib/common/style/mixins/hairline.wxss
================================================
================================================
FILE: lib/common/style/var.wxss
================================================
================================================
FILE: lib/common/utils.d.ts
================================================
///
///
///
///
///
export { isDef } from './validator';
export { getSystemInfoSync } from './version';
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(cb: (...args: any[]) => void): void;
export declare function addUnit(value?: string | number): string | undefined;
export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout;
export declare function pickExclude(obj: unknown, keys: string[]): {};
export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise;
export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise;
export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void;
export declare function toPromise(promiseLike: Promise | unknown): Promise;
export declare function addNumber(num1: any, num2: any): number;
export declare const clamp: (num: any, min: any, max: any) => number;
export declare function getCurrentPage(): T & WechatMiniprogram.OptionalInterface & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods & WechatMiniprogram.Page.Data & WechatMiniprogram.IAnyObject;
export declare const isPC: boolean;
export declare const isWxWork: boolean;
================================================
FILE: lib/common/utils.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isWxWork = exports.isPC = exports.getCurrentPage = exports.clamp = exports.addNumber = exports.toPromise = exports.groupSetData = exports.getAllRect = exports.getRect = exports.pickExclude = exports.requestAnimationFrame = exports.addUnit = exports.nextTick = exports.range = exports.getSystemInfoSync = exports.isDef = void 0;
var validator_1 = require("./validator");
var version_1 = require("./version");
var validator_2 = require("./validator");
Object.defineProperty(exports, "isDef", { enumerable: true, get: function () { return validator_2.isDef; } });
var version_2 = require("./version");
Object.defineProperty(exports, "getSystemInfoSync", { enumerable: true, get: function () { return version_2.getSystemInfoSync; } });
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
exports.range = range;
function nextTick(cb) {
if ((0, version_1.canIUseNextTick)()) {
wx.nextTick(cb);
}
else {
setTimeout(function () {
cb();
}, 1000 / 30);
}
}
exports.nextTick = nextTick;
function addUnit(value) {
if (!(0, validator_1.isDef)(value)) {
return undefined;
}
value = String(value);
return (0, validator_1.isNumber)(value) ? "".concat(value, "px") : value;
}
exports.addUnit = addUnit;
function requestAnimationFrame(cb) {
return setTimeout(function () {
cb();
}, 1000 / 30);
}
exports.requestAnimationFrame = requestAnimationFrame;
function pickExclude(obj, keys) {
if (!(0, validator_1.isPlainObject)(obj)) {
return {};
}
return Object.keys(obj).reduce(function (prev, key) {
if (!keys.includes(key)) {
prev[key] = obj[key];
}
return prev;
}, {});
}
exports.pickExclude = pickExclude;
function getRect(context, selector) {
return new Promise(function (resolve) {
wx.createSelectorQuery()
.in(context)
.select(selector)
.boundingClientRect()
.exec(function (rect) {
if (rect === void 0) { rect = []; }
return resolve(rect[0]);
});
});
}
exports.getRect = getRect;
function getAllRect(context, selector) {
return new Promise(function (resolve) {
wx.createSelectorQuery()
.in(context)
.selectAll(selector)
.boundingClientRect()
.exec(function (rect) {
if (rect === void 0) { rect = []; }
return resolve(rect[0]);
});
});
}
exports.getAllRect = getAllRect;
function groupSetData(context, cb) {
if ((0, version_1.canIUseGroupSetData)()) {
context.groupSetData(cb);
}
else {
cb();
}
}
exports.groupSetData = groupSetData;
function toPromise(promiseLike) {
if ((0, validator_1.isPromise)(promiseLike)) {
return promiseLike;
}
return Promise.resolve(promiseLike);
}
exports.toPromise = toPromise;
// 浮点数精度处理
function addNumber(num1, num2) {
var cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
exports.addNumber = addNumber;
// 限制value在[min, max]之间
var clamp = function (num, min, max) { return Math.min(Math.max(num, min), max); };
exports.clamp = clamp;
function getCurrentPage() {
var pages = getCurrentPages();
return pages[pages.length - 1];
}
exports.getCurrentPage = getCurrentPage;
exports.isPC = ['mac', 'windows'].includes((0, version_1.getSystemInfoSync)().platform);
// 是否企业微信
exports.isWxWork = (0, version_1.getSystemInfoSync)().environment === 'wxwork';
================================================
FILE: lib/common/validator.d.ts
================================================
export declare function isFunction(val: unknown): val is Function;
export declare function isPlainObject(val: unknown): val is Record;
export declare function isPromise(val: unknown): val is Promise;
export declare function isDef(value: unknown): boolean;
export declare function isObj(x: unknown): x is Record;
export declare function isNumber(value: string): boolean;
export declare function isBoolean(value: unknown): value is boolean;
export declare function isImageUrl(url: string): boolean;
export declare function isVideoUrl(url: string): boolean;
================================================
FILE: lib/common/validator.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isVideoUrl = exports.isImageUrl = exports.isBoolean = exports.isNumber = exports.isObj = exports.isDef = exports.isPromise = exports.isPlainObject = exports.isFunction = void 0;
// eslint-disable-next-line @typescript-eslint/ban-types
function isFunction(val) {
return typeof val === 'function';
}
exports.isFunction = isFunction;
function isPlainObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
exports.isPlainObject = isPlainObject;
function isPromise(val) {
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
}
exports.isPromise = isPromise;
function isDef(value) {
return value !== undefined && value !== null;
}
exports.isDef = isDef;
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
exports.isObj = isObj;
function isNumber(value) {
return /^\d+(\.\d+)?$/.test(value);
}
exports.isNumber = isNumber;
function isBoolean(value) {
return typeof value === 'boolean';
}
exports.isBoolean = isBoolean;
var IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
var VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
function isImageUrl(url) {
return IMAGE_REGEXP.test(url);
}
exports.isImageUrl = isImageUrl;
function isVideoUrl(url) {
return VIDEO_REGEXP.test(url);
}
exports.isVideoUrl = isVideoUrl;
================================================
FILE: lib/common/version.d.ts
================================================
///
interface WxWorkSystemInfo extends WechatMiniprogram.SystemInfo {
environment?: 'wxwork';
}
interface SystemInfo extends WxWorkSystemInfo, WechatMiniprogram.SystemInfo {
}
export declare function getSystemInfoSync(): SystemInfo;
export declare function canIUseModel(): boolean;
export declare function canIUseFormFieldButton(): boolean;
export declare function canIUseAnimate(): boolean;
export declare function canIUseGroupSetData(): boolean;
export declare function canIUseNextTick(): boolean;
export declare function canIUseCanvas2d(): boolean;
export declare function canIUseGetUserProfile(): boolean;
export {};
================================================
FILE: lib/common/version.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.canIUseGetUserProfile = exports.canIUseCanvas2d = exports.canIUseNextTick = exports.canIUseGroupSetData = exports.canIUseAnimate = exports.canIUseFormFieldButton = exports.canIUseModel = exports.getSystemInfoSync = void 0;
var systemInfo;
function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo;
}
exports.getSystemInfoSync = getSystemInfoSync;
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
var len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (var i = 0; i < len; i++) {
var num1 = parseInt(v1[i], 10);
var num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
function gte(version) {
var system = getSystemInfoSync();
return compareVersion(system.SDKVersion, version) >= 0;
}
function canIUseModel() {
return gte('2.9.3');
}
exports.canIUseModel = canIUseModel;
function canIUseFormFieldButton() {
return gte('2.10.3');
}
exports.canIUseFormFieldButton = canIUseFormFieldButton;
function canIUseAnimate() {
return gte('2.9.0');
}
exports.canIUseAnimate = canIUseAnimate;
function canIUseGroupSetData() {
return gte('2.4.0');
}
exports.canIUseGroupSetData = canIUseGroupSetData;
function canIUseNextTick() {
try {
return wx.canIUse('nextTick');
}
catch (e) {
return gte('2.7.1');
}
}
exports.canIUseNextTick = canIUseNextTick;
function canIUseCanvas2d() {
return gte('2.9.0');
}
exports.canIUseCanvas2d = canIUseCanvas2d;
function canIUseGetUserProfile() {
return !!wx.getUserProfile;
}
exports.canIUseGetUserProfile = canIUseGetUserProfile;
================================================
FILE: lib/config-provider/index.d.ts
================================================
export {};
================================================
FILE: lib/config-provider/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
themeVars: {
type: Object,
value: {},
},
},
});
================================================
FILE: lib/config-provider/index.json
================================================
{
"component": true
}
================================================
FILE: lib/config-provider/index.wxml
================================================
================================================
FILE: lib/config-provider/index.wxs
================================================
/* eslint-disable */
var object = require('../wxs/object.wxs');
var style = require('../wxs/style.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
.replace(getRegExp("^-"), '');
return newWord;
}
function mapThemeVarsToCSSVars(themeVars) {
var cssVars = {};
object.keys(themeVars).forEach(function (key) {
var cssVarsKey = '--' + kebabCase(key);
cssVars[cssVarsKey] = themeVars[key];
});
return style(cssVars);
}
module.exports = {
kebabCase: kebabCase,
mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
};
================================================
FILE: lib/count-down/index.d.ts
================================================
export {};
================================================
FILE: lib/count-down/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var utils_1 = require("./utils");
function simpleTick(fn) {
return setTimeout(fn, 30);
}
(0, component_1.VantComponent)({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset',
},
format: {
type: String,
value: 'HH:mm:ss',
},
autoStart: {
type: Boolean,
value: true,
},
},
data: {
timeData: (0, utils_1.parseTimeData)(0),
formattedTime: '0',
},
destroyed: function () {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start: function () {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause: function () {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset: function () {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick: function () {
if (this.data.millisecond) {
this.microTick();
}
else {
this.macroTick();
}
},
microTick: function () {
var _this = this;
this.tid = simpleTick(function () {
_this.setRemain(_this.getRemain());
if (_this.remain !== 0) {
_this.microTick();
}
});
},
macroTick: function () {
var _this = this;
this.tid = simpleTick(function () {
var remain = _this.getRemain();
if (!(0, utils_1.isSameSecond)(remain, _this.remain) || remain === 0) {
_this.setRemain(remain);
}
if (_this.remain !== 0) {
_this.macroTick();
}
});
},
getRemain: function () {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain: function (remain) {
this.remain = remain;
var timeData = (0, utils_1.parseTimeData)(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: (0, utils_1.parseFormat)(this.data.format, timeData),
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
},
});
================================================
FILE: lib/count-down/index.json
================================================
{
"component": true
}
================================================
FILE: lib/count-down/index.wxml
================================================
{{ formattedTime }}
================================================
FILE: lib/count-down/index.wxss
================================================
@import '../common/index.wxss';.van-count-down{color:var(--count-down-text-color,#323233);font-size:var(--count-down-font-size,14px);line-height:var(--count-down-line-height,20px)}
================================================
FILE: lib/count-down/utils.d.ts
================================================
export type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
export declare function parseTimeData(time: number): TimeData;
export declare function parseFormat(format: string, timeData: TimeData): string;
export declare function isSameSecond(time1: number, time2: number): boolean;
================================================
FILE: lib/count-down/utils.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSameSecond = exports.parseFormat = exports.parseTimeData = void 0;
function padZero(num, targetLength) {
if (targetLength === void 0) { targetLength = 2; }
var str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
var SECOND = 1000;
var MINUTE = 60 * SECOND;
var HOUR = 60 * MINUTE;
var DAY = 24 * HOUR;
function parseTimeData(time) {
var days = Math.floor(time / DAY);
var hours = Math.floor((time % DAY) / HOUR);
var minutes = Math.floor((time % HOUR) / MINUTE);
var seconds = Math.floor((time % MINUTE) / SECOND);
var milliseconds = Math.floor(time % SECOND);
return {
days: days,
hours: hours,
minutes: minutes,
seconds: seconds,
milliseconds: milliseconds,
};
}
exports.parseTimeData = parseTimeData;
function parseFormat(format, timeData) {
var days = timeData.days;
var hours = timeData.hours, minutes = timeData.minutes, seconds = timeData.seconds, milliseconds = timeData.milliseconds;
if (format.indexOf('DD') === -1) {
hours += days * 24;
}
else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
}
else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
}
else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
}
else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
exports.parseFormat = parseFormat;
function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
exports.isSameSecond = isSameSecond;
================================================
FILE: lib/datetime-picker/index.d.ts
================================================
export {};
================================================
FILE: lib/datetime-picker/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var validator_1 = require("../common/validator");
var shared_1 = require("../picker/shared");
var currentYear = new Date().getFullYear();
function isValidDate(date) {
return (0, validator_1.isDef)(date) && !isNaN(new Date(date).getTime());
}
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function padZero(val) {
return "00".concat(val).slice(-2);
}
function times(n, iteratee) {
var index = -1;
var result = Array(n < 0 ? 0 : n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
function getTrueValue(formattedValue) {
if (formattedValue === undefined) {
formattedValue = '1';
}
while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1);
}
return parseInt(formattedValue, 10);
}
function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
var defaultFormatter = function (type, value) { return value; };
(0, component_1.VantComponent)({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: __assign(__assign({}, shared_1.pickerProps), { value: {
type: null,
observer: 'updateValue',
}, filter: null, type: {
type: String,
value: 'datetime',
observer: 'updateValue',
}, showToolbar: {
type: Boolean,
value: true,
}, formatter: {
type: null,
value: defaultFormatter,
}, minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime(),
observer: 'updateValue',
}, maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime(),
observer: 'updateValue',
}, minHour: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxHour: {
type: Number,
value: 23,
observer: 'updateValue',
}, minMinute: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxMinute: {
type: Number,
value: 59,
observer: 'updateValue',
} }),
data: {
innerValue: Date.now(),
columns: [],
},
methods: {
updateValue: function () {
var _this = this;
var data = this.data;
var val = this.correctValue(data.value);
var isEqual = val === data.innerValue;
this.updateColumnValue(val).then(function () {
if (!isEqual) {
_this.$emit('input', val);
}
});
},
getPicker: function () {
if (this.picker == null) {
this.picker = this.selectComponent('.van-datetime-picker');
var picker_1 = this.picker;
var setColumnValues_1 = picker_1.setColumnValues;
picker_1.setColumnValues = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return setColumnValues_1.apply(picker_1, __spreadArray(__spreadArray([], args, true), [false], false));
};
}
return this.picker;
},
updateColumns: function () {
var _a = this.data.formatter, formatter = _a === void 0 ? defaultFormatter : _a;
var results = this.getOriginColumns().map(function (column) { return ({
values: column.values.map(function (value) { return formatter(column.type, value); }),
}); });
return this.set({ columns: results });
},
getOriginColumns: function () {
var filter = this.data.filter;
var results = this.getRanges().map(function (_a) {
var type = _a.type, range = _a.range;
var values = times(range[1] - range[0] + 1, function (index) {
var value = range[0] + index;
return type === 'year' ? "".concat(value) : padZero(value);
});
if (filter) {
values = filter(type, values);
}
return { type: type, values: values };
});
return results;
},
getRanges: function () {
var data = this.data;
if (data.type === 'time') {
return [
{
type: 'hour',
range: [data.minHour, data.maxHour],
},
{
type: 'minute',
range: [data.minMinute, data.maxMinute],
},
];
}
var _a = this.getBoundary('max', data.innerValue), maxYear = _a.maxYear, maxDate = _a.maxDate, maxMonth = _a.maxMonth, maxHour = _a.maxHour, maxMinute = _a.maxMinute;
var _b = this.getBoundary('min', data.innerValue), minYear = _b.minYear, minDate = _b.minDate, minMonth = _b.minMonth, minHour = _b.minHour, minMinute = _b.minMinute;
var result = [
{
type: 'year',
range: [minYear, maxYear],
},
{
type: 'month',
range: [minMonth, maxMonth],
},
{
type: 'day',
range: [minDate, maxDate],
},
{
type: 'hour',
range: [minHour, maxHour],
},
{
type: 'minute',
range: [minMinute, maxMinute],
},
];
if (data.type === 'date')
result.splice(3, 2);
if (data.type === 'year-month')
result.splice(2, 3);
return result;
},
correctValue: function (value) {
var data = this.data;
// validate value
var isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) {
value = data.minDate;
}
else if (!isDateType && !value) {
var minHour = data.minHour;
value = "".concat(padZero(minHour), ":00");
}
// time type
if (!isDateType) {
var _a = value.split(':'), hour = _a[0], minute = _a[1];
hour = padZero(range(hour, data.minHour, data.maxHour));
minute = padZero(range(minute, data.minMinute, data.maxMinute));
return "".concat(hour, ":").concat(minute);
}
// date type
value = Math.max(value, data.minDate);
value = Math.min(value, data.maxDate);
return value;
},
getBoundary: function (type, innerValue) {
var _a;
var value = new Date(innerValue);
var boundary = new Date(this.data["".concat(type, "Date")]);
var year = boundary.getFullYear();
var month = 1;
var date = 1;
var hour = 0;
var minute = 0;
if (type === 'max') {
month = 12;
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
hour = 23;
minute = 59;
}
if (value.getFullYear() === year) {
month = boundary.getMonth() + 1;
if (value.getMonth() + 1 === month) {
date = boundary.getDate();
if (value.getDate() === date) {
hour = boundary.getHours();
if (value.getHours() === hour) {
minute = boundary.getMinutes();
}
}
}
}
return _a = {},
_a["".concat(type, "Year")] = year,
_a["".concat(type, "Month")] = month,
_a["".concat(type, "Date")] = date,
_a["".concat(type, "Hour")] = hour,
_a["".concat(type, "Minute")] = minute,
_a;
},
onCancel: function () {
this.$emit('cancel');
},
onConfirm: function () {
this.$emit('confirm', this.data.innerValue);
},
onChange: function () {
var _this = this;
var data = this.data;
var value;
var picker = this.getPicker();
var originColumns = this.getOriginColumns();
if (data.type === 'time') {
var indexes = picker.getIndexes();
value = "".concat(+originColumns[0].values[indexes[0]], ":").concat(+originColumns[1]
.values[indexes[1]]);
}
else {
var indexes = picker.getIndexes();
var values = indexes.map(function (value, index) { return originColumns[index].values[value]; });
var year = getTrueValue(values[0]);
var month = getTrueValue(values[1]);
var maxDate = getMonthEndDay(year, month);
var date = getTrueValue(values[2]);
if (data.type === 'year-month') {
date = 1;
}
date = date > maxDate ? maxDate : date;
var hour = 0;
var minute = 0;
if (data.type === 'datetime') {
hour = getTrueValue(values[3]);
minute = getTrueValue(values[4]);
}
value = new Date(year, month - 1, date, hour, minute);
}
value = this.correctValue(value);
this.updateColumnValue(value).then(function () {
_this.$emit('input', value);
_this.$emit('change', picker);
});
},
updateColumnValue: function (value) {
var _this = this;
var values = [];
var type = this.data.type;
var formatter = this.data.formatter || defaultFormatter;
var picker = this.getPicker();
if (type === 'time') {
var pair = value.split(':');
values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
}
else {
var date = new Date(value);
values = [
formatter('year', "".concat(date.getFullYear())),
formatter('month', padZero(date.getMonth() + 1)),
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
if (type === 'datetime') {
values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
}
}
return this.set({ innerValue: value })
.then(function () { return _this.updateColumns(); })
.then(function () { return picker.setValues(values); });
},
},
created: function () {
var _this = this;
var innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(function () {
_this.$emit('input', innerValue);
});
},
});
================================================
FILE: lib/datetime-picker/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: lib/datetime-picker/index.wxml
================================================
================================================
FILE: lib/datetime-picker/index.wxss
================================================
@import '../common/index.wxss';
================================================
FILE: lib/definitions/index.d.ts
================================================
///
interface VantComponentInstance {
parent: WechatMiniprogram.Component.TrivialInstance;
children: WechatMiniprogram.Component.TrivialInstance[];
index: number;
$emit: (name: string, detail?: unknown, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
setView: (value: Record, callback?: () => void) => void;
}
export type VantComponentOptions = {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props;
relation?: {
relations: Record;
mixin: string;
};
watch?: Record any>;
methods?: Methods;
beforeCreate?: () => void;
created?: () => void;
mounted?: () => void;
destroyed?: () => void;
} & ThisType, Props, Methods> & Record>;
export {};
================================================
FILE: lib/definitions/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
================================================
FILE: lib/dialog/dialog.d.ts
================================================
///
///
export type Action = 'confirm' | 'cancel' | 'overlay';
type DialogContext = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
interface DialogOptions {
lang?: string;
show?: boolean;
title?: string;
width?: string | number | null;
zIndex?: number;
theme?: string;
context?: (() => DialogContext) | DialogContext;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
/**
* @deprecated use custom-class instead
*/
className?: string;
customStyle?: string;
transition?: string;
/**
* @deprecated use beforeClose instead
*/
asyncClose?: boolean;
beforeClose?: null | ((action: Action) => Promise | void);
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
showMessageCard?: boolean;
sendMessagePath?: string;
sendMessageTitle?: string;
confirmButtonText?: string;
cancelButtonText?: string;
showConfirmButton?: boolean;
showCancelButton?: boolean;
closeOnClickOverlay?: boolean;
confirmButtonOpenType?: string;
}
declare const Dialog: {
(options: DialogOptions): Promise;
alert(options: DialogOptions): Promise;
confirm(options: DialogOptions): Promise;
close(): void;
stopLoading(): void;
currentOptions: DialogOptions;
defaultOptions: DialogOptions;
setDefaultOptions(options: DialogOptions): void;
resetDefaultOptions(): void;
};
export default Dialog;
================================================
FILE: lib/dialog/dialog.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var queue = [];
var defaultOptions = {
show: false,
title: '',
width: null,
theme: 'default',
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
asyncClose: false,
beforeClose: null,
transition: 'scale',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: '',
};
var currentOptions = __assign({}, defaultOptions);
function getContext() {
var pages = getCurrentPages();
return pages[pages.length - 1];
}
var Dialog = function (options) {
options = __assign(__assign({}, currentOptions), options);
return new Promise(function (resolve, reject) {
var context = (typeof options.context === 'function'
? options.context()
: options.context) || getContext();
var dialog = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (dialog) {
dialog.setData(__assign({ callback: function (action, instance) {
action === 'confirm' ? resolve(instance) : reject(instance);
} }, options));
wx.nextTick(function () {
dialog.setData({ show: true });
});
queue.push(dialog);
}
else {
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
}
});
};
Dialog.alert = function (options) { return Dialog(options); };
Dialog.confirm = function (options) {
return Dialog(__assign({ showCancelButton: true }, options));
};
Dialog.close = function () {
queue.forEach(function (dialog) {
dialog.close();
});
queue = [];
};
Dialog.stopLoading = function () {
queue.forEach(function (dialog) {
dialog.stopLoading();
});
};
Dialog.currentOptions = currentOptions;
Dialog.defaultOptions = defaultOptions;
Dialog.setDefaultOptions = function (options) {
currentOptions = __assign(__assign({}, currentOptions), options);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions = function () {
currentOptions = __assign({}, defaultOptions);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions();
exports.default = Dialog;
================================================
FILE: lib/dialog/index.d.ts
================================================
export {};
================================================
FILE: lib/dialog/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var button_1 = require("../mixins/button");
var color_1 = require("../common/color");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
mixins: [button_1.button],
classes: ['cancle-button-class', 'confirm-button-class'],
props: {
show: {
type: Boolean,
observer: function (show) {
!show && this.stopLoading();
},
},
title: String,
message: String,
theme: {
type: String,
value: 'default',
},
confirmButtonId: String,
className: String,
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
beforeClose: null,
overlayStyle: String,
useSlot: Boolean,
useTitleSlot: Boolean,
useConfirmButtonSlot: Boolean,
useCancelButtonSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: null,
zIndex: {
type: Number,
value: 2000,
},
confirmButtonText: {
type: String,
value: '确认',
},
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonColor: {
type: String,
value: color_1.RED,
},
cancelButtonColor: {
type: String,
value: color_1.GRAY,
},
showConfirmButton: {
type: Boolean,
value: true,
},
overlay: {
type: Boolean,
value: true,
},
transition: {
type: String,
value: 'scale',
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
loading: {
confirm: false,
cancel: false,
},
callback: (function () { }),
},
methods: {
onConfirm: function () {
this.handleAction('confirm');
},
onCancel: function () {
this.handleAction('cancel');
},
onClickOverlay: function () {
this.close('overlay');
},
close: function (action) {
this.setData({ show: false });
this.closeAction = action;
},
onAfterLeave: function () {
var action = this.closeAction;
this.$emit('close', action);
var callback = this.data.callback;
if (callback) {
callback(action, this);
}
},
stopLoading: function () {
this.setData({
loading: {
confirm: false,
cancel: false,
},
});
},
handleAction: function (action) {
var _a;
var _this = this;
this.$emit(action, { dialog: this });
var _b = this.data, asyncClose = _b.asyncClose, beforeClose = _b.beforeClose;
if (!asyncClose && !beforeClose) {
this.close(action);
return;
}
this.setData((_a = {},
_a["loading.".concat(action)] = true,
_a));
if (beforeClose) {
(0, utils_1.toPromise)(beforeClose(action)).then(function (value) {
if (value) {
_this.close(action);
}
else {
_this.stopLoading();
}
});
}
},
},
});
================================================
FILE: lib/dialog/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-button": "../button/index",
"van-goods-action": "../goods-action/index",
"van-goods-action-button": "../goods-action-button/index"
}
}
================================================
FILE: lib/dialog/index.wxml
================================================
{{ message }}
{{ cancelButtonText }}
{{ confirmButtonText }}
================================================
FILE: lib/dialog/index.wxss
================================================
@import '../common/index.wxss';.van-dialog{background-color:var(--dialog-background-color,#fff);border-radius:var(--dialog-border-radius,16px);font-size:var(--dialog-font-size,16px);overflow:hidden;top:45%!important;width:var(--dialog-width,320px)}@media (max-width:321px){.van-dialog{width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-weight:var(--dialog-header-font-weight,500);line-height:var(--dialog-header-line-height,24px);padding-top:var(--dialog-header-padding-top,24px);text-align:center}.van-dialog__header--isolated{padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{-webkit-overflow-scrolling:touch;font-size:var(--dialog-message-font-size,14px);line-height:var(--dialog-message-line-height,20px);max-height:var(--dialog-message-max-height,60vh);overflow-y:auto;padding:var(--dialog-message-padding,24px);text-align:center}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--hasTitle{color:var(--dialog-has-title-message-text-color,#646566);padding-top:var(--dialog-has-title-message-padding-top,8px)}.van-dialog__message--round-button{color:#323233;padding-bottom:16px}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__message--justify{text-align:justify}.van-dialog__footer{display:flex}.van-dialog__footer--round-button{padding:8px 24px 16px!important;position:relative!important}.van-dialog__button{flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;transform:translate3d(-50%,-50%,0) scale(.9)}
================================================
FILE: lib/divider/index.d.ts
================================================
export {};
================================================
FILE: lib/divider/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
dashed: Boolean,
hairline: Boolean,
contentPosition: String,
fontSize: String,
borderColor: String,
textColor: String,
customStyle: String,
},
});
================================================
FILE: lib/divider/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: lib/divider/index.wxml
================================================
================================================
FILE: lib/divider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
'border-color': data.borderColor,
color: data.textColor,
'font-size': addUnit(data.fontSize),
},
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/divider/index.wxss
================================================
@import '../common/index.wxss';.van-divider{align-items:center;border:0 solid var(--divider-border-color,#ebedf0);color:var(--divider-text-color,#969799);display:flex;font-size:var(--divider-font-size,14px);line-height:var(--divider-line-height,24px);margin:var(--divider-margin,16px 0)}.van-divider:after,.van-divider:before{border-color:inherit;border-style:inherit;border-width:1px 0 0;box-sizing:border-box;display:block;flex:1;height:1px}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:var(--divider-content-right-width,10%)}
================================================
FILE: lib/dropdown-item/index.d.ts
================================================
export {};
================================================
FILE: lib/dropdown-item/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var relation_1 = require("../common/relation");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: ['item-title-class'],
field: true,
relation: (0, relation_1.useParent)('dropdown-menu', function () {
this.updateDataFromParent();
}),
props: {
value: {
type: null,
observer: 'rerender',
},
title: {
type: String,
observer: 'rerender',
},
disabled: Boolean,
titleClass: {
type: String,
observer: 'rerender',
},
options: {
type: Array,
value: [],
observer: 'rerender',
},
popupStyle: String,
useBeforeToggle: {
type: Boolean,
value: false,
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: '',
safeAreaTabBar: false,
},
methods: {
rerender: function () {
var _this = this;
wx.nextTick(function () {
var _a;
(_a = _this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData();
});
},
updateDataFromParent: function () {
if (this.parent) {
var _a = this.parent.data, overlay = _a.overlay, duration = _a.duration, activeColor = _a.activeColor, closeOnClickOverlay = _a.closeOnClickOverlay, direction = _a.direction, safeAreaTabBar = _a.safeAreaTabBar;
this.setData({
overlay: overlay,
duration: duration,
activeColor: activeColor,
closeOnClickOverlay: closeOnClickOverlay,
direction: direction,
safeAreaTabBar: safeAreaTabBar,
});
}
},
onOpen: function () {
this.$emit('open');
},
onOpened: function () {
this.$emit('opened');
},
onClose: function () {
this.$emit('close');
},
onClosed: function () {
this.$emit('closed');
this.setData({ showWrapper: false });
},
onOptionTap: function (event) {
var option = event.currentTarget.dataset.option;
var value = option.value;
var shouldEmitChange = this.data.value !== value;
this.setData({ showPopup: false, value: value });
this.$emit('close');
this.rerender();
if (shouldEmitChange) {
this.$emit('change', value);
}
},
toggle: function (show, options) {
var _this = this;
if (options === void 0) { options = {}; }
var showPopup = this.data.showPopup;
if (typeof show !== 'boolean') {
show = !showPopup;
}
if (show === showPopup) {
return;
}
this.onBeforeToggle(show).then(function (status) {
var _a;
if (!status) {
return;
}
_this.setData({
transition: !options.immediate,
showPopup: show,
});
if (show) {
(_a = _this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then(function (wrapperStyle) {
_this.setData({ wrapperStyle: wrapperStyle, showWrapper: true });
_this.rerender();
});
}
else {
_this.rerender();
}
});
},
onBeforeToggle: function (status) {
var _this = this;
var useBeforeToggle = this.data.useBeforeToggle;
if (!useBeforeToggle) {
return Promise.resolve(true);
}
return new Promise(function (resolve) {
_this.$emit('before-toggle', {
status: status,
callback: function (value) { return resolve(value); },
});
});
},
},
});
================================================
FILE: lib/dropdown-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/dropdown-item/index.wxml
================================================
{{ item.text }}
================================================
FILE: lib/dropdown-item/index.wxss
================================================
@import '../common/index.wxss';.van-dropdown-item{left:0;overflow:hidden;position:fixed;right:0}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:var(--dropdown-menu-option-active-color,#ee0a24)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
================================================
FILE: lib/dropdown-item/shared.d.ts
================================================
export interface Option {
text: string;
value: string | number;
icon: string;
}
================================================
FILE: lib/dropdown-item/shared.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
================================================
FILE: lib/dropdown-menu/index.d.ts
================================================
export {};
================================================
FILE: lib/dropdown-menu/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var utils_1 = require("../common/utils");
var ARRAY = [];
(0, component_1.VantComponent)({
field: true,
classes: ['title-class'],
relation: (0, relation_1.useChildren)('dropdown-item', function () {
this.updateItemListData();
}),
props: {
activeColor: {
type: String,
observer: 'updateChildrenData',
},
overlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
zIndex: {
type: Number,
value: 10,
},
duration: {
type: Number,
value: 200,
observer: 'updateChildrenData',
},
direction: {
type: String,
value: 'down',
observer: 'updateChildrenData',
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
closeOnClickOutside: {
type: Boolean,
value: true,
},
},
data: {
itemListData: [],
},
beforeCreate: function () {
var windowHeight = (0, utils_1.getSystemInfoSync)().windowHeight;
this.windowHeight = windowHeight;
ARRAY.push(this);
},
destroyed: function () {
var _this = this;
ARRAY = ARRAY.filter(function (item) { return item !== _this; });
},
methods: {
updateItemListData: function () {
this.setData({
itemListData: this.children.map(function (child) { return child.data; }),
});
},
updateChildrenData: function () {
this.children.forEach(function (child) {
child.updateDataFromParent();
});
},
toggleItem: function (active) {
this.children.forEach(function (item, index) {
var showPopup = item.data.showPopup;
if (index === active) {
item.toggle();
}
else if (showPopup) {
item.toggle(false, { immediate: true });
}
});
},
close: function () {
this.children.forEach(function (child) {
child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle: function () {
var _this = this;
var _a = this.data, zIndex = _a.zIndex, direction = _a.direction;
return (0, utils_1.getRect)(this, '.van-dropdown-menu').then(function (rect) {
var _a = rect.top, top = _a === void 0 ? 0 : _a, _b = rect.bottom, bottom = _b === void 0 ? 0 : _b;
var offset = direction === 'down' ? bottom : _this.windowHeight - top;
var wrapperStyle = "z-index: ".concat(zIndex, ";");
if (direction === 'down') {
wrapperStyle += "top: ".concat((0, utils_1.addUnit)(offset), ";");
}
else {
wrapperStyle += "bottom: ".concat((0, utils_1.addUnit)(offset), ";");
}
return wrapperStyle;
});
},
onTitleTap: function (event) {
var _this = this;
var index = event.currentTarget.dataset.index;
var child = this.children[index];
if (!child.data.disabled) {
ARRAY.forEach(function (menuItem) {
if (menuItem &&
menuItem.data.closeOnClickOutside &&
menuItem !== _this) {
menuItem.close();
}
});
this.toggleItem(index);
}
},
},
});
================================================
FILE: lib/dropdown-menu/index.json
================================================
{
"component": true
}
================================================
FILE: lib/dropdown-menu/index.wxml
================================================
================================================
FILE: lib/dropdown-menu/index.wxs
================================================
/* eslint-disable */
function displayTitle(item) {
if (item.title) {
return item.title;
}
var match = item.options.filter(function(option) {
return option.value === item.value;
});
var displayTitle = match.length ? match[0].text : '';
return displayTitle;
}
module.exports = {
displayTitle: displayTitle
};
================================================
FILE: lib/dropdown-menu/index.wxss
================================================
@import '../common/index.wxss';.van-dropdown-menu{background-color:var(--dropdown-menu-background-color,#fff);box-shadow:var(--dropdown-menu-box-shadow,0 2px 12px hsla(210,1%,40%,.12));display:flex;height:var(--dropdown-menu-height,50px);-webkit-user-select:none;user-select:none}.van-dropdown-menu__item{align-items:center;display:flex;flex:1;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{box-sizing:border-box;color:var(--dropdown-menu-title-text-color,#323233);font-size:var(--dropdown-menu-title-font-size,15px);line-height:var(--dropdown-menu-title-line-height,18px);max-width:100%;padding:var(--dropdown-menu-title-padding,0 24px 0 8px);position:relative}.van-dropdown-menu__title:after{border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;content:"";margin-top:-5px;opacity:.8;position:absolute;right:11px;top:50%;transform:rotate(-45deg)}.van-dropdown-menu__title--active{color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;transform:rotate(135deg)}
================================================
FILE: lib/empty/index.d.ts
================================================
export {};
================================================
FILE: lib/empty/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
description: String,
image: {
type: String,
value: 'default',
},
},
});
================================================
FILE: lib/empty/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: lib/empty/index.wxml
================================================
{{ description }}
================================================
FILE: lib/empty/index.wxs
================================================
/* eslint-disable */
var PRESETS = ['error', 'search', 'default', 'network'];
function imageUrl(image) {
if (PRESETS.indexOf(image) !== -1) {
return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png';
}
return image;
}
module.exports = {
imageUrl: imageUrl,
};
================================================
FILE: lib/empty/index.wxss
================================================
@import '../common/index.wxss';.van-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:32px 0}.van-empty__image{height:160px;width:160px}.van-empty__image:empty{display:none}.van-empty__image__img{height:100%;width:100%}.van-empty__image:not(:empty)+.van-empty__image{display:none}.van-empty__description{color:#969799;font-size:14px;line-height:20px;margin-top:16px;padding:0 60px}.van-empty__description:empty,.van-empty__description:not(:empty)+.van-empty__description{display:none}.van-empty__bottom{margin-top:24px}
================================================
FILE: lib/field/index.d.ts
================================================
export {};
================================================
FILE: lib/field/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("../common/utils");
var component_1 = require("../common/component");
var props_1 = require("./props");
(0, component_1.VantComponent)({
field: true,
classes: ['input-class', 'right-icon-class', 'label-class'],
props: __assign(__assign(__assign(__assign({}, props_1.commonProps), props_1.inputProps), props_1.textareaProps), { size: String, icon: String, label: String, error: Boolean, center: Boolean, isLink: Boolean, leftIcon: String, rightIcon: String, autosize: null, required: Boolean, iconClass: String, clickable: Boolean, inputAlign: String, customStyle: String, errorMessage: String, arrowDirection: String, showWordLimit: Boolean, errorMessageAlign: String, readonly: {
type: Boolean,
observer: 'setShowClear',
}, clearable: {
type: Boolean,
observer: 'setShowClear',
}, clearTrigger: {
type: String,
value: 'focus',
}, border: {
type: Boolean,
value: true,
}, titleWidth: {
type: String,
value: '6.2em',
}, clearIcon: {
type: String,
value: 'clear',
}, extraEventParams: {
type: Boolean,
value: false,
} }),
data: {
focused: false,
innerValue: '',
showClear: false,
},
watch: {
value: function (value) {
if (value !== this.value) {
this.setData({ innerValue: value });
this.value = value;
this.setShowClear();
}
},
clearTrigger: function () {
this.setShowClear();
},
},
created: function () {
this.value = this.data.value;
this.setData({ innerValue: this.value });
},
methods: {
formatValue: function (value) {
var maxlength = this.data.maxlength;
if (maxlength !== -1 && value.length > maxlength) {
return value.slice(0, maxlength);
}
return value;
},
onInput: function (event) {
var _a = (event.detail || {}).value, value = _a === void 0 ? '' : _a;
var formatValue = this.formatValue(value);
this.value = formatValue;
this.setShowClear();
return this.emitChange(__assign(__assign({}, event.detail), { value: formatValue }));
},
onFocus: function (event) {
this.focused = true;
this.setShowClear();
this.$emit('focus', event.detail);
},
onBlur: function (event) {
this.focused = false;
this.setShowClear();
this.$emit('blur', event.detail);
},
onClickIcon: function () {
this.$emit('click-icon');
},
onClickInput: function (event) {
this.$emit('click-input', event.detail);
},
onClear: function () {
var _this = this;
this.setData({ innerValue: '' });
this.value = '';
this.setShowClear();
(0, utils_1.nextTick)(function () {
_this.emitChange({ value: '' });
_this.$emit('clear', '');
});
},
onConfirm: function (event) {
var _a = (event.detail || {}).value, value = _a === void 0 ? '' : _a;
this.value = value;
this.setShowClear();
this.$emit('confirm', value);
},
setValue: function (value) {
this.value = value;
this.setShowClear();
if (value === '') {
this.setData({ innerValue: '' });
}
this.emitChange({ value: value });
},
onLineChange: function (event) {
this.$emit('linechange', event.detail);
},
onKeyboardHeightChange: function (event) {
this.$emit('keyboardheightchange', event.detail);
},
onBindNicknameReview: function (event) {
this.$emit('nicknamereview', event.detail);
},
emitChange: function (detail) {
var extraEventParams = this.data.extraEventParams;
this.setData({ value: detail.value });
var result;
var data = extraEventParams
? __assign(__assign({}, detail), { callback: function (data) {
result = data;
} }) : detail.value;
this.$emit('input', data);
this.$emit('change', data);
return result;
},
setShowClear: function () {
var _a = this.data, clearable = _a.clearable, readonly = _a.readonly, clearTrigger = _a.clearTrigger;
var _b = this, focused = _b.focused, value = _b.value;
var showClear = false;
if (clearable && !readonly) {
var hasValue = !!value;
var trigger = clearTrigger === 'always' || (clearTrigger === 'focus' && focused);
showClear = hasValue && trigger;
}
this.setView({ showClear: showClear });
},
noop: function () { },
},
});
================================================
FILE: lib/field/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/field/index.wxml
================================================
================================================
FILE: lib/field/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function inputStyle(autosize) {
if (autosize && autosize.constructor === 'Object') {
return style({
'min-height': addUnit(autosize.minHeight),
'max-height': addUnit(autosize.maxHeight),
});
}
return '';
}
module.exports = {
inputStyle: inputStyle,
};
================================================
FILE: lib/field/index.wxss
================================================
@import '../common/index.wxss';.van-field{--cell-icon-size:var(--field-icon-size,16px)}.van-field__label{color:var(--field-label-color,#646566)}.van-field__label--disabled{color:var(--field-disabled-text-color,#c8c9cc)}.van-field__body{align-items:center;display:flex}.van-field__body--textarea{box-sizing:border-box;line-height:1.2em;min-height:var(--cell-line-height,24px);padding:3.6px 0}.van-field__control:empty+.van-field__control{display:block}.van-field__control{background-color:initial;border:0;box-sizing:border-box;color:var(--field-input-text-color,#323233);display:none;height:var(--cell-line-height,24px);line-height:inherit;margin:0;min-height:var(--cell-line-height,24px);padding:0;position:relative;resize:none;text-align:left;width:100%}.van-field__control:empty{display:none}.van-field__control--textarea{height:var(--field-text-area-min-height,18px);min-height:var(--field-text-area-min-height,18px)}.van-field__control--error{color:var(--field-input-error-text-color,#ee0a24)}.van-field__control--disabled{background-color:initial;color:var(--field-input-disabled-text-color,#c8c9cc);opacity:1}.van-field__control--center{text-align:center}.van-field__control--right{text-align:right}.van-field__control--custom{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__placeholder{color:var(--field-placeholder-text-color,#c8c9cc);left:0;pointer-events:none;position:absolute;right:0;top:0}.van-field__placeholder--error{color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;margin-right:calc(var(--padding-xs, 8px)*-1);padding:0 var(--padding-xs,8px);vertical-align:middle}.van-field__button,.van-field__clear-root,.van-field__icon-container{flex-shrink:0}.van-field__clear-root{color:var(--field-clear-icon-color,#c8c9cc);font-size:var(--field-clear-icon-size,16px)}.van-field__icon-container{color:var(--field-icon-container-color,#969799);font-size:var(--field-icon-size,16px)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{color:var(--field-error-message-color,#ee0a24);display:block;font-size:var(--field-error-message-text-font-size,12px);text-align:left}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{color:var(--field-word-limit-color,#646566);font-size:var(--field-word-limit-font-size,12px);line-height:var(--field-word-limit-line-height,16px);margin-top:var(--padding-base,4px);text-align:right}.van-field__word-num{display:inline}.van-field__word-num--full{color:var(--field-word-num-full-color,#ee0a24)}
================================================
FILE: lib/field/input.wxml
================================================
================================================
FILE: lib/field/props.d.ts
================================================
///
export declare const commonProps: WechatMiniprogram.Component.PropertyOption;
export declare const inputProps: WechatMiniprogram.Component.PropertyOption;
export declare const textareaProps: WechatMiniprogram.Component.PropertyOption;
================================================
FILE: lib/field/props.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.textareaProps = exports.inputProps = exports.commonProps = void 0;
exports.commonProps = {
value: String,
placeholder: String,
placeholderStyle: String,
placeholderClass: String,
disabled: Boolean,
maxlength: {
type: Number,
value: -1,
},
cursorSpacing: {
type: Number,
value: 50,
},
autoFocus: Boolean,
focus: Boolean,
cursor: {
type: Number,
value: -1,
},
selectionStart: {
type: Number,
value: -1,
},
selectionEnd: {
type: Number,
value: -1,
},
adjustPosition: {
type: Boolean,
value: true,
},
holdKeyboard: Boolean,
};
exports.inputProps = {
type: {
type: String,
value: 'text',
},
password: Boolean,
confirmType: String,
confirmHold: Boolean,
alwaysEmbed: Boolean,
};
exports.textareaProps = {
autoHeight: Boolean,
fixed: Boolean,
showConfirmBar: {
type: Boolean,
value: true,
},
disableDefaultPadding: {
type: Boolean,
value: true,
},
};
================================================
FILE: lib/field/textarea.wxml
================================================
================================================
FILE: lib/field/types.d.ts
================================================
export interface InputDetails {
/** 输入框内容 */
value: string;
/** 光标位置 */
cursor?: number;
/** keyCode 为键值 (目前工具还不支持返回keyCode参数) `2.1.0` 起支持 */
keyCode?: number;
}
================================================
FILE: lib/field/types.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
================================================
FILE: lib/goods-action/index.d.ts
================================================
export {};
================================================
FILE: lib/goods-action/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('goods-action-button', function () {
this.children.forEach(function (item) {
item.updateStyle();
});
}),
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
});
================================================
FILE: lib/goods-action/index.json
================================================
{
"component": true
}
================================================
FILE: lib/goods-action/index.wxml
================================================
================================================
FILE: lib/goods-action/index.wxss
================================================
@import '../common/index.wxss';.van-goods-action{align-items:center;background-color:var(--goods-action-background-color,#fff);bottom:0;box-sizing:initial;display:flex;height:var(--goods-action-height,50px);left:0;position:fixed;right:0}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
================================================
FILE: lib/goods-action-button/index.d.ts
================================================
export {};
================================================
FILE: lib/goods-action-button/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var button_1 = require("../mixins/button");
var link_1 = require("../mixins/link");
(0, component_1.VantComponent)({
mixins: [link_1.link, button_1.button],
relation: (0, relation_1.useParent)('goods-action'),
props: {
text: String,
color: String,
size: {
type: String,
value: 'normal',
},
loading: Boolean,
disabled: Boolean,
plain: Boolean,
type: {
type: String,
value: 'danger',
},
customStyle: {
type: String,
value: '',
},
},
methods: {
onClick: function (event) {
this.$emit('click', event.detail);
this.jumpLink();
},
updateStyle: function () {
if (this.parent == null) {
return;
}
var index = this.index;
var _a = this.parent.children, children = _a === void 0 ? [] : _a;
this.setData({
isFirst: index === 0,
isLast: index === children.length - 1,
});
},
},
});
================================================
FILE: lib/goods-action-button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
================================================
FILE: lib/goods-action-button/index.wxml
================================================
{{ text }}
================================================
FILE: lib/goods-action-button/index.wxss
================================================
@import '../common/index.wxss';:host{flex:1}.van-goods-action-button{--button-warning-background-color:var(--goods-action-button-warning-color,linear-gradient(to right,#ffd01e,#ff8917));--button-danger-background-color:var(--goods-action-button-danger-color,linear-gradient(to right,#ff6034,#ee0a24));--button-default-height:var(--goods-action-button-height,40px);--button-line-height:var(--goods-action-button-line-height,20px);--button-plain-background-color:var(--goods-action-button-plain-color,#fff);--button-border-width:0;display:block}.van-goods-action-button--first{--button-border-radius:999px 0 0 var(--goods-action-button-border-radius,999px);margin-left:5px}.van-goods-action-button--last{--button-border-radius:0 999px var(--goods-action-button-border-radius,999px) 0;margin-right:5px}.van-goods-action-button--first.van-goods-action-button--last{--button-border-radius:var(--goods-action-button-border-radius,999px)}.van-goods-action-button--plain{--button-border-width:1px}.van-goods-action-button__inner{font-weight:var(--font-weight-bold,500)!important;width:100%}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
================================================
FILE: lib/goods-action-icon/index.d.ts
================================================
export {};
================================================
FILE: lib/goods-action-icon/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var button_1 = require("../mixins/button");
var link_1 = require("../mixins/link");
(0, component_1.VantComponent)({
classes: ['icon-class', 'text-class', 'info-class'],
mixins: [link_1.link, button_1.button],
props: {
text: String,
dot: Boolean,
info: String,
icon: String,
size: String,
color: String,
classPrefix: {
type: String,
value: 'van-icon',
},
disabled: Boolean,
loading: Boolean,
},
methods: {
onClick: function (event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: lib/goods-action-icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-button": "../button/index"
}
}
================================================
FILE: lib/goods-action-icon/index.wxml
================================================
{{ text }}
================================================
FILE: lib/goods-action-icon/index.wxss
================================================
@import '../common/index.wxss';.van-goods-action-icon{border:none!important;color:var(--goods-action-icon-text-color,#646566)!important;display:flex!important;flex-direction:column;font-size:var(--goods-action-icon-font-size,10px)!important;height:var(--goods-action-icon-height,50px)!important;justify-content:center!important;line-height:1!important;min-width:var(--goods-action-icon-width,48px)}.van-goods-action-icon__icon{color:var(--goods-action-icon-color,#323233);display:flex;font-size:var(--goods-action-icon-size,18px);margin:0 auto 5px}
================================================
FILE: lib/grid/index.d.ts
================================================
export {};
================================================
FILE: lib/grid/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('grid-item'),
props: {
square: {
type: Boolean,
observer: 'updateChildren',
},
gutter: {
type: null,
value: 0,
observer: 'updateChildren',
},
clickable: {
type: Boolean,
observer: 'updateChildren',
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren',
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
direction: {
type: String,
observer: 'updateChildren',
},
iconSize: {
type: String,
observer: 'updateChildren',
},
reverse: {
type: Boolean,
value: false,
observer: 'updateChildren',
},
},
methods: {
updateChildren: function () {
this.children.forEach(function (child) {
child.updateStyle();
});
},
},
});
================================================
FILE: lib/grid/index.json
================================================
{
"component": true
}
================================================
FILE: lib/grid/index.wxml
================================================
================================================
FILE: lib/grid/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'padding-left': addUnit(data.gutter),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/grid/index.wxss
================================================
@import '../common/index.wxss';.van-grid{box-sizing:border-box;overflow:hidden;position:relative}
================================================
FILE: lib/grid-item/index.d.ts
================================================
export {};
================================================
FILE: lib/grid-item/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var link_1 = require("../mixins/link");
(0, component_1.VantComponent)({
relation: (0, relation_1.useParent)('grid'),
classes: ['content-class', 'icon-class', 'text-class'],
mixins: [link_1.link],
props: {
icon: String,
iconColor: String,
iconPrefix: {
type: String,
value: 'van-icon',
},
dot: Boolean,
info: null,
badge: null,
text: String,
useSlot: Boolean,
},
data: {
viewStyle: '',
},
mounted: function () {
this.updateStyle();
},
methods: {
updateStyle: function () {
if (!this.parent) {
return;
}
var _a = this.parent, data = _a.data, children = _a.children;
var columnNum = data.columnNum, border = data.border, square = data.square, gutter = data.gutter, clickable = data.clickable, center = data.center, direction = data.direction, reverse = data.reverse, iconSize = data.iconSize;
this.setData({
center: center,
border: border,
square: square,
gutter: gutter,
clickable: clickable,
direction: direction,
reverse: reverse,
iconSize: iconSize,
index: children.indexOf(this),
columnNum: columnNum,
});
},
onClick: function () {
this.$emit('click');
this.jumpLink();
},
},
});
================================================
FILE: lib/grid-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/grid-item/index.wxml
================================================
{{ text }}
================================================
FILE: lib/grid-item/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapperStyle(data) {
var width = 100 / data.columnNum + '%';
return style({
width: width,
'padding-top': data.square ? width : null,
'padding-right': addUnit(data.gutter),
'margin-top':
data.index >= data.columnNum && !data.square
? addUnit(data.gutter)
: null,
});
}
function contentStyle(data) {
return data.square
? style({
right: addUnit(data.gutter),
bottom: addUnit(data.gutter),
height: 'auto',
})
: '';
}
module.exports = {
wrapperStyle: wrapperStyle,
contentStyle: contentStyle,
};
================================================
FILE: lib/grid-item/index.wxss
================================================
@import '../common/index.wxss';.van-grid-item{box-sizing:border-box;float:left;position:relative}.van-grid-item--square{height:0}.van-grid-item__content{background-color:var(--grid-item-content-background-color,#fff);box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:var(--grid-item-content-padding,16px 8px)}.van-grid-item__content:after{border-width:0 1px 1px 0;z-index:1}.van-grid-item__content--surround:after{border-width:1px}.van-grid-item__content--center{align-items:center;justify-content:center}.van-grid-item__content--square{left:0;position:absolute;right:0;top:0}.van-grid-item__content--horizontal{flex-direction:row}.van-grid-item__content--horizontal .van-grid-item__text{margin:0 0 0 8px}.van-grid-item__content--reverse{flex-direction:column-reverse}.van-grid-item__content--reverse .van-grid-item__text{margin:0 0 8px}.van-grid-item__content--horizontal.van-grid-item__content--reverse{flex-direction:row-reverse}.van-grid-item__content--horizontal.van-grid-item__content--reverse .van-grid-item__text{margin:0 8px 0 0}.van-grid-item__content--clickable:active{background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{align-items:center;display:flex;font-size:var(--grid-item-icon-size,26px);height:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:var(--grid-item-text-color,#646566);font-size:var(--grid-item-text-font-size,12px)}.van-grid-item__icon+.van-grid-item__text{margin-top:8px}
================================================
FILE: lib/icon/index.d.ts
================================================
export {};
================================================
FILE: lib/icon/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: ['info-class'],
props: {
dot: Boolean,
info: null,
size: null,
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon',
},
name: String,
},
methods: {
onClick: function () {
this.$emit('click');
},
},
});
================================================
FILE: lib/icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: lib/icon/index.wxml
================================================
================================================
FILE: lib/icon/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isImage(name) {
return name.indexOf('/') !== -1;
}
function rootClass(data) {
var classes = ['custom-class'];
if (data.classPrefix !== 'van-icon') {
classes.push('van-icon--custom')
}
if (data.classPrefix != null) {
classes.push(data.classPrefix);
}
if (isImage(data.name)) {
classes.push('van-icon--image');
} else if (data.classPrefix != null) {
classes.push(data.classPrefix + '-' + data.name);
}
return classes.join(' ');
}
function rootStyle(data) {
return style([
{
color: data.color,
'font-size': addUnit(data.size),
},
data.customStyle,
]);
}
module.exports = {
isImage: isImage,
rootClass: rootClass,
rootStyle: rootStyle,
};
================================================
FILE: lib/icon/index.wxss
================================================
@import '../common/index.wxss';.van-icon{text-rendering:auto;-webkit-font-smoothing:antialiased;font:normal normal normal 14px/1 vant-icon;font:normal normal normal 14px/1 var(--van-icon-font-family,"vant-icon");font-size:inherit;position:relative}.van-icon,.van-icon:before{display:inline-block}.van-icon-contact:before{content:"\e753"}.van-icon-notes:before{content:"\e63c"}.van-icon-records:before{content:"\e63d"}.van-icon-cash-back-record:before{content:"\e63e"}.van-icon-newspaper:before{content:"\e63f"}.van-icon-discount:before{content:"\e640"}.van-icon-completed:before{content:"\e641"}.van-icon-user:before{content:"\e642"}.van-icon-description:before{content:"\e643"}.van-icon-list-switch:before{content:"\e6ad"}.van-icon-list-switching:before{content:"\e65a"}.van-icon-link-o:before{content:"\e751"}.van-icon-miniprogram-o:before{content:"\e752"}.van-icon-qq:before{content:"\e74e"}.van-icon-wechat-moments:before{content:"\e74f"}.van-icon-weibo:before{content:"\e750"}.van-icon-cash-o:before{content:"\e74d"}.van-icon-guide-o:before{content:"\e74c"}.van-icon-invitation:before{content:"\e6d6"}.van-icon-shield-o:before{content:"\e74b"}.van-icon-exchange:before{content:"\e6af"}.van-icon-eye:before{content:"\e6b0"}.van-icon-enlarge:before{content:"\e6b1"}.van-icon-expand-o:before{content:"\e6b2"}.van-icon-eye-o:before{content:"\e6b3"}.van-icon-expand:before{content:"\e6b4"}.van-icon-filter-o:before{content:"\e6b5"}.van-icon-fire:before{content:"\e6b6"}.van-icon-fail:before{content:"\e6b7"}.van-icon-failure:before{content:"\e6b8"}.van-icon-fire-o:before{content:"\e6b9"}.van-icon-flag-o:before{content:"\e6ba"}.van-icon-font:before{content:"\e6bb"}.van-icon-font-o:before{content:"\e6bc"}.van-icon-gem-o:before{content:"\e6bd"}.van-icon-flower-o:before{content:"\e6be"}.van-icon-gem:before{content:"\e6bf"}.van-icon-gift-card:before{content:"\e6c0"}.van-icon-friends:before{content:"\e6c1"}.van-icon-friends-o:before{content:"\e6c2"}.van-icon-gold-coin:before{content:"\e6c3"}.van-icon-gold-coin-o:before{content:"\e6c4"}.van-icon-good-job-o:before{content:"\e6c5"}.van-icon-gift:before{content:"\e6c6"}.van-icon-gift-o:before{content:"\e6c7"}.van-icon-gift-card-o:before{content:"\e6c8"}.van-icon-good-job:before{content:"\e6c9"}.van-icon-home-o:before{content:"\e6ca"}.van-icon-goods-collect:before{content:"\e6cb"}.van-icon-graphic:before{content:"\e6cc"}.van-icon-goods-collect-o:before{content:"\e6cd"}.van-icon-hot-o:before{content:"\e6ce"}.van-icon-info:before{content:"\e6cf"}.van-icon-hotel-o:before{content:"\e6d0"}.van-icon-info-o:before{content:"\e6d1"}.van-icon-hot-sale-o:before{content:"\e6d2"}.van-icon-hot:before{content:"\e6d3"}.van-icon-like:before{content:"\e6d4"}.van-icon-idcard:before{content:"\e6d5"}.van-icon-like-o:before{content:"\e6d7"}.van-icon-hot-sale:before{content:"\e6d8"}.van-icon-location-o:before{content:"\e6d9"}.van-icon-location:before{content:"\e6da"}.van-icon-label:before{content:"\e6db"}.van-icon-lock:before{content:"\e6dc"}.van-icon-label-o:before{content:"\e6dd"}.van-icon-map-marked:before{content:"\e6de"}.van-icon-logistics:before{content:"\e6df"}.van-icon-manager:before{content:"\e6e0"}.van-icon-more:before{content:"\e6e1"}.van-icon-live:before{content:"\e6e2"}.van-icon-manager-o:before{content:"\e6e3"}.van-icon-medal:before{content:"\e6e4"}.van-icon-more-o:before{content:"\e6e5"}.van-icon-music-o:before{content:"\e6e6"}.van-icon-music:before{content:"\e6e7"}.van-icon-new-arrival-o:before{content:"\e6e8"}.van-icon-medal-o:before{content:"\e6e9"}.van-icon-new-o:before{content:"\e6ea"}.van-icon-free-postage:before{content:"\e6eb"}.van-icon-newspaper-o:before{content:"\e6ec"}.van-icon-new-arrival:before{content:"\e6ed"}.van-icon-minus:before{content:"\e6ee"}.van-icon-orders-o:before{content:"\e6ef"}.van-icon-new:before{content:"\e6f0"}.van-icon-paid:before{content:"\e6f1"}.van-icon-notes-o:before{content:"\e6f2"}.van-icon-other-pay:before{content:"\e6f3"}.van-icon-pause-circle:before{content:"\e6f4"}.van-icon-pause:before{content:"\e6f5"}.van-icon-pause-circle-o:before{content:"\e6f6"}.van-icon-peer-pay:before{content:"\e6f7"}.van-icon-pending-payment:before{content:"\e6f8"}.van-icon-passed:before{content:"\e6f9"}.van-icon-plus:before{content:"\e6fa"}.van-icon-phone-circle-o:before{content:"\e6fb"}.van-icon-phone-o:before{content:"\e6fc"}.van-icon-printer:before{content:"\e6fd"}.van-icon-photo-fail:before{content:"\e6fe"}.van-icon-phone:before{content:"\e6ff"}.van-icon-photo-o:before{content:"\e700"}.van-icon-play-circle:before{content:"\e701"}.van-icon-play:before{content:"\e702"}.van-icon-phone-circle:before{content:"\e703"}.van-icon-point-gift-o:before{content:"\e704"}.van-icon-point-gift:before{content:"\e705"}.van-icon-play-circle-o:before{content:"\e706"}.van-icon-shrink:before{content:"\e707"}.van-icon-photo:before{content:"\e708"}.van-icon-qr:before{content:"\e709"}.van-icon-qr-invalid:before{content:"\e70a"}.van-icon-question-o:before{content:"\e70b"}.van-icon-revoke:before{content:"\e70c"}.van-icon-replay:before{content:"\e70d"}.van-icon-service:before{content:"\e70e"}.van-icon-question:before{content:"\e70f"}.van-icon-search:before{content:"\e710"}.van-icon-refund-o:before{content:"\e711"}.van-icon-service-o:before{content:"\e712"}.van-icon-scan:before{content:"\e713"}.van-icon-share:before{content:"\e714"}.van-icon-send-gift-o:before{content:"\e715"}.van-icon-share-o:before{content:"\e716"}.van-icon-setting:before{content:"\e717"}.van-icon-points:before{content:"\e718"}.van-icon-photograph:before{content:"\e719"}.van-icon-shop:before{content:"\e71a"}.van-icon-shop-o:before{content:"\e71b"}.van-icon-shop-collect-o:before{content:"\e71c"}.van-icon-shop-collect:before{content:"\e71d"}.van-icon-smile:before{content:"\e71e"}.van-icon-shopping-cart-o:before{content:"\e71f"}.van-icon-sign:before{content:"\e720"}.van-icon-sort:before{content:"\e721"}.van-icon-star-o:before{content:"\e722"}.van-icon-smile-comment-o:before{content:"\e723"}.van-icon-stop:before{content:"\e724"}.van-icon-stop-circle-o:before{content:"\e725"}.van-icon-smile-o:before{content:"\e726"}.van-icon-star:before{content:"\e727"}.van-icon-success:before{content:"\e728"}.van-icon-stop-circle:before{content:"\e729"}.van-icon-records-o:before{content:"\e72a"}.van-icon-shopping-cart:before{content:"\e72b"}.van-icon-tosend:before{content:"\e72c"}.van-icon-todo-list:before{content:"\e72d"}.van-icon-thumb-circle-o:before{content:"\e72e"}.van-icon-thumb-circle:before{content:"\e72f"}.van-icon-umbrella-circle:before{content:"\e730"}.van-icon-underway:before{content:"\e731"}.van-icon-upgrade:before{content:"\e732"}.van-icon-todo-list-o:before{content:"\e733"}.van-icon-tv-o:before{content:"\e734"}.van-icon-underway-o:before{content:"\e735"}.van-icon-user-o:before{content:"\e736"}.van-icon-vip-card-o:before{content:"\e737"}.van-icon-vip-card:before{content:"\e738"}.van-icon-send-gift:before{content:"\e739"}.van-icon-wap-home:before{content:"\e73a"}.van-icon-wap-nav:before{content:"\e73b"}.van-icon-volume-o:before{content:"\e73c"}.van-icon-video:before{content:"\e73d"}.van-icon-wap-home-o:before{content:"\e73e"}.van-icon-volume:before{content:"\e73f"}.van-icon-warning:before{content:"\e740"}.van-icon-weapp-nav:before{content:"\e741"}.van-icon-wechat-pay:before{content:"\e742"}.van-icon-warning-o:before{content:"\e743"}.van-icon-wechat:before{content:"\e744"}.van-icon-setting-o:before{content:"\e745"}.van-icon-youzan-shield:before{content:"\e746"}.van-icon-warn-o:before{content:"\e747"}.van-icon-smile-comment:before{content:"\e748"}.van-icon-user-circle-o:before{content:"\e749"}.van-icon-video-o:before{content:"\e74a"}.van-icon-add-square:before{content:"\e65c"}.van-icon-add:before{content:"\e65d"}.van-icon-arrow-down:before{content:"\e65e"}.van-icon-arrow-up:before{content:"\e65f"}.van-icon-arrow:before{content:"\e660"}.van-icon-after-sale:before{content:"\e661"}.van-icon-add-o:before{content:"\e662"}.van-icon-alipay:before{content:"\e663"}.van-icon-ascending:before{content:"\e664"}.van-icon-apps-o:before{content:"\e665"}.van-icon-aim:before{content:"\e666"}.van-icon-award:before{content:"\e667"}.van-icon-arrow-left:before{content:"\e668"}.van-icon-award-o:before{content:"\e669"}.van-icon-audio:before{content:"\e66a"}.van-icon-bag-o:before{content:"\e66b"}.van-icon-balance-list:before{content:"\e66c"}.van-icon-back-top:before{content:"\e66d"}.van-icon-bag:before{content:"\e66e"}.van-icon-balance-pay:before{content:"\e66f"}.van-icon-balance-o:before{content:"\e670"}.van-icon-bar-chart-o:before{content:"\e671"}.van-icon-bars:before{content:"\e672"}.van-icon-balance-list-o:before{content:"\e673"}.van-icon-birthday-cake-o:before{content:"\e674"}.van-icon-bookmark:before{content:"\e675"}.van-icon-bill:before{content:"\e676"}.van-icon-bell:before{content:"\e677"}.van-icon-browsing-history-o:before{content:"\e678"}.van-icon-browsing-history:before{content:"\e679"}.van-icon-bookmark-o:before{content:"\e67a"}.van-icon-bulb-o:before{content:"\e67b"}.van-icon-bullhorn-o:before{content:"\e67c"}.van-icon-bill-o:before{content:"\e67d"}.van-icon-calendar-o:before{content:"\e67e"}.van-icon-brush-o:before{content:"\e67f"}.van-icon-card:before{content:"\e680"}.van-icon-cart-o:before{content:"\e681"}.van-icon-cart-circle:before{content:"\e682"}.van-icon-cart-circle-o:before{content:"\e683"}.van-icon-cart:before{content:"\e684"}.van-icon-cash-on-deliver:before{content:"\e685"}.van-icon-cash-back-record-o:before{content:"\e686"}.van-icon-cashier-o:before{content:"\e687"}.van-icon-chart-trending-o:before{content:"\e688"}.van-icon-certificate:before{content:"\e689"}.van-icon-chat:before{content:"\e68a"}.van-icon-clear:before{content:"\e68b"}.van-icon-chat-o:before{content:"\e68c"}.van-icon-checked:before{content:"\e68d"}.van-icon-clock:before{content:"\e68e"}.van-icon-clock-o:before{content:"\e68f"}.van-icon-close:before{content:"\e690"}.van-icon-closed-eye:before{content:"\e691"}.van-icon-circle:before{content:"\e692"}.van-icon-cluster-o:before{content:"\e693"}.van-icon-column:before{content:"\e694"}.van-icon-comment-circle-o:before{content:"\e695"}.van-icon-cluster:before{content:"\e696"}.van-icon-comment:before{content:"\e697"}.van-icon-comment-o:before{content:"\e698"}.van-icon-comment-circle:before{content:"\e699"}.van-icon-completed-o:before{content:"\e69a"}.van-icon-credit-pay:before{content:"\e69b"}.van-icon-coupon:before{content:"\e69c"}.van-icon-debit-pay:before{content:"\e69d"}.van-icon-coupon-o:before{content:"\e69e"}.van-icon-contact-o:before{content:"\e69f"}.van-icon-descending:before{content:"\e6a0"}.van-icon-desktop-o:before{content:"\e6a1"}.van-icon-diamond-o:before{content:"\e6a2"}.van-icon-description-o:before{content:"\e6a3"}.van-icon-delete:before{content:"\e6a4"}.van-icon-diamond:before{content:"\e6a5"}.van-icon-delete-o:before{content:"\e6a6"}.van-icon-cross:before{content:"\e6a7"}.van-icon-edit:before{content:"\e6a8"}.van-icon-ellipsis:before{content:"\e6a9"}.van-icon-down:before{content:"\e6aa"}.van-icon-discount-o:before{content:"\e6ab"}.van-icon-ecard-pay:before{content:"\e6ac"}.van-icon-envelop-o:before{content:"\e6ae"}@font-face{font-display:auto;font-family:vant-icon;font-style:normal;font-weight:400;src:url(//at.alicdn.com/t/c/font_2553510_kfwma2yq1rs.woff2?t=1694918397022) format("woff2"),url(//at.alicdn.com/t/c/font_2553510_kfwma2yq1rs.woff?t=1694918397022) format("woff")}:host{align-items:center;display:inline-flex;justify-content:center}.van-icon--custom{position:relative}.van-icon--image{height:1em;width:1em}.van-icon__image{height:100%;width:100%}.van-icon__info{z-index:1}
================================================
FILE: lib/image/index.d.ts
================================================
export {};
================================================
FILE: lib/image/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var button_1 = require("../mixins/button");
(0, component_1.VantComponent)({
mixins: [button_1.button],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: {
type: String,
observer: function () {
this.setData({
error: false,
loading: true,
});
},
},
round: Boolean,
width: null,
height: null,
radius: null,
lazyLoad: Boolean,
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
fit: {
type: String,
value: 'fill',
},
webp: {
type: Boolean,
value: false,
},
showError: {
type: Boolean,
value: true,
},
showLoading: {
type: Boolean,
value: true,
},
},
data: {
error: false,
loading: true,
viewStyle: '',
},
methods: {
onLoad: function (event) {
this.setData({
loading: false,
});
this.$emit('load', event.detail);
},
onError: function (event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick: function (event) {
this.$emit('click', event.detail);
},
},
});
================================================
FILE: lib/image/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: lib/image/index.wxml
================================================
================================================
FILE: lib/image/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
width: addUnit(data.width),
height: addUnit(data.height),
'border-radius': addUnit(data.radius),
},
data.radius ? 'overflow: hidden' : null,
]);
}
var FIT_MODE_MAP = {
none: 'center',
fill: 'scaleToFill',
cover: 'aspectFill',
contain: 'aspectFit',
widthFix: 'widthFix',
heightFix: 'heightFix',
};
function mode(fit) {
return FIT_MODE_MAP[fit];
}
module.exports = {
rootStyle: rootStyle,
mode: mode,
};
================================================
FILE: lib/image/index.wxss
================================================
@import '../common/index.wxss';.van-image{display:inline-block;position:relative;vertical-align:top}.van-image--round{border-radius:50%;overflow:hidden}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;height:100%;width:100%}.van-image__error,.van-image__loading{align-items:center;background-color:var(--image-placeholder-background-color,#f7f8fa);color:var(--image-placeholder-text-color,#969799);display:flex;flex-direction:column;font-size:var(--image-placeholder-font-size,14px);justify-content:center;left:0;position:absolute;top:0}.van-image__loading-icon{color:var(--image-loading-icon-color,#dcdee0);font-size:var(--image-loading-icon-size,32px)!important}.van-image__error-icon{color:var(--image-error-icon-color,#dcdee0);font-size:var(--image-error-icon-size,32px)!important}
================================================
FILE: lib/index-anchor/index.d.ts
================================================
export {};
================================================
FILE: lib/index-anchor/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("../common/utils");
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useParent)('index-bar'),
props: {
useSlot: Boolean,
index: null,
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: '',
},
methods: {
scrollIntoView: function (scrollTop) {
var _this = this;
(0, utils_1.getRect)(this, '.van-index-anchor-wrapper').then(function (rect) {
wx.pageScrollTo({
duration: 0,
scrollTop: scrollTop + rect.top - _this.parent.data.stickyOffsetTop,
});
});
},
},
});
================================================
FILE: lib/index-anchor/index.json
================================================
{
"component": true
}
================================================
FILE: lib/index-anchor/index.wxml
================================================
{{ index }}
================================================
FILE: lib/index-anchor/index.wxss
================================================
@import '../common/index.wxss';.van-index-anchor{background-color:var(--index-anchor-background-color,transparent);color:var(--index-anchor-text-color,#323233);font-size:var(--index-anchor-font-size,14px);font-weight:var(--index-anchor-font-weight,500);line-height:var(--index-anchor-line-height,32px);padding:var(--index-anchor-padding,0 16px)}.van-index-anchor--active{background-color:var(--index-anchor-active-background-color,#fff);color:var(--index-anchor-active-text-color,#07c160);left:0;right:0}
================================================
FILE: lib/index-bar/index.d.ts
================================================
export {};
================================================
FILE: lib/index-bar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var color_1 = require("../common/color");
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var utils_1 = require("../common/utils");
var page_scroll_1 = require("../mixins/page-scroll");
var indexList = function () {
var indexList = [];
var charCodeOfA = 'A'.charCodeAt(0);
for (var i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('index-anchor', function () {
this.updateData();
}),
props: {
sticky: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
highlightColor: {
type: String,
value: color_1.GREEN,
},
stickyOffsetTop: {
type: Number,
value: 0,
},
indexList: {
type: Array,
value: indexList(),
},
},
mixins: [
(0, page_scroll_1.pageScrollMixin)(function (event) {
this.scrollTop = (event === null || event === void 0 ? void 0 : event.scrollTop) || 0;
this.onScroll();
}),
],
data: {
activeAnchorIndex: null,
showSidebar: false,
},
created: function () {
this.scrollTop = 0;
},
methods: {
updateData: function () {
var _this = this;
wx.nextTick(function () {
if (_this.timer != null) {
clearTimeout(_this.timer);
}
_this.timer = setTimeout(function () {
_this.setData({
showSidebar: !!_this.children.length,
});
_this.setRect().then(function () {
_this.onScroll();
});
}, 0);
});
},
setRect: function () {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect(),
]);
},
setAnchorsRect: function () {
var _this = this;
return Promise.all(this.children.map(function (anchor) {
return (0, utils_1.getRect)(anchor, '.van-index-anchor-wrapper').then(function (rect) {
Object.assign(anchor, {
height: rect.height,
top: rect.top + _this.scrollTop,
});
});
}));
},
setListRect: function () {
var _this = this;
return (0, utils_1.getRect)(this, '.van-index-bar').then(function (rect) {
if (!(0, utils_1.isDef)(rect)) {
return;
}
Object.assign(_this, {
height: rect.height,
top: rect.top + _this.scrollTop,
});
});
},
setSiderbarRect: function () {
var _this = this;
return (0, utils_1.getRect)(this, '.van-index-bar__sidebar').then(function (res) {
if (!(0, utils_1.isDef)(res)) {
return;
}
_this.sidebar = {
height: res.height,
top: res.top,
};
});
},
setDiffData: function (_a) {
var target = _a.target, data = _a.data;
var diffData = {};
Object.keys(data).forEach(function (key) {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect: function (anchor) {
return (0, utils_1.getRect)(anchor, '.van-index-anchor-wrapper').then(function (rect) { return ({
height: rect.height,
top: rect.top,
}); });
},
getActiveAnchorIndex: function () {
var _a = this, children = _a.children, scrollTop = _a.scrollTop;
var _b = this.data, sticky = _b.sticky, stickyOffsetTop = _b.stickyOffsetTop;
for (var i = this.children.length - 1; i >= 0; i--) {
var preAnchorHeight = i > 0 ? children[i - 1].height : 0;
var reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll: function () {
var _this = this;
var _a = this, _b = _a.children, children = _b === void 0 ? [] : _b, scrollTop = _a.scrollTop;
if (!children.length) {
return;
}
var _c = this.data, sticky = _c.sticky, stickyOffsetTop = _c.stickyOffsetTop, zIndex = _c.zIndex, highlightColor = _c.highlightColor;
var active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active,
},
});
if (sticky) {
var isActiveAnchorSticky_1 = false;
if (active !== -1) {
isActiveAnchorSticky_1 =
children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach(function (item, index) {
if (index === active) {
var wrapperStyle = '';
var anchorStyle = "\n color: ".concat(highlightColor, ";\n ");
if (isActiveAnchorSticky_1) {
wrapperStyle = "\n height: ".concat(children[index].height, "px;\n ");
anchorStyle = "\n position: fixed;\n top: ".concat(stickyOffsetTop, "px;\n z-index: ").concat(zIndex, ";\n color: ").concat(highlightColor, ";\n ");
}
_this.setDiffData({
target: item,
data: {
active: true,
anchorStyle: anchorStyle,
wrapperStyle: wrapperStyle,
},
});
}
else if (index === active - 1) {
var currentAnchor = children[index];
var currentOffsetTop = currentAnchor.top;
var targetOffsetTop = index === children.length - 1
? _this.top
: children[index + 1].top;
var parentOffsetHeight = targetOffsetTop - currentOffsetTop;
var translateY = parentOffsetHeight - currentAnchor.height;
var anchorStyle = "\n position: relative;\n transform: translate3d(0, ".concat(translateY, "px, 0);\n z-index: ").concat(zIndex, ";\n color: ").concat(highlightColor, ";\n ");
_this.setDiffData({
target: item,
data: {
active: true,
anchorStyle: anchorStyle,
},
});
}
else {
_this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
},
});
}
});
}
},
onClick: function (event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove: function (event) {
var sidebarLength = this.children.length;
var touch = event.touches[0];
var itemHeight = this.sidebar.height / sidebarLength;
var index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
}
else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop: function () {
this.scrollToAnchorIndex = null;
},
scrollToAnchor: function (index) {
var _this = this;
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
var anchor = this.children.find(function (item) { return item.data.index === _this.data.indexList[index]; });
if (anchor) {
anchor.scrollIntoView(this.scrollTop);
this.$emit('select', anchor.data.index);
}
},
},
});
================================================
FILE: lib/index-bar/index.json
================================================
{
"component": true
}
================================================
FILE: lib/index-bar/index.wxml
================================================
================================================
FILE: lib/index-bar/index.wxss
================================================
@import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{display:flex;flex-direction:column;position:fixed;right:0;text-align:center;top:50%;transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-size:var(--index-bar-index-font-size,10px);font-weight:500;line-height:var(--index-bar-index-line-height,14px);padding:0 var(--padding-base,4px) 0 var(--padding-md,16px)}
================================================
FILE: lib/info/index.d.ts
================================================
export {};
================================================
FILE: lib/info/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
dot: Boolean,
info: null,
customStyle: String,
},
});
================================================
FILE: lib/info/index.json
================================================
{
"component": true
}
================================================
FILE: lib/info/index.wxml
================================================
{{ dot ? '' : info }}
================================================
FILE: lib/info/index.wxss
================================================
@import '../common/index.wxss';.van-info{align-items:center;background-color:var(--info-background-color,#ee0a24);border:var(--info-border-width,1px) solid #fff;border-radius:var(--info-size,16px);box-sizing:border-box;color:var(--info-color,#fff);display:inline-flex;font-family:var(--info-font-family,-apple-system-font,Helvetica Neue,Arial,sans-serif);font-size:var(--info-font-size,12px);font-weight:var(--info-font-weight,500);height:var(--info-size,16px);justify-content:center;min-width:var(--info-size,16px);padding:var(--info-padding,0 3px);position:absolute;right:0;top:0;transform:translate(50%,-50%);transform-origin:100%;white-space:nowrap}.van-info--dot{background-color:var(--info-dot-color,#ee0a24);border-radius:100%;height:var(--info-dot-size,8px);min-width:0;width:var(--info-dot-size,8px)}
================================================
FILE: lib/loading/index.d.ts
================================================
export {};
================================================
FILE: lib/loading/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
color: String,
vertical: Boolean,
type: {
type: String,
value: 'circular',
},
size: String,
textSize: String,
},
data: {
array12: Array.from({ length: 12 }),
},
});
================================================
FILE: lib/loading/index.json
================================================
{
"component": true
}
================================================
FILE: lib/loading/index.wxml
================================================
================================================
FILE: lib/loading/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function spinnerStyle(data) {
return style({
color: data.color,
width: addUnit(data.size),
height: addUnit(data.size),
});
}
function textStyle(data) {
return style({
'font-size': addUnit(data.textSize),
});
}
module.exports = {
spinnerStyle: spinnerStyle,
textStyle: textStyle,
};
================================================
FILE: lib/loading/index.wxss
================================================
@import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{align-items:center;color:var(--loading-spinner-color,#c8c9cc);display:inline-flex;justify-content:center}.van-loading__spinner{animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;box-sizing:border-box;height:var(--loading-spinner-size,30px);max-height:100%;max-width:100%;position:relative;width:var(--loading-spinner-size,30px)}.van-loading__spinner--spinner{animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-radius:100%;border-top-color:initial}.van-loading__text{color:var(--loading-text-color,#969799);font-size:var(--loading-text-font-size,14px);line-height:var(--loading-text-line-height,20px);margin-left:var(--padding-xs,8px)}.van-loading__text:empty{display:none}.van-loading--vertical{flex-direction:column}.van-loading--vertical .van-loading__text{margin:var(--padding-xs,8px) 0 0}.van-loading__dot{height:100%;left:0;position:absolute;top:0;width:100%}.van-loading__dot:before{background-color:currentColor;border-radius:40%;content:" ";display:block;height:25%;margin:0 auto;width:2px}.van-loading__dot:first-of-type{opacity:1;transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;transform:rotate(1turn)}@keyframes van-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
================================================
FILE: lib/mixins/basic.d.ts
================================================
export declare const basic: string;
================================================
FILE: lib/mixins/basic.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.basic = void 0;
exports.basic = Behavior({
methods: {
$emit: function (name, detail, options) {
this.triggerEvent(name, detail, options);
},
set: function (data) {
this.setData(data);
return new Promise(function (resolve) { return wx.nextTick(resolve); });
},
// high performance setData
setView: function (data, callback) {
var _this = this;
var target = {};
var hasChange = false;
Object.keys(data).forEach(function (key) {
if (data[key] !== _this.data[key]) {
target[key] = data[key];
hasChange = true;
}
});
if (hasChange) {
return this.setData(target, callback);
}
return callback && callback();
},
},
});
================================================
FILE: lib/mixins/button.d.ts
================================================
export declare const button: string;
================================================
FILE: lib/mixins/button.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.button = void 0;
var version_1 = require("../common/version");
exports.button = Behavior({
externalClasses: ['hover-class'],
properties: {
id: String,
buttonId: String,
lang: String,
businessId: Number,
sessionFrom: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean,
appParameter: String,
ariaLabel: String,
openType: String,
getUserProfileDesc: String,
},
data: {
canIUseGetUserProfile: (0, version_1.canIUseGetUserProfile)(),
},
methods: {
onGetUserInfo: function (event) {
this.triggerEvent('getuserinfo', event.detail);
},
onContact: function (event) {
this.triggerEvent('contact', event.detail);
},
onGetPhoneNumber: function (event) {
this.triggerEvent('getphonenumber', event.detail);
},
onGetRealTimePhoneNumber: function (event) {
this.triggerEvent('getrealtimephonenumber', event.detail);
},
onError: function (event) {
this.triggerEvent('error', event.detail);
},
onLaunchApp: function (event) {
this.triggerEvent('launchapp', event.detail);
},
onOpenSetting: function (event) {
this.triggerEvent('opensetting', event.detail);
},
onAgreePrivacyAuthorization: function (event) {
this.triggerEvent('agreeprivacyauthorization', event.detail);
},
onChooseAvatar: function (event) {
this.triggerEvent('chooseavatar', event.detail);
},
},
});
================================================
FILE: lib/mixins/link.d.ts
================================================
export declare const link: string;
================================================
FILE: lib/mixins/link.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.link = void 0;
exports.link = Behavior({
properties: {
url: String,
linkType: {
type: String,
value: 'navigateTo',
},
},
methods: {
jumpLink: function (urlKey) {
if (urlKey === void 0) { urlKey = 'url'; }
var url = this.data[urlKey];
if (url) {
if (this.data.linkType === 'navigateTo' &&
getCurrentPages().length > 9) {
wx.redirectTo({ url: url });
}
else {
wx[this.data.linkType]({ url: url });
}
}
},
},
});
================================================
FILE: lib/mixins/page-scroll.d.ts
================================================
///
///
type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
type Scroller = (this: WechatMiniprogram.Component.TrivialInstance, event?: IPageScrollOption) => void;
export declare function pageScrollMixin(scroller: Scroller): string;
export {};
================================================
FILE: lib/mixins/page-scroll.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pageScrollMixin = void 0;
var validator_1 = require("../common/validator");
var utils_1 = require("../common/utils");
function onPageScroll(event) {
var _a = (0, utils_1.getCurrentPage)().vanPageScroller, vanPageScroller = _a === void 0 ? [] : _a;
vanPageScroller.forEach(function (scroller) {
if (typeof scroller === 'function') {
// @ts-ignore
scroller(event);
}
});
}
function pageScrollMixin(scroller) {
return Behavior({
attached: function () {
var page = (0, utils_1.getCurrentPage)();
if (!(0, utils_1.isDef)(page)) {
return;
}
var _scroller = scroller.bind(this);
var _a = page.vanPageScroller, vanPageScroller = _a === void 0 ? [] : _a;
if ((0, validator_1.isFunction)(page.onPageScroll) && page.onPageScroll !== onPageScroll) {
vanPageScroller.push(page.onPageScroll.bind(page));
}
vanPageScroller.push(_scroller);
page.vanPageScroller = vanPageScroller;
page.onPageScroll = onPageScroll;
this._scroller = _scroller;
},
detached: function () {
var _this = this;
var page = (0, utils_1.getCurrentPage)();
if (!(0, utils_1.isDef)(page) || !(0, utils_1.isDef)(page.vanPageScroller)) {
return;
}
var vanPageScroller = page.vanPageScroller;
var index = vanPageScroller.findIndex(function (v) { return v === _this._scroller; });
if (index > -1) {
page.vanPageScroller.splice(index, 1);
}
this._scroller = undefined;
},
});
}
exports.pageScrollMixin = pageScrollMixin;
================================================
FILE: lib/mixins/touch.d.ts
================================================
export declare const touch: string;
================================================
FILE: lib/mixins/touch.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.touch = void 0;
// @ts-nocheck
var MIN_DISTANCE = 10;
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
exports.touch = Behavior({
methods: {
resetTouchStatus: function () {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
touchStart: function (event) {
this.resetTouchStatus();
var touch = event.touches[0];
this.startX = touch.clientX;
this.startY = touch.clientY;
},
touchMove: function (event) {
var touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction =
this.direction || getDirection(this.offsetX, this.offsetY);
},
},
});
================================================
FILE: lib/mixins/transition.d.ts
================================================
export declare function transition(showDefaultValue: boolean): string;
================================================
FILE: lib/mixins/transition.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transition = void 0;
// @ts-nocheck
var utils_1 = require("../common/utils");
var validator_1 = require("../common/validator");
var getClassNames = function (name) { return ({
enter: "van-".concat(name, "-enter van-").concat(name, "-enter-active enter-class enter-active-class"),
'enter-to': "van-".concat(name, "-enter-to van-").concat(name, "-enter-active enter-to-class enter-active-class"),
leave: "van-".concat(name, "-leave van-").concat(name, "-leave-active leave-class leave-active-class"),
'leave-to': "van-".concat(name, "-leave-to van-").concat(name, "-leave-active leave-to-class leave-active-class"),
}); };
function transition(showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
// @ts-ignore
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow',
},
// @ts-ignore
duration: {
type: null,
value: 300,
},
name: {
type: String,
value: 'fade',
},
},
data: {
type: '',
inited: false,
display: false,
},
ready: function () {
if (this.data.show === true) {
this.observeShow(true, false);
}
},
methods: {
observeShow: function (value, old) {
if (value === old) {
return;
}
value ? this.enureEnter() : this.enureLeave();
},
enureEnter: function () {
var _this = this;
if (this.enterPromise)
return;
this.enterPromise = new Promise(function (resolve) { return _this.enter(resolve); });
},
enureLeave: function () {
var _this = this;
var enterPromise = this.enterPromise;
if (!enterPromise)
return;
enterPromise
.then(function () { return new Promise(function (resolve) { return _this.leave(resolve); }); })
.then(function () {
_this.enterPromise = null;
});
},
enter: function (resolve) {
var _this = this;
var _a = this.data, duration = _a.duration, name = _a.name;
var classNames = getClassNames(name);
var currentDuration = (0, validator_1.isObj)(duration) ? duration.enter : duration;
if (this.status === 'enter') {
return;
}
this.status = 'enter';
this.$emit('before-enter');
(0, utils_1.requestAnimationFrame)(function () {
if (_this.status !== 'enter') {
return;
}
_this.$emit('enter');
_this.setData({
inited: true,
display: true,
classes: classNames.enter,
currentDuration: currentDuration,
});
(0, utils_1.requestAnimationFrame)(function () {
if (_this.status !== 'enter') {
return;
}
_this.transitionEnded = false;
_this.setData({ classes: classNames['enter-to'] });
resolve();
});
});
},
leave: function (resolve) {
var _this = this;
if (!this.data.display) {
return;
}
var _a = this.data, duration = _a.duration, name = _a.name;
var classNames = getClassNames(name);
var currentDuration = (0, validator_1.isObj)(duration) ? duration.leave : duration;
this.status = 'leave';
this.$emit('before-leave');
(0, utils_1.requestAnimationFrame)(function () {
if (_this.status !== 'leave') {
return;
}
_this.$emit('leave');
_this.setData({
classes: classNames.leave,
currentDuration: currentDuration,
});
(0, utils_1.requestAnimationFrame)(function () {
if (_this.status !== 'leave') {
return;
}
_this.transitionEnded = false;
setTimeout(function () {
_this.onTransitionEnd();
resolve();
}, currentDuration);
_this.setData({ classes: classNames['leave-to'] });
});
});
},
onTransitionEnd: function () {
if (this.transitionEnded) {
return;
}
this.transitionEnded = true;
this.$emit("after-".concat(this.status));
var _a = this.data, show = _a.show, display = _a.display;
if (!show && display) {
this.setData({ display: false });
}
},
},
});
}
exports.transition = transition;
================================================
FILE: lib/nav-bar/index.d.ts
================================================
export {};
================================================
FILE: lib/nav-bar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
classes: ['title-class'],
props: {
title: String,
fixed: {
type: Boolean,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
leftText: String,
rightText: String,
customStyle: String,
leftArrow: Boolean,
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetTop: {
type: Boolean,
value: true,
},
},
data: {
height: 46,
},
created: function () {
var statusBarHeight = (0, utils_1.getSystemInfoSync)().statusBarHeight;
this.setData({
statusBarHeight: statusBarHeight,
height: 46 + statusBarHeight,
});
},
mounted: function () {
this.setHeight();
},
methods: {
onClickLeft: function () {
this.$emit('click-left');
},
onClickRight: function () {
this.$emit('click-right');
},
setHeight: function () {
var _this = this;
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(function () {
(0, utils_1.getRect)(_this, '.van-nav-bar').then(function (res) {
if (res && 'height' in res) {
_this.setData({ height: res.height });
}
});
});
},
},
});
================================================
FILE: lib/nav-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/nav-bar/index.wxml
================================================
{{ leftText }}
{{ title }}
{{ rightText }}
================================================
FILE: lib/nav-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function barStyle(data) {
return style({
'z-index': data.zIndex,
'padding-top': data.safeAreaInsetTop ? data.statusBarHeight + 'px' : 0,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: lib/nav-bar/index.wxss
================================================
@import '../common/index.wxss';.van-nav-bar{background-color:var(--nav-bar-background-color,#fff);box-sizing:initial;height:var(--nav-bar-height,46px);line-height:var(--nav-bar-height,46px);position:relative;text-align:center;-webkit-user-select:none;user-select:none}.van-nav-bar__content{height:100%;position:relative}.van-nav-bar__text{color:var(--nav-bar-text-color,#1989fa);display:inline-block;margin:0 calc(var(--padding-md, 16px)*-1);padding:0 var(--padding-md,16px);vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:var(--nav-bar-icon-color,#1989fa)!important;font-size:var(--nav-bar-arrow-size,16px)!important;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{left:0;position:fixed;top:0;width:100%}.van-nav-bar__title{color:var(--nav-bar-title-text-color,#323233);font-size:var(--nav-bar-title-font-size,16px);font-weight:var(--font-weight-bold,500);margin:0 auto;max-width:60%}.van-nav-bar__left,.van-nav-bar__right{align-items:center;bottom:0;display:flex;font-size:var(--font-size-md,14px);position:absolute;top:0}.van-nav-bar__left{left:var(--padding-md,16px)}.van-nav-bar__right{right:var(--padding-md,16px)}
================================================
FILE: lib/notice-bar/index.d.ts
================================================
export {};
================================================
FILE: lib/notice-bar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
props: {
text: {
type: String,
value: '',
observer: 'init',
},
mode: {
type: String,
value: '',
},
url: {
type: String,
value: '',
},
openType: {
type: String,
value: 'navigate',
},
delay: {
type: Number,
value: 1,
},
speed: {
type: Number,
value: 60,
observer: 'init',
},
scrollable: null,
leftIcon: {
type: String,
value: '',
},
color: String,
backgroundColor: String,
background: String,
wrapable: Boolean,
},
data: {
show: true,
},
created: function () {
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear',
});
},
destroyed: function () {
this.timer && clearTimeout(this.timer);
},
mounted: function () {
this.init();
},
methods: {
init: function () {
var _this = this;
(0, utils_1.requestAnimationFrame)(function () {
Promise.all([
(0, utils_1.getRect)(_this, '.van-notice-bar__content'),
(0, utils_1.getRect)(_this, '.van-notice-bar__wrap'),
]).then(function (rects) {
var contentRect = rects[0], wrapRect = rects[1];
var scrollable = _this.data.scrollable;
if (contentRect == null ||
wrapRect == null ||
!contentRect.width ||
!wrapRect.width ||
scrollable === false) {
return;
}
if (scrollable || wrapRect.width < contentRect.width) {
_this.initAnimation(wrapRect.width, contentRect.width);
_this.scroll(true);
}
});
});
},
initAnimation: function (warpWidth, contentWidth) {
var _a = this.data, speed = _a.speed, delay = _a.delay;
this.wrapWidth = warpWidth;
this.contentWidth = contentWidth;
// begin 0
this.contentDuration = (contentWidth / speed) * 1000;
// begin -wrapWidth
this.duration = ((warpWidth + contentWidth) / speed) * 1000;
this.animation = wx.createAnimation({
duration: this.contentDuration,
timingFunction: 'linear',
delay: delay,
});
},
scroll: function (isInit) {
var _this = this;
if (isInit === void 0) { isInit = false; }
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({
animationData: this.resetAnimation
.translateX(isInit ? 0 : this.wrapWidth)
.step()
.export(),
});
var duration = isInit ? this.contentDuration : this.duration;
(0, utils_1.requestAnimationFrame)(function () {
_this.setData({
animationData: _this.animation
.translateX(-_this.contentWidth)
.step({ duration: duration })
.export(),
});
});
this.timer = setTimeout(function () {
_this.scroll();
}, duration + this.data.delay);
},
onClickIcon: function (event) {
if (this.data.mode === 'closeable') {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({ show: false });
this.$emit('close', event.detail);
}
},
onClick: function (event) {
this.$emit('click', event);
},
},
});
================================================
FILE: lib/notice-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/notice-bar/index.wxml
================================================
{{ text }}
================================================
FILE: lib/notice-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
color: data.color,
'background-color': data.backgroundColor,
background: data.background,
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/notice-bar/index.wxss
================================================
@import '../common/index.wxss';.van-notice-bar{align-items:center;background-color:var(--notice-bar-background-color,#fffbe8);color:var(--notice-bar-text-color,#ed6a0c);display:flex;font-size:var(--notice-bar-font-size,14px);height:var(--notice-bar-height,40px);line-height:var(--notice-bar-line-height,24px);padding:var(--notice-bar-padding,0 16px)}.van-notice-bar--withicon{padding-right:40px;position:relative}.van-notice-bar--wrapable{height:auto;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{align-items:center;display:flex;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:var(--notice-bar-icon-size,16px);min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;right:15px;top:10px}.van-notice-bar__wrap{flex:1;height:var(--notice-bar-line-height,24px);overflow:hidden;position:relative}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
================================================
FILE: lib/notify/index.d.ts
================================================
export {};
================================================
FILE: lib/notify/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var color_1 = require("../common/color");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
props: {
message: String,
background: String,
type: {
type: String,
value: 'danger',
},
color: {
type: String,
value: color_1.WHITE,
},
duration: {
type: Number,
value: 3000,
},
zIndex: {
type: Number,
value: 110,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
top: null,
},
data: {
show: false,
onOpened: null,
onClose: null,
onClick: null,
},
created: function () {
var statusBarHeight = (0, utils_1.getSystemInfoSync)().statusBarHeight;
this.setData({ statusBarHeight: statusBarHeight });
},
methods: {
show: function () {
var _this = this;
var _a = this.data, duration = _a.duration, onOpened = _a.onOpened;
clearTimeout(this.timer);
this.setData({ show: true });
wx.nextTick(onOpened);
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(function () {
_this.hide();
}, duration);
}
},
hide: function () {
var onClose = this.data.onClose;
clearTimeout(this.timer);
this.setData({ show: false });
wx.nextTick(onClose);
},
onTap: function (event) {
var onClick = this.data.onClick;
if (onClick) {
onClick(event.detail);
}
},
},
});
================================================
FILE: lib/notify/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: lib/notify/index.wxml
================================================
{{ message }}
================================================
FILE: lib/notify/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'z-index': data.zIndex,
top: addUnit(data.top),
});
}
function notifyStyle(data) {
return style({
background: data.background,
color: data.color,
});
}
module.exports = {
rootStyle: rootStyle,
notifyStyle: notifyStyle,
};
================================================
FILE: lib/notify/index.wxss
================================================
@import '../common/index.wxss';.van-notify{word-wrap:break-word;font-size:var(--notify-font-size,14px);line-height:var(--notify-line-height,20px);padding:var(--notify-padding,6px 15px);text-align:center}.van-notify__container{box-sizing:border-box;left:0;position:fixed;top:0;width:100%}.van-notify--primary{background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:var(--notify-warning-background-color,#ff976a)}
================================================
FILE: lib/notify/notify.d.ts
================================================
interface NotifyOptions {
type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string;
zIndex?: number;
top?: number;
message: string;
context?: any;
duration?: number;
selector?: string;
background?: string;
safeAreaInsetTop?: boolean;
onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
declare function Notify(options: NotifyOptions | string): any;
declare namespace Notify {
var clear: (options?: NotifyOptions | undefined) => void;
var setDefaultOptions: (options: NotifyOptions) => void;
var resetDefaultOptions: () => void;
}
export default Notify;
================================================
FILE: lib/notify/notify.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var color_1 = require("../common/color");
var defaultOptions = {
selector: '#van-notify',
type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
top: 0,
color: color_1.WHITE,
safeAreaInsetTop: false,
onClick: function () { },
onOpened: function () { },
onClose: function () { },
};
var currentOptions = __assign({}, defaultOptions);
function parseOptions(message) {
if (message == null) {
return {};
}
return typeof message === 'string' ? { message: message } : message;
}
function getContext() {
var pages = getCurrentPages();
return pages[pages.length - 1];
}
function Notify(options) {
options = __assign(__assign({}, currentOptions), parseOptions(options));
var context = options.context || getContext();
var notify = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (notify) {
notify.setData(options);
notify.show();
return notify;
}
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
exports.default = Notify;
Notify.clear = function (options) {
options = __assign(__assign({}, defaultOptions), parseOptions(options));
var context = options.context || getContext();
var notify = context.selectComponent(options.selector);
if (notify) {
notify.hide();
}
};
Notify.setDefaultOptions = function (options) {
Object.assign(currentOptions, options);
};
Notify.resetDefaultOptions = function () {
currentOptions = __assign({}, defaultOptions);
};
================================================
FILE: lib/overlay/index.d.ts
================================================
export {};
================================================
FILE: lib/overlay/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
show: Boolean,
customStyle: String,
duration: {
type: null,
value: 300,
},
zIndex: {
type: Number,
value: 1,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClick: function () {
this.$emit('click');
},
// for prevent touchmove
noop: function () { },
},
});
================================================
FILE: lib/overlay/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: lib/overlay/index.wxml
================================================
================================================
FILE: lib/overlay/index.wxss
================================================
@import '../common/index.wxss';.van-overlay{background-color:var(--overlay-background-color,rgba(0,0,0,.7));height:100%;left:0;position:fixed;top:0;width:100%}
================================================
FILE: lib/overlay/overlay.wxml
================================================
================================================
FILE: lib/panel/index.d.ts
================================================
export {};
================================================
FILE: lib/panel/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: ['header-class', 'footer-class'],
props: {
desc: String,
title: String,
status: String,
},
});
================================================
FILE: lib/panel/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: lib/panel/index.wxml
================================================
================================================
FILE: lib/panel/index.wxss
================================================
@import '../common/index.wxss';.van-panel{background:var(--panel-background-color,#fff)}.van-panel__header-value{color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:var(--panel-footer-padding,8px 16px)}.van-panel__footer:empty{display:none}
================================================
FILE: lib/picker/index.d.ts
================================================
export {};
================================================
FILE: lib/picker/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var shared_1 = require("./shared");
(0, component_1.VantComponent)({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: __assign(__assign({}, shared_1.pickerProps), { valueKey: {
type: String,
value: 'text',
}, toolbarPosition: {
type: String,
value: 'top',
}, defaultIndex: {
type: Number,
value: 0,
}, columns: {
type: Array,
value: [],
observer: function (columns) {
if (columns === void 0) { columns = []; }
this.simple = columns.length && !columns[0].values;
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(function () { });
}
},
} }),
beforeCreate: function () {
var _this = this;
Object.defineProperty(this, 'children', {
get: function () { return _this.selectAllComponents('.van-picker__column') || []; },
});
},
methods: {
noop: function () { },
setColumns: function () {
var _this = this;
var data = this.data;
var columns = this.simple ? [{ values: data.columns }] : data.columns;
var stack = columns.map(function (column, index) {
return _this.setColumnValues(index, column.values);
});
return Promise.all(stack);
},
emit: function (event) {
var type = event.currentTarget.dataset.type;
if (this.simple) {
this.$emit(type, {
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
}
else {
this.$emit(type, {
value: this.getValues(),
index: this.getIndexes(),
});
}
},
onChange: function (event) {
if (this.simple) {
this.$emit('change', {
picker: this,
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
}
else {
this.$emit('change', {
picker: this,
value: this.getValues(),
index: event.currentTarget.dataset.index,
});
}
},
// get column instance by index
getColumn: function (index) {
return this.children[index];
},
// get column value by index
getColumnValue: function (index) {
var column = this.getColumn(index);
return column && column.getValue();
},
// set column value by index
setColumnValue: function (index, value) {
var column = this.getColumn(index);
if (column == null) {
return Promise.reject(new Error('setColumnValue: 对应列不存在'));
}
return column.setValue(value);
},
// get column option index by column index
getColumnIndex: function (columnIndex) {
return (this.getColumn(columnIndex) || {}).data.currentIndex;
},
// set column option index by column index
setColumnIndex: function (columnIndex, optionIndex) {
var column = this.getColumn(columnIndex);
if (column == null) {
return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
}
return column.setIndex(optionIndex);
},
// get options of column by index
getColumnValues: function (index) {
return (this.children[index] || {}).data.options;
},
// set options of column by index
setColumnValues: function (index, options, needReset) {
if (needReset === void 0) { needReset = true; }
var column = this.children[index];
if (column == null) {
return Promise.reject(new Error('setColumnValues: 对应列不存在'));
}
var isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) {
return Promise.resolve();
}
return column.set({ options: options }).then(function () {
if (needReset) {
column.setIndex(0);
}
});
},
// get values of all columns
getValues: function () {
return this.children.map(function (child) { return child.getValue(); });
},
// set values of all columns
setValues: function (values) {
var _this = this;
var stack = values.map(function (value, index) {
return _this.setColumnValue(index, value);
});
return Promise.all(stack);
},
// get indexes of all columns
getIndexes: function () {
return this.children.map(function (child) { return child.data.currentIndex; });
},
// set indexes of all columns
setIndexes: function (indexes) {
var _this = this;
var stack = indexes.map(function (optionIndex, columnIndex) {
return _this.setColumnIndex(columnIndex, optionIndex);
});
return Promise.all(stack);
},
},
});
================================================
FILE: lib/picker/index.json
================================================
{
"component": true,
"usingComponents": {
"picker-column": "../picker-column/index",
"loading": "../loading/index"
}
}
================================================
FILE: lib/picker/index.wxml
================================================
================================================
FILE: lib/picker/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
var array = require('../wxs/array.wxs');
function columnsStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function maskStyle(data) {
return style({
'background-size':
'100% ' + addUnit((data.itemHeight * (data.visibleItemCount - 1)) / 2),
});
}
function frameStyle(data) {
return style({
height: addUnit(data.itemHeight),
});
}
function columns(columns) {
if (!array.isArray(columns)) {
return [];
}
if (columns.length && !columns[0].values) {
return [{ values: columns }];
}
return columns;
}
module.exports = {
columnsStyle: columnsStyle,
frameStyle: frameStyle,
maskStyle: maskStyle,
columns: columns,
};
================================================
FILE: lib/picker/index.wxss
================================================
@import '../common/index.wxss';.van-picker{-webkit-text-size-adjust:100%;background-color:var(--picker-background-color,#fff);overflow:hidden;position:relative;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:flex;height:var(--picker-toolbar-height,44px);justify-content:space-between;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{font-size:var(--picker-action-font-size,14px);padding:var(--picker-action-padding,0 16px)}.van-picker__cancel--hover,.van-picker__confirm--hover{opacity:.7}.van-picker__confirm{color:var(--picker-confirm-action-color,#576b95)}.van-picker__cancel{color:var(--picker-cancel-action-color,#969799)}.van-picker__title{font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);max-width:50%;text-align:center}.van-picker__columns{display:flex;position:relative}.van-picker__column{flex:1 1;width:0}.van-picker__loading{align-items:center;background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9));bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:4}.van-picker__mask{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-position:top,bottom;background-repeat:no-repeat;height:100%;left:0;top:0;width:100%;z-index:2}.van-picker__frame,.van-picker__mask{pointer-events:none;position:absolute}.van-picker__frame{left:16px;right:16px;top:50%;transform:translateY(-50%);z-index:1}
================================================
FILE: lib/picker/shared.d.ts
================================================
export declare const pickerProps: {
title: StringConstructor;
loading: BooleanConstructor;
showToolbar: BooleanConstructor;
cancelButtonText: {
type: StringConstructor;
value: string;
};
confirmButtonText: {
type: StringConstructor;
value: string;
};
visibleItemCount: {
type: NumberConstructor;
value: number;
};
itemHeight: {
type: NumberConstructor;
value: number;
};
};
================================================
FILE: lib/picker/shared.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pickerProps = void 0;
exports.pickerProps = {
title: String,
loading: Boolean,
showToolbar: Boolean,
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonText: {
type: String,
value: '确认',
},
visibleItemCount: {
type: Number,
value: 6,
},
itemHeight: {
type: Number,
value: 44,
},
};
================================================
FILE: lib/picker/toolbar.wxml
================================================
{{ cancelButtonText }}
{{
title
}}
{{ confirmButtonText }}
================================================
FILE: lib/picker-column/index.d.ts
================================================
export {};
================================================
FILE: lib/picker-column/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var utils_1 = require("../common/utils");
var validator_1 = require("../common/validator");
var DEFAULT_DURATION = 200;
(0, component_1.VantComponent)({
classes: ['active-class'],
props: {
valueKey: String,
className: String,
itemHeight: Number,
visibleItemCount: Number,
initialOptions: {
type: Array,
value: [],
},
defaultIndex: {
type: Number,
value: 0,
observer: function (value) {
this.setIndex(value);
},
},
},
data: {
startY: 0,
offset: 0,
duration: 0,
startOffset: 0,
options: [],
currentIndex: 0,
},
created: function () {
var _this = this;
var _a = this.data, defaultIndex = _a.defaultIndex, initialOptions = _a.initialOptions;
this.set({
currentIndex: defaultIndex,
options: initialOptions,
}).then(function () {
_this.setIndex(defaultIndex);
});
},
methods: {
getCount: function () {
return this.data.options.length;
},
onTouchStart: function (event) {
this.setData({
startY: event.touches[0].clientY,
startOffset: this.data.offset,
duration: 0,
});
},
onTouchMove: function (event) {
var data = this.data;
var deltaY = event.touches[0].clientY - data.startY;
this.setData({
offset: (0, utils_1.range)(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
});
},
onTouchEnd: function () {
var data = this.data;
if (data.offset !== data.startOffset) {
this.setData({ duration: DEFAULT_DURATION });
var index = (0, utils_1.range)(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
this.setIndex(index, true);
}
},
onClickItem: function (event) {
var index = event.currentTarget.dataset.index;
this.setIndex(index, true);
},
adjustIndex: function (index) {
var data = this.data;
var count = this.getCount();
index = (0, utils_1.range)(index, 0, count);
for (var i = index; i < count; i++) {
if (!this.isDisabled(data.options[i]))
return i;
}
for (var i = index - 1; i >= 0; i--) {
if (!this.isDisabled(data.options[i]))
return i;
}
},
isDisabled: function (option) {
return (0, validator_1.isObj)(option) && option.disabled;
},
getOptionText: function (option) {
var data = this.data;
return (0, validator_1.isObj)(option) && data.valueKey in option
? option[data.valueKey]
: option;
},
setIndex: function (index, userAction) {
var _this = this;
var data = this.data;
index = this.adjustIndex(index) || 0;
var offset = -index * data.itemHeight;
if (index !== data.currentIndex) {
return this.set({ offset: offset, currentIndex: index }).then(function () {
userAction && _this.$emit('change', index);
});
}
return this.set({ offset: offset });
},
setValue: function (value) {
var options = this.data.options;
for (var i = 0; i < options.length; i++) {
if (this.getOptionText(options[i]) === value) {
return this.setIndex(i);
}
}
return Promise.resolve();
},
getValue: function () {
var data = this.data;
return data.options[data.currentIndex];
},
},
});
================================================
FILE: lib/picker-column/index.json
================================================
{
"component": true
}
================================================
FILE: lib/picker-column/index.wxml
================================================
{{ computed.optionText(option, valueKey) }}
================================================
FILE: lib/picker-column/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function optionText(option, valueKey) {
return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
}
function rootStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function wrapperStyle(data) {
var offset = addUnit(
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
);
return style({
transition: 'transform ' + data.duration + 'ms',
'line-height': addUnit(data.itemHeight),
transform: 'translate3d(0, ' + offset + ', 0)',
});
}
module.exports = {
optionText: optionText,
rootStyle: rootStyle,
wrapperStyle: wrapperStyle,
};
================================================
FILE: lib/picker-column/index.wxss
================================================
@import '../common/index.wxss';.van-picker-column{color:var(--picker-option-text-color,#000);font-size:var(--picker-option-font-size,16px);overflow:hidden;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{color:var(--picker-option-selected-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}
================================================
FILE: lib/popup/index.d.ts
================================================
export {};
================================================
FILE: lib/popup/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var transition_1 = require("../mixins/transition");
(0, component_1.VantComponent)({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
'close-icon-class',
],
mixins: [(0, transition_1.transition)(false)],
props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: {
type: String,
observer: 'observeClass',
},
zIndex: {
type: Number,
value: 100,
},
overlay: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
closeIconPosition: {
type: String,
value: 'top-right',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
position: {
type: String,
value: 'center',
observer: 'observeClass',
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
created: function () {
this.observeClass();
},
methods: {
onClickCloseIcon: function () {
this.$emit('close');
},
onClickOverlay: function () {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
},
observeClass: function () {
var _a = this.data, transition = _a.transition, position = _a.position, duration = _a.duration;
var updateData = {
name: transition || position,
};
if (transition === 'none') {
updateData.duration = 0;
this.originDuration = duration;
}
else if (this.originDuration != null) {
updateData.duration = this.originDuration;
}
this.setData(updateData);
},
},
});
================================================
FILE: lib/popup/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index"
}
}
================================================
FILE: lib/popup/index.wxml
================================================
================================================
FILE: lib/popup/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function popupStyle(data) {
return style([
{
'z-index': data.zIndex,
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
popupStyle: popupStyle,
};
================================================
FILE: lib/popup/index.wxss
================================================
@import '../common/index.wxss';.van-popup{-webkit-overflow-scrolling:touch;animation:ease both;background-color:var(--popup-background-color,#fff);box-sizing:border-box;max-height:100%;overflow-y:auto;position:fixed;transition-timing-function:ease}.van-popup--center{left:50%;top:50%;transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:var(--popup-round-border-radius,16px)}.van-popup--top{left:0;top:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--right{right:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0}.van-popup--left{left:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--bottom.van-popup--safeTabBar,.van-popup--top.van-popup--safeTabBar{bottom:var(--tabbar-height,50px)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{color:var(--popup-close-icon-color,#969799);font-size:var(--popup-close-icon-size,18px);position:absolute;z-index:var(--popup-close-icon-z-index,1)}.van-popup__close-icon--top-left{left:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{right:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:var(--popup-close-icon-margin,16px);left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{bottom:var(--popup-close-icon-margin,16px);right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,transform}.van-scale-enter,.van-scale-leave-to{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:transform}.van-bottom-enter,.van-bottom-leave-to{transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{transform:translate3d(100%,-50%,0)}
================================================
FILE: lib/popup/popup.wxml
================================================
================================================
FILE: lib/progress/index.d.ts
================================================
export {};
================================================
FILE: lib/progress/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var color_1 = require("../common/color");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
props: {
inactive: Boolean,
percentage: {
type: Number,
observer: 'setLeft',
},
pivotText: String,
pivotColor: String,
trackColor: String,
showPivot: {
type: Boolean,
value: true,
},
color: {
type: String,
value: color_1.BLUE,
},
textColor: {
type: String,
value: '#fff',
},
strokeWidth: {
type: null,
value: 4,
},
},
data: {
right: 0,
},
mounted: function () {
this.setLeft();
},
methods: {
setLeft: function () {
var _this = this;
Promise.all([
(0, utils_1.getRect)(this, '.van-progress'),
(0, utils_1.getRect)(this, '.van-progress__pivot'),
]).then(function (_a) {
var portion = _a[0], pivot = _a[1];
if (portion && pivot) {
_this.setData({
right: (pivot.width * (_this.data.percentage - 100)) / 100,
});
}
});
},
},
});
================================================
FILE: lib/progress/index.json
================================================
{
"component": true
}
================================================
FILE: lib/progress/index.wxml
================================================
{{ computed.pivotText(pivotText, percentage) }}
================================================
FILE: lib/progress/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function pivotText(pivotText, percentage) {
return pivotText || percentage + '%';
}
function rootStyle(data) {
return style({
'height': data.strokeWidth ? utils.addUnit(data.strokeWidth) : '',
'background': data.trackColor,
});
}
function portionStyle(data) {
return style({
background: data.inactive ? '#cacaca' : data.color,
width: data.percentage ? data.percentage + '%' : '',
});
}
function pivotStyle(data) {
return style({
color: data.textColor,
right: data.right + 'px',
background: data.pivotColor ? data.pivotColor : data.inactive ? '#cacaca' : data.color,
});
}
module.exports = {
pivotText: pivotText,
rootStyle: rootStyle,
portionStyle: portionStyle,
pivotStyle: pivotStyle,
};
================================================
FILE: lib/progress/index.wxss
================================================
@import '../common/index.wxss';.van-progress{background:var(--progress-background-color,#ebedf0);border-radius:var(--progress-height,4px);height:var(--progress-height,4px);position:relative}.van-progress__portion{background:var(--progress-color,#1989fa);border-radius:inherit;height:100%;left:0;position:absolute}.van-progress__pivot{background-color:var(--progress-pivot-background-color,#1989fa);border-radius:1em;box-sizing:border-box;color:var(--progress-pivot-text-color,#fff);font-size:var(--progress-pivot-font-size,10px);line-height:var(--progress-pivot-line-height,1.6);min-width:3.6em;padding:var(--progress-pivot-padding,0 5px);position:absolute;text-align:center;top:50%;transform:translateY(-50%);word-break:keep-all}
================================================
FILE: lib/radio/index.d.ts
================================================
export {};
================================================
FILE: lib/radio/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var version_1 = require("../common/version");
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
field: true,
relation: (0, relation_1.useParent)('radio-group', function () {
this.updateFromParent();
}),
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
direction: '',
parentDisabled: false,
},
methods: {
updateFromParent: function () {
if (!this.parent) {
return;
}
var _a = this.parent.data, value = _a.value, parentDisabled = _a.disabled, direction = _a.direction;
this.setData({
value: value,
direction: direction,
parentDisabled: parentDisabled,
});
},
emitChange: function (value) {
var instance = this.parent || this;
instance.$emit('input', value);
instance.$emit('change', value);
if ((0, version_1.canIUseModel)()) {
instance.setData({ value: value });
}
},
onChange: function () {
if (!this.data.disabled && !this.data.parentDisabled) {
this.emitChange(this.data.name);
}
},
onClickLabel: function () {
var _a = this.data, disabled = _a.disabled, parentDisabled = _a.parentDisabled, labelDisabled = _a.labelDisabled, name = _a.name;
if (!(disabled || parentDisabled) && !labelDisabled) {
this.emitChange(name);
}
},
},
});
================================================
FILE: lib/radio/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/radio/index.wxml
================================================
================================================
FILE: lib/radio/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(data) {
var styles = {
'font-size': addUnit(data.iconSize),
};
if (
data.checkedColor &&
!(data.disabled || data.parentDisabled) &&
data.value === data.name
) {
styles['border-color'] = data.checkedColor;
styles['background-color'] = data.checkedColor;
}
return style(styles);
}
function iconCustomStyle(data) {
return style({
'line-height': addUnit(data.iconSize),
'font-size': '.8em',
display: 'block',
});
}
module.exports = {
iconStyle: iconStyle,
iconCustomStyle: iconCustomStyle,
};
================================================
FILE: lib/radio/index.wxss
================================================
@import '../common/index.wxss';.van-radio{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{flex:none}.van-radio--horizontal{margin-right:var(--padding-sm,12px)}.van-radio__icon{align-items:center;border:1px solid var(--radio-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--radio-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--radio-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{background-color:var(--radio-checked-icon-color,#1989fa);border-color:var(--radio-checked-icon-color,#1989fa);color:#fff}.van-radio__icon--disabled{background-color:var(--radio-disabled-background-color,#ebedf0);border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;color:var(--radio-label-color,#323233);line-height:var(--radio-size,20px);padding-left:var(--radio-label-margin,10px)}.van-radio__label--left{float:left;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
================================================
FILE: lib/radio-group/index.d.ts
================================================
export {};
================================================
FILE: lib/radio-group/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
field: true,
relation: (0, relation_1.useChildren)('radio'),
props: {
value: {
type: null,
observer: 'updateChildren',
},
direction: String,
disabled: {
type: Boolean,
observer: 'updateChildren',
},
},
methods: {
updateChildren: function () {
this.children.forEach(function (child) { return child.updateFromParent(); });
},
},
});
================================================
FILE: lib/radio-group/index.json
================================================
{
"component": true
}
================================================
FILE: lib/radio-group/index.wxml
================================================
================================================
FILE: lib/radio-group/index.wxss
================================================
@import '../common/index.wxss';.van-radio-group--horizontal{display:flex;flex-wrap:wrap}
================================================
FILE: lib/rate/index.d.ts
================================================
export {};
================================================
FILE: lib/rate/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("../common/utils");
var component_1 = require("../common/component");
var version_1 = require("../common/version");
(0, component_1.VantComponent)({
field: true,
classes: ['icon-class'],
props: {
value: {
type: Number,
observer: function (value) {
if (value !== this.data.innerValue) {
this.setData({ innerValue: value });
}
},
},
readonly: Boolean,
disabled: Boolean,
allowHalf: Boolean,
size: null,
icon: {
type: String,
value: 'star',
},
voidIcon: {
type: String,
value: 'star-o',
},
color: String,
voidColor: String,
disabledColor: String,
count: {
type: Number,
value: 5,
observer: function (value) {
this.setData({ innerCountArray: Array.from({ length: value }) });
},
},
gutter: null,
touchable: {
type: Boolean,
value: true,
},
},
data: {
innerValue: 0,
innerCountArray: Array.from({ length: 5 }),
},
methods: {
onSelect: function (event) {
var _this = this;
var data = this.data;
var score = event.currentTarget.dataset.score;
if (!data.disabled && !data.readonly) {
this.setData({ innerValue: score + 1 });
if ((0, version_1.canIUseModel)()) {
this.setData({ value: score + 1 });
}
wx.nextTick(function () {
_this.$emit('input', score + 1);
_this.$emit('change', score + 1);
});
}
},
onTouchMove: function (event) {
var _this = this;
var touchable = this.data.touchable;
if (!touchable)
return;
var clientX = event.touches[0].clientX;
(0, utils_1.getAllRect)(this, '.van-rate__icon').then(function (list) {
var target = list
.sort(function (cur, next) { return cur.dataset.score - next.dataset.score; })
.find(function (item) { return clientX >= item.left && clientX <= item.right; });
if (target != null) {
_this.onSelect(__assign(__assign({}, event), { currentTarget: target }));
}
});
},
},
});
================================================
FILE: lib/rate/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/rate/index.wxml
================================================
================================================
FILE: lib/rate/index.wxss
================================================
@import '../common/index.wxss';.van-rate{display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{padding:0 var(--rate-horizontal-padding,2px);position:relative}.van-rate__item:not(:last-child){padding-right:var(--rate-icon-gutter,4px)}.van-rate__icon{color:var(--rate-icon-void-color,#c8c9cc);display:block;font-size:var(--rate-icon-size,20px);height:100%}.van-rate__icon--half{left:var(--rate-horizontal-padding,2px);overflow:hidden;position:absolute;top:0;width:.5em}.van-rate__icon--full,.van-rate__icon--half{color:var(--rate-icon-full-color,#ee0a24)}.van-rate__icon--disabled{color:var(--rate-icon-disabled-color,#c8c9cc)}
================================================
FILE: lib/row/index.d.ts
================================================
export {};
================================================
FILE: lib/row/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('col', function (target) {
var gutter = this.data.gutter;
if (gutter) {
target.setData({ gutter: gutter });
}
}),
props: {
gutter: {
type: Number,
observer: 'setGutter',
},
},
methods: {
setGutter: function () {
var _this = this;
this.children.forEach(function (col) {
col.setData(_this.data);
});
},
},
});
================================================
FILE: lib/row/index.json
================================================
{
"component": true
}
================================================
FILE: lib/row/index.wxml
================================================
================================================
FILE: lib/row/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'margin-right': addUnit(-data.gutter / 2),
'margin-left': addUnit(-data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/row/index.wxss
================================================
@import '../common/index.wxss';.van-row:after{clear:both;content:"";display:table}
================================================
FILE: lib/search/index.d.ts
================================================
export {};
================================================
FILE: lib/search/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var version_1 = require("../common/version");
(0, component_1.VantComponent)({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
value: {
type: String,
value: '',
},
label: String,
focus: Boolean,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search',
},
rightIcon: String,
placeholder: String,
placeholderStyle: String,
actionText: {
type: String,
value: '取消',
},
background: {
type: String,
value: '#ffffff',
},
maxlength: {
type: Number,
value: -1,
},
shape: {
type: String,
value: 'square',
},
clearable: {
type: Boolean,
value: true,
},
clearTrigger: {
type: String,
value: 'focus',
},
clearIcon: {
type: String,
value: 'clear',
},
cursorSpacing: {
type: Number,
value: 0,
},
},
methods: {
onChange: function (event) {
if ((0, version_1.canIUseModel)()) {
this.setData({ value: event.detail });
}
this.$emit('change', event.detail);
},
onCancel: function () {
var _this = this;
/**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* https://github.com/youzan/vant-weapp/issues/1768
*/
setTimeout(function () {
if ((0, version_1.canIUseModel)()) {
_this.setData({ value: '' });
}
_this.$emit('cancel');
_this.$emit('change', '');
}, 200);
},
onSearch: function (event) {
this.$emit('search', event.detail);
},
onFocus: function (event) {
this.$emit('focus', event.detail);
},
onBlur: function (event) {
this.$emit('blur', event.detail);
},
onClear: function (event) {
this.$emit('clear', event.detail);
},
onClickInput: function (event) {
this.$emit('click-input', event.detail);
},
},
});
================================================
FILE: lib/search/index.json
================================================
{
"component": true,
"usingComponents": {
"van-field": "../field/index"
}
}
================================================
FILE: lib/search/index.wxml
================================================
{{ label }}
{{ actionText }}
================================================
FILE: lib/search/index.wxss
================================================
@import '../common/index.wxss';.van-search{align-items:center;box-sizing:border-box;display:flex;padding:var(--search-padding,10px 12px)}.van-search__content{background-color:var(--search-background-color,#f7f8fa);border-radius:2px;display:flex;flex:1;padding-left:var(--padding-sm,12px)}.van-search__content--round{border-radius:999px}.van-search__label{color:var(--search-label-color,#323233);font-size:var(--search-label-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-label-padding,0 5px)}.van-search__field{flex:1}.van-search__field__left-icon{color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{color:var(--search-action-text-color,#323233);font-size:var(--search-action-font-size,14px);line-height:var(--search-input-height,34px)}.van-search__action--hover{background-color:#f2f3f5}.van-search__action-button{padding:var(--search-action-padding,0 8px)}
================================================
FILE: lib/share-sheet/index.d.ts
================================================
export {};
================================================
FILE: lib/share-sheet/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
// whether to show popup
show: Boolean,
// overlay custom style
overlayStyle: String,
// z-index
zIndex: {
type: Number,
value: 100,
},
title: String,
cancelText: {
type: String,
value: '取消',
},
description: String,
options: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
duration: {
type: null,
value: 300,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClickOverlay: function () {
this.$emit('click-overlay');
},
onCancel: function () {
this.onClose();
this.$emit('cancel');
},
onSelect: function (event) {
this.$emit('select', event.detail);
},
onClose: function () {
this.$emit('close');
},
},
});
================================================
FILE: lib/share-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"options": "./options"
}
}
================================================
FILE: lib/share-sheet/index.wxml
================================================
================================================
FILE: lib/share-sheet/index.wxs
================================================
/* eslint-disable */
function isMulti(options) {
if (options == null || options[0] == null) {
return false;
}
return "Array" === options.constructor && "Array" === options[0].constructor;
}
module.exports = {
isMulti: isMulti
};
================================================
FILE: lib/share-sheet/index.wxss
================================================
@import '../common/index.wxss';.van-share-sheet__header{padding:12px 16px 4px;text-align:center}.van-share-sheet__title{color:#323233;font-size:14px;font-weight:400;line-height:20px;margin-top:8px}.van-share-sheet__title:empty,.van-share-sheet__title:not(:empty)+.van-share-sheet__title{display:none}.van-share-sheet__description{color:#969799;display:block;font-size:12px;line-height:16px;margin-top:8px}.van-share-sheet__description:empty,.van-share-sheet__description:not(:empty)+.van-share-sheet__description{display:none}.van-share-sheet__cancel{background:#fff;border:none;box-sizing:initial;display:block;font-size:16px;height:auto;line-height:48px;padding:0;text-align:center;width:100%}.van-share-sheet__cancel:before{background-color:#f7f8fa;content:" ";display:block;height:8px}.van-share-sheet__cancel:after{display:none}.van-share-sheet__cancel:active{background-color:#f2f3f5}
================================================
FILE: lib/share-sheet/options.d.ts
================================================
export {};
================================================
FILE: lib/share-sheet/options.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
options: Array,
showBorder: Boolean,
},
methods: {
onSelect: function (event) {
var index = event.currentTarget.dataset.index;
var option = this.data.options[index];
this.$emit('select', __assign(__assign({}, option), { index: index }));
},
},
});
================================================
FILE: lib/share-sheet/options.json
================================================
{
"component": true
}
================================================
FILE: lib/share-sheet/options.wxml
================================================
================================================
FILE: lib/share-sheet/options.wxs
================================================
/* eslint-disable */
var PRESET_ICONS = ['qq', 'link', 'weibo', 'wechat', 'poster', 'qrcode', 'weapp-qrcode', 'wechat-moments'];
function getIconURL(icon) {
if (PRESET_ICONS.indexOf(icon) !== -1) {
return 'https://img.yzcdn.cn/vant/share-sheet-' + icon + '.png';
}
return icon;
}
module.exports = {
getIconURL: getIconURL,
};
================================================
FILE: lib/share-sheet/options.wxss
================================================
@import '../common/index.wxss';.van-share-sheet__options{-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto;overflow-y:visible;padding:16px 0 16px 8px;position:relative}.van-share-sheet__options--border:before{border-top:1px solid #ebedf0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:0;top:0;transform:scaleY(.5);transform-origin:center}.van-share-sheet__options::-webkit-scrollbar{height:0}.van-share-sheet__option{align-items:center;display:flex;flex-direction:column;-webkit-user-select:none;user-select:none}.van-share-sheet__option:active{opacity:.7}.van-share-sheet__button{background-color:initial;border:0;height:auto;line-height:inherit;padding:0}.van-share-sheet__button:after{border:0}.van-share-sheet__icon{height:48px;margin:0 16px;width:48px}.van-share-sheet__name{color:#646566;font-size:12px;margin-top:8px;padding:0 4px}.van-share-sheet__option-description{color:#c8c9cc;font-size:12px;padding:0 4px}
================================================
FILE: lib/sidebar/index.d.ts
================================================
export {};
================================================
FILE: lib/sidebar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('sidebar-item', function () {
this.setActive(this.data.activeKey);
}),
props: {
activeKey: {
type: Number,
value: 0,
observer: 'setActive',
},
},
beforeCreate: function () {
this.currentActive = -1;
},
methods: {
setActive: function (activeKey) {
var _a = this, children = _a.children, currentActive = _a.currentActive;
if (!children.length) {
return Promise.resolve();
}
this.currentActive = activeKey;
var stack = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
},
},
});
================================================
FILE: lib/sidebar/index.json
================================================
{
"component": true
}
================================================
FILE: lib/sidebar/index.wxml
================================================
================================================
FILE: lib/sidebar/index.wxss
================================================
@import '../common/index.wxss';.van-sidebar{width:var(--sidebar-width,80px)}
================================================
FILE: lib/sidebar-item/index.d.ts
================================================
export {};
================================================
FILE: lib/sidebar-item/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
classes: ['active-class', 'disabled-class'],
relation: (0, relation_1.useParent)('sidebar'),
props: {
dot: Boolean,
badge: null,
info: null,
title: String,
disabled: Boolean,
},
methods: {
onClick: function () {
var _this = this;
var parent = this.parent;
if (!parent || this.data.disabled) {
return;
}
var index = parent.children.indexOf(this);
parent.setActive(index).then(function () {
_this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive: function (selected) {
return this.setData({ selected: selected });
},
},
});
================================================
FILE: lib/sidebar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: lib/sidebar-item/index.wxml
================================================
================================================
FILE: lib/sidebar-item/index.wxss
================================================
@import '../common/index.wxss';.van-sidebar-item{background-color:var(--sidebar-background-color,#f7f8fa);border-left:3px solid transparent;box-sizing:border-box;color:var(--sidebar-text-color,#323233);display:block;font-size:var(--sidebar-font-size,14px);line-height:var(--sidebar-line-height,20px);overflow:hidden;padding:var(--sidebar-padding,20px 12px 20px 8px);-webkit-user-select:none;user-select:none}.van-sidebar-item__text{display:inline-block;position:relative;word-break:break-all}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{border-color:var(--sidebar-selected-border-color,#ee0a24);color:var(--sidebar-selected-text-color,#323233);font-weight:var(--sidebar-selected-font-weight,500)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:var(--sidebar-disabled-text-color,#c8c9cc)}
================================================
FILE: lib/skeleton/index.d.ts
================================================
export {};
================================================
FILE: lib/skeleton/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: ['avatar-class', 'title-class', 'row-class'],
props: {
row: {
type: Number,
value: 0,
observer: function (value) {
this.setData({ rowArray: Array.from({ length: value }) });
},
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true,
},
animate: {
type: Boolean,
value: true,
},
avatarSize: {
type: String,
value: '32px',
},
avatarShape: {
type: String,
value: 'round',
},
titleWidth: {
type: String,
value: '40%',
},
rowWidth: {
type: null,
value: '100%',
observer: function (val) {
this.setData({ isArray: val instanceof Array });
},
},
},
data: {
isArray: false,
rowArray: [],
},
});
================================================
FILE: lib/skeleton/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: lib/skeleton/index.wxml
================================================
================================================
FILE: lib/skeleton/index.wxss
================================================
@import '../common/index.wxss';.van-skeleton{box-sizing:border-box;display:flex;padding:var(--skeleton-padding,0 16px);width:100%}.van-skeleton__avatar{background-color:var(--skeleton-avatar-background-color,#f2f3f5);flex-shrink:0;margin-right:var(--padding-md,16px)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{background-color:var(--skeleton-row-background-color,#f2f3f5);height:var(--skeleton-row-height,16px)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{animation:van-skeleton-blink 1.2s ease-in-out infinite}@keyframes van-skeleton-blink{50%{opacity:.6}}
================================================
FILE: lib/slider/index.d.ts
================================================
export {};
================================================
FILE: lib/slider/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var touch_1 = require("../mixins/touch");
var version_1 = require("../common/version");
var utils_1 = require("../common/utils");
var DRAG_STATUS = {
START: 'start',
MOVING: 'moving',
END: 'end',
};
(0, component_1.VantComponent)({
mixins: [touch_1.touch],
props: {
range: Boolean,
disabled: Boolean,
useButtonSlot: Boolean,
activeColor: String,
inactiveColor: String,
max: {
type: Number,
value: 100,
},
min: {
type: Number,
value: 0,
},
step: {
type: Number,
value: 1,
},
value: {
type: null,
value: 0,
observer: function (val) {
if (val !== this.value) {
this.updateValue(val);
}
},
},
vertical: Boolean,
barHeight: null,
},
created: function () {
this.updateValue(this.data.value);
},
methods: {
onTouchStart: function (event) {
var _this = this;
if (this.data.disabled)
return;
var index = event.currentTarget.dataset.index;
if (typeof index === 'number') {
this.buttonIndex = index;
}
this.touchStart(event);
this.startValue = this.format(this.value);
this.newValue = this.value;
if (this.isRange(this.newValue)) {
this.startValue = this.newValue.map(function (val) { return _this.format(val); });
}
else {
this.startValue = this.format(this.newValue);
}
this.dragStatus = DRAG_STATUS.START;
},
onTouchMove: function (event) {
var _this = this;
if (this.data.disabled)
return;
if (this.dragStatus === DRAG_STATUS.START) {
this.$emit('drag-start');
}
this.touchMove(event);
this.dragStatus = DRAG_STATUS.MOVING;
(0, utils_1.getRect)(this, '.van-slider').then(function (rect) {
var vertical = _this.data.vertical;
var delta = vertical ? _this.deltaY : _this.deltaX;
var total = vertical ? rect.height : rect.width;
var diff = (delta / total) * _this.getRange();
if (_this.isRange(_this.startValue)) {
_this.newValue[_this.buttonIndex] =
_this.startValue[_this.buttonIndex] + diff;
}
else {
_this.newValue = _this.startValue + diff;
}
_this.updateValue(_this.newValue, false, true);
});
},
onTouchEnd: function () {
var _this = this;
if (this.data.disabled)
return;
if (this.dragStatus === DRAG_STATUS.MOVING) {
this.dragStatus = DRAG_STATUS.END;
(0, utils_1.nextTick)(function () {
_this.updateValue(_this.newValue, true);
_this.$emit('drag-end');
});
}
},
onClick: function (event) {
var _this = this;
if (this.data.disabled)
return;
var min = this.data.min;
(0, utils_1.getRect)(this, '.van-slider').then(function (rect) {
var vertical = _this.data.vertical;
var touch = event.touches[0];
var delta = vertical
? touch.clientY - rect.top
: touch.clientX - rect.left;
var total = vertical ? rect.height : rect.width;
var value = Number(min) + (delta / total) * _this.getRange();
if (_this.isRange(_this.value)) {
var _a = _this.value, left = _a[0], right = _a[1];
var middle = (left + right) / 2;
if (value <= middle) {
_this.updateValue([value, right], true);
}
else {
_this.updateValue([left, value], true);
}
}
else {
_this.updateValue(value, true);
}
});
},
isRange: function (val) {
var range = this.data.range;
return range && Array.isArray(val);
},
handleOverlap: function (value) {
if (value[0] > value[1]) {
return value.slice(0).reverse();
}
return value;
},
updateValue: function (value, end, drag) {
var _this = this;
if (this.isRange(value)) {
value = this.handleOverlap(value).map(function (val) { return _this.format(val); });
}
else {
value = this.format(value);
}
this.value = value;
var vertical = this.data.vertical;
var mainAxis = vertical ? 'height' : 'width';
this.setData({
wrapperStyle: "\n background: ".concat(this.data.inactiveColor || '', ";\n ").concat(vertical ? 'width' : 'height', ": ").concat((0, utils_1.addUnit)(this.data.barHeight) || '', ";\n "),
barStyle: "\n ".concat(mainAxis, ": ").concat(this.calcMainAxis(), ";\n left: ").concat(vertical ? 0 : this.calcOffset(), ";\n top: ").concat(vertical ? this.calcOffset() : 0, ";\n ").concat(drag ? 'transition: none;' : '', "\n "),
});
if (drag) {
this.$emit('drag', { value: value });
}
if (end) {
this.$emit('change', value);
}
if ((drag || end) && (0, version_1.canIUseModel)()) {
this.setData({ value: value });
}
},
getScope: function () {
return Number(this.data.max) - Number(this.data.min);
},
getRange: function () {
var _a = this.data, max = _a.max, min = _a.min;
return max - min;
},
getOffsetWidth: function (current, min) {
var scope = this.getScope();
// 避免最小值小于最小step时出现负数情况
return "".concat(Math.max(((current - min) * 100) / scope, 0), "%");
},
// 计算选中条的长度百分比
calcMainAxis: function () {
var value = this.value;
var min = this.data.min;
if (this.isRange(value)) {
return this.getOffsetWidth(value[1], value[0]);
}
return this.getOffsetWidth(value, Number(min));
},
// 计算选中条的开始位置的偏移量
calcOffset: function () {
var value = this.value;
var min = this.data.min;
var scope = this.getScope();
if (this.isRange(value)) {
return "".concat(((value[0] - Number(min)) * 100) / scope, "%");
}
return '0%';
},
format: function (value) {
var min = +this.data.min;
var max = +this.data.max;
var step = +this.data.step;
value = (0, utils_1.clamp)(value, min, max);
var diff = Math.round((value - min) / step) * step;
return (0, utils_1.addNumber)(min, diff);
},
},
});
================================================
FILE: lib/slider/index.json
================================================
{
"component": true
}
================================================
FILE: lib/slider/index.wxml
================================================
================================================
FILE: lib/slider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function barStyle(barHeight, activeColor) {
return style({
height: addUnit(barHeight),
background: activeColor,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: lib/slider/index.wxss
================================================
@import '../common/index.wxss';.van-slider{background-color:var(--slider-inactive-background-color,#ebedf0);border-radius:999px;height:var(--slider-bar-height,2px);position:relative}.van-slider:before{bottom:calc(var(--padding-xs, 8px)*-1);content:"";left:0;position:absolute;right:0;top:calc(var(--padding-xs, 8px)*-1)}.van-slider__bar{background-color:var(--slider-active-background-color,#1989fa);border-radius:inherit;height:100%;position:relative;transition:all .2s;width:100%}.van-slider__button{background-color:var(--slider-button-background-color,#fff);border-radius:var(--slider-button-border-radius,50%);box-shadow:var(--slider-button-box-shadow,0 1px 2px rgba(0,0,0,.5));height:var(--slider-button-height,24px);width:var(--slider-button-width,24px)}.van-slider__button-wrapper,.van-slider__button-wrapper-right{position:absolute;right:0;top:50%;transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper-left{left:0;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.van-slider--disabled{opacity:var(--slider-disabled-opacity,.5)}.van-slider--vertical{display:inline-block;height:100%;width:var(--slider-bar-height,2px)}.van-slider--vertical .van-slider__button-wrapper,.van-slider--vertical .van-slider__button-wrapper-right{bottom:0;right:50%;top:auto;transform:translate3d(50%,50%,0)}.van-slider--vertical .van-slider__button-wrapper-left{left:auto;right:50%;top:0;transform:translate3d(50%,-50%,0)}.van-slider--vertical:before{bottom:0;left:-8px;right:-8px;top:0}
================================================
FILE: lib/stepper/index.d.ts
================================================
export {};
================================================
FILE: lib/stepper/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var validator_1 = require("../common/validator");
var LONG_PRESS_START_TIME = 600;
var LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1, num2) {
var cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
function equal(value1, value2) {
return String(value1) === String(value2);
}
(0, component_1.VantComponent)({
field: true,
classes: ['input-class', 'plus-class', 'minus-class'],
props: {
value: {
type: null,
},
integer: {
type: Boolean,
observer: 'check',
},
disabled: Boolean,
inputWidth: String,
buttonSize: String,
asyncChange: Boolean,
disableInput: Boolean,
decimalLength: {
type: Number,
value: null,
observer: 'check',
},
min: {
type: null,
value: 1,
observer: 'check',
},
max: {
type: null,
value: Number.MAX_SAFE_INTEGER,
observer: 'check',
},
step: {
type: null,
value: 1,
},
showPlus: {
type: Boolean,
value: true,
},
showMinus: {
type: Boolean,
value: true,
},
disablePlus: Boolean,
disableMinus: Boolean,
longPress: {
type: Boolean,
value: true,
},
theme: String,
alwaysEmbed: Boolean,
},
data: {
currentValue: '',
},
watch: {
value: function () {
this.observeValue();
},
},
created: function () {
this.setData({
currentValue: this.format(this.data.value).newValue,
});
},
methods: {
observeValue: function () {
var value = this.data.value;
this.setData({ currentValue: this.format(value).newValue });
},
check: function () {
var newValue = this.format(this.data.currentValue).newValue;
if (!equal(newValue, this.data.currentValue)) {
this.setData({ currentValue: newValue });
}
},
isDisabled: function (type) {
var _a = this.data, disabled = _a.disabled, disablePlus = _a.disablePlus, disableMinus = _a.disableMinus, currentValue = _a.currentValue, max = _a.max, min = _a.min;
if (type === 'plus') {
return disabled || disablePlus || +currentValue >= +max;
}
return disabled || disableMinus || +currentValue <= +min;
},
onFocus: function (event) {
this.$emit('focus', event.detail);
},
onBlur: function (event) {
var data = this.format(event.detail.value);
this.setData({ currentValue: data.newValue });
this.emitChange(data);
this.$emit('blur', __assign(__assign({}, event.detail), { value: +data.newValue }));
},
// filter illegal characters
filter: function (value) {
value = String(value).replace(/[^0-9.-]/g, '');
if (this.data.integer && value.indexOf('.') !== -1) {
value = value.split('.')[0];
}
return value;
},
format: function (value) {
// filter illegal characters and format integer
var safeValue = this.filter(value);
// format range
var rangeValue = Math.max(Math.min(this.data.max, +safeValue), this.data.min);
// format decimal
var newValue = (0, validator_1.isDef)(this.data.decimalLength)
? rangeValue.toFixed(this.data.decimalLength)
: String(rangeValue);
return { value: value, newValue: newValue };
},
onInput: function (event) {
var _a = (event.detail || {}).value, value = _a === void 0 ? '' : _a;
// allow input to be empty
if (value === '') {
return;
}
var formatted = this.format(value);
this.emitChange(formatted);
},
emitChange: function (data) {
var value = data.value, newValue = data.newValue;
if (!this.data.asyncChange) {
// fix when input 11. parsed to 11, unable to enter decimal
this.setData({ currentValue: +value === +newValue ? value : newValue });
}
this.$emit('change', +newValue);
},
onChange: function () {
var type = this.type;
if (this.isDisabled(type)) {
this.$emit('overlimit', type);
return;
}
var diff = type === 'minus' ? -this.data.step : +this.data.step;
var value = this.format(String(add(+this.data.currentValue, diff)));
this.emitChange(value);
this.$emit(type);
},
longPressStep: function () {
var _this = this;
this.longPressTimer = setTimeout(function () {
_this.onChange();
_this.longPressStep();
}, LONG_PRESS_INTERVAL);
},
onTap: function (event) {
var type = event.currentTarget.dataset.type;
this.type = type;
this.onChange();
},
onTouchStart: function (event) {
var _this = this;
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
var type = event.currentTarget.dataset.type;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(function () {
_this.isLongPress = true;
_this.onChange();
_this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onTouchEnd: function () {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
},
},
});
================================================
FILE: lib/stepper/index.json
================================================
{
"component": true
}
================================================
FILE: lib/stepper/index.wxml
================================================
================================================
FILE: lib/stepper/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function buttonStyle(data) {
return style({
width: addUnit(data.buttonSize),
height: addUnit(data.buttonSize),
});
}
function inputStyle(data) {
return style({
width: addUnit(data.inputWidth),
height: addUnit(data.buttonSize),
});
}
module.exports = {
buttonStyle: buttonStyle,
inputStyle: inputStyle,
};
================================================
FILE: lib/stepper/index.wxss
================================================
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{background-color:var(--stepper-background-color,#f2f3f5);border:0;box-sizing:border-box;color:var(--stepper-button-icon-color,#323233);display:inline-block;height:var(--stepper-input-height,28px);margin:1px;padding:var(--padding-base,4px);position:relative;vertical-align:middle;width:var(--stepper-input-height,28px)}.van-stepper__minus:before,.van-stepper__plus:before{height:1px;width:9px}.van-stepper__minus:after,.van-stepper__plus:after{height:9px;width:1px}.van-stepper__minus:empty.van-stepper__minus:after,.van-stepper__minus:empty.van-stepper__minus:before,.van-stepper__minus:empty.van-stepper__plus:after,.van-stepper__minus:empty.van-stepper__plus:before,.van-stepper__plus:empty.van-stepper__minus:after,.van-stepper__plus:empty.van-stepper__minus:before,.van-stepper__plus:empty.van-stepper__plus:after,.van-stepper__plus:empty.van-stepper__plus:before{background-color:currentColor;bottom:0;content:"";left:0;margin:auto;position:absolute;right:0;top:0}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0 0 var(--stepper-border-radius,var(--stepper-border-radius,4px))}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 var(--stepper-border-radius,var(--stepper-border-radius,4px)) var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0}.van-stepper--round .van-stepper__input{background-color:initial!important}.van-stepper--round .van-stepper__minus,.van-stepper--round .van-stepper__plus{border-radius:100%}.van-stepper--round .van-stepper__minus:active,.van-stepper--round .van-stepper__plus:active{opacity:.7}.van-stepper--round .van-stepper__minus--disabled,.van-stepper--round .van-stepper__minus--disabled:active,.van-stepper--round .van-stepper__plus--disabled,.van-stepper--round .van-stepper__plus--disabled:active{opacity:.3}.van-stepper--round .van-stepper__plus{background-color:#ee0a24;color:#fff}.van-stepper--round .van-stepper__minus{background-color:#fff;border:1px solid #ee0a24;color:#ee0a24}.van-stepper__input{-webkit-appearance:none;background-color:var(--stepper-background-color,#f2f3f5);border:0;border-radius:0;border-width:1px 0;box-sizing:border-box;color:var(--stepper-input-text-color,#323233);display:inline-block;font-size:var(--stepper-input-font-size,14px);height:var(--stepper-input-height,28px);margin:1px;min-height:0;padding:1px;text-align:center;vertical-align:middle;width:var(--stepper-input-width,32px)}.van-stepper__input--disabled{background-color:var(--stepper-input-disabled-background-color,#f2f3f5);color:var(--stepper-input-disabled-text-color,#c8c9cc)}
================================================
FILE: lib/steps/index.d.ts
================================================
export {};
================================================
FILE: lib/steps/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var color_1 = require("../common/color");
(0, component_1.VantComponent)({
classes: ['desc-class'],
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal',
},
activeColor: {
type: String,
value: color_1.GREEN,
},
inactiveColor: {
type: String,
value: color_1.GRAY_DARK,
},
activeIcon: {
type: String,
value: 'checked',
},
inactiveIcon: String,
},
methods: {
onClick: function (event) {
var index = event.currentTarget.dataset.index;
this.$emit('click-step', index);
},
},
});
================================================
FILE: lib/steps/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/steps/index.wxml
================================================
{{ item.text }}
{{ item.desc }}
function get(index, active) {
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return 'inactive';
}
module.exports = get;
================================================
FILE: lib/steps/index.wxss
================================================
@import '../common/index.wxss';.van-steps{background-color:var(--steps-background-color,#fff);overflow:hidden}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{display:flex;overflow:hidden;position:relative}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{color:var(--step-text-color,#969799);flex:1;font-size:var(--step-font-size,14px);position:relative}.van-step--finish{color:var(--step-finish-text-color,#323233)}.van-step__circle{background-color:var(--step-circle-color,#969799);border-radius:50%;height:var(--step-circle-size,5px);width:var(--step-circle-size,5px)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{bottom:0;position:absolute;right:0;top:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;transform:none}.van-step--horizontal:last-child .van-step__circle-container{padding:0 0 0 8px;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{background-color:#fff;bottom:6px;padding:0 var(--padding-xs,8px);position:absolute;transform:translate3d(-50%,50%,0);z-index:1}.van-step--horizontal .van-step__title{display:inline-block;font-size:var(--step-horizontal-title-font-size,12px);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{background-color:var(--step-line-color,#ebedf0);bottom:6px;height:1px;left:0;position:absolute;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical{line-height:18px;padding:10px 10px 10px 0}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{background-color:#fff;content:"";height:20px;left:-15px;position:absolute;top:0;width:1px;z-index:1}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{left:-14px;position:absolute;top:19px;transform:translate3d(-50%,-50%,0);z-index:2}.van-step--vertical .van-step__icon{background-color:var(--steps-background-color,#fff);font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical .van-step__line{background-color:var(--step-line-color,#ebedf0);height:100%;transform:translate3d(-50%,0,0);width:1px;z-index:1}
================================================
FILE: lib/sticky/index.d.ts
================================================
export {};
================================================
FILE: lib/sticky/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("../common/utils");
var component_1 = require("../common/component");
var validator_1 = require("../common/validator");
var page_scroll_1 = require("../mixins/page-scroll");
var ROOT_ELEMENT = '.van-sticky';
(0, component_1.VantComponent)({
props: {
zIndex: {
type: Number,
value: 99,
},
offsetTop: {
type: Number,
value: 0,
observer: 'onScroll',
},
disabled: {
type: Boolean,
observer: 'onScroll',
},
container: {
type: null,
observer: 'onScroll',
},
scrollTop: {
type: null,
observer: function (val) {
this.onScroll({ scrollTop: val });
},
},
},
mixins: [
(0, page_scroll_1.pageScrollMixin)(function (event) {
if (this.data.scrollTop != null) {
return;
}
this.onScroll(event);
}),
],
data: {
height: 0,
fixed: false,
transform: 0,
},
mounted: function () {
this.onScroll();
},
methods: {
onScroll: function (_a) {
var _this = this;
var _b = _a === void 0 ? {} : _a, scrollTop = _b.scrollTop;
var _c = this.data, container = _c.container, offsetTop = _c.offsetTop, disabled = _c.disabled;
if (disabled) {
this.setDataAfterDiff({
fixed: false,
transform: 0,
});
return;
}
this.scrollTop = scrollTop || this.scrollTop;
if (typeof container === 'function') {
Promise.all([(0, utils_1.getRect)(this, ROOT_ELEMENT), this.getContainerRect()])
.then(function (_a) {
var root = _a[0], container = _a[1];
if (offsetTop + root.height > container.height + container.top) {
_this.setDataAfterDiff({
fixed: false,
transform: container.height - root.height,
});
}
else if (offsetTop >= root.top) {
_this.setDataAfterDiff({
fixed: true,
height: root.height,
transform: 0,
});
}
else {
_this.setDataAfterDiff({ fixed: false, transform: 0 });
}
})
.catch(function () { });
return;
}
(0, utils_1.getRect)(this, ROOT_ELEMENT).then(function (root) {
if (!(0, validator_1.isDef)(root) || (!root.width && !root.height)) {
return;
}
if (offsetTop >= root.top) {
_this.setDataAfterDiff({ fixed: true, height: root.height });
_this.transform = 0;
}
else {
_this.setDataAfterDiff({ fixed: false });
}
});
},
setDataAfterDiff: function (data) {
var _this = this;
wx.nextTick(function () {
var diff = Object.keys(data).reduce(function (prev, key) {
if (data[key] !== _this.data[key]) {
prev[key] = data[key];
}
return prev;
}, {});
if (Object.keys(diff).length > 0) {
_this.setData(diff);
}
_this.$emit('scroll', {
scrollTop: _this.scrollTop,
isFixed: data.fixed || _this.data.fixed,
});
});
},
getContainerRect: function () {
var nodesRef = this.data.container();
if (!nodesRef) {
return Promise.reject(new Error('not found container'));
}
return new Promise(function (resolve) { return nodesRef.boundingClientRect(resolve).exec(); });
},
},
});
================================================
FILE: lib/sticky/index.json
================================================
{
"component": true
}
================================================
FILE: lib/sticky/index.wxml
================================================
================================================
FILE: lib/sticky/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapStyle(data) {
return style({
transform: data.transform
? 'translate3d(0, ' + data.transform + 'px, 0)'
: '',
top: data.fixed ? addUnit(data.offsetTop) : '',
'z-index': data.zIndex,
});
}
function containerStyle(data) {
return style({
height: data.fixed ? addUnit(data.height) : '',
'z-index': data.zIndex,
});
}
module.exports = {
wrapStyle: wrapStyle,
containerStyle: containerStyle,
};
================================================
FILE: lib/sticky/index.wxss
================================================
@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{left:0;position:fixed;right:0}
================================================
FILE: lib/submit-bar/index.d.ts
================================================
export {};
================================================
FILE: lib/submit-bar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: ['bar-class', 'price-class', 'button-class'],
props: {
tip: {
type: null,
observer: 'updateTip',
},
tipIcon: String,
type: Number,
price: {
type: null,
observer: 'updatePrice',
},
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥',
},
buttonType: {
type: String,
value: 'danger',
},
decimalLength: {
type: Number,
value: 2,
observer: 'updatePrice',
},
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
updatePrice: function () {
var _a = this.data, price = _a.price, decimalLength = _a.decimalLength;
var priceStrArr = typeof price === 'number' &&
(price / 100).toFixed(decimalLength).split('.');
this.setData({
hasPrice: typeof price === 'number',
integerStr: priceStrArr && priceStrArr[0],
decimalStr: decimalLength && priceStrArr ? ".".concat(priceStrArr[1]) : '',
});
},
updateTip: function () {
this.setData({ hasTip: typeof this.data.tip === 'string' });
},
onSubmit: function (event) {
this.$emit('submit', event.detail);
},
},
});
================================================
FILE: lib/submit-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/submit-bar/index.wxml
================================================
{{ tip }}
{{ label || '合计:' }}
{{ currency }}
{{ integerStr }}{{decimalStr}}
{{ suffixLabel }}
{{ loading ? '' : buttonText }}
================================================
FILE: lib/submit-bar/index.wxss
================================================
@import '../common/index.wxss';.van-submit-bar{background-color:var(--submit-bar-background-color,#fff);bottom:0;left:0;position:fixed;-webkit-user-select:none;user-select:none;width:100%;z-index:var(--submit-bar-z-index,100)}.van-submit-bar__tip{background-color:var(--submit-bar-tip-background-color,#fff7cc);color:var(--submit-bar-tip-color,#f56723);font-size:var(--submit-bar-tip-font-size,12px);line-height:var(--submit-bar-tip-line-height,1.5);padding:var(--submit-bar-tip-padding,10px)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{margin-right:4px;vertical-align:middle}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{align-items:center;background-color:var(--submit-bar-background-color,#fff);display:flex;font-size:var(--submit-bar-text-font-size,14px);height:var(--submit-bar-height,50px);justify-content:flex-end;padding:var(--submit-bar-padding,0 16px)}.van-submit-bar__safe{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}.van-submit-bar__text{color:var(--submit-bar-text-color,#323233);flex:1;font-weight:var(--font-weight-bold,500);padding-right:var(--padding-sm,12px);text-align:right}.van-submit-bar__price{color:var(--submit-bar-price-color,#ee0a24);font-size:var(--submit-bar-price-font-size,12px);font-weight:var(--font-weight-bold,500)}.van-submit-bar__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:20px}.van-submit-bar__currency{font-size:var(--submit-bar-currency-font-size,12px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{--button-default-height:var(--submit-bar-button-height,40px)!important;--button-line-height:var(--submit-bar-button-height,40px)!important;font-weight:var(--font-weight-bold,500);width:var(--submit-bar-button-width,110px)}
================================================
FILE: lib/swipe-cell/index.d.ts
================================================
export {};
================================================
FILE: lib/swipe-cell/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var touch_1 = require("../mixins/touch");
var utils_1 = require("../common/utils");
var THRESHOLD = 0.3;
var ARRAY = [];
(0, component_1.VantComponent)({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0,
observer: function (leftWidth) {
if (leftWidth === void 0) { leftWidth = 0; }
if (this.offset > 0) {
this.swipeMove(leftWidth);
}
},
},
rightWidth: {
type: Number,
value: 0,
observer: function (rightWidth) {
if (rightWidth === void 0) { rightWidth = 0; }
if (this.offset < 0) {
this.swipeMove(-rightWidth);
}
},
},
asyncClose: Boolean,
name: {
type: null,
value: '',
},
},
mixins: [touch_1.touch],
data: {
catchMove: false,
wrapperStyle: '',
},
created: function () {
this.offset = 0;
ARRAY.push(this);
},
destroyed: function () {
var _this = this;
ARRAY = ARRAY.filter(function (item) { return item !== _this; });
},
methods: {
open: function (position) {
var _a = this.data, leftWidth = _a.leftWidth, rightWidth = _a.rightWidth;
var offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
this.$emit('open', {
position: position,
name: this.data.name,
});
},
close: function () {
this.swipeMove(0);
},
swipeMove: function (offset) {
if (offset === void 0) { offset = 0; }
this.offset = (0, utils_1.range)(offset, -this.data.rightWidth, this.data.leftWidth);
var transform = "translate3d(".concat(this.offset, "px, 0, 0)");
var transition = this.dragging
? 'none'
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.setData({
wrapperStyle: "\n -webkit-transform: ".concat(transform, ";\n -webkit-transition: ").concat(transition, ";\n transform: ").concat(transform, ";\n transition: ").concat(transition, ";\n "),
});
},
swipeLeaveTransition: function () {
var _a = this.data, leftWidth = _a.leftWidth, rightWidth = _a.rightWidth;
var offset = this.offset;
if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
this.open('right');
}
else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
this.open('left');
}
else {
this.swipeMove(0);
}
this.setData({ catchMove: false });
},
startDrag: function (event) {
if (this.data.disabled) {
return;
}
this.startOffset = this.offset;
this.touchStart(event);
},
noop: function () { },
onDrag: function (event) {
var _this = this;
if (this.data.disabled) {
return;
}
this.touchMove(event);
if (this.direction !== 'horizontal') {
return;
}
this.dragging = true;
ARRAY.filter(function (item) { return item !== _this && item.offset !== 0; }).forEach(function (item) { return item.close(); });
this.setData({ catchMove: true });
this.swipeMove(this.startOffset + this.deltaX);
},
endDrag: function () {
if (this.data.disabled) {
return;
}
this.dragging = false;
this.swipeLeaveTransition();
},
onClick: function (event) {
var _a = event.currentTarget.dataset.key, position = _a === void 0 ? 'outside' : _a;
this.$emit('click', position);
if (!this.offset) {
return;
}
if (this.data.asyncClose) {
this.$emit('close', {
position: position,
instance: this,
name: this.data.name,
});
}
else {
this.swipeMove(0);
}
},
},
});
================================================
FILE: lib/swipe-cell/index.json
================================================
{
"component": true
}
================================================
FILE: lib/swipe-cell/index.wxml
================================================
================================================
FILE: lib/swipe-cell/index.wxss
================================================
@import '../common/index.wxss';.van-swipe-cell{overflow:hidden;position:relative}.van-swipe-cell__left,.van-swipe-cell__right{height:100%;position:absolute;top:0}.van-swipe-cell__left{left:0;transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;transform:translate3d(100%,0,0)}
================================================
FILE: lib/switch/index.d.ts
================================================
export {};
================================================
FILE: lib/switch/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
field: true,
classes: ['node-class'],
props: {
checked: null,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '30',
},
activeValue: {
type: null,
value: true,
},
inactiveValue: {
type: null,
value: false,
},
},
methods: {
onClick: function () {
var _a = this.data, activeValue = _a.activeValue, inactiveValue = _a.inactiveValue, disabled = _a.disabled, loading = _a.loading;
if (disabled || loading) {
return;
}
var checked = this.data.checked === activeValue;
var value = checked ? inactiveValue : activeValue;
this.$emit('input', value);
this.$emit('change', value);
},
},
});
================================================
FILE: lib/switch/index.json
================================================
{
"component": true,
"usingComponents": {
"van-loading": "../loading/index"
}
}
================================================
FILE: lib/switch/index.wxml
================================================
================================================
FILE: lib/switch/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
var currentColor = data.checked === data.activeValue ? data.activeColor : data.inactiveColor;
return style({
'font-size': addUnit(data.size),
'background-color': currentColor,
});
}
var BLUE = '#1989fa';
var GRAY_DARK = '#969799';
function loadingColor(data) {
return data.checked === data.activeValue
? data.activeColor || BLUE
: data.inactiveColor || GRAY_DARK;
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: lib/switch/index.wxss
================================================
@import '../common/index.wxss';.van-switch{background-color:var(--switch-background-color,#fff);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:var(--switch-node-size,1em);box-sizing:initial;display:inline-block;height:var(--switch-height,1em);position:relative;transition:background-color var(--switch-transition-duration,.3s);width:var(--switch-width,2em)}.van-switch__node{background-color:var(--switch-node-background-color,#fff);border-radius:100%;box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));height:var(--switch-node-size,1em);left:0;position:absolute;top:0;transition:var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);width:var(--switch-node-size,1em);z-index:var(--switch-node-z-index,1)}.van-switch__loading{height:50%;left:25%;position:absolute!important;top:25%;width:50%}.van-switch--on{background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:var(--switch-disabled-opacity,.4)}
================================================
FILE: lib/tab/index.d.ts
================================================
export {};
================================================
FILE: lib/tab/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var relation_1 = require("../common/relation");
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
relation: (0, relation_1.useParent)('tabs'),
props: {
dot: {
type: Boolean,
observer: 'update',
},
info: {
type: null,
observer: 'update',
},
title: {
type: String,
observer: 'update',
},
disabled: {
type: Boolean,
observer: 'update',
},
titleStyle: {
type: String,
observer: 'update',
},
name: {
type: null,
value: '',
},
},
data: {
active: false,
},
methods: {
getComputedName: function () {
if (this.data.name !== '') {
return this.data.name;
}
return this.index;
},
updateRender: function (active, parent) {
var parentData = parent.data;
this.inited = this.inited || active;
this.setData({
active: active,
shouldRender: this.inited || !parentData.lazyRender,
shouldShow: active || parentData.animated,
});
},
update: function () {
if (this.parent) {
this.parent.updateTabs();
}
},
},
});
================================================
FILE: lib/tab/index.json
================================================
{
"component": true
}
================================================
FILE: lib/tab/index.wxml
================================================
================================================
FILE: lib/tab/index.wxss
================================================
@import '../common/index.wxss';:host{box-sizing:border-box;flex-shrink:0;width:100%}.van-tab__pane{-webkit-overflow-scrolling:touch;box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
================================================
FILE: lib/tabbar/index.d.ts
================================================
export {};
================================================
FILE: lib/tabbar/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
var utils_1 = require("../common/utils");
(0, component_1.VantComponent)({
relation: (0, relation_1.useChildren)('tabbar-item', function () {
this.updateChildren();
}),
props: {
active: {
type: null,
observer: 'updateChildren',
},
activeColor: {
type: String,
observer: 'updateChildren',
},
inactiveColor: {
type: String,
observer: 'updateChildren',
},
fixed: {
type: Boolean,
value: true,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
data: {
height: 50,
},
methods: {
updateChildren: function () {
var children = this.children;
if (!Array.isArray(children) || !children.length) {
return;
}
children.forEach(function (child) { return child.updateFromParent(); });
},
setHeight: function () {
var _this = this;
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(function () {
(0, utils_1.getRect)(_this, '.van-tabbar').then(function (res) {
_this.setData({ height: res.height });
});
});
},
},
});
================================================
FILE: lib/tabbar/index.json
================================================
{
"component": true
}
================================================
FILE: lib/tabbar/index.wxml
================================================
================================================
FILE: lib/tabbar/index.wxss
================================================
@import '../common/index.wxss';.van-tabbar{background-color:var(--tabbar-background-color,#fff);box-sizing:initial;display:flex;height:var(--tabbar-height,50px);width:100%}.van-tabbar--fixed{bottom:0;left:0;position:fixed}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
================================================
FILE: lib/tabbar-item/index.d.ts
================================================
export {};
================================================
FILE: lib/tabbar-item/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
props: {
info: null,
name: null,
icon: String,
dot: Boolean,
url: {
type: String,
value: '',
},
linkType: {
type: String,
value: 'redirectTo',
},
iconPrefix: {
type: String,
value: 'van-icon',
},
},
relation: (0, relation_1.useParent)('tabbar'),
data: {
active: false,
activeColor: '',
inactiveColor: '',
},
methods: {
onClick: function () {
var parent = this.parent;
if (parent) {
var index = parent.children.indexOf(this);
var active = this.data.name || index;
if (active !== this.data.active) {
parent.$emit('change', active);
}
}
var _a = this.data, url = _a.url, linkType = _a.linkType;
if (url && wx[linkType]) {
return wx[linkType]({ url: url });
}
this.$emit('click');
},
updateFromParent: function () {
var parent = this.parent;
if (!parent) {
return;
}
var index = parent.children.indexOf(this);
var parentData = parent.data;
var data = this.data;
var active = (data.name || index) === parentData.active;
var patch = {};
if (active !== data.active) {
patch.active = active;
}
if (parentData.activeColor !== data.activeColor) {
patch.activeColor = parentData.activeColor;
}
if (parentData.inactiveColor !== data.inactiveColor) {
patch.inactiveColor = parentData.inactiveColor;
}
if (Object.keys(patch).length > 0) {
this.setData(patch);
}
},
},
});
================================================
FILE: lib/tabbar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-info": "../info/index"
}
}
================================================
FILE: lib/tabbar-item/index.wxml
================================================
================================================
FILE: lib/tabbar-item/index.wxss
================================================
@import '../common/index.wxss';:host{flex:1}.van-tabbar-item{align-items:center;color:var(--tabbar-item-text-color,#646566);display:flex;flex-direction:column;font-size:var(--tabbar-item-font-size,12px);height:100%;justify-content:center;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{font-size:var(--tabbar-item-icon-size,22px);margin-bottom:var(--tabbar-item-margin-bottom,4px);position:relative}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
================================================
FILE: lib/tabs/index.d.ts
================================================
export {};
================================================
FILE: lib/tabs/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var touch_1 = require("../mixins/touch");
var utils_1 = require("../common/utils");
var validator_1 = require("../common/validator");
var relation_1 = require("../common/relation");
(0, component_1.VantComponent)({
mixins: [touch_1.touch],
classes: [
'nav-class',
'tab-class',
'tab-active-class',
'line-class',
'wrap-class',
],
relation: (0, relation_1.useChildren)('tab', function () {
this.updateTabs();
}),
props: {
sticky: Boolean,
border: Boolean,
swipeable: Boolean,
titleActiveColor: String,
titleInactiveColor: String,
color: String,
animated: {
type: Boolean,
observer: function () {
var _this = this;
this.children.forEach(function (child, index) {
return child.updateRender(index === _this.data.currentIndex, _this);
});
},
},
lineWidth: {
type: null,
value: 40,
observer: 'resize',
},
lineHeight: {
type: null,
value: -1,
},
active: {
type: null,
value: 0,
observer: function (name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
},
},
type: {
type: String,
value: 'line',
},
ellipsis: {
type: Boolean,
value: true,
},
duration: {
type: Number,
value: 0.3,
},
zIndex: {
type: Number,
value: 1,
},
swipeThreshold: {
type: Number,
value: 5,
observer: function (value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis,
});
},
},
offsetTop: {
type: Number,
value: 0,
},
lazyRender: {
type: Boolean,
value: true,
},
useBeforeChange: {
type: Boolean,
value: false,
},
},
data: {
tabs: [],
scrollLeft: 0,
scrollable: false,
currentIndex: 0,
container: null,
skipTransition: true,
scrollWithAnimation: false,
lineOffsetLeft: 0,
inited: false,
},
mounted: function () {
var _this = this;
(0, utils_1.requestAnimationFrame)(function () {
_this.swiping = true;
_this.setData({
container: function () { return _this.createSelectorQuery().select('.van-tabs'); },
});
_this.resize();
_this.scrollIntoView();
});
},
methods: {
updateTabs: function () {
var _a = this, _b = _a.children, children = _b === void 0 ? [] : _b, data = _a.data;
this.setData({
tabs: children.map(function (child) { return child.data; }),
scrollable: this.children.length > data.swipeThreshold || !data.ellipsis,
});
this.setCurrentIndexByName(data.active || this.getCurrentName());
},
trigger: function (eventName, child) {
var currentIndex = this.data.currentIndex;
var data = this.getChildData(currentIndex, child);
if (!(0, validator_1.isDef)(data)) {
return;
}
this.$emit(eventName, data);
},
onTap: function (event) {
var _this = this;
var index = event.currentTarget.dataset.index;
var child = this.children[index];
if (child.data.disabled) {
this.trigger('disabled', child);
return;
}
this.onBeforeChange(index).then(function () {
_this.setCurrentIndex(index);
(0, utils_1.nextTick)(function () {
_this.trigger('click');
});
});
},
// correct the index of active tab
setCurrentIndexByName: function (name) {
var _a = this.children, children = _a === void 0 ? [] : _a;
var matched = children.filter(function (child) { return child.getComputedName() === name; });
if (matched.length) {
this.setCurrentIndex(matched[0].index);
}
},
setCurrentIndex: function (currentIndex) {
var _this = this;
var _a = this, data = _a.data, _b = _a.children, children = _b === void 0 ? [] : _b;
if (!(0, validator_1.isDef)(currentIndex) ||
currentIndex >= children.length ||
currentIndex < 0) {
return;
}
(0, utils_1.groupSetData)(this, function () {
children.forEach(function (item, index) {
var active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, _this);
}
});
});
if (currentIndex === data.currentIndex) {
if (!data.inited) {
this.resize();
}
return;
}
var shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex: currentIndex });
(0, utils_1.requestAnimationFrame)(function () {
_this.resize();
_this.scrollIntoView();
});
(0, utils_1.nextTick)(function () {
_this.trigger('input');
if (shouldEmitChange) {
_this.trigger('change');
}
});
},
getCurrentName: function () {
var activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
}
},
resize: function () {
var _this = this;
if (this.data.type !== 'line') {
return;
}
var _a = this.data, currentIndex = _a.currentIndex, ellipsis = _a.ellipsis, skipTransition = _a.skipTransition;
Promise.all([
(0, utils_1.getAllRect)(this, '.van-tab'),
(0, utils_1.getRect)(this, '.van-tabs__line'),
]).then(function (_a) {
var _b = _a[0], rects = _b === void 0 ? [] : _b, lineRect = _a[1];
var rect = rects[currentIndex];
if (rect == null) {
return;
}
var lineOffsetLeft = rects
.slice(0, currentIndex)
.reduce(function (prev, curr) { return prev + curr.width; }, 0);
lineOffsetLeft +=
(rect.width - lineRect.width) / 2 + (ellipsis ? 0 : 8);
_this.setData({ lineOffsetLeft: lineOffsetLeft, inited: true });
_this.swiping = true;
if (skipTransition) {
// waiting transition end
setTimeout(function () {
_this.setData({ skipTransition: false });
}, _this.data.duration);
}
});
},
// scroll active tab into view
scrollIntoView: function () {
var _this = this;
var _a = this.data, currentIndex = _a.currentIndex, scrollable = _a.scrollable, scrollWithAnimation = _a.scrollWithAnimation;
if (!scrollable) {
return;
}
Promise.all([
(0, utils_1.getAllRect)(this, '.van-tab'),
(0, utils_1.getRect)(this, '.van-tabs__nav'),
]).then(function (_a) {
var tabRects = _a[0], navRect = _a[1];
var tabRect = tabRects[currentIndex];
var offsetLeft = tabRects
.slice(0, currentIndex)
.reduce(function (prev, curr) { return prev + curr.width; }, 0);
_this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
});
if (!scrollWithAnimation) {
(0, utils_1.nextTick)(function () {
_this.setData({ scrollWithAnimation: true });
});
}
});
},
onTouchScroll: function (event) {
this.$emit('scroll', event.detail);
},
onTouchStart: function (event) {
if (!this.data.swipeable)
return;
this.swiping = true;
this.touchStart(event);
},
onTouchMove: function (event) {
if (!this.data.swipeable || !this.swiping)
return;
this.touchMove(event);
},
// watch swipe touch end
onTouchEnd: function () {
var _this = this;
if (!this.data.swipeable || !this.swiping)
return;
var _a = this, direction = _a.direction, deltaX = _a.deltaX, offsetX = _a.offsetX;
var minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
var index_1 = this.getAvaiableTab(deltaX);
if (index_1 !== -1) {
this.onBeforeChange(index_1).then(function () { return _this.setCurrentIndex(index_1); });
}
}
this.swiping = false;
},
getAvaiableTab: function (direction) {
var _a = this.data, tabs = _a.tabs, currentIndex = _a.currentIndex;
var step = direction > 0 ? -1 : 1;
for (var i = step; currentIndex + i < tabs.length && currentIndex + i >= 0; i += step) {
var index = currentIndex + i;
if (index >= 0 &&
index < tabs.length &&
tabs[index] &&
!tabs[index].disabled) {
return index;
}
}
return -1;
},
onBeforeChange: function (index) {
var _this = this;
var useBeforeChange = this.data.useBeforeChange;
if (!useBeforeChange) {
return Promise.resolve();
}
return new Promise(function (resolve, reject) {
_this.$emit('before-change', __assign(__assign({}, _this.getChildData(index)), { callback: function (status) { return (status ? resolve() : reject()); } }));
});
},
getChildData: function (index, child) {
var currentChild = child || this.children[index];
if (!(0, validator_1.isDef)(currentChild)) {
return;
}
return {
index: currentChild.index,
name: currentChild.getComputedName(),
title: currentChild.data.title,
};
},
},
});
================================================
FILE: lib/tabs/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index",
"van-sticky": "../sticky/index"
}
}
================================================
FILE: lib/tabs/index.wxml
================================================
{{ item.title }}
================================================
FILE: lib/tabs/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(data) {
var titleColor = data.active
? data.titleActiveColor
: data.titleInactiveColor;
var ellipsis = data.scrollable && data.ellipsis;
// card theme color
if (data.type === 'card') {
return style({
'border-color': data.color,
'background-color': !data.disabled && data.active ? data.color : null,
color: titleColor || (!data.disabled && !data.active ? data.color : null),
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
return style({
color: titleColor,
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
function navStyle(color, type) {
return style({
'border-color': type === 'card' && color ? color : null,
});
}
function trackStyle(data) {
if (!data.animated) {
return '';
}
return style({
left: -100 * data.currentIndex + '%',
'transition-duration': data.duration + 's',
'-webkit-transition-duration': data.duration + 's',
});
}
function lineStyle(data) {
return style({
width: utils.addUnit(data.lineWidth),
opacity: data.inited ? 1 : 0,
transform: 'translateX(' + data.lineOffsetLeft + 'px)',
'-webkit-transform': 'translateX(' + data.lineOffsetLeft + 'px)',
'background-color': data.color,
height: data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'border-radius':
data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'transition-duration': !data.skipTransition ? data.duration + 's' : null,
'-webkit-transition-duration': !data.skipTransition
? data.duration + 's'
: null,
});
}
module.exports = {
tabClass: tabClass,
tabStyle: tabStyle,
trackStyle: trackStyle,
lineStyle: lineStyle,
navStyle: navStyle,
};
================================================
FILE: lib/tabs/index.wxss
================================================
@import '../common/index.wxss';.van-tabs{-webkit-tap-highlight-color:transparent;position:relative}.van-tabs__wrap{display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{flex:0 0 22%}.van-tabs__wrap--scrollable .van-tab--complete{flex:1 0 auto!important;padding:0 12px}.van-tabs__wrap--scrollable .van-tabs__nav--complete{padding-left:8px;padding-right:8px}.van-tabs__scroll{background-color:var(--tabs-nav-background-color,#fff);overflow:auto}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{border:1px solid var(--tabs-default-color,#ee0a24);border-radius:2px;box-sizing:border-box;margin:0 var(--padding-md,16px);width:calc(100% - var(--padding-md, 16px)*2)}.van-tabs__scroll::-webkit-scrollbar{display:none}.van-tabs__nav{display:flex;position:relative;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:var(--tabs-card-height,30px)}.van-tabs__nav--card .van-tab{border-right:1px solid var(--tabs-default-color,#ee0a24);color:var(--tabs-default-color,#ee0a24);line-height:calc(var(--tabs-card-height, 30px) - 2px)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{background-color:var(--tabs-default-color,#ee0a24);color:#fff}.van-tabs__nav--card .van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{background-color:var(--tabs-bottom-bar-color,#ee0a24);border-radius:var(--tabs-bottom-bar-height,3px);bottom:0;height:var(--tabs-bottom-bar-height,3px);left:0;opacity:0;position:absolute;z-index:1}.van-tabs__track{height:100%;position:relative;width:100%}.van-tabs__track--animated{display:flex;transition-property:left}.van-tabs__content{overflow:hidden}.van-tabs--line{height:var(--tabs-line-height,44px)}.van-tabs--card{height:var(--tabs-card-height,30px)}.van-tab{box-sizing:border-box;color:var(--tab-text-color,#646566);cursor:pointer;flex:1;font-size:var(--tab-font-size,14px);line-height:var(--tabs-line-height,44px);min-width:0;padding:0 5px;position:relative;text-align:center}.van-tab--active{color:var(--tab-active-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab__title__info{position:relative!important;top:-1px!important;transform:translateX(0)!important}
================================================
FILE: lib/tag/index.d.ts
================================================
export {};
================================================
FILE: lib/tag/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
size: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String,
type: {
type: String,
value: 'default',
},
closeable: Boolean,
},
methods: {
onClose: function () {
this.$emit('close');
},
},
});
================================================
FILE: lib/tag/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: lib/tag/index.wxml
================================================
================================================
FILE: lib/tag/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style({
'background-color': data.plain ? '' : data.color,
color: data.textColor || data.plain ? data.textColor || data.color : '',
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/tag/index.wxss
================================================
@import '../common/index.wxss';.van-tag{align-items:center;border-radius:var(--tag-border-radius,2px);color:var(--tag-text-color,#fff);display:inline-flex;font-size:var(--tag-font-size,12px);line-height:var(--tag-line-height,16px);padding:var(--tag-padding,0 4px);position:relative}.van-tag--default{background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:var(--tag-danger-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:var(--tag-danger-color,#ee0a24)}.van-tag--primary{background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:var(--tag-plain-background-color,#fff)}.van-tag--plain:before{border:1px solid;border-radius:inherit;bottom:0;content:"";left:0;pointer-events:none;position:absolute;right:0;top:0}.van-tag--medium{padding:var(--tag-medium-padding,2px 6px)}.van-tag--large{border-radius:var(--tag-large-border-radius,4px);font-size:var(--tag-large-font-size,14px);padding:var(--tag-large-padding,4px 8px)}.van-tag--mark{border-radius:0 var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) 0}.van-tag--mark:after{content:"";display:block;width:2px}.van-tag--round{border-radius:var(--tag-round-border-radius,999px)}.van-tag__close{margin-left:2px;min-width:1em}
================================================
FILE: lib/toast/index.d.ts
================================================
export {};
================================================
FILE: lib/toast/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000,
},
type: {
type: String,
value: 'text',
},
loadingType: {
type: String,
value: 'circular',
},
position: {
type: String,
value: 'middle',
},
},
methods: {
// for prevent touchmove
noop: function () { },
},
});
================================================
FILE: lib/toast/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index",
"van-overlay": "../overlay/index",
"van-transition": "../transition/index"
}
}
================================================
FILE: lib/toast/index.wxml
================================================
{{ message }}
{{ message }}
================================================
FILE: lib/toast/index.wxss
================================================
@import '../common/index.wxss';.van-toast{word-wrap:break-word;align-items:center;background-color:var(--toast-background-color,rgba(0,0,0,.7));border-radius:var(--toast-border-radius,8px);box-sizing:initial;color:var(--toast-text-color,#fff);display:flex;flex-direction:column;font-size:var(--toast-font-size,14px);justify-content:center;line-height:var(--toast-line-height,20px);white-space:pre-wrap}.van-toast__container{left:50%;max-width:var(--toast-max-width,70%);position:fixed;top:50%;transform:translate(-50%,-50%);width:-webkit-fit-content;width:fit-content}.van-toast--text{min-width:var(--toast-text-min-width,96px);padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{min-height:var(--toast-default-min-height,88px);padding:var(--toast-default-padding,16px);width:var(--toast-default-width,88px)}.van-toast--icon .van-toast__icon{font-size:var(--toast-icon-size,36px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{transform:translateY(-30vh)}.van-toast--bottom{transform:translateY(30vh)}
================================================
FILE: lib/toast/toast.d.ts
================================================
///
///
type ToastMessage = string | number;
type ToastContext = WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
interface ToastOptions {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: (() => ToastContext) | ToastContext;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
onClose?: () => void;
}
declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance | undefined;
declare namespace Toast {
var loading: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var success: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var fail: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var clear: () => void;
var setDefaultOptions: (options: ToastOptions) => void;
var resetDefaultOptions: () => void;
}
export default Toast;
================================================
FILE: lib/toast/toast.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var validator_1 = require("../common/validator");
var defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 2000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast',
};
var queue = [];
var currentOptions = __assign({}, defaultOptions);
function parseOptions(message) {
return (0, validator_1.isObj)(message) ? message : { message: message };
}
function getContext() {
var pages = getCurrentPages();
return pages[pages.length - 1];
}
function Toast(toastOptions) {
var options = __assign(__assign({}, currentOptions), parseOptions(toastOptions));
var context = (typeof options.context === 'function'
? options.context()
: options.context) || getContext();
var toast = context.selectComponent(options.selector);
if (!toast) {
console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
return;
}
delete options.context;
delete options.selector;
toast.clear = function () {
toast.setData({ show: false });
if (options.onClose) {
options.onClose();
}
};
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration != null && options.duration > 0) {
toast.timer = setTimeout(function () {
toast.clear();
queue = queue.filter(function (item) { return item !== toast; });
}, options.duration);
}
return toast;
}
var createMethod = function (type) { return function (options) {
return Toast(__assign({ type: type }, parseOptions(options)));
}; };
Toast.loading = createMethod('loading');
Toast.success = createMethod('success');
Toast.fail = createMethod('fail');
Toast.clear = function () {
queue.forEach(function (toast) {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = function (options) {
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = function () {
currentOptions = __assign({}, defaultOptions);
};
exports.default = Toast;
================================================
FILE: lib/transition/index.d.ts
================================================
export {};
================================================
FILE: lib/transition/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var transition_1 = require("../mixins/transition");
(0, component_1.VantComponent)({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
],
mixins: [(0, transition_1.transition)(true)],
});
================================================
FILE: lib/transition/index.json
================================================
{
"component": true
}
================================================
FILE: lib/transition/index.wxml
================================================
================================================
FILE: lib/transition/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style([
{
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: lib/transition/index.wxss
================================================
@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:transform}.van-slide-up-enter,.van-slide-up-leave-to{transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{transform:translate3d(100%,0,0)}
================================================
FILE: lib/tree-select/index.d.ts
================================================
export {};
================================================
FILE: lib/tree-select/index.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
(0, component_1.VantComponent)({
classes: [
'main-item-class',
'content-item-class',
'main-active-class',
'content-active-class',
'main-disabled-class',
'content-disabled-class',
],
props: {
items: {
type: Array,
observer: 'updateSubItems',
},
activeId: null,
mainActiveIndex: {
type: Number,
value: 0,
observer: 'updateSubItems',
},
height: {
type: null,
value: 300,
},
max: {
type: Number,
value: Infinity,
},
selectedIcon: {
type: String,
value: 'success',
},
},
data: {
subItems: [],
},
methods: {
// 当一个子项被选择时
onSelectItem: function (event) {
var item = event.currentTarget.dataset.item;
var isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
var isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
var isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav: function (event) {
var index = event.detail;
var item = this.data.items[index];
if (!item.disabled) {
this.$emit('click-nav', { index: index });
}
},
// 更新子项列表
updateSubItems: function () {
var _a = this.data, items = _a.items, mainActiveIndex = _a.mainActiveIndex;
var _b = (items[mainActiveIndex] || {}).children, children = _b === void 0 ? [] : _b;
this.setData({ subItems: children });
},
},
});
================================================
FILE: lib/tree-select/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
}
}
================================================
FILE: lib/tree-select/index.wxml
================================================
{{ item.text }}
================================================
FILE: lib/tree-select/index.wxs
================================================
/* eslint-disable */
var array = require('../wxs/array.wxs');
function isActive (activeList, itemId) {
if (array.isArray(activeList)) {
return activeList.indexOf(itemId) > -1;
}
return activeList === itemId;
}
module.exports.isActive = isActive;
================================================
FILE: lib/tree-select/index.wxss
================================================
@import '../common/index.wxss';.van-tree-select{display:flex;font-size:var(--tree-select-font-size,14px);position:relative;-webkit-user-select:none;user-select:none}.van-tree-select__nav{--sidebar-padding:12px 8px 12px 12px;background-color:var(--tree-select-nav-background-color,#f7f8fa);flex:1}.van-tree-select__nav__inner{height:100%;width:100%!important}.van-tree-select__content{background-color:var(--tree-select-content-background-color,#fff);flex:2}.van-tree-select__item{font-weight:700;line-height:var(--tree-select-item-height,44px);padding:0 32px 0 var(--padding-md,16px);position:relative}.van-tree-select__item--active{color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;right:var(--padding-md,16px);top:50%;transform:translateY(-50%)}
================================================
FILE: lib/uploader/index.d.ts
================================================
export {};
================================================
FILE: lib/uploader/index.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var component_1 = require("../common/component");
var validator_1 = require("../common/validator");
var shared_1 = require("./shared");
var utils_1 = require("./utils");
(0, component_1.VantComponent)({
props: __assign(__assign(__assign(__assign({ disabled: Boolean, multiple: Boolean, uploadText: String, useBeforeRead: Boolean, afterRead: null, beforeRead: null, previewSize: {
type: null,
value: 80,
}, name: {
type: null,
value: '',
}, accept: {
type: String,
value: 'image',
}, fileList: {
type: Array,
value: [],
observer: 'formatFileList',
}, maxSize: {
type: Number,
value: Number.MAX_VALUE,
}, maxCount: {
type: Number,
value: 100,
}, deletable: {
type: Boolean,
value: true,
}, showUpload: {
type: Boolean,
value: true,
}, previewImage: {
type: Boolean,
value: true,
}, previewFullImage: {
type: Boolean,
value: true,
}, videoFit: {
type: String,
value: 'contain',
}, imageFit: {
type: String,
value: 'scaleToFill',
}, uploadIcon: {
type: String,
value: 'photograph',
} }, shared_1.imageProps), shared_1.videoProps), shared_1.mediaProps), shared_1.messageFileProps),
data: {
lists: [],
isInCount: true,
},
methods: {
formatFileList: function () {
var _a = this.data, _b = _a.fileList, fileList = _b === void 0 ? [] : _b, maxCount = _a.maxCount;
var lists = fileList.map(function (item) { return (__assign(__assign({}, item), { isImage: (0, utils_1.isImageFile)(item), isVideo: (0, utils_1.isVideoFile)(item), deletable: (0, validator_1.isBoolean)(item.deletable) ? item.deletable : true })); });
this.setData({ lists: lists, isInCount: lists.length < maxCount });
},
getDetail: function (index) {
return {
name: this.data.name,
index: index == null ? this.data.fileList.length : index,
};
},
startUpload: function () {
var _this = this;
var _a = this.data, maxCount = _a.maxCount, multiple = _a.multiple, lists = _a.lists, disabled = _a.disabled;
if (disabled)
return;
(0, utils_1.chooseFile)(__assign(__assign({}, this.data), { maxCount: maxCount - lists.length }))
.then(function (res) {
_this.onBeforeRead(multiple ? res : res[0]);
})
.catch(function (error) {
_this.$emit('error', error);
});
},
onBeforeRead: function (file) {
var _this = this;
var _a = this.data, beforeRead = _a.beforeRead, useBeforeRead = _a.useBeforeRead;
var res = true;
if (typeof beforeRead === 'function') {
res = beforeRead(file, this.getDetail());
}
if (useBeforeRead) {
res = new Promise(function (resolve, reject) {
_this.$emit('before-read', __assign(__assign({ file: file }, _this.getDetail()), { callback: function (ok) {
ok ? resolve() : reject();
} }));
});
}
if (!res) {
return;
}
if ((0, validator_1.isPromise)(res)) {
res.then(function (data) { return _this.onAfterRead(data || file); });
}
else {
this.onAfterRead(file);
}
},
onAfterRead: function (file) {
var _a = this.data, maxSize = _a.maxSize, afterRead = _a.afterRead;
var oversize = Array.isArray(file)
? file.some(function (item) { return item.size > maxSize; })
: file.size > maxSize;
if (oversize) {
this.$emit('oversize', __assign({ file: file }, this.getDetail()));
return;
}
if (typeof afterRead === 'function') {
afterRead(file, this.getDetail());
}
this.$emit('after-read', __assign({ file: file }, this.getDetail()));
},
deleteItem: function (event) {
var index = event.currentTarget.dataset.index;
this.$emit('delete', __assign(__assign({}, this.getDetail(index)), { file: this.data.fileList[index] }));
},
onPreviewImage: function (event) {
if (!this.data.previewFullImage)
return;
var index = event.currentTarget.dataset.index;
var _a = this.data, lists = _a.lists, showmenu = _a.showmenu;
var item = lists[index];
wx.previewImage({
urls: lists.filter(function (item) { return (0, utils_1.isImageFile)(item); }).map(function (item) { return item.url; }),
current: item.url,
showmenu: showmenu,
fail: function () {
wx.showToast({ title: '预览图片失败', icon: 'none' });
},
});
},
onPreviewVideo: function (event) {
if (!this.data.previewFullImage)
return;
var index = event.currentTarget.dataset.index;
var lists = this.data.lists;
var sources = [];
var current = lists.reduce(function (sum, cur, curIndex) {
if (!(0, utils_1.isVideoFile)(cur)) {
return sum;
}
sources.push(__assign(__assign({}, cur), { type: 'video' }));
if (curIndex < index) {
sum++;
}
return sum;
}, 0);
wx.previewMedia({
sources: sources,
current: current,
fail: function () {
wx.showToast({ title: '预览视频失败', icon: 'none' });
},
});
},
onPreviewFile: function (event) {
if (!this.data.previewFile)
return;
var index = event.currentTarget.dataset.index;
wx.openDocument({
filePath: this.data.lists[index].url,
showMenu: true,
});
},
onClickPreview: function (event) {
var index = event.currentTarget.dataset.index;
var item = this.data.lists[index];
this.$emit('click-preview', __assign(__assign({}, item), this.getDetail(index)));
},
},
});
================================================
FILE: lib/uploader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: lib/uploader/index.wxml
================================================
{{ item.name || item.url }}
{{ item.message }}
{{ uploadText }}
================================================
FILE: lib/uploader/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function sizeStyle(data) {
return "Array" === data.previewSize.constructor ? style({
width: addUnit(data.previewSize[0]),
height: addUnit(data.previewSize[1]),
}) : style({
width: addUnit(data.previewSize),
height: addUnit(data.previewSize),
});
}
module.exports = {
sizeStyle: sizeStyle,
};
================================================
FILE: lib/uploader/index.wxss
================================================
@import '../common/index.wxss';.van-uploader{display:inline-block;position:relative}.van-uploader__wrapper{display:flex;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{align-items:center;background-color:var(--uploader-upload-background-color,#f7f8fa);box-sizing:border-box;display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;margin:0 8px 8px 0;position:relative;width:var(--uploader-size,80px)}.van-uploader__upload:active{background-color:var(--uploader-upload-active-color,#f2f3f5)}.van-uploader__upload-icon{color:var(--uploader-icon-color,#dcdee0);font-size:var(--uploader-icon-size,24px)}.van-uploader__upload-text{color:var(--uploader-text-color,#969799);font-size:var(--uploader-text-font-size,12px);margin-top:var(--padding-xs,8px)}.van-uploader__upload--disabled{opacity:var(--uploader-disabled-opacity,.5)}.van-uploader__preview{cursor:pointer;margin:0 8px 8px 0;position:relative}.van-uploader__preview-image{display:block;height:var(--uploader-size,80px);overflow:hidden;width:var(--uploader-size,80px)}.van-uploader__preview-delete,.van-uploader__preview-delete:after{height:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;width:var(--uploader-delete-icon-size,14px)}.van-uploader__preview-delete:after{background-color:var(--uploader-delete-background-color,rgba(0,0,0,.7));border-radius:0 0 0 12px;content:""}.van-uploader__preview-delete-icon{color:var(--uploader-delete-color,#fff);font-size:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;transform:scale(.7) translate(10%,-10%);z-index:1}.van-uploader__file{align-items:center;background-color:var(--uploader-file-background-color,#f7f8fa);display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;width:var(--uploader-size,80px)}.van-uploader__file-icon{color:var(--uploader-file-icon-color,#646566);font-size:var(--uploader-file-icon-size,20px)}.van-uploader__file-name{box-sizing:border-box;color:var(--uploader-file-name-text-color,#646566);font-size:var(--uploader-file-name-font-size,12px);margin-top:var(--uploader-file-name-margin-top,8px);padding:var(--uploader-file-name-padding,0 4px);text-align:center;width:100%}.van-uploader__mask{align-items:center;background-color:var(--uploader-mask-background-color,rgba(50,50,51,.88));bottom:0;color:#fff;display:flex;flex-direction:column;justify-content:center;left:0;position:absolute;right:0;top:0}.van-uploader__mask-icon{font-size:var(--uploader-mask-icon-size,22px)}.van-uploader__mask-message{font-size:var(--uploader-mask-message-font-size,12px);line-height:var(--uploader-mask-message-line-height,14px);margin-top:6px;padding:0 var(--padding-base,4px)}.van-uploader__loading{color:var(--uploader-loading-icon-color,#fff)!important;height:var(--uploader-loading-icon-size,22px);width:var(--uploader-loading-icon-size,22px)}
================================================
FILE: lib/uploader/shared.d.ts
================================================
export declare const imageProps: {
sizeType: {
type: ArrayConstructor;
value: string[];
};
capture: {
type: ArrayConstructor;
value: string[];
};
showmenu: {
type: BooleanConstructor;
value: boolean;
};
};
export declare const videoProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
compressed: {
type: BooleanConstructor;
value: boolean;
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
referrerPolicy: {
type: StringConstructor;
value: string;
};
};
export declare const mediaProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
mediaType: {
type: ArrayConstructor;
value: string[];
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
};
export declare const messageFileProps: {
extension: null;
previewFile: {
type: BooleanConstructor;
value: boolean;
};
};
================================================
FILE: lib/uploader/shared.js
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.messageFileProps = exports.mediaProps = exports.videoProps = exports.imageProps = void 0;
// props for image
exports.imageProps = {
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
capture: {
type: Array,
value: ['album', 'camera'],
},
showmenu: {
type: Boolean,
value: true,
},
};
// props for video
exports.videoProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
referrerPolicy: {
type: String,
value: 'no-referrer',
},
};
// props for media
exports.mediaProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
mediaType: {
type: Array,
value: ['image', 'video', 'mix'],
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
};
// props for file
exports.messageFileProps = {
extension: null,
previewFile: {
type: Boolean,
value: true,
},
};
================================================
FILE: lib/uploader/utils.d.ts
================================================
export interface File {
url: string;
size?: number;
name?: string;
type: string;
duration?: number;
time?: number;
isImage?: boolean;
isVideo?: boolean;
}
export declare function isImageFile(item: File): boolean;
export declare function isVideoFile(item: File): boolean;
export declare function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, mediaType, extension, }: {
accept: any;
multiple: any;
capture: any;
compressed: any;
maxDuration: any;
sizeType: any;
camera: any;
maxCount: any;
mediaType: any;
extension: any;
}): Promise;
================================================
FILE: lib/uploader/utils.js
================================================
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.chooseFile = exports.isVideoFile = exports.isImageFile = void 0;
var utils_1 = require("../common/utils");
var validator_1 = require("../common/validator");
function isImageFile(item) {
if (item.isImage != null) {
return item.isImage;
}
if (item.type) {
return item.type === 'image';
}
if (item.url) {
return (0, validator_1.isImageUrl)(item.url);
}
return false;
}
exports.isImageFile = isImageFile;
function isVideoFile(item) {
if (item.isVideo != null) {
return item.isVideo;
}
if (item.type) {
return item.type === 'video';
}
if (item.url) {
return (0, validator_1.isVideoUrl)(item.url);
}
return false;
}
exports.isVideoFile = isVideoFile;
function formatImage(res) {
return res.tempFiles.map(function (item) { return (__assign(__assign({}, (0, utils_1.pickExclude)(item, ['path'])), { type: 'image', url: item.tempFilePath || item.path, thumb: item.tempFilePath || item.path })); });
}
function formatVideo(res) {
return [
__assign(__assign({}, (0, utils_1.pickExclude)(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg'])), { type: 'video', url: res.tempFilePath, thumb: res.thumbTempFilePath }),
];
}
function formatMedia(res) {
return res.tempFiles.map(function (item) { return (__assign(__assign({}, (0, utils_1.pickExclude)(item, ['fileType', 'thumbTempFilePath', 'tempFilePath'])), { type: item.fileType, url: item.tempFilePath, thumb: item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath })); });
}
function formatFile(res) {
return res.tempFiles.map(function (item) { return (__assign(__assign({}, (0, utils_1.pickExclude)(item, ['path'])), { url: item.path })); });
}
function chooseFile(_a) {
var accept = _a.accept, multiple = _a.multiple, capture = _a.capture, compressed = _a.compressed, maxDuration = _a.maxDuration, sizeType = _a.sizeType, camera = _a.camera, maxCount = _a.maxCount, mediaType = _a.mediaType, extension = _a.extension;
return new Promise(function (resolve, reject) {
switch (accept) {
case 'image':
if (utils_1.isPC || utils_1.isWxWork) {
wx.chooseImage({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
sizeType: sizeType,
success: function (res) { return resolve(formatImage(res)); },
fail: reject,
});
}
else {
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType: ['image'],
sourceType: capture,
maxDuration: maxDuration,
sizeType: sizeType,
camera: camera,
success: function (res) { return resolve(formatImage(res)); },
fail: reject,
});
}
break;
case 'media':
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType: mediaType,
sourceType: capture,
maxDuration: maxDuration,
sizeType: sizeType,
camera: camera,
success: function (res) { return resolve(formatMedia(res)); },
fail: reject,
});
break;
case 'video':
wx.chooseVideo({
sourceType: capture,
compressed: compressed,
maxDuration: maxDuration,
camera: camera,
success: function (res) { return resolve(formatVideo(res)); },
fail: reject,
});
break;
default:
wx.chooseMessageFile(__assign(__assign({ count: multiple ? maxCount : 1, type: accept }, (extension ? { extension: extension } : {})), { success: function (res) { return resolve(formatFile(res)); }, fail: reject }));
break;
}
});
}
exports.chooseFile = chooseFile;
================================================
FILE: lib/wxs/add-unit.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
function addUnit(value) {
if (value == null) {
return undefined;
}
return REGEXP.test('' + value) ? value + 'px' : value;
}
module.exports = addUnit;
================================================
FILE: lib/wxs/array.wxs
================================================
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
================================================
FILE: lib/wxs/bem.wxs
================================================
/* eslint-disable */
var array = require('./array.wxs');
var object = require('./object.wxs');
var PREFIX = 'van-';
function join(name, mods) {
name = PREFIX + name;
mods = mods.map(function(mod) {
return name + '--' + mod;
});
mods.unshift(name);
return mods.join(' ');
}
function traversing(mods, conf) {
if (!conf) {
return;
}
if (typeof conf === 'string' || typeof conf === 'number') {
mods.push(conf);
} else if (array.isArray(conf)) {
conf.forEach(function(item) {
traversing(mods, item);
});
} else if (typeof conf === 'object') {
object.keys(conf).forEach(function(key) {
conf[key] && mods.push(key);
});
}
}
function bem(name, conf) {
var mods = [];
traversing(mods, conf);
return join(name, mods);
}
module.exports = bem;
================================================
FILE: lib/wxs/memoize.wxs
================================================
/**
* Simple memoize
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
*/
/* eslint-disable */
function isPrimitive(value) {
var type = typeof value;
return (
type === 'boolean' ||
type === 'number' ||
type === 'string' ||
type === 'undefined' ||
value === null
);
}
// mock simple fn.call in wxs
function call(fn, args) {
if (args.length === 2) {
return fn(args[0], args[1]);
}
if (args.length === 1) {
return fn(args[0]);
}
return fn();
}
function serializer(args) {
if (args.length === 1 && isPrimitive(args[0])) {
return args[0];
}
var obj = {};
for (var i = 0; i < args.length; i++) {
obj['key' + i] = args[i];
}
return JSON.stringify(obj);
}
function memoize(fn) {
var cache = {};
return function() {
var key = serializer(arguments);
if (cache[key] === undefined) {
cache[key] = call(fn, arguments);
}
return cache[key];
};
}
module.exports = memoize;
================================================
FILE: lib/wxs/object.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('{|}|"', 'g');
function keys(obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[0];
});
}
module.exports.keys = keys;
================================================
FILE: lib/wxs/style.wxs
================================================
/* eslint-disable */
var object = require('./object.wxs');
var array = require('./array.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
return newWord;
}
function style(styles) {
if (array.isArray(styles)) {
return styles
.filter(function (item) {
return item != null && item !== '';
})
.map(function (item) {
return style(item);
})
.join(';');
}
if ('Object' === styles.constructor) {
return object
.keys(styles)
.filter(function (key) {
return styles[key] != null && styles[key] !== '';
})
.map(function (key) {
return [kebabCase(key), [styles[key]]].join(':');
})
.join(';');
}
return styles;
}
module.exports = style;
================================================
FILE: lib/wxs/utils.wxs
================================================
/* eslint-disable */
var bem = require('./bem.wxs');
var memoize = require('./memoize.wxs');
var addUnit = require('./add-unit.wxs');
module.exports = {
bem: memoize(bem),
memoize: memoize,
addUnit: addUnit
};
================================================
FILE: package.json
================================================
{
"name": "@vant/weapp",
"version": "1.11.7",
"author": "vant-ui",
"license": "MIT",
"miniprogram": "lib",
"description": "轻量、可靠的小程序 UI 组件库",
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"dev": "node build/dev.mjs",
"lint": "eslint ./packages --ext .js,.ts --fix && stylelint \"packages/**/*.less\" --fix",
"prepare": "husky install",
"release": "sh build/release.sh",
"release:site": "vant-cli build-site && gh-pages -d site-dist --add",
"build:lib": "yarn && npx gulp -f build/compiler.js --series buildEs buildLib",
"upload:weapp": "node build/upload.js",
"test": "jest",
"test:watch": "jest --watch"
},
"files": [
"dist",
"lib"
],
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/youzan/vant-weapp.git"
},
"lint-staged": {
"*.{ts,js}": [
"eslint --fix",
"prettier --write"
],
"*.{css,less}": [
"stylelint --fix",
"prettier --write"
]
},
"homepage": "https://github.com/youzan/vant-weapp#readme",
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@types/jest": "^27.0.2",
"@vant/cli": "^7.0.3",
"@vant/icons": "^3.0.1",
"@vant/stylelint-config": "^1.4.2",
"gulp": "^4.0.2",
"gulp-insert": "^0.5.0",
"gulp-less": "^5.0.0",
"gulp-postcss": "^9.0.1",
"gulp-rename": "^2.0.0",
"gulp-typescript": "^6.0.0-alpha.1",
"jest": "^27.3.1",
"lint-staged": "^13.0.3",
"merge2": "^1.4.1",
"miniprogram-api-typings": "^3.1.6",
"miniprogram-ci": "^1.6.1",
"miniprogram-simulate": "^1.4.2",
"stylelint": "13.13.1",
"ts-jest": "^27.0.7",
"tscpaths": "^0.0.9",
"typescript": "^4.4.4",
"vue": "^3.2.30"
},
"browserslist": [
"Chrome >= 53",
"ChromeAndroid >= 53",
"iOS >= 9"
],
"resolutions": {
"source-map": "0.7.4"
}
}
================================================
FILE: packages/action-sheet/README.md
================================================
# ActionSheet 动作面板
### 介绍
底部弹起的模态面板,包含与当前情境相关的多个选项。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-action-sheet": "@vant/weapp/action-sheet/index"
}
```
## 代码演示
### 基础用法
需要传入一个`actions`的数组,数组的每一项是一个对象,对象属性见文档下方表格。
```html
```
```javascript
Page({
data: {
show: false,
actions: [
{
name: '选项',
},
{
name: '选项',
},
{
name: '选项',
subname: '描述信息',
openType: 'share',
},
],
},
onClose() {
this.setData({ show: false });
},
onSelect(event) {
console.log(event.detail);
},
});
```
### 展示取消按钮
设置`cancel-text`属性后,会在底部展示取消按钮,点击后关闭当前菜单。
```html
```
### 展示描述信息
设置`description`属性后,会在选项上方显示描述信息。
```html
```
### 选项状态
选项可以设置为加载状态或禁用状态。
```html
```
```javascript
Page({
data: {
show: false,
actions: [
{ name: '着色选项', color: '#ee0a24' },
{ loading: true },
{ name: '禁用选项', disabled: true },
],
},
});
```
### 自定义面板
通过设置`title`属性展示标题栏,同时可以使用插槽自定义菜单内容。
```html
内容
```
### 微信开放能力
需要传入一个`actions`的数组,数组的每一项是一个对象,对象属性见文档下方表格。
```html
```
```javascript
Page({
data: {
show: false,
actions: [
{ name: '获取用户信息', color: '#07c160', openType: 'getUserInfo' },
],
},
onClose() {
this.setData({ show: false });
},
onGetUserInfo(e) {
console.log(e.detail);
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否显示动作面板 | _boolean_ | - |
| actions | 菜单选项 | _Array_ | `[]` |
| title | 标题 | _string_ | - |
| description `v1.0.0` | 选项上方的描述信息 | _string_ | - |
| z-index | z-index 层级 | _number_ | `100` |
| cancel-text | 取消按钮文字 | _string_ | - |
| overlay | 是否显示遮罩层 | _boolean_ | - |
| round `v1.0.0` | 是否显示圆角 | _boolean_ | `true` |
| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `true` |
| close-on-click-overlay | 点击遮罩是否关闭菜单 | _boolean_ | `true` |
| safe-area-inset-bottom | 是否为 iPhoneX 留出底部安全距离 | _boolean_ | `true` |
| root-portal `v1.11.3` | 是否从页面子树中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| bind:select | 选中选项时触发,禁用或加载状态下不会触发 | event.detail: 选项对应的对象 |
| bind:close | 关闭时触发 | - |
| bind:cancel | 取消按钮点击时触发 | - |
| bind:click-overlay | 点击遮罩层时触发 | - |
| bind:getuserinfo | 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效 | - |
| bind:contact | 客服消息回调,openType="contact"时有效 | - |
| bind:getphonenumber | 获取用户手机号回调,openType="getPhoneNumber"时有效 | - |
| bind:getrealtimephonenumber `v1.10.21` | 获取手机号实时验证回调,openType="getRealtimePhoneNumber"时有效 | - |
| bind:agreeprivacyauthorization `v1.10.24` | 同意隐私协议回调,openType="agreePrivacyAuthorization"时有效 | - |
| bind:error | 当使用开放能力时,发生错误的回调,openType="launchApp"时有效 | - |
| bind:launchapp | 打开 APP 成功的回调,openType="launchApp"时有效 | - |
| bind:opensetting | 在打开授权设置页后回调,openType="openSetting"时有效 | - |
### actions
`API`中的`actions`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`:
| 键名 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 标题 | _string_ | - |
| subname | 二级标题 | _string_ | - |
| color | 选项文字颜色 | _string_ | - |
| loading | 是否为加载状态 | _boolean_ | - |
| disabled | 是否为禁用状态 | _boolean_ | - |
| className | 为对应列添加额外的 class 类名 | _string_ | - |
| openType | 微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 | _string_ | `en` |
| sessionFrom | 会话来源,openType="contact"时有效 | _string_ | - |
| sendMessageTitle | 会话内消息卡片标题,openType="contact"时有效 | _string_ | 当前标题 |
| sendMessagePath | 会话内消息卡片点击跳转小程序路径,openType="contact"时有效 | _string_ | 当前分享路径 |
| sendMessageImg | 会话内消息卡片图片,openType="contact"时有效 | _string_ | 截图 |
| showMessageCard | 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 | _string_ | `false` |
| appParameter | 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效 | _string_ | - |
### 外部样式类
| 类名 | 说明 |
| ---------------------- | ------------------- |
| custom-class `v1.10.7` | 根节点样式类 |
| list-class `v1.10.7` | `actions`容器样式类 |
================================================
FILE: packages/action-sheet/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"van-action-sheet": "../../action-sheet/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/action-sheet/demo/index.less
================================================
.content {
padding: 20px;
}
================================================
FILE: packages/action-sheet/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show1: false,
show2: false,
show3: false,
show4: false,
show5: false,
show6: false,
action1: [
{ name: '选项' },
{ name: '选项' },
{ name: '选项', subname: '描述信息' },
],
action2: [
{ name: '着色选项', color: '#ee0a24' },
{ loading: true },
{ name: '禁用选项', disabled: true },
],
action6: [
{ name: '获取用户信息', color: '#07c160', openType: 'getUserInfo' },
],
},
methods: {
toggle(type) {
this.setData({
[type]: !this.data[type],
});
},
toggleActionSheet1() {
this.toggle('show1');
},
toggleActionSheet2() {
this.toggle('show2');
},
toggleActionSheet3() {
this.toggle('show3');
},
toggleActionSheet4() {
this.toggle('show4');
},
toggleActionSheet5() {
this.toggle('show5');
},
toggleActionSheet6() {
this.toggle('show6');
},
onGetUserInfo(e) {
console.log(e.detail);
},
},
});
================================================
FILE: packages/action-sheet/demo/index.wxml
================================================
弹出菜单
弹出菜单
弹出菜单
弹出菜单
弹出菜单
内容
弹出菜单
================================================
FILE: packages/action-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: packages/action-sheet/index.less
================================================
@import '../common/style/var.less';
.van-action-sheet {
max-height: var(
--action-sheet-max-height,
@action-sheet-max-height
) !important;
color: var(--action-sheet-item-text-color, @action-sheet-item-text-color);
&__item,
&__cancel {
padding: 14px @padding-md;
text-align: center;
font-size: var(--action-sheet-item-font-size, @action-sheet-item-font-size);
line-height: var(
--action-sheet-item-line-height,
@action-sheet-item-line-height
);
background-color: var(
--action-sheet-item-background,
@action-sheet-item-background
);
&--hover {
background-color: @active-color;
}
// reset weapp default border
&::after {
border-width: 0;
}
}
&__cancel {
color: var(
--action-sheet-cancel-text-color,
@action-sheet-cancel-text-color
);
}
&__gap {
display: block;
height: var(
--action-sheet-cancel-padding-top,
@action-sheet-cancel-padding-top
);
background-color: var(
--action-sheet-cancel-padding-color,
@action-sheet-cancel-padding-color
);
}
&__item--disabled {
color: var(
--action-sheet-item-disabled-text-color,
@action-sheet-item-disabled-text-color
);
}
&__item--disabled&__item--hover {
background-color: var(
--action-sheet-item-background,
@action-sheet-item-background
);
}
&__subname {
margin-top: var(--padding-xs, @padding-xs);
font-size: var(
--action-sheet-subname-font-size,
@action-sheet-subname-font-size
);
color: var(--action-sheet-subname-color, @action-sheet-subname-color);
line-height: var(
--action-sheet-subname-line-height,
@action-sheet-subname-line-height
);
}
&__header {
text-align: center;
font-weight: var(--font-weight-bold, @font-weight-bold);
font-size: var(
--action-sheet-header-font-size,
@action-sheet-header-font-size
);
line-height: var(--action-sheet-header-height, @action-sheet-header-height);
}
&__description {
text-align: center;
padding: 20px var(--padding-md, @padding-md);
color: var(
--action-sheet-description-color,
@action-sheet-description-color
);
font-size: var(
--action-sheet-description-font-size,
@action-sheet-description-font-size
);
line-height: var(
--action-sheet-description-line-height,
@action-sheet-description-line-height
);
}
&__close {
position: absolute !important;
top: 0;
right: 0;
line-height: inherit !important;
padding: var(
--action-sheet-close-icon-padding,
@action-sheet-close-icon-padding
);
font-size: var(
--action-sheet-close-icon-size,
@action-sheet-close-icon-size
) !important;
color: var(--action-sheet-close-icon-color, @action-sheet-close-icon-color);
}
&__loading {
display: flex !important;
}
}
================================================
FILE: packages/action-sheet/index.ts
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
classes: ['list-class'],
mixins: [button],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100,
},
actions: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onSelect(event: WechatMiniprogram.TouchEvent) {
const { index } = event.currentTarget.dataset;
const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
const item = actions[index];
if (item) {
this.$emit('select', item);
if (closeOnClickAction) {
this.onClose();
}
if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: item.getUserProfileDesc || ' ',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
});
================================================
FILE: packages/action-sheet/index.wxml
================================================
{{ description }}
{{ cancelText }}
================================================
FILE: packages/action-sheet/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
弹出菜单
选项状态
弹出菜单
展示取消按钮
弹出菜单
展示描述信息
弹出菜单
展示标题栏
弹出菜单
微信开放能力
弹出菜单
`;
================================================
FILE: packages/action-sheet/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/area/README.md
================================================
# Area 省市区选择
### 介绍
省市区选择组件通常与 [弹出层](#/popup) 组件配合使用。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-area": "@vant/weapp/area/index"
}
```
## 代码演示
### 基础用法
初始化省市区组件时,需要通过 `area-list` 属性传入省市区数据。
```html
```
### areaList 格式
areaList 为对象结构,包含 `province_list`、`city_list`、`county_list` 三个 key。
每项以地区码作为 key,省市区名字作为 value。地区码为 6 位数字,前两位代表省份,中间两位代表城市,后两位代表区县,以 0 补足 6 位。比如北京的地区码为 `11`,以 0 补足 6 位,为 `110000`。
示例数据如下:
```js
const areaList = {
province_list: {
110000: '北京市',
120000: '天津市',
},
city_list: {
110100: '北京市',
120100: '天津市',
},
county_list: {
110101: '东城区',
110102: '西城区',
// ....
},
};
```
### @vant/area-data
Vant 官方提供了一份默认的省市区数据,可以通过 [@vant/area-data](https://github.com/vant-ui/vant/tree/dev/packages/vant-area-data) 引入。
```bash
yarn add @vant/area-data
```
```ts
import { areaList } from '@vant/area-data';
Page({
data: {
areaList,
},
});
```
### 选中省市区
如果想选中某个省市区,需要传入一个`value`属性,绑定对应的省市区`code`。
```html
```
### 配置显示列
可以通过`columns-num`属性配置省市区显示的列数,默认情况下会显示省市区,当你设置为`2`,则只会显示省市选择。
```html
```
### 配置列占位提示文字
可以通过`columns-placeholder`属性配置每一列的占位提示文字。
```html
```
## 云开发示例
### 使用云开发获取省市区数据
实际项目中,可以通过[小程序云开发](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)的能力,将省市区数据保存在云开发的数据库中,并在小程序中使用云开发的接口异步获取数据。
在小程序中使用云能力之前需要先调用`wx.could.init`方法完成云能力的初始化。
```js
const db = wx.cloud.database();
db.collection('region')
.limit(1)
.get()
.then((res) => {
if (res.data && res.data.length > 0) {
this.setData({
areaList: res.data[0],
});
}
})
.catch((err) => {
console.log(err);
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前选中的省市区`code` | _string_ | - |
| title | 顶部栏标题 | _string_ | - |
| area-list | 省市区数据,格式见下方 | _object_ | - |
| columns-num | 省市区显示列数,3-省市区,2-省市,1-省 | _number_ | `3` |
| columns-placeholder | 列占位提示文字 | _string[]_ | `[]` |
| loading | 是否显示加载状态 | _boolean_ | `false` |
| item-height | 选项高度 | _number_ | `44` |
| visible-item-count | 可见的选项个数 | _number_ | `6` |
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |
| show-toolbar `1.10.3` | 是否显示顶部栏 | _boolean_ | `true` |
### Events
| 事件 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:confirm | 点击右上方完成按钮 | 一个数组参数,具体格式看下方数据格式章节 |
| bind:cancel | 点击取消按钮时 | - |
| bind:change | 选项改变时触发 | Picker 实例,所有列选中值,当前列对应的索引 |
### 方法
通过 selectComponent 可以获取到 Area 实例并调用实例方法。
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| reset | code: string | - | 根据 code 重置所有选项,若不传 code,则重置到第一项 |
### 点击完成时返回的数据格式
返回的数据整体为一个 Object,包含 `values`, `index` 两个 key。
`values` 整体为一个数组,数组内包含 `columnsNum` 个数据, 每个数据对应一列选项中被选中的数据。
`code` 代表被选中的地区编码, `name` 代表被选中的地区名称。
```javascript
[
{
code: '110000',
name: '北京市',
},
{
code: '110100',
name: '北京市',
},
{
code: '110101',
name: '东城区',
},
];
```
`index` 为一个数组,数组内包含 `columnsNum` 个数据, 每个数据对应一列选项中被选中项的序号。
================================================
FILE: packages/area/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-area": "../../area/index",
"van-toast": "../../toast/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/area/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
const db = wx.cloud?.database();
VantComponent({
data: {
areaList: {},
loading: true,
value: 330302,
},
mounted() {
db?.collection('region')
.limit(1)
.get()
.then((res) => {
if (res.data && res.data.length > 0) {
this.setData({
loading: false,
areaList: res.data[0],
});
}
})
.catch((err) => {
console.log(err);
this.setData({
loading: false,
});
});
},
methods: {
onChange(event) {
const { values } = event.detail;
Toast({
context: this,
message: values.map((item) => item.name).join('-'),
});
},
onConfirm(event) {
console.log(event);
},
onCancel(event) {
console.log(event);
},
},
});
================================================
FILE: packages/area/demo/index.wxml
================================================
================================================
FILE: packages/area/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: packages/area/index.less
================================================
// empty
================================================
FILE: packages/area/index.ts
================================================
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
import { requestAnimationFrame } from '../common/utils';
type AreaItem = {
name: string;
code: string;
};
const EMPTY_CODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
...pickerProps,
showToolbar: {
type: Boolean,
value: true,
},
value: {
type: String,
observer(value: string) {
this.code = value;
this.setValues();
},
},
areaList: {
type: Object,
value: {},
observer: 'setValues',
},
columnsNum: {
type: null,
value: 3,
},
columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
},
});
},
},
},
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {},
},
mounted() {
requestAnimationFrame(() => {
this.setValues();
});
},
methods: {
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel(event: WechatMiniprogram.CustomEvent) {
this.emit('cancel', event.detail);
},
onConfirm(event: WechatMiniprogram.CustomEvent) {
const { index } = event.detail;
let { value } = event.detail;
value = this.parseValues(value);
this.emit('confirm', { value, index });
},
emit(type: string, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
parseValues(values: AreaItem[]) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
if (
value &&
(!value.code || value.name === columnsPlaceholder[index])
) {
return {
...value,
code: '',
name: '',
};
}
return value;
});
},
onChange(event: WechatMiniprogram.CustomEvent) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
this.setValues()?.then(() => {
this.$emit('change', {
picker,
values: this.parseValues(picker.getValues()),
index,
});
});
},
getConfig(type: string) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type: string, code?: string): AreaItem[] {
if (type !== 'province' && !code) {
return [];
}
const { typeToColumnsPlaceholder } = this.data;
const list: Record = this.getConfig(type);
let result = Object.keys(list).map((code) => ({
code,
name: list[code],
}));
if (code != null) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter(
(item) => item.code.indexOf(code as string) === 0
);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill =
type === 'province'
? ''
: type === 'city'
? EMPTY_CODE.slice(2, 4)
: EMPTY_CODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type],
});
}
return result;
},
getIndex(type: string, code: string) {
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
const list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (let i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues() {
const picker = this.getPicker();
if (!picker) {
return;
}
let code = this.code || this.getDefaultCode();
const provinceList = this.getList('province');
const cityList = this.getList('city', code.slice(0, 2));
const stack: Promise[] = [];
const indexes: number[] = [];
const { columnsNum } = this.data;
if (columnsNum >= 1) {
stack.push(picker.setColumnValues(0, provinceList, false));
indexes.push(this.getIndex('province', code));
}
if (columnsNum >= 2) {
stack.push(picker.setColumnValues(1, cityList, false));
indexes.push(this.getIndex('city', code));
if (cityList.length && code.slice(2, 4) === '00') {
[{ code }] = cityList;
}
}
if (columnsNum === 3) {
stack.push(
picker.setColumnValues(
2,
this.getList('county', code.slice(0, 4)),
false
)
);
indexes.push(this.getIndex('county', code));
}
return Promise.all(stack)
.catch(() => {})
.then(() => picker.setIndexes(indexes))
.catch(() => {});
},
getDefaultCode() {
const { columnsPlaceholder } = this.data;
if (columnsPlaceholder.length) {
return EMPTY_CODE;
}
const countyCodes = Object.keys(this.getConfig('county'));
if (countyCodes[0]) {
return countyCodes[0];
}
const cityCodes = Object.keys(this.getConfig('city'));
if (cityCodes[0]) {
return cityCodes[0];
}
return '';
},
getValues() {
const picker = this.getPicker();
if (!picker) {
return [];
}
return this.parseValues(picker.getValues().filter((value) => !!value));
},
getDetail() {
const values = this.getValues();
const area = {
code: '',
country: '',
province: '',
city: '',
county: '',
};
if (!values.length) {
return area;
}
const names = values.map((item: AreaItem) => item.name);
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
} else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset(code) {
this.code = code || '';
return this.setValues();
},
},
});
================================================
FILE: packages/area/index.wxml
================================================
================================================
FILE: packages/area/index.wxs
================================================
/* eslint-disable */
function displayColumns(columns, columnsNum) {
return columns.slice(0, +columnsNum);
}
module.exports = {
displayColumns: displayColumns,
};
================================================
FILE: packages/area/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
取消
确认
`;
================================================
FILE: packages/area/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/button/README.md
================================================
# Button 按钮
### 介绍
按钮用于触发一个操作,如提交表单。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
```
## 代码演示
### 按钮类型
支持`default`、`primary`、`info`、`warning`、`danger`五种类型,默认为`default`。
```html
默认按钮
主要按钮
信息按钮
警告按钮
危险按钮
```
### 朴素按钮
通过`plain`属性将按钮设置为朴素按钮,朴素按钮的文字为按钮颜色,背景为白色。
```html
朴素按钮
朴素按钮
```
### 细边框
设置`hairline`属性可以开启 0.5px 边框,基于伪类实现。
```html
细边框按钮
细边框按钮
```
### 禁用状态
通过`disabled`属性来禁用按钮,此时按钮的`bind:click`事件不会触发。
```html
禁用状态
禁用状态
```
### 加载状态
```html
```
### 按钮形状
```html
方形按钮
圆形按钮
```
### 图标按钮
通过`icon`属性设置按钮图标,支持 Icon 组件里的所有图标,也可以传入图标 URL。
```html
按钮
按钮
```
### 按钮尺寸
支持`large`、`normal`、`small`、`mini`四种尺寸,默认为`normal`。
```html
大号按钮
普通按钮
小型按钮
迷你按钮
```
### 块级元素
通过`block`属性可以将按钮的元素类型设置为块级元素。
```html
块级元素
```
### 自定义颜色
通过`color`属性可以自定义按钮的颜色。
```html
单色按钮
单色按钮
渐变色按钮
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| id | 标识符 | _string_ | - |
| button-id `v1.10.25` | 标识符,作为原生 button 组件的 id 值 | _string_ | - |
| type | 按钮类型,可选值为 `primary` `info` `warning` `danger` | _string_ | `default` |
| size | 按钮尺寸,可选值为 `normal` `large` `small` `mini` | _string_ | `normal` |
| color `v1.0.0` | 按钮颜色,支持传入`linear-gradient`渐变色 | _string_ | - |
| icon | 左侧图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| class-prefix | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/icon) | _string_ | `van-icon` |
| plain | 是否为朴素按钮 | _boolean_ | `false` |
| block | 是否为块级元素 | _boolean_ | `false` |
| round | 是否为圆形按钮 | _boolean_ | `false` |
| square | 是否为方形按钮 | _boolean_ | `false` |
| disabled | 是否禁用按钮 | _boolean_ | `false` |
| hairline | 是否使用 0.5px 边框 | _boolean_ | `false` |
| loading | 是否显示为加载状态 | _boolean_ | `false` |
| loading-text | 加载状态提示文字 | _string_ | - |
| loading-type | 加载状态图标类型,可选值为 `spinner` | _string_ | `circular` |
| loading-size | 加载图标大小 | _string_ | `20px` |
| custom-style | 自定义样式 | _string_ | - |
| open-type | 微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
| app-parameter | 打开 APP 时,向 APP 传递的参数 | _string_ | - |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,
zh_TW 繁体中文,en 英文 | _string_ | `en` |
| session-from | 会话来源 | _string_ | - |
| business-id | 客服消息子商户 id | _number_ | - |
| send-message-title | 会话内消息卡片标题 | _string_ | 当前标题 |
| send-message-path | 会话内消息卡片点击跳转小程序路径 | _string_ | 当前分享路径 |
| send-message-img | sendMessageImg | _string_ | 截图 |
| show-message-card | 显示会话内消息卡片 | _string_ | `false` |
| dataset | 按钮 dataset,open-type 为 `share` 时,可在 onShareAppMessage 事件的 `event.target.dataset.detail` 中看到传入的值 | _any_ | - |
| form-type | 用于 form 组件,可选值为`submit` `reset`,点击分别会触发 form 组件的 submit/reset 事件 | _string_ | - |
### Events
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| bind:click | 点击按钮,且按钮状态不为加载或禁用时触发 | - |
| bind:getuserinfo | 用户点击该按钮时,会返回获取到的用户信息,
从返回参数的 detail 中获取到的值同 wx.getUserInfo | - |
| bind:contact | 客服消息回调 | - |
| bind:getphonenumber | 获取用户手机号回调 | - |
| bind:getrealtimephonenumber `v1.10.21` | 获取手机号实时验证回调,open-type=getRealtimePhoneNumber 时有效 | - |
| bind:agreeprivacyauthorization `v1.10.24` | 同意隐私协议回调,openType="agreePrivacyAuthorization"时有效 | - |
| bind:error | 当使用开放能力时,发生错误的回调 | - |
| bind:opensetting | 在打开授权设置页后回调 | - |
| bind:chooseavatar | 当 open-type 的值为 chooseAvatar 时,选择头像之后的回调 |
> Button 提供的是 click 事件而不是原生 tap 事件,按钮禁用时,click 事件不会触发,tap 事件依然会触发。
### 外部样式类
| 类名 | 说明 |
| ------------- | ---------------------- |
| custom-class | 根节点样式类 |
| hover-class | 指定按钮按下去的样式类 |
| loading-class | 加载图标样式类 |
================================================
FILE: packages/button/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/button/demo/index.less
================================================
.row {
height: 44px;
margin-bottom: 15px;
}
.demo-margin-left {
margin-left: 10px;
}
.demo-margin-right {
margin-right: 10px;
}
.demo-margin-bottom {
display: block;
margin-bottom: 15px;
}
================================================
FILE: packages/button/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/button/demo/index.wxml
================================================
默认按钮
主要按钮
信息按钮
危险按钮
警告按钮
朴素按钮
朴素按钮
细边框按钮
细边框按钮
禁用状态
禁用状态
方形按钮
圆形按钮
按钮
按钮
大号按钮
普通按钮
小型按钮
迷你按钮
普通按钮
块级元素
单色按钮
单色按钮
渐变色按钮
================================================
FILE: packages/button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: packages/button/index.less
================================================
@import '../common/style/var.less';
.van-button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0;
text-align: center;
vertical-align: middle;
-webkit-appearance: none;
-webkit-text-size-adjust: 100%;
height: var(--button-default-height, @button-default-height);
line-height: var(--button-line-height, @button-line-height);
font-size: var(--button-default-font-size, @button-default-font-size);
transition: opacity @animation-duration-fast;
border-radius: var(--button-border-radius, @button-border-radius);
&::before {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
border: inherit;
border-radius: inherit; /* inherit parent's border radius */
transform: translate(-50%, -50%);
opacity: 0;
content: ' ';
background-color: @black;
border-color: @black;
}
// reset weapp default border
&::after {
border-width: 0;
}
&--active::before {
opacity: 0.15;
}
&--unclickable::after {
display: none;
}
&--default {
color: var(--button-default-color, @button-default-color);
background: var(
--button-default-background-color,
@button-default-background-color
);
border: var(--button-border-width, @button-border-width) solid
var(--button-default-border-color, @button-default-border-color);
}
&--primary {
color: var(--button-primary-color, @button-primary-color);
background: var(
--button-primary-background-color,
@button-primary-background-color
);
border: var(--button-border-width, @button-border-width) solid
var(--button-primary-border-color, @button-primary-border-color);
}
&--info {
color: var(--button-info-color, @button-info-color);
background: var(
--button-info-background-color,
@button-info-background-color
);
border: var(--button-border-width, @button-border-width) solid
var(--button-info-border-color, @button-info-border-color);
}
&--danger {
color: var(--button-danger-color, @button-danger-color);
background: var(
--button-danger-background-color,
@button-danger-background-color
);
border: var(--button-border-width, @button-border-width) solid
var(--button-danger-border-color, @button-danger-border-color);
}
&--warning {
color: var(--button-warning-color, @button-warning-color);
background: var(
--button-warning-background-color,
@button-warning-background-color
);
border: var(--button-border-width, @button-border-width) solid
var(--button-warning-border-color, @button-warning-border-color);
}
&--plain {
background: var(
--button-plain-background-color,
@button-plain-background-color
);
&.van-button--primary {
color: var(
--button-primary-background-color,
@button-primary-background-color
);
}
&.van-button--info {
color: var(--button-info-background-color, @button-info-background-color);
}
&.van-button--danger {
color: var(
--button-danger-background-color,
@button-danger-background-color
);
}
&.van-button--warning {
color: var(
--button-warning-background-color,
@button-warning-background-color
);
}
}
&--large {
width: 100%;
height: var(--button-large-height, @button-large-height);
}
&--normal {
padding: 0 15px;
font-size: var(--button-normal-font-size, @button-normal-font-size);
}
&--small {
min-width: var(--button-small-min-width, @button-small-min-width);
height: var(--button-small-height, @button-small-height);
padding: 0 var(--padding-xs, @padding-xs);
font-size: var(--button-small-font-size, @button-small-font-size);
}
// mini图标默认宽度50px,文字不能超过4个
&--mini {
display: inline-block;
min-width: var(--button-mini-min-width, @button-mini-min-width);
height: var(--button-mini-height, @button-mini-height);
font-size: var(--button-mini-font-size, @button-mini-font-size);
& + .van-button--mini {
margin-left: 5px;
}
}
&--block {
display: flex;
width: 100%;
}
&--round {
border-radius: var(
--button-round-border-radius,
@button-round-border-radius
);
}
&--square {
border-radius: 0;
}
&--disabled {
opacity: var(--button-disabled-opacity, @button-disabled-opacity);
}
&__text {
display: inline;
}
&__loading-text,
&__icon + &__text:not(:empty) {
margin-left: @padding-base;
}
&__icon {
min-width: 1em;
line-height: inherit !important;
vertical-align: top;
}
&--hairline {
padding-top: 1px; // add 1px padding for text vertical align middle
border-width: 0;
&::after {
border-color: inherit;
border-width: 1px;
border-radius: calc(
var(--button-border-radius, @button-border-radius) * 2
);
}
&.van-button--round::after {
border-radius: var(
--button-round-border-radius,
@button-round-border-radius
);
}
&.van-button--square::after {
border-radius: 0;
}
}
}
================================================
FILE: packages/button/index.ts
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { canIUseFormFieldButton } from '../common/version';
const mixins = [button];
if (canIUseFormFieldButton()) {
mixins.push('wx://form-field-button');
}
VantComponent({
mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick(event: WechatMiniprogram.TouchEvent) {
this.$emit('click', event);
const {
canIUseGetUserProfile,
openType,
getUserProfileDesc,
lang,
} = this.data;
if (openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: getUserProfileDesc || ' ',
lang: lang || 'en',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
},
},
});
================================================
FILE: packages/button/index.wxml
================================================
================================================
FILE: packages/button/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return data.customStyle;
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style([properties, data.customStyle]);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: packages/button/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
按钮类型
默认按钮
主要按钮
信息按钮
危险按钮
警告按钮
朴素按钮
朴素按钮
朴素按钮
细边框
细边框按钮
细边框按钮
禁用状态
禁用状态
禁用状态
加载状态
加载中...
按钮形状
方形按钮
圆形按钮
图标按钮
按钮
按钮
按钮尺寸
大号按钮
普通按钮
小型按钮
迷你按钮
块级元素
普通按钮
块级元素
自定义颜色
单色按钮
单色按钮
渐变色按钮
`;
================================================
FILE: packages/button/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/button/test/index.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
describe('button', () => {
const VanButton = simulate.load(
path.resolve(__dirname, '../../button/index'),
'van-button',
{
rootPath: path.resolve(__dirname, '../../'),
}
);
test('should emit click event', async () => {
const comp = simulate.render(
simulate.load({
usingComponents: {
'van-button': VanButton,
},
template: ``,
data: {
tapValue: 0,
},
methods: {
onClick() {
this.setData({
tapValue: this.data.tapValue + 1,
});
},
},
})
);
comp.attach(document.createElement('parent-wrapper'));
const wrapper = comp.querySelector('#wrapper');
const btn = wrapper?.querySelector('.van-button');
btn?.dispatchEvent('tap');
await simulate.sleep(10);
expect(comp.data.tapValue).toEqual(1);
});
test('should not emit click event when disabled', async () => {
const comp = simulate.render(
simulate.load({
usingComponents: {
'van-button': VanButton,
},
template: ``,
data: {
tapValue: 0,
},
methods: {
onClick() {
this.setData({
tapValue: this.data.tapValue + 1,
});
},
},
})
);
comp.attach(document.createElement('parent-wrapper'));
const wrapper = comp.querySelector('#wrapper');
const btn = wrapper?.querySelector('.van-button');
btn?.dispatchEvent('tap');
await simulate.sleep(10);
expect(comp.data.tapValue).toEqual(0);
});
});
================================================
FILE: packages/calendar/README.md
================================================
# Calendar 日历
### 介绍
日历组件用于选择日期或日期区间。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-calendar": "@vant/weapp/calendar/index"
}
```
## 代码演示
### 选择单个日期
下面演示了结合单元格来使用日历组件的用法,日期选择完成后会触发`confirm`事件。
```html
```
```js
Page({
data: {
date: '',
show: false,
},
onDisplay() {
this.setData({ show: true });
},
onClose() {
this.setData({ show: false });
},
formatDate(date) {
date = new Date(date);
return `${date.getMonth() + 1}/${date.getDate()}`;
},
onConfirm(event) {
this.setData({
show: false,
date: this.formatDate(event.detail),
});
},
});
```
### 选择多个日期
设置`type`为`multiple`后可以选择多个日期,此时`confirm`事件返回的 date 为数组结构,数组包含若干个选中的日期。
```html
```
```js
Page({
data: {
text: '',
show: false,
},
onDisplay() {
this.setData({ show: true });
},
onClose() {
this.setData({ show: false });
},
onConfirm(event) {
this.setData({
show: false,
text: `选择了 ${event.detail.length} 个日期`,
});
},
});
```
### 选择日期区间
设置`type`为`range`后可以选择日期区间,此时`confirm`事件返回的 date 为数组结构,数组第一项为开始时间,第二项为结束时间。
```html
```
```js
Page({
data: {
date: '',
show: false,
},
onDisplay() {
this.setData({ show: true });
},
onClose() {
this.setData({ show: false });
},
formatDate(date) {
date = new Date(date);
return `${date.getMonth() + 1}/${date.getDate()}`;
},
onConfirm(event) {
const [start, end] = event.detail;
this.setData({
show: false,
date: `${this.formatDate(start)} - ${this.formatDate(end)}`,
});
},
});
```
> Tips: 默认情况下,日期区间的起止时间不能为同一天,可以通过设置 allow-same-day 属性来允许选择同一天。
### 快捷选择
将`show-confirm`设置为`false`可以隐藏确认按钮,这种情况下选择完成后会立即触发`confirm`事件。
```html
```
### 自定义颜色
通过`color`属性可以自定义日历的颜色,对选中日期和底部按钮生效。
```html
```
### 自定义日期范围
通过`min-date`和`max-date`定义日历的范围,需要注意的是`min-date`和`max-date`的区间不宜过大,否则会造成严重的性能问题。
```html
```
```js
Page({
data: {
show: false,
minDate: new Date(2010, 0, 1).getTime(),
maxDate: new Date(2010, 0, 31).getTime(),
},
});
```
### 自定义按钮文字
通过`confirm-text`设置按钮文字,通过`confirm-disabled-text`设置按钮禁用时的文字。
```html
```
### 自定义日期文案
通过传入`formatter`函数来对日历上每一格的内容进行格式化
```html
```
```js
Page({
data: {
formatter(day) {
const month = day.date.getMonth() + 1;
const date = day.date.getDate();
if (month === 5) {
if (date === 1) {
day.topInfo = '劳动节';
} else if (date === 4) {
day.topInfo = '五四青年节';
} else if (date === 11) {
day.text = '今天';
}
}
if (day.type === 'start') {
day.bottomInfo = '入住';
} else if (day.type === 'end') {
day.bottomInfo = '离店';
}
return day;
},
},
});
```
### 自定义弹出位置
通过`position`属性自定义弹出层的弹出位置,可选值为`top`、`left`、`right`。
```html
```
### 日期区间最大范围
选择日期区间时,可以通过`max-range`属性来指定最多可选天数,选择的范围超过最多可选天数时,会弹出相应的提示文案。
```html
```
### 自定义周起始日
通过 `first-day-of-week` 属性设置一周从哪天开始。
```html
```
### 平铺展示
将`poppable`设置为`false`,日历会直接展示在页面内,而不是以弹层的形式出现。
```html
```
```css
.calendar {
--calendar-height: 618px;
}
```
> Tips: 注意,在自定义calendar的高度时,需要确保,滚动到当前月份时,所有的日期要展现在.van-calendar__body内,否则可能会出现滚动时头部月份与当前月份不同步的情况。目前平铺型预设高度618px,弹窗型高度90%。
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 选择类型:
`single`表示选择单个日期,
`multiple`表示选择多个日期,
`range`表示选择日期区间 | _string_ | `single` |
| title | 日历标题 | _string_ | `日期选择` |
| color | 主题色,对底部按钮和选中日期生效 | _string_ | `#ee0a24` |
| min-date | 可选择的最小日期 | _timestamp_ | 当前日期 |
| max-date | 可选择的最大日期 | _timestamp_ | 当前日期的六个月后 |
| default-date `v1.10.21` | 默认选中的日期,`type`为`multiple`或`range`时为数组,传入 `null` 表示默认不选择| _timestamp \| timestamp[] \| null_ | 今天 |
| row-height | 日期行高 | _number \| string_ | `64` |
| formatter | 日期格式化函数 | _(day: Day) => Day_ | - |
| poppable | 是否以弹层的形式展示日历 | _boolean_ | `true` |
| show-mark | 是否显示月份背景水印 | _boolean_ | `true` |
| show-title | 是否展示日历标题 | _boolean_ | `true` |
| show-subtitle | 是否展示日历副标题(年月) | _boolean_ | `true` |
| show-confirm | 是否展示确认按钮 | _boolean_ | `true` |
| confirm-text | 确认按钮的文字 | _string_ | `确定` |
| confirm-disabled-text | 确认按钮处于禁用状态时的文字 | _string_ | `确定` |
| first-day-of-week | 设置周起始日 | _0~6_ | `0` |
| readonly `v1.9.1` | 是否为只读状态,只读状态下不能选择日期 | _boolean_ | `false` |
| root-portal `v1.11.3` | 是否从页面子树中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### Poppable Props
当 Calendar 的 `poppable` 为 `true` 时,支持以下 props:
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否显示日历弹窗 | _boolean_ | `false` |
| position | 弹出位置,可选值为 `top` `right` `left` | _string_ | `bottom` |
| round | 是否显示圆角弹窗 | _boolean_ | `true` |
| close-on-click-overlay | 是否在点击遮罩层后关闭 | _boolean_ | `true` |
| safe-area-inset-bottom | 是否开启底部安全区适配 | _boolean_ | `true` |
### Range Props
当 Calendar 的 `type` 为 `range` 时,支持以下 props:
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| max-range | 日期区间最多可选天数,默认无限制 | _number \| string_ | - |
| range-prompt | 范围选择超过最多可选天数时的提示文案 | _string \| null_ | `选择天数不能超过 xx 天` |
| show-range-prompt | 范围选择超过最多可选天数时,是否展示提示文案 | _boolean_ | `true` |
| allow-same-day | 是否允许日期范围的起止时间为同一天 | _boolean_ | `false` |
### Multiple Props
当 Calendar 的 `type` 为 `multiple` 时,支持以下 props:
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| min-range | 日期最少可选天数 | _number \| string_ | `1` |
### Day 数据结构
日历中的每个日期都对应一个 Day 对象,通过`formatter`属性可以自定义 Day 对象的内容。
| 键名 | 说明 | 类型 |
| --- | --- | --- |
| date | 日期对应的 Date 对象 | _Date_ |
| type | 日期类型,可选值为`selected`、`start`、`middle`、`end`、`disabled` | _string_ |
| text | 中间显示的文字 | _string_ |
| topInfo | 上方的提示信息 | _string_ |
| bottomInfo | 下方的提示信息 | _string_ |
| className | 自定义 className | _string_ |
### Events
| 事件名 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:select | 点击任意日期时触发 | _value: Date \| Date[]_ |
| bind:unselect | 当 Calendar 的 `type` 为 `multiple` 时,点击已选中的日期时触发 | _value: Date_ |
| bind:confirm | 日期选择完成后触发,若`show-confirm`为`true`,则点击确认按钮后触发 | _value: Date \| Date[]_ |
| bind:open | 打开弹出层时触发 | - |
| bind:close | 关闭弹出层时触发 | - |
| bind:opened | 打开弹出层且动画结束后触发 | - |
| bind:closed | 关闭弹出层且动画结束后触发 | - |
| bind:over-range | 范围选择超过最多可选天数时触发 | - |
| bind:click-subtitle `v1.8.1` | 点击日历副标题时触发 | _WechatMiniprogram.TouchEvent_ |
### Slots
| 名称 | 说明 |
| ------ | ------------------ |
| title | 自定义标题 |
| footer | 自定义底部区域内容 |
### 方法
通过 selectComponent 可以获取到 Calendar 实例并调用实例方法。
| 方法名 | 说明 | 参数 | 返回值 |
| ------ | ---------------------- | ---- | ------ |
| reset | 重置选中的日期到默认值 | - | - |
================================================
FILE: packages/calendar/calendar.wxml
================================================
================================================
FILE: packages/calendar/components/header/index.json
================================================
{
"component": true
}
================================================
FILE: packages/calendar/components/header/index.less
================================================
@import '../../../common/style/var.less';
.van-calendar {
&__header {
flex-shrink: 0;
box-shadow: var(--calendar-header-box-shadow, @calendar-header-box-shadow);
}
&__header-title,
&__header-subtitle {
text-align: center;
height: var(--calendar-header-title-height, @calendar-header-title-height);
font-weight: var(--font-weight-bold, @font-weight-bold);
line-height: var(
--calendar-header-title-height,
@calendar-header-title-height
);
}
&__header-title:empty,
&__header-title + &__header-title {
display: none;
}
&__header-title:empty + &__header-title {
display: block !important;
}
&__weekdays {
display: flex;
}
&__weekday {
flex: 1;
text-align: center;
font-size: var(--calendar-weekdays-font-size, @calendar-weekdays-font-size);
line-height: var(--calendar-weekdays-height, @calendar-weekdays-height);
}
}
================================================
FILE: packages/calendar/components/header/index.ts
================================================
import { VantComponent } from '../../../common/component';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
firstDayOfWeek: {
type: Number,
observer: 'initWeekDay',
},
},
data: {
weekdays: [] as Array,
},
created() {
this.initWeekDay();
},
methods: {
initWeekDay() {
const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
const firstDayOfWeek = this.data.firstDayOfWeek || 0;
this.setData({
weekdays: [
...defaultWeeks.slice(firstDayOfWeek, 7),
...defaultWeeks.slice(0, firstDayOfWeek),
],
});
},
onClickSubtitle(event: WechatMiniprogram.TouchEvent) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: packages/calendar/components/header/index.wxml
================================================
================================================
FILE: packages/calendar/components/month/index.json
================================================
{
"component": true
}
================================================
FILE: packages/calendar/components/month/index.less
================================================
@import '../../../common/style/var';
.van-calendar {
display: flex;
flex-direction: column;
height: 100%;
background-color: var(
--calendar-background-color,
@calendar-background-color
);
&__month-title {
text-align: center;
height: var(--calendar-header-title-height, @calendar-header-title-height);
font-weight: var(--font-weight-bold, @font-weight-bold);
font-size: var(
--calendar-month-title-font-size,
@calendar-month-title-font-size
);
line-height: var(
--calendar-header-title-height,
@calendar-header-title-height
);
}
&__days {
position: relative;
display: flex;
flex-wrap: wrap;
user-select: none;
}
&__month-mark {
position: absolute;
top: 50%;
left: 50%;
z-index: 0;
transform: translate(-50%, -50%);
pointer-events: none;
color: var(--calendar-month-mark-color, @calendar-month-mark-color);
font-size: var(
--calendar-month-mark-font-size,
@calendar-month-mark-font-size
);
}
&__day,
&__selected-day {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
&__day {
position: relative;
width: 14.285%;
height: var(--calendar-day-height, @calendar-day-height);
font-size: var(--calendar-day-font-size, @calendar-day-font-size);
&--end,
&--start,
&--start-end,
&--multiple-middle,
&--multiple-selected {
color: var(--calendar-range-edge-color, @calendar-range-edge-color);
background-color: var(
--calendar-range-edge-background-color,
@calendar-range-edge-background-color
);
}
&--start {
border-radius: @border-radius-md 0 0 @border-radius-md;
}
&--end {
border-radius: 0 @border-radius-md @border-radius-md 0;
}
&--start-end,
&--multiple-selected {
border-radius: @border-radius-md;
}
&--middle {
color: var(--calendar-range-middle-color, @calendar-range-middle-color);
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: currentColor;
content: '';
opacity: var(
--calendar-range-middle-background-opacity,
@calendar-range-middle-background-opacity
);
}
}
&--disabled {
cursor: default;
color: var(--calendar-day-disabled-color, @calendar-day-disabled-color);
}
}
&__top-info,
&__bottom-info {
position: absolute;
right: 0;
left: 0;
font-size: var(--calendar-info-font-size, @calendar-info-font-size);
line-height: var(--calendar-info-line-height, @calendar-info-line-height);
@media (max-width: 350px) {
font-size: 9px;
}
}
&__top-info {
top: 6px;
}
&__bottom-info {
bottom: 6px;
}
&__selected-day {
width: var(--calendar-selected-day-size, @calendar-selected-day-size);
height: var(--calendar-selected-day-size, @calendar-selected-day-size);
color: var(--calendar-selected-day-color, @calendar-selected-day-color);
background-color: var(
--calendar-selected-day-background-color,
@calendar-selected-day-background-color
);
border-radius: @border-radius-md;
}
}
================================================
FILE: packages/calendar/components/month/index.ts
================================================
import { VantComponent } from '../../../common/component';
import {
getMonthEndDay,
compareDay,
getPrevDay,
getNextDay,
} from '../../utils';
export interface Day {
date: Date;
type: string;
text: number;
bottomInfo?: string;
}
VantComponent({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: null,
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: null,
observer: 'setDays',
},
firstDayOfWeek: {
type: Number,
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [] as Day[],
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
const item: Day = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays() {
const days: Day[] = [];
const startDate = new Date(this.data.date);
const year = startDate.getFullYear();
const month = startDate.getMonth();
const totalDay = getMonthEndDay(
startDate.getFullYear(),
startDate.getMonth() + 1
);
for (let day = 1; day <= totalDay; day++) {
const date = new Date(year, month, day);
const type = this.getDayType(date);
let config: Day = {
date,
type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days });
},
getMultipleDayType(day) {
const { currentDate } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const isSelected = (date) =>
currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
const nextDay = getNextDay(day);
const prevSelected = isSelected(prevDay);
const nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType(day) {
const { currentDate, allowSameDay } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const [startDay, endDay] = currentDate;
if (!startDay) {
return '';
}
const compareToStart = compareDay(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
const compareToEnd = compareDay(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
return '';
},
getDayType(day) {
const { type, minDate, maxDate, currentDate } = this.data;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
return '';
},
getBottomInfo(type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});
================================================
FILE: packages/calendar/components/month/index.wxml
================================================
{{ computed.formatMonthTitle(date) }}
{{ computed.getMark(date) }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
{{ item.topInfo }}
{{ item.text }}
{{ item.bottomInfo }}
================================================
FILE: packages/calendar/components/month/index.wxs
================================================
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
var style = [];
var current = getDate(date).getDay() || 7;
var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
current === 7 && firstDayOfWeek === 0 ? 0 :
(current - firstDayOfWeek);
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'start-end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};
================================================
FILE: packages/calendar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-calendar": "../../calendar/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/calendar/demo/index.less
================================================
.tiled-calendar {
--calendar-height: 618px;
}
================================================
FILE: packages/calendar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
type Data = {
id?: string;
type?: 'single' | 'multiple' | 'range';
round?: boolean;
color?: string;
minDate?: number;
maxDate?: number;
maxRange?: any;
position?: 'top' | 'right' | 'bottom' | 'left';
formatter?: any;
showConfirm?: boolean;
showCalendar?: boolean;
tiledMinDate?: number;
tiledMaxDate?: number;
confirmText?: string | '确定';
confirmDisabledText?: string | '确定';
firstDayOfWeek?: number;
};
VantComponent({
data: {
date: {
maxRange: [],
selectSingle: null,
selectRange: [],
selectMultiple: [],
quickSelect1: null,
quickSelect2: [],
customColor: [],
customConfirm: [],
customRange: null,
customDayText: [],
customPosition: null,
},
type: 'single',
round: true,
color: '',
minDate: Date.now(),
maxDate: new Date(
new Date().getFullYear(),
new Date().getMonth() + 6,
new Date().getDate()
).getTime(),
maxRange: undefined,
position: 'bottom',
formatter: undefined,
showConfirm: false,
showCalendar: false,
tiledMinDate: new Date(2012, 0, 10).getTime(),
tiledMaxDate: new Date(2012, 2, 20).getTime(),
confirmText: '确定',
confirmDisabledText: '确定',
firstDayOfWeek: 0,
},
methods: {
onConfirm(event) {
console.log(event);
this.setData({ showCalendar: false });
this.setData({
[`date.${this.data.id}`]: Array.isArray(event.detail)
? event.detail.map((date) => date.valueOf())
: event.detail.valueOf(),
});
},
onSelect(event) {
console.log(event);
},
onUnselect(event) {
console.log(event);
},
onClose() {
this.setData({ showCalendar: false });
},
onOpen() {
console.log('open');
},
onOpened() {
console.log('opened');
},
onClosed() {
console.log('closed');
},
resetSettings() {
this.setData({
round: true,
color: '',
minDate: Date.now(),
maxDate: new Date(
new Date().getFullYear(),
new Date().getMonth() + 6,
new Date().getDate()
).getTime(),
maxRange: undefined,
position: 'bottom',
formatter: undefined,
showConfirm: true,
confirmText: '确定',
confirmDisabledText: '确定',
});
},
show(event) {
this.resetSettings();
const { type, id } = event.currentTarget.dataset;
const data: Data = {
id,
type,
showCalendar: true,
};
switch (id) {
case 'quickSelect1':
case 'quickSelect2':
data.showConfirm = false;
break;
case 'customColor':
data.color = '#07c160';
break;
case 'customConfirm':
data.confirmText = '完成';
data.confirmDisabledText = '请选择结束时间';
break;
case 'customRange':
data.minDate = new Date(2010, 0, 1).getTime();
data.maxDate = new Date(2010, 0, 31).getTime();
break;
case 'customDayText':
data.minDate = new Date(2010, 4, 1).getTime();
data.maxDate = new Date(2010, 4, 31).getTime();
data.formatter = this.dayFormatter;
break;
case 'customPosition':
data.round = false;
data.position = 'right';
break;
case 'maxRange':
data.maxRange = 3;
break;
}
this.setData(data);
},
dayFormatter(day) {
const month = day.date.getMonth() + 1;
const date = day.date.getDate();
if (month === 5) {
if (date === 1) {
day.topInfo = '劳动节';
} else if (date === 4) {
day.topInfo = '五四青年节';
} else if (date === 11) {
day.text = '今天';
}
}
if (day.type === 'start') {
day.bottomInfo = '入店';
} else if (day.type === 'end') {
day.bottomInfo = '离店';
}
return day;
},
},
});
================================================
FILE: packages/calendar/demo/index.wxml
================================================
================================================
FILE: packages/calendar/demo/index.wxs
================================================
/* eslint-disable */
function formatDate(date) {
if (date) {
date = getDate(date);
return date.getMonth() + 1 + '/' + date.getDate();
}
}
function formatFullDate(date) {
if (date) {
date = getDate(date);
return date.getFullYear() + '/' + formatDate(date);
}
}
function formatMultiple(dates) {
if (dates.length) {
return '选择了 ' + dates.length + '个日期';
}
}
function formatRange(dateRange) {
if (dateRange.length) {
return formatDate(dateRange[0]) + ' - ' + formatDate(dateRange[1]);
}
}
module.exports = {
formatDate: formatDate,
formatFullDate: formatFullDate,
formatMultiple: formatMultiple,
formatRange: formatRange
};
================================================
FILE: packages/calendar/index.json
================================================
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index",
"van-toast": "../toast/index"
}
}
================================================
FILE: packages/calendar/index.less
================================================
@import '../common/style/var';
.van-calendar {
display: flex;
flex-direction: column;
height: var(--calendar-height, @calendar-height);
background-color: var(
--calendar-background-color,
@calendar-background-color
);
&__close-icon {
top: 11px;
}
&__popup--top,
&__popup--bottom {
height: var(--calendar-popup-height, @calendar-popup-height);
}
&__popup--left,
&__popup--right {
height: 100%;
}
&__body {
flex: 1;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
&__footer {
flex-shrink: 0;
padding: 0 var(--padding-md, @padding-md);
&--safe-area-inset-bottom {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
}
&__footer:empty,
&__footer + &__footer {
display: none;
}
&__footer:empty + &__footer {
display: block !important;
}
&__confirm {
height: var(
--calendar-confirm-button-height,
@calendar-confirm-button-height
) !important;
margin: var(
--calendar-confirm-button-margin,
@calendar-confirm-button-margin
) !important;
line-height: var(
--calendar-confirm-button-line-height,
@calendar-confirm-button-line-height
) !important;
}
}
================================================
FILE: packages/calendar/index.ts
================================================
import { VantComponent } from '../common/component';
import {
ROW_HEIGHT,
getPrevDay,
getNextDay,
getToday,
compareDay,
copyDates,
calcDateNum,
formatMonthTitle,
compareMonth,
getMonths,
getDayByOffset,
} from './utils';
import { Day } from './components/month/index';
import Toast from '../toast/toast';
import { requestAnimationFrame } from '../common/utils';
const initialMinDate = getToday().getTime();
const initialMaxDate = (() => {
const now = getToday();
return new Date(
now.getFullYear(),
now.getMonth() + 6,
now.getDate()
).getTime();
})();
const getTime = (date: Date | number) =>
date instanceof Date ? date.getTime() : date;
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
confirmDisabledText: {
type: String,
value: '确定',
},
rangePrompt: String,
showRangePrompt: {
type: Boolean,
value: true,
},
defaultDate: {
type: null,
value: getToday().getTime(),
observer(val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: Number,
value: initialMinDate,
},
maxDate: {
type: Number,
value: initialMaxDate,
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: null,
value: ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: null,
value: null,
},
minRange: {
type: Number,
value: 1,
},
firstDayOfWeek: {
type: Number,
value: 0,
},
readonly: Boolean,
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
subtitle: '',
currentDate: null as any,
scrollIntoView: '',
},
watch: {
minDate() {
this.initRect();
},
maxDate() {
this.initRect();
},
},
created() {
this.setData({
currentDate: this.getInitialDate(this.data.defaultDate),
});
},
mounted() {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset() {
this.setData({ currentDate: this.getInitialDate(this.data.defaultDate) });
this.scrollIntoView();
},
initRect() {
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', (res) => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
}
});
},
limitDateRange(
date: number,
minDate: number | null = null,
maxDate: number | null = null
) {
minDate = minDate || (this.data.minDate as number);
maxDate = maxDate || (this.data.maxDate as number);
if (compareDay(date, minDate) === -1) {
return minDate;
}
if (compareDay(date, maxDate) === 1) {
return maxDate;
}
return date;
},
getInitialDate(defaultDate: number | number[] | null = null) {
const { type, minDate, maxDate, allowSameDay } = this.data;
if (!defaultDate) return [];
const now = getToday().getTime();
if (type === 'range') {
if (!Array.isArray(defaultDate)) {
defaultDate = [];
}
const [startDay, endDay] = defaultDate || [];
const startDate = getTime(startDay || now);
const start = this.limitDateRange(
startDate,
minDate,
allowSameDay ? startDate : getPrevDay(new Date(maxDate)).getTime()
);
const date = getTime(endDay || now);
const end = this.limitDateRange(
date,
allowSameDay ? date : getNextDay(new Date(minDate)).getTime()
);
return [start, end];
}
if (type === 'multiple') {
if (Array.isArray(defaultDate)) {
return defaultDate.map((date) => this.limitDateRange(date));
}
return [this.limitDateRange(now)];
}
if (!defaultDate || Array.isArray(defaultDate)) {
defaultDate = now;
}
return this.limitDateRange(defaultDate);
},
scrollIntoView() {
requestAnimationFrame(() => {
const { currentDate, type, show, poppable, minDate, maxDate } =
this.data;
if (!currentDate) return;
// @ts-ignore
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoView: `month${index}` });
return true;
}
return false;
});
});
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onClickDay(event) {
if (this.data.readonly) {
return;
}
let { date } = event.detail;
const { type, currentDate, allowSameDay } = this.data;
if (type === 'range') {
// @ts-ignore
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
const { days } = this.selectComponent('.month').data;
days.some((day: Day, index) => {
const isDisabled =
day.type === 'disabled' &&
getTime(startDay) < getTime(day.date) &&
getTime(day.date) < getTime(date);
if (isDisabled) {
({ date } = days[index - 1]);
}
return isDisabled;
});
this.select([startDay, date], true);
} else if (compareToStart === -1) {
this.select([date, null]);
} else if (allowSameDay) {
this.select([date, date], true);
}
} else {
this.select([date, null]);
}
} else if (type === 'multiple') {
let selectedIndex: number;
// @ts-ignore
const selected = currentDate.some((dateItem: number, index: number) => {
const equal = compareDay(dateItem, date) === 0;
if (equal) {
selectedIndex = index;
}
return equal;
});
if (selected) {
// @ts-ignore
const cancelDate = currentDate.splice(selectedIndex, 1);
this.setData({ currentDate });
this.unselect(cancelDate);
} else {
// @ts-ignore
this.select([...currentDate, date]);
}
} else {
this.select(date, true);
}
},
unselect(dateArray) {
const date = dateArray[0];
if (date) {
this.$emit('unselect', copyDates(date));
}
},
select(date, complete?: boolean) {
if (complete && this.data.type === 'range') {
const valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
getDayByOffset(date[0], this.data.maxRange - 1),
]);
} else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit(date) {
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', copyDates(date));
},
checkRange(date) {
const { maxRange, rangePrompt, showRangePrompt } = this.data;
if (maxRange && calcDateNum(date) > maxRange) {
if (showRangePrompt) {
Toast({
context: this,
message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
});
}
this.$emit('over-range');
return false;
}
return true;
},
onConfirm() {
if (
this.data.type === 'range' &&
!this.checkRange(this.data.currentDate)
) {
return;
}
wx.nextTick(() => {
// @ts-ignore
this.$emit('confirm', copyDates(this.data.currentDate));
});
},
onClickSubtitle(event: WechatMiniprogram.TouchEvent) {
this.$emit('click-subtitle', event);
},
},
});
================================================
FILE: packages/calendar/index.wxml
================================================
================================================
FILE: packages/calendar/index.wxs
================================================
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate, minRange) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return currentDate.length < minRange;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};
================================================
FILE: packages/calendar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
选择单个日期
选择多个日期
选择日期区间
快捷选择
选择单个日期
选择日期区间
自定义日历
自定义颜色
自定义日期范围
自定义按钮文字
自定义日期文案
自定义弹出位置
日期区间最大范围
平铺展示
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2012年2月
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2012年3月
3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
`;
================================================
FILE: packages/calendar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/calendar/utils.ts
================================================
export const ROW_HEIGHT = 64;
export function formatMonthTitle(date: Date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return `${date.getFullYear()}年${date.getMonth() + 1}月`;
}
export function compareMonth(date1: Date | number, date2: Date | number) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
const year1 = date1.getFullYear();
const year2 = date2.getFullYear();
const month1 = date1.getMonth();
const month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
export function compareDay(day1: Date | number, day2: Date | number) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
const compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
const date1 = day1.getDate();
const date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
export function getDayByOffset(date: Date, offset: number) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
export function getPrevDay(date: Date) {
return getDayByOffset(date, -1);
}
export function getNextDay(date: Date) {
return getDayByOffset(date, 1);
}
export function getToday() {
const today = new Date();
today.setHours(0, 0, 0, 0);
return today;
}
export function calcDateNum(date: [Date, Date]) {
const day1 = new Date(date[0]).getTime();
const day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
export function copyDates(dates: Date | Date[]) {
if (Array.isArray(dates)) {
return dates.map((date) => {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
export function getMonthEndDay(year: number, month: number): number {
return 32 - new Date(year, month - 1, 32).getDate();
}
export function getMonths(minDate: number, maxDate: number) {
const months: number[] = [];
const cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}
================================================
FILE: packages/calendar/utils.wxs
================================================
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};
================================================
FILE: packages/card/README.md
================================================
# Card 商品卡片
### 介绍
商品卡片,用于展示商品的图片、价格等信息。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-card": "@vant/weapp/card/index"
}
```
## 代码演示
### 基础用法
```html
```
### 高级用法
可以通过插槽添加定制内容。
```html
按钮
按钮
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| thumb | 左侧图片 | _string_ | - |
| thumb-mode | 左侧图片裁剪、缩放的模式,可选值参考小程序 image 组件 mode 属性值 | _string_ | `aspectFit` |
| title | 标题 | _string_ | - |
| desc | 描述 | _string_ | - |
| tag | 标签 | _string_ | - |
| num | 商品数量 | _string \| number_ | - |
| price | 商品价格 | _string \| number_ | - |
| origin-price | 商品划线原价 | _string \| number_ | - |
| centered | 内容是否垂直居中 | _string_ | `false` |
| currency | 货币符号 | _string_ | `¥` |
| thumb-link | 点击左侧图片后跳转的链接地址 | _string_ | - |
| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | _string_ | `navigateTo` |
| lazy-load | 是否开启图片懒加载 | _boolean_ | `false` |
### Slot
| 名称 | 说明 |
| ------------ | ---------------------------------------------------- |
| title | 自定义标题栏,如果设置了`title`属性则不生效 |
| desc | 自定义描述栏,如果设置了`desc`属性则不生效 |
| num | 自定义数量 |
| price | 自定义价格 |
| origin-price | 自定义商品原价,如果设置了`origin-price`属性则不生效 |
| price-top | 自定义价格上方区域 |
| bottom | 自定义价格下方区域 |
| thumb | 自定义图片,如果设置了`thumb`属性则不生效 |
| tag | 自定义图片角标,如果设置了`tag`属性则不生效 |
| tags | 自定义描述下方标签区域 |
| footer | 自定义右下角内容 |
### 外部样式类
| 类名 | 说明 |
| ------------------ | -------------- |
| custom-class | 根节点样式类 |
| thumb-class | 左侧图片样式类 |
| title-class | 标题样式类 |
| price-class | 价格样式类 |
| origin-price-class | 划线原价样式类 |
| desc-class | 描述样式类 |
| num-class | 数量样式类 |
================================================
FILE: packages/card/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-card": "../../card/index",
"van-tag": "../../tag/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/card/demo/index.less
================================================
.container {
height: 100vh;
background-color: #fff;
}
.tag,
.button {
margin-right: 5px;
}
.van-card__footer {
margin-top: 5px;
}
================================================
FILE: packages/card/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
imageURL:
'https://img.yzcdn.cn/upload_files/2017/07/02/af5b9f44deaeb68000d7e4a711160c53.jpg',
},
});
================================================
FILE: packages/card/demo/index.wxml
================================================
标签1
标签2
================================================
FILE: packages/card/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}
================================================
FILE: packages/card/index.less
================================================
@import '../common/style/var.less';
.van-card {
position: relative;
box-sizing: border-box;
padding: var(--card-padding, @card-padding);
font-size: var(--card-font-size, @card-font-size);
color: var(--card-text-color, @card-text-color);
background-color: var(--card-background-color, @card-background-color);
&__header {
display: flex;
&--center {
align-items: center;
justify-content: center;
}
}
&__thumb {
position: relative;
flex: none;
width: var(--card-thumb-size, @card-thumb-size);
height: var(--card-thumb-size, @card-thumb-size);
margin-right: var(--padding-xs, @padding-xs);
&:empty {
display: none;
}
}
&__img {
width: 100%;
height: 100%;
border-radius: @border-radius-lg;
}
&__content {
position: relative;
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
min-width: 0; /* hack for flex box ellipsis */
min-height: var(--card-thumb-size, @card-thumb-size);
&--center {
justify-content: center;
}
}
&__title,
&__desc {
word-wrap: break-word;
}
&__title {
font-weight: bold;
line-height: var(--card-title-line-height, @card-title-line-height);
}
&__desc {
line-height: var(--card-desc-line-height, @card-desc-line-height);
color: var(--card-desc-color, @card-desc-color);
}
&__bottom {
line-height: 20px;
}
&__price {
display: inline-block;
font-weight: bold;
color: var(--card-price-color, @card-price-color);
font-size: var(--card-price-font-size, @card-price-font-size);
&-integer {
font-size: var(
--card-price-integer-font-size,
@card-price-integer-font-size
);
font-family: var(--card-price-font-family, @card-price-font-family);
}
&-decimal {
font-family: var(--card-price-font-family, @card-price-font-family);
}
}
&__origin-price {
display: inline-block;
margin-left: 5px;
text-decoration: line-through;
font-size: var(--card-origin-price-font-size, @card-origin-price-font-size);
color: var(--card-origin-price-color, @card-origin-price-color);
}
&__num {
float: right;
}
&__tag {
position: absolute !important;
top: 2px;
left: 0;
}
&__footer {
flex: none;
width: 100%;
text-align: right;
}
}
================================================
FILE: packages/card/index.ts
================================================
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class',
],
mixins: [link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit',
},
currency: {
type: String,
value: '¥',
},
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
onClickThumb() {
this.jumpLink('thumbLink');
},
},
});
================================================
FILE: packages/card/index.wxml
================================================
================================================
FILE: packages/card/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
高级用法
`;
================================================
FILE: packages/card/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/cascader/README.md
================================================
# Cascader 级联选择
### 介绍
级联选择框,用于多层级数据的选择,典型场景为省市区选择。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-cascader": "@vant/weapp/cascader/index"
}
```
## 代码演示
### 基础用法
级联选择组件可以搭配 Field 和 Popup 组件使用,示例如下:
```html
```
```js
const options = [
{
text: '浙江省',
value: '330000',
children: [{ text: '杭州市', value: '330100' }],
},
{
text: '江苏省',
value: '320000',
children: [{ text: '南京市', value: '320100' }],
},
];
Page({
data: {
show: false,
options,
fieldValue: '',
cascaderValue: '',
},
onClick() {
this.setData({
show: true,
});
},
onClose() {
this.setData({
show: false,
});
},
onFinish(e) {
const { selectedOptions, value } = e.detail;
const fieldValue = selectedOptions
.map((option) => option.text || option.name)
.join('/');
this.setData({
fieldValue,
cascaderValue: value,
})
},
});
```
### 自定义颜色
通过 `active-color` 属性来设置选中状态的高亮颜色。
```html
```
### 异步加载选项
可以监听 `change` 事件并动态设置 `options`,实现异步加载选项。
```html
```
```js
Page({
data: {
options: [
{
text: '浙江省',
value: '330000',
children: [],
}
];
},
onChange(e) {
const { value } = e.detail;
if (value === this.data.options[0].value) {
setTimeout(() => {
const children = [
{ text: '杭州市', value: '330100' },
{ text: '宁波市', value: '330200' },
];
this.setData({
'options[0].children': children,
})
}, 500);
}
},
});
```
### 自定义字段名
通过 `field-names` 属性可以自定义 `options` 里的字段名称。
```html
```
```js
Page({
data: {
code: '',
fieldNames: {
text: 'name',
value: 'code',
children: 'items',
},
options: [
{
name: '浙江省',
code: '330000',
items: [{ name: '杭州市', code: '330100' }],
},
{
name: '江苏省',
code: '320000',
items: [{ name: '南京市', code: '320100' }],
},
],
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 顶部标题 | _string_ | - |
| value | 选中项的值 | _string \| number_ | - |
| options | 可选项数据源 | _CascaderOption[]_ | `[]` |
| placeholder | 未选中时的提示文案 | _string_ | `请选择` |
| active-color | 选中状态的高亮颜色 | _string_ | `#1989fa` |
| swipeable | 是否开启手势左右滑动切换 | _boolean_ | `false` |
| closeable | 是否显示关闭图标 | _boolean_ | `true` |
| ellipsis `v1.11.7` | 是否省略过长的标题文字, 关闭后文字过长会出现横向滚动 | _boolean_ | `true` |
| show-header | 是否展示标题栏 | _boolean_ | `true` |
| close-icon | 关闭图标名称或图片链接,等同于 Icon 组件的 [name 属性](#/icon) | _string_ | `cross` |
| field-names | 自定义 `options` 结构中的字段 | _CascaderFieldNames_ | `{ text: 'text', value: 'value', children: 'children' }` |
| use-title-slot `v1.11.3` | 是否使用自定义标题的插槽 | _boolean_ | `false` |
### CascaderOption 数据结构
`options` 属性是一个由对象构成的数组,数组中的每个对象配置一个可选项,对象可以包含以下值:
| 键名 | 说明 | 类型 |
| ------------------ | ------------------------ | --------------------------- |
| text | 选项文字(必填) | _string_ |
| value | 选项对应的值(必填) | _string \| number_ |
| color | 选项文字颜色 | _string_ |
| children | 子选项列表 | _CascaderOption[]_ |
| disabled | 是否禁用选项 | _boolean_ |
| className | 为对应列添加额外的 class | _string \| Array \| object_ |
### Events
| 事件 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:change | 选中项变化时触发 | event.detail:_{ value: string \| number, selectedOptions: CascaderOption[], tabIndex: number }_ |
| bind:finish | 全部选项选择完成后触发 | event.detail:_{ value: string \| number, selectedOptions: CascaderOption[], tabIndex: number }_ |
| bind:close | 点击关闭图标时触发 | - |
| bind:click-tab | 点击标签时触发 | event.detail:_{ tabIndex: number, title: string }_ |
### Slots
| 名称 | 说明 | 参数 |
| --- | --- | --- |
| title | 自定义顶部标题 | - |
================================================
FILE: packages/cascader/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-field": "../../field/index",
"van-popup": "../../popup/index",
"van-cascader": "../../cascader/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/cascader/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import { isDef } from '../../common/utils';
import { isObj } from '../../common/validator';
function deepClone>(obj: T): T {
if (!isDef(obj)) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => deepClone(item)) as unknown as T;
}
if (isObj(obj)) {
const to = {} as Record;
Object.keys(obj).forEach((key: string) => {
// @ts-ignore
to[key] = deepClone(obj[key]);
});
return to as T;
}
return obj;
}
const zhCNOptions = [
{
text: '浙江省',
value: '330000',
children: [
{
text: '杭州市',
value: '330100',
children: [
{
text: '上城区',
value: '330102',
},
{
text: '下城区',
value: '330103',
},
{
text: '江干区',
value: '330104',
},
],
},
{
text: '宁波市',
value: '330200',
children: [
{
text: '海曙区',
value: '330203',
},
{
text: '江北区',
value: '330205',
},
{
text: '北仑区',
value: '330206',
},
],
},
{
text: '温州市',
value: '330300',
children: [
{
text: '鹿城区',
value: '330302',
},
{
text: '龙湾区',
value: '330303',
},
{
text: '瓯海区',
value: '330304',
},
],
},
],
},
{
text: '江苏省',
value: '320000',
children: [
{
text: '南京市',
value: '320100',
children: [
{
text: '玄武区',
value: '320102',
},
{
text: '秦淮区',
value: '320104',
},
{
text: '建邺区',
value: '320105',
},
],
},
{
text: '无锡市',
value: '320200',
children: [
{
text: '锡山区',
value: '320205',
},
{
text: '惠山区',
value: '320206',
},
{
text: '滨湖区',
value: '320211',
},
],
},
{
text: '徐州市',
value: '320300',
children: [
{
text: '鼓楼区',
value: '320302',
},
{
text: '云龙区',
value: '320303',
},
{
text: '贾汪区',
value: '320305',
},
],
},
],
},
];
const asyncOptions1 = [
{
text: '浙江省',
value: '330000',
children: [],
},
];
const asyncOptions2 = [
{ text: '杭州市', value: '330100' },
{ text: '宁波市', value: '330200' },
];
function getCustomFieldOptions(options) {
const newOptions = deepClone(options);
const adjustFieldName = (item) => {
if ('text' in item) {
item.name = item.text;
delete item.text;
}
if ('value' in item) {
item.code = item.value;
delete item.value;
}
if ('children' in item) {
item.items = item.children;
delete item.children;
item.items.forEach(adjustFieldName);
}
};
newOptions.forEach(adjustFieldName);
return newOptions;
}
VantComponent({
data: {
area: '地区',
options: zhCNOptions,
selectArea: '请选择地区',
baseState: {
show: false,
value: '',
result: '',
},
asyncState: {
show: false,
value: undefined,
result: '',
options: asyncOptions1,
},
fieldNames: {
text: 'name',
value: 'code',
children: 'items',
},
customFieldOptions: getCustomFieldOptions(zhCNOptions),
customFieldState: {
show: false,
value: '',
result: '',
},
},
methods: {
onClick(e) {
const { stateKey } = e.currentTarget.dataset;
this.setData({
[`${stateKey}.show`]: true,
});
},
onClose(e) {
const { stateKey } = e.currentTarget.dataset;
this.setData({
[`${stateKey}.show`]: false,
});
},
onFinish(e) {
const { stateKey } = e.currentTarget.dataset;
const { selectedOptions, value } = e.detail;
const result = selectedOptions
.map((option) => option.text || option.name)
.join('/');
this.setData({
[`${stateKey}.value`]: value,
[`${stateKey}.result`]: result,
});
this.onClose(e);
},
loadDynamicOptions(e) {
const { value } = e.detail;
if (value === '330000') {
setTimeout(() => {
this.setData({
'asyncState.options[0].children': asyncOptions2,
});
}, 500);
}
},
},
});
================================================
FILE: packages/cascader/demo/index.wxml
================================================
================================================
FILE: packages/cascader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-tab": "../tab/index",
"van-tabs": "../tabs/index"
}
}
================================================
FILE: packages/cascader/index.less
================================================
@import '../common/style/var.less';
.van-cascader {
&__header {
display: flex;
align-items: center;
justify-content: space-between;
height: @cascader-header-height;
padding: @cascader-header-padding;
}
&__title {
font-weight: 600;
font-size: @cascader-title-font-size;
line-height: @cascader-title-line-height;
}
&__close-icon {
color: @cascader-close-icon-color;
font-size: @cascader-close-icon-size;
height: 22px;
}
&__tabs {
&-wrap {
padding: 0 8px;
height: @cascader-tabs-height !important;
}
}
&__tab {
flex: none !important;
padding: 0 8px !important;
color: @cascader-tab-color !important;
font-weight: 600 !important;
&--unselected {
color: @cascader-unselected-tab-color !important;
font-weight: normal !important;
}
}
&__option {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 16px;
font-size: 14px;
line-height: 20px;
cursor: pointer;
&:active {
background-color: #f2f3f5;
}
&--selected {
color: @cascader-active-color;
font-weight: 600;
}
&--disabled {
color: @cascader-option-disabled-color;
cursor: not-allowed;
&:active {
background-color: transparent;
}
}
}
&__options {
box-sizing: border-box;
height: @cascader-options-height;
padding-top: 6px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}
================================================
FILE: packages/cascader/index.ts
================================================
import { VantComponent } from '../common/component';
enum FieldName {
TEXT = 'text',
VALUE = 'value',
CHILDREN = 'children',
}
type Option = Record;
interface ITab {
options: Option[];
selected: Option | null;
}
const defaultFieldNames = {
text: FieldName.TEXT,
value: FieldName.VALUE,
children: FieldName.CHILDREN,
};
VantComponent({
props: {
title: String,
value: {
type: String,
},
placeholder: {
type: String,
value: '请选择',
},
activeColor: {
type: String,
value: '#1989fa',
},
options: {
type: Array,
value: [],
},
swipeable: {
type: Boolean,
value: false,
},
closeable: {
type: Boolean,
value: true,
},
ellipsis: {
type: Boolean,
value: true,
},
showHeader: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
fieldNames: {
type: Object,
value: defaultFieldNames,
observer: 'updateFieldNames',
},
useTitleSlot: Boolean,
},
data: {
tabs: [] as ITab[],
activeTab: 0,
textKey: FieldName.TEXT,
valueKey: FieldName.VALUE,
childrenKey: FieldName.CHILDREN,
innerValue: '',
},
watch: {
options() {
this.updateTabs();
},
value(newVal) {
this.updateValue(newVal);
},
},
created() {
this.updateTabs();
},
methods: {
updateValue(val: string) {
if (val !== undefined) {
const values = this.data.tabs.map(
(tab: ITab) => tab.selected && tab.selected[this.data.valueKey]
);
if (values.indexOf(val) > -1) {
return;
}
}
this.innerValue = val;
this.updateTabs();
},
updateFieldNames() {
const {
text = 'text',
value = 'value',
children = 'children',
} = this.data.fieldNames || defaultFieldNames;
this.setData({
textKey: text,
valueKey: value,
childrenKey: children,
});
},
getSelectedOptionsByValue(options, value) {
for (let i = 0; i < options.length; i++) {
const option = options[i];
if (option[this.data.valueKey] === value) {
return [option];
}
if (option[this.data.childrenKey]) {
const selectedOptions = this.getSelectedOptionsByValue(
option[this.data.childrenKey],
value
);
if (selectedOptions) {
return [option, ...selectedOptions];
}
}
}
},
updateTabs() {
const { options } = this.data;
const { innerValue } = this;
if (!options.length) {
return;
}
if (innerValue !== undefined) {
const selectedOptions = this.getSelectedOptionsByValue(
options,
innerValue
);
if (selectedOptions) {
let optionsCursor = options;
const tabs = selectedOptions.map((option) => {
const tab = {
options: optionsCursor,
selected: option,
};
const next = optionsCursor.find(
(item) => item[this.data.valueKey] === option[this.data.valueKey]
);
if (next) {
optionsCursor = next[this.data.childrenKey];
}
return tab;
});
if (optionsCursor) {
tabs.push({
options: optionsCursor,
selected: null,
});
}
this.setData({
tabs,
});
wx.nextTick(() => {
this.setData({
activeTab: tabs.length - 1,
});
});
return;
}
}
this.setData({
tabs: [
{
options,
selected: null,
},
],
activeTab: 0,
});
},
onClose() {
this.$emit('close');
},
onClickTab(e) {
const { index: tabIndex, title } = e.detail;
this.$emit('click-tab', { title, tabIndex });
this.setData({
activeTab: tabIndex,
});
},
// 选中
onSelect(e) {
const { option, tabIndex } = e.currentTarget.dataset;
if (option && option.disabled) {
return;
}
const { valueKey, childrenKey } = this.data;
let { tabs } = this.data;
tabs[tabIndex].selected = option;
if (tabs.length > tabIndex + 1) {
tabs = tabs.slice(0, tabIndex + 1);
}
if (option[childrenKey]) {
const nextTab = {
options: option[childrenKey],
selected: null,
};
if (tabs[tabIndex + 1]) {
tabs[tabIndex + 1] = nextTab;
} else {
tabs.push(nextTab);
}
wx.nextTick(() => {
this.setData({
activeTab: tabIndex + 1,
});
});
}
this.setData({
tabs,
});
const selectedOptions = tabs.map((tab) => tab.selected).filter(Boolean);
const value = option[valueKey];
const params = {
value,
tabIndex,
selectedOptions,
};
this.innerValue = value;
this.$emit('change', params);
if (!option[childrenKey]) {
this.$emit('finish', params);
}
},
},
});
================================================
FILE: packages/cascader/index.wxml
================================================
{{ option[textKey] }}
================================================
FILE: packages/cascader/index.wxs
================================================
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function isSelected(tab, valueKey, option) {
return tab.selected && tab.selected[valueKey] === option[valueKey]
}
function optionClass(tab, valueKey, option) {
return utils.bem('cascader__option', { selected: isSelected(tab, valueKey, option), disabled: option.disabled })
}
function optionStyle(data) {
var color = data.option.color || (isSelected(data.tab, data.valueKey, data.option) ? data.activeColor : undefined);
return style({
color
});
}
module.exports = {
isSelected: isSelected,
optionClass: optionClass,
optionStyle: optionStyle,
};
================================================
FILE: packages/cascader/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
地区
自定义颜色
地区
异步加载选项
地区
自定义字段名
地区
`;
================================================
FILE: packages/cascader/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/cell/README.md
================================================
# Cell 单元格
### 介绍
单元格为列表中的单个展示项。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index"
}
```
## 代码演示
### 基础用法
`Cell`可以单独使用,也可以与`CellGroup`搭配使用。`CellGroup`可以为`Cell`提供上下外边框。
```html
```
### 卡片风格
通过 `CellGroup` 的 `inset` 属性,可以将单元格转换为圆角卡片风格(从 1.7.2 版本开始支持)。
```html
```
### 单元格大小
通过`size`属性可以控制单元格的大小。
```html
```
### 展示图标
通过`icon`属性在标题左侧展示图标。
```html
```
### 展示箭头
设置`is-link`属性后会在单元格右侧显示箭头,并且可以通过`arrow-direction`属性控制箭头方向。
```html
```
### 页面跳转
可以通过`url`属性进行页面跳转,通过`link-type`属性控制跳转类型。
```html
```
### 分组标题
通过`CellGroup`的`title`属性可以指定分组标题。
```html
```
### 使用插槽
如以上用法不能满足你的需求,可以使用插槽来自定义内容。
```html
单元格
标签
```
### 垂直居中
通过`center`属性可以让`Cell`的左右内容都垂直居中。
```html
```
## API
### CellGroup Props
| 参数 | 说明 | 类型 | 默认值 |
| -------------- | ---------------------- | --------- | ------- |
| title | 分组标题 | _string_ | `-` |
| inset `v1.7.2` | 是否展示为圆角卡片风格 | _boolean_ | `false` |
| border | 是否显示外边框 | _boolean_ | `true` |
### CellGroup 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### Cell Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| icon | 左侧图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| title | 左侧标题 | _string \| number_ | - |
| title-width | 标题宽度,须包含单位 | _string_ | - |
| value | 右侧内容 | _string \| number_ | - |
| label | 标题下方的描述信息 | _string_ | - |
| size | 单元格大小,可选值为 `large` | _string_ | - |
| border | 是否显示下边框 | _boolean_ | `true` |
| center | 是否使内容垂直居中 | _boolean_ | `false` |
| url | 点击后跳转的链接地址 | _string_ | - |
| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | _string_ | `navigateTo` |
| clickable | 是否开启点击反馈 | _boolean_ | `false` |
| is-link | 是否展示右侧箭头并开启点击反馈 | _boolean_ | `false` |
| required | 是否显示表单必填星号 | _boolean_ | `false` |
| arrow-direction | 箭头方向,可选值为 `left` `up` `down` | _string_ | - |
| use-label-slot | 是否使用 label slot | _boolean_ | `false` |
| title-style `v1.4.0` | 标题样式 | _string_ | - |
### Cell Event
| 事件名 | 说明 | 参数 |
| ---------- | ---------------- | ---- |
| bind:click | 点击单元格时触发 | - |
### Cell Slot
| 名称 | 说明 |
| ---------- | -------------------------------------------------------------- |
| - | 自定义`value`显示内容,如果设置了`value`属性则不生效 |
| title | 自定义`title`显示内容,如果设置了`title`属性则不生效 |
| label | 自定义`label`显示内容,需要设置 `use-label-slot`属性 |
| icon | 自定义`icon`显示内容,如果设置了`icon`属性则不生效 |
| right-icon | 自定义右侧按钮,默认是`arrow`,如果设置了`is-link`属性则不生效 |
### Cell 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| title-class | 标题样式类 |
| label-class | 描述信息样式类 |
| value-class | 右侧内容样式类 |
================================================
FILE: packages/cell/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-cell-group": "../../cell-group/index",
"van-icon": "../../icon/index",
"van-tag": "../../tag/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/cell/demo/index.less
================================================
.title {
margin-right: 5px;
display: inline-block;
vertical-align: middle;
}
================================================
FILE: packages/cell/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/cell/demo/index.wxml
================================================
描述信息
单元格
标签
================================================
FILE: packages/cell/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/cell/index.less
================================================
@import '../common/style/var.less';
@import '../common/style/mixins/hairline.less';
.van-cell {
position: relative;
display: flex;
box-sizing: border-box;
width: 100%;
padding: var(--cell-vertical-padding, @cell-vertical-padding)
var(--cell-horizontal-padding, @cell-horizontal-padding);
font-size: var(--cell-font-size, @cell-font-size);
line-height: var(--cell-line-height, @cell-line-height);
color: var(--cell-text-color, @cell-text-color);
background-color: var(--cell-background-color, @cell-background-color);
&::after {
.hairline-bottom(@border-color, @padding-md, @padding-md);
}
&--borderless::after {
display: none;
}
&-group {
background-color: var(--cell-background-color, @cell-background-color);
}
&__label {
margin-top: var(--cell-label-margin-top, @cell-label-margin-top);
font-size: var(--cell-label-font-size, @cell-label-font-size);
line-height: var(--cell-label-line-height, @cell-label-line-height);
color: var(--cell-label-color, @cell-label-color);
}
&__value {
overflow: hidden;
text-align: right;
vertical-align: middle;
color: var(--cell-value-color, @cell-value-color);
}
&__title,
&__value {
flex: 1;
&:empty {
display: none;
}
}
&__left-icon-wrap,
&__right-icon-wrap {
display: flex;
align-items: center;
height: var(--cell-line-height, @cell-line-height);
font-size: var(--cell-icon-size, @cell-icon-size);
}
&__left-icon-wrap {
margin-right: var(--padding-base, @padding-base);
}
&__right-icon-wrap {
margin-left: var(--padding-base, @padding-base);
color: var(--cell-right-icon-color, @cell-right-icon-color);
}
&__left-icon {
vertical-align: middle;
line-height: var(--cell-line-height, @cell-line-height);
}
&__right-icon {
line-height: var(--cell-line-height, @cell-line-height);
}
&--clickable&--hover {
background-color: var(--cell-active-color, @cell-active-color);
}
&--required {
overflow: visible;
&::before {
position: absolute;
content: '*';
left: var(--padding-xs, @padding-xs);
font-size: var(--cell-font-size, @cell-font-size);
color: var(--cell-required-color, @cell-required-color);
}
}
&--center {
align-items: center;
}
&--large {
padding-top: var(
--cell-large-vertical-padding,
@cell-large-vertical-padding
);
padding-bottom: var(
--cell-large-vertical-padding,
@cell-large-vertical-padding
);
.van-cell__title {
font-size: var(--cell-large-title-font-size, @cell-large-title-font-size);
}
.van-cell__value {
font-size: var(--cell-large-value-font-size, @cell-large-value-font-size);
}
.van-cell__label {
font-size: var(--cell-large-label-font-size, @cell-large-label-font-size);
}
}
}
================================================
FILE: packages/cell/index.ts
================================================
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class',
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick(event: WechatMiniprogram.TouchEvent) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: packages/cell/index.wxml
================================================
{{ title }}
{{ label }}
{{ value }}
================================================
FILE: packages/cell/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};
================================================
FILE: packages/cell/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
单元格
内容
单元格
描述信息
内容
卡片风格
单元格
内容
单元格
描述信息
内容
单元格大小
单元格
内容
单元格
描述信息
内容
展示图标
单元格
内容
展示箭头
单元格
单元格
内容
单元格
内容
页面跳转
单元格
单元格
分组标题
分组 1
单元格
内容
分组 2
单元格
内容
使用插槽
单元格
标签
内容
单元格
垂直居中
单元格
描述信息
内容
`;
================================================
FILE: packages/cell/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/cell-group/index.json
================================================
{
"component": true
}
================================================
FILE: packages/cell-group/index.less
================================================
@import '../common/style/var.less';
.van-cell-group {
&--inset {
margin: var(--cell-group-inset-padding, @cell-group-inset-padding);
border-radius: var(
--cell-group-inset-border-radius,
@cell-group-inset-border-radius
);
overflow: hidden;
}
&__title {
padding: var(--cell-group-title-padding, @cell-group-title-padding);
font-size: var(--cell-group-title-font-size, @cell-group-title-font-size);
line-height: var(
--cell-group-title-line-height,
@cell-group-title-line-height
);
color: var(--cell-group-title-color, @cell-group-title-color);
&--inset {
padding: var(
--cell-group-inset-title-padding,
@cell-group-inset-title-padding
);
}
}
}
================================================
FILE: packages/cell-group/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
inset: Boolean,
},
});
================================================
FILE: packages/cell-group/index.wxml
================================================
{{ title }}
================================================
FILE: packages/checkbox/README.md
================================================
# Checkbox 复选框
### 介绍
在一组备选项中进行多选。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-checkbox": "@vant/weapp/checkbox/index",
"van-checkbox-group": "@vant/weapp/checkbox-group/index"
}
```
## 代码演示
### 基础用法
通过`value`绑定复选框的勾选状态。
```html
复选框
```
```js
Page({
data: {
checked: true,
},
onChange(event) {
this.setData({
checked: event.detail,
});
},
});
```
### 禁用状态
通过设置`disabled`属性可以禁用复选框。
```html
复选框
```
### 自定义形状
将`shape`属性设置为`square`,复选框的形状会变成方形。
```html
复选框
```
### 自定义颜色
通过`checked-color`属性可以自定义选中状态下的图标颜色。
```html
复选框
```
### 自定义大小
通过`icon-size`属性可以自定义图标的大小。
```html
复选框
```
### 自定义图标
通过 icon 插槽自定义图标。
```html
自定义图标
```
```js
Page({
data: {
checked: true,
activeIcon: '//img.yzcdn.cn/icon-active.png',
inactiveIcon: '//img.yzcdn.cn/icon-normal.png',
},
onChange(event) {
this.setData({
checked: event.detail,
});
},
});
```
### 禁用文本点击
通过设置`label-disabled`属性可以禁用复选框文本点击。
```html
复选框
```
### 复选框组
需要与`van-checkbox-group`一起使用,选中值是一个数组,通过`value`绑定在`van-checkbox-group`上,数组中的项即为选中的`Checkbox`的`name`属性设置的值。
```html
复选框 a
复选框 b
复选框 c
```
```javascript
Page({
data: {
result: ['a', 'b'],
},
onChange(event) {
this.setData({
result: event.detail,
});
},
});
```
### 限制最大可选数
```html
复选框 a
复选框 b
复选框 c
```
### 搭配单元格组件使用
此时你需要再引入`Cell`和`CellGroup`组件,并通过 checkbox 的 toggle 方法手动触发切换。
```html
```
```js
Page({
data: {
list: ['a', 'b', 'c'],
result: ['a', 'b'],
},
onChange(event) {
this.setData({
result: event.detail,
});
},
toggle(event) {
const { index } = event.currentTarget.dataset;
const checkbox = this.selectComponent(`.checkboxes-${index}`);
checkbox.toggle();
},
noop() {},
});
```
```css
.value-class {
flex: none !important;
}
```
## API
### Checkbox Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 标识 Checkbox 名称 | _string_ | - |
| shape | 形状,可选值为 `round` `square` | _string_ | `round` |
| value | 是否为选中状态 | _boolean_ | `false` |
| disabled | 是否禁用单选框 | _boolean_ | `false` |
| label-disabled | 是否禁用单选框内容点击 | _boolean_ | `false` |
| label-position | 文本位置,可选值为 `left` | _string_ | `right` |
| use-icon-slot | 是否使用 icon slot | _boolean_ | `false` |
| checked-color | 选中状态颜色 | _string_ | `#1989fa` |
| icon-size | icon 大小 | _string \| number_ | `20px` |
### CheckboxGroup Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符 | _string_ | - |
| value | 所有选中项的 name | _Array_ | - |
| disabled | 是否禁用所有单选框 | _boolean_ | `false` |
| max | 设置最大可选数 | _number_ | `0`(无限制) |
| direction `v1.7.0` | 排列方向,可选值为 `horizontal` | _string_ | `vertical` |
### Checkbox Event
| 事件名 | 说明 | 回调参数 |
| ----------- | ------------------------ | ------------ |
| bind:change | 当绑定值变化时触发的事件 | 当前组件的值 |
### Checkbox 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| icon-class | 图标样式类 |
| label-class | 描述信息样式类 |
### CheckboxGroup Event
| 事件名 | 说明 | 回调参数 |
| ----------- | ------------------------ | ------------ |
| bind:change | 当绑定值变化时触发的事件 | 当前组件的值 |
### Checkbox Slot
| 名称 | 说明 |
| ---- | ---------- |
| - | 自定义文本 |
| icon | 自定义图标 |
### Checkbox 方法
通过 selectComponent 可以获取到 checkbox 实例并调用实例方法。
| 方法名 | 参数 | 返回值 | 介绍 |
| ------ | ---- | ------ | ------------ |
| toggle | - | - | 切换选中状态 |
================================================
FILE: packages/checkbox/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"van-cell": "../../cell/index",
"van-checkbox": "../../checkbox/index",
"van-checkbox-group": "../../checkbox-group/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/checkbox/demo/index.less
================================================
.demo-checkbox-group {
margin: 10px 0 0 20px;
}
.demo-checkbox {
margin: 10px 0 0 20px;
}
.value-class {
flex: none !important;
}
.icon {
width: 20px;
}
================================================
FILE: packages/checkbox/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
checkbox1: true,
checkbox2: true,
checkbox3: true,
checkboxLabel: true,
checkboxSize: true,
checkboxShape: true,
list: ['a', 'b', 'c'],
result: ['a', 'b'],
result2: [],
result3: [],
result4: [],
activeIcon: 'https://img.yzcdn.cn/vant/user-active.png',
inactiveIcon: 'https://img.yzcdn.cn/vant/user-inactive.png',
},
methods: {
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({ [key]: event.detail });
},
toggle(event) {
const { index } = event.currentTarget.dataset;
const checkbox = this.selectComponent(`.checkboxes-${index}`);
checkbox.toggle();
},
noop() {},
},
});
================================================
FILE: packages/checkbox/demo/index.wxml
================================================
复选框
复选框
复选框
复选框
复选框
复选框
自定义图标
复选框
复选框 {{ item }}
复选框 {{ item }}
复选框 {{ item }}
================================================
FILE: packages/checkbox/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/checkbox/index.less
================================================
@import '../common/style/var.less';
.van-checkbox {
display: flex;
align-items: center;
overflow: hidden;
user-select: none;
&--horizontal {
margin-right: @padding-sm;
}
&__icon-wrap,
&__label {
line-height: var(--checkbox-size, @checkbox-size);
}
&__icon-wrap {
flex: none;
}
&__icon {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 1em;
height: 1em;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: var(--checkbox-size, @checkbox-size);
border: 1px solid var(--checkbox-border-color, @checkbox-border-color);
transition-duration: var(
--checkbox-transition-duration,
@checkbox-transition-duration
);
&--round {
border-radius: 100%;
}
&--checked {
color: @white;
background-color: var(
--checkbox-checked-icon-color,
@checkbox-checked-icon-color
);
border-color: var(
--checkbox-checked-icon-color,
@checkbox-checked-icon-color
);
}
&--disabled {
background-color: var(
--checkbox-disabled-background-color,
@checkbox-disabled-background-color
);
border-color: var(
--checkbox-disabled-icon-color,
@checkbox-disabled-icon-color
);
}
&--disabled&--checked {
color: var(--checkbox-disabled-icon-color, @checkbox-disabled-icon-color);
}
}
&__label {
word-wrap: break-word;
padding-left: var(--checkbox-label-margin, @checkbox-label-margin);
color: var(--checkbox-label-color, @checkbox-label-color);
&--left {
float: left;
margin: 0 var(--checkbox-label-margin, @checkbox-label-margin) 0 0;
}
&--disabled {
color: var(
--checkbox-disabled-label-color,
@checkbox-disabled-label-color
);
}
&:empty {
margin: 0;
}
}
}
================================================
FILE: packages/checkbox/index.ts
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
function emit(
target: WechatMiniprogram.Component.TrivialInstance,
value: boolean | any[]
) {
target.$emit('input', value);
target.$emit('change', value);
}
VantComponent({
field: true,
relation: useParent('checkbox-group'),
classes: ['icon-class', 'label-class'],
props: {
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
direction: 'vertical',
},
methods: {
emitChange(value: boolean) {
if (this.parent) {
this.setParentValue(this.parent, value);
} else {
emit(this, value);
}
},
toggle() {
const { parentDisabled, disabled, value } = this.data;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel() {
const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
setParentValue(
parent: WechatMiniprogram.Component.TrivialInstance,
value: boolean
) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
const { max } = parent.data;
if (value) {
if (max && parentValue.length >= max) {
return;
}
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
emit(parent, parentValue);
}
} else {
const index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
},
},
});
================================================
FILE: packages/checkbox/index.wxml
================================================
================================================
FILE: packages/checkbox/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = {
'font-size': addUnit(iconSize),
};
if (checkedColor && value && !disabled && !parentDisabled) {
styles['border-color'] = checkedColor;
styles['background-color'] = checkedColor;
}
return style(styles);
}
module.exports = {
iconStyle: iconStyle,
};
================================================
FILE: packages/checkbox/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基本用法
复选框
禁用状态
复选框
复选框
自定义形状
复选框
自定义颜色
复选框
自定义大小
复选框
自定义图标
自定义图标
禁用文本点击
复选框
复选框组
复选框 a
复选框 b
复选框 c
水平排列
复选框 a
复选框 b
复选框 c
限制最大可选数
复选框 a
复选框 b
复选框 c
搭配单元格组件使用
复选框 a
复选框 b
复选框 c
`;
================================================
FILE: packages/checkbox/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/checkbox-group/index.json
================================================
{
"component": true
}
================================================
FILE: packages/checkbox-group/index.less
================================================
.van-checkbox-group {
&--horizontal {
display: flex;
flex-wrap: wrap;
}
}
================================================
FILE: packages/checkbox-group/index.ts
================================================
import { useChildren } from '../common/relation';
import { VantComponent } from '../common/component';
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
VantComponent({
field: true,
relation: useChildren('checkbox', function (target) {
this.updateChild(target);
}),
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren',
},
direction: {
type: String,
value: 'vertical',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => this.updateChild(child));
},
updateChild(child: TrivialInstance) {
const { value, disabled, direction } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled,
direction,
});
},
},
});
================================================
FILE: packages/checkbox-group/index.wxml
================================================
================================================
FILE: packages/circle/README.md
================================================
# Circle 环形进度条
### 介绍
圆环形的进度条组件,支持进度渐变动画。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-circle": "@vant/weapp/circle/index"
}
```
## 代码演示
### 基础用法
`value`属性表示进度条的目标进度。
```html
```
### 宽度定制
通过`stroke-width`属性来控制进度条宽度。
```html
```
### 颜色定制
通过`color`属性来控制进度条颜色,`layer-color`属性来控制轨道颜色。
```html
```
### 渐变色
`color`属性支持传入对象格式来定义渐变色。
```html
```
```javascript
Page({
data: {
value: 25,
gradientColor: {
'0%': '#ffd01e',
'100%': '#ee0a24',
},
},
});
```
### 逆时针方向
将`clockwise`设置为`false`,进度会从逆时针方向开始。
```html
```
### 大小定制
通过`size`属性设置圆环直径。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 目标进度 | _number_ | `0` |
| type | 指定 canvas 类型,可选值为 `2d` | _string_ | - |
| size | 圆环直径,默认单位为 `px` | _number_ | `100` |
| color | 进度条颜色,传入对象格式可以定义渐变色 | _string \| object_ | `#1989fa` |
| layer-color | 轨道颜色 | _string_ | `#fff` |
| fill | 填充颜色 | _string_ | - |
| speed | 动画速度(单位为 value/s) | _number_ | `50` |
| text | 文字 | _string_ | - |
| stroke-width | 进度条宽度 | _number_ | `4` |
| clockwise | 是否顺时针增加 | _boolean_ | `true` |
### Slots
| 名称 | 说明 |
| ---- | ---------------------------------------------------------- |
| - | 自定义文字内容,如果设置了`fill`,插槽内容会被原生组件覆盖 |
================================================
FILE: packages/circle/canvas.ts
================================================
type CanvasContext = WechatMiniprogram.CanvasContext;
export function adaptor(
ctx: CanvasContext & Record
): CanvasContext {
// @ts-ignore
return Object.assign(ctx, {
setStrokeStyle(val) {
ctx.strokeStyle = val;
},
setLineWidth(val) {
ctx.lineWidth = val;
},
setLineCap(val) {
ctx.lineCap = val;
},
setFillStyle(val) {
ctx.fillStyle = val;
},
setFontSize(val) {
ctx.font = String(val);
},
setGlobalAlpha(val) {
ctx.globalAlpha = val;
},
setLineJoin(val) {
ctx.lineJoin = val;
},
setTextAlign(val) {
ctx.textAlign = val;
},
setMiterLimit(val) {
ctx.miterLimit = val;
},
setShadow(offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline(val) {
ctx.textBaseline = val;
},
createCircularGradient() {},
draw() {},
});
}
================================================
FILE: packages/circle/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-circle": "../../circle/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/circle/demo/index.less
================================================
.van-circle {
margin: 5px 10px 20px;
}
.van-button {
margin-left: 10px;
}
================================================
FILE: packages/circle/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
const format = (rate) => Math.min(Math.max(rate, 0), 100);
VantComponent({
data: {
value: 25,
gradientColor: {
'0%': '#ffd01e',
'100%': '#ee0a24',
},
},
methods: {
run(e) {
const step = parseFloat(e.currentTarget.dataset.step);
this.setData({
value: format((this.data.value += step)),
});
},
},
});
================================================
FILE: packages/circle/demo/index.wxml
================================================
增加
减少
================================================
FILE: packages/circle/index.json
================================================
{
"component": true
}
================================================
FILE: packages/circle/index.less
================================================
@import '../common/style/var.less';
.van-circle {
position: relative;
display: inline-block;
text-align: center;
&__text {
position: absolute;
top: 50%;
left: 0;
width: 100%;
transform: translateY(-50%);
color: var(--circle-text-color, @circle-text-color);
}
}
================================================
FILE: packages/circle/index.ts
================================================
import { BLUE, WHITE } from '../common/color';
import { VantComponent } from '../common/component';
import { getSystemInfoSync } from '../common/utils';
import { isObj } from '../common/validator';
import { canIUseCanvas2d } from '../common/version';
import { adaptor } from './canvas';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round',
},
value: {
type: Number,
value: 0,
observer: 'reRender',
},
speed: {
type: Number,
value: 50,
},
size: {
type: Number,
value: 100,
observer() {
this.drawCircle(this.currentValue);
},
},
fill: String,
layerColor: {
type: String,
value: WHITE,
},
color: {
type: null,
value: BLUE,
observer() {
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
},
type: {
type: String,
value: '',
},
strokeWidth: {
type: Number,
value: 4,
},
clockwise: {
type: Boolean,
value: true,
},
},
data: {
hoverColor: BLUE,
},
methods: {
getContext(): Promise {
const { type, size } = this.data;
if (type === '' || !canIUseCanvas2d()) {
const ctx = wx.createCanvasContext('van-circle', this);
return Promise.resolve(ctx);
}
const dpr = getSystemInfoSync().pixelRatio;
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(this)
.select('#van-circle')
.node()
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext(type);
if (!this.inited) {
this.inited = true;
canvas.width = size * dpr;
canvas.height = size * dpr;
ctx.scale(dpr, dpr);
}
resolve(adaptor(ctx));
});
});
},
setHoverColor() {
const { color, size } = this.data;
if (isObj(color)) {
return this.getContext().then((context) => {
if (!context) return;
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map((key) =>
LinearColor.addColorStop(
parseFloat(key) / 100,
color[key] as string
)
);
this.hoverColor = LinearColor;
});
}
this.hoverColor = color;
return Promise.resolve();
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill?: string) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const { size } = this.data;
this.getContext().then((context) => {
if (!context) return;
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
});
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearMockInterval();
this.currentValue = this.currentValue || 0;
const run = () => {
this.interval = setTimeout(() => {
if (this.currentValue !== value) {
if (Math.abs(this.currentValue - value) < STEP) {
this.currentValue = value;
} else if (this.currentValue < value) {
this.currentValue += STEP;
} else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
run();
} else {
this.clearMockInterval();
}
}, 1000 / speed);
};
run();
},
clearMockInterval() {
if (this.interval) {
clearTimeout(this.interval);
this.interval = null;
}
},
},
mounted() {
this.currentValue = this.data.value;
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
destroyed() {
this.clearMockInterval();
},
});
================================================
FILE: packages/circle/index.wxml
================================================
{{ text }}
================================================
FILE: packages/circle/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
25%
样式定制
宽度定制
颜色定制
渐变色
逆时针
大小定制
增加
减少
`;
================================================
FILE: packages/circle/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/col/README.md
================================================
# Layout 布局
### 介绍
Layout 提供了`van-row`和`van-col`两个组件来进行行列布局。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-row": "@vant/weapp/row/index",
"van-col": "@vant/weapp/col/index"
}
```
## 代码演示
### 基本用法
Layout 组件提供了`24列栅格`,通过在`Col`上添加`span`属性设置列所占的宽度百分比。此外,添加`offset`属性可以设置列的偏移宽度,计算方式与 span 相同。
```html
span: 8
span: 8
span: 8
span: 4
offset: 4, span: 10
offset: 12, span: 12
```
### 设置列元素间距
通过`gutter`属性可以设置列元素之间的间距,默认间距为 0。
```html
span: 8
span: 8
span: 8
```
## API
### Row Props
| 参数 | 说明 | 类型 | 默认值 |
| ------ | ----------------------------- | ------------------ | ------ |
| gutter | 列元素之间的间距(单位为 px) | _string \| number_ | - |
### Col Props
| 参数 | 说明 | 类型 | 默认值 |
| ------ | -------------- | ------------------ | ------ |
| span | 列元素宽度 | _string \| number_ | - |
| offset | 列元素偏移距离 | _string \| number_ | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/col/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-row": "../../row/index",
"van-col": "../../col/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/col/demo/index.less
================================================
.dark,
.light {
color: #fff;
font-size: 13px;
line-height: 30px;
text-align: center;
margin-bottom: 10px;
background-clip: content-box;
}
.dark {
background-color: #39a9ed;
}
.light {
background-color: #66c6f2;
}
================================================
FILE: packages/col/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/col/demo/index.wxml
================================================
span: 8
span: 8
span: 8
span: 4
offset: 4, span: 10
offset: 12, span: 12
span: 8
span: 8
span: 8
================================================
FILE: packages/col/index.json
================================================
{
"component": true
}
================================================
FILE: packages/col/index.less
================================================
.van-col {
float: left;
box-sizing: border-box;
}
.generate(24);
.generate(@n, @i: 1) when (@i =< @n) {
.van-col--@{i} {
width: @i * (100% / 24);
}
.van-col--offset-@{i} {
margin-left: @i * (100% / 24);
}
.generate(@n, (@i + 1));
}
================================================
FILE: packages/col/index.ts
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('row'),
props: {
span: Number,
offset: Number,
},
});
================================================
FILE: packages/col/index.wxml
================================================
================================================
FILE: packages/col/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'padding-right': addUnit(data.gutter / 2),
'padding-left': addUnit(data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/col/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
span: 8
span: 8
span: 8
span: 4
offset: 4, span: 10
offset: 12, span: 12
在列元素之间增加间距
span: 8
span: 8
span: 8
`;
================================================
FILE: packages/col/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/collapse/README.md
================================================
# Collapse 折叠面板
### 介绍
将一组内容放置在多个折叠面板中,点击面板的标题可以展开或收缩其内容。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-collapse": "@vant/weapp/collapse/index",
"van-collapse-item": "@vant/weapp/collapse-item/index"
}
```
## 代码演示
### 基础用法
通过`value`控制展开的面板列表,`activeNames`为数组格式。
```html
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
```
```javascript
Page({
data: {
activeNames: ['1'],
},
onChange(event) {
this.setData({
activeNames: event.detail,
});
},
});
```
### 手风琴
通过`accordion`可以设置为手风琴模式,最多展开一个面板,此时`activeName`为字符串格式。
```html
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
```
```javascript
Page({
data: {
activeName: '1',
},
onChange(event) {
this.setData({
activeName: event.detail,
});
},
});
```
### 事件监听
`van-collapse` 提供了 `change`, `open` 和 `close` 事件。`change` 事件在面板切换时触发,`open` 事件在面板展开时触发,`close` 事件在面板关闭时触发。
```html
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
```
```javascript
Page({
data: {
activeNames: ['1'],
},
onChange(event) {
this.setData({
activeNames: event.detail,
});
},
onOpen(event) {
Toast(`展开: ${event.detail}`);
},
onClose(event) {
Toast(`关闭: ${event.detail}`);
},
});
```
### 自定义标题内容
```html
标题1
代码是写出来给人看的,附带能在机器上运行
代码是写出来给人看的,附带能在机器上运行
```
```javascript
Page({
data: {
activeNames: ['1'],
},
onChange(event) {
this.setData({
activeNames: event.detail,
});
},
});
```
## API
### Collapse Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前展开面板的 name | 非手风琴模式:_(string \| number)[]_
手风琴模式:_string \| number_ | - |
| accordion | 是否开启手风琴模式 | _boolean_ | `false` |
| border | 是否显示外边框 | _boolean_ | `true` |
### Collapse Event
| 事件名 | 说明 | 参数 |
| ------ | -------------- | ------------------------------- |
| change | 切换面板时触发 | activeNames: _string \| Array_ |
| open | 展开面板时触发 | currentName: _string \| number_ |
| close | 关闭面板时触发 | currentName: _string \| number_ |
### CollapseItem Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 唯一标识符,默认为索引值 | _string \| number_ | `index` |
| title | 标题栏左侧内容 | _string \| number_ | - |
| size | 标题栏大小,可选值为`large` | _string_ | - |
| icon | 标题栏左侧图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| value | 标题栏右侧内容 | _string \| number_ | - |
| label | 标题栏描述信息 | _string_ | - |
| border | 是否显示内边框 | _boolean_ | `true` |
| is-link | 是否展示标题栏右侧箭头并开启点击反馈 | _boolean_ | `true` |
| clickable | 是否开启点击反馈 | _boolean_ | `false` |
| disabled | 是否禁用面板 | _boolean_ | `false` |
### CollapseItem Slot
| 名称 | 说明 |
| ---------- | ----------------------------- |
| - | 面板内容 |
| value | 自定义显示内容 |
| icon | 自定义`icon` |
| title | 自定义`title` |
| right-icon | 自定义右侧按钮,默认是`arrow`, 需要将 `is-link` 设置为 `false`, 才会生效 |
### Collapse 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### CollapseItem 外部样式类
| 类名 | 说明 |
| ------------- | ------------ |
| custom-class | 根节点样式类 |
| content-class | 内容样式类 |
================================================
FILE: packages/collapse/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-collapse": "../../collapse/index",
"van-collapse-item": "../../collapse-item/index",
"van-toast": "../../toast/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/collapse/demo/index.less
================================================
.van-icon-question {
margin-left: 5px;
font-size: 15px !important;
color: #1989fa;
vertical-align: -3px;
}
================================================
FILE: packages/collapse/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
active1: [0],
active2: 0,
active3: [],
active4: [],
title1: '标题1',
title2: '标题2',
title3: '标题3',
content1: '代码是写出来给人看的,附带能在机器上运行',
content2: '代码是写出来给人看的,附带能在机器上运行',
content3: '代码是写出来给人看的,附带能在机器上运行',
},
methods: {
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({
[key]: event.detail,
});
},
onOpen(event) {
Toast({
context: this,
message: `展开: ${event.detail}`,
});
},
onClose(event) {
Toast({
context: this,
message: `关闭: ${event.detail}`,
});
},
},
});
================================================
FILE: packages/collapse/demo/index.wxml
================================================
{{ content1 }}
{{ content2 }}
{{ content3 }}
{{ content1 }}
{{ content2 }}
{{ content3 }}
{{ content1 }}
{{ content2 }}
{{ content3 }}
{{ title1 }}
{{ content1 }}
{{ content2 }}
================================================
FILE: packages/collapse/index.json
================================================
{
"component": true
}
================================================
FILE: packages/collapse/index.less
================================================
@import '../common/style/var.less';
================================================
FILE: packages/collapse/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('collapse-item'),
props: {
value: {
type: null,
observer: 'updateExpanded',
},
accordion: {
type: Boolean,
observer: 'updateExpanded',
},
border: {
type: Boolean,
value: true,
},
},
methods: {
updateExpanded() {
this.children.forEach((child) => {
child.updateExpanded();
});
},
switch(name: string | number, expanded: boolean) {
const { accordion, value } = this.data;
const changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter(
(activeName: string | number) => activeName !== name
);
} else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
} else {
this.$emit('close', changeItem);
}
this.$emit('change', name);
this.$emit('input', name);
},
},
});
================================================
FILE: packages/collapse/index.wxml
================================================
================================================
FILE: packages/collapse/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标题1
代码是写出来给人看的,附带能在机器上运行
标题2
代码是写出来给人看的,附带能在机器上运行
标题3
代码是写出来给人看的,附带能在机器上运行
手风琴
标题1
代码是写出来给人看的,附带能在机器上运行
标题2
代码是写出来给人看的,附带能在机器上运行
标题3
代码是写出来给人看的,附带能在机器上运行
事件监听
标题1
代码是写出来给人看的,附带能在机器上运行
标题2
代码是写出来给人看的,附带能在机器上运行
标题3
代码是写出来给人看的,附带能在机器上运行
自定义标题内容
标题1
代码是写出来给人看的,附带能在机器上运行
标题2
内容
代码是写出来给人看的,附带能在机器上运行
`;
================================================
FILE: packages/collapse/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/collapse-item/animate.ts
================================================
import { getRect } from '../common/utils';
function useAnimation(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean,
height: number
) {
const animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
} else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
export function setContentAnimate(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean
) {
getRect(context, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height: number) => {
useAnimation(context, expanded, mounted, height);
});
}
================================================
FILE: packages/collapse-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: packages/collapse-item/index.less
================================================
@import '../common/style/var.less';
.van-collapse-item {
&__title {
.van-cell__right-icon {
transform: rotate(90deg);
transition: transform
var(
--collapse-item-transition-duration,
@collapse-item-transition-duration
);
}
&--expanded {
.van-cell__right-icon {
transform: rotate(-90deg);
}
}
&--disabled {
.van-cell,
.van-cell__right-icon {
color: var(
--collapse-item-title-disabled-color,
@collapse-item-title-disabled-color
) !important;
}
.van-cell--hover {
background-color: @white !important;
}
}
}
&__wrapper {
overflow: hidden;
}
&__content {
padding: var(
--collapse-item-content-padding,
@collapse-item-content-padding
);
color: var(
--collapse-item-content-text-color,
@collapse-item-content-text-color
);
font-size: var(
--collapse-item-content-font-size,
@collapse-item-content-font-size
);
line-height: var(
--collapse-item-content-line-height,
@collapse-item-content-line-height
);
background-color: var(
--collapse-item-content-background-color,
@collapse-item-content-background-color
);
}
}
================================================
FILE: packages/collapse-item/index.ts
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { setContentAnimate } from './animate';
VantComponent({
classes: ['title-class', 'content-class'],
relation: useParent('collapse'),
props: {
size: String,
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true,
},
isLink: {
type: Boolean,
value: true,
},
},
data: {
expanded: false,
parentBorder: true,
},
mounted() {
this.updateExpanded();
this.mounted = true;
},
methods: {
updateExpanded() {
if (!this.parent) {
return;
}
const { value, accordion, border } = this.parent.data;
const { children = [] } = this.parent;
const { name } = this.data;
const index = children.indexOf(this);
const currentName = name == null ? index : name;
const expanded = accordion
? value === currentName
: (value || []).some((name: string | number) => name === currentName);
if (expanded !== this.data.expanded) {
setContentAnimate(this, expanded, this.mounted);
}
this.setData({ index, expanded, parentBorder: border });
},
onClick() {
if (this.data.disabled) {
return;
}
const { name, expanded } = this.data;
const index = this.parent.children.indexOf(this);
const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
},
},
});
================================================
FILE: packages/collapse-item/index.wxml
================================================
================================================
FILE: packages/common/README.md
================================================
# 内置样式
### 介绍
Vant 中默认包含了一些常用样式,可以直接通过 className 的方式使用。
### 引入
在 app.wxss 中引入内置样式。
```css
@import '@vant/weapp/common/index.wxss';
```
## 代码演示
### 文字省略
当文本内容长度超过容器最大宽度时,自动省略多余的文本。
```xml
这是一段宽度限制 250px 的文字,后面的内容会省略。
这是一段最多显示两行的文字,后面的内容会省略。
这是一段最多显示三行的文字,后面的内容会省略。
```
### 1px 边框
为元素添加 Retina 屏幕下的 1px 边框(即 hairline),基于伪类 transform 实现。
```xml
```
### 全局字体
推荐在 app.wxss 中设置以下全局字体,以保证在不同设备上提供最佳的视觉体验。
```css
page {
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
'Segoe UI', Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
'Microsoft Yahei', sans-serif;
}
```
================================================
FILE: packages/common/color.ts
================================================
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
================================================
FILE: packages/common/component.ts
================================================
import { basic } from '../mixins/basic';
import { VantComponentOptions } from 'definitions/index';
function mapKeys(
source: Record,
target: Record,
map: Record
) {
Object.keys(map).forEach((key) => {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent<
Data extends WechatMiniprogram.Component.DataOption,
Props extends WechatMiniprogram.Component.PropertyOption,
Methods extends WechatMiniprogram.Component.MethodOption
>(vantOptions: VantComponentOptions): void {
const options: WechatMiniprogram.Component.Options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
watch: 'observers',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
destroyed: 'detached',
classes: 'externalClasses',
});
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// add relations
const { relation } = vantOptions;
if (relation) {
options.relations = relation.relations;
options.behaviors.push(relation.mixin);
}
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true,
};
Component(options);
}
export { VantComponent };
================================================
FILE: packages/common/index.less
================================================
/**
* Entry of basic styles
*/
@import './style/var.less';
@import './style/ellipsis.less';
@import './style/clearfix.less';
@import './style/hairline.less';
================================================
FILE: packages/common/relation.ts
================================================
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
type RelationOption = WechatMiniprogram.Component.RelationOption;
export function useParent(
name: string,
onEffect?: (this: TrivialInstance) => void
) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'ancestor',
linked(this: TrivialInstance) {
onEffect && onEffect.call(this);
},
linkChanged(this: TrivialInstance) {
onEffect && onEffect.call(this);
},
unlinked(this: TrivialInstance) {
onEffect && onEffect.call(this);
},
} as RelationOption,
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'parent', {
get: () => this.getRelationNodes(path)[0],
});
Object.defineProperty(this, 'index', {
// @ts-ignore
get: () => this.parent?.children?.indexOf(this),
});
},
}),
};
}
export function useChildren(
name: string,
onEffect?: (this: TrivialInstance, target: TrivialInstance) => void
) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'descendant',
linked(this: TrivialInstance, target) {
onEffect && onEffect.call(this, target);
},
linkChanged(this: TrivialInstance, target) {
onEffect && onEffect.call(this, target);
},
unlinked(this: TrivialInstance, target) {
onEffect && onEffect.call(this, target);
},
} as RelationOption,
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'children', {
get: () => this.getRelationNodes(path) || [],
});
},
}),
};
}
================================================
FILE: packages/common/style/clearfix.less
================================================
@import './mixins/clearfix.less';
.van-clearfix {
.clearfix();
}
================================================
FILE: packages/common/style/ellipsis.less
================================================
@import './mixins/ellipsis.less';
.van-ellipsis {
.ellipsis();
}
.van-multi-ellipsis--l2 {
.multi-ellipsis(2);
}
.van-multi-ellipsis--l3 {
.multi-ellipsis(3);
}
================================================
FILE: packages/common/style/hairline.less
================================================
@import './mixins/hairline.less';
.van-hairline,
.van-hairline--top,
.van-hairline--left,
.van-hairline--right,
.van-hairline--bottom,
.van-hairline--top-bottom,
.van-hairline--surround {
position: relative;
&::after {
.hairline();
}
}
.van-hairline {
&--top::after {
border-top-width: 1px;
}
&--left::after {
border-left-width: 1px;
}
&--right::after {
border-right-width: 1px;
}
&--bottom::after {
border-bottom-width: 1px;
}
&--top-bottom::after {
border-width: 1px 0;
}
&--surround::after {
border-width: 1px;
}
}
================================================
FILE: packages/common/style/mixins/clearfix.less
================================================
.clearfix() {
&::after {
display: table;
clear: both;
content: '';
}
}
================================================
FILE: packages/common/style/mixins/ellipsis.less
================================================
.multi-ellipsis(@lines) {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: @lines;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
}
.ellipsis() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
================================================
FILE: packages/common/style/mixins/hairline.less
================================================
@import '../var.less';
.hairline-common() {
position: absolute;
box-sizing: border-box;
transform-origin: center; /* cover wechat button:after default transforn-origin */
content: ' ';
pointer-events: none;
}
.hairline(@color: @border-color) {
.hairline-common();
top: -50%;
right: -50%;
bottom: -50%;
left: -50%;
border: 0 solid @color;
transform: scale(0.5);
}
.hairline-top(@color: @border-color, @left: 0, @right: 0) {
.hairline-common();
top: 0;
right: @right;
left: @left;
border-top: 1px solid @color;
transform: scaleY(0.5);
}
.hairline-bottom(@color: @border-color, @left: 0, @right: 0) {
.hairline-common();
right: @right;
bottom: 0;
left: @left;
border-bottom: 1px solid @color;
transform: scaleY(0.5);
}
================================================
FILE: packages/common/style/var.less
================================================
// Color Palette
@black: #000;
@white: #fff;
@gray-1: #f7f8fa;
@gray-2: #f2f3f5;
@gray-3: #ebedf0;
@gray-4: #dcdee0;
@gray-5: #c8c9cc;
@gray-6: #969799;
@gray-7: #646566;
@gray-8: #323233;
@red: #ee0a24;
@blue: #1989fa;
@orange: #ff976a;
@orange-dark: #ed6a0c;
@orange-light: #fffbe8;
@green: #07c160;
// Gradient Colors
@gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
// Component Colors
@text-color: @gray-8;
@active-color: @gray-2;
@active-opacity: 0.7;
@disabled-opacity: 0.5;
@background-color: @gray-1;
@background-color-light: #fafafa;
@text-link-color: #576b95;
// Padding
@padding-base: 4px;
@padding-xs: @padding-base * 2;
@padding-sm: @padding-base * 3;
@padding-md: @padding-base * 4;
@padding-lg: @padding-base * 6;
@padding-xl: @padding-base * 8;
// Font
@font-size-xs: 10px;
@font-size-sm: 12px;
@font-size-md: 14px;
@font-size-lg: 16px;
@font-weight-bold: 500;
@line-height-xs: 14px;
@line-height-sm: 18px;
@line-height-md: 20px;
@line-height-lg: 22px;
@base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
'Microsoft Yahei', sans-serif;
@price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial,
sans-serif;
// Animation
@animation-duration-base: 0.3s;
@animation-duration-fast: 0.2s;
// Border
@border-color: @gray-3;
@border-width-base: 1px;
@border-radius-sm: 2px;
@border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-max: 999px;
//ActionSheet
@action-sheet-max-height: 90%;
@action-sheet-header-height: 48px;
@action-sheet-header-font-size: @font-size-lg;
@action-sheet-description-color: @gray-6;
@action-sheet-description-font-size: @font-size-md;
@action-sheet-description-line-height: 20px;
@action-sheet-item-background: @white;
@action-sheet-item-font-size: @font-size-lg;
@action-sheet-item-line-height: 22px;
@action-sheet-item-text-color: @text-color;
@action-sheet-item-disabled-text-color: @gray-5;
@action-sheet-subname-color: @gray-6;
@action-sheet-subname-font-size: @font-size-sm;
@action-sheet-subname-line-height: 20px;
@action-sheet-close-icon-size: 22px;
@action-sheet-close-icon-color: @gray-5;
@action-sheet-close-icon-padding: 0 @padding-md;
@action-sheet-cancel-text-color: @gray-7;
@action-sheet-cancel-padding-top: @padding-xs;
@action-sheet-cancel-padding-color: @background-color;
// Button
@button-mini-height: 22px;
@button-mini-min-width: 50px;
@button-mini-font-size: @font-size-xs;
@button-small-height: 30px;
@button-small-font-size: @font-size-sm;
@button-small-min-width: 60px;
@button-normal-font-size: @font-size-md;
@button-large-height: 50px;
@button-default-color: @text-color;
@button-default-height: 44px;
@button-default-font-size: @font-size-lg;
@button-default-background-color: @white;
@button-default-border-color: @border-color;
@button-primary-color: @white;
@button-primary-background-color: @green;
@button-primary-border-color: @green;
@button-info-color: @white;
@button-info-background-color: @blue;
@button-info-border-color: @blue;
@button-danger-color: @white;
@button-danger-background-color: @red;
@button-danger-border-color: @red;
@button-warning-color: @white;
@button-warning-background-color: @orange;
@button-warning-border-color: @orange;
@button-line-height: 20px;
@button-border-width: 1px;
@button-border-radius: @border-radius-sm;
@button-round-border-radius: @border-radius-max;
@button-plain-background-color: @white;
@button-disabled-opacity: @disabled-opacity;
// Calendar
@calendar-height: 100%;
@calendar-background-color: @white;
@calendar-popup-height: 90%;
@calendar-header-box-shadow: 0 2px 10px rgba(125, 126, 128, 0.16);
@calendar-header-title-height: 44px;
@calendar-header-title-font-size: @font-size-lg;
@calendar-header-subtitle-font-size: @font-size-md;
@calendar-weekdays-height: 30px;
@calendar-weekdays-font-size: @font-size-sm;
@calendar-month-title-font-size: @font-size-md;
@calendar-month-mark-color: fade(@gray-2, 80%);
@calendar-month-mark-font-size: 160px;
@calendar-day-height: 64px;
@calendar-day-font-size: @font-size-lg;
@calendar-range-edge-color: @white;
@calendar-range-edge-background-color: @red;
@calendar-range-middle-color: @red;
@calendar-range-middle-background-opacity: 0.1;
@calendar-selected-day-size: 54px;
@calendar-selected-day-color: @white;
@calendar-info-font-size: @font-size-xs;
@calendar-info-line-height: 14px;
@calendar-selected-day-background-color: @red;
@calendar-day-disabled-color: @gray-5;
@calendar-confirm-button-height: 36px;
@calendar-confirm-button-margin: 7px 0;
@calendar-confirm-button-line-height: 34px;
// Card
@card-padding: @padding-xs @padding-md;
@card-font-size: @font-size-sm;
@card-text-color: @text-color;
@card-background-color: @background-color-light;
@card-thumb-size: 88px;
@card-title-line-height: 16px;
@card-desc-color: @gray-7;
@card-desc-line-height: 20px;
@card-price-color: @red;
@card-origin-price-color: @gray-7;
@card-origin-price-font-size: @font-size-xs;
@card-price-font-size: @font-size-sm;
@card-price-integer-font-size: @font-size-lg;
@card-price-font-family: @price-integer-font-family;
// Cell
@cell-font-size: @font-size-md;
@cell-line-height: 24px;
@cell-vertical-padding: 10px;
@cell-horizontal-padding: @padding-md;
@cell-text-color: @text-color;
@cell-background-color: @white;
@cell-border-color: @border-color;
@cell-active-color: @active-color;
@cell-required-color: @red;
@cell-label-color: @gray-6;
@cell-label-font-size: @font-size-sm;
@cell-label-line-height: 18px;
@cell-label-margin-top: 3px;
@cell-value-color: @gray-6;
@cell-icon-size: 16px;
@cell-right-icon-color: @gray-6;
@cell-large-vertical-padding: @padding-sm;
@cell-large-title-font-size: @font-size-lg;
@cell-large-value-font-size: @font-size-lg;
@cell-large-label-font-size: @font-size-md;
// CellGroup
@cell-group-background-color: @white;
@cell-group-title-color: @gray-6;
@cell-group-title-padding: @padding-md @padding-md @padding-xs;
@cell-group-title-font-size: @font-size-md;
@cell-group-title-line-height: 16px;
@cell-group-inset-padding: 0 @padding-md;
@cell-group-inset-border-radius: @border-radius-lg;
@cell-group-inset-title-padding: @padding-md @padding-md @padding-xs @padding-xl;
// Checkbox
@checkbox-size: 20px;
@checkbox-border-color: @gray-5;
@checkbox-transition-duration: 0.2s;
@checkbox-label-margin: 10px;
@checkbox-label-color: @text-color;
@checkbox-checked-icon-color: @blue;
@checkbox-disabled-icon-color: @gray-5;
@checkbox-disabled-label-color: @gray-5;
@checkbox-disabled-background-color: @border-color;
// Circle
@circle-text-color: @text-color;
// Collapse
@collapse-item-transition-duration: 0.3s;
@collapse-item-content-padding: 15px;
@collapse-item-content-font-size: 13px;
@collapse-item-content-line-height: 1.5;
@collapse-item-content-text-color: @gray-6;
@collapse-item-content-background-color: @white;
@collapse-item-title-disabled-color: @gray-5;
// CountDown
@count-down-text-color: @text-color;
@count-down-font-size: @font-size-md;
@count-down-line-height: 20px;
// Dialog
@dialog-width: 320px;
@dialog-small-screen-width: 90%;
@dialog-font-size: @font-size-lg;
@dialog-border-radius: 16px;
@dialog-background-color: @white;
@dialog-header-font-weight: @font-weight-bold;
@dialog-header-line-height: 24px;
@dialog-header-padding-top: @padding-lg;
@dialog-header-isolated-padding: @padding-lg 0;
@dialog-message-padding: @padding-lg;
@dialog-message-font-size: @font-size-md;
@dialog-message-line-height: 20px;
@dialog-message-max-height: 60vh;
@dialog-has-title-message-text-color: @gray-7;
@dialog-has-title-message-padding-top: @padding-xs;
// Field
@field-label-color: @gray-7;
@field-input-text-color: @text-color;
@field-input-error-text-color: @red;
@field-input-disabled-text-color: @gray-5;
@field-placeholder-text-color: @gray-5;
@field-icon-size: 16px;
@field-clear-icon-size: 16px;
@field-clear-icon-color: @gray-5;
@field-icon-container-color: @gray-6;
@field-error-message-color: @red;
@field-error-message-text-font-size: @font-size-sm;
@field-text-area-min-height: 18px;
@field-word-limit-color: @gray-7;
@field-word-limit-font-size: @font-size-sm;
@field-word-limit-line-height: 16px;
@field-word-num-full-color: @red;
@field-disabled-text-color: @gray-5;
// GoodsAction
@goods-action-background-color: @white;
@goods-action-height: 50px;
@goods-action-icon-width: 48px;
@goods-action-icon-height: @goods-action-height;
@goods-action-icon-color: @text-color;
@goods-action-icon-size: 18px;
@goods-action-icon-font-size: @font-size-xs;
@goods-action-icon-text-color: @gray-7;
@goods-action-button-height: 40px;
@goods-action-button-line-height: @button-line-height;
@goods-action-button-border-radius: @border-radius-max;
@goods-action-button-warning-color: @gradient-orange;
@goods-action-button-danger-color: @gradient-red;
@goods-action-button-plain-color: @white;
// Image
@image-placeholder-text-color: @gray-6;
@image-placeholder-font-size: @font-size-md;
@image-placeholder-background-color: @background-color;
@image-loading-icon-size: 32px;
@image-loading-icon-color: @gray-4;
@image-error-icon-size: 32px;
@image-error-icon-color: @gray-4;
// Info
@info-size: 16px;
@info-color: @white;
@info-padding: 0 3px;
@info-font-size: 12px;
@info-font-weight: 500;
@info-border-width: 1px;
@info-background-color: @red;
@info-dot-color: @red;
@info-dot-size: 8px;
@info-font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
// Loading
@loading-text-color: @gray-6;
@loading-text-font-size: @font-size-md;
@loading-text-line-height: 20px;
@loading-spinner-color: @gray-5;
@loading-spinner-size: 30px;
@loading-spinner-animation-duration: 0.8s;
// NavBar
@nav-bar-height: 46px;
@nav-bar-background-color: @white;
@nav-bar-arrow-size: 16px;
@nav-bar-icon-color: @blue;
@nav-bar-text-color: @blue;
@nav-bar-title-font-size: @font-size-lg;
@nav-bar-title-text-color: @text-color;
// NoticeBar
@notice-bar-height: 40px;
@notice-bar-padding: 0 @padding-md;
@notice-bar-wrapable-padding: @padding-xs @padding-md;
@notice-bar-font-size: @font-size-md;
@notice-bar-text-color: @orange-dark;
@notice-bar-line-height: 24px;
@notice-bar-background-color: @orange-light;
@notice-bar-icon-size: 16px;
@notice-bar-icon-min-width: 22px;
// Notify
@notify-padding: 6px 15px;
@notify-font-size: 14px;
@notify-line-height: 20px;
@notify-primary-background-color: @blue;
@notify-success-background-color: @green;
@notify-danger-background-color: @red;
@notify-warning-background-color: @orange;
// Overlay
@overlay-background-color: rgba(0, 0, 0, 0.7);
// Panel
@panel-background-color: @white;
@panel-header-value-color: @red;
@panel-footer-padding: @padding-xs @padding-md;
// Picker
@picker-background-color: @white;
@picker-toolbar-height: 44px;
@picker-title-font-size: @font-size-lg;
@picker-action-padding: 0 @padding-md;
@picker-action-font-size: @font-size-md;
@picker-confirm-action-color: @text-link-color;
@picker-cancel-action-color: @gray-6;
@picker-option-font-size: @font-size-lg;
@picker-option-text-color: @black;
@picker-loading-icon-color: @blue;
@picker-loading-mask-color: rgba(255, 255, 255, 0.9);
@picker-option-disabled-opacity: 0.3;
@picker-option-selected-text-color: @text-color;
// Popup
@popup-background-color: @white;
@popup-round-border-radius: 16px;
@popup-close-icon-size: 18px;
@popup-close-icon-color: @gray-6;
@popup-close-icon-margin: 16px;
@popup-close-icon-z-index: 1;
// Progress
@progress-height: 4px;
@progress-background-color: @gray-3;
@progress-pivot-padding: 0 5px;
@progress-color: @blue;
@progress-pivot-font-size: @font-size-xs;
@progress-pivot-line-height: 1.6;
@progress-pivot-background-color: @blue;
@progress-pivot-text-color: @white;
// Radio
@radio-size: 20px;
@radio-border-color: @gray-5;
@radio-transition-duration: 0.2s;
@radio-label-margin: 10px;
@radio-label-color: @text-color;
@radio-checked-icon-color: @blue;
@radio-disabled-icon-color: @gray-5;
@radio-disabled-label-color: @gray-5;
@radio-disabled-background-color: @border-color;
// Rate
@rate-horizontal-padding: 2px;
@rate-icon-size: 20px;
@rate-icon-void-color: @gray-5;
@rate-icon-full-color: @red;
@rate-icon-disabled-color: @gray-5;
@rate-icon-gutter: @padding-base;
// Switch
@switch-width: 2em;
@switch-height: 1em;
@switch-node-size: 1em;
@switch-node-z-index: 1;
@switch-node-background-color: @white;
@switch-node-box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05),
0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
@switch-background-color: @white;
@switch-on-background-color: @blue;
@switch-transition-duration: 0.3s;
@switch-disabled-opacity: 0.4;
@switch-border: 1px solid rgba(0, 0, 0, 0.1);
// ShareSheet
@share-sheet-header-padding: @padding-sm @padding-md @padding-base;
@share-sheet-title-color: @text-color;
@share-sheet-title-font-size: @font-size-md;
@share-sheet-title-line-height: @line-height-md;
@share-sheet-description-color: @gray-6;
@share-sheet-description-font-size: @font-size-sm;
@share-sheet-description-line-height: 16px;
@share-sheet-icon-size: 48px;
@share-sheet-option-name-color: @gray-7;
@share-sheet-option-name-font-size: @font-size-sm;
@share-sheet-option-description-color: @gray-5;
@share-sheet-option-description-font-size: @font-size-sm;
@share-sheet-cancel-button-font-size: @font-size-lg;
@share-sheet-cancel-button-height: 48px;
@share-sheet-cancel-button-background: @white;
// Search
@search-background-color: @gray-1;
@search-padding: 10px @padding-sm;
@search-input-height: 34px;
@search-label-padding: 0 5px;
@search-label-color: @text-color;
@search-label-font-size: @font-size-md;
@search-left-icon-color: @gray-6;
@search-action-padding: 0 @padding-xs;
@search-action-text-color: @text-color;
@search-action-font-size: @font-size-md;
// Sidebar
@sidebar-width: 80px;
// SidebarItem
@sidebar-font-size: @font-size-md;
@sidebar-line-height: 20px;
@sidebar-text-color: @text-color;
@sidebar-disabled-text-color: @gray-5;
@sidebar-padding: 20px @padding-sm 20px @padding-xs;
@sidebar-active-color: @active-color;
@sidebar-background-color: @background-color;
@sidebar-selected-font-weight: @font-weight-bold;
@sidebar-selected-text-color: @text-color;
@sidebar-selected-border-color: @red;
@sidebar-selected-background-color: @white;
// Slider
@slider-active-background-color: @blue;
@slider-inactive-background-color: @gray-3;
@slider-disabled-opacity: @disabled-opacity;
@slider-bar-height: 2px;
@slider-button-width: 24px;
@slider-button-height: 24px;
@slider-button-border-radius: 50%;
@slider-button-background-color: @white;
@slider-button-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
// Step
@step-text-color: @gray-6;
@step-process-text-color: @text-color;
@step-font-size: @font-size-md;
@step-line-color: @border-color;
@step-finish-line-color: @green;
@step-finish-text-color: @text-color;
@step-icon-size: 12px;
@step-circle-size: 5px;
@step-circle-color: @gray-6;
@step-horizontal-title-font-size: @font-size-sm;
// Steps
@steps-background-color: @white;
// Stepper
@stepper-active-color: #e8e8e8;
@stepper-background-color: @active-color;
@stepper-button-icon-color: @text-color;
@stepper-button-disabled-color: @background-color;
@stepper-button-disabled-icon-color: @gray-5;
@stepper-button-round-theme-color: @red;
@stepper-input-width: 32px;
@stepper-input-height: 28px;
@stepper-input-font-size: @font-size-md;
@stepper-input-line-height: normal;
@stepper-input-text-color: @text-color;
@stepper-input-disabled-text-color: @gray-5;
@stepper-input-disabled-background-color: @active-color;
@stepper-border-radius: @border-radius-md;
// SubmitBar
@submit-bar-height: 50px;
@submit-bar-z-index: 100;
@submit-bar-background-color: @white;
@submit-bar-button-width: 110px;
@submit-bar-price-color: @red;
@submit-bar-price-font-size: @font-size-sm;
@submit-bar-currency-font-size: @font-size-sm;
@submit-bar-text-color: @text-color;
@submit-bar-text-font-size: 14px;
@submit-bar-tip-padding: 10px;
@submit-bar-tip-font-size: 12px;
@submit-bar-tip-line-height: 1.5;
@submit-bar-tip-color: #f56723;
@submit-bar-tip-background-color: #fff7cc;
@submit-bar-tip-icon-size: 12px;
@submit-bar-button-height: 40px;
@submit-bar-padding: 0 @padding-md;
@submit-bar-price-integer-font-size: 20px;
@submit-bar-price-font-family: @price-integer-font-family;
// Tabbar
@tabbar-height: 50px;
@tabbar-background-color: @white;
// TabbarItem
@tabbar-item-font-size: @font-size-sm;
@tabbar-item-text-color: @gray-7;
@tabbar-item-active-color: @blue;
@tabbar-item-line-height: 1;
@tabbar-item-icon-size: 22px;
@tabbar-item-margin-bottom: 4px;
// Tab
@tab-text-color: @gray-7;
@tab-active-text-color: @text-color;
@tab-disabled-text-color: @gray-5;
@tab-font-size: @font-size-md;
// Tabs
@tabs-default-color: @red;
@tabs-line-height: 44px;
@tabs-card-height: 30px;
@tabs-nav-background-color: @white;
@tabs-bottom-bar-height: 3px;
@tabs-bottom-bar-color: @tabs-default-color;
// Tag
@tag-padding: 0 @padding-base;
@tag-text-color: @white;
@tag-font-size: @font-size-sm;
@tag-border-radius: 2px;
@tag-line-height: 16px;
@tag-medium-padding: 2px 6px;
@tag-large-padding: @padding-base @padding-xs;
@tag-large-border-radius: @border-radius-md;
@tag-large-font-size: @font-size-md;
@tag-round-border-radius: @border-radius-max;
@tag-danger-color: @red;
@tag-primary-color: @blue;
@tag-success-color: @green;
@tag-warning-color: @orange;
@tag-default-color: @gray-6;
@tag-plain-background-color: @white;
// Toast
@toast-max-width: 70%;
@toast-font-size: 14px;
@toast-text-color: @white;
@toast-line-height: 20px;
@toast-border-radius: @border-radius-lg;
@toast-background-color: fade(@black, 70%);
@toast-icon-size: 36px;
@toast-text-min-width: 96px;
@toast-text-padding: @padding-xs @padding-sm;
@toast-default-padding: @padding-md;
@toast-default-width: 88px;
@toast-default-min-height: 88px;
// GridItem
@grid-item-content-padding: @padding-md @padding-xs;
@grid-item-content-background-color: @white;
@grid-item-content-active-color: @active-color;
@grid-item-icon-size: 26px;
@grid-item-text-color: @gray-7;
@grid-item-text-font-size: @font-size-sm;
// Divider
@divider-margin: @padding-md 0;
@divider-text-color: @gray-6;
@divider-font-size: @font-size-md;
@divider-line-height: 24px;
@divider-border-color: @border-color;
@divider-content-padding: @padding-md;
@divider-content-left-width: 10%;
@divider-content-right-width: 10%;
// Empty
@empty-padding: @padding-xl 0;
@empty-image-size: 160px;
@empty-description-margin-top: @padding-md;
@empty-description-padding: 0 60px;
@empty-description-color: @gray-6;
@empty-description-font-size: 14px;
@empty-description-line-height: 20px;
@empty-bottom-margin-top: 24px;
// TreeSelect
@tree-select-font-size: @font-size-md;
@tree-select-nav-background-color: @background-color;
@tree-select-content-background-color: @white;
@tree-select-nav-item-padding: @padding-sm @padding-xs @padding-sm @padding-sm;
@tree-select-item-height: 44px;
@tree-select-item-active-color: @red;
@tree-select-item-disabled-color: @gray-5;
// Uploader
@uploader-size: 80px;
@uploader-icon-size: 24px;
@uploader-icon-color: @gray-4;
@uploader-text-color: @gray-6;
@uploader-text-font-size: @font-size-sm;
@uploader-upload-background-color: @gray-1;
@uploader-upload-active-color: @active-color;
@uploader-delete-color: @white;
@uploader-delete-icon-size: 14px;
@uploader-delete-background-color: rgba(0, 0, 0, 0.7);
@uploader-file-background-color: @background-color;
@uploader-file-icon-size: 20px;
@uploader-file-icon-color: @gray-7;
@uploader-file-name-padding: 0 @padding-base;
@uploader-file-name-margin-top: @padding-xs;
@uploader-file-name-font-size: @font-size-sm;
@uploader-file-name-text-color: @gray-7;
@uploader-mask-background-color: fade(@gray-8, 88%);
@uploader-mask-icon-size: 22px;
@uploader-mask-message-font-size: @font-size-sm;
@uploader-mask-message-line-height: 14px;
@uploader-loading-icon-size: 22px;
@uploader-loading-icon-color: @white;
@uploader-disabled-opacity: @disabled-opacity;
// DropdownMenu
@dropdown-menu-height: 50px;
@dropdown-menu-background-color: @white;
@dropdown-menu-title-font-size: 15px;
@dropdown-menu-title-text-color: @text-color;
@dropdown-menu-title-active-text-color: @red;
@dropdown-menu-title-disabled-text-color: @gray-6;
@dropdown-menu-title-padding: 0 @padding-lg 0 @padding-xs;
@dropdown-menu-title-line-height: 18px;
@dropdown-menu-option-active-color: @red;
@dropdown-menu-box-shadow: 0 2px 12px fade(@gray-7, 12);
// IndexAnchor
@index-anchor-padding: 0 @padding-md;
@index-anchor-text-color: @text-color;
@index-anchor-font-weight: 500;
@index-anchor-font-size: @font-size-md;
@index-anchor-line-height: 32px;
@index-anchor-background-color: transparent;
@index-anchor-active-background-color: @white;
@index-anchor-active-text-color: @green;
// IndexBar
@index-bar-index-font-size: @font-size-xs;
@index-bar-index-line-height: 14px;
// skeleton
@skeleton-padding: 0 @padding-md;
@skeleton-row-height: 16px;
@skeleton-row-background-color: @gray-2;
@skeleton-row-margin-top: @padding-sm;
@skeleton-avatar-background-color: @gray-2;
@skeleton-animation-duration: 1.2s;
// Cascader
@cascader-header-height: 48px;
@cascader-header-padding: 0 16px;
@cascader-title-font-size: 16px;
@cascader-title-line-height: 20px;
@cascader-close-icon-size: 22px;
@cascader-close-icon-color: #c8c9cc;
@cascader-selected-icon-size: 18px;
@cascader-tabs-height: 48px;
@cascader-active-color: @blue;
@cascader-options-height: 384px;
@cascader-option-disabled-color: #c8c9cc;
@cascader-tab-color: #323233;
@cascader-unselected-tab-color: #969799;
================================================
FILE: packages/common/utils.ts
================================================
import { isDef, isNumber, isPlainObject, isPromise } from './validator';
import {
canIUseGroupSetData,
canIUseNextTick,
getSystemInfoSync,
} from './version';
export { isDef } from './validator';
export { getSystemInfoSync } from './version';
export function range(num: number, min: number, max: number) {
return Math.min(Math.max(num, min), max);
}
export function nextTick(cb: (...args: any[]) => void) {
if (canIUseNextTick()) {
wx.nextTick(cb);
} else {
setTimeout(() => {
cb();
}, 1000 / 30);
}
}
export function addUnit(value?: string | number): string | undefined {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
export function requestAnimationFrame(cb: () => void) {
return setTimeout(() => {
cb();
}, 1000 / 30);
}
export function pickExclude(obj: unknown, keys: string[]) {
if (!isPlainObject(obj)) {
return {};
}
return Object.keys(obj).reduce((prev, key) => {
if (!keys.includes(key)) {
prev[key] = obj[key];
}
return prev;
}, {});
}
export function getRect(
context: WechatMiniprogram.Component.TrivialInstance,
selector: string
) {
return new Promise(
(resolve) => {
wx.createSelectorQuery()
.in(context)
.select(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
}
);
}
export function getAllRect(
context: WechatMiniprogram.Component.TrivialInstance,
selector: string
) {
return new Promise(
(resolve) => {
wx.createSelectorQuery()
.in(context)
.selectAll(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
}
);
}
export function groupSetData(
context: WechatMiniprogram.Component.TrivialInstance,
cb: () => void
) {
if (canIUseGroupSetData()) {
context.groupSetData(cb);
} else {
cb();
}
}
export function toPromise(promiseLike: Promise | unknown) {
if (isPromise(promiseLike)) {
return promiseLike;
}
return Promise.resolve(promiseLike);
}
// 浮点数精度处理
export function addNumber(num1, num2) {
const cardinal = 10 ** 10;
return Math.round((num1 + num2) * cardinal) / cardinal;
}
// 限制value在[min, max]之间
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
export function getCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1] as T & WechatMiniprogram.Page.TrivialInstance;
}
export const isPC = ['mac', 'windows'].includes(getSystemInfoSync().platform);
// 是否企业微信
export const isWxWork = getSystemInfoSync().environment === 'wxwork';
================================================
FILE: packages/common/validator.ts
================================================
// eslint-disable-next-line @typescript-eslint/ban-types
export function isFunction(val: unknown): val is Function {
return typeof val === 'function';
}
export function isPlainObject(val: unknown): val is Record {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
export function isPromise(val: unknown): val is Promise {
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
}
export function isDef(value: unknown): boolean {
return value !== undefined && value !== null;
}
export function isObj(x: unknown): x is Record {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
export function isNumber(value: string) {
return /^\d+(\.\d+)?$/.test(value);
}
export function isBoolean(value: unknown): value is boolean {
return typeof value === 'boolean';
}
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
export function isImageUrl(url: string): boolean {
return IMAGE_REGEXP.test(url);
}
export function isVideoUrl(url: string): boolean {
return VIDEO_REGEXP.test(url);
}
================================================
FILE: packages/common/version.ts
================================================
interface WxWorkSystemInfo extends WechatMiniprogram.SystemInfo {
environment?: 'wxwork';
}
interface SystemInfo extends WxWorkSystemInfo, WechatMiniprogram.SystemInfo {}
let systemInfo: SystemInfo;
export function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo as SystemInfo;
}
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
function gte(version: string) {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, version) >= 0;
}
export function canIUseModel() {
return gte('2.9.3');
}
export function canIUseFormFieldButton() {
return gte('2.10.3');
}
export function canIUseAnimate() {
return gte('2.9.0');
}
export function canIUseGroupSetData() {
return gte('2.4.0');
}
export function canIUseNextTick() {
try {
return wx.canIUse('nextTick');
} catch (e) {
return gte('2.7.1');
}
}
export function canIUseCanvas2d() {
return gte('2.9.0');
}
export function canIUseGetUserProfile() {
return !!wx.getUserProfile;
}
================================================
FILE: packages/config-provider/README.md
================================================
# ConfigProvider 全局配置
### 介绍
用于配置 Vant Weapp 组件的主题样式,从 `v1.7.0` 版本开始支持。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-config-provider": "@vant/weapp/config-provider/index"
}
```
## 定制主题
### 介绍
Vant Weapp 组件通过丰富的 [CSS 变量](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties) 来组织样式,通过覆盖这些 CSS 变量,可以实现**定制主题、动态切换主题**等效果。
#### 示例
以 Button 组件为例,查看组件的样式,可以看到 `.van-button--primary` 类名上存在以下变量:
```css
.van-button--primary {
color: var(--button-primary-color, #fff);
background: var(--button-primary-background-color, #07c160);
border: var(--button-border-width, 1px) solid var(
--button-primary-border-color,
#07c160
);
}
```
### 自定义 CSS 变量
#### 通过 CSS 覆盖
你可以直接在代码中覆盖这些 CSS 变量,Button 组件的样式会随之发生改变:
```css
/* 添加这段样式后,Primary Button 会变成红色 */
page {
--button-primary-background-color: red;
}
```
#### 通过 ConfigProvider 覆盖
`ConfigProvider` 组件提供了覆盖 CSS 变量的能力,你需要在根节点包裹一个 `ConfigProvider` 组件,并通过 `theme-vars` 属性来配置一些主题变量。
```html
提交
```
```js
import Page from '../../common/page';
Page({
data: {
rate: 4,
slider: 50,
themeVars: {
rateIconFullColor: '#07c160',
sliderBarHeight: '4px',
sliderButtonWidth: '20px',
sliderButtonHeight: '20px',
sliderActiveBackgroundColor: '#07c160',
buttonPrimaryBorderColor: '#07c160',
buttonPrimaryBackgroundColor: '#07c160',
},
},
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({
[key]: event.detail,
});
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ---------- | -------------- | -------- | ------ |
| theme-vars | 自定义主题变量 | _object_ | - |
================================================
FILE: packages/config-provider/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-rate": "../../rate/index",
"van-field": "../../field/index",
"van-slider": "../../slider/index",
"van-button": "../../button/index",
"van-cell-group": "../../cell-group/index",
"van-config-provider": "../../config-provider/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/config-provider/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
rate: 4,
slider: 50,
themeVars: {
rateIconFullColor: '#07c160',
sliderBarHeight: '4px',
sliderButtonWidth: '20px',
sliderButtonHeight: '20px',
sliderActiveBackgroundColor: '#07c160',
buttonPrimaryBorderColor: '#07c160',
buttonPrimaryBackgroundColor: '#07c160',
},
},
methods: {
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({
[key]: event.detail,
});
},
},
});
================================================
FILE: packages/config-provider/demo/index.wxml
================================================
提交
提交
================================================
FILE: packages/config-provider/index.json
================================================
{
"component": true
}
================================================
FILE: packages/config-provider/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
themeVars: {
type: Object,
value: {},
},
},
});
================================================
FILE: packages/config-provider/index.wxml
================================================
================================================
FILE: packages/config-provider/index.wxs
================================================
/* eslint-disable */
var object = require('../wxs/object.wxs');
var style = require('../wxs/style.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
.replace(getRegExp("^-"), '');
return newWord;
}
function mapThemeVarsToCSSVars(themeVars) {
var cssVars = {};
object.keys(themeVars).forEach(function (key) {
var cssVarsKey = '--' + kebabCase(key);
cssVars[cssVarsKey] = themeVars[key];
});
return style(cssVars);
}
module.exports = {
kebabCase: kebabCase,
mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
};
================================================
FILE: packages/config-provider/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
默认主题
评分
滑块
提交
定制主题
评分
滑块
提交
`;
================================================
FILE: packages/config-provider/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/count-down/README.md
================================================
# CountDown 倒计时
### 介绍
用于实时展示倒计时数值,支持毫秒精度。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-count-down": "@vant/weapp/count-down/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)。
## 代码演示
### 基本用法
`time`属性表示倒计时总时长,单位为毫秒。
```html
```
```js
Page({
data: {
time: 30 * 60 * 60 * 1000,
},
});
```
### 自定义格式
通过`format`属性设置倒计时文本的内容。
```html
```
### 毫秒级渲染
倒计时默认每秒渲染一次,设置`millisecond`属性可以开启毫秒级渲染。
```html
```
### 自定义样式
设置`use-slot`属性后可以自定义倒计时样式,需要通过`bind:change`事件获取`timeData`对象并自行渲染,格式见下方表格。
```html
{{ timeData.hours }}
{{ timeData.minutes }}
{{ timeData.seconds }}
```
```js
Page({
data: {
time: 30 * 60 * 60 * 1000,
timeData: {},
},
onChange(e) {
this.setData({
timeData: e.detail,
});
},
});
```
```css
.item {
display: inline-block;
width: 22px;
margin-right: 5px;
color: #fff;
font-size: 12px;
text-align: center;
background-color: #1989fa;
border-radius: 2px;
}
```
### 手动控制
通过 `selectComponent` 选择器获取到组件实例后,可以调用`start`、`pause`、`reset`方法。
```html
```
```js
Page({
start() {
const countDown = this.selectComponent('.control-count-down');
countDown.start();
},
pause() {
const countDown = this.selectComponent('.control-count-down');
countDown.pause();
},
reset() {
const countDown = this.selectComponent('.control-count-down');
countDown.reset();
},
finished() {
Toast('倒计时结束');
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| time | 倒计时时长,单位毫秒 | _number_ | - |
| format | 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 | _string_ | `HH:mm:ss` |
| auto-start | 是否自动开始倒计时 | _boolean_ | `true` |
| millisecond | 是否开启毫秒级渲染 | _boolean_ | `false` |
| use-slot | 是否使用自定义样式插槽 | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 回调参数 |
| ------ | -------------------------------------------- | -------- |
| bind:finish | 倒计时结束时触发 | - |
| bind:change | 时间变化时触发,仅在开启`use-slot`后才会触发 | timeData |
### timeData 格式
| 名称 | 说明 | 类型 |
| ------------ | -------- | -------- |
| days | 剩余天数 | _number_ |
| hours | 剩余小时 | _number_ |
| minutes | 剩余分钟 | _number_ |
| seconds | 剩余秒数 | _number_ |
| milliseconds | 剩余毫秒 | _number_ |
### 方法
通过 selectComponent 可以获取到 CountDown 实例并调用实例方法。
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| start | - | - | 开始倒计时 |
| pause | - | - | 暂停倒计时 |
| reset | - | - | 重设倒计时,若`auto-start`为`true`,重设后会自动开始倒计时 |
================================================
FILE: packages/count-down/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-grid": "../../grid/index",
"van-toast": "../../toast/index",
"van-grid-item": "../../grid-item/index",
"van-count-down": "../../count-down/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/count-down/demo/index.less
================================================
.van-count-down {
margin: 0 16px 10px;
}
.item {
display: inline-block;
width: 22px;
margin-right: 5px;
color: #fff;
font-size: 12px;
text-align: center;
background-color: #1989fa;
border-radius: 2px;
}
================================================
FILE: packages/count-down/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
time: 30 * 60 * 60 * 1000,
timeData: {},
},
methods: {
onChange(e) {
this.setData({
timeData: e.detail,
});
},
start() {
const countDown = this.selectComponent('.control-count-down');
countDown.start();
},
pause() {
const countDown = this.selectComponent('.control-count-down');
countDown.pause();
},
reset() {
const countDown = this.selectComponent('.control-count-down');
countDown.reset();
},
finished() {
Toast({
context: this,
message: '倒计时结束',
});
},
},
});
================================================
FILE: packages/count-down/demo/index.wxml
================================================
{{ timeData.hours }}
{{ timeData.minutes }}
{{ timeData.seconds }}
================================================
FILE: packages/count-down/index.json
================================================
{
"component": true
}
================================================
FILE: packages/count-down/index.less
================================================
@import '../common/style/var.less';
.van-count-down {
color: var(--count-down-text-color, @count-down-text-color);
font-size: var(--count-down-font-size, @count-down-font-size);
line-height: var(--count-down-line-height, @count-down-line-height);
}
================================================
FILE: packages/count-down/index.ts
================================================
import { VantComponent } from '../common/component';
import { isSameSecond, parseFormat, parseTimeData } from './utils';
function simpleTick(fn: WechatMiniprogram.SetTimeoutCompleteCallback) {
return setTimeout(fn, 30);
}
VantComponent({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset',
},
format: {
type: String,
value: 'HH:mm:ss',
},
autoStart: {
type: Boolean,
value: true,
},
},
data: {
timeData: parseTimeData(0),
formattedTime: '0',
},
destroyed() {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start() {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause() {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset() {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick() {
if (this.data.millisecond) {
this.microTick();
} else {
this.macroTick();
}
},
microTick() {
this.tid = simpleTick(() => {
this.setRemain(this.getRemain());
if (this.remain !== 0) {
this.microTick();
}
});
},
macroTick() {
this.tid = simpleTick(() => {
const remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain !== 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
const timeData = parseTimeData(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: parseFormat(this.data.format, timeData),
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
},
});
================================================
FILE: packages/count-down/index.wxml
================================================
{{ formattedTime }}
================================================
FILE: packages/count-down/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
30:00:00
自定义格式
01 天 06 时 00 分 00 秒
毫秒级渲染
30:00:00:000
自定义样式
手动控制
03:000
开始
暂停
重置
`;
================================================
FILE: packages/count-down/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/count-down/utils.ts
================================================
function padZero(num: number | string, targetLength = 2): string {
let str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
export type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
export function parseTimeData(time: number): TimeData {
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
days,
hours,
minutes,
seconds,
milliseconds,
};
}
export function parseFormat(format: string, timeData: TimeData): string {
const { days } = timeData;
let { hours, minutes, seconds, milliseconds } = timeData;
if (format.indexOf('DD') === -1) {
hours += days * 24;
} else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
} else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
} else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
} else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
export function isSameSecond(time1: number, time2: number): boolean {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
================================================
FILE: packages/datetime-picker/README.md
================================================
# DatetimePicker 时间选择
### 介绍
用于选择时间,支持日期、时分等时间维度,通常与 [弹出层](#/popup) 组件配合使用。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-datetime-picker": "@vant/weapp/datetime-picker/index"
}
```
## 代码演示
### 选择完整时间
`value` 为时间戳。
```html
```
```javascript
Page({
data: {
minHour: 10,
maxHour: 20,
minDate: new Date().getTime(),
maxDate: new Date(2019, 10, 1).getTime(),
currentDate: new Date().getTime(),
},
onInput(event) {
this.setData({
currentDate: event.detail,
});
},
});
```
### 选择日期(年月日)
`value` 为时间戳,通过传入 `formatter` 函数对选项文字进行处理。
```html
```
```js
Page({
data: {
currentDate: new Date().getTime(),
minDate: new Date().getTime(),
formatter(type, value) {
if (type === 'year') {
return `${value}年`;
}
if (type === 'month') {
return `${value}月`;
}
return value;
},
},
onInput(event) {
this.setData({
currentDate: event.detail,
});
},
});
```
### 选择日期(年月)
`value` 为时间戳。
```html
```
```js
Page({
data: {
currentDate: new Date().getTime(),
minDate: new Date().getTime(),
},
onInput(event) {
this.setData({
currentDate: event.detail,
});
},
});
```
### 选择时间
`value` 为字符串。
```html
```
```js
Page({
data: {
currentDate: '12:00',
minHour: 10,
maxHour: 20,
},
onInput(event) {
this.setData({
currentDate: event.detail,
});
},
});
```
### 选项过滤器
通过传入 `filter` 函数,可以对选项数组进行过滤,实现自定义时间间隔。
```html
```
```js
Page({
data: {
currentDate: '12:00',
filter(type, options) {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前选中值 | _string \| number_ | - |
| type | 类型,可选值为 `date` `time` `year-month`
不建议动态修改 | _string_ | `datetime` |
| min-date | 可选的最小时间,精确到分钟 | _number_ | 十年前 |
| max-date | 可选的最大时间,精确到分钟 | _number_ | 十年后 |
| min-hour | 可选的最小小时,针对 time 类型 | _number_ | `0` |
| max-hour | 可选的最大小时,针对 time 类型 | _number_ | `23` |
| min-minute | 可选的最小分钟,针对 time 类型 | _number_ | `0` |
| max-minute | 可选的最大分钟,针对 time 类型 | _number_ | `59` |
| filter | 选项过滤函数(`type` 可能值为 `year`, `month`, `day`, `hour`, `minute`) | _(type, values) => values_ | - |
| formatter | 选项格式化函数(`type` 可能值为 `year`, `month`, `day`, `hour`, `minute`) | _(type, value) => value_ | - |
| title | 顶部栏标题 | _string_ | `''` |
| show-toolbar | 是否显示顶部栏 | _boolean_ | `true` |
| loading | 是否显示加载状态 | _boolean_ | `false` |
| item-height | 选项高度 | _number_ | `44` |
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |
| visible-item-count | 可见的选项个数 | _number_ | `6` |
### Events
| 事件名称 | 说明 | 回调参数 |
| -------- | ------------------------ | ---------- |
| bind:input | 当值变化时触发的事件 | 当前 value |
| bind:change | 当值变化时触发的事件 | 组件实例 |
| bind:confirm | 点击完成按钮时触发的事件 | 当前 value |
| bind:cancel | 点击取消按钮时触发的事件 | - |
### change 事件
在`change`事件中,可以获取到组件实例,对组件进行相应的更新等操作:
| 函数 | 说明 |
| ------------------------------ | ------------------------------------------ |
| getColumnValue(index) | 获取对应列中选中的值 |
| setColumnValue(index, value) | 设置对应列中选中的值 |
| getColumnValues(index) | 获取对应列中所有的备选值 |
| setColumnValues(index, values) | 设置对应列中所有的备选值 |
| getValues() | 获取所有列中被选中的值,返回一个数组 |
| setValues(values) | `values`为一个数组,设置所有列中被选中的值 |
### 外部样式类
| 类名 | 说明 |
| ------------- | ------------ |
| active-class | 选中项样式类 |
| toolbar-class | 顶部栏样式类 |
| column-class | 列样式类 |
================================================
FILE: packages/datetime-picker/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-toast": "../../toast/index",
"van-datetime-picker": "../../datetime-picker/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/datetime-picker/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
minHour: 10,
maxHour: 20,
minDate: new Date(2018, 0, 1).getTime(),
maxDate: new Date(2019, 10, 1).getTime(),
currentDate1: new Date(2018, 2, 31).getTime(),
currentDate2: null,
currentDate3: new Date(2018, 0, 1),
currentDate4: '12:00',
loading: false,
formatter(type, value) {
if (type === 'year') {
return `${value}年`;
}
if (type === 'month') {
return `${value}月`;
}
return value;
},
filter(type, options) {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
},
methods: {
onInput(event) {
const { detail, currentTarget } = event;
const result = this.getResult(detail, currentTarget.dataset.type);
Toast({
context: this,
message: result,
});
},
getResult(time, type) {
const date = new Date(time);
switch (type) {
case 'datetime':
return date.toLocaleString();
case 'date':
return date.toLocaleDateString();
case 'year-month':
return `${date.getFullYear()}/${date.getMonth() + 1}`;
case 'time':
return time;
default:
return '';
}
},
},
});
================================================
FILE: packages/datetime-picker/demo/index.wxml
================================================
================================================
FILE: packages/datetime-picker/index.json
================================================
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
================================================
FILE: packages/datetime-picker/index.less
================================================
// empty
================================================
FILE: packages/datetime-picker/index.ts
================================================
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pickerProps } from '../picker/shared';
const currentYear = new Date().getFullYear();
function isValidDate(date: number) {
return isDef(date) && !isNaN(new Date(date).getTime());
}
function range(num: number, min: number, max: number) {
return Math.min(Math.max(num, min), max);
}
function padZero(val: string | number) {
return `00${val}`.slice(-2);
}
function times(n: number, iteratee: (index: number) => string): string[] {
let index = -1;
const result = Array(n < 0 ? 0 : n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
function getTrueValue(formattedValue: string) {
if (formattedValue === undefined) {
formattedValue = '1';
}
while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1);
}
return parseInt(formattedValue, 10);
}
function getMonthEndDay(year: number, month: number): number {
return 32 - new Date(year, month - 1, 32).getDate();
}
const defaultFormatter = (
type: 'year' | 'month' | 'day' | 'hour' | 'minute',
value: string
) => value;
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
...pickerProps,
value: {
type: null,
observer: 'updateValue',
},
filter: null,
type: {
type: String,
value: 'datetime',
observer: 'updateValue',
},
showToolbar: {
type: Boolean,
value: true,
},
formatter: {
type: null,
value: defaultFormatter,
},
minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime(),
observer: 'updateValue',
},
maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime(),
observer: 'updateValue',
},
minHour: {
type: Number,
value: 0,
observer: 'updateValue',
},
maxHour: {
type: Number,
value: 23,
observer: 'updateValue',
},
minMinute: {
type: Number,
value: 0,
observer: 'updateValue',
},
maxMinute: {
type: Number,
value: 59,
observer: 'updateValue',
},
},
data: {
innerValue: Date.now(),
columns: [],
},
methods: {
updateValue() {
const { data } = this;
const val = this.correctValue(data.value);
const isEqual = val === data.innerValue;
this.updateColumnValue(val).then(() => {
if (!isEqual) {
this.$emit('input', val);
}
});
},
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this;
const { setColumnValues } = picker;
picker.setColumnValues = (...args: any) =>
setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
const { formatter = defaultFormatter } = this.data;
const results = this.getOriginColumns().map((column) => ({
values: column.values.map((value) => formatter(column.type, value)),
}));
return this.set({ columns: results });
},
getOriginColumns() {
const { filter } = this.data;
const results = this.getRanges().map(({ type, range }) => {
let values = times(range[1] - range[0] + 1, (index) => {
const value = range[0] + index;
return type === 'year' ? `${value}` : padZero(value);
});
if (filter) {
values = filter(type, values);
}
return { type, values };
});
return results;
},
getRanges() {
const { data } = this;
if (data.type === 'time') {
return [
{
type: 'hour',
range: [data.minHour, data.maxHour],
},
{
type: 'minute',
range: [data.minMinute, data.maxMinute],
},
];
}
const {
maxYear,
maxDate,
maxMonth,
maxHour,
maxMinute,
} = this.getBoundary('max', data.innerValue);
const {
minYear,
minDate,
minMonth,
minHour,
minMinute,
} = this.getBoundary('min', data.innerValue);
const result = [
{
type: 'year',
range: [minYear, maxYear],
},
{
type: 'month',
range: [minMonth, maxMonth],
},
{
type: 'day',
range: [minDate, maxDate],
},
{
type: 'hour',
range: [minHour, maxHour],
},
{
type: 'minute',
range: [minMinute, maxMinute],
},
];
if (data.type === 'date') result.splice(3, 2);
if (data.type === 'year-month') result.splice(2, 3);
return result;
},
correctValue(value: any) {
const { data } = this;
// validate value
const isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) {
value = data.minDate;
} else if (!isDateType && !value) {
const { minHour } = data;
value = `${padZero(minHour)}:00`;
}
// time type
if (!isDateType) {
let [hour, minute] = value.split(':');
hour = padZero(range(hour, data.minHour, data.maxHour));
minute = padZero(range(minute, data.minMinute, data.maxMinute));
return `${hour}:${minute}`;
}
// date type
value = Math.max(value, data.minDate);
value = Math.min(value, data.maxDate);
return value;
},
getBoundary(type: string, innerValue: number) {
const value = new Date(innerValue);
const boundary = new Date(this.data[`${type}Date`]);
const year = boundary.getFullYear();
let month = 1;
let date = 1;
let hour = 0;
let minute = 0;
if (type === 'max') {
month = 12;
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
hour = 23;
minute = 59;
}
if (value.getFullYear() === year) {
month = boundary.getMonth() + 1;
if (value.getMonth() + 1 === month) {
date = boundary.getDate();
if (value.getDate() === date) {
hour = boundary.getHours();
if (value.getHours() === hour) {
minute = boundary.getMinutes();
}
}
}
}
return {
[`${type}Year`]: year,
[`${type}Month`]: month,
[`${type}Date`]: date,
[`${type}Hour`]: hour,
[`${type}Minute`]: minute,
};
},
onCancel() {
this.$emit('cancel');
},
onConfirm() {
this.$emit('confirm', this.data.innerValue);
},
onChange() {
const { data } = this;
let value;
const picker = this.getPicker();
const originColumns = this.getOriginColumns();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1]
.values[indexes[1]]}`;
} else {
const indexes = picker.getIndexes();
const values = indexes.map(
(value, index) => originColumns[index].values[value]
);
const year = getTrueValue(values[0]);
const month = getTrueValue(values[1]);
const maxDate = getMonthEndDay(year, month);
let date = getTrueValue(values[2]);
if (data.type === 'year-month') {
date = 1;
}
date = date > maxDate ? maxDate : date;
let hour = 0;
let minute = 0;
if (data.type === 'datetime') {
hour = getTrueValue(values[3]);
minute = getTrueValue(values[4]);
}
value = new Date(year, month - 1, date, hour, minute);
}
value = this.correctValue(value);
this.updateColumnValue(value).then(() => {
this.$emit('input', value);
this.$emit('change', picker);
});
},
updateColumnValue(value) {
let values: string[] = [];
const { type } = this.data;
const formatter = this.data.formatter || defaultFormatter;
const picker = this.getPicker();
if (type === 'time') {
const pair = value.split(':');
values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
} else {
const date = new Date(value);
values = [
formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1)),
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
if (type === 'datetime') {
values.push(
formatter('day', padZero(date.getDate())),
formatter('hour', padZero(date.getHours())),
formatter('minute', padZero(date.getMinutes()))
);
}
}
return this.set({ innerValue: value })
.then(() => this.updateColumns())
.then(() => picker.setValues(values));
},
},
created() {
const innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(() => {
this.$emit('input', innerValue);
});
},
});
================================================
FILE: packages/datetime-picker/index.wxml
================================================
================================================
FILE: packages/datetime-picker/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
选择完整时间
取消
确认
选择日期(年月日)
取消
确认
选择日期(年月)
取消
确认
选择时间
取消
确认
选项过滤器
取消
确认
`;
================================================
FILE: packages/datetime-picker/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/definitions/index.ts
================================================
interface VantComponentInstance {
parent: WechatMiniprogram.Component.TrivialInstance;
children: WechatMiniprogram.Component.TrivialInstance[];
index: number;
$emit: (
name: string,
detail?: unknown,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
setView: (value: Record, callback?: () => void) => void;
}
export type VantComponentOptions<
Data extends WechatMiniprogram.Component.DataOption,
Props extends WechatMiniprogram.Component.PropertyOption,
Methods extends WechatMiniprogram.Component.MethodOption
> = {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props;
relation?: {
relations: Record;
mixin: string;
};
watch?: Record any>;
methods?: Methods;
// lifetimes
beforeCreate?: () => void;
created?: () => void;
mounted?: () => void;
destroyed?: () => void;
} & ThisType<
VantComponentInstance &
WechatMiniprogram.Component.Instance<
Data & {
name: string;
value: any;
} & Record,
Props,
Methods
> &
Record
>;
================================================
FILE: packages/dialog/README.md
================================================
# Dialog 弹出框
### 介绍
弹出模态框,常用于消息提示、消息确认,或在当前页面内完成特定的交互操作,支持函数调用和组件调用两种方式。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-dialog": "@vant/weapp/dialog/index"
}
```
## 代码演示
### 消息提示
用于提示一些消息,只包含一个确认按钮。
```html
```
```javascript
import Dialog from '@vant/weapp/dialog/dialog';
Dialog.alert({
title: '标题',
message: '弹窗内容',
}).then(() => {
// on close
});
Dialog.alert({
message: '弹窗内容',
}).then(() => {
// on close
});
```
### 消息确认
用于确认消息,包含取消和确认按钮。
```html
```
```javascript
import Dialog from '@vant/weapp/dialog/dialog';
Dialog.confirm({
title: '标题',
message: '弹窗内容',
})
.then(() => {
// on confirm
})
.catch(() => {
// on cancel
});
```
### 圆角按钮风格
将 theme 选项设置为 `round-button` 可以展示圆角按钮风格的弹窗。
```html
```
```javascript
import Dialog from '@vant/weapp/dialog/dialog';
Dialog.alert({
title: '标题',
message: '弹窗内容',
theme: 'round-button',
}).then(() => {
// on close
});
Dialog.alert({
message: '弹窗内容',
theme: 'round-button',
}).then(() => {
// on close
});
```
### 异步关闭
通过 `beforeClose` 属性可以传入一个回调函数,在弹窗关闭前进行特定操作。
```html
```
```javascript
import Dialog from '@vant/weapp/dialog/dialog';
const beforeClose = (action) =>
new Promise((resolve) => {
setTimeout(() => {
if (action === 'confirm') {
resolve(true);
} else {
// 拦截取消操作
resolve(false);
}
}, 1000);
});
Dialog.confirm({
title: '标题',
message: '弹窗内容',
beforeClose,
});
```
### 组件调用
如果需要在弹窗内嵌入组件或其他自定义内容,可以使用组件调用的方式。
```html
```
```js
Page({
data: {
show: true,
},
getUserInfo(event) {
console.log(event.detail);
},
onClose() {
this.setData({ show: false });
},
});
```
### 自定义样式
如果需要自定义样式,建议使用 `custom-class` 实现,不在推荐 `className` 属性(在自定义组件中使用并不会生效),使用方法如下
#### 组件调用
```html
```
#### API 调用
```html
```
## API
### 方法
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| Dialog | `options` | `Promise` | 展示弹窗 |
| Dialog.alert | `options` | `Promise` | 展示消息提示弹窗 |
| Dialog.confirm | `options` | `Promise` | 展示消息确认弹窗 |
| Dialog.setDefaultOptions | `options` | `void` | 修改默认配置,对所有 Dialog 生效 |
| Dialog.resetDefaultOptions | - | `void` | 重置默认配置,对所有 Dialog 生效 |
| Dialog.close | - | `void` | 关闭弹窗 |
| Dialog.stopLoading | - | `void` | 停止按钮的加载状态 |
### Options
通过函数调用 Dialog 时,支持传入以下选项:
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 标题 | _string_ | - |
| width | 弹窗宽度,默认单位为`px` | _string \| number_ | `320px` |
| message | 文本内容,支持通过`\n`换行 | _string_ | - |
| messageAlign | 内容对齐方式,可选值为`left` `right` | _string_ | `center` |
| theme | 样式风格,可选值为`round-button` | _string_ | `default` |
| zIndex | z-index 层级 | _number_ | `100` |
| className | 自定义类名,dialog 在自定义组件内时无效,已废弃,请使用 `custom-class` 代替,将在 2.0.0 移除 | _string_ | '' |
| customStyle | 自定义样式 | _string_ | '' |
| selector | 自定义选择器 | _string_ | `van-dialog` |
| showConfirmButton | 是否展示确认按钮 | _boolean_ | `true` |
| showCancelButton | 是否展示取消按钮 | _boolean_ | `false` |
| confirmButtonText | 确认按钮的文案 | _string_ | `确认` |
| cancelButtonText | 取消按钮的文案 | _string_ | `取消` |
| overlay | 是否展示遮罩层 | _boolean_ | `true` |
| overlayStyle | 自定义遮罩层样式 | _object_ | - |
| closeOnClickOverlay | 点击遮罩层时是否关闭弹窗 | _boolean_ | `false` |
| asyncClose | 已废弃,将在 2.0.0 移除,请使用 `beforeClose` 属性代替 | _boolean_ | `false` |
| beforeClose | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(action) => boolean \| Promise\_ | - |
| context | 选择器的选择范围,可以传入自定义组件的 this 作为上下文 | _object_ | 当前页面 |
| transition | 动画名称,可选值为`fade` `none` | _string_ | `scale` |
| confirmButtonOpenType | 确认按钮的微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
### OpenType Options
使用`confirmButtonOpenType`后,支持以下选项:
| 参数 | 说明 | 类型 | 默认值 | open-type |
| --- | --- | --- | --- | --- |
| appParameter | 打开 APP 时,向 APP 传递的参数 | _string_ | - | `launchApp` |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,
zh_TW 繁体中文,en 英文 | _string_ | `en` | `getUserInfo` |
| sessionFrom | 会话来源 | _string_ | - | `contact` |
| businessId | 客服消息子商户 id | _number_ | - | `contact` |
| sendMessageTitle | 会话内消息卡片标题 | _string_ | 当前标题 | `contact` |
| sendMessagePath | 会话内消息卡片点击跳转小程序路径 | _string_ | 当前分享路径 | `contact` |
| sendMessageImg | sendMessageImg | _string_ | 截图 | `contact` |
| showMessageCard | 显示会话内消息卡片 | _string_ | `false` | `contact` |
### Props
通过组件调用 Dialog 时,支持以下 Props:
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否显示弹窗 | _boolean_ | - |
| confirm-button-id `v1.10.25`| 确认按钮的标识符,作为底层原生button组件的id值 | _string_ | - |
| title | 标题 | _string_ | - |
| width | 弹窗宽度,默认单位为`px` | _string \| number_ | `320px` |
| message | 文本内容,支持通过`\n`换行 | _string_ | - |
| theme | 样式风格,可选值为`round-button` | _string_ | `default` |
| message-align | 内容对齐方式,可选值为`left` `right` | _string_ | `center` |
| z-index | z-index 层级 | _number_ | `100` |
| class-name | 自定义类名,dialog 在自定义组件内时无效,已废弃,请使用 `custom-class` 代替,将在 2.0.0 移除 | _string_ | '' |
| custom-style | 自定义样式 | _string_ | '' |
| show-confirm-button | 是否展示确认按钮 | _boolean_ | `true` |
| show-cancel-button | 是否展示取消按钮 | _boolean_ | `false` |
| confirm-button-text | 确认按钮的文案 | _string_ | `确认` |
| cancel-button-text | 取消按钮的文案 | _string_ | `取消` |
| confirm-button-color | 确认按钮的字体颜色 | _string_ | `#ee0a24` |
| cancel-button-color | 取消按钮的字体颜色 | _string_ | `#333` |
| overlay | 是否展示遮罩层 | _boolean_ | `true` |
| overlay-style `v1.0.0` | 自定义遮罩层样式 | _object_ | - |
| close-on-click-overlay | 点击遮罩层时是否关闭弹窗 | _boolean_ | `false` |
| use-slot | 是否使用自定义内容的插槽 | _boolean_ | `false` |
| use-title-slot | 是否使用自定义标题的插槽 | _boolean_ | `false` |
| use-confirm-button-slot `1.10.23` | 是否使用自定义确认按钮的插槽 | _boolean_ | `false` |
| use-cancel-button-slot `1.10.23` | 是否使用自定义取消按钮的插槽 | _boolean_ | `false` |
| async-close | 已废弃,将在 2.0.0 移除,请使用 `beforeClose` 属性代替 | _boolean_ | `false` |
| before-close | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(action) => boolean \| Promise\_ | - |
| transition | 动画名称,可选值为`fade` | _string_ | `scale` |
| confirm-button-open-type | 确认按钮的微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
| root-portal `v1.11.3` | 是否从页面子树中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### OpenType Props
使用`confirm-button-open-type`后,支持以下 Props:
| 参数 | 说明 | 类型 | 默认值 | open-type |
| --- | --- | --- | --- | --- |
| app-parameter | 打开 APP 时,向 APP 传递的参数 | _string_ | - | `launchApp` |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,
zh_TW 繁体中文,en 英文 | _string_ | `en` | `getUserInfo` |
| session-from | 会话来源 | _string_ | - | `contact` |
| business-id | 客服消息子商户 id | _number_ | - | `contact` |
| send-message-title | 会话内消息卡片标题 | _string_ | 当前标题 | `contact` |
| send-message-path | 会话内消息卡片点击跳转小程序路径 | _string_ | 当前分享路径 | `contact` |
| send-message-img | sendMessageImg | _string_ | 截图 | `contact` |
| show-message-card | 显示会话内消息卡片 | _string_ | `false` | `contact` |
### Events
| 事件 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:close | 弹窗关闭时触发 | event.detail: 触发关闭事件的来源,
枚举为`confirm`,`cancel`,`overlay` |
| bind:confirm | 点击确认按钮时触发 | - |
| bind:cancel | 点击取消按钮时触发 | - |
| bind:getuserinfo | 点击确认按钮时,会返回获取到的用户信息,
从返回参数的 detail 中获取到的值同 wx.getUserInfo | - |
| bind:contact | 客服消息回调 | - |
| bind:getphonenumber | 获取用户手机号回调 | - |
| bind:getrealtimephonenumber `v1.10.21` | 获取手机号实时验证回调,open-type=getRealtimePhoneNumber 时有效 | - |
| bind:agreeprivacyauthorization `v1.10.25` | 同意隐私协议回调,openType="agreePrivacyAuthorization"时有效 | - |
| bind:error | 当使用开放能力时,发生错误的回调 | - |
| bind:opensetting | 在打开授权设置页后回调 | - |
### Slot
| 名称 | 说明 |
| --- | --- |
| title | 自定义`title`显示内容,如果设置了`title`属性则不生效 |
| confirm-button `1.10.23` | 自定义`confirm-button`显示内容,需要 `use-confirm-button-slot` 为 `true` |
| cancel-button `1.10.23` | 自定义`cancel-button`显示内容,需要 `use-cancel-button-slot` 为 `true` |
### 外部样式类
| 类名 | 说明 |
| ------------------------------- | -------------- |
| custom-class `v1.10.8` | 根节点样式类 |
| cancle-button-class `v1.10.21` | 取消按钮样式类 |
| confirm-button-class `v1.10.21` | 确认按钮样式类 |
================================================
FILE: packages/dialog/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-dialog": "../../dialog/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/dialog/demo/index.less
================================================
.demo-image {
box-sizing: border-box;
width: 100%;
padding: 25px 20px 0;
}
================================================
FILE: packages/dialog/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Dialog, { Action } from '../../dialog/dialog';
const message = '代码是写出来给人看的,附带能在机器上运行';
VantComponent({
data: {
show: false,
},
methods: {
showCustomDialog() {
this.setData({ show: true });
},
getUserInfo(event) {
console.log(event.detail);
},
onClickThemeAlert() {
Dialog.alert({
context: this,
title: '标题',
theme: 'round-button',
message,
});
},
onClickThemeAlert2() {
Dialog.alert({
context: this,
theme: 'round-button',
message,
});
},
onClickAlert() {
Dialog.alert({
context: this,
title: '标题',
message,
});
},
onClickAlert2() {
Dialog.alert({
context: this,
message,
});
},
onClickConfirm() {
Dialog.confirm({
context: this,
title: '标题',
message,
});
},
onClickAsyncClose() {
const beforeClose = (action: Action): Promise =>
new Promise((resolve) => {
setTimeout(() => {
if (action === 'confirm') {
resolve(true);
} else {
// 拦截取消操作
resolve(false);
}
}, 1000);
});
Dialog.confirm({
context: this,
title: '标题',
message,
beforeClose,
});
},
onClose() {
this.setData({
show: false,
});
},
},
});
================================================
FILE: packages/dialog/demo/index.wxml
================================================
================================================
FILE: packages/dialog/dialog.ts
================================================
let queue: WechatMiniprogram.Component.TrivialInstance[] = [];
export type Action = 'confirm' | 'cancel' | 'overlay';
type DialogContext =
| WechatMiniprogram.Page.TrivialInstance
| WechatMiniprogram.Component.TrivialInstance;
interface DialogOptions {
lang?: string;
show?: boolean;
title?: string;
width?: string | number | null;
zIndex?: number;
theme?: string;
context?: (() => DialogContext) | DialogContext;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
/**
* @deprecated use custom-class instead
*/
className?: string;
customStyle?: string;
transition?: string;
/**
* @deprecated use beforeClose instead
*/
asyncClose?: boolean;
beforeClose?: null | ((action: Action) => Promise | void);
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
showMessageCard?: boolean;
sendMessagePath?: string;
sendMessageTitle?: string;
confirmButtonText?: string;
cancelButtonText?: string;
showConfirmButton?: boolean;
showCancelButton?: boolean;
closeOnClickOverlay?: boolean;
confirmButtonOpenType?: string;
}
const defaultOptions: DialogOptions = {
show: false,
title: '',
width: null,
theme: 'default',
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
asyncClose: false,
beforeClose: null,
transition: 'scale',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: '',
};
let currentOptions: DialogOptions = { ...defaultOptions };
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Dialog = (options: DialogOptions) => {
options = {
...currentOptions,
...options,
};
return new Promise(
(resolve, reject) => {
const context =
(typeof options.context === 'function'
? options.context()
: options.context) || getContext();
const dialog = context.selectComponent(options.selector as string);
delete options.context;
delete options.selector;
if (dialog) {
dialog.setData({
callback: (
action: Action,
instance: WechatMiniprogram.Component.TrivialInstance
) => {
action === 'confirm' ? resolve(instance) : reject(instance);
},
...options,
});
wx.nextTick(() => {
dialog.setData({ show: true });
});
queue.push(dialog);
} else {
console.warn(
'未找到 van-dialog 节点,请确认 selector 及 context 是否正确'
);
}
}
);
};
Dialog.alert = (options: DialogOptions) => Dialog(options);
Dialog.confirm = (options: DialogOptions) =>
Dialog({
showCancelButton: true,
...options,
});
Dialog.close = () => {
queue.forEach((dialog) => {
dialog.close();
});
queue = [];
};
Dialog.stopLoading = () => {
queue.forEach((dialog) => {
dialog.stopLoading();
});
};
Dialog.currentOptions = currentOptions;
Dialog.defaultOptions = defaultOptions;
Dialog.setDefaultOptions = (options: DialogOptions) => {
currentOptions = { ...currentOptions, ...options };
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions = () => {
currentOptions = { ...defaultOptions };
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions();
export default Dialog;
================================================
FILE: packages/dialog/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-button": "../button/index",
"van-goods-action": "../goods-action/index",
"van-goods-action-button": "../goods-action-button/index"
}
}
================================================
FILE: packages/dialog/index.less
================================================
@import '../common/style/var.less';
.van-dialog {
top: 45% !important;
overflow: hidden;
width: var(--dialog-width, @dialog-width);
font-size: var(--dialog-font-size, @dialog-font-size);
border-radius: var(--dialog-border-radius, @dialog-border-radius);
background-color: var(--dialog-background-color, @dialog-background-color);
@media (max-width: 321px) {
width: var(--dialog-small-screen-width, @dialog-small-screen-width);
}
&__header {
text-align: center;
padding-top: var(--dialog-header-padding-top, @dialog-header-padding-top);
font-weight: var(--dialog-header-font-weight, @dialog-header-font-weight);
line-height: var(--dialog-header-line-height, @dialog-header-line-height);
&--isolated {
padding: var(
--dialog-header-isolated-padding,
@dialog-header-isolated-padding
);
}
}
&__message {
overflow-y: auto;
text-align: center;
-webkit-overflow-scrolling: touch;
font-size: var(--dialog-message-font-size, @dialog-message-font-size);
line-height: var(--dialog-message-line-height, @dialog-message-line-height);
max-height: var(--dialog-message-max-height, @dialog-message-max-height);
padding: var(--dialog-message-padding, @dialog-message-padding);
&-text {
word-wrap: break-word;
}
&--hasTitle {
padding-top: var(
--dialog-has-title-message-padding-top,
@dialog-has-title-message-padding-top
);
color: var(
--dialog-has-title-message-text-color,
@dialog-has-title-message-text-color
);
}
&--round-button {
padding-bottom: @padding-md;
color: @text-color;
}
&--left {
text-align: left;
}
&--right {
text-align: right;
}
&--justify {
text-align: justify;
}
}
&__footer {
display: flex;
&--round-button {
position: relative !important;
padding: @padding-xs @padding-lg @padding-md !important;
}
}
&__button {
flex: 1;
}
&__confirm,
&__cancel {
border: 0 !important;
}
&-bounce-enter {
transform: translate3d(-50%, -50%, 0) scale(0.7);
opacity: 0;
}
&-bounce-leave-active {
transform: translate3d(-50%, -50%, 0) scale(0.9);
opacity: 0;
}
}
================================================
FILE: packages/dialog/index.ts
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { GRAY, RED } from '../common/color';
import { toPromise } from '../common/utils';
import type { Action } from './dialog';
VantComponent({
mixins: [button],
classes: ['cancle-button-class', 'confirm-button-class'],
props: {
show: {
type: Boolean,
observer(show: boolean) {
!show && this.stopLoading();
},
},
title: String,
message: String,
theme: {
type: String,
value: 'default',
},
confirmButtonId: String,
className: String,
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
beforeClose: null,
overlayStyle: String,
useSlot: Boolean,
useTitleSlot: Boolean,
useConfirmButtonSlot: Boolean,
useCancelButtonSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: null,
zIndex: {
type: Number,
value: 2000,
},
confirmButtonText: {
type: String,
value: '确认',
},
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonColor: {
type: String,
value: RED,
},
cancelButtonColor: {
type: String,
value: GRAY,
},
showConfirmButton: {
type: Boolean,
value: true,
},
overlay: {
type: Boolean,
value: true,
},
transition: {
type: String,
value: 'scale',
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
loading: {
confirm: false,
cancel: false,
},
callback: (() => {}) as unknown as (
action: string,
context: WechatMiniprogram.Component.TrivialInstance
) => void,
},
methods: {
onConfirm() {
this.handleAction('confirm');
},
onCancel() {
this.handleAction('cancel');
},
onClickOverlay() {
this.close('overlay');
},
close(action: string) {
this.setData({ show: false });
this.closeAction = action;
},
onAfterLeave() {
const { closeAction: action } = this;
this.$emit('close', action);
const { callback } = this.data;
if (callback) {
callback(action, this);
}
},
stopLoading() {
this.setData({
loading: {
confirm: false,
cancel: false,
},
});
},
handleAction(action: Action) {
this.$emit(action, { dialog: this });
const { asyncClose, beforeClose } = this.data;
if (!asyncClose && !beforeClose) {
this.close(action);
return;
}
this.setData({
[`loading.${action}`]: true,
});
if (beforeClose) {
toPromise(beforeClose(action)).then((value) => {
if (value) {
this.close(action);
} else {
this.stopLoading();
}
});
}
},
},
});
================================================
FILE: packages/dialog/index.wxml
================================================
{{ message }}
{{ cancelButtonText }}
{{ confirmButtonText }}
================================================
FILE: packages/dialog/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
提示弹窗
提示弹窗
提示弹窗(无标题)
确认弹窗
圆角按钮样式
提示弹窗
提示弹窗(无标题)
异步关闭
异步关闭
组件调用
组件调用
`;
================================================
FILE: packages/dialog/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/divider/README.md
================================================
# Divider 分割线
### 介绍
用于将内容分隔为多个区域。
### 引入
在`app.json`或`index.json`中引入组件,默认为`ES6`版本,`ES5`引入方式参见[快速上手](#/quickstart)
```json
"usingComponents": {
"van-divider": "@vant/weapp/divider/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)。
## 代码演示
### 基础用法
```html
```
### 使用 hairline
```html
```
### 虚线
```html
```
### 文本位置
```html
文本
文本
文本
```
### 自定义属性
```html
文本颜色
border 颜色
字体大小
```
### 自定义样式
```html
文本
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ---------------- | --------------------------------- | --------- | ------ |
| dashed | 虚线 | _boolean_ | false |
| hairline | 细线 | _boolean_ | false |
| content-position | 文本位置,`left` `center` `right` | _string_ | - |
| custom-style | 自定义样式 | _string_ | - |
### Slot
| 名称 | 说明 |
| ---- | -------------- |
| 默认 | 自定义文本内容 |
================================================
FILE: packages/divider/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-divider": "../../divider/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/divider/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/divider/demo/index.wxml
================================================
文本
文本
文本
文本
================================================
FILE: packages/divider/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: packages/divider/index.less
================================================
@import '../common/style/var.less';
.van-divider {
display: flex;
align-items: center;
border-style: solid;
border-width: 0;
margin: var(--divider-margin, @divider-margin);
color: var(--divider-text-color, @divider-text-color);
font-size: var(--divider-font-size, @divider-font-size);
line-height: var(--divider-line-height, @divider-line-height);
border-color: var(--divider-border-color, @divider-border-color);
&::before,
&::after {
display: block;
flex: 1;
box-sizing: border-box;
height: 1px;
border-color: inherit;
border-style: inherit;
border-width: 1px 0 0;
}
&::before {
content: '';
}
&--hairline {
&::before,
&::after {
transform: scaleY(0.5);
}
}
&--dashed {
border-style: dashed;
}
&--center,
&--left,
&--right {
&::before {
margin-right: var(--divider-content-padding, @divider-content-padding);
}
&::after {
content: '';
margin-left: var(--divider-content-padding, @divider-content-padding);
}
}
&--left {
&::before {
max-width: var(--divider-content-left-width, @divider-content-left-width);
}
}
&--right {
&::after {
max-width: var(
--divider-content-right-width,
@divider-content-right-width
);
}
}
}
================================================
FILE: packages/divider/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: Boolean,
hairline: Boolean,
contentPosition: String,
fontSize: String,
borderColor: String,
textColor: String,
customStyle: String,
},
});
================================================
FILE: packages/divider/index.wxml
================================================
================================================
FILE: packages/divider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
'border-color': data.borderColor,
color: data.textColor,
'font-size': addUnit(data.fontSize),
},
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/divider/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
内容位置
文本
文本
文本
虚线
自定义样式
文本
`;
================================================
FILE: packages/divider/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/dropdown-item/dropdown-item.wxml
================================================
{{ item.text }}
================================================
FILE: packages/dropdown-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/dropdown-item/index.less
================================================
@import '../common/style/var.less';
.van-dropdown-item {
position: fixed;
right: 0;
left: 0;
overflow: hidden;
&__option {
text-align: left;
&--active {
.van-dropdown-item__title,
.van-dropdown-item__icon {
color: var(
--dropdown-menu-option-active-color,
@dropdown-menu-option-active-color
);
}
}
}
&--up {
top: 0;
}
&--down {
bottom: 0;
}
&__icon {
display: block;
line-height: inherit;
}
}
================================================
FILE: packages/dropdown-item/index.ts
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
import { Option } from './shared';
VantComponent({
classes: ['item-title-class'],
field: true,
relation: useParent('dropdown-menu', function () {
this.updateDataFromParent();
}),
props: {
value: {
type: null,
observer: 'rerender',
},
title: {
type: String,
observer: 'rerender',
},
disabled: Boolean,
titleClass: {
type: String,
observer: 'rerender',
},
options: {
type: Array,
value: [],
observer: 'rerender',
},
popupStyle: String,
useBeforeToggle: {
type: Boolean,
value: false,
},
rootPortal: {
type: Boolean,
value: false,
},
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: '',
safeAreaTabBar: false,
},
methods: {
rerender() {
wx.nextTick(() => {
this.parent?.updateItemListData();
});
},
updateDataFromParent() {
if (this.parent) {
const {
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
safeAreaTabBar,
} = this.parent.data;
this.setData({
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
safeAreaTabBar,
});
}
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
this.setData({ showWrapper: false });
},
onOptionTap(event: WechatMiniprogram.TouchEvent) {
const { option } = event.currentTarget.dataset;
const { value } = option as unknown as Option;
const shouldEmitChange = this.data.value !== value;
this.setData({ showPopup: false, value });
this.$emit('close');
this.rerender();
if (shouldEmitChange) {
this.$emit('change', value);
}
},
toggle(show?: boolean, options: { immediate?: boolean } = {}) {
const { showPopup } = this.data;
if (typeof show !== 'boolean') {
show = !showPopup;
}
if (show === showPopup) {
return;
}
this.onBeforeToggle(show).then((status) => {
if (!status) {
return;
}
this.setData({
transition: !options.immediate,
showPopup: show,
});
if (show) {
this.parent?.getChildWrapperStyle().then((wrapperStyle: string) => {
this.setData({ wrapperStyle, showWrapper: true });
this.rerender();
});
} else {
this.rerender();
}
});
},
onBeforeToggle(status: boolean): Promise {
const { useBeforeToggle } = this.data;
if (!useBeforeToggle) {
return Promise.resolve(true);
}
return new Promise((resolve) => {
this.$emit('before-toggle', {
status,
callback: (value: boolean) => resolve(value),
});
});
},
},
});
================================================
FILE: packages/dropdown-item/index.wxml
================================================
================================================
FILE: packages/dropdown-item/shared.ts
================================================
export interface Option {
text: string;
value: string | number;
icon: string;
}
================================================
FILE: packages/dropdown-menu/README.md
================================================
# DropdownMenu 下拉菜单
### 介绍
向下弹出的菜单列表。
### 引入
在`app.json`或`index.json`中引入组件,默认为`ES6`版本,`ES5`引入方式参见[快速上手](#/quickstart)。
```json
"usingComponents": {
"van-dropdown-menu": "@vant/weapp/dropdown-menu/index",
"van-dropdown-item": "@vant/weapp/dropdown-item/index"
}
```
## 代码演示
### 基础用法
```html
```
```js
Page({
data: {
option1: [
{ text: '全部商品', value: 0 },
{ text: '新款商品', value: 1 },
{ text: '活动商品', value: 2 },
],
option2: [
{ text: '默认排序', value: 'a' },
{ text: '好评排序', value: 'b' },
{ text: '销量排序', value: 'c' },
],
value1: 0,
value2: 'a',
},
});
```
### 自定义菜单内容
```html
确认
```
```js
Page({
data: {
switchTitle1: '包邮',
switchTitle2: '团购',
itemTitle: '筛选',
option1: [
{ text: '全部商品', value: 0 },
{ text: '新款商品', value: 1 },
{ text: '活动商品', value: 2 },
],
value1: 0,
},
onConfirm() {
this.selectComponent('#item').toggle();
},
onSwitch1Change({ detail }) {
this.setData({ switch1: detail });
},
onSwitch2Change({ detail }) {
this.setData({ switch2: detail });
},
});
```
### 自定义选中状态颜色
```html
```
### 向上展开
```html
```
### 禁用菜单
```html
```
### 异步打开/关闭
通过 `before-toggle` 事件可以在下拉菜单打开或者关闭前执行特定的逻辑,实现状态变更前校验、异步打开/关闭的目的
```html
```
```js
Page({
data: {
value1: 0,
option1: [
{ text: '全部商品', value: 0 },
{ text: '新款商品', value: 1 },
{ text: '活动商品', value: 2 },
],
},
onBeforeChange({ detail: { status, callback }}) {
wx.showModal({
title: '异步打开/关闭',
content: `确定要${status ? '打开' : '关闭'}下拉菜单吗?`,
success: (res) => {
if (res.confirm) {
callback(true)
} else if (res.cancel) {
callback(false)
}
},
})
}
});
```
## API
### DropdownMenu Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| active-color | 菜单标题和选项的选中态颜色 | _string_ | `#ee0a24` |
| z-index | 菜单栏 z-index 层级 | _number_ | `10` |
| duration | 动画时长,单位毫秒 | _number_ | `200` |
| direction | 菜单展开方向,可选值为 up | _string_ | `down` |
| overlay | 是否显示遮罩层 | _boolean_ | `true` |
| safe-area-tab-bar `v1.10.14`| 是否留出底部 tabbar 安全距离 | _boolean_ | `false` |
| close-on-click-overlay | 是否在点击遮罩层后关闭菜单 | _boolean_ | `true` |
| close-on-click-outside | 是否在点击外部 menu 后关闭菜单 | _boolean_ | `true` |
### DropdownItem Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前选中项对应的 value | _number \| string_ | - |
| title | 菜单项标题 | _string_ | 当前选中项文字 |
| options | 选项数组 | _Option[]_ | `[]` |
| disabled | 是否禁用菜单 | _boolean_ | `false` |
| title-class | 标题额外类名,建议使用自定义样式 item-title-class 代替 | _string_ | - |
| popup-style | 自定义弹出层样式 | _string_ | - |
| use-before-toggle `v1.10.12` | 是否开启下拉菜单打开或者关闭前校验 | _boolean_ | `false` |
| root-portal `v1.10.14` | 是否从页面子树中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### DropdownItem Events
| 事件名 | 说明 | 回调参数 |
| ------ | ----------------------------- | -------- |
| change | 点击选项导致 value 变化时触发 | value |
| open | 打开菜单栏时触发 | - |
| close | 关闭菜单栏时触发 | - |
| opened | 打开菜单栏且动画结束后触发 | - |
| closed | 关闭菜单栏且动画结束后触发 | - |
| before-toggle `v1.10.12` | 下拉菜单打开或者关闭前触发,需要将`use-before-toggle`属性设置为`true` | `event.detail.status`: `true` 打开下拉菜单,`false` 关闭下拉菜单
`event.detail.callback`: 回调函数,调用`callback(false)`终止下拉菜单状态变更 |
### DropdownItem 方法
通过 selectComponent(id) 可访问。
| 方法名 | 说明 | 参数 | 返回值 |
| --- | --- | --- | --- |
| toggle | 切换菜单展示状态,传`true`为显示,`false`为隐藏,不传参为取反 | show?: boolean | - |
### Option 数据结构
| 键名 | 说明 | 类型 |
| ----- | -------------------------------- | ------------------ |
| text | 文字 | _string_ |
| value | 标识符 | _number \| string_ |
| icon | 左侧[图标名称](#/icon)或图片链接 | _string_ |
### DropdownMenu 外部样式类
| 类名 | 说明 |
| --------------------- | ------------ |
| custom-class | 根节点样式类 |
| title-class `v1.10.7` | 选中项样式类 |
### DropdownItem 外部样式类
| 类名 | 说明 |
| -------------------------- | ------------ |
| custom-class `v1.10.7` | 根节点样式类 |
| item-title-class `v1.10.7` | 选项样式类 |
================================================
FILE: packages/dropdown-menu/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-switch": "../../switch/index",
"van-button": "../../button/index",
"van-dropdown-item": "../../dropdown-item/index",
"van-dropdown-menu": "../../dropdown-menu/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/dropdown-menu/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
switchTitle1: '包邮',
switchTitle2: '团购',
itemTitle: '筛选',
option1: [
{ text: '全部商品', value: 0 },
{ text: '新款商品', value: 1 },
{ text: '活动商品', value: 2 },
],
option2: [
{ text: '默认排序', value: 'a' },
{ text: '好评排序', value: 'b' },
{ text: '销量排序', value: 'c' },
],
switch1: true,
switch2: false,
value1: 0,
value2: 'a',
},
methods: {
onConfirm() {
this.selectComponent('#item').toggle();
},
onSwitch1Change({ detail }) {
this.setData({ switch1: detail });
},
onSwitch2Change({ detail }) {
this.setData({ switch2: detail });
},
onBeforeChange({ detail: { status, callback } }) {
wx.showModal({
title: '异步打开/关闭',
content: `确定要${status ? '打开' : '关闭'}下拉菜单吗?`,
success: (res) => {
if (res.confirm) {
callback(true);
} else if (res.cancel) {
callback(false);
}
},
});
},
},
});
================================================
FILE: packages/dropdown-menu/demo/index.wxml
================================================
确认
================================================
FILE: packages/dropdown-menu/index.json
================================================
{
"component": true
}
================================================
FILE: packages/dropdown-menu/index.less
================================================
@import '../common/style/var.less';
.van-dropdown-menu {
display: flex;
box-shadow: var(--dropdown-menu-box-shadow, @dropdown-menu-box-shadow);
user-select: none;
height: var(--dropdown-menu-height, @dropdown-menu-height);
background-color: var(
--dropdown-menu-background-color,
@dropdown-menu-background-color
);
&__item {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
min-width: 0; // hack for flex ellipsis
&:active {
opacity: 0.7;
}
&--disabled {
&:active {
opacity: 1;
}
.van-dropdown-menu__title {
color: var(
--dropdown-menu-title-disabled-text-color,
@dropdown-menu-title-disabled-text-color
);
}
}
}
&__title {
position: relative;
box-sizing: border-box;
max-width: 100%;
padding: var(--dropdown-menu-title-padding, @dropdown-menu-title-padding);
color: var(
--dropdown-menu-title-text-color,
@dropdown-menu-title-text-color
);
font-size: var(
--dropdown-menu-title-font-size,
@dropdown-menu-title-font-size
);
line-height: var(
--dropdown-menu-title-line-height,
@dropdown-menu-title-line-height
);
&::after {
position: absolute;
top: 50%;
right: 11px;
margin-top: -5px;
border: 3px solid;
border-color: transparent transparent currentColor currentColor;
transform: rotate(-45deg);
opacity: 0.8;
content: '';
}
&--active {
color: var(
--dropdown-menu-title-active-text-color,
@dropdown-menu-title-active-text-color
);
}
&--down {
&::after {
margin-top: -1px;
transform: rotate(135deg);
}
}
}
}
================================================
FILE: packages/dropdown-menu/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { addUnit, getRect, getSystemInfoSync } from '../common/utils';
let ARRAY: WechatMiniprogram.Component.TrivialInstance[] = [];
VantComponent({
field: true,
classes: ['title-class'],
relation: useChildren('dropdown-item', function () {
this.updateItemListData();
}),
props: {
activeColor: {
type: String,
observer: 'updateChildrenData',
},
overlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
zIndex: {
type: Number,
value: 10,
},
duration: {
type: Number,
value: 200,
observer: 'updateChildrenData',
},
direction: {
type: String,
value: 'down',
observer: 'updateChildrenData',
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
closeOnClickOutside: {
type: Boolean,
value: true,
},
},
data: {
itemListData: [] as Record[],
},
beforeCreate() {
const { windowHeight } = getSystemInfoSync();
this.windowHeight = windowHeight;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
updateItemListData() {
this.setData({
itemListData: this.children.map((child) => child.data),
});
},
updateChildrenData() {
this.children.forEach((child) => {
child.updateDataFromParent();
});
},
toggleItem(active: number) {
this.children.forEach((item, index) => {
const { showPopup } = item.data;
if (index === active) {
item.toggle();
} else if (showPopup) {
item.toggle(false, { immediate: true });
}
});
},
close() {
this.children.forEach((child) => {
child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle() {
const { zIndex, direction } = this.data;
return getRect(this, '.van-dropdown-menu').then((rect) => {
const { top = 0, bottom = 0 } = rect;
const offset = direction === 'down' ? bottom : this.windowHeight - top;
let wrapperStyle = `z-index: ${zIndex};`;
if (direction === 'down') {
wrapperStyle += `top: ${addUnit(offset)};`;
} else {
wrapperStyle += `bottom: ${addUnit(offset)};`;
}
return wrapperStyle;
});
},
onTitleTap(event: WechatMiniprogram.TouchEvent) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (!child.data.disabled) {
ARRAY.forEach((menuItem) => {
if (
menuItem &&
menuItem.data.closeOnClickOutside &&
menuItem !== this
) {
menuItem.close();
}
});
this.toggleItem(index);
}
},
},
});
================================================
FILE: packages/dropdown-menu/index.wxml
================================================
================================================
FILE: packages/dropdown-menu/index.wxs
================================================
/* eslint-disable */
function displayTitle(item) {
if (item.title) {
return item.title;
}
var match = item.options.filter(function(option) {
return option.value === item.value;
});
var displayTitle = match.length ? match[0].text : '';
return displayTitle;
}
module.exports = {
displayTitle: displayTitle
};
================================================
FILE: packages/dropdown-menu/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
自定义菜单内容
自定义选中状态颜色
向上展开
禁用菜单
异步打开/关闭
`;
================================================
FILE: packages/dropdown-menu/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/empty/README.md
================================================
# Empty 空状态
### 介绍
空状态时的占位提示。
### 引入
在`app.json`或`index.json`中引入组件,默认为`ES6`版本,`ES5`引入方式参见[快速上手](#/quickstart)。
```json
"usingComponents": {
"van-empty": "@vant/weapp/empty/index"
}
```
## 代码演示
### 基础用法
```html
```
### 图片类型
Empty 组件内置了多种占位图片类型,可以在不同业务场景下使用。
```html
```
### 自定义图片
需要自定义图片时,可以在 image 属性中传入任意图片 URL。
```html
```
### 底部内容
通过默认插槽可以在 Empty 组件的下方插入内容。
```html
按钮
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| image | 图片类型,可选值为 `error` `network` `search`,支持传入图片 URL | _string_ | `default` |
| description | 图片下方的描述文字 | _string_ | - |
### Slots
| 名称 | 说明 |
| ----------- | -------------- |
| - | 自定义底部内容 |
| image | 自定义图标 |
| description | 自定义描述文字 |
================================================
FILE: packages/empty/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tab": "../../tab/index",
"van-tabs": "../../tabs/index",
"van-empty": "../../empty/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/empty/demo/index.less
================================================
.custom-image .van-empty__image {
width: 90px;
height: 90px;
}
.bottom-button {
width: 160px;
height: 40px;
}
================================================
FILE: packages/empty/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
activeTab: 0,
},
methods: {
onChange(event) {
this.setData({
activeTab: event.detail.name,
});
},
},
});
================================================
FILE: packages/empty/demo/index.wxml
================================================
按钮
================================================
FILE: packages/empty/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: packages/empty/index.less
================================================
@import '../common/style/var.less';
.van-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: @empty-padding;
&__image {
width: @empty-image-size;
height: @empty-image-size;
&:empty {
display: none;
}
&__img {
width: 100%;
height: 100%;
}
}
&__image:not(:empty) + &__image {
display: none;
}
&__description {
margin-top: @empty-description-margin-top;
padding: @empty-description-padding;
color: @empty-description-color;
font-size: @empty-description-font-size;
line-height: @empty-description-line-height;
&:empty {
display: none;
}
}
&__description:not(:empty) + &__description {
display: none;
}
&__bottom {
margin-top: @empty-bottom-margin-top;
}
}
================================================
FILE: packages/empty/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
description: String,
image: {
type: String,
value: 'default',
},
},
});
================================================
FILE: packages/empty/index.wxml
================================================
{{ description }}
================================================
FILE: packages/empty/index.wxs
================================================
/* eslint-disable */
var PRESETS = ['error', 'search', 'default', 'network'];
function imageUrl(image) {
if (PRESETS.indexOf(image) !== -1) {
return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png';
}
return image;
}
module.exports = {
imageUrl: imageUrl,
};
================================================
FILE: packages/empty/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
描述文字
图片类型
通用错误
网络错误
搜索提示
描述文字
自定义图片
描述文字
底部内容
描述文字
按钮
`;
================================================
FILE: packages/empty/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/field/README.md
================================================
# Field 输入框
### 介绍
用户可以在文本框内输入或编辑文字。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-field": "@vant/weapp/field/index"
}
```
## 代码演示
### 基础用法
```html
```
```js
Page({
data: {
value: '',
},
onChange(event) {
// event.detail 为当前输入的值
console.log(event.detail);
},
});
```
### 双向绑定
最低基础库版本在 2.9.3 以上时,可以使用[简易双向绑定](https://developers.weixin.qq.com/miniprogram/dev/framework/view/two-way-bindings.html)。
```html
```
```js
Page({
data: {
value: '',
},
});
```
### 自定义类型
根据`type`属性定义不同类型的输入框。
```html
```
### 禁用输入框
```html
```
### 错误提示
通过`error`或者`error-message`属性增加对应的错误提示。
```html
```
### 内容对齐方式
可以通过`input-align`属性设置内容的对齐方式。
```html
```
### 高度自适应
对于 textarea,可以通过`autosize`属性设置高度自适应。
```html
```
### 插入按钮
通过 button slot 可以在输入框尾部插入按钮。
```html
发送验证码
```
### 替换输入框值
在微信小程序中,bind:input 事件可以通过返回字符串或者一个对象来替换输入框的值以及调整光标的位置,在 vant-weapp 中,可以通过调用 change 或 input 参数中的 callback 函数,传入参数来实现
```html
```
```js
Page({
data: {
value: '',
},
onChange(e) {
const { value, callback } = e.detail;
callback({
value: value + 1,
cursor: 0,
});
},
});
```
## 常见问题
### 真机上为什么会出现聚焦时 placeholder 加粗、闪烁的现象?
由于微信小程序的 input 组件和 textarea 组件是原生组件,聚焦时会将原生的输入框覆盖在对应位置上,导致了这个现象的产生。
相关的讨论可以查看[微信开放社区](https://developers.weixin.qq.com/community/search?query=placeholder%20%E9%97%AA%E7%83%81%20%E5%8A%A0%E7%B2%97)。
### 真机上 placeholder 为什么会盖过 popup 等其它组件?
由于微信小程序的 input 组件和 textarea 组件是原生组件,遵循原生组件的限制,详情可以查看[原生组件说明](https://developers.weixin.qq.com/miniprogram/dev/component/native-component.html)。
### textarea 的 placeholder 在真机上为什么会偏移?
微信小程序的 textarea 组件在 Android 和 iOS 中默认样式不同,在 iOS 中会有默认的 `padding`,且无法置 0。
同时 `placeholder-style` 对 `vertical-align`、`line-height` 等大量 css 属性都不生效。
这一系列的问题导致了 placeholder 在真机上可能会出现偏移。
微信已经在 `2.10.0` 基础库版本后支持移除默认的 `padding`,但低版本仍有问题。详情可以查看 [微信开放社区](https://developers.weixin.qq.com/community/develop/issue/96)。
### 手写输入法为什么会丢失部分字符 / 手写输入法为什么不会触发 input 事件?
这是微信小程序的 input 组件本身的问题,如果需要兼容手写输入法的场景,可以在 `blur` 事件中取到输入的值。
相关的讨论可以查看[微信开放社区](https://developers.weixin.qq.com/community/search?query=input%20%E6%89%8B%E5%86%99%E8%BE%93%E5%85%A5&page=1&block=1&random=1567079239098)。
### 如何扩大点击区域?点击 label、错误信息 都能聚焦唤起键盘呢?
升级至 1.10.21 版本及以上,配置 `name` 属性即可
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符。可以通过配置 `name` 来扩大点击区域 | _string_ | - |
| label | 输入框左侧文本 | _string_ | - |
| size | 单元格大小,可选值为 `large` | _string_ | - |
| value | 当前输入的值 | _string \| number_ | - |
| type | 可设置为任意原生类型, 如 `number` `idcard` `textarea` `digit` `nickname` | _string_ | `text` |
| fixed | 如果 type 为 `textarea` 且在一个 `position:fixed` 的区域,需要显示指定属性 fixed 为 true | _boolean_ | `false` |
| focus | 获取焦点 | _boolean_ | `false` |
| border | 是否显示内边框 | _boolean_ | `true` |
| disabled | 是否禁用输入框 | _boolean_ | `false` |
| readonly | 是否只读 | _boolean_ | `false` |
| clearable | 是否启用清除控件 | _boolean_ | `false` |
| clickable | 是否开启点击反馈 | _boolean_ | `false` |
| required | 是否显示表单必填星号 | _boolean_ | `false` |
| center | 是否使内容垂直居中 | _boolean_ | `false` |
| password | 是否是密码类型 | _boolean_ | `false` |
| title-width | 标题宽度 | _string_ | `6.2em` |
| maxlength | 最大输入长度,设置为 -1 的时候不限制最大长度 | _number_ | `-1` |
| placeholder | 输入框为空时占位符 | _string_ | - |
| placeholder-style | 指定 placeholder 的样式 | _string_ | - |
| custom-style | 自定义样式 | _string_ | - |
| is-link | 是否展示右侧箭头并开启点击反馈 | _boolean_ | `false` |
| arrow-direction | 箭头方向,可选值为 `left` `up` `down` | _string_ | - |
| show-word-limit | 是否显示字数统计,需要设置`maxlength`属性 | _boolean_ | `false` |
| error | 是否将输入内容标红 | _boolean_ | `false` |
| error-message | 底部错误提示文案,为空时不展示 | _string_ | `''` |
| error-message-align | 底部错误提示文案对齐方式,可选值为 `center` `right` | _string_ | `''` |
| input-align | 输入框内容对齐方式,可选值为 `center` `right` | _string_ | `left` |
| autosize | 是否自适应内容高度,只对 textarea 有效,
可传入对象,如 { maxHeight: 100, minHeight: 50 },
单位为`px` | _boolean \| object_ | `false` |
| left-icon | 左侧图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| right-icon | 右侧图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| confirm-type | 设置键盘右下角按钮的文字,仅在 type='text' 时生效 | _string_ | `done` |
| confirm-hold | 点击键盘右下角按钮时是否保持键盘不收起,在 type='textarea' 时无效 | _boolean_ | `false` |
| hold-keyboard | focus 时,点击页面的时候不收起键盘 | _boolean_ | `false` |
| cursor-spacing | 输入框聚焦时底部与键盘的距离 | _number_ | `50` |
| adjust-position | 键盘弹起时,是否自动上推页面 | _boolean_ | `true` |
| show-confirm-bar | 是否显示键盘上方带有”完成“按钮那一栏,只对 textarea 有效 | _boolean_ | `true` |
| selection-start | 光标起始位置,自动聚集时有效,需与 selection-end 搭配使用 | _number_ | `-1` |
| selection-end | 光标结束位置,自动聚集时有效,需与 selection-start 搭配使用 | _number_ | `-1` |
| auto-focus | 自动聚焦,拉起键盘 | _boolean_ | `false` |
| disable-default-padding | 是否去掉 iOS 下的默认内边距,只对 textarea 有效 | _boolean_ | `true` |
| cursor | 指定 focus 时的光标位置 | _number_ | `-1` |
| clear-trigger `v1.8.4` | 显示清除图标的时机,`always` 表示输入框不为空时展示,
`focus` 表示输入框聚焦且不为空时展示 | _string_ | `focus` |
| always-embed `v1.9.2` | 强制 input 处于同层状态,默认 focus 时 input 会切到非同层状态 (仅在 iOS 下生效) | _boolean_ | `false` |
| extra-event-params `v1.10.12` | 开启事件增强模式,会在 input 和 change 事件额外提供 `cursor` 和 `keyCode` 参数,计划在下一个大版本作为默认行为 | _boolean_ | `false` |
### Events
| 事件 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:input | 输入内容时触发 | event.detail: 当前输入值; 在 extra-event-params 为 `true` 时为 [InputDetail](#/field#inputdetail) |
| bind:change | 输入内容时触发 | event.detail: 当前输入值; 在 extra-event-params 为 `true` 时为 [InputDetail](#/field#inputdetail) |
| bind:confirm | 点击完成按钮时触发 | event.detail: 当前输入值 |
| bind:click-icon | 点击尾部图标时触发 | - |
| bind:focus | 输入框聚焦时触发 | event.detail.value: 当前输入值;
event.detail.height: 键盘高度 |
| bind:blur | 输入框失焦时触发 | event.detail.value: 当前输入值;
event.detail.cursor: 游标位置(如果 `type` 不为 `textarea`,值为 `0`) |
| bind:clear | 点击清空控件时触发 | - |
| bind:click-input | 点击输入区域时触发 | - |
| bind:linechange | 输入框行数变化时调用,只对 textarea 有效 | event.detail = { height: 0, heightRpx: 0, lineCount: 0 } |
| bind:keyboardheightchange | 键盘高度发生变化的时候触发此事件 | event.detail = { height: height, duration: duration } |
| bind:nicknamereview `v1.11.5` | 用户昵称审核完毕后触发,仅在 type 为 "nickname" 时有效 | event.detail = { pass, timeout } |
### InputDetail
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前输入值 | _string_ | - |
| cursor | 光标位置 | _number_ | - |
| keyCode | 键值 | _number_ | - |
| callback | 调用该函数传 `{ value: string, cursor: number }` 来替换输入框的内容,具体用法可以参考 [wx-input](https://developers.weixin.qq.com/miniprogram/dev/component/input.html) | _function_ | - |
### Slot
| 名称 | 说明 |
| ---------- | ---------------------------------------------------------- |
| label | 自定义输入框标签,如果设置了`label`属性则不生效 |
| left-icon | 自定义输入框头部图标 |
| right-icon | 自定义输入框尾部图标 |
| button | 自定义输入框尾部按钮 |
| input | 自定义输入框,使用此插槽后,与输入框相关的属性和事件将失效 |
### 外部样式类
| 类名 | 说明 |
| ----------------------- | -------------- |
| custom-class `v1.10.21` | 根节点样式类 |
| label-class | 左侧文本样式类 |
| input-class | 输入框样式类 |
| right-icon-class | 右侧图标样式类 |
================================================
FILE: packages/field/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-field": "../../field/index",
"van-button": "../../button/index",
"van-cell-group": "../../cell-group/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/field/demo/index.less
================================================
.button {
vertical-align: middle;
}
.custom-icon {
color: #1989fa;
}
================================================
FILE: packages/field/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
sms: '',
value: '',
password: '',
username: '',
username2: '',
username3: '',
message: '',
phone: '1365577',
},
methods: {
onClickIcon() {
wx.showToast({
icon: 'none',
title: '点击图标',
});
},
},
});
================================================
FILE: packages/field/demo/index.wxml
================================================
发送验证码
================================================
FILE: packages/field/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/field/index.less
================================================
@import '../common/style/var.less';
.van-field {
--cell-icon-size: var(--field-icon-size, @field-icon-size);
&__label {
color: var(--field-label-color, @field-label-color);
&--disabled {
color: var(--field-disabled-text-color, @field-disabled-text-color);
}
}
&__body {
display: flex;
align-items: center;
&--textarea {
box-sizing: border-box;
padding: 3.6px 0;
line-height: 1.2em;
min-height: var(--cell-line-height, @cell-line-height);
}
}
&__control:empty + &__control {
display: block;
}
&__control {
position: relative;
display: none;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0;
line-height: inherit;
text-align: left;
background-color: transparent;
border: 0;
resize: none;
color: var(--field-input-text-color, @field-input-text-color);
height: var(--cell-line-height, @cell-line-height);
min-height: var(--cell-line-height, @cell-line-height);
&:empty {
display: none;
}
&--textarea {
height: var(--field-text-area-min-height, @field-text-area-min-height);
min-height: var(
--field-text-area-min-height,
@field-text-area-min-height
);
}
&--error {
color: var(--field-input-error-text-color, @field-input-error-text-color);
}
&--disabled {
background-color: transparent;
opacity: 1;
color: var(
--field-input-disabled-text-color,
@field-input-disabled-text-color
);
}
&--center {
text-align: center;
}
&--right {
text-align: right;
}
&--custom {
display: flex;
align-items: center;
min-height: var(--cell-line-height, @cell-line-height);
}
}
&__placeholder {
position: absolute;
top: 0;
right: 0;
left: 0;
pointer-events: none;
color: var(--field-placeholder-text-color, @field-placeholder-text-color);
&--error {
color: var(--field-error-message-color, @field-error-message-color);
}
}
&__icon-root {
display: flex;
align-items: center;
min-height: var(--cell-line-height, @cell-line-height);
}
&__clear-root,
&__icon-container {
line-height: inherit;
vertical-align: middle;
padding: 0 var(--padding-xs, @padding-xs);
margin-right: calc(-1 * var(--padding-xs, @padding-xs));
}
&__clear-root,
&__icon-container,
&__button {
flex-shrink: 0;
}
&__clear-root {
font-size: var(--field-clear-icon-size, @field-clear-icon-size);
color: var(--field-clear-icon-color, @field-clear-icon-color);
}
&__icon-container {
font-size: var(--field-icon-size, @field-icon-size);
color: var(--field-icon-container-color, @field-icon-container-color);
&:empty {
display: none;
}
}
&__button {
padding-left: var(--padding-xs, @padding-xs);
&:empty {
display: none;
}
}
&__error-message {
display: block;
text-align: left;
font-size: var(
--field-error-message-text-font-size,
@field-error-message-text-font-size
);
color: var(--field-error-message-color, @field-error-message-color);
&--center {
text-align: center;
}
&--right {
text-align: right;
}
}
&__word-limit {
text-align: right;
margin-top: var(--padding-base, @padding-base);
color: var(--field-word-limit-color, @field-word-limit-color);
font-size: var(--field-word-limit-font-size, @field-word-limit-font-size);
line-height: var(
--field-word-limit-line-height,
@field-word-limit-line-height
);
}
&__word-num {
display: inline;
&--full {
color: var(--field-word-num-full-color, @field-word-num-full-color);
}
}
}
================================================
FILE: packages/field/index.ts
================================================
import { nextTick } from '../common/utils';
import { VantComponent } from '../common/component';
import { commonProps, inputProps, textareaProps } from './props';
import { InputDetails } from './types';
VantComponent({
field: true,
classes: ['input-class', 'right-icon-class', 'label-class'],
props: {
...commonProps,
...inputProps,
...textareaProps,
size: String,
icon: String,
label: String,
error: Boolean,
center: Boolean,
isLink: Boolean,
leftIcon: String,
rightIcon: String,
autosize: null,
required: Boolean,
iconClass: String,
clickable: Boolean,
inputAlign: String,
customStyle: String,
errorMessage: String,
arrowDirection: String,
showWordLimit: Boolean,
errorMessageAlign: String,
readonly: {
type: Boolean,
observer: 'setShowClear',
},
clearable: {
type: Boolean,
observer: 'setShowClear',
},
clearTrigger: {
type: String,
value: 'focus',
},
border: {
type: Boolean,
value: true,
},
titleWidth: {
type: String,
value: '6.2em',
},
clearIcon: {
type: String,
value: 'clear',
},
extraEventParams: {
type: Boolean,
value: false,
},
},
data: {
focused: false,
innerValue: '',
showClear: false,
},
watch: {
value(this: WechatMiniprogram.Component.TrivialInstance, value) {
if (value !== this.value) {
this.setData({ innerValue: value });
this.value = value;
this.setShowClear();
}
},
clearTrigger() {
this.setShowClear();
},
},
created() {
this.value = this.data.value;
this.setData({ innerValue: this.value });
},
methods: {
formatValue(value: string) {
const { maxlength } = this.data;
if (maxlength !== -1 && value.length > maxlength) {
return value.slice(0, maxlength);
}
return value;
},
onInput(event: WechatMiniprogram.Input | WechatMiniprogram.TextareaInput) {
const { value = '' } = event.detail || {};
const formatValue = this.formatValue(value);
this.value = formatValue;
this.setShowClear();
return this.emitChange({
...event.detail,
value: formatValue,
});
},
onFocus(
event: WechatMiniprogram.InputFocus | WechatMiniprogram.TextareaFocus
) {
this.focused = true;
this.setShowClear();
this.$emit('focus', event.detail);
},
onBlur(
event: WechatMiniprogram.InputBlur | WechatMiniprogram.TextareaBlur
) {
this.focused = false;
this.setShowClear();
this.$emit('blur', event.detail);
},
onClickIcon() {
this.$emit('click-icon');
},
onClickInput(event: WechatMiniprogram.TouchEvent) {
this.$emit('click-input', event.detail);
},
onClear() {
this.setData({ innerValue: '' });
this.value = '';
this.setShowClear();
nextTick(() => {
this.emitChange({ value: '' });
this.$emit('clear', '');
});
},
onConfirm(
event: WechatMiniprogram.InputConfirm | WechatMiniprogram.TextareaConfirm
) {
const { value = '' } = event.detail || {};
this.value = value;
this.setShowClear();
this.$emit('confirm', value);
},
setValue(value: string) {
this.value = value;
this.setShowClear();
if (value === '') {
this.setData({ innerValue: '' });
}
this.emitChange({ value });
},
onLineChange(event: WechatMiniprogram.TextareaLineChange) {
this.$emit('linechange', event.detail);
},
onKeyboardHeightChange(
event:
| WechatMiniprogram.InputKeyboardHeightChange
| WechatMiniprogram.TextareaKeyboardHeightChange
) {
this.$emit('keyboardheightchange', event.detail);
},
onBindNicknameReview(event) {
this.$emit('nicknamereview', event.detail);
},
emitChange(detail: InputDetails) {
const { extraEventParams } = this.data;
this.setData({ value: detail.value });
let result: InputDetails | undefined;
const data = extraEventParams
? {
...detail,
callback: (data: InputDetails) => {
result = data;
},
}
: detail.value;
this.$emit('input', data);
this.$emit('change', data);
return result;
},
setShowClear() {
const { clearable, readonly, clearTrigger } = this.data;
const { focused, value } = this;
let showClear = false;
if (clearable && !readonly) {
const hasValue = !!value;
const trigger =
clearTrigger === 'always' || (clearTrigger === 'focus' && focused);
showClear = hasValue && trigger;
}
this.setView({ showClear });
},
noop() {},
},
});
================================================
FILE: packages/field/index.wxml
================================================
================================================
FILE: packages/field/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function inputStyle(autosize) {
if (autosize && autosize.constructor === 'Object') {
return style({
'min-height': addUnit(autosize.minHeight),
'max-height': addUnit(autosize.maxHeight),
});
}
return '';
}
module.exports = {
inputStyle: inputStyle,
};
================================================
FILE: packages/field/input.wxml
================================================
================================================
FILE: packages/field/props.ts
================================================
export const commonProps: WechatMiniprogram.Component.PropertyOption = {
value: String,
placeholder: String,
placeholderStyle: String,
placeholderClass: String,
disabled: Boolean,
maxlength: {
type: Number,
value: -1,
},
cursorSpacing: {
type: Number,
value: 50,
},
autoFocus: Boolean,
focus: Boolean,
cursor: {
type: Number,
value: -1,
},
selectionStart: {
type: Number,
value: -1,
},
selectionEnd: {
type: Number,
value: -1,
},
adjustPosition: {
type: Boolean,
value: true,
},
holdKeyboard: Boolean,
};
export const inputProps: WechatMiniprogram.Component.PropertyOption = {
type: {
type: String,
value: 'text',
},
password: Boolean,
confirmType: String,
confirmHold: Boolean,
alwaysEmbed: Boolean,
};
export const textareaProps: WechatMiniprogram.Component.PropertyOption = {
autoHeight: Boolean,
fixed: Boolean,
showConfirmBar: {
type: Boolean,
value: true,
},
disableDefaultPadding: {
type: Boolean,
value: true,
},
};
================================================
FILE: packages/field/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
自定义类型
用户名
密码
禁用输入框
用户名
错误提示
用户名
手机号
手机号格式错误
内容对齐方式
用户名
高度自适应
留言
插入按钮
短信验证码
发送验证码
`;
================================================
FILE: packages/field/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/field/textarea.wxml
================================================
================================================
FILE: packages/field/types.ts
================================================
export interface InputDetails {
/** 输入框内容 */
value: string;
/** 光标位置 */
cursor?: number;
/** keyCode 为键值 (目前工具还不支持返回keyCode参数) `2.1.0` 起支持 */
keyCode?: number;
}
================================================
FILE: packages/goods-action/README.md
================================================
# GoodsAction 商品导航
### 介绍
用于为商品相关操作提供便捷交互。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-goods-action": "@vant/weapp/goods-action/index",
"van-goods-action-icon": "@vant/weapp/goods-action-icon/index",
"van-goods-action-button": "@vant/weapp/goods-action-button/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)。
## 代码演示
### 基础用法
```html
```
```javascript
Page({
onClickIcon() {
Toast('点击图标');
},
onClickButton() {
Toast('点击按钮');
},
});
```
### 提示信息
设置`dot`属性后,会在图标右上角展示一个小红点。设置`info`属性后,会在图标右上角展示相应的徽标。
```html
```
### 自定义按钮颜色
通过`color`属性可以自定义按钮的颜色,支持传入`linear-gradient`渐变色。
```html
```
### 朴素按钮
通过`plain`属性将按钮设置为朴素按钮,朴素按钮的文字为按钮颜色,背景为白色。
```html
```
## API
### GoodsAction Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| safe-area-inset-bottom | 是否为 iPhoneX 留出底部安全距离 | _boolean_ | `true` |
### GoodsActionIcon Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| text | 按钮文字 | _string_ | - |
| icon | 图标类型,可选值见`icon`组件 | _string_ | - |
| info | 图标右上角提示信息 | _string \| number_ | - |
| color `v1.10.15` | 图标颜色 | _string_ | `inherit` |
| size | 图标大小,如 20px,2em,默认单位为px | _string \| number_ | - |
| url | 点击后跳转的链接地址 | _string_ | - |
| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | _string_ | `navigateTo` |
| id | 标识符 | _string_ | - |
| disabled | 是否禁用按钮 | _boolean_ | `false` |
| loading | 是否显示为加载状态 | _boolean_ | `false` |
| open-type | 微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
| app-parameter | 打开 APP 时,向 APP 传递的参数 | _string_ | - |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,
zh_TW 繁体中文,en 英文 | _string_ | `en` |
| session-from | 会话来源 | _string_ | - |
| send-message-title | 会话内消息卡片标题 | _string_ | 当前标题 |
| send-message-path | 会话内消息卡片点击跳转小程序路径 | _string_ | 当前分享路径 |
| send-message-img | sendMessageImg | _string_ | 截图 |
| show-message-card | 显示会话内消息卡片 | _string_ | `false` |
| class-prefix `v1.10.1` | 类名前缀 | _string_ | `van-icon` |
### GoodsActionButton Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| text | 按钮文字 | _string_ | - |
| color | 按钮颜色,支持传入 `linear-gradient` 渐变色 | _string_ | - |
| url | 点击后跳转的链接地址 | _string_ | - |
| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | _string_ | `navigateTo` |
| id | 标识符 | _string_ | - |
| button-id `v1.10.25`| 标识符,作为原生button组件的id值 | _string_ | - |
| type | 按钮类型,可选值为 `primary` `warning` `danger` | _string_ | `danger` |
| plain | 是否为朴素按钮 | _boolean_ | `false` |
| size | 按钮尺寸,可选值为 `normal` `large` `small` `mini` | _string_ | `normal` |
| disabled | 是否禁用按钮 | _boolean_ | `false` |
| loading | 是否显示为加载状态 | _boolean_ | `false` |
| open-type | 微信开放能力,具体支持可参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) | _string_ | - |
| app-parameter | 打开 APP 时,向 APP 传递的参数 | _string_ | - |
| lang | 指定返回用户信息的语言,zh_CN 简体中文,
zh_TW 繁体中文,en 英文 | _string_ | `en` |
| session-from | 会话来源 | _string_ | - |
| send-message-title | 会话内消息卡片标题 | _string_ | 当前标题 |
| send-message-path | 会话内消息卡片点击跳转小程序路径 | _string_ | 当前分享路径 |
| send-message-img | sendMessageImg | _string_ | 截图 |
| show-message-card | 显示会话内消息卡片 | _string_ | `false` |
| custom-style `v1.11.3` | 自定义样式 | _string_ | '' |
### Events
| 事件名 | 说明 | 参数 |
| ------ | ---------------- | ---- |
| bind:click | 按钮点击事件回调 | - |
### GoodsActionIcon Slot
| 名称 | 说明 |
| ---- | ---------- |
| icon | 自定义图标 |
### GoodsActionButton Slot
| 名称 | 说明 |
| ---- | ------------ |
| - | 按钮显示内容 |
### GoodsActionIcon 外部样式类
| 类名 | 说明 |
| ---------- | ---------- |
| icon-class | 图标样式类 |
| text-class | 文字样式类 |
| info-class `v1.10.20` | 图标右上角文字样式类 |
### GoodsActionButton 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/goods-action/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-toast": "../../toast/index",
"van-goods-action": "../../goods-action/index",
"van-goods-action-icon": "../../goods-action-icon/index",
"van-goods-action-button": "../../goods-action-button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/goods-action/demo/index.less
================================================
.goods-action-position {
position: relative !important;
}
================================================
FILE: packages/goods-action/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
methods: {
onClickIcon() {
Toast({ context: this, message: '点击图标' });
},
onClickButton() {
Toast({ context: this, message: '点击按钮' });
},
},
});
================================================
FILE: packages/goods-action/demo/index.wxml
================================================
================================================
FILE: packages/goods-action/index.json
================================================
{
"component": true
}
================================================
FILE: packages/goods-action/index.less
================================================
@import '../common/style/var.less';
.van-goods-action {
position: fixed;
right: 0;
bottom: 0;
left: 0;
display: flex;
align-items: center;
box-sizing: content-box;
height: var(--goods-action-height, @goods-action-height);
background-color: var(
--goods-action-background-color,
@goods-action-background-color
);
&--safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
}
================================================
FILE: packages/goods-action/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('goods-action-button', function () {
this.children.forEach((item) => {
item.updateStyle();
});
}),
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
});
================================================
FILE: packages/goods-action/index.wxml
================================================
================================================
FILE: packages/goods-action/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
客服
购物车
加入购物车
立即购买
提示信息
客服
5
购物车
店铺
加入购物车
立即购买
自定义按钮颜色
客服
店铺
加入购物车
立即购买
朴素按钮
客服
店铺
加入购物车
立即购买
`;
================================================
FILE: packages/goods-action/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/goods-action-button/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
================================================
FILE: packages/goods-action-button/index.less
================================================
@import '../common/style/var.less';
:host {
flex: 1;
}
.van-goods-action-button {
--button-warning-background-color: var(
--goods-action-button-warning-color,
@goods-action-button-warning-color
);
--button-danger-background-color: var(
--goods-action-button-danger-color,
@goods-action-button-danger-color
);
--button-default-height: var(
--goods-action-button-height,
@goods-action-button-height
);
--button-line-height: var(
--goods-action-button-line-height,
@goods-action-button-line-height
);
--button-plain-background-color: var(
--goods-action-button-plain-color,
@goods-action-button-plain-color
);
display: block;
--button-border-width: 0;
&--first {
margin-left: 5px;
--button-border-radius: @goods-action-button-border-radius 0 0
var(
--goods-action-button-border-radius,
@goods-action-button-border-radius
);
}
&--last {
margin-right: 5px;
--button-border-radius: 0 @goods-action-button-border-radius
var(
--goods-action-button-border-radius,
@goods-action-button-border-radius
)
0;
}
&--first&--last {
--button-border-radius: var(
--goods-action-button-border-radius,
@goods-action-button-border-radius
);
}
&--plain {
--button-border-width: @button-border-width;
}
&__inner {
width: 100%;
font-weight: var(--font-weight-bold, @font-weight-bold) !important;
}
@media (max-width: 321px) {
font-size: 13px;
}
}
================================================
FILE: packages/goods-action-button/index.ts
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
mixins: [link, button],
relation: useParent('goods-action'),
props: {
text: String,
color: String,
size: {
type: String,
value: 'normal',
},
loading: Boolean,
disabled: Boolean,
plain: Boolean,
type: {
type: String,
value: 'danger',
},
customStyle: {
type: String,
value: '',
},
},
methods: {
onClick(event: WechatMiniprogram.CustomEvent) {
this.$emit('click', event.detail);
this.jumpLink();
},
updateStyle() {
if (this.parent == null) {
return;
}
const { index } = this;
const { children = [] } = this.parent;
this.setData({
isFirst: index === 0,
isLast: index === children.length - 1,
});
},
},
});
================================================
FILE: packages/goods-action-button/index.wxml
================================================
{{ text }}
================================================
FILE: packages/goods-action-icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-button": "../button/index"
}
}
================================================
FILE: packages/goods-action-icon/index.less
================================================
@import '../common/style/var.less';
.van-goods-action-icon {
display: flex !important;
flex-direction: column;
justify-content: center !important;
line-height: 1 !important;
border: none !important;
font-size: var(
--goods-action-icon-font-size,
@goods-action-icon-font-size
) !important;
color: var(
--goods-action-icon-text-color,
@goods-action-icon-text-color
) !important;
min-width: var(--goods-action-icon-width, @goods-action-icon-width);
height: var(--goods-action-icon-height, @goods-action-icon-height) !important;
&__icon {
display: flex;
margin: 0 auto 5px;
color: var(--goods-action-icon-color, @goods-action-icon-color);
font-size: var(--goods-action-icon-size, @goods-action-icon-size);
}
}
================================================
FILE: packages/goods-action-icon/index.ts
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
classes: ['icon-class', 'text-class', 'info-class'],
mixins: [link, button],
props: {
text: String,
dot: Boolean,
info: String,
icon: String,
size: String,
color: String,
classPrefix: {
type: String,
value: 'van-icon',
},
disabled: Boolean,
loading: Boolean,
},
methods: {
onClick(event: WechatMiniprogram.CustomEvent) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
================================================
FILE: packages/goods-action-icon/index.wxml
================================================
{{ text }}
================================================
FILE: packages/grid/README.md
================================================
# Grid 宫格
### 介绍
宫格可以在水平方向上把页面分隔成等宽度的区块,用于展示内容或进行页面导航。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-grid": "@vant/weapp/grid/index",
"van-grid-item": "@vant/weapp/grid-item/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基本用法
通过`icon`属性设置格子内的图标,`text`属性设置文字内容。
```html
```
### 自定义列数
默认一行展示四个格子,可以通过`column-num`自定义列数。
```html
```
### 自定义内容
通过插槽可以自定义格子展示的内容。
```html
```
### 正方形格子
设置`square`属性后,格子的高度会和宽度保持一致。
```html
```
### 格子间距
通过`gutter`属性设置格子之间的距离。
```html
```
### 内容横排
将`direction`属性设置为`horizontal`,可以让宫格的内容呈横向排列。
```html
```
### 页面跳转
可以通过`url`属性进行页面跳转,通过`link-type`属性控制跳转类型。
```html
```
### 提示信息
设置`dot`属性后,会在图标右上角展示一个小红点。设置`badge`属性后,会在图标右上角展示相应的徽标。
```html
```
## API
### Grid Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| column-num | 列数 | _number_ | `4` |
| icon-size `v1.3.2` | 图标大小,默认单位为`px` | _string_ | `28px` |
| gutter | 格子之间的间距,默认单位为`px` | _string \| number_ | `0` |
| border | 是否显示边框 | _boolean_ | `true` |
| center | 是否将格子内容居中显示 | _boolean_ | `true` |
| square | 是否将格子固定为正方形 | _boolean_ | `false` |
| clickable | 是否开启格子点击反馈 | _boolean_ | `false` |
| direction | 格子内容排列的方向,可选值为 `horizontal` | _string_ | `vertical` |
| reverse `v1.7.0` | 是否调换图标和文本的位置 | _boolean_ | `false` |
| use-slot | 是否使用自定义内容的插槽 | _boolean_ | `false` |
### Grid 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### GridItem Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| text | 文字 | _string_ | - |
| icon | 图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| icon-color | 图标颜色 | _string_ | - |
| icon-prefix `v1.7.0` | 第三方图标前缀 | _string_ | `van-icon` |
| dot | 是否显示图标右上角小红点 | _boolean_ | `false` |
| badge | 图标右上角徽标的内容 | _string \| number_ | - |
| url | 点击后跳转的链接地址 | _string_ | - |
| link-type | 链接跳转类型,可选值为 `redirectTo` `switchTab` `reLaunch` | _string_ | `navigateTo` |
### GridItem Events
| 事件名 | 说明 | 回调参数 |
| ---------- | -------------- | -------- |
| bind:click | 点击格子时触发 | - |
### GridItem Slots
| 名称 | 说明 |
| ---- | ------------------------------------------------------ |
| - | 自定义宫格的所有内容,需要设置`use-slot`属性 |
| icon | 自定义图标,如果设置了`use-slot`或者`icon`属性则不生效 |
| text | 自定义文字,如果设置了`use-slot`或者`text`属性则不生效 |
### GridItem 外部样式类
| 类名 | 说明 |
| ------------- | ------------ |
| custom-class | 根节点样式类 |
| content-class | 内容样式类 |
| icon-class | 图标样式类 |
| text-class | 文本样式类 |
================================================
FILE: packages/grid/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-grid": "../../grid/index",
"van-grid-item": "../../grid-item/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/grid/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
array3: [0, 1, 2],
array4: [0, 1, 2, 3],
array6: [0, 1, 2, 3, 4, 5],
array8: [0, 1, 2, 3, 4, 5, 6, 7],
},
});
================================================
FILE: packages/grid/demo/index.wxml
================================================
================================================
FILE: packages/grid/index.json
================================================
{
"component": true
}
================================================
FILE: packages/grid/index.less
================================================
.van-grid {
position: relative;
box-sizing: border-box;
overflow: hidden;
}
================================================
FILE: packages/grid/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('grid-item'),
props: {
square: {
type: Boolean,
observer: 'updateChildren',
},
gutter: {
type: null,
value: 0,
observer: 'updateChildren',
},
clickable: {
type: Boolean,
observer: 'updateChildren',
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren',
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
direction: {
type: String,
observer: 'updateChildren',
},
iconSize: {
type: String,
observer: 'updateChildren',
},
reverse: {
type: Boolean,
value: false,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => {
child.updateStyle();
});
},
},
});
================================================
FILE: packages/grid/index.wxml
================================================
================================================
FILE: packages/grid/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'padding-left': addUnit(data.gutter),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/grid/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基本用法
文字
文字
文字
文字
自定义列数
文字
文字
文字
文字
文字
文字
自定义内容
正方形格子
文字
文字
文字
文字
文字
文字
文字
文字
格子间距
文字
文字
文字
文字
文字
文字
文字
文字
内容横排
文字
文字
文字
页面跳转
Navigate 跳转
ReLaunch 跳转
徽标提示
文字
99+
文字
`;
================================================
FILE: packages/grid/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/grid-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/grid-item/index.less
================================================
@import '../common/style/var.less';
.van-grid-item {
position: relative;
float: left;
box-sizing: border-box;
&--square {
height: 0;
}
&__content {
display: flex;
flex-direction: column;
box-sizing: border-box;
height: 100%;
padding: var(--grid-item-content-padding, @grid-item-content-padding);
background-color: var(
--grid-item-content-background-color,
@grid-item-content-background-color
);
&::after {
z-index: 1;
border-width: 0 @border-width-base @border-width-base 0;
}
&--surround {
&::after {
border-width: @border-width-base;
}
}
&--center {
align-items: center;
justify-content: center;
}
&--square {
position: absolute;
top: 0;
right: 0;
left: 0;
}
&--horizontal {
flex-direction: row;
.van-grid-item__text {
margin: 0 0 0 @padding-xs;
}
}
&--reverse {
flex-direction: column-reverse;
.van-grid-item__text {
margin: 0 0 @padding-xs;
}
}
&--horizontal&--reverse {
flex-direction: row-reverse;
.van-grid-item__text {
margin: 0 @padding-xs 0 0;
}
}
&--clickable:active {
background-color: var(
--grid-item-content-active-color,
@grid-item-content-active-color
);
}
}
&__icon {
display: flex;
align-items: center;
font-size: var(--grid-item-icon-size, @grid-item-icon-size);
height: var(--grid-item-icon-size, @grid-item-icon-size);
}
&__text {
word-wrap: break-word;
color: var(--grid-item-text-color, @grid-item-text-color);
font-size: var(--grid-item-text-font-size, @grid-item-text-font-size);
}
&__icon + &__text {
margin-top: 8px;
}
}
================================================
FILE: packages/grid-item/index.ts
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { link } from '../mixins/link';
VantComponent({
relation: useParent('grid'),
classes: ['content-class', 'icon-class', 'text-class'],
mixins: [link],
props: {
icon: String,
iconColor: String,
iconPrefix: {
type: String,
value: 'van-icon',
},
dot: Boolean,
info: null,
badge: null,
text: String,
useSlot: Boolean,
},
data: {
viewStyle: '',
},
mounted() {
this.updateStyle();
},
methods: {
updateStyle() {
if (!this.parent) {
return;
}
const { data, children } = this.parent;
const {
columnNum,
border,
square,
gutter,
clickable,
center,
direction,
reverse,
iconSize,
} = data;
this.setData({
center,
border,
square,
gutter,
clickable,
direction,
reverse,
iconSize,
index: children.indexOf(this),
columnNum,
});
},
onClick() {
this.$emit('click');
this.jumpLink();
},
},
});
================================================
FILE: packages/grid-item/index.wxml
================================================
{{ text }}
================================================
FILE: packages/grid-item/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapperStyle(data) {
var width = 100 / data.columnNum + '%';
return style({
width: width,
'padding-top': data.square ? width : null,
'padding-right': addUnit(data.gutter),
'margin-top':
data.index >= data.columnNum && !data.square
? addUnit(data.gutter)
: null,
});
}
function contentStyle(data) {
return data.square
? style({
right: addUnit(data.gutter),
bottom: addUnit(data.gutter),
height: 'auto',
})
: '';
}
module.exports = {
wrapperStyle: wrapperStyle,
contentStyle: contentStyle,
};
================================================
FILE: packages/icon/README.md
================================================
# Icon 图标
### 介绍
基于字体的图标集,可以通过 Icon 组件使用,也可以在其他组件中通过 icon 属性引用。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-icon": "@vant/weapp/icon/index"
}
```
## 代码演示
### 基础用法
`Icon`的`name`属性支持传入图标名称或图片链接。
```html
```
### 提示信息
设置`dot`属性后,会在图标右上角展示一个小红点。设置`info`属性后,会在图标右上角展示相应的徽标。
```html
```
### 图标颜色
设置`color`属性来控制图标颜色。
```html
```
### 图标大小
设置`size`属性来控制图标大小。
```html
```
### 自定义图标
如果需要在现有 Icon 的基础上使用更多图标,可以引入第三方 iconfont 对应的字体文件和 CSS 文件,之后就可以在 Icon 组件中直接使用。例如,可以在 `app.wxss` 文件中引入。
```css
/* 引入第三方或自定义的字体图标样式 */
@font-face {
font-family: 'my-icon';
src: url('./my-icon.ttf') format('truetype');
}
.my-icon {
font-family: 'my-icon';
}
.my-icon-extra::before {
content: '\e626';
}
```
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 图标名称或图片链接 | _string_ | - |
| dot | 是否显示图标右上角小红点 | _boolean_ | `false` |
| info | 图标右上角文字提示 | _string \| number_ | - |
| color | 图标颜色 | _string_ | `inherit` |
| size `v1.10.20` | 图标大小,如 `20px`,`2em`,默认单位为`px` | _string \| number_ | `inherit` |
| custom-style | 自定义样式 | _string_ | - |
| class-prefix | 类名前缀 | _string_ | `van-icon` |
### Events
| 事件名 | 说明 | 参数 |
| ---------- | -------------- | ---- |
| bind:click | 点击图标时触发 | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| info-class | 图标右上角文字样式类 |
## 常见问题
### 开发者工具上提示 Failed to load font 是什么情况?
这个是开发者工具本身的问题,可以忽略,具体可以查看[微信小程序文档](https://developers.weixin.qq.com/miniprogram/dev/api/ui/font/wx.loadFontFace.html) - 注意事项第 5 条。
================================================
FILE: packages/icon/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-col": "../../col/index",
"van-tab": "../../tab/index",
"van-tabs": "../../tabs/index",
"van-icon": "../../icon/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/icon/demo/index.less
================================================
.col {
display: inline-block;
float: none;
text-align: center;
vertical-align: middle;
}
.icon {
margin: 16px 0;
color: #323233;
}
.text {
display: block;
height: 36px;
margin: -4px 0 4px;
padding: 0 5px;
color: #646566;
font-size: 12px;
line-height: 18px;
}
.demo-tab-pane {
margin: 20px;
background-color: #fff;
}
================================================
FILE: packages/icon/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import icons from '@vant/icons/src/config';
VantComponent({
data: {
icons,
active: 0,
demoIcon: 'chat-o',
demoImage: 'https://b.yzcdn.cn/vant/icon-demo-1126.png',
},
methods: {
onSwitch(event) {
this.setData({
active: event.detail.index,
});
},
},
});
================================================
FILE: packages/icon/demo/index.wxml
================================================
{{ item }}
{{ item }}
{{ item }}
================================================
FILE: packages/icon/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: packages/icon/index.less
================================================
@import '../common/style/var.less';
@import '@vant/icons/src/index.less';
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
.van-icon {
&--custom {
position: relative;
}
&--image {
width: 1em;
height: 1em;
}
&__image {
width: 100%;
height: 100%;
}
&__info {
z-index: 1;
}
}
================================================
FILE: packages/icon/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['info-class'],
props: {
dot: Boolean,
info: null,
size: null,
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon',
},
name: String,
},
methods: {
onClick() {
this.$emit('click');
},
},
});
================================================
FILE: packages/icon/index.wxml
================================================
================================================
FILE: packages/icon/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isImage(name) {
return name.indexOf('/') !== -1;
}
function rootClass(data) {
var classes = ['custom-class'];
if (data.classPrefix !== 'van-icon') {
classes.push('van-icon--custom')
}
if (data.classPrefix != null) {
classes.push(data.classPrefix);
}
if (isImage(data.name)) {
classes.push('van-icon--image');
} else if (data.classPrefix != null) {
classes.push(data.classPrefix + '-' + data.name);
}
return classes.join(' ');
}
function rootStyle(data) {
return style([
{
color: data.color,
'font-size': addUnit(data.size),
},
data.customStyle,
]);
}
module.exports = {
isImage: isImage,
rootClass: rootClass,
rootStyle: rootStyle,
};
================================================
FILE: packages/icon/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
用法示例
基础图标
线框风格
实底风格
基础用法
提示信息
9
99+
图标颜色
图标大小
`;
================================================
FILE: packages/icon/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/image/README.md
================================================
# Image 图片
### 介绍
增强版的 img 标签,提供多种图片填充模式,支持图片懒加载、加载中提示、加载失败提示。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-image": "@vant/weapp/image/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)。
## 代码演示
### 基础用法
基础用法与原生 [image](https://developers.weixin.qq.com/miniprogram/dev/component/image.html) 标签一致,可以设置`src`、`width`、`height`等原生属性。
```html
```
### 填充模式
通过`fit`属性可以设置图片填充模式,可选值见下方表格。
```html
```
### 圆形图片
通过`round`属性可以设置图片变圆,注意当图片宽高不相等且`fit`为`contain`或`scale-down`时,将无法填充一个完整的圆形。
```html
```
### 图片懒加载
图片懒加载,在即将进入一定范围(上下三屏)时才开始加载。
```html
```
### 加载中提示
`Image`组件提供了默认的加载中提示,支持通过`loading`插槽自定义内容。
```html
```
### 加载失败提示
`Image`组件提供了默认的加载失败提示,支持通过`error`插槽自定义内容。
```html
加载失败
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| src | 图片链接 | _string_ | - |
| fit | 图片填充模式 | _string_ | _fill_ |
| alt | 替代文本 | _string_ | - |
| width | 宽度,默认单位为`px` | _string \| number_ | - |
| height | 高度,默认单位为`px` | _string \| number_ | - |
| radius | 圆角大小,默认单位为`px` | _string \| number_ | `0` |
| round | 是否显示为圆形 | _boolean_ | `false` |
| lazy-load | 是否懒加载 | _boolean_ | `false` |
| webp `v1.10.11` | 是否解析 webp 格式 | _boolean_ | `false` |
| show-error | 是否展示图片加载失败提示 | _boolean_ | `true` |
| show-loading | 是否展示图片加载中提示 | _boolean_ | `true` |
| use-error-slot | 是否使用 error 插槽 | _boolean_ | `false` |
| use-loading-slot | 是否使用 loading 插槽 | _boolean_ | `false` |
| show-menu-by-longpress | 是否开启长按图片显示识别小程序码菜单 | _boolean_ | `false` |
### 图片填充模式
| 名称 | 含义 |
| --------- | ------------------------------------------------------ |
| contain | 保持宽高缩放图片,使图片的长边能完全显示出来 |
| cover | 保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边 |
| fill | 拉伸图片,使图片填满元素 |
| widthFix | 缩放模式,宽度不变,高度自动变化,保持原图宽高比不变 |
| heightFix | 缩放模式,高度不变,宽度自动变化,保持原图宽高比不变 |
| none | 保持图片原有尺寸 |
### Events
| 事件名 | 说明 | 回调参数 |
| ------ | ------------------ | ------------ |
| bind:click | 点击图片时触发 | event: Event |
| bind:load | 图片加载完毕时触发 | event: Event |
| bind:error | 图片加载失败时触发 | event: Event |
### Slots
| 名称 | 说明 |
| ------- | -------------------------- |
| loading | 自定义加载中的提示内容 |
| error | 自定义加载失败时的提示内容 |
### 外部样式类
| 类名 | 说明 |
| ------------- | -------------- |
| custom-class | 根节点样式类 |
| image-class | 图片样式类 |
| loading-class | loading 样式类 |
| error-class | error 样式类 |
================================================
FILE: packages/image/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-row": "../../row/index",
"van-col": "../../col/index",
"van-image": "../../image/index",
"van-loading": "../../loading/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/image/demo/index.less
================================================
.text {
width: 100%;
margin: 5px 0 20px;
color: #7d7e80;
font-size: 14px;
text-align: center;
}
================================================
FILE: packages/image/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
fits: [
'contain',
'cover',
'fill',
'none',
'scale-down',
'widthFix',
'heightFix',
],
src: 'https://img.yzcdn.cn/vant/cat.jpeg',
},
});
================================================
FILE: packages/image/demo/index.wxml
================================================
{{ fit }}
{{ fit }}
默认提示
自定义提示
默认提示
加载失败
自定义提示
================================================
FILE: packages/image/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: packages/image/index.less
================================================
@import '../common/style/var.less';
.van-image {
position: relative;
display: inline-block;
vertical-align: top;
&--round {
overflow: hidden;
border-radius: 50%;
.van-image__img {
border-radius: inherit;
}
}
&__img,
&__error,
&__loading {
display: block;
width: 100%;
height: 100%;
}
&__error,
&__loading {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: var(--image-placeholder-text-color, @image-placeholder-text-color);
font-size: var(--image-placeholder-font-size, @image-placeholder-font-size);
background-color: var(
--image-placeholder-background-color,
@image-placeholder-background-color
);
}
&__loading-icon {
color: var(--image-loading-icon-color, @image-loading-icon-color);
font-size: var(
--image-loading-icon-size,
@image-loading-icon-size
) !important;
}
&__error-icon {
color: var(--image-error-icon-color, @image-error-icon-color);
font-size: var(--image-error-icon-size, @image-error-icon-size) !important;
}
}
================================================
FILE: packages/image/index.ts
================================================
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
mixins: [button],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: {
type: String,
observer() {
this.setData({
error: false,
loading: true,
});
},
},
round: Boolean,
width: null,
height: null,
radius: null,
lazyLoad: Boolean,
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
fit: {
type: String,
value: 'fill',
},
webp: {
type: Boolean,
value: false,
},
showError: {
type: Boolean,
value: true,
},
showLoading: {
type: Boolean,
value: true,
},
},
data: {
error: false,
loading: true,
viewStyle: '',
},
methods: {
onLoad(event) {
this.setData({
loading: false,
});
this.$emit('load', event.detail);
},
onError(event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
},
},
});
================================================
FILE: packages/image/index.wxml
================================================
================================================
FILE: packages/image/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
width: addUnit(data.width),
height: addUnit(data.height),
'border-radius': addUnit(data.radius),
},
data.radius ? 'overflow: hidden' : null,
]);
}
var FIT_MODE_MAP = {
none: 'center',
fill: 'scaleToFill',
cover: 'aspectFill',
contain: 'aspectFit',
widthFix: 'widthFix',
heightFix: 'heightFix',
};
function mode(fit) {
return FIT_MODE_MAP[fit];
}
module.exports = {
rootStyle: rootStyle,
mode: mode,
};
================================================
FILE: packages/image/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
填充模式
contain
cover
fill
none
scale-down
widthFix
heightFix
圆形图片
contain
cover
fill
none
scale-down
widthFix
heightFix
加载中提示
默认提示
自定义提示
加载失败提示
默认提示
自定义提示
`;
================================================
FILE: packages/image/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/index-anchor/index.json
================================================
{
"component": true
}
================================================
FILE: packages/index-anchor/index.less
================================================
@import '../common/style/var.less';
.van-index-anchor {
padding: var(--index-anchor-padding, @index-anchor-padding);
color: var(--index-anchor-text-color, @index-anchor-text-color);
font-weight: var(--index-anchor-font-weight, @index-anchor-font-weight);
font-size: var(--index-anchor-font-size, @index-anchor-font-size);
line-height: var(--index-anchor-line-height, @index-anchor-line-height);
background-color: var(
--index-anchor-background-color,
@index-anchor-background-color
);
&--active {
right: 0;
left: 0;
color: var(
--index-anchor-active-text-color,
@index-anchor-active-text-color
);
background-color: var(
--index-anchor-active-background-color,
@index-anchor-active-background-color
);
}
}
================================================
FILE: packages/index-anchor/index.ts
================================================
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
relation: useParent('index-bar'),
props: {
useSlot: Boolean,
index: null,
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: '',
},
methods: {
scrollIntoView(scrollTop) {
getRect(this, '.van-index-anchor-wrapper').then((rect) => {
wx.pageScrollTo({
duration: 0,
scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
});
});
},
},
});
================================================
FILE: packages/index-anchor/index.wxml
================================================
{{ index }}
================================================
FILE: packages/index-bar/README.md
================================================
# IndexBar 索引栏
### 介绍
用于列表的索引分类显示和快速定位。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-index-bar": "@vant/weapp/index-bar/index",
"van-index-anchor": "@vant/weapp/index-anchor/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基础用法
点击索引栏时,会自动跳转到对应的`IndexAnchor`锚点位置。
```html
...
```
### 自定义索引列表
可以通过`index-list`属性自定义展示的索引字符列表。
```html
标题1
标题2
...
```
```javascript
Page({
data: {
indexList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
},
});
```
## API
### IndexBar Props
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| index-list | 索引字符列表 | _string[] \| number[]_ | `A-Z` | - |
| z-index | z-index 层级 | _number_ | `1` | - |
| sticky | 是否开启锚点自动吸顶 | _boolean_ | `true` | - |
| sticky-offset-top | 锚点自动吸顶时与顶部的距离 | _number_ | `0` | - |
| highlight-color | 索引字符高亮颜色 | _string_ | `#07c160` | - |
### IndexAnchor Props
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ------------------------ | ------------------ | ------- | ---- |
| use-slot | 是否使用自定义内容的插槽 | _boolean_ | `false` | - |
| index | 索引字符 | _string \| number_ | - | - |
### IndexBar Events
| 事件名 | 说明 | 回调参数 |
| ------ | -------------- | --------------- |
| select | 选中字符时触发 | index: 索引字符 |
### IndexAnchor Slots
| 名称 | 说明 |
| ---- | -------------------------------- |
| - | 锚点位置显示内容,默认为索引字符 |
## 常见问题
### 嵌套在滚动元素中 IndexAnchor 失效?
由于 `` 内部使用 wx.pageScrollTo 滚动到指定位置,因此只支持页面级滚动,无法在滚动元素中嵌套使用,例如:`view` 使用 `overflow: scroll;` 或者 `scroll-view`,具体可查看[微信小程序文档](https://developers.weixin.qq.com/miniprogram/dev/api/ui/scroll/wx.pageScrollTo.html)。历史 issue: [#4252](https://github.com/youzan/vant-weapp/issues/4252)
================================================
FILE: packages/index-bar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tab": "../../tab/index",
"van-tabs": "../../tabs/index",
"van-cell": "../../cell/index",
"van-index-bar": "../../index-bar/index",
"van-index-anchor": "../../index-anchor/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/index-bar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
const indexList: string[] = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
VantComponent({
data: {
activeTab: 0,
indexList,
customIndexList: [1, 2, 3, 4, 5, 6, 8, 9, 10],
scrollTop: 0,
},
methods: {
onChange(event) {
this.setData({
activeTab: event.detail.name,
});
},
onPageScroll(event) {
this.setData({
scrollTop: event.scrollTop,
});
},
},
});
================================================
FILE: packages/index-bar/demo/index.wxml
================================================
标题{{ item }}
================================================
FILE: packages/index-bar/index.json
================================================
{
"component": true
}
================================================
FILE: packages/index-bar/index.less
================================================
@import '../common/style/var.less';
.van-index-bar {
position: relative;
&__sidebar {
position: fixed;
top: 50%;
right: 0;
display: flex;
flex-direction: column;
text-align: center;
transform: translateY(-50%);
user-select: none;
}
&__index {
font-weight: 500;
padding: 0 var(--padding-base, @padding-base) 0
var(--padding-md, @padding-md);
font-size: var(--index-bar-index-font-size, @index-bar-index-font-size);
line-height: var(
--index-bar-index-line-height,
@index-bar-index-line-height
);
}
}
================================================
FILE: packages/index-bar/index.ts
================================================
import { GREEN } from '../common/color';
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect, isDef } from '../common/utils';
import { pageScrollMixin } from '../mixins/page-scroll';
const indexList = () => {
const indexList: string[] = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
VantComponent({
relation: useChildren('index-anchor', function () {
this.updateData();
}),
props: {
sticky: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
highlightColor: {
type: String,
value: GREEN,
},
stickyOffsetTop: {
type: Number,
value: 0,
},
indexList: {
type: Array,
value: indexList(),
},
},
mixins: [
pageScrollMixin(function (event) {
this.scrollTop = event?.scrollTop || 0;
this.onScroll();
}),
],
data: {
activeAnchorIndex: null,
showSidebar: false,
},
created() {
this.scrollTop = 0;
},
methods: {
updateData() {
wx.nextTick(() => {
if (this.timer != null) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
this.setData({
showSidebar: !!this.children.length,
});
this.setRect().then(() => {
this.onScroll();
});
}, 0);
});
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect(),
]);
},
setAnchorsRect() {
return Promise.all(
this.children.map((anchor) =>
getRect(anchor, '.van-index-anchor-wrapper').then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top + this.scrollTop,
});
})
)
);
},
setListRect() {
return getRect(this, '.van-index-bar').then((rect) => {
if (!isDef(rect)) {
return;
}
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop,
});
});
},
setSiderbarRect() {
return getRect(this, '.van-index-bar__sidebar').then((res) => {
if (!isDef(res)) {
return;
}
this.sidebar = {
height: res.height,
top: res.top,
};
});
},
setDiffData({ target, data }) {
const diffData = {};
Object.keys(data).forEach((key) => {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect(anchor) {
return getRect(anchor, '.van-index-anchor-wrapper').then((rect) => ({
height: rect.height,
top: rect.top,
}));
},
getActiveAnchorIndex() {
const { children, scrollTop } = this;
const { sticky, stickyOffsetTop } = this.data;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const { children = [], scrollTop } = this;
if (!children.length) {
return;
}
const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
const active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active,
},
});
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = `
color: ${highlightColor};
`;
if (isActiveAnchorSticky) {
wrapperStyle = `
height: ${children[index].height}px;
`;
anchorStyle = `
position: fixed;
top: ${stickyOffsetTop}px;
z-index: ${zIndex};
color: ${highlightColor};
`;
}
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
wrapperStyle,
},
});
} else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop =
index === children.length - 1
? this.top
: children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = `
position: relative;
transform: translate3d(0, ${translateY}px, 0);
z-index: ${zIndex};
color: ${highlightColor};
`;
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
},
});
} else {
this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
},
});
}
});
}
},
onClick(event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove(event) {
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
} else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop() {
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find(
(item) => item.data.index === this.data.indexList[index]
);
if (anchor) {
anchor.scrollIntoView(this.scrollTop);
this.$emit('select', anchor.data.index);
}
},
},
});
================================================
FILE: packages/index-bar/index.wxml
================================================
================================================
FILE: packages/index-bar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
自定义索引列表
A
文本
文本
文本
B
文本
文本
文本
C
文本
文本
文本
D
文本
文本
文本
E
文本
文本
文本
F
文本
文本
文本
G
文本
文本
文本
H
文本
文本
文本
I
文本
文本
文本
J
文本
文本
文本
K
文本
文本
文本
L
文本
文本
文本
M
文本
文本
文本
N
文本
文本
文本
O
文本
文本
文本
P
文本
文本
文本
Q
文本
文本
文本
R
文本
文本
文本
S
文本
文本
文本
T
文本
文本
文本
U
文本
文本
文本
V
文本
文本
文本
W
文本
文本
文本
X
文本
文本
文本
Y
文本
文本
文本
Z
文本
文本
文本
`;
================================================
FILE: packages/index-bar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/info/index.json
================================================
{
"component": true
}
================================================
FILE: packages/info/index.less
================================================
@import '../common/style/var.less';
.van-info {
position: absolute;
top: 0;
right: 0;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
white-space: nowrap;
transform: translate(50%, -50%);
transform-origin: 100%;
height: var(--info-size, @info-size);
min-width: var(--info-size, @info-size);
padding: var(--info-padding, @info-padding);
color: var(--info-color, @info-color);
font-weight: var(--info-font-weight, @info-font-weight);
font-size: var(--info-font-size, @info-font-size);
font-family: var(--info-font-family, @info-font-family);
background-color: var(--info-background-color, @info-background-color);
border: var(--info-border-width, @info-border-width) solid @white;
border-radius: var(--info-size, @info-size);
&--dot {
min-width: 0;
border-radius: 100%;
width: var(--info-dot-size, @info-dot-size);
height: var(--info-dot-size, @info-dot-size);
background-color: var(--info-dot-color, @info-dot-color);
}
}
================================================
FILE: packages/info/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
dot: Boolean,
info: null,
customStyle: String,
},
});
================================================
FILE: packages/info/index.wxml
================================================
{{ dot ? '' : info }}
================================================
FILE: packages/loading/README.md
================================================
# Loading 加载
### 介绍
加载图标,用于表示加载中的过渡状态。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-loading": "@vant/weapp/loading/index"
}
```
## 代码演示
### 加载类型
```html
```
### 自定义颜色
```html
```
### 加载文案
```html
加载中...
```
### 垂直排列
```html
加载中...
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| color | 颜色 | _string_ | `#c9c9c9` |
| type | 类型,可选值为 `spinner` | _string_ | `circular` |
| size | 加载图标大小,默认单位为 `px` | _string \| number_ | `30px` |
| text-size `v1.0.0` | 文字大小,默认单位为为 `px` | _string \| number_ | `14px` |
| vertical `v1.0.0` | 是否垂直排列图标和文字内容 | _boolean_ | `false` |
### Slots
| 名称 | 说明 |
| ---- | -------- |
| - | 加载文案 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/loading/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-loading": "../../loading/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/loading/demo/index.less
================================================
.demo-loading {
margin: 4px 16px 4px 0;
}
================================================
FILE: packages/loading/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/loading/demo/index.wxml
================================================
加载中...
加载中...
================================================
FILE: packages/loading/index.json
================================================
{
"component": true
}
================================================
FILE: packages/loading/index.less
================================================
@import '../common/style/var.less';
:host {
font-size: 0;
line-height: 1;
}
.van-loading {
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--loading-spinner-color, @loading-spinner-color);
&__spinner {
position: relative;
box-sizing: border-box;
width: var(--loading-spinner-size, @loading-spinner-size);
// compatible for 0.x, users may set width or height in root element
max-width: 100%;
max-height: 100%;
height: var(--loading-spinner-size, @loading-spinner-size);
animation: van-rotate
var(
--loading-spinner-animation-duration,
@loading-spinner-animation-duration
)
linear infinite;
&--spinner {
animation-timing-function: steps(12);
}
&--circular {
border: 1px solid transparent;
border-top-color: currentColor;
border-radius: 100%;
}
}
&__text {
margin-left: var(--padding-xs, @padding-xs);
color: var(--loading-text-color, @loading-text-color);
font-size: var(--loading-text-font-size, @loading-text-font-size);
line-height: var(--loading-text-line-height, @loading-text-line-height);
&:empty {
display: none;
}
}
&--vertical {
flex-direction: column;
.van-loading__text {
margin: var(--padding-xs, @padding-xs) 0 0;
}
}
&__dot {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
&::before {
display: block;
width: 2px;
height: 25%;
margin: 0 auto;
background-color: currentColor;
border-radius: 40%;
content: ' ';
}
}
}
.generate(@n, @i: 1) when (@i =< @n) {
.van-loading__dot:nth-of-type(@{i}) {
transform: rotate(@i * 30deg);
opacity: 1 - (0.75 / 12) * (@i - 1);
}
.generate(@n, (@i + 1));
}
.generate(12);
@keyframes van-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
================================================
FILE: packages/loading/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
color: String,
vertical: Boolean,
type: {
type: String,
value: 'circular',
},
size: String,
textSize: String,
},
data: {
array12: Array.from({ length: 12 }),
},
});
================================================
FILE: packages/loading/index.wxml
================================================
================================================
FILE: packages/loading/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function spinnerStyle(data) {
return style({
color: data.color,
width: addUnit(data.size),
height: addUnit(data.size),
});
}
function textStyle(data) {
return style({
'font-size': addUnit(data.textSize),
});
}
module.exports = {
spinnerStyle: spinnerStyle,
textStyle: textStyle,
};
================================================
FILE: packages/loading/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
加载类型
自定义颜色
加载文案
加载中...
垂直排列
加载中...
`;
================================================
FILE: packages/loading/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/mixins/basic.ts
================================================
export const basic = Behavior({
methods: {
$emit(
name: string,
detail?: Record,
options?: WechatMiniprogram.Component.TriggerEventOption
) {
this.triggerEvent(name, detail, options);
},
set(data: Record) {
this.setData(data);
return new Promise((resolve) => wx.nextTick(resolve));
},
// high performance setData
setView(
this: WechatMiniprogram.Component.TrivialInstance,
data: Record,
callback?: () => void
) {
const target: Record = {};
let hasChange = false;
Object.keys(data).forEach((key) => {
if (data[key] !== this.data[key]) {
target[key] = data[key];
hasChange = true;
}
});
if (hasChange) {
return this.setData(target, callback);
}
return callback && callback();
},
},
});
================================================
FILE: packages/mixins/button.ts
================================================
import { canIUseGetUserProfile } from '../common/version';
export const button = Behavior({
externalClasses: ['hover-class'],
properties: {
id: String,
buttonId: String,
lang: String,
businessId: Number,
sessionFrom: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean,
appParameter: String,
ariaLabel: String,
openType: String,
getUserProfileDesc: String,
},
data: {
canIUseGetUserProfile: canIUseGetUserProfile(),
},
methods: {
onGetUserInfo(event: WechatMiniprogram.ButtonGetUserInfo) {
this.triggerEvent('getuserinfo', event.detail);
},
onContact(event: WechatMiniprogram.ButtonContact) {
this.triggerEvent('contact', event.detail);
},
onGetPhoneNumber(event: WechatMiniprogram.ButtonGetPhoneNumber) {
this.triggerEvent('getphonenumber', event.detail);
},
onGetRealTimePhoneNumber(event: WechatMiniprogram.ButtonGetPhoneNumber) {
this.triggerEvent('getrealtimephonenumber', event.detail);
},
onError(event: WechatMiniprogram.ButtonError) {
this.triggerEvent('error', event.detail);
},
onLaunchApp(event: WechatMiniprogram.ButtonLaunchApp) {
this.triggerEvent('launchapp', event.detail);
},
onOpenSetting(event: WechatMiniprogram.ButtonOpenSetting) {
this.triggerEvent('opensetting', event.detail);
},
onAgreePrivacyAuthorization(event) {
this.triggerEvent('agreeprivacyauthorization', event.detail);
},
onChooseAvatar(
event: WechatMiniprogram.CustomEvent<
WechatMiniprogram.GeneralCallbackResult & { avatarUrl: string }
>
) {
this.triggerEvent('chooseavatar', event.detail);
},
},
});
================================================
FILE: packages/mixins/link.ts
================================================
export const link = Behavior({
properties: {
url: String,
linkType: {
type: String,
value: 'navigateTo',
},
},
methods: {
jumpLink(urlKey = 'url') {
const url = this.data[urlKey];
if (url) {
if (
this.data.linkType === 'navigateTo' &&
getCurrentPages().length > 9
) {
wx.redirectTo({ url });
} else {
wx[this.data.linkType]({ url });
}
}
},
},
});
================================================
FILE: packages/mixins/page-scroll.ts
================================================
import { isFunction } from '../common/validator';
import { getCurrentPage, isDef } from '../common/utils';
type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
type Scroller = (
this: WechatMiniprogram.Component.TrivialInstance,
event?: IPageScrollOption
) => void;
function onPageScroll(event?: IPageScrollOption) {
const { vanPageScroller = [] } = getCurrentPage<{
vanPageScroller: Scroller[];
}>();
vanPageScroller.forEach((scroller: Scroller) => {
if (typeof scroller === 'function') {
// @ts-ignore
scroller(event);
}
});
}
export function pageScrollMixin(scroller: Scroller) {
return Behavior({
attached(this: WechatMiniprogram.Component.TrivialInstance) {
const page = getCurrentPage<{ vanPageScroller: Scroller[] }>();
if (!isDef(page)) {
return;
}
const _scroller = scroller.bind(this);
const { vanPageScroller = [] } = page;
if (isFunction(page.onPageScroll) && page.onPageScroll !== onPageScroll) {
vanPageScroller.push(page.onPageScroll.bind(page));
}
vanPageScroller.push(_scroller);
page.vanPageScroller = vanPageScroller;
page.onPageScroll = onPageScroll;
this._scroller = _scroller;
},
detached(this: WechatMiniprogram.Component.TrivialInstance) {
const page = getCurrentPage<{ vanPageScroller: Scroller[] }>();
if (!isDef(page) || !isDef(page.vanPageScroller)) {
return;
}
const { vanPageScroller } = page;
const index = vanPageScroller.findIndex((v) => v === this._scroller);
if (index > -1) {
page.vanPageScroller.splice(index, 1);
}
this._scroller = undefined;
},
});
}
================================================
FILE: packages/mixins/touch.ts
================================================
// @ts-nocheck
const MIN_DISTANCE = 10;
function getDirection(x: number, y: number) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
export const touch = Behavior({
methods: {
resetTouchStatus() {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
touchStart(event: WechatMiniprogram.TouchEvent) {
this.resetTouchStatus();
const touch = event.touches[0];
this.startX = touch.clientX;
this.startY = touch.clientY;
},
touchMove(event: WechatMiniprogram.TouchEvent) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction =
this.direction || getDirection(this.offsetX, this.offsetY);
},
},
});
================================================
FILE: packages/mixins/transition.ts
================================================
// @ts-nocheck
import { requestAnimationFrame } from '../common/utils';
import { isObj } from '../common/validator';
const getClassNames = (name: string) => ({
enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
});
export function transition(showDefaultValue: boolean) {
return Behavior({
properties: {
customStyle: String,
// @ts-ignore
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow',
},
// @ts-ignore
duration: {
type: null,
value: 300,
},
name: {
type: String,
value: 'fade',
},
},
data: {
type: '',
inited: false,
display: false,
},
ready() {
if (this.data.show === true) {
this.observeShow(true, false);
}
},
methods: {
observeShow(value: boolean, old: boolean) {
if (value === old) {
return;
}
value ? this.enureEnter() : this.enureLeave();
},
enureEnter() {
if (this.enterPromise) return;
this.enterPromise = new Promise((resolve) => this.enter(resolve));
},
enureLeave() {
const { enterPromise } = this;
if (!enterPromise) return;
enterPromise
.then(() => new Promise((resolve) => this.leave(resolve)))
.then(() => {
this.enterPromise = null;
});
},
enter(resolve: () => void) {
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.enter : duration;
if (this.status === 'enter') {
return;
}
this.status = 'enter';
this.$emit('before-enter');
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.$emit('enter');
this.setData({
inited: true,
display: true,
classes: classNames.enter,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.transitionEnded = false;
this.setData({ classes: classNames['enter-to'] });
resolve();
});
});
},
leave(resolve: () => void) {
if (!this.data.display) {
return;
}
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.leave : duration;
this.status = 'leave';
this.$emit('before-leave');
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.$emit('leave');
this.setData({
classes: classNames.leave,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.transitionEnded = false;
setTimeout(() => {
this.onTransitionEnd();
resolve();
}, currentDuration);
this.setData({ classes: classNames['leave-to'] });
});
});
},
onTransitionEnd() {
if (this.transitionEnded) {
return;
}
this.transitionEnded = true;
this.$emit(`after-${this.status}`);
const { show, display } = this.data;
if (!show && display) {
this.setData({ display: false });
}
},
},
});
}
================================================
FILE: packages/nav-bar/README.md
================================================
# NavBar 导航栏
### 介绍
为页面提供导航功能,常用于页面顶部。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-nav-bar": "@vant/weapp/nav-bar/index"
}
```
## 代码演示
### 基础用法
```html
```
```js
Page({
onClickLeft() {
wx.showToast({ title: '点击返回', icon: 'none' });
},
onClickRight() {
wx.showToast({ title: '点击按钮', icon: 'none' });
},
});
```
### 高级用法
通过 slot 定制内容。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 标题 | _string_ | `''` |
| left-text | 左侧文案 | _string_ | `''` |
| right-text | 右侧文案 | _string_ | `''` |
| left-arrow | 是否显示左侧箭头 | _boolean_ | `false` |
| fixed | 是否固定在顶部 | _boolean_ | `false` |
| placeholder | 固定在顶部时是否开启占位 | _boolean_ | `false` |
| border | 是否显示下边框 | _boolean_ | `true` |
| z-index | 元素 z-index | _number_ | `1` |
| custom-style | 根节点自定义样式 | _string_ | - |
| safe-area-inset-top | 是否留出顶部安全距离(状态栏高度) | _boolean_ | `true` |
### Slot
| 名称 | 说明 |
| ----- | ------------------ |
| title | 自定义标题 |
| left | 自定义左侧区域内容 |
| right | 自定义右侧区域内容 |
### Events
| 事件名 | 说明 | 参数 |
| ---------------- | ------------------ | ---- |
| bind:click-left | 点击左侧按钮时触发 | - |
| bind:click-right | 点击右侧按钮时触发 | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| title-class | 标题样式类 |
================================================
FILE: packages/nav-bar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../../icon/index",
"van-nav-bar": "../../nav-bar/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/nav-bar/demo/index.less
================================================
.icon {
color: #1989fa;
}
================================================
FILE: packages/nav-bar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
methods: {
onClickLeft() {
wx.showToast({ title: '点击返回', icon: 'none' });
},
onClickRight() {
wx.showToast({ title: '点击按钮', icon: 'none' });
},
},
});
================================================
FILE: packages/nav-bar/demo/index.wxml
================================================
================================================
FILE: packages/nav-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/nav-bar/index.less
================================================
@import '../common/style/var.less';
.van-nav-bar {
position: relative;
text-align: center;
user-select: none;
height: var(--nav-bar-height, @nav-bar-height);
line-height: var(--nav-bar-height, @nav-bar-height);
background-color: var(--nav-bar-background-color, @nav-bar-background-color);
box-sizing: content-box;
&__content {
position: relative;
height: 100%;
}
&__text {
display: inline-block;
vertical-align: middle;
margin: 0 calc(-1 * var(--padding-md, @padding-md));
padding: 0 var(--padding-md, @padding-md);
color: var(--nav-bar-text-color, @nav-bar-text-color);
&--hover {
background-color: @active-color;
}
}
&__arrow {
vertical-align: middle;
font-size: var(--nav-bar-arrow-size, @nav-bar-arrow-size) !important;
color: var(--nav-bar-icon-color, @nav-bar-icon-color) !important;
+ .van-nav-bar__text {
margin-left: -20px;
padding-left: 25px;
}
}
&--fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
&__title {
max-width: 60%;
margin: 0 auto;
color: var(--nav-bar-title-text-color, @nav-bar-title-text-color);
font-weight: var(--font-weight-bold, @font-weight-bold);
font-size: var(--nav-bar-title-font-size, @nav-bar-title-font-size);
}
&__left,
&__right {
position: absolute;
top: 0;
bottom: 0;
display: flex;
align-items: center;
font-size: var(--font-size-md, @font-size-md);
}
&__left {
left: var(--padding-md, @padding-md);
}
&__right {
right: var(--padding-md, @padding-md);
}
}
================================================
FILE: packages/nav-bar/index.ts
================================================
import { VantComponent } from '../common/component';
import { getRect, getSystemInfoSync } from '../common/utils';
VantComponent({
classes: ['title-class'],
props: {
title: String,
fixed: {
type: Boolean,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
leftText: String,
rightText: String,
customStyle: String,
leftArrow: Boolean,
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetTop: {
type: Boolean,
value: true,
},
},
data: {
height: 46,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({
statusBarHeight,
height: 46 + statusBarHeight,
});
},
mounted() {
this.setHeight();
},
methods: {
onClickLeft() {
this.$emit('click-left');
},
onClickRight() {
this.$emit('click-right');
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-nav-bar').then((res) => {
if (res && 'height' in res) {
this.setData({ height: res.height });
}
});
});
},
},
});
================================================
FILE: packages/nav-bar/index.wxml
================================================
{{ leftText }}
{{ title }}
{{ rightText }}
================================================
FILE: packages/nav-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function barStyle(data) {
return style({
'z-index': data.zIndex,
'padding-top': data.safeAreaInsetTop ? data.statusBarHeight + 'px' : 0,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: packages/nav-bar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标题
按钮
高级用法
返回
标题
`;
================================================
FILE: packages/nav-bar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/notice-bar/README.md
================================================
# NoticeBar 通知栏
### 介绍
用于循环播放展示一组消息通知。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-notice-bar": "@vant/weapp/notice-bar/index"
}
```
## 代码演示
### 基础用法
```html
```
### 滚动播放
通知栏的内容长度溢出时会自动开启滚动播放,通过 `scrollable` 属性可以控制该行为。
```html
```
### 多行展示
文字较长时,可以通过设置 `wrapable` 属性来开启多行展示。
```html
```
### 通知栏模式
通知栏支持 `closeable` 和 `link` 两种模式。
```html
```
### 自定义样式
通过 `color` 属性设置文本颜色,通过 `background` 属性设置背景色。
```html
```
### 自定义滚动速率
使用`speed`属性控制滚动速率。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| mode | 通知栏模式,可选值为 `closeable` `link` | _string_ | `''` |
| text | 通知文本内容 | _string_ | `''` |
| color | 通知文本颜色 | _string_ | `#ed6a0c` |
| background | 滚动条背景 | _string_ | `#fffbe8` |
| left-icon | 左侧[图标名称](#/icon)或图片链接 | _string_ | - |
| delay | 动画延迟时间 (ms) | _number_ | `1` |
| speed | 滚动速率 (px/s) | _number_ | `60` |
| scrollable | 是否开启滚动播放,内容长度溢出时默认开启 | _boolean_ | - |
| wrapable | 是否开启文本换行,只在禁用滚动时生效 | _boolean_ | `false` |
| open-type | 微信开放能力 | _string_ | `navigate` |
### Events
| 事件名 | 说明 | 参数 |
| ------ | ---------------- | -------------- |
| bind:click | 点击通知栏时触发 | _event: Event_ |
| bind:close | 关闭通知栏时触发 | _event: Event_ |
### Slot
| 名称 | 说明 |
| ---------- | ---------------------------------------- |
| - | 通知文本内容,仅在 `text` 属性为空时有效 |
| left-icon | 自定义左侧图标 |
| right-icon | 自定义右侧图标 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### 样式变量
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](#/config-provider)。
| 名称 | 默认值 | 描述 |
| --- | --- | --- |
| --notice-bar-height | _40px_ | - |
| --notice-bar-padding | _0 var(--van-padding-md)_ | - |
| --notice-bar-wrapable-padding | _var(--van-padding-xs) var(--van-padding-md)_ | - |
| --notice-bar-text-color | _var(--van-orange-dark)_ | - |
| --notice-bar-font-size | _var(--van-font-size-md)_ | - |
| --notice-bar-line-height | _24px_ | - |
| --notice-bar-background-color | _var(--van-orange-light)_ | - |
| --notice-bar-icon-size | _16px_ | - |
| --notice-bar-icon-min-width | _24px_ | - |
================================================
FILE: packages/notice-bar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-notice-bar": "../../notice-bar/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/notice-bar/demo/index.less
================================================
.margin-top {
margin-top: 4px;
}
================================================
FILE: packages/notice-bar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
text: '在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。',
shortText: '技术是开发它的人的共同灵魂。',
},
});
================================================
FILE: packages/notice-bar/demo/index.wxml
================================================
================================================
FILE: packages/notice-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/notice-bar/index.less
================================================
@import '../common/style/var.less';
.van-notice-bar {
display: flex;
align-items: center;
height: var(--notice-bar-height, @notice-bar-height);
padding: var(--notice-bar-padding, @notice-bar-padding);
font-size: var(--notice-bar-font-size, @notice-bar-font-size);
color: var(--notice-bar-text-color, @notice-bar-text-color);
line-height: var(--notice-bar-line-height, @notice-bar-line-height);
background-color: var(
--notice-bar-background-color,
@notice-bar-background-color
);
&--withicon {
position: relative;
padding-right: 40px;
}
&--wrapable {
height: auto;
padding: var(--notice-bar-wrapable-padding, @notice-bar-wrapable-padding);
.van-notice-bar {
&__wrap {
height: auto;
}
&__content {
position: relative;
white-space: normal;
}
}
}
&__left-icon {
display: flex;
align-items: center;
margin-right: 4px;
vertical-align: middle;
font-size: var(--notice-bar-icon-size, @notice-bar-icon-size);
min-width: var(--notice-bar-icon-min-width, @notice-bar-icon-min-width);
}
&__right-icon {
position: absolute;
top: 10px;
right: 15px;
font-size: var(--notice-bar-icon-size, @notice-bar-icon-size);
min-width: var(--notice-bar-icon-min-width, @notice-bar-icon-min-width);
}
&__wrap {
position: relative;
flex: 1;
overflow: hidden;
height: var(--notice-bar-line-height, @notice-bar-line-height);
}
&__content {
position: absolute;
white-space: nowrap;
&.van-ellipsis {
max-width: 100%;
}
}
}
================================================
FILE: packages/notice-bar/index.ts
================================================
import { VantComponent } from '../common/component';
import { getRect, requestAnimationFrame } from '../common/utils';
VantComponent({
props: {
text: {
type: String,
value: '',
observer: 'init',
},
mode: {
type: String,
value: '',
},
url: {
type: String,
value: '',
},
openType: {
type: String,
value: 'navigate',
},
delay: {
type: Number,
value: 1,
},
speed: {
type: Number,
value: 60,
observer: 'init',
},
scrollable: null,
leftIcon: {
type: String,
value: '',
},
color: String,
backgroundColor: String,
background: String,
wrapable: Boolean,
},
data: {
show: true,
},
created() {
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear',
});
},
destroyed() {
this.timer && clearTimeout(this.timer);
},
mounted() {
this.init();
},
methods: {
init() {
requestAnimationFrame(() => {
Promise.all([
getRect(this, '.van-notice-bar__content'),
getRect(this, '.van-notice-bar__wrap'),
]).then((rects) => {
const [contentRect, wrapRect] = rects;
const { scrollable } = this.data;
if (
contentRect == null ||
wrapRect == null ||
!contentRect.width ||
!wrapRect.width ||
scrollable === false
) {
return;
}
if (scrollable || wrapRect.width < contentRect.width) {
this.initAnimation(wrapRect.width, contentRect.width);
this.scroll(true);
} else {
this.reset();
}
});
});
},
initAnimation(warpWidth: number, contentWidth: number) {
const { speed, delay } = this.data;
this.wrapWidth = warpWidth;
this.contentWidth = contentWidth;
// begin 0
this.contentDuration = (contentWidth / speed) * 1000;
// begin -wrapWidth
this.duration = ((warpWidth + contentWidth) / speed) * 1000;
this.animation = wx.createAnimation({
duration: this.contentDuration,
timingFunction: 'linear',
delay,
});
},
reset(x = 0) {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
this.setData({
animationData: this.resetAnimation.translateX(x).step().export(),
});
},
scroll(isInit = false) {
this.reset(isInit ? 0 : this.wrapWidth);
const duration = isInit ? this.contentDuration : this.duration;
requestAnimationFrame(() => {
this.setData({
animationData: this.animation
.translateX(-this.contentWidth)
.step({ duration })
.export(),
});
});
this.timer = setTimeout(() => {
this.scroll();
}, duration + this.data.delay);
},
onClickIcon(event) {
if (this.data.mode === 'closeable') {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({ show: false });
this.$emit('close', event.detail);
}
},
onClick(event: WechatMiniprogram.TouchEvent) {
this.$emit('click', event);
},
},
});
================================================
FILE: packages/notice-bar/index.wxml
================================================
{{ text }}
================================================
FILE: packages/notice-bar/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
color: data.color,
'background-color': data.backgroundColor,
background: data.background,
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/notice-bar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。
滚动模式
技术是开发它的人的共同灵魂。
在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。
多行展示
在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。
通知栏模式
技术是开发它的人的共同灵魂。
技术是开发它的人的共同灵魂。
自定义样式
技术是开发它的人的共同灵魂。
`;
================================================
FILE: packages/notice-bar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/notify/README.md
================================================
# Notify 消息提示
### 介绍
在页面顶部展示消息提示,支持函数调用和组件调用两种方式。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-notify": "@vant/weapp/notify/index"
}
```
## 代码演示
### 基础用法
```js
import Notify from '@vant/weapp/notify/notify';
Notify('通知内容');
```
```html
```
### 通知类型
支持`primary`、`success`、`warning`、`danger`四种通知类型,默认为`danger`。
```js
// 主要通知
Notify({ type: 'primary', message: '通知内容' });
// 成功通知
Notify({ type: 'success', message: '通知内容' });
// 危险通知
Notify({ type: 'danger', message: '通知内容' });
// 警告通知
Notify({ type: 'warning', message: '通知内容' });
```
### 自定义通知
自定义消息通知的颜色和展示时长。
```js
Notify({
message: '自定义颜色',
color: '#ad0000',
background: '#ffe1e1',
});
Notify({
message: '自定义时长',
duration: 1000,
});
```
### 自定义选择器
```js
Notify({
message: '自定义节点选择器',
duration: 1000,
selector: '#custom-selector',
});
```
```html
```
## API
### 方法
| 方法名 | 说明 | 参数 | 返回值 |
| ------------ | -------- | -------------------- | ----------- |
| Notify | 展示提示 | `options \| message` | notify 实例 |
| Notify.clear | 关闭提示 | `options` | `void` |
### Options
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type `v1.0.0` | 类型,可选值为 `primary` `success` `warning` | _string_ | `danger` |
| message `v1.0.0` | 展示文案,支持通过`\n`换行 | _string_ | `''` |
| duration | 展示时长(ms),值为 0 时,notify 不会消失 | _number_ | `3000` |
| selector | 自定义节点选择器 | _string_ | `van-notify` |
| color | 字体颜色 | _string_ | `#fff` |
| top | 顶部距离 | _number_ | `0` |
| background | 背景颜色 | _string_ | - |
| context | 选择器的选择范围,可以传入自定义组件的 this 作为上下文 | _object_ | 当前页面 |
| onClick | 点击时的回调函数 | _Function_ | - |
| onOpened | 完全展示后的回调函数 | _Function_ | - |
| onClose | 关闭时的回调函数 | _Function_ | - |
| safeAreaInsetTop | 是否留出顶部安全距离(状态栏高度) | _boolean_ | `false` |
================================================
FILE: packages/notify/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"van-notify": "../../notify/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/notify/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Notify from '../../notify/notify';
VantComponent({
methods: {
showNotify() {
Notify({ context: this, message: '通知内容' });
},
showCustomColor() {
Notify({
context: this,
message: '自定义颜色',
color: '#ad0000',
background: '#ffe1e1',
});
Notify.clear();
},
showCustomDuration() {
Notify({
context: this,
duration: 1000,
message: '自定义时长',
});
},
showNotifyByType(event) {
const { type } = event.currentTarget.dataset;
Notify({
type,
context: this,
message: '通知内容',
});
},
showSafe() {
Notify({
context: this,
message: '通知内容',
safeAreaInsetTop: true,
});
},
},
});
================================================
FILE: packages/notify/demo/index.wxml
================================================
基础用法
主要通知
成功通知
危险通知
警告通知
自定义颜色
自定义时长
插入状态栏高度
================================================
FILE: packages/notify/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: packages/notify/index.less
================================================
@import '../common/style/var.less';
.van-notify {
text-align: center;
word-wrap: break-word;
padding: var(--notify-padding, @notify-padding);
font-size: var(--notify-font-size, @notify-font-size);
line-height: var(--notify-line-height, @notify-line-height);
&__container {
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
width: 100%;
}
&--primary {
background-color: var(
--notify-primary-background-color,
@notify-primary-background-color
);
}
&--success {
background-color: var(
--notify-success-background-color,
@notify-success-background-color
);
}
&--danger {
background-color: var(
--notify-danger-background-color,
@notify-danger-background-color
);
}
&--warning {
background-color: var(
--notify-warning-background-color,
@notify-warning-background-color
);
}
}
================================================
FILE: packages/notify/index.ts
================================================
import { VantComponent } from '../common/component';
import { WHITE } from '../common/color';
import { getSystemInfoSync } from '../common/utils';
VantComponent({
props: {
message: String,
background: String,
type: {
type: String,
value: 'danger',
},
color: {
type: String,
value: WHITE,
},
duration: {
type: Number,
value: 3000,
},
zIndex: {
type: Number,
value: 110,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
top: null,
},
data: {
show: false,
onOpened: (null as unknown) as () => void,
onClose: (null as unknown) as () => void,
onClick: (null as unknown) as (detail: Record) => void,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({ statusBarHeight });
},
methods: {
show() {
const { duration, onOpened } = this.data;
clearTimeout(this.timer);
this.setData({ show: true });
wx.nextTick(onOpened);
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
const { onClose } = this.data;
clearTimeout(this.timer);
this.setData({ show: false });
wx.nextTick(onClose);
},
onTap(event: WechatMiniprogram.TouchEvent) {
const { onClick } = this.data;
if (onClick) {
onClick(event.detail);
}
},
},
});
================================================
FILE: packages/notify/index.wxml
================================================
{{ message }}
================================================
FILE: packages/notify/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'z-index': data.zIndex,
top: addUnit(data.top),
});
}
function notifyStyle(data) {
return style({
background: data.background,
color: data.color,
});
}
module.exports = {
rootStyle: rootStyle,
notifyStyle: notifyStyle,
};
================================================
FILE: packages/notify/notify.ts
================================================
import { WHITE } from '../common/color';
interface NotifyOptions {
type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string;
zIndex?: number;
top?: number;
message: string;
context?: any;
duration?: number;
selector?: string;
background?: string;
safeAreaInsetTop?: boolean;
onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
const defaultOptions: NotifyOptions = {
selector: '#van-notify',
type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
top: 0,
color: WHITE,
safeAreaInsetTop: false,
onClick: () => {},
onOpened: () => {},
onClose: () => {},
};
let currentOptions: NotifyOptions = { ...defaultOptions };
function parseOptions(
message?: NotifyOptions | string
): Partial {
if (message == null) {
return {};
}
return typeof message === 'string' ? { message } : message;
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export default function Notify(options: NotifyOptions | string) {
options = { ...currentOptions, ...parseOptions(options) };
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (notify) {
notify.setData(options);
notify.show();
return notify;
}
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
Notify.clear = function (options?: NotifyOptions) {
options = { ...defaultOptions, ...parseOptions(options) };
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
if (notify) {
notify.hide();
}
};
Notify.setDefaultOptions = (options: NotifyOptions) => {
Object.assign(currentOptions, options);
};
Notify.resetDefaultOptions = () => {
currentOptions = { ...defaultOptions };
};
================================================
FILE: packages/notify/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
基础用法
通知类型
主要通知
成功通知
危险通知
警告通知
自定义通知
自定义颜色
自定义时长
插入状态栏高度
插入状态栏高度
`;
================================================
FILE: packages/notify/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/overlay/README.md
================================================
# Overlay 遮罩层
### 介绍
创建一个遮罩层,用于强调特定的页面元素,并阻止用户进行其他操作。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-overlay": "@vant/weapp/overlay/index"
}
```
## 代码演示
### 基础用法
```html
显示遮罩层
```
```js
Page({
data: {
show: false,
},
onClickShow() {
this.setData({ show: true });
},
onClickHide() {
this.setData({ show: false });
},
});
```
### 嵌入内容
通过默认插槽可以在遮罩层上嵌入任意内容。
```html
嵌入内容
```
```js
Page({
data: {
show: false,
},
onClickShow() {
this.setData({ show: true });
},
onClickHide() {
this.setData({ show: false });
},
noop() {},
});
```
```css
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block {
width: 120px;
height: 120px;
background-color: #fff;
}
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否展示遮罩层 | _boolean_ | `false` |
| z-index | z-index 层级 | _string \| number_ | `1` |
| duration | 动画时长,单位秒 | _string \| number_ | `0.3` |
| class-name | 自定义类名 | _string_ | - |
| custom-style | 自定义样式 | _string_ | - |
| lock-scroll `v1.7.3` | 是否锁定背景滚动,锁定时蒙层里的内容也将无法滚动 | _boolean_ | `true` |
| root-portal `v1.10.14` | 是否从页面中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 回调参数 |
| ---------- | ---------- | -------- |
| bind:click | 点击时触发 | - |
### Slots
| 名称 | 说明 |
| ---- | ---------------------------------- |
| - | 默认插槽,用于在遮罩层上方嵌入内容 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/overlay/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"van-overlay": "../../overlay/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/overlay/demo/index.less
================================================
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block {
width: 120px;
height: 120px;
background-color: #fff;
}
================================================
FILE: packages/overlay/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show: false,
showEmbedded: false,
},
methods: {
onClickShow() {
this.setData({ show: true });
},
onClickHide() {
this.setData({ show: false });
},
onClickShowEmbedded() {
this.setData({ showEmbedded: true });
},
onClickHideEmbedded() {
this.setData({ showEmbedded: false });
},
noop() {},
},
});
================================================
FILE: packages/overlay/demo/index.wxml
================================================
显示遮罩层
嵌入内容
================================================
FILE: packages/overlay/index.json
================================================
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
================================================
FILE: packages/overlay/index.less
================================================
@import '../common/style/var.less';
.van-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--overlay-background-color, @overlay-background-color);
}
================================================
FILE: packages/overlay/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
customStyle: String,
duration: {
type: null,
value: 300,
},
zIndex: {
type: Number,
value: 1,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClick() {
this.$emit('click');
},
// for prevent touchmove
noop() {},
},
});
================================================
FILE: packages/overlay/index.wxml
================================================
================================================
FILE: packages/overlay/overlay.wxml
================================================
================================================
FILE: packages/overlay/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
显示遮罩层
嵌入内容
嵌入内容
`;
================================================
FILE: packages/overlay/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/panel/README.md
================================================
# Panel 面板
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-panel": "@vant/weapp/panel/index"
}
```
## 代码演示
### 基础用法
面板只是一个容器,里面可以放入自定义的内容。
```html
内容
```
### 高级用法
使用`slot`自定义内容。
```html
内容
按钮
按钮
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ------ | ---- | -------- | ------ |
| title | 标题 | _string_ | - |
| desc | 描述 | _string_ | - |
| status | 状态 | _string_ | - |
### Slot
| 名称 | 说明 |
| ------ | -------------------------------------------------------------- |
| - | 自定义内容 |
| header | 自定义 header,如果设置了`title`、`desc`、`status`属性则不生效 |
| footer | 自定义 footer |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| header-class | 头部样式类 |
| footer-class | 底部样式类 |
================================================
FILE: packages/panel/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-panel": "../../panel/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/panel/demo/index.less
================================================
.content {
padding: 20px;
font-size: 16px;
}
.footer {
text-align: right;
}
================================================
FILE: packages/panel/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/panel/demo/index.wxml
================================================
内容
内容
================================================
FILE: packages/panel/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
================================================
FILE: packages/panel/index.less
================================================
@import '../common/style/var.less';
.van-panel {
background: var(--panel-background-color, @panel-background-color);
&__header-value {
color: var(--panel-header-value-color, @panel-header-value-color);
}
&__footer {
padding: var(--panel-footer-padding, @panel-footer-padding);
&:empty {
display: none;
}
}
}
================================================
FILE: packages/panel/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['header-class', 'footer-class'],
props: {
desc: String,
title: String,
status: String,
},
});
================================================
FILE: packages/panel/index.wxml
================================================
================================================
FILE: packages/panel/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标题
描述信息
状态
内容
高级用法
标题
描述信息
状态
内容
`;
================================================
FILE: packages/panel/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/picker/README.md
================================================
# Picker 选择器
### 介绍
提供多个选项集合供用户选择,支持单列选择和多列级联,通常与 [弹出层](#/popup) 组件配合使用。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-picker": "@vant/weapp/picker/index"
}
```
## 代码演示
### 基础用法
```html
```
```javascript
import Toast from '@vant/weapp/toast/toast';
Page({
data: {
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
},
onChange(event) {
const { picker, value, index } = event.detail;
Toast(`当前值:${value}, 当前索引:${index}`);
},
});
```
### 默认选中项
单列选择器可以直接通过`default-index`属性设置初始选中项的索引值。
```html
```
### 展示顶部栏
```html
```
```javascript
import Toast from '@vant/weapp/toast/toast';
Page({
data: {
columns: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
},
onConfirm(event) {
const { picker, value, index } = event.detail;
Toast(`当前值:${value}, 当前索引:${index}`);
},
onCancel() {
Toast('取消');
},
});
```
### 多列联动
```html
```
```javascript
const citys = {
浙江: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
福建: ['福州', '厦门', '莆田', '三明', '泉州'],
};
Page({
data: {
columns: [
{
values: Object.keys(citys),
className: 'column1',
},
{
values: citys['浙江'],
className: 'column2',
defaultIndex: 2,
},
],
},
onChange(event) {
const { picker, value, index } = event.detail;
picker.setColumnValues(1, citys[value[0]]);
},
});
```
### 禁用选项
选项可以为对象结构,通过设置 disabled 来禁用该选项。
```html
```
```javascript
Page({
data: {
columns: [
{ text: '杭州', disabled: true },
{ text: '宁波' },
{ text: '温州' },
],
},
});
```
### 加载状态
当 Picker 数据是通过异步获取时,可以通过 `loading` 属性显示加载提示。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| columns | 对象数组,配置每一列显示的数据 | _Array_ | `[]` |
| show-toolbar | 是否显示顶部栏 | _boolean_ | `false` |
| toolbar-position | 顶部栏位置,可选值为`bottom` | _string_ | `top` |
| title | 顶部栏标题 | _string_ | `''` |
| loading | 是否显示加载状态 | _boolean_ | `false` |
| value-key | 选项对象中,文字对应的 key | _string_ | `text` |
| item-height | 选项高度 | _number_ | `44` |
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |
| visible-item-count | 可见的选项个数 | _number_ | `6` |
| default-index | 单列选择器的默认选中项索引,
多列选择器请参考下方的 Columns 配置 | _number_ | `0` |
### Events
Picker 组件的事件会根据 columns 是单列或多列返回不同的参数。
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| bind:confirm | 点击完成按钮时触发 | 单列:选中值,选中值对应的索引
多列:所有列选中值,所有列选中值对应的索引 |
| bind:cancel | 点击取消按钮时触发 | 单列:选中值,选中值对应的索引
多列:所有列选中值,所有列选中值对应的索引 |
| bind:change | 选项改变时触发 | 单列:Picker 实例,选中值,选中值对应的索引
多列:Picker 实例,所有列选中值,当前列对应的索引 |
### Columns 数据结构
当传入多列数据时,`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`。
| key | 说明 |
| ------------ | -------------------------- |
| values | 列中对应的备选值 |
| defaultIndex | 初始选中项的索引,默认为 0 |
### 外部样式类
| 类名 | 说明 |
| ------------- | ------------ |
| custom-class | 根节点样式类 |
| active-class | 选中项样式类 |
| toolbar-class | 顶部栏样式类 |
| column-class | 列样式类 |
### 方法
通过 selectComponent 可以获取到 picker 实例并调用实例方法。
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| getValues | - | values | 获取所有列选中的值 |
| setValues | values | - | 设置所有列选中的值 |
| getIndexes | - | indexes | 获取所有列选中值对应的索引 |
| setIndexes | indexes | - | 设置所有列选中值对应的索引 |
| getColumnValue | columnIndex | value | 获取对应列选中的值 |
| setColumnValue | columnIndex, value | - | 设置对应列选中的值 |
| getColumnIndex | columnIndex | optionIndex | 获取对应列选中项的索引 |
| setColumnIndex | columnIndex, optionIndex | - | 设置对应列选中项的索引 |
| getColumnValues | columnIndex | values | 获取对应列中所有选项 |
| setColumnValues | columnIndex, values | - | 设置对应列中所有选项 |
================================================
FILE: packages/picker/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-toast": "../../toast/index",
"van-picker": "../../picker/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/picker/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
column1: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
column2: [
{ text: '杭州', disabled: true },
{ text: '宁波' },
{ text: '温州' },
],
column3: {
浙江: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
福建: ['福州', '厦门', '莆田', '三明', '泉州'],
},
column4: [
{
values: ['浙江', '福建'],
className: 'column1',
},
{
values: ['杭州', '宁波', '温州', '嘉兴', '湖州'],
className: 'column2',
defaultIndex: 2,
},
],
},
methods: {
onChange1(event) {
const { value, index } = event.detail;
Toast({
context: this,
message: `Value: ${value}, Index:${index}`,
});
},
onConfirm(event) {
const { value, index } = event.detail;
Toast({
context: this,
message: `Value: ${value}, Index:${index}`,
});
},
onCancel() {
Toast({
context: this,
message: '取消',
});
},
onChange2(event) {
const { picker, value } = event.detail;
picker.setColumnValues(1, this.data.column3[value[0]]);
getApp().picker = picker;
},
},
});
================================================
FILE: packages/picker/demo/index.wxml
================================================
================================================
FILE: packages/picker/index.json
================================================
{
"component": true,
"usingComponents": {
"picker-column": "../picker-column/index",
"loading": "../loading/index"
}
}
================================================
FILE: packages/picker/index.less
================================================
@import '../common/style/var';
.van-picker {
position: relative;
overflow: hidden;
-webkit-text-size-adjust: 100%; /* avoid iOS text size adjust */
user-select: none;
background-color: var(--picker-background-color, @picker-background-color);
&__toolbar {
display: flex;
justify-content: space-between;
height: var(--picker-toolbar-height, @picker-toolbar-height);
line-height: var(--picker-toolbar-height, @picker-toolbar-height);
}
&__cancel,
&__confirm {
padding: var(--picker-action-padding, @picker-action-padding);
font-size: var(--picker-action-font-size, @picker-action-font-size);
&--hover {
opacity: @active-opacity;
}
}
&__confirm {
color: var(--picker-confirm-action-color, @picker-confirm-action-color);
}
&__cancel {
color: var(--picker-cancel-action-color, @picker-cancel-action-color);
}
&__title {
max-width: 50%;
text-align: center;
font-weight: var(--font-weight-bold, @font-weight-bold);
font-size: var(--picker-option-font-size, @picker-option-font-size);
}
&__columns {
position: relative;
display: flex;
}
&__column {
flex: 1 1;
width: 0;
}
&__loading {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 4;
display: flex;
align-items: center;
justify-content: center;
background-color: var(
--picker-loading-mask-color,
@picker-loading-mask-color
);
}
&__mask {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
background-image: linear-gradient(
180deg,
hsla(0, 0%, 100%, 0.9),
hsla(0, 0%, 100%, 0.4)
),
linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));
background-repeat: no-repeat;
background-position: top, bottom;
backface-visibility: hidden;
pointer-events: none;
}
&__frame {
position: absolute;
top: 50%;
right: @padding-md;
left: @padding-md;
z-index: 1;
transform: translateY(-50%);
pointer-events: none;
}
}
================================================
FILE: packages/picker/index.ts
================================================
import { VantComponent } from '../common/component';
import { pickerProps } from './shared';
interface Column {
values: any[];
defaultIndex?: number;
}
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
...pickerProps,
valueKey: {
type: String,
value: 'text',
},
toolbarPosition: {
type: String,
value: 'top',
},
defaultIndex: {
type: Number,
value: 0,
},
columns: {
type: Array,
value: [],
observer(columns = []) {
this.simple = columns.length && !columns[0].values;
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => {});
}
},
},
},
beforeCreate() {
Object.defineProperty(this, 'children', {
get: () => this.selectAllComponents('.van-picker__column') || [],
});
},
methods: {
noop() {},
setColumns() {
const { data } = this;
const columns = this.simple ? [{ values: data.columns }] : data.columns;
const stack = columns.map((column: Column, index: number) =>
this.setColumnValues(index, column.values)
);
return Promise.all(stack);
},
emit(event: WechatMiniprogram.TouchEvent) {
const { type } = event.currentTarget.dataset;
if (this.simple) {
this.$emit(type, {
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
} else {
this.$emit(type, {
value: this.getValues(),
index: this.getIndexes(),
});
}
},
onChange(event: WechatMiniprogram.CustomEvent) {
if (this.simple) {
this.$emit('change', {
picker: this,
value: this.getColumnValue(0),
index: this.getColumnIndex(0),
});
} else {
this.$emit('change', {
picker: this,
value: this.getValues(),
index: event.currentTarget.dataset.index,
});
}
},
// get column instance by index
getColumn(index: number) {
return this.children[index];
},
// get column value by index
getColumnValue(index: number) {
const column = this.getColumn(index);
return column && column.getValue();
},
// set column value by index
setColumnValue(index: number, value: any) {
const column = this.getColumn(index);
if (column == null) {
return Promise.reject(new Error('setColumnValue: 对应列不存在'));
}
return column.setValue(value);
},
// get column option index by column index
getColumnIndex(columnIndex: number) {
return (this.getColumn(columnIndex) || {}).data.currentIndex;
},
// set column option index by column index
setColumnIndex(columnIndex: number, optionIndex: number) {
const column = this.getColumn(columnIndex);
if (column == null) {
return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
}
return column.setIndex(optionIndex);
},
// get options of column by index
getColumnValues(index: number) {
return (this.children[index] || {}).data.options;
},
// set options of column by index
setColumnValues(index: number, options: any[], needReset = true) {
const column = this.children[index];
if (column == null) {
return Promise.reject(new Error('setColumnValues: 对应列不存在'));
}
const isSame =
JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) {
return Promise.resolve();
}
return column.set({ options }).then(() => {
if (needReset) {
column.setIndex(0);
}
});
},
// get values of all columns
getValues() {
return this.children.map((child) => child.getValue());
},
// set values of all columns
setValues(values: any[]) {
const stack = values.map((value, index) =>
this.setColumnValue(index, value)
);
return Promise.all(stack);
},
// get indexes of all columns
getIndexes() {
return this.children.map((child) => child.data.currentIndex);
},
// set indexes of all columns
setIndexes(indexes: number[]) {
const stack = indexes.map((optionIndex, columnIndex) =>
this.setColumnIndex(columnIndex, optionIndex)
);
return Promise.all(stack);
},
},
});
================================================
FILE: packages/picker/index.wxml
================================================
================================================
FILE: packages/picker/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
var array = require('../wxs/array.wxs');
function columnsStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function maskStyle(data) {
return style({
'background-size':
'100% ' + addUnit((data.itemHeight * (data.visibleItemCount - 1)) / 2),
});
}
function frameStyle(data) {
return style({
height: addUnit(data.itemHeight),
});
}
function columns(columns) {
if (!array.isArray(columns)) {
return [];
}
if (columns.length && !columns[0].values) {
return [{ values: columns }];
}
return columns;
}
module.exports = {
columnsStyle: columnsStyle,
frameStyle: frameStyle,
maskStyle: maskStyle,
columns: columns,
};
================================================
FILE: packages/picker/shared.ts
================================================
export const pickerProps = {
title: String,
loading: Boolean,
showToolbar: Boolean,
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonText: {
type: String,
value: '确认',
},
visibleItemCount: {
type: Number,
value: 6,
},
itemHeight: {
type: Number,
value: 44,
},
};
================================================
FILE: packages/picker/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
杭州
宁波
温州
嘉兴
湖州
默认选中项
杭州
宁波
温州
嘉兴
湖州
展示顶部栏
取消
标题
确认
杭州
宁波
温州
嘉兴
湖州
多列联动
浙江
福建
杭州
宁波
温州
嘉兴
湖州
禁用选项
杭州
宁波
温州
加载状态
浙江
福建
杭州
宁波
温州
嘉兴
湖州
`;
================================================
FILE: packages/picker/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/picker/toolbar.wxml
================================================
{{ cancelButtonText }}
{{
title
}}
{{ confirmButtonText }}
================================================
FILE: packages/picker-column/index.json
================================================
{
"component": true
}
================================================
FILE: packages/picker-column/index.less
================================================
@import '../common/style/var';
.van-picker-column {
overflow: hidden;
text-align: center;
color: var(--picker-option-text-color, @picker-option-text-color);
font-size: var(--picker-option-font-size, @picker-option-font-size);
&__item {
padding: 0 5px;
&--selected {
font-weight: var(--font-weight-bold, @font-weight-bold);
color: var(
--picker-option-selected-text-color,
@picker-option-selected-text-color
);
}
&--disabled {
opacity: var(
--picker-option-disabled-opacity,
@picker-option-disabled-opacity
);
}
}
}
================================================
FILE: packages/picker-column/index.ts
================================================
import { VantComponent } from '../common/component';
import { range } from '../common/utils';
import { isObj } from '../common/validator';
const DEFAULT_DURATION = 200;
VantComponent({
classes: ['active-class'],
props: {
valueKey: String,
className: String,
itemHeight: Number,
visibleItemCount: Number,
initialOptions: {
type: Array,
value: [],
},
defaultIndex: {
type: Number,
value: 0,
observer(value: number) {
this.setIndex(value);
},
},
},
data: {
startY: 0,
offset: 0,
duration: 0,
startOffset: 0,
options: [],
currentIndex: 0,
},
created() {
const { defaultIndex, initialOptions } = this.data;
this.set({
currentIndex: defaultIndex,
options: initialOptions,
}).then(() => {
this.setIndex(defaultIndex);
});
},
methods: {
getCount() {
return this.data.options.length;
},
onTouchStart(event: WechatMiniprogram.TouchEvent) {
this.setData({
startY: event.touches[0].clientY,
startOffset: this.data.offset,
duration: 0,
});
},
onTouchMove(event: WechatMiniprogram.TouchEvent) {
const { data } = this;
const deltaY = event.touches[0].clientY - data.startY;
this.setData({
offset: range(
data.startOffset + deltaY,
-(this.getCount() * data.itemHeight),
data.itemHeight
),
});
},
onTouchEnd() {
const { data } = this;
if (data.offset !== data.startOffset) {
this.setData({ duration: DEFAULT_DURATION });
const index = range(
Math.round(-data.offset / data.itemHeight),
0,
this.getCount() - 1
);
this.setIndex(index, true);
}
},
onClickItem(event: WechatMiniprogram.TouchEvent) {
const { index } = event.currentTarget.dataset;
this.setIndex(index, true);
},
adjustIndex(index: number) {
const { data } = this;
const count = this.getCount();
index = range(index, 0, count);
for (let i = index; i < count; i++) {
if (!this.isDisabled(data.options[i])) return i;
}
for (let i = index - 1; i >= 0; i--) {
if (!this.isDisabled(data.options[i])) return i;
}
},
isDisabled(option: any) {
return isObj(option) && option.disabled;
},
getOptionText(option: any) {
const { data } = this;
return isObj(option) && data.valueKey in option
? option[data.valueKey]
: option;
},
setIndex(index: number, userAction?: boolean) {
const { data } = this;
index = this.adjustIndex(index) || 0;
const offset = -index * data.itemHeight;
if (index !== data.currentIndex) {
return this.set({ offset, currentIndex: index }).then(() => {
userAction && this.$emit('change', index);
});
}
return this.set({ offset });
},
setValue(value: string) {
const { options } = this.data;
for (let i = 0; i < options.length; i++) {
if (this.getOptionText(options[i]) === value) {
return this.setIndex(i);
}
}
return Promise.resolve();
},
getValue() {
const { data } = this;
return data.options[data.currentIndex];
},
},
});
================================================
FILE: packages/picker-column/index.wxml
================================================
{{ computed.optionText(option, valueKey) }}
================================================
FILE: packages/picker-column/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function optionText(option, valueKey) {
return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
}
function rootStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function wrapperStyle(data) {
var offset = addUnit(
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
);
return style({
transition: 'transform ' + data.duration + 'ms',
'line-height': addUnit(data.itemHeight),
transform: 'translate3d(0, ' + offset + ', 0)',
});
}
module.exports = {
optionText: optionText,
rootStyle: rootStyle,
wrapperStyle: wrapperStyle,
};
================================================
FILE: packages/popup/README.md
================================================
# Popup 弹出层
### 介绍
弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-popup": "@vant/weapp/popup/index"
}
```
## 代码演示
### 基础用法
通过`show`属性控制弹出层是否展示。
```html
内容
```
```javascript
Page({
data: {
show: false,
},
showPopup() {
this.setData({ show: true });
},
onClose() {
this.setData({ show: false });
},
});
```
### 弹出位置
通过`position`属性设置弹出位置,默认居中弹出,可以设置为`top`、`bottom`、`left`、`right`。
```html
```
### 关闭图标
设置`closeable`属性后,会在弹出层的右上角显示关闭图标,并且可以通过`close-icon`属性自定义图标,使用`close-icon-position`属性可以自定义图标位置。
```html
```
### 圆角弹窗
设置`round`属性后,弹窗会根据弹出位置添加不同的圆角样式。
```html
```
### 禁止滚动穿透
使用组件时,会发现内容部分滚动到底时,继续划动会导致底层页面的滚动,这就是滚动穿透。
目前,组件可以通过 `lock-scroll` 属性处理部分滚动穿透问题。 **但由于小程序自身原因,弹窗内容区域仍会出现滚动穿透。** 不过,我们为开发者提供了一个推荐方案以完整解决滚动穿透:
#### [page-meta](https://developers.weixin.qq.com/miniprogram/dev/component/page-meta.html)
当小程序基础库最低版本在 2.9.0 以上时,即可使用 [page-meta](https://developers.weixin.qq.com/miniprogram/dev/component/page-meta.html) 组件动态修改页面样式
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否显示弹出层 | _boolean_ | `false` |
| z-index | z-index 层级 | _number_ | `100` |
| overlay | 是否显示遮罩层 | _boolean_ | `true` |
| position | 弹出位置,可选值为 `top` `bottom` `right` `left` | _string_ | `center` |
| duration | 动画时长,单位为毫秒 | _number \| object_ | `300` |
| round | 是否显示圆角 | _boolean_ | `false` |
| custom-style | 自定义弹出层样式 | _string_ | `''` |
| overlay-style | 自定义遮罩层样式 | _string_ | `''` |
| close-on-click-overlay | 是否在点击遮罩层后关闭 | _boolean_ | `true` |
| closeable | 是否显示关闭图标 | _boolean_ | `false` |
| close-icon | 关闭图标名称或图片链接 | _string_ | `cross` |
| close-icon-position | 关闭图标位置,可选值为 `top-left`
`bottom-left` `bottom-right` | _string_ | `top-right` |
| safe-area-inset-bottom | 是否为 iPhoneX 留出底部安全距离 | _boolean_ | `true` |
| safe-area-inset-top | 是否留出顶部安全距离(状态栏高度) | _boolean_ | `false` |
| safe-area-tab-bar | 是否留出底部 tabbar 安全距离(在使用 tabbar 组件 & 小程序自定义 tabbar 时,popup 组件层级无法盖住 tabbar) | _boolean_ | `false` |
| lock-scroll `v1.7.3` | 是否锁定背景滚动 | _boolean_ | `true` |
| root-portal `v1.10.14` | 是否从页面中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 参数 |
| ------------------ | ---------------- | ---- |
| bind:close | 关闭弹出层时触发 | - |
| bind:click-overlay | 点击遮罩层时触发 | - |
| bind:before-enter | 进入前触发 | - |
| bind:enter | 进入中触发 | - |
| bind:after-enter | 进入后触发 | - |
| bind:before-leave | 离开前触发 | - |
| bind:leave | 离开中触发 | - |
| bind:after-leave | 离开后触发 | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/popup/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-popup": "../../popup/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/popup/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show: {
basic: false,
top: false,
bottom: false,
left: false,
right: false,
round: false,
closeIcon: false,
customCloseIcon: false,
customIconPosition: false,
},
},
methods: {
toggle(type, show) {
this.setData({
[`show.${type}`]: show,
});
},
showBasic() {
this.toggle('basic', true);
},
hideBasic() {
this.toggle('basic', false);
},
showTop() {
this.toggle('top', true);
},
hideTop() {
this.toggle('top', false);
},
showLeft() {
this.toggle('left', true);
},
hideLeft() {
this.toggle('left', false);
},
showRight() {
this.toggle('right', true);
},
hideRight() {
this.toggle('right', false);
},
showBottom() {
this.toggle('bottom', true);
},
hideBottom() {
this.toggle('bottom', false);
},
showRound() {
this.toggle('round', true);
},
hideRound() {
this.toggle('round', false);
},
showCloseIcon() {
this.toggle('closeIcon', true);
},
hideCloseIcon() {
this.toggle('closeIcon', false);
},
showCustomCloseIcon() {
this.toggle('customCloseIcon', true);
},
hideCustomCloseIcon() {
this.toggle('customCloseIcon', false);
},
showCustomIconPosition() {
this.toggle('customIconPosition', true);
},
hideCustomIconPosition() {
this.toggle('customIconPosition', false);
},
},
});
================================================
FILE: packages/popup/demo/index.wxml
================================================
内容
================================================
FILE: packages/popup/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index"
}
}
================================================
FILE: packages/popup/index.less
================================================
@import '../common/style/var.less';
.van-popup {
position: fixed;
box-sizing: border-box;
max-height: 100%;
overflow-y: auto;
transition-timing-function: ease;
animation: ease both;
-webkit-overflow-scrolling: touch;
background-color: var(--popup-background-color, @popup-background-color);
&--center {
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
&.van-popup--round {
border-radius: var(
--popup-round-border-radius,
@popup-round-border-radius
);
}
}
&--top {
top: 0;
left: 0;
width: 100%;
&.van-popup--round {
border-radius: 0 0
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
);
}
}
&--right {
top: 50%;
right: 0;
transform: translate3d(0, -50%, 0);
&.van-popup--round {
border-radius: var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
0 0
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
);
}
}
&--bottom {
bottom: 0;
left: 0;
width: 100%;
&.van-popup--round {
border-radius: var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
0 0;
}
}
&--left {
top: 50%;
left: 0;
transform: translate3d(0, -50%, 0);
&.van-popup--round {
border-radius: 0
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
var(
--popup-round-border-radius,
var(--popup-round-border-radius, @popup-round-border-radius)
)
0;
}
}
&--bottom&--safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
&--bottom&--safeTabBar,
&--top&--safeTabBar {
bottom: var(--tabbar-height, @tabbar-height);
}
&--safeTop {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}
&__close-icon {
position: absolute;
z-index: var(--popup-close-icon-z-index, @popup-close-icon-z-index);
color: var(--popup-close-icon-color, @popup-close-icon-color);
font-size: var(--popup-close-icon-size, @popup-close-icon-size);
&--top-left {
top: var(--popup-close-icon-margin, @popup-close-icon-margin);
left: var(--popup-close-icon-margin, @popup-close-icon-margin);
}
&--top-right {
top: var(--popup-close-icon-margin, @popup-close-icon-margin);
right: var(--popup-close-icon-margin, @popup-close-icon-margin);
}
&--bottom-left {
bottom: var(--popup-close-icon-margin, @popup-close-icon-margin);
left: var(--popup-close-icon-margin, @popup-close-icon-margin);
}
&--bottom-right {
right: var(--popup-close-icon-margin, @popup-close-icon-margin);
bottom: var(--popup-close-icon-margin, @popup-close-icon-margin);
}
&:active {
opacity: 0.6;
}
}
}
.van-scale-enter-active,
.van-scale-leave-active {
transition-property: opacity, transform;
}
.van-scale-enter,
.van-scale-leave-to {
transform: translate3d(-50%, -50%, 0) scale(0.7);
opacity: 0;
}
.van-fade-enter-active,
.van-fade-leave-active {
transition-property: opacity;
}
.van-fade-enter,
.van-fade-leave-to {
opacity: 0;
}
.van-center-enter-active,
.van-center-leave-active {
transition-property: opacity;
}
.van-center-enter,
.van-center-leave-to {
opacity: 0;
}
.van-bottom-enter-active,
.van-bottom-leave-active,
.van-top-enter-active,
.van-top-leave-active,
.van-left-enter-active,
.van-left-leave-active,
.van-right-enter-active,
.van-right-leave-active {
transition-property: transform;
}
.van-bottom-enter,
.van-bottom-leave-to {
transform: translate3d(0, 100%, 0);
}
.van-top-enter,
.van-top-leave-to {
transform: translate3d(0, -100%, 0);
}
.van-left-enter,
.van-left-leave-to {
transform: translate3d(-100%, -50%, 0);
}
.van-right-enter,
.van-right-leave-to {
transform: translate3d(100%, -50%, 0);
}
================================================
FILE: packages/popup/index.ts
================================================
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
'close-icon-class',
],
mixins: [transition(false)],
props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: {
type: String,
observer: 'observeClass',
},
zIndex: {
type: Number,
value: 100,
},
overlay: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
closeIconPosition: {
type: String,
value: 'top-right',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
position: {
type: String,
value: 'center',
observer: 'observeClass',
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
safeAreaTabBar: {
type: Boolean,
value: false,
},
lockScroll: {
type: Boolean,
value: true,
},
rootPortal: {
type: Boolean,
value: false,
},
},
created() {
this.observeClass();
},
methods: {
onClickCloseIcon() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
},
observeClass() {
const { transition, position, duration } = this.data;
const updateData: { [key: string]: any } = {
name: transition || position,
};
if (transition === 'none') {
updateData.duration = 0;
this.originDuration = duration;
} else if (this.originDuration != null) {
updateData.duration = this.originDuration;
}
this.setData(updateData);
},
},
});
================================================
FILE: packages/popup/index.wxml
================================================
================================================
FILE: packages/popup/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function popupStyle(data) {
return style([
{
'z-index': data.zIndex,
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
popupStyle: popupStyle,
};
================================================
FILE: packages/popup/popup.wxml
================================================
================================================
FILE: packages/popup/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
展示弹出层
弹出位置
顶部弹出
底部弹出
左侧弹出
右侧弹出
关闭图标
关闭图标
自定义图标
图标位置
圆角弹窗
圆角弹窗
`;
================================================
FILE: packages/popup/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/progress/README.md
================================================
# Progress 进度条
### 介绍
用于展示操作的当前进度。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-progress": "@vant/weapp/progress/index"
}
```
## 代码演示
### 基础用法
进度条默认为蓝色,使用`percentage`属性来设置当前进度。
```html
```
### 线条粗细
通过`stroke-width`可以设置进度条的粗细。
```html
```
### 置灰
设置`inactive`属性后进度条将置灰。
```html
```
### 样式定制
可以使用`pivot-text`属性自定义文字,`color`属性自定义进度条颜色。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| inactive | 是否置灰 | _boolean_ | `false` |
| percentage | 进度百分比 | _number_ | `0` |
| stroke-width | 进度条粗细,默认单位为`px` | _string \| number_ | `4px` |
| show-pivot | 是否显示进度文字 | _boolean_ | `true` |
| color | 进度条颜色 | _string_ | `#1989fa` |
| text-color | 进度文字颜色 | _string_ | `#fff` |
| track-color | 轨道颜色 | _string_ | `#e5e5e5` |
| pivot-text | 文字显示 | _string_ | 百分比文字 |
| pivot-color | 文字背景色 | _string_ | 与进度条颜色一致 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/progress/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-progress": "../../progress/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/progress/demo/index.less
================================================
.progress-position {
margin: 5px 15px 20px;
}
================================================
FILE: packages/progress/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {},
});
================================================
FILE: packages/progress/demo/index.wxml
================================================
================================================
FILE: packages/progress/index.json
================================================
{
"component": true
}
================================================
FILE: packages/progress/index.less
================================================
@import '../common/style/var.less';
.van-progress {
position: relative;
height: var(--progress-height, @progress-height);
border-radius: var(--progress-height, @progress-height);
background: var(--progress-background-color, @progress-background-color);
&__portion {
position: absolute;
left: 0;
height: 100%;
border-radius: inherit;
background: var(--progress-color, @progress-color);
}
&__pivot {
position: absolute;
top: 50%;
box-sizing: border-box;
min-width: 3.6em;
text-align: center;
word-break: keep-all;
border-radius: 1em;
transform: translate(0, -50%);
color: var(--progress-pivot-text-color, @progress-pivot-text-color);
padding: var(--progress-pivot-padding, @progress-pivot-padding);
font-size: var(--progress-pivot-font-size, @progress-pivot-font-size);
line-height: var(--progress-pivot-line-height, @progress-pivot-line-height);
background-color: var(
--progress-pivot-background-color,
@progress-pivot-background-color
);
}
}
================================================
FILE: packages/progress/index.ts
================================================
import { VantComponent } from '../common/component';
import { BLUE } from '../common/color';
import { getRect } from '../common/utils';
VantComponent({
props: {
inactive: Boolean,
percentage: {
type: Number,
observer: 'setLeft',
},
pivotText: String,
pivotColor: String,
trackColor: String,
showPivot: {
type: Boolean,
value: true,
},
color: {
type: String,
value: BLUE,
},
textColor: {
type: String,
value: '#fff',
},
strokeWidth: {
type: null,
value: 4,
},
},
data: {
right: 0,
},
mounted() {
this.setLeft();
},
methods: {
setLeft() {
Promise.all([
getRect(this, '.van-progress'),
getRect(this, '.van-progress__pivot'),
]).then(([portion, pivot]) => {
if (portion && pivot) {
this.setData({
right: (pivot.width * (this.data.percentage - 100)) / 100,
});
}
});
},
},
});
================================================
FILE: packages/progress/index.wxml
================================================
{{ computed.pivotText(pivotText, percentage) }}
================================================
FILE: packages/progress/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function pivotText(pivotText, percentage) {
return pivotText || percentage + '%';
}
function rootStyle(data) {
return style({
'height': data.strokeWidth ? utils.addUnit(data.strokeWidth) : '',
'background': data.trackColor,
});
}
function portionStyle(data) {
return style({
background: data.inactive ? '#cacaca' : data.color,
width: data.percentage ? data.percentage + '%' : '',
});
}
function pivotStyle(data) {
return style({
color: data.textColor,
right: data.right + 'px',
background: data.pivotColor ? data.pivotColor : data.inactive ? '#cacaca' : data.color,
});
}
module.exports = {
pivotText: pivotText,
rootStyle: rootStyle,
portionStyle: portionStyle,
pivotStyle: pivotStyle,
};
================================================
FILE: packages/progress/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
0%
线条粗细
100%
置灰
50%
样式定制
橙色
红色
紫色
`;
================================================
FILE: packages/progress/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/radio/README.md
================================================
# Radio 单选框
### 介绍
在一组备选项中进行单选。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-radio": "@vant/weapp/radio/index",
"van-radio-group": "@vant/weapp/radio-group/index"
}
```
## 代码演示
### 基础用法
通过`value`绑定值当前选中项的 name 。
```html
单选框 1
单选框 2
```
```js
Page({
data: {
radio: '1',
},
onChange(event) {
this.setData({
radio: event.detail,
});
},
});
```
### 水平排列
将`direction`属性设置为`horizontal`后,单选框组会变成水平排列。
```html
单选框 1
单选框 2
```
### 禁用状态
通过`disabled`属性禁止选项切换,在`Radio`上设置`diabled`可以禁用单个选项。
```html
单选框 1
单选框 2
```
### 自定义形状
将`shape`属性设置为`square`,单选框的形状会变成方形。
```html
单选框 1
单选框 2
```
### 自定义颜色
通过`checked-color`属性设置选中状态的图标颜色。
```html
单选框 1
单选框 2
```
### 自定义大小
通过`icon-size`属性可以自定义图标的大小。
```html
单选框 1
单选框 2
```
### 自定义图标
通过`icon`插槽自定义图标,需要设置`use-icon-slot`属性。
```html
自定义图标
自定义图标
```
```js
Page({
data: {
radio: true,
icon: {
normal: '//img.yzcdn.cn/icon-normal.png',
active: '//img.yzcdn.cn/icon-active.png',
},
},
onChange(event) {
this.setData({
radio: event.detail,
});
},
});
```
### 禁用文本点击
通过设置`label-disabled`属性可以禁用单选框文本点击。
```html
单选框 1
单选框 2
```
### 与 Cell 组件一起使用
此时你需要再引入`Cell`和`CellGroup`组件。
```html
```
```js
Page({
data: {
radio: '1',
},
onChange(event) {
this.setData({
radio: event.detail,
});
},
onClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
radio: name,
});
},
});
```
## API
### RadioGroup Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符 | _string_ | - |
| value | 当前选中项的标识符 | _any_ | - |
| disabled | 是否禁用所有单选框 | _boolean_ | `false` |
| direction `v1.6.7` | 排列方向,可选值为 `horizontal` | _string_ | `vertical` |
### Radio Props
| 参数 | 说明 | 类型 | 默认值 |
| -------------- | ------------------------- | ------------------ | --------- |
| name | 标识符 | _string_ | - |
| shape | 形状,可选值为 `square` | _string_ | `round` |
| disabled | 是否为禁用状态 | _boolean_ | `false` |
| label-disabled | 是否禁用文本内容点击 | _boolean_ | `false` |
| label-position | 文本位置,可选值为 `left` | _string_ | `right` |
| icon-size | 图标大小,默认单位为`px` | _string \| number_ | `20px` |
| checked-color | 选中状态颜色 | _string_ | `#1989fa` |
| use-icon-slot | 是否使用 icon 插槽 | _boolean_ | `false` |
### Radio Event
| 事件名 | 说明 | 回调参数 |
| ----------- | ------------------------ | ----------------- |
| bind:change | 当绑定值变化时触发的事件 | 当前选中项的 name |
### Radio 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| icon-class | 图标样式类 |
| label-class | 描述信息样式类 |
### RadioGroup Event
| 事件名 | 说明 | 回调参数 |
| ----------- | ------------------------ | ----------------- |
| bind:change | 当绑定值变化时触发的事件 | 当前选中项的 name |
================================================
FILE: packages/radio/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-radio": "../../radio/index",
"van-radio-group": "../../radio-group/index",
"van-cell": "../../cell/index",
"van-cell-group": "../../cell-group/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/radio/demo/index.less
================================================
.demo-radio {
margin-bottom: 10px;
}
.icon {
width: 20px;
}
================================================
FILE: packages/radio/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
radio1: '1',
radio2: '2',
radio3: '1',
radio4: '1',
radio5: '1',
radioSize: '1',
radioLabel: '1',
radioShape: '1',
icon: {
normal:
'https://img.yzcdn.cn/public_files/2017/10/13/c547715be149dd3faa817e4a948b40c4.png',
active:
'https://img.yzcdn.cn/public_files/2017/10/13/793c77793db8641c4c325b7f25bf130d.png',
},
},
methods: {
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({ [key]: event.detail });
},
onClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
radio5: name,
});
},
},
});
================================================
FILE: packages/radio/demo/index.wxml
================================================
单选框 1
单选框 2
单选框 1
单选框 2
单选框 1
单选框 2
单选框
单选框
单选框
单选框
单选框
单选框
自定义图标
自定义图标
单选框 1
单选框 2
================================================
FILE: packages/radio/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/radio/index.less
================================================
@import '../common/style/var.less';
.van-radio {
display: flex;
align-items: center;
overflow: hidden;
user-select: none;
&__icon-wrap {
flex: none;
}
&--horizontal {
margin-right: var(--padding-sm, @padding-sm);
}
&__icon {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 1em;
height: 1em;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
border: 1px solid var(--radio-border-color, @radio-border-color);
font-size: var(--radio-size, @radio-size);
transition-duration: var(
--radio-transition-duration,
@radio-transition-duration
);
&--round {
border-radius: 100%;
}
&--checked {
color: @white;
background-color: var(
--radio-checked-icon-color,
@radio-checked-icon-color
);
border-color: var(--radio-checked-icon-color, @radio-checked-icon-color);
}
&--disabled {
background-color: var(
--radio-disabled-background-color,
@radio-disabled-background-color
);
border-color: var(
--radio-disabled-icon-color,
@radio-disabled-icon-color
);
}
&--disabled&--checked {
color: var(--radio-disabled-icon-color, @radio-disabled-icon-color);
}
}
&__label {
word-wrap: break-word;
padding-left: var(--radio-label-margin, @radio-label-margin);
color: var(--radio-label-color, @radio-label-color);
line-height: var(--radio-size, @radio-size);
&--left {
float: left;
margin: 0 var(--radio-label-margin, @radio-label-margin) 0 0;
}
&--disabled {
color: var(--radio-disabled-label-color, @radio-disabled-label-color);
}
&:empty {
margin: 0;
}
}
}
================================================
FILE: packages/radio/index.ts
================================================
import { canIUseModel } from '../common/version';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
field: true,
relation: useParent('radio-group', function () {
this.updateFromParent();
}),
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
direction: '',
parentDisabled: false,
},
methods: {
updateFromParent() {
if (!this.parent) {
return;
}
const { value, disabled: parentDisabled, direction } = this.parent.data;
this.setData({
value,
direction,
parentDisabled,
});
},
emitChange(value: boolean) {
const instance = this.parent || this;
instance.$emit('input', value);
instance.$emit('change', value);
if (canIUseModel()) {
instance.setData({ value });
}
},
onChange() {
if (!this.data.disabled && !this.data.parentDisabled) {
this.emitChange(this.data.name);
}
},
onClickLabel() {
const { disabled, parentDisabled, labelDisabled, name } = this.data;
if (!(disabled || parentDisabled) && !labelDisabled) {
this.emitChange(name);
}
},
},
});
================================================
FILE: packages/radio/index.wxml
================================================
================================================
FILE: packages/radio/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(data) {
var styles = {
'font-size': addUnit(data.iconSize),
};
if (
data.checkedColor &&
!(data.disabled || data.parentDisabled) &&
data.value === data.name
) {
styles['border-color'] = data.checkedColor;
styles['background-color'] = data.checkedColor;
}
return style(styles);
}
function iconCustomStyle(data) {
return style({
'line-height': addUnit(data.iconSize),
'font-size': '.8em',
display: 'block',
});
}
module.exports = {
iconStyle: iconStyle,
iconCustomStyle: iconCustomStyle,
};
================================================
FILE: packages/radio/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基本用法
单选框 1
单选框 2
水平排列
单选框 1
单选框 2
禁用状态
单选框 1
单选框 2
自定义形状
单选框
单选框
自定义颜色
单选框
单选框
自定义大小
单选框
单选框
自定义图标
自定义图标
自定义图标
禁用文本点击
单选框 1
单选框 2
与 Cell 组件一起使用
单选框 1
单选框 2
`;
================================================
FILE: packages/radio/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/radio-group/index.json
================================================
{
"component": true
}
================================================
FILE: packages/radio-group/index.less
================================================
.van-radio-group {
&--horizontal {
display: flex;
flex-wrap: wrap;
}
}
================================================
FILE: packages/radio-group/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
field: true,
relation: useChildren('radio'),
props: {
value: {
type: null,
observer: 'updateChildren',
},
direction: String,
disabled: {
type: Boolean,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => child.updateFromParent());
},
},
});
================================================
FILE: packages/radio-group/index.wxml
================================================
================================================
FILE: packages/rate/README.md
================================================
# Rate 评分
### 介绍
用于对事物进行评级操作。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-rate": "@vant/weapp/rate/index"
}
```
## 代码演示
### 基础用法
```html
```
```javascript
Page({
data: {
value: 3,
},
onChange(event) {
this.setData({
value: event.detail,
});
},
});
```
### 自定义图标
```html
```
### 自定义样式
```html
```
### 半星
```html
```
```javascript
Page({
data: {
value: 2.5,
},
onChange(event) {
this.setData({
value: event.detail,
});
},
});
```
### 自定义数量
```html
```
### 禁用状态
```html
```
### 只读状态
```html
```
### 监听 change 事件
评分变化时,会触发 `change` 事件。
```html
```
```javascript
Page({
data: {
value: 2,
},
onChange(event) {
Toast('当前值:' + event.detail);
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符 | _string_ | - |
| value | 当前分值 | _number_ | - |
| count | 图标总数 | _number_ | `5` |
| size | 图标大小,默认单位为 `px` | _string \| number_ | `20px` |
| gutter | 图标间距,默认单位为 `px` | _string \| number_ | `4px` |
| color | 选中时的颜色 | _string_ | `#ffd21e` |
| void-color | 未选中时的颜色 | _string_ | `#c7c7c7` |
| icon | 选中时的图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | `star` |
| void-icon | 未选中时的图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | `star-o` |
| allow-half | 是否允许半选 | _boolean_ | `false` |
| readonly | 是否为只读状态 | _boolean_ | `false` |
| disabled | 是否禁用评分 | _boolean_ | `false` |
| disabled-color | 禁用时的颜色 | _string_ | `#bdbdbd` |
| touchable | 是否可以通过滑动手势选择评分 | _boolean_ | `true` |
### Events
| 事件名称 | 说明 | 回调参数 |
| -------- | ------------------------ | --------------------- |
| bind:change | 当前分值变化时触发的事件 | event.detail:当前分值 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| icon-class | 图标样式类 |
================================================
FILE: packages/rate/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-rate": "../../rate/index",
"van-toast": "../../toast/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/rate/demo/index.less
================================================
.rate-position {
margin-left: 15px;
}
================================================
FILE: packages/rate/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
value1: 3,
value2: 3,
value3: 3,
value4: 2.5,
value5: 4,
value6: 3,
value8: 2,
},
methods: {
onChange(event) {
Toast({
context: this,
message: '当前值:' + event.detail,
});
},
},
});
================================================
FILE: packages/rate/demo/index.wxml
================================================
================================================
FILE: packages/rate/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/rate/index.less
================================================
@import '../common/style/var.less';
.van-rate {
display: inline-flex;
user-select: none;
&__item {
position: relative;
padding: 0 var(--rate-horizontal-padding, @rate-horizontal-padding);
&:not(:last-child) {
padding-right: var(--rate-icon-gutter, @rate-icon-gutter);
}
}
&__icon {
display: block;
height: 100%;
color: var(--rate-icon-void-color, @rate-icon-void-color);
font-size: var(--rate-icon-size, @rate-icon-size);
&--half {
position: absolute;
top: 0;
width: 0.5em;
overflow: hidden;
left: var(--rate-horizontal-padding, @rate-horizontal-padding);
color: var(--rate-icon-full-color, @rate-icon-full-color);
}
&--full {
color: var(--rate-icon-full-color, @rate-icon-full-color);
}
&--disabled {
color: var(--rate-icon-disabled-color, @rate-icon-disabled-color);
}
}
}
================================================
FILE: packages/rate/index.ts
================================================
import { getAllRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['icon-class'],
props: {
value: {
type: Number,
observer(value: number) {
if (value !== this.data.innerValue) {
this.setData({ innerValue: value });
}
},
},
readonly: Boolean,
disabled: Boolean,
allowHalf: Boolean,
size: null,
icon: {
type: String,
value: 'star',
},
voidIcon: {
type: String,
value: 'star-o',
},
color: String,
voidColor: String,
disabledColor: String,
count: {
type: Number,
value: 5,
observer(value: number) {
this.setData({ innerCountArray: Array.from({ length: value }) });
},
},
gutter: null,
touchable: {
type: Boolean,
value: true,
},
},
data: {
innerValue: 0,
innerCountArray: Array.from({ length: 5 }),
},
methods: {
onSelect(event: WechatMiniprogram.CustomEvent) {
const { data } = this;
const { score } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) {
this.setData({ innerValue: score + 1 });
if (canIUseModel()) {
this.setData({ value: score + 1 });
}
wx.nextTick(() => {
this.$emit('input', score + 1);
this.$emit('change', score + 1);
});
}
},
onTouchMove(event: WechatMiniprogram.TouchEvent) {
const { touchable } = this.data;
if (!touchable) return;
const { clientX } = event.touches[0];
getAllRect(this, '.van-rate__icon').then((list) => {
const target = list
.sort((cur, next) => cur.dataset.score - next.dataset.score)
.find((item) => clientX >= item.left && clientX <= item.right);
if (target != null) {
this.onSelect({
...event,
currentTarget: (target as unknown) as WechatMiniprogram.Target,
});
}
});
},
},
});
================================================
FILE: packages/rate/index.wxml
================================================
================================================
FILE: packages/rate/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
自定义图标
自定义样式
半星
自定义数量
禁用状态
只读状态
监听 change 事件
`;
================================================
FILE: packages/rate/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/row/index.json
================================================
{
"component": true
}
================================================
FILE: packages/row/index.less
================================================
.van-row {
&::after {
display: table;
clear: both;
content: '';
}
}
================================================
FILE: packages/row/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('col', function (target) {
const { gutter } = this.data;
if (gutter) {
target.setData({ gutter });
}
}),
props: {
gutter: {
type: Number,
observer: 'setGutter',
},
},
methods: {
setGutter() {
this.children.forEach((col) => {
col.setData(this.data);
});
},
},
});
================================================
FILE: packages/row/index.wxml
================================================
================================================
FILE: packages/row/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'margin-right': addUnit(-data.gutter / 2),
'margin-left': addUnit(-data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/search/README.md
================================================
# Search 搜索
### 介绍
用于搜索场景的输入框组件。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-search": "@vant/weapp/search/index"
}
```
## 代码演示
### 基础用法
`van-search` 中,value 用于控制搜索框中的文字。background 可以自定义搜索框外部背景色。
```html
```
### 事件监听
`van-search` 提供了 search 和 cancel 事件。search 事件在用户点击键盘上的搜索按钮触发。cancel 事件在用户点击搜索框右侧取消按钮时触发。
```html
```
### 搜索框内容对齐
通过 `input-align` 属性可以设置搜索框内容的对齐方式。
```html
```
### 禁用搜索框
通过 `disabled` 属性可以将组件设置为禁用状态。
```html
```
### 自定义背景色
通过`background`属性可以设置搜索框外部的背景色,通过`shape`属性设置搜索框的形状,可选值为`round`。
```html
```
### 自定义按钮
`van-search` 支持自定义右侧取消按钮,使用名字为 action 的 slot,并设置 use-action-slot 为 true 即可。
```html
搜索
```
```javascript
Page({
data: {
value: '',
},
onChange(e) {
this.setData({
value: e.detail,
});
},
onSearch() {
Toast('搜索' + this.data.value);
},
onClick() {
Toast('搜索' + this.data.value);
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符 | _string_ | - |
| label | 搜索框左侧文本 | _string_ | - |
| shape | 形状,可选值为 `round` | _string_ | `square` |
| value | 当前输入的值 | _string \| number_ | - |
| background | 搜索框背景色 | _string_ | `#f2f2f2` |
| show-action | 是否在搜索框右侧显示取消按钮 | _boolean_ | `false` |
| action-text `v1.0.0` | 取消按钮文字 | _string_ | `取消` |
| focus | 获取焦点 | _boolean_ | `false` |
| error | 是否将输入内容标红 | _boolean_ | `false` |
| disabled | 是否禁用输入框 | _boolean_ | `false` |
| readonly | 是否只读 | _boolean_ | `false` |
| clearable | 是否启用清除控件 | _boolean_ | `true` |
| clear-trigger `v1.8.4` | 显示清除图标的时机,`always` 表示输入框不为空时展示,
`focus` 表示输入框聚焦且不为空时展示 | _string_ | `focus` |
| clear-icon `v1.8.4` | 清除[图标名称](#/icon)或图片链接 | _string_ | `clear` |
| maxlength | 最大输入长度,设置为 -1 的时候不限制最大长度 | _number_ | `-1` |
| use-action-slot | 是否使用 action slot | _boolean_ | `false` |
| placeholder | 输入框为空时占位符 | _string_ | - |
| placeholder-style | 指定占位符的样式 | _string_ | - |
| input-align | 输入框内容对齐方式,可选值为 `center` `right` | _string_ | `left` |
| use-left-icon-slot | 是否使用输入框左侧图标 slot | _boolean_ | `false` |
| use-right-icon-slot | 是否使用输入框右侧图标 slot | _boolean_ | `false` |
| left-icon | 输入框左侧图标名称或图片链接,可选值见 Icon 组件(如果设置了 use-left-icon-slot,则该属性无效) | _string_ | `search` |
| right-icon | 输入框右侧图标名称或图片链接,可选值见 Icon 组件(如果设置了 use-right-icon-slot,则该属性无效) | _string_ | - |
| cursor-spacing | 输入框聚焦时底部与键盘的距离 | _number_ | `0` |
### Events
| 事件名 | 说明 | 参数 |
| ---------------- | ------------------ | ------------------------ |
| bind:search | 确定搜索时触发 | event.detail: 当前输入值 |
| bind:change | 输入内容变化时触发 | event.detail: 当前输入值 |
| bind:cancel | 取消搜索搜索时触发 | - |
| bind:focus | 输入框聚焦时触发 | - |
| bind:blur | 输入框失焦时触发 | - |
| bind:clear | 点击清空控件时触发 | - |
| bind:click-input | 点击搜索区域时触发 | - |
### Slot
| 名称 | 说明 |
| --- | --- |
| action | 自定义搜索框右侧按钮,需要在`use-action-slot`为 true 时才会显示 |
| label | 自定义搜索框左侧文本 |
| left-icon | 自定义输入框左侧图标,需要在`use-left-icon-slot`为 true 时才会显示 |
| right-icon | 自定义输入框右侧图标,需要在`use-right-icon-slot`为 true 时才会显示 |
### 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| field-class | 搜索框样式类 |
| input-class | 输入框样式类 |
| cancel-class | 取消按钮样式类 |
================================================
FILE: packages/search/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-search": "../../search/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/search/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
value: '',
},
methods: {
onChange(e) {
this.setData({
value: e.detail,
});
},
onSearch() {
if (this.data.value) {
wx.showToast({
title: '搜索:' + this.data.value,
icon: 'none',
});
}
},
onClick() {
if (this.data.value) {
wx.showToast({
title: '搜索:' + this.data.value,
icon: 'none',
});
}
},
onCancel() {
wx.showToast({
title: '取消',
icon: 'none',
});
},
onClear() {
wx.showToast({
title: '清空',
icon: 'none',
});
},
},
});
================================================
FILE: packages/search/demo/index.wxml
================================================
搜索
================================================
FILE: packages/search/index.json
================================================
{
"component": true,
"usingComponents": {
"van-field": "../field/index"
}
}
================================================
FILE: packages/search/index.less
================================================
@import '../common/style/var.less';
.van-search {
display: flex;
align-items: center;
box-sizing: border-box;
padding: var(--search-padding, @search-padding);
&__content {
display: flex;
flex: 1;
padding-left: var(--padding-sm, @padding-sm);
border-radius: @border-radius-sm;
background-color: var(--search-background-color, @search-background-color);
&--round {
border-radius: @border-radius-max;
}
}
&__label {
padding: var(--search-label-padding, @search-label-padding);
font-size: var(--search-label-font-size, @search-label-font-size);
line-height: var(--search-input-height, @search-input-height);
color: var(--search-label-color, @search-label-color);
}
&__field {
flex: 1;
&__left-icon {
color: var(--search-left-icon-color, @search-left-icon-color);
}
}
&--withaction {
padding-right: 0;
}
&__action {
font-size: var(--search-action-font-size, @search-action-font-size);
line-height: var(--search-input-height, @search-input-height);
color: var(--search-action-text-color, @search-action-text-color);
&--hover {
background-color: @active-color;
}
&-button {
padding: var(--search-action-padding, @search-action-padding);
}
}
}
================================================
FILE: packages/search/index.ts
================================================
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
value: {
type: String,
value: '',
},
label: String,
focus: Boolean,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search',
},
rightIcon: String,
placeholder: String,
placeholderStyle: String,
actionText: {
type: String,
value: '取消',
},
background: {
type: String,
value: '#ffffff',
},
maxlength: {
type: Number,
value: -1,
},
shape: {
type: String,
value: 'square',
},
clearable: {
type: Boolean,
value: true,
},
clearTrigger: {
type: String,
value: 'focus',
},
clearIcon: {
type: String,
value: 'clear',
},
cursorSpacing: {
type: Number,
value: 0,
},
},
methods: {
onChange(event: WechatMiniprogram.CustomEvent) {
if (canIUseModel()) {
this.setData({ value: event.detail });
}
this.$emit('change', event.detail);
},
onCancel() {
/**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* https://github.com/youzan/vant-weapp/issues/1768
*/
setTimeout(() => {
if (canIUseModel()) {
this.setData({ value: '' });
}
this.$emit('cancel');
this.$emit('change', '');
}, 200);
},
onSearch(event: WechatMiniprogram.CustomEvent) {
this.$emit('search', event.detail);
},
onFocus(event: WechatMiniprogram.CustomEvent) {
this.$emit('focus', event.detail);
},
onBlur(event: WechatMiniprogram.CustomEvent) {
this.$emit('blur', event.detail);
},
onClear(event: WechatMiniprogram.CustomEvent) {
this.$emit('clear', event.detail);
},
onClickInput(event) {
this.$emit('click-input', event.detail);
},
},
});
================================================
FILE: packages/search/index.wxml
================================================
{{ label }}
{{ actionText }}
================================================
FILE: packages/search/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基本用法
事件监听
取消
搜索框内容对齐
禁用搜索框
自定义背景色
自定义按钮
地址
搜索
`;
================================================
FILE: packages/search/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/share-sheet/README.md
================================================
# ShareSheet 分享面板
### 介绍
底部弹起的分享面板,用于展示各分享渠道对应的操作按钮,不含具体的分享逻辑。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-share-sheet": "@vant/weapp/share-sheet/index"
}
```
## 代码演示
### 基础用法
分享面板通过 `options` 属性来定义分享选项,数组的每一项是一个对象,对象格式见文档下方表格。
```html
```
```js
Page({
data: {
showShare: false,
options: [
{ name: '微信', icon: 'wechat', openType: 'share' },
{ name: '微博', icon: 'weibo' },
{ name: '复制链接', icon: 'link' },
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
],
},
onClick(event) {
this.setData({ showShare: true });
},
onClose() {
this.setData({ showShare: false });
},
onSelect(event) {
Toast(event.detail.name);
this.onClose();
},
});
```
### 展示多行选项
当分享选项的数量较多时,可以将 `options` 定义为数组嵌套的格式,每个子数组会作为一行选项展示。
```html
```
```js
Page({
data: {
showShare: false,
options: [
[
{ name: '微信', icon: 'wechat' },
{ name: '微博', icon: 'weibo' },
{ name: 'QQ', icon: 'qq' },
],
[
{ name: '复制链接', icon: 'link' },
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
],
],
},
});
```
### 自定义图标
除了使用内置的几种图标外,可以直接在 `icon` 中传入图片 URL 来使用自定义的图标。
```html
```
```js
Page({
data: {
showShare: false,
options: [
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-fire.png',
},
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-light.png',
},
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-water.png',
},
],
},
});
```
### 展示描述信息
通过 `description` 属性可以设置标题下方的描述文字, 在 `options` 内设置 `description` 属性可以添加分享选项描述。
```html
```
```js
Page({
data: {
showShare: false,
options: [
{ name: '微信', icon: 'wechat' },
{ name: '微博', icon: 'weibo' },
{
name: '复制链接',
icon: 'link',
description: '描述信息',
},
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
],
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| show | 是否显示分享面板 | _boolean_ | `false` |
| options | 分享选项 | _Option[]_ | `[]` |
| title | 顶部标题 | _string_ | - |
| cancel-text | 取消按钮文字 | _string_ | `'取消'` |
| description | 标题下方的辅助描述文字 | _string_ | - |
| duration | 动画时长,单位毫秒 | _number \| string_ | `300` |
| overlay | 是否显示遮罩层 | _boolean_ | `true` |
| close-on-click-overlay | 是否在点击遮罩层后关闭 | _boolean_ | `true` |
| safe-area-inset-bottom | 是否开启底部安全区适配 | _boolean_ | `true` |
| root-portal `v1.11.3` | 是否从页面子树中脱离出来,用于解决各种 fixed 失效问题,微信基础库 >= `2.25.2 ` | _boolean_ | `false` |
### Option 数据结构
`options`属性为一个对象数组,数组中的每个对象配置一列,对象可以包含以下值:
| 键名 | 说明 | 类型 |
| --- | --- | --- |
| name | 分享渠道名称 | _string_ |
| description | 分享选项描述 | _string_ |
| icon | 图标,可选值为 `qq` `link` `weibo` `wechat` `poster` `qrcode` `weapp-qrcode` `wechat-moments`,支持传入图片 URL | _string_ |
| openType | 按钮 `open-type`,可用于实现分享功能,可选值为 `share` | _string_ |
### Events
| 事件名 | 说明 | 回调参数 |
| ------------- | ------------------ | ------------------------------- |
| bind:select | 点击分享选项时触发 | _option: Option, index: number_ |
| bind:close | 关闭时触发 | - |
| bind:cancel | 点击取消按钮时触发 | - |
| bind:click-overlay | 点击遮罩层时触发 | - |
### Slots
| 名称 | 说明 |
| ----------- | -------------- |
| title | 自定义顶部标题 |
| description | 自定义描述文字 |
================================================
FILE: packages/share-sheet/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-toast": "../../toast/index",
"van-share-sheet": "../../share-sheet/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/share-sheet/demo/index.less
================================================
.container {
height: 100vh;
background-color: #fff;
}
.tag,
.button {
margin-right: 5px;
}
.van-card__footer {
margin-top: 5px;
}
================================================
FILE: packages/share-sheet/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
show: {
basic: false,
withDesc: false,
multiLine: false,
customIcon: false,
},
options: [
{ name: '微信', icon: 'wechat', openType: 'share' },
{ name: '朋友圈', icon: 'wechat-moments' },
{ name: 'QQ', icon: 'qq' },
{ name: '微博', icon: 'weibo' },
{ name: '复制链接', icon: 'link' },
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
{ name: '小程序码', icon: 'weapp-qrcode' },
],
multiLineOptions: [
[
{ name: '微信', icon: 'wechat' },
{ name: '微博', icon: 'weibo' },
{ name: 'QQ', icon: 'qq' },
],
[
{ name: '复制链接', icon: 'link' },
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
],
],
customIconOptions: [
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-fire.png',
},
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-light.png',
},
{
name: '名称',
icon: 'https://img.yzcdn.cn/vant/custom-icon-water.png',
},
],
optionsWithDesc: [
{ name: '微信', icon: 'wechat' },
{ name: '微博', icon: 'weibo' },
{
name: '复制链接',
icon: 'link',
description: '描述信息',
},
{ name: '分享海报', icon: 'poster' },
{ name: '二维码', icon: 'qrcode' },
],
},
methods: {
onShowShareSheet(event) {
this.setData({
[`show.${event.target.dataset.type}`]: true,
});
},
onClose() {
this.setData({
show: {
basic: false,
withDesc: false,
multiLine: false,
customIcon: false,
},
});
},
onSelect(event) {
Toast({ context: this, message: event.detail.name });
this.onClose();
},
},
});
================================================
FILE: packages/share-sheet/demo/index.wxml
================================================
================================================
FILE: packages/share-sheet/index.json
================================================
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"options": "./options"
}
}
================================================
FILE: packages/share-sheet/index.less
================================================
@import '../common/style/var';
@import '../common/style/mixins/hairline.less';
.van-share-sheet {
&__header {
padding: @share-sheet-header-padding;
text-align: center;
}
&__title {
margin-top: @padding-xs;
color: @share-sheet-title-color;
font-weight: normal;
font-size: @share-sheet-title-font-size;
line-height: @share-sheet-title-line-height;
&:empty {
display: none;
}
}
&__title:not(:empty) + &__title {
display: none;
}
&__description {
display: block;
margin-top: @padding-xs;
color: @share-sheet-description-color;
font-size: @share-sheet-description-font-size;
line-height: @share-sheet-description-line-height;
&:empty {
display: none;
}
}
&__description:not(:empty) + &__description {
display: none;
}
&__cancel {
display: block;
box-sizing: content-box;
width: 100%;
height: auto;
padding: 0;
font-size: @share-sheet-cancel-button-font-size;
line-height: @share-sheet-cancel-button-height;
text-align: center;
background: @share-sheet-cancel-button-background;
border: none;
&::before {
display: block;
height: @padding-xs;
background-color: @background-color;
content: ' ';
}
&::after {
display: none;
}
&:active {
background-color: @active-color;
}
}
}
================================================
FILE: packages/share-sheet/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
// whether to show popup
show: Boolean,
// overlay custom style
overlayStyle: String,
// z-index
zIndex: {
type: Number,
value: 100,
},
title: String,
cancelText: {
type: String,
value: '取消',
},
description: String,
options: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
duration: {
type: null,
value: 300,
},
rootPortal: {
type: Boolean,
value: false,
},
},
methods: {
onClickOverlay() {
this.$emit('click-overlay');
},
onCancel() {
this.onClose();
this.$emit('cancel');
},
onSelect(event: WechatMiniprogram.CustomEvent) {
this.$emit('select', event.detail);
},
onClose() {
this.$emit('close');
},
},
});
================================================
FILE: packages/share-sheet/index.wxml
================================================
================================================
FILE: packages/share-sheet/index.wxs
================================================
/* eslint-disable */
function isMulti(options) {
if (options == null || options[0] == null) {
return false;
}
return "Array" === options.constructor && "Array" === options[0].constructor;
}
module.exports = {
isMulti: isMulti
};
================================================
FILE: packages/share-sheet/options.json
================================================
{
"component": true
}
================================================
FILE: packages/share-sheet/options.less
================================================
@import '../common/style/var';
@import '../common/style/mixins/hairline.less';
.van-share-sheet {
&__options {
position: relative;
display: flex;
padding: @padding-md 0 @padding-md @padding-xs;
overflow-x: auto;
overflow-y: visible;
-webkit-overflow-scrolling: touch;
&--border::before {
.hairline-top(@cell-border-color, @padding-md);
}
&::-webkit-scrollbar {
height: 0;
}
}
&__option {
display: flex;
flex-direction: column;
align-items: center;
user-select: none;
&:active {
opacity: @active-opacity;
}
}
&__button {
height: auto;
padding: 0;
line-height: inherit;
background-color: transparent;
border: 0;
&::after {
border: 0;
}
}
&__icon {
width: @share-sheet-icon-size;
height: @share-sheet-icon-size;
margin: 0 @padding-md;
}
&__name {
margin-top: @padding-xs;
padding: 0 @padding-base;
color: @share-sheet-option-name-color;
font-size: @share-sheet-option-name-font-size;
}
&__option-description {
padding: 0 @padding-base;
color: @share-sheet-option-description-color;
font-size: @share-sheet-option-description-font-size;
}
}
================================================
FILE: packages/share-sheet/options.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
options: Array,
showBorder: Boolean,
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const option = this.data.options[index];
this.$emit('select', { ...option, index });
},
},
});
================================================
FILE: packages/share-sheet/options.wxml
================================================
================================================
FILE: packages/share-sheet/options.wxs
================================================
/* eslint-disable */
var PRESET_ICONS = ['qq', 'link', 'weibo', 'wechat', 'poster', 'qrcode', 'weapp-qrcode', 'wechat-moments'];
function getIconURL(icon) {
if (PRESET_ICONS.indexOf(icon) !== -1) {
return 'https://img.yzcdn.cn/vant/share-sheet-' + icon + '.png';
}
return icon;
}
module.exports = {
getIconURL: getIconURL,
};
================================================
FILE: packages/share-sheet/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
显示分享面板
展示多行选项
显示分享面板
自定义图标
显示分享面板
展示描述信息
显示分享面板
`;
================================================
FILE: packages/share-sheet/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/sidebar/README.md
================================================
# Sidebar 侧边导航
### 介绍
垂直展示的导航栏,用于在不同的内容区域之间进行切换。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-sidebar": "@vant/weapp/sidebar/index",
"van-sidebar-item": "@vant/weapp/sidebar-item/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基础用法
通过在`van-sidebar`上设置`activeKey`属性来控制选中项。
```html
```
```javascript
Page({
data: {
activeKey: 0,
},
});
```
### 徽标提示
设置`dot`属性后,会在右上角展示一个小红点。设置`badge`属性后,会在右上角展示相应的徽标。
```html
```
### 禁用选项
通过`disabled`属性禁用选项。
```html
```
### 监听切换事件
设置`change`方法来监听切换导航项时的事件。
```html
```
```js
import Notify from '@vant/weapp/notify/notify';
Page({
data: {
activeKey: 0,
},
onChange(event) {
Notify({ type: 'primary', message: event.detail });
},
});
```
## API
### Sidebar Props
| 参数 | 说明 | 类型 | 默认值 |
| --------- | ------------ | ------------------ | ------ |
| activeKey | 选中项的索引 | _string \| number_ | `0` |
### Sidebar Event
| 事件名 | 说明 | 参数 |
| ------ | -------------- | ------------------ |
| change | 切换徽章时触发 | 当前选中徽章的索引 |
### Sidebar 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### SidebarItem Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 内容 | _string_ | `''` |
| dot | 是否显示右上角小红点 | _boolean_ | `false` |
| info | 图标右上角徽标的内容(已废弃,请使用 badge 属性) | _string \| number_ | `''` |
| badge `v1.5.0` | 图标右上角徽标的内容 | _string \| number_ | `''` |
| disabled | 是否禁用该项 | _boolean_ | `false` |
### SidebarItem Slot
| 名称 | 说明 |
| ----- | ------------------------------------------- |
| title | 自定义标题栏,如果设置了`title`属性则不生效 |
### SidebarItem Event
| 事件名 | 说明 | 参数 |
| ------ | -------------- | ------------------------------- |
| click | 点击徽章时触发 | `event.detail` 为当前徽章的索引 |
### SidebarItem 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/sidebar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-grid": "../../grid/index",
"van-grid-item": "../../grid-item/index",
"van-sidebar": "../../sidebar/index",
"van-sidebar-item": "../../sidebar-item/index",
"van-notify": "../../notify/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/sidebar/demo/index.less
================================================
.custom-sidebar {
margin-left: 16px;
}
.demo-sidebar {
background-color: #fff;
}
.demo-sidebar-title {
margin-bottom: 16px;
color: #969799;
font-weight: normal;
font-size: 14px;
}
================================================
FILE: packages/sidebar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Notify from '../../notify/notify';
VantComponent({
methods: {
onChange(event) {
Notify({
context: this,
type: 'primary',
message: `切换至第${event.detail}项`,
});
},
},
});
================================================
FILE: packages/sidebar/demo/index.wxml
================================================
================================================
FILE: packages/sidebar/index.json
================================================
{
"component": true
}
================================================
FILE: packages/sidebar/index.less
================================================
@import '../common/style/var.less';
.van-sidebar {
width: var(--sidebar-width, @sidebar-width);
}
================================================
FILE: packages/sidebar/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('sidebar-item', function () {
this.setActive(this.data.activeKey);
}),
props: {
activeKey: {
type: Number,
value: 0,
observer: 'setActive',
},
},
beforeCreate() {
this.currentActive = -1;
},
methods: {
setActive(activeKey: number) {
const { children, currentActive } = this;
if (!children.length) {
return Promise.resolve();
}
this.currentActive = activeKey;
const stack: Promise[] = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
},
},
});
================================================
FILE: packages/sidebar/index.wxml
================================================
================================================
FILE: packages/sidebar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
`;
================================================
FILE: packages/sidebar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/sidebar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
================================================
FILE: packages/sidebar-item/index.less
================================================
@import '../common/style/var.less';
.van-sidebar-item {
display: block;
box-sizing: border-box;
overflow: hidden;
border-left: 3px solid transparent;
user-select: none;
padding: var(--sidebar-padding, @sidebar-padding);
font-size: var(--sidebar-font-size, @sidebar-font-size);
line-height: var(--sidebar-line-height, @sidebar-line-height);
color: var(--sidebar-text-color, @sidebar-text-color);
background-color: var(--sidebar-background-color, @sidebar-background-color);
&__text {
position: relative;
display: inline-block;
word-break: break-all;
}
&--hover:not(&--disabled) {
background-color: var(--sidebar-active-color, @sidebar-active-color);
}
&::after {
border-bottom-width: 1px;
}
&--selected {
color: var(--sidebar-selected-text-color, @sidebar-selected-text-color);
font-weight: var(
--sidebar-selected-font-weight,
@sidebar-selected-font-weight
);
border-color: var(
--sidebar-selected-border-color,
@sidebar-selected-border-color
);
&::after {
border-right-width: 1px;
}
}
&--selected,
&--selected&--hover {
background-color: var(
--sidebar-selected-background-color,
@sidebar-selected-background-color
);
}
&--disabled {
color: var(--sidebar-disabled-text-color, @sidebar-disabled-text-color);
}
}
================================================
FILE: packages/sidebar-item/index.ts
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
classes: ['active-class', 'disabled-class'],
relation: useParent('sidebar'),
props: {
dot: Boolean,
badge: null,
info: null,
title: String,
disabled: Boolean,
},
methods: {
onClick() {
const { parent } = this;
if (!parent || this.data.disabled) {
return;
}
const index = parent.children.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(selected: boolean) {
return this.setData({ selected });
},
},
});
================================================
FILE: packages/sidebar-item/index.wxml
================================================
================================================
FILE: packages/skeleton/README.md
================================================
# Skeleton 骨架屏
### 介绍
用于在内容加载过程中展示一组占位图形。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-skeleton": "@vant/weapp/skeleton/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基础用法
通过`title`属性显示标题占位图,通过`row`属性配置占位段落行数。
```html
```
### 显示头像
通过`avatar`属性显示头像占位图。
```html
```
### 展示子组件
将`loading`属性设置成`false`表示内容加载完成,此时会隐藏占位图,并显示`Skeleton`的子组件。
```html
实际内容
```
```js
Page({
data: {
loading: true,
},
onReady() {
this.setData({
loading: false,
});
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| row | 段落占位图行数 | _number_ | `0` |
| row-width | 段落占位图宽度,可传数组来设置每一行的宽度 | _string \| string[]_ | `100%` |
| title | 是否显示标题占位图 | _boolean_ | `false` |
| title-width | 标题占位图宽度 | _string \| number_ | `40%` |
| avatar | 是否显示头像占位图 | _boolean_ | `false` |
| avatar-size | 头像占位图大小 | _string \| number_ | `32px` |
| avatar-shape | 头像占位图形状,可选值为`square` | _string_ | `round` |
| loading | 是否显示占位图,传`false`时会展示子组件内容 | _boolean_ | `true` |
| animate | 是否开启动画 | _boolean_ | `true` |
### 外部样式类
| 类名 | 说明 |
| ---------------- | ------------------ |
| custom-class | 根节点样式类 |
| row-class | 段落占位样式类 |
| avatar-class | 头像占位样式类 |
| title-class | 标题占位样式类 |
================================================
FILE: packages/skeleton/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-switch": "../../switch/index",
"van-skeleton": "../../skeleton/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/skeleton/demo/index.less
================================================
.van-switch {
margin: 0 16px 8px;
}
.demo-preview {
display: flex;
padding: 0 16px;
}
.demo-content {
padding-top: 6px;
}
.demo-content-h3 {
margin: 0;
font-size: 18px;
line-height: 20px;
}
.demo-content-p {
margin: 13px 0 0;
font-size: 14px;
line-height: 20px;
}
.demo-preview-img {
flex-shrink: 0;
width: 32px;
height: 32px;
margin-right: 16px;
}
================================================
FILE: packages/skeleton/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show: false,
},
methods: {
onChange({ detail }) {
this.setData({ show: detail });
},
},
});
================================================
FILE: packages/skeleton/demo/index.wxml
================================================
关于 Vant Weapp
Vant Weapp 是移动端 Vue 组件库 Vant 的小程序版本,两者基于相同的视觉规范,提供一致的 API 接口,助力开发者快速搭建小程序应用。
================================================
FILE: packages/skeleton/index.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: packages/skeleton/index.less
================================================
@import '../common/style/var.less';
.van-skeleton {
display: flex;
box-sizing: border-box;
width: 100%;
padding: var(--skeleton-padding, @skeleton-padding);
&__avatar {
flex-shrink: 0;
margin-right: var(--padding-md, @padding-md);
background-color: var(
--skeleton-avatar-background-color,
@skeleton-avatar-background-color
);
&--round {
border-radius: 100%;
}
}
&__content {
flex: 1;
}
&__avatar + &__content {
padding-top: var(--padding-xs, @padding-xs);
}
&__row,
&__title {
height: var(--skeleton-row-height, @skeleton-row-height);
background-color: var(
--skeleton-row-background-color,
@skeleton-row-background-color
);
}
&__title {
margin: 0;
}
&__row {
&:not(:first-child) {
margin-top: var(--skeleton-row-margin-top, @skeleton-row-margin-top);
}
}
&__title + &__row {
margin-top: 20px;
}
&--animate {
animation: van-skeleton-blink @skeleton-animation-duration ease-in-out
infinite;
}
}
@keyframes van-skeleton-blink {
50% {
opacity: 0.6;
}
}
================================================
FILE: packages/skeleton/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['avatar-class', 'title-class', 'row-class'],
props: {
row: {
type: Number,
value: 0,
observer(value: number) {
this.setData({ rowArray: Array.from({ length: value }) });
},
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true,
},
animate: {
type: Boolean,
value: true,
},
avatarSize: {
type: String,
value: '32px',
},
avatarShape: {
type: String,
value: 'round',
},
titleWidth: {
type: String,
value: '40%',
},
rowWidth: {
type: null,
value: '100%',
observer(val) {
this.setData({ isArray: val instanceof Array });
},
},
},
data: {
isArray: false,
rowArray: [],
},
});
================================================
FILE: packages/skeleton/index.wxml
================================================
================================================
FILE: packages/skeleton/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
显示头像
展示子组件
`;
================================================
FILE: packages/skeleton/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/slider/README.md
================================================
# Slider 滑块
### 介绍
滑动输入条,用于在给定的范围内选择一个值。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-slider": "@vant/weapp/slider/index"
}
```
## 代码演示
### 基本用法
```html
```
```js
Page({
onChange(event) {
wx.showToast({
icon: 'none',
title: `当前值:${event.detail}`,
});
},
});
```
### 双滑块
添加 `range` 属性就可以开启双滑块模式,确保 `value` 的值是一个数组。
```html
```
```js
Page({
onChange(event) {
wx.showToast({
icon: 'none',
title: `当前值:${event.detail}`,
});
},
});
```
### 指定选择范围
```html
```
### 禁用
```html
```
### 指定步长
```html
```
### 自定义样式
```html
```
### 自定义按钮
```html
{{ currentValue }}/100
```
```js
Page({
data: {
currentValue: 50,
},
onDrag(event) {
this.setData({
currentValue: event.detail.value,
});
},
});
```
### 垂直方向
设置 `vertical` 属性后,滑块会垂直展示,且高度为 100% 父元素高度。
```html
```
```js
Page({
onChange(event) {
wx.showToast({
icon: 'none',
title: `当前值:${event.detail}`,
});
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 当前进度百分比,在双滑块模式下为数组格式 | _number \| number[]_ | `0` |
| disabled | 是否禁用滑块 | _boolean_ | `false` |
| max | 最大值 | _number_ | `100` |
| min | 最小值 | _number_ | `0` |
| step | 步长 | _number_ | `1` |
| bar-height | 进度条高度,默认单位为 `px` | _string \| number_ | `2px` |
| active-color | 进度条激活态颜色 | _string_ | `#1989fa` |
| inactive-color | 进度条默认颜色 | _string_ | `#e5e5e5` |
| use-button-slot | 是否使用按钮插槽 | _boolean_ | `false` |
| range `v1.8.4` | 是否开启双滑块模式 | _boolean_ | `false` |
| vertical `v1.8.5` | 是否垂直展示 | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 参数 |
| --------------- | ---------------- | ---------------------------- |
| bind:drag | 拖动进度条时触发 | event.detail.value: 当前进度 |
| bind:change | 进度值改变后触发 | event.detail: 当前进度 |
| bind:drag-start | 开始拖动时触发 | - |
| bind:drag-end | 结束拖动时触发 | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
### Slots
| 名称 | 说明 | 参数 |
| --- | --- | --- |
| button | 自定义滑块按钮 | _{ value: number }_ |
| left-button `v1.8.4` | 自定义左侧滑块按钮(双滑块模式下) | _{ value: number }_ |
| right-button `v1.8.4` | 自定义右侧滑块按钮 (双滑块模式下) | _{ value: number }_ |
================================================
FILE: packages/slider/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-slider": "../../slider/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/slider/demo/index.less
================================================
.slider {
margin: 0 15px 30px;
}
.custom-button {
width: 26px;
color: #fff;
font-size: 10px;
line-height: 18px;
text-align: center;
border-radius: 100px;
background-color: #ee0a24;
}
================================================
FILE: packages/slider/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
currentValue: 50,
},
methods: {
onChange(event) {
wx.showToast({
icon: 'none',
title: `当前值:${event.detail}`,
});
},
onDrag(event) {
this.setData({
currentValue: event.detail.value,
});
},
},
});
================================================
FILE: packages/slider/demo/index.wxml
================================================
{{ currentValue }}
================================================
FILE: packages/slider/index.json
================================================
{
"component": true
}
================================================
FILE: packages/slider/index.less
================================================
@import '../common/style/var.less';
.van-slider {
position: relative;
height: var(--slider-bar-height, @slider-bar-height);
border-radius: @border-radius-max;
background-color: var(
--slider-inactive-background-color,
@slider-inactive-background-color
);
// use pseudo element to expand click area
&::before {
position: absolute;
right: 0;
left: 0;
content: '';
top: calc(-1 * var(--padding-xs, @padding-xs));
bottom: calc(-1 * var(--padding-xs, @padding-xs));
}
&__bar {
position: relative;
width: 100%;
height: 100%;
background-color: var(
--slider-active-background-color,
@slider-active-background-color
);
border-radius: inherit;
transition: all @animation-duration-fast;
}
&__button {
width: var(--slider-button-width, @slider-button-width);
height: var(--slider-button-height, @slider-button-height);
border-radius: var(
--slider-button-border-radius,
@slider-button-border-radius
);
box-shadow: var(--slider-button-box-shadow, @slider-button-box-shadow);
background-color: var(
--slider-button-background-color,
@slider-button-background-color
);
&-wrapper,
&-wrapper-right {
position: absolute;
top: 50%;
right: 0;
transform: translate3d(50%, -50%, 0);
}
&-wrapper-left {
position: absolute;
top: 50%;
left: 0;
transform: translate3d(-50%, -50%, 0);
}
}
&--disabled {
opacity: var(--slider-disabled-opacity, @slider-disabled-opacity);
}
&--vertical {
display: inline-block;
width: var(--slider-bar-height, @slider-bar-height);
height: 100%;
.van-slider__button-wrapper,
.van-slider__button-wrapper-right {
top: auto;
right: 50%;
bottom: 0;
transform: translate3d(50%, 50%, 0);
}
.van-slider__button-wrapper-left {
top: 0;
right: 50%;
left: auto;
transform: translate3d(50%, -50%, 0);
}
// use pseudo element to expand click area
&::before {
top: 0;
right: -@padding-xs;
bottom: 0;
left: -@padding-xs;
}
}
}
================================================
FILE: packages/slider/index.ts
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { canIUseModel } from '../common/version';
import { getRect, addUnit, nextTick, addNumber, clamp } from '../common/utils';
type SliderValue = number | [number, number];
const DRAG_STATUS = {
START: 'start',
MOVING: 'moving',
END: 'end',
};
VantComponent({
mixins: [touch],
props: {
range: Boolean,
disabled: Boolean,
useButtonSlot: Boolean,
activeColor: String,
inactiveColor: String,
max: {
type: Number,
value: 100,
},
min: {
type: Number,
value: 0,
},
step: {
type: Number,
value: 1,
},
value: {
type: null,
value: 0,
observer(val) {
if (val !== this.value) {
this.updateValue(val);
}
},
},
vertical: Boolean,
barHeight: null,
},
created() {
this.updateValue(this.data.value);
},
methods: {
onTouchStart(event: WechatMiniprogram.TouchEvent) {
if (this.data.disabled) return;
const { index } = event.currentTarget.dataset;
if (typeof index === 'number') {
this.buttonIndex = index;
}
this.touchStart(event);
this.startValue = this.format(this.value);
this.newValue = this.value;
if (this.isRange(this.newValue)) {
this.startValue = this.newValue.map((val) => this.format(val)) as [
number,
number
];
} else {
this.startValue = this.format(this.newValue);
}
this.dragStatus = DRAG_STATUS.START;
},
onTouchMove(event: WechatMiniprogram.TouchEvent) {
if (this.data.disabled) return;
if (this.dragStatus === DRAG_STATUS.START) {
this.$emit('drag-start');
}
this.touchMove(event);
this.dragStatus = DRAG_STATUS.MOVING;
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const delta = vertical ? this.deltaY : this.deltaX;
const total = vertical ? rect.height : rect.width;
const diff = (delta / total) * this.getRange();
if (this.isRange(this.startValue)) {
(this.newValue as [number, number])[this.buttonIndex] =
this.startValue[this.buttonIndex] + diff;
} else {
this.newValue = this.startValue + diff;
}
this.updateValue(this.newValue, false, true);
});
},
onTouchEnd() {
if (this.data.disabled) return;
if (this.dragStatus === DRAG_STATUS.MOVING) {
this.dragStatus = DRAG_STATUS.END;
nextTick(() => {
this.updateValue(this.newValue, true);
this.$emit('drag-end');
});
}
},
onClick(event: WechatMiniprogram.TouchEvent) {
if (this.data.disabled) return;
const { min } = this.data;
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const touch = event.touches[0];
const delta = vertical
? touch.clientY - rect.top
: touch.clientX - rect.left;
const total = vertical ? rect.height : rect.width;
const value = Number(min) + (delta / total) * this.getRange();
if (this.isRange(this.value)) {
const [left, right] = this.value;
const middle = (left + right) / 2;
if (value <= middle) {
this.updateValue([value, right], true);
} else {
this.updateValue([left, value], true);
}
} else {
this.updateValue(value, true);
}
});
},
isRange(val: unknown): val is [number, number] {
const { range } = this.data;
return range && Array.isArray(val);
},
handleOverlap(value: [number, number]) {
if (value[0] > value[1]) {
return value.slice(0).reverse();
}
return value;
},
updateValue(value: SliderValue, end?: boolean, drag?: boolean) {
if (this.isRange(value)) {
value = this.handleOverlap(value).map((val) => this.format(val)) as [
number,
number
];
} else {
value = this.format(value);
}
this.value = value;
const { vertical } = this.data;
const mainAxis = vertical ? 'height' : 'width';
this.setData({
wrapperStyle: `
background: ${this.data.inactiveColor || ''};
${vertical ? 'width' : 'height'}: ${
addUnit(this.data.barHeight) || ''
};
`,
barStyle: `
${mainAxis}: ${this.calcMainAxis()};
left: ${vertical ? 0 : this.calcOffset()};
top: ${vertical ? this.calcOffset() : 0};
${drag ? 'transition: none;' : ''}
`,
});
if (drag) {
this.$emit('drag', { value });
}
if (end) {
this.$emit('change', value);
}
if ((drag || end) && canIUseModel()) {
this.setData({ value });
}
},
getScope() {
return Number(this.data.max) - Number(this.data.min);
},
getRange() {
const { max, min } = this.data;
return max - min;
},
getOffsetWidth(current: number, min: number) {
const scope = this.getScope();
// 避免最小值小于最小step时出现负数情况
return `${Math.max(((current - min) * 100) / scope, 0)}%`;
},
// 计算选中条的长度百分比
calcMainAxis() {
const { value } = this;
const { min } = this.data;
if (this.isRange(value)) {
return this.getOffsetWidth(value[1], value[0]);
}
return this.getOffsetWidth(value, Number(min));
},
// 计算选中条的开始位置的偏移量
calcOffset() {
const { value } = this;
const { min } = this.data;
const scope = this.getScope();
if (this.isRange(value)) {
return `${((value[0] - Number(min)) * 100) / scope}%`;
}
return '0%';
},
format(value: number) {
const min = +this.data.min;
const max = +this.data.max;
const step = +this.data.step;
value = clamp(value, min, max);
const diff = Math.round((value - min) / step) * step;
return addNumber(min, diff);
},
},
});
================================================
FILE: packages/slider/index.wxml
================================================
================================================
FILE: packages/slider/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function barStyle(barHeight, activeColor) {
return style({
height: addUnit(barHeight),
background: activeColor,
});
}
module.exports = {
barStyle: barStyle,
};
================================================
FILE: packages/slider/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
双滑块
指定选择范围
禁用
指定步长
自定义样式
自定义按钮
50
垂直方向
`;
================================================
FILE: packages/slider/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/stepper/README.md
================================================
# Stepper 步进器
### 介绍
步进器由增加按钮、减少按钮和输入框组成,用于在一定范围内输入、调整数字。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-stepper": "@vant/weapp/stepper/index"
}
```
## 代码演示
### 基础用法
通过`value`设置输入值,可以通过`change`事件监听到输入值的变化。
```html
```
```js
Page({
onChange(event) {
console.log(event.detail);
},
});
```
### 步长设置
通过`step`属性设置每次点击增加或减少按钮时变化的值,默认为`1`。
```html
```
### 限制输入范围
通过`min`和`max`属性限制输入值的范围。
```html
```
### 限制输入整数
设置`integer`属性后,输入框将限制只能输入整数。
```html
```
### 禁用状态
通过设置`disabled`属性来禁用步进器,禁用状态下无法点击按钮或修改输入框。
```html
```
### 关闭长按
通过设置`long-press`属性决定步进器是否开启长按手势。
```html
```
### 固定小数位数
通过设置`decimal-length`属性可以保留固定的小数位数。
```html
```
### 异步变更
如果需要异步地修改输入框的值,可以设置`async-change`属性,并在`change`事件中手动修改`value`。
```html
```
```js
Page({
data: {
value: 1,
},
onChange(event) {
Toast.loading({ forbidClick: true });
setTimeout(() => {
Toast.clear();
this.setData({ value: event.detail });
}, 500);
},
});
```
### 自定义大小
通过`input-width`属性设置输入框宽度,通过`button-size`属性设置按钮大小和输入框高度。
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 在表单内提交时的标识符 | _string_ | - |
| value | 输入值 | _string \| number_ | 最小值 |
| min | 最小值 | _string \| number_ | `1` |
| max | 最大值 | _string \| number_ | - |
| step | 步长 | _string \| number_ | `1` |
| integer | 是否只允许输入整数 | _boolean_ | `false` |
| disabled | 是否禁用 | _boolean_ | `false` |
| disable-input | 是否禁用输入框 | _boolean_ | `false` |
| async-change | 是否开启异步变更,开启后需要手动控制输入值 | _boolean_ | `false` |
| input-width | 输入框宽度,默认单位为 `px` | _string \| number_ | `32px` |
| button-size | 按钮大小,默认单位为 `px`,输入框高度会和按钮大小保持一致 | _string \| number_ | `28px` |
| show-plus | 是否显示增加按钮 | _boolean_ | `true` |
| show-minus | 是否显示减少按钮 | _boolean_ | `true` |
| decimal-length | 固定显示的小数位数 | _number_ | - |
| theme | 样式风格,可选值为 `round` | _string_ | - |
| disable-plus | 是否禁用增加按钮 | _boolean_ | - |
| disable-minus | 是否禁用减少按钮 | _boolean_ | - |
| long-press | 是否开启长按手势 | _boolean_ | `true` |
| always-embed `v1.9.3` | 强制 input 处于同层状态,默认 focus 时 input 会切到非同层状态 (仅在 iOS 下生效) | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 回调参数 |
| -------------- | ------------------------ | -------------------------- |
| bind:change | 当绑定值变化时触发的事件 | event.detail: 当前输入的值 |
| bind:overlimit | 点击不可用的按钮时触发 | - |
| bind:plus | 点击增加按钮时触发 | - |
| bind:minus | 点击减少按钮时触发 | - |
| bind:focus | 输入框聚焦时触发 | - |
| bind:blur | 输入框失焦时触发 | - |
### Slot
| 名称 | 说明 |
| ----- | -------- |
| plus | 加号按钮 |
| minus | 减号按钮 |
### 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| input-class | 输入框样式类 |
| plus-class | 加号按钮样式类 |
| minus-class | 减号按钮样式类 |
================================================
FILE: packages/stepper/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-toast": "../../toast/index",
"van-stepper": "../../stepper/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/stepper/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
data: {
value: 1,
},
methods: {
onChange(event) {
Toast.loading({
context: this,
forbidClick: true,
});
setTimeout(() => {
Toast.clear();
this.setData({ value: event.detail });
}, 500);
},
},
});
================================================
FILE: packages/stepper/demo/index.wxml
================================================
================================================
FILE: packages/stepper/index.json
================================================
{
"component": true
}
================================================
FILE: packages/stepper/index.less
================================================
@import '../common/style/var.less';
.van-stepper {
font-size: 0;
&__minus,
&__plus {
position: relative;
display: inline-block;
box-sizing: border-box;
margin: 1px;
vertical-align: middle;
border: 0;
background-color: var(
--stepper-background-color,
@stepper-background-color
);
color: var(--stepper-button-icon-color, @stepper-button-icon-color);
width: var(--stepper-input-height, @stepper-input-height);
height: var(--stepper-input-height, @stepper-input-height);
padding: var(--padding-base, @padding-base);
&::before {
width: 9px;
height: 1px;
}
&::after {
width: 1px;
height: 9px;
}
&:empty&::before,
&:empty&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
background-color: currentColor;
content: '';
}
&--hover {
background-color: var(--stepper-active-color, @stepper-active-color);
}
&--disabled {
color: var(
--stepper-button-disabled-icon-color,
@stepper-button-disabled-icon-color
);
background-color: var(
--stepper-button-disabled-color,
@stepper-button-disabled-color
);
}
&--disabled&--hover {
background-color: var(
--stepper-button-disabled-color,
@stepper-button-disabled-color
);
}
}
&__minus {
border-radius: var(
--stepper-border-radius,
var(--stepper-border-radius, @stepper-border-radius)
)
0 0
var(
--stepper-border-radius,
var(--stepper-border-radius, @stepper-border-radius)
);
&::after {
display: none;
}
}
&__plus {
border-radius: 0
var(
--stepper-border-radius,
var(--stepper-border-radius, @stepper-border-radius)
)
var(
--stepper-border-radius,
var(--stepper-border-radius, @stepper-border-radius)
)
0;
}
&--round {
.van-stepper__input {
background-color: transparent !important;
}
.van-stepper__plus,
.van-stepper__minus {
border-radius: 100%;
&:active {
opacity: @active-opacity;
}
&--disabled {
&,
&:active {
opacity: 0.3;
}
}
}
.van-stepper__plus {
color: @white;
background-color: @stepper-button-round-theme-color;
}
.van-stepper__minus {
color: @stepper-button-round-theme-color;
background-color: @white;
border: 1px solid @stepper-button-round-theme-color;
}
}
&__input {
display: inline-block;
box-sizing: border-box;
// 覆盖 common style 中 input 的 min-height: 1.4rem;
// 避免 button-size 对 input 设置的 height 不生效
min-height: 0;
margin: 1px;
padding: 1px;
text-align: center;
vertical-align: middle;
border: 0;
border-width: 1px 0;
border-radius: 0;
-webkit-appearance: none;
font-size: var(--stepper-input-font-size, @stepper-input-font-size);
color: var(--stepper-input-text-color, @stepper-input-text-color);
background-color: var(
--stepper-background-color,
@stepper-background-color
);
width: var(--stepper-input-width, @stepper-input-width);
height: var(--stepper-input-height, @stepper-input-height);
&--disabled {
color: var(
--stepper-input-disabled-text-color,
@stepper-input-disabled-text-color
);
background-color: var(
--stepper-input-disabled-background-color,
@stepper-input-disabled-background-color
);
}
}
}
================================================
FILE: packages/stepper/index.ts
================================================
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
const LONG_PRESS_START_TIME = 600;
const LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1: number, num2: number) {
const cardinal = 10 ** 10;
return Math.round((num1 + num2) * cardinal) / cardinal;
}
function equal(value1: number | string, value2: number | string) {
return String(value1) === String(value2);
}
VantComponent({
field: true,
classes: ['input-class', 'plus-class', 'minus-class'],
props: {
value: {
type: null,
},
integer: {
type: Boolean,
observer: 'check',
},
disabled: Boolean,
inputWidth: String,
buttonSize: String,
asyncChange: Boolean,
disableInput: Boolean,
decimalLength: {
type: Number,
value: null as unknown as number,
observer: 'check',
},
min: {
type: null,
value: 1,
observer: 'check',
},
max: {
type: null,
value: Number.MAX_SAFE_INTEGER,
observer: 'check',
},
step: {
type: null,
value: 1,
},
showPlus: {
type: Boolean,
value: true,
},
showMinus: {
type: Boolean,
value: true,
},
disablePlus: Boolean,
disableMinus: Boolean,
longPress: {
type: Boolean,
value: true,
},
theme: String,
alwaysEmbed: Boolean,
},
data: {
currentValue: '',
},
watch: {
value() {
this.observeValue();
},
},
created() {
this.setData({
currentValue: this.format(this.data.value).newValue,
});
},
methods: {
observeValue() {
const { value } = this.data;
this.setData({ currentValue: this.format(value).newValue });
},
check() {
const { newValue } = this.format(this.data.currentValue);
if (!equal(newValue, this.data.currentValue)) {
this.setData({ currentValue: newValue });
}
},
isDisabled(type: string) {
const { disabled, disablePlus, disableMinus, currentValue, max, min } =
this.data;
if (type === 'plus') {
return disabled || disablePlus || +currentValue >= +max;
}
return disabled || disableMinus || +currentValue <= +min;
},
onFocus(event: WechatMiniprogram.InputFocus) {
this.$emit('focus', event.detail);
},
onBlur(event: WechatMiniprogram.InputBlur) {
const data = this.format(event.detail.value);
this.setData({ currentValue: data.newValue });
this.emitChange(data);
this.$emit('blur', {
...event.detail,
value: +data.newValue,
});
},
// filter illegal characters
filter(value: string): string {
value = String(value).replace(/[^0-9.-]/g, '');
if (this.data.integer && value.indexOf('.') !== -1) {
value = value.split('.')[0];
}
return value;
},
format(value: string) {
// filter illegal characters and format integer
const safeValue = this.filter(value);
// format range
const rangeValue = Math.max(
Math.min(this.data.max, +safeValue),
this.data.min
);
// format decimal
const newValue = isDef(this.data.decimalLength)
? rangeValue.toFixed(this.data.decimalLength)
: String(rangeValue);
return { value, newValue };
},
onInput(event: WechatMiniprogram.Input) {
const { value = '' } = event.detail || {};
// allow input to be empty
if (value === '') {
return;
}
const formatted = this.format(value);
this.emitChange(formatted);
},
emitChange(data: { value: string; newValue: string }) {
const { value, newValue } = data;
if (!this.data.asyncChange) {
// fix when input 11. parsed to 11, unable to enter decimal
this.setData({ currentValue: +value === +newValue ? value : newValue });
}
this.$emit('change', +newValue);
},
onChange() {
const { type } = this;
if (this.isDisabled(type)) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = this.format(String(add(+this.data.currentValue, diff)));
this.emitChange(value);
this.$emit(type);
},
longPressStep() {
this.longPressTimer = setTimeout(() => {
this.onChange();
this.longPressStep();
}, LONG_PRESS_INTERVAL);
},
onTap(event: WechatMiniprogram.TouchEvent) {
const { type } = event.currentTarget.dataset;
this.type = type;
this.onChange();
},
onTouchStart(event: WechatMiniprogram.TouchEvent) {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
const { type } = event.currentTarget.dataset;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(() => {
this.isLongPress = true;
this.onChange();
this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onTouchEnd() {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
},
},
});
================================================
FILE: packages/stepper/index.wxml
================================================
================================================
FILE: packages/stepper/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function buttonStyle(data) {
return style({
width: addUnit(data.buttonSize),
height: addUnit(data.buttonSize),
});
}
function inputStyle(data) {
return style({
width: addUnit(data.inputWidth),
height: addUnit(data.buttonSize),
});
}
module.exports = {
buttonStyle: buttonStyle,
inputStyle: inputStyle,
};
================================================
FILE: packages/stepper/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
步长设置
限制输入范围
限制输入整数
禁用状态
禁用长按
固定小数位数
异步变更
自定义大小
圆角风格
`;
================================================
FILE: packages/stepper/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/steps/README.md
================================================
# Steps 步骤条
### 介绍
用于展示操作流程的各个环节,让用户了解当前的操作在整体流程中的位置。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-steps": "@vant/weapp/steps/index"
}
```
## 代码演示
### 基础用法
```html
```
```javascript
Page({
data: {
steps: [
{
text: '步骤一',
desc: '描述信息',
},
{
text: '步骤二',
desc: '描述信息',
},
{
text: '步骤三',
desc: '描述信息',
},
{
text: '步骤四',
desc: '描述信息',
},
],
},
});
```
### 自定义样式
可以通过 `active-icon` 和 `active-color` 属性设置激活状态下的图标和颜色。
```html
```
### 自定义图标
可以通过 `inactiveIcon` 和 `activeIcon` 属性分别设置每一项的图标。
```html
```
```javascript
Page({
data: {
steps: [
{
text: '步骤一',
desc: '描述信息',
inactiveIcon: 'location-o',
activeIcon: 'success',
},
{
text: '步骤二',
desc: '描述信息',
inactiveIcon: 'like-o',
activeIcon: 'plus',
},
{
text: '步骤三',
desc: '描述信息',
inactiveIcon: 'star-o',
activeIcon: 'cross',
},
{
text: '步骤四',
desc: '描述信息',
inactiveIcon: 'phone-o',
activeIcon: 'fail',
},
],
},
});
```
### 竖向步骤条
可以通过设置`direction`属性来改变步骤条的显示方式。
```html
```
## API
### Steps Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| active | 当前步骤 | _number_ | 0 |
| steps | 步骤配置集合,见下面配置项 | _Step 配置项数组_ | `[]` |
| direction | 显示方向,可选值为 `horizontal` `vertical` | _string_ | `horizontal` |
| active-color | 激活状态颜色 | _string_ | `#07c160` |
| inactive-color | 未激活状态颜色 | _string_ | `#969799` |
| active-icon | 激活状态底部图标,可选值见 [Icon 组件](#/icon) | _string_ | `checked` |
| inactive-icon | 未激活状态底部图标,可选值见 [Icon 组件](#/icon) | _string_ | - |
### Events
| 事件名称 | 说明 | 回调参数 |
| --------------- | -------------------- | --------------------------- |
| bind:click-step | 点击步骤时触发的事件 | event.detail:当前步骤的索引 |
### 外部样式类
| 类名 | 说明 |
| ------------ | -------------- |
| custom-class | 根节点样式类 |
| desc-class | 描述信息样式类 |
### Step 配置项
| 键名 | 说明 | 类型 |
| ------------ | -------------------------------------------------------- | -------- |
| text | 当前步骤名称 | _string_ |
| desc | 当前步骤描述信息 | _string_ |
| activeIcon | 当前步骤激活状态底部图标 | _string_ |
| inactiveIcon | 当前步骤未激活状态底部图标,可选值见 [Icon 组件](#/icon) | _string_ |
================================================
FILE: packages/steps/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-steps": "../../steps/index",
"van-toast": "../../toast/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/steps/demo/index.less
================================================
.demo-margin-left {
margin-left: 10px;
}
.demo-margin-bottom {
display: block;
margin-bottom: 15px;
}
================================================
FILE: packages/steps/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
import icons from '@vant/icons/src/config';
const steps = [
{
text: '步骤一',
desc: '描述信息',
},
{
text: '步骤二',
desc: '描述信息',
},
{
text: '步骤三',
desc: '描述信息',
},
{
text: '步骤四',
desc: '描述信息',
},
];
VantComponent({
data: {
active: 1,
steps,
customIconSteps: steps.map((item, index) => ({
...item,
inactiveIcon: icons.outline[index],
activeIcon: icons.basic[index],
})),
},
methods: {
nextStep() {
this.setData({
active: ++this.data.active % 4,
});
},
onClick(event) {
Toast({
context: this,
message: `Index: ${event.detail}`,
});
},
},
});
================================================
FILE: packages/steps/demo/index.wxml
================================================
下一步
================================================
FILE: packages/steps/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/steps/index.less
================================================
@import '../common/style/var.less';
.van-steps {
overflow: hidden;
background-color: var(--steps-background-color, @steps-background-color);
&--horizontal {
padding: 10px;
.van-step__wrapper {
position: relative;
display: flex;
overflow: hidden;
}
}
&--vertical {
padding-left: 10px;
.van-step__wrapper {
padding: 0 0 0 20px;
}
}
}
.van-step {
position: relative;
flex: 1;
font-size: var(--step-font-size, @step-font-size);
color: var(--step-text-color, @step-text-color);
&--finish {
color: var(--step-finish-text-color, @step-finish-text-color);
}
&__circle {
border-radius: 50%;
width: var(--step-circle-size, @step-circle-size);
height: var(--step-circle-size, @step-circle-size);
background-color: var(--step-circle-color, @step-circle-color);
}
&--horizontal {
padding-bottom: 14px;
&:first-child {
.van-step__title {
transform: none;
}
.van-step__circle-container {
padding: 0 8px 0 0;
transform: translate3d(0, 50%, 0);
}
}
&:last-child {
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: auto;
.van-step__title {
text-align: right;
transform: none;
}
.van-step__circle-container {
right: 0;
padding: 0 0 0 8px;
transform: translate3d(0, 50%, 0);
}
}
.van-step__circle-container {
position: absolute;
bottom: 6px;
z-index: 1;
transform: translate3d(-50%, 50%, 0);
background-color: @white;
padding: 0 var(--padding-xs, @padding-xs);
}
.van-step__title {
display: inline-block;
transform: translate3d(-50%, 0, 0);
font-size: var(
--step-horizontal-title-font-size,
@step-horizontal-title-font-size
);
}
.van-step__line {
position: absolute;
right: 0;
bottom: 6px;
left: 0;
height: 1px;
transform: translate3d(0, 50%, 0);
background-color: var(--step-line-color, @step-line-color);
}
&.van-step--process {
color: var(--step-process-text-color, @step-process-text-color);
.van-step__icon {
display: block;
line-height: 1;
font-size: var(--step-icon-size, @step-icon-size);
}
}
}
&--vertical {
padding: 10px 10px 10px 0;
line-height: 18px;
&::after {
border-bottom-width: 1px;
}
&:last-child::after {
border-bottom-width: none;
}
&:first-child {
&::before {
position: absolute;
top: 0;
left: -15px;
z-index: 1;
width: 1px;
height: 20px;
content: '';
background-color: @white;
}
}
.van-step__icon,
.van-step__circle,
.van-step__line {
position: absolute;
top: 19px;
left: -14px;
z-index: 2;
transform: translate3d(-50%, -50%, 0);
}
.van-step__icon {
line-height: 1;
font-size: var(--step-icon-size, @step-icon-size);
background-color: var(--steps-background-color, @steps-background-color);
}
.van-step__line {
z-index: 1;
width: 1px;
height: 100%;
transform: translate3d(-50%, 0, 0);
background-color: var(--step-line-color, @step-line-color);
}
}
}
================================================
FILE: packages/steps/index.ts
================================================
import { VantComponent } from '../common/component';
import { GREEN, GRAY_DARK } from '../common/color';
VantComponent({
classes: ['desc-class'],
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal',
},
activeColor: {
type: String,
value: GREEN,
},
inactiveColor: {
type: String,
value: GRAY_DARK,
},
activeIcon: {
type: String,
value: 'checked',
},
inactiveIcon: String,
},
methods: {
onClick(event: WechatMiniprogram.TouchEvent) {
const { index } = event.currentTarget.dataset;
this.$emit('click-step', index);
},
},
});
================================================
FILE: packages/steps/index.wxml
================================================
{{ item.text }}
{{ item.desc }}
function get(index, active) {
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return 'inactive';
}
module.exports = get;
================================================
FILE: packages/steps/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
步骤一
描述信息
步骤二
描述信息
步骤三
描述信息
步骤四
描述信息
下一步
自定义样式
步骤一
描述信息
步骤二
描述信息
步骤三
描述信息
步骤四
描述信息
自定义图标
步骤一
描述信息
步骤二
描述信息
步骤三
描述信息
步骤四
描述信息
竖向步骤条
步骤一
描述信息
步骤二
描述信息
步骤三
描述信息
步骤四
描述信息
`;
================================================
FILE: packages/steps/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/sticky/README.md
================================================
# Sticky 粘性布局
### 介绍
Sticky 组件与 CSS 中`position: sticky`属性实现的效果一致,当组件在屏幕范围内时,会按照正常的布局排列,当组件滚出屏幕范围时,始终会固定在屏幕顶部。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-sticky": "@vant/weapp/sticky/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基础用法
将内容包裹在`Sticky`组件内即可。
```html
基础用法
```
### 吸顶距离
通过`offset-top`属性可以设置组件在吸顶时与顶部的距离。
```html
吸顶距离
```
### 指定容器
通过`container`属性可以指定组件的容器,页面滚动时,组件会始终保持在容器范围内,当组件即将超出容器底部时,会返回原位置。
```html
指定容器
```
```js
Page({
data: {
container: null,
},
onReady() {
this.setData({
container: () => wx.createSelectorQuery().select('#container'),
});
},
});
```
### 嵌套在 scroll-view 内使用
通过 `scroll-top` 与 `offset-top` 属性可以实现在 scroll-view 内嵌套使用。
```html
嵌套在 scroll-view 内
```
```js
Page({
data: {
scrollTop: 0,
offsetTop: 0,
},
onScroll(event) {
wx.createSelectorQuery()
.select('#scroller')
.boundingClientRect((res) => {
this.setData({
scrollTop: event.detail.scrollTop,
offsetTop: res.top,
});
})
.exec();
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| offset-top | 吸顶时与顶部的距离,单位`px` | _number_ | `0` |
| z-index | 吸顶时的 z-index | _number_ | `99` |
| container | 一个函数,返回容器对应的 NodesRef 节点 | _function_ | - |
| scroll-top | 当前滚动区域的滚动位置,非 `null` 时会禁用页面滚动事件的监听 | _number_ | - |
### Events
| 事件名 | 说明 | 回调参数 |
| ------ | ---------- | ---------------------------------------------- |
| bind:scroll | 滚动时触发 | { scrollTop: 距离顶部位置, isFixed: 是否吸顶 } |
================================================
FILE: packages/sticky/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-sticky": "../../sticky/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/sticky/demo/index.less
================================================
.van-button {
margin-left: 16px;
}
.sticky-container {
position: relative;
z-index: -1;
height: 150px;
background-color: #fff;
}
================================================
FILE: packages/sticky/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
container: () => {},
scrollTop: 0,
offsetTop: 0,
},
mounted() {
this.setData({
container: () => this.createSelectorQuery().select('#container'),
});
},
methods: {
onScroll(event) {
this.createSelectorQuery()
.select('#scroller')
.boundingClientRect((res) => {
this.setData({
scrollTop: event.detail.scrollTop,
offsetTop: res.top,
});
})
.exec();
},
},
});
================================================
FILE: packages/sticky/demo/index.wxml
================================================
基础用法
吸顶距离
指定容器
嵌套在 scroll-view 内
================================================
FILE: packages/sticky/index.json
================================================
{
"component": true
}
================================================
FILE: packages/sticky/index.less
================================================
.van-sticky {
position: relative;
&-wrap {
&--fixed {
position: fixed;
right: 0;
left: 0;
}
}
}
================================================
FILE: packages/sticky/index.ts
================================================
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pageScrollMixin } from '../mixins/page-scroll';
const ROOT_ELEMENT = '.van-sticky';
VantComponent({
props: {
zIndex: {
type: Number,
value: 99,
},
offsetTop: {
type: Number,
value: 0,
observer: 'onScroll',
},
disabled: {
type: Boolean,
observer: 'onScroll',
},
container: {
type: null,
observer: 'onScroll',
},
scrollTop: {
type: null,
observer(val) {
this.onScroll({ scrollTop: val });
},
},
},
mixins: [
pageScrollMixin(function (event) {
if (this.data.scrollTop != null) {
return;
}
this.onScroll(event);
}),
],
data: {
height: 0,
fixed: false,
transform: 0,
},
mounted() {
this.onScroll();
},
methods: {
onScroll({ scrollTop }: { scrollTop?: number } = {}) {
const { container, offsetTop, disabled } = this.data;
if (disabled) {
this.setDataAfterDiff({
fixed: false,
transform: 0,
});
return;
}
this.scrollTop = scrollTop || this.scrollTop;
if (typeof container === 'function') {
Promise.all([getRect(this, ROOT_ELEMENT), this.getContainerRect()])
.then(([root, container]) => {
if (offsetTop + root.height > container.height + container.top) {
this.setDataAfterDiff({
fixed: false,
transform: container.height - root.height,
});
} else if (offsetTop >= root.top) {
this.setDataAfterDiff({
fixed: true,
height: root.height,
transform: 0,
});
} else {
this.setDataAfterDiff({ fixed: false, transform: 0 });
}
})
.catch(() => {});
return;
}
getRect(this, ROOT_ELEMENT).then((root) => {
if (!isDef(root) || (!root.width && !root.height)) {
return;
}
if (offsetTop >= root.top) {
this.setDataAfterDiff({ fixed: true, height: root.height });
this.transform = 0;
} else {
this.setDataAfterDiff({ fixed: false });
}
});
},
setDataAfterDiff(data) {
wx.nextTick(() => {
const diff = Object.keys(data).reduce((prev, key) => {
if (data[key] !== this.data[key]) {
prev[key] = data[key];
}
return prev;
}, {});
if (Object.keys(diff).length > 0) {
this.setData(diff);
}
this.$emit('scroll', {
scrollTop: this.scrollTop,
isFixed: data.fixed || this.data.fixed,
});
});
},
getContainerRect() {
const nodesRef: WechatMiniprogram.NodesRef = this.data.container();
if (!nodesRef) {
return Promise.reject(new Error('not found container'));
}
return new Promise(
(resolve) => nodesRef.boundingClientRect(resolve).exec()
);
},
},
});
================================================
FILE: packages/sticky/index.wxml
================================================
================================================
FILE: packages/sticky/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapStyle(data) {
return style({
transform: data.transform
? 'translate3d(0, ' + data.transform + 'px, 0)'
: '',
top: data.fixed ? addUnit(data.offsetTop) : '',
'z-index': data.zIndex,
});
}
function containerStyle(data) {
return style({
height: data.fixed ? addUnit(data.height) : '',
'z-index': data.zIndex,
});
}
module.exports = {
wrapStyle: wrapStyle,
containerStyle: containerStyle,
};
================================================
FILE: packages/sticky/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
基础用法
吸顶距离
吸顶距离
指定容器
指定容器
嵌套在 scroll-view 内使用
嵌套在 scroll-view 内
`;
================================================
FILE: packages/sticky/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/submit-bar/README.md
================================================
# SubmitBar 提交订单栏
### 介绍
用于展示订单金额与提交订单。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-submit-bar": "@vant/weapp/submit-bar/index"
}
```
## 代码演示
### 基础用法
```html
```
### 禁用状态
禁用状态下不会触发`submit`事件。
```html
```
### 加载状态
加载状态下不会触发`submit`事件。
```html
```
### 高级用法
通过插槽插入自定义内容。
```html
标签
您的收货地址不支持同城送, 修改地址
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| price | 价格(单位分) | _number_ | - |
| label | 价格文案 | _string_ | `合计:` |
| suffix-label | 价格右侧文案 | _string_ | - |
| button-text | 按钮文字 | _string_ | - |
| button-type | 按钮类型 | _string_ | `danger` |
| tip | 提示文案 | _string \| boolean_ | - |
| tip-icon | 图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| disabled | 是否禁用按钮 | _boolean_ | `false` |
| loading | 是否显示加载中的按钮 | _boolean_ | `false` |
| currency | 货币符号 | _string_ | `¥` |
| safe-area-inset-bottom | 是否为 iPhoneX 留出底部安全距离 | _boolean_ | `true` |
| decimal-length | 价格小数点后位数 | _number_ | `2` |
### Events
| 事件名 | 说明 | 参数 |
| ------ | ---------------- | ---- |
| bind:submit | 按钮点击事件回调 | - |
### Slot
| 名称 | 说明 |
| ---- | -------------------------- |
| - | 自定义订单栏左侧内容 |
| top | 自定义订单栏上方内容 |
| tip | 提示文案中的额外操作和说明 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| price-class | 价格样式类 |
| button-class | 按钮样式类 |
| bar-class | 订单栏样式类 |
================================================
FILE: packages/submit-bar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tag": "../../tag/index",
"van-toast": "../../toast/index",
"van-submit-bar": "../../submit-bar/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/submit-bar/demo/index.less
================================================
.van-submit-bar {
position: relative !important;
}
.edit-address {
color: #1989fa;
}
.submit-tag {
margin-left: 15px;
}
================================================
FILE: packages/submit-bar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
methods: {
onClickButton() {
Toast({
context: this,
message: '点击按钮',
});
},
onClickLink() {
Toast({
context: this,
message: '修改地址',
});
},
},
});
================================================
FILE: packages/submit-bar/demo/index.wxml
================================================
标签
您的收货地址不支持同城送
修改地址
================================================
FILE: packages/submit-bar/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../button/index",
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/submit-bar/index.less
================================================
@import '../common/style/var.less';
.van-submit-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
user-select: none;
z-index: var(--submit-bar-z-index, @submit-bar-z-index);
background-color: var(
--submit-bar-background-color,
@submit-bar-background-color
);
&__tip {
padding: var(--submit-bar-tip-padding, @submit-bar-tip-padding);
color: var(--submit-bar-tip-color, @submit-bar-tip-color);
font-size: var(--submit-bar-tip-font-size, @submit-bar-tip-font-size);
line-height: var(--submit-bar-tip-line-height, @submit-bar-tip-line-height);
background-color: var(
--submit-bar-tip-background-color,
@submit-bar-tip-background-color
);
&:empty {
display: none;
}
}
&__tip-icon {
margin-right: 4px;
vertical-align: middle;
}
&__tip-text {
display: inline;
vertical-align: middle;
}
&__bar {
display: flex;
align-items: center;
justify-content: flex-end;
padding: var(--submit-bar-padding, @submit-bar-padding);
height: var(--submit-bar-height, @submit-bar-height);
font-size: var(--submit-bar-text-font-size, @submit-bar-text-font-size);
background-color: var(
--submit-bar-background-color,
@submit-bar-background-color
);
}
&__safe {
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
&__text {
flex: 1;
text-align: right;
color: var(--submit-bar-text-color, @submit-bar-text-color);
padding-right: var(--padding-sm, @padding-sm);
font-weight: var(--font-weight-bold, @font-weight-bold);
}
&__price {
color: var(--submit-bar-price-color, @submit-bar-price-color);
font-weight: var(--font-weight-bold, @font-weight-bold);
font-size: var(--submit-bar-price-font-size, @submit-bar-price-font-size);
&-integer {
font-size: @submit-bar-price-integer-font-size;
font-family: @submit-bar-price-font-family;
}
}
&__currency {
font-size: var(
--submit-bar-currency-font-size,
@submit-bar-currency-font-size
);
}
&__suffix-label {
margin-left: 5px;
}
&__button {
width: var(--submit-bar-button-width, @submit-bar-button-width);
font-weight: var(--font-weight-bold, @font-weight-bold);
--button-default-height: var(
--submit-bar-button-height,
@submit-bar-button-height
) !important;
--button-line-height: var(
--submit-bar-button-height,
@submit-bar-button-height
) !important;
}
}
================================================
FILE: packages/submit-bar/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: ['bar-class', 'price-class', 'button-class'],
props: {
tip: {
type: null,
observer: 'updateTip',
},
tipIcon: String,
type: Number,
price: {
type: null,
observer: 'updatePrice',
},
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥',
},
buttonType: {
type: String,
value: 'danger',
},
decimalLength: {
type: Number,
value: 2,
observer: 'updatePrice',
},
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
updatePrice() {
const { price, decimalLength } = this.data;
const priceStrArr =
typeof price === 'number' &&
(price / 100).toFixed(decimalLength).split('.');
this.setData({
hasPrice: typeof price === 'number',
integerStr: priceStrArr && priceStrArr[0],
decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
});
},
updateTip() {
this.setData({ hasTip: typeof this.data.tip === 'string' });
},
onSubmit(event: WechatMiniprogram.CustomEvent) {
this.$emit('submit', event.detail);
},
},
});
================================================
FILE: packages/submit-bar/index.wxml
================================================
{{ tip }}
{{ label || '合计:' }}
{{ currency }}
{{ integerStr }}{{decimalStr}}
{{ suffixLabel }}
{{ loading ? '' : buttonText }}
================================================
FILE: packages/submit-bar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
合计:
¥
30
.50
提交订单
禁用状态
您的收货地址不支持同城送, 我们已为您推荐快递
合计:
¥
30
.50
提交订单
加载状态
合计:
¥
30
.50
高级用法
您的收货地址不支持同城送
修改地址
标签
合计:
¥
30
.50
提交订单
`;
================================================
FILE: packages/submit-bar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/swipe-cell/README.md
================================================
# SwipeCell 滑动单元格
### 介绍
可以左右滑动来展示操作按钮的单元格组件。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-swipe-cell": "@vant/weapp/swipe-cell/index"
}
```
## 代码演示
### 基础用法
```html
选择
删除
```
### 异步关闭
当开启`async-close`时, 通过绑定`close`事件,可以自定义两侧滑动内容点击时的关闭行为。
```html
选择
删除
```
```js
Page({
onClose(event) {
const { position, instance } = event.detail;
switch (position) {
case 'left':
case 'cell':
instance.close();
break;
case 'right':
Dialog.confirm({
message: '确定删除吗?',
}).then(() => {
instance.close();
});
break;
}
},
});
```
### 主动打开
```html
选择
删除
```
```js
Page({
onOpen(event) {
const { position, name } = event.detail;
switch (position) {
case 'left':
Notify({
type: 'primary',
message: `${name}${position}部分展示open事件被触发`,
});
break;
case 'right':
Notify({
type: 'primary',
message: `${name}${position}部分展示open事件被触发`,
});
break;
}
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 标识符,可以在 close 事件的参数中获取到 | _string \| number_ | - |
| left-width | 左侧滑动区域宽度 | _number_ | `0` |
| right-width | 右侧滑动区域宽度 | _number_ | `0` |
| async-close | 是否异步关闭 | _boolean_ | `false` |
| disabled `v1.3.4` | 是否禁用滑动 | _boolean_ | `false` |
### Slot
| 名称 | 说明 |
| ----- | -------------- |
| - | 自定义显示内容 |
| left | 左侧滑动内容 |
| right | 右侧滑动内容 |
### Events
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| bind:click | 点击时触发 | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| bind:close | 关闭时触发 | { position: 'left' \| 'right' , instance , name: string } |
| bind:open | 打开时触发 | { position: 'left' \| 'right' , name: string } |
### close 参数
| 参数 | 类型 | 说明 |
| -------- | -------- | -------------------------------------------------- |
| position | _string_ | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| instance | _object_ | SwipeCell 实例 |
| name | 标识符 | _string_ |
### 方法
通过 selectComponent 可以获取到 SwipeCell 实例并调用实例方法
| 方法名 | 参数 | 返回值 | 介绍 |
| ------ | ------------------------- | ------ | ---------------- |
| open | position: `left \| right` | - | 打开单元格侧边栏 |
| close | - | - | 收起单元格侧边栏 |
================================================
FILE: packages/swipe-cell/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-dialog": "../../dialog/index",
"van-notify": "../../notify/index",
"van-swipe-cell": "../../swipe-cell/index",
"van-cell-group": "../../cell-group/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/swipe-cell/demo/index.less
================================================
.demo-swipe-cell {
user-select: none;
}
.van-swipe-cell__left,
.van-swipe-cell__right {
display: inline-block;
width: 65px;
height: 44px;
font-size: 15px;
line-height: 44px;
color: #fff;
text-align: center;
background-color: #ee0a24;
}
================================================
FILE: packages/swipe-cell/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Dialog from '../../dialog/dialog';
import Notify from '../../notify/notify';
VantComponent({
methods: {
onClose(event) {
const { position, instance } = event.detail;
switch (position) {
case 'left':
case 'cell':
instance.close();
break;
case 'right':
Dialog.confirm({
context: this,
message: '确定删除吗?',
}).then(() => {
instance.close();
});
break;
}
},
onOpen(event) {
const { position, name } = event.detail;
switch (position) {
case 'left':
Notify({
context: this,
type: 'primary',
message: `${name}${position}部分展示open事件被触发`,
});
break;
case 'right':
Notify({
context: this,
type: 'primary',
message: `${name}${position}部分展示open事件被触发`,
});
break;
}
},
},
});
================================================
FILE: packages/swipe-cell/demo/index.wxml
================================================
选择
删除
选择
删除
选择
删除
================================================
FILE: packages/swipe-cell/index.json
================================================
{
"component": true
}
================================================
FILE: packages/swipe-cell/index.less
================================================
@import '../common/style/var.less';
.van-swipe-cell {
position: relative;
overflow: hidden;
&__left,
&__right {
position: absolute;
top: 0;
height: 100%;
}
&__left {
left: 0;
transform: translate3d(-100%, 0, 0);
}
&__right {
right: 0;
transform: translate3d(100%, 0, 0);
}
}
================================================
FILE: packages/swipe-cell/index.ts
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { range } from '../common/utils';
const THRESHOLD = 0.3;
let ARRAY: WechatMiniprogram.Component.TrivialInstance[] = [];
VantComponent({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0,
observer(leftWidth = 0) {
if (this.offset > 0) {
this.swipeMove(leftWidth);
}
},
},
rightWidth: {
type: Number,
value: 0,
observer(rightWidth = 0) {
if (this.offset < 0) {
this.swipeMove(-rightWidth);
}
},
},
asyncClose: Boolean,
name: {
type: null,
value: '',
},
},
mixins: [touch],
data: {
catchMove: false,
wrapperStyle: '',
},
created() {
this.offset = 0;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
open(position: 'left' | 'right') {
const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
this.$emit('open', {
position,
name: this.data.name,
});
},
close() {
this.swipeMove(0);
},
swipeMove(offset = 0) {
this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
const transform = `translate3d(${this.offset}px, 0, 0)`;
const transition = this.dragging
? 'none'
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.setData({
wrapperStyle: `
-webkit-transform: ${transform};
-webkit-transition: ${transition};
transform: ${transform};
transition: ${transition};
`,
});
},
swipeLeaveTransition() {
const { leftWidth, rightWidth } = this.data;
const { offset } = this;
if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
this.open('right');
} else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
this.open('left');
} else {
this.swipeMove(0);
}
this.setData({ catchMove: false });
},
startDrag(event: WechatMiniprogram.TouchEvent) {
if (this.data.disabled) {
return;
}
this.startOffset = this.offset;
this.touchStart(event);
},
noop() {},
onDrag(event: WechatMiniprogram.TouchEvent) {
if (this.data.disabled) {
return;
}
this.touchMove(event);
if (this.direction !== 'horizontal') {
return;
}
this.dragging = true;
ARRAY.filter(
(item) => item !== this && item.offset !== 0
).forEach((item) => item.close());
this.setData({ catchMove: true });
this.swipeMove(this.startOffset + this.deltaX);
},
endDrag() {
if (this.data.disabled) {
return;
}
this.dragging = false;
this.swipeLeaveTransition();
},
onClick(event: WechatMiniprogram.TouchEvent) {
const { key: position = 'outside' } = event.currentTarget.dataset;
this.$emit('click', position);
if (!this.offset) {
return;
}
if (this.data.asyncClose) {
this.$emit('close', {
position,
instance: this,
name: this.data.name,
});
} else {
this.swipeMove(0);
}
},
},
});
================================================
FILE: packages/swipe-cell/index.wxml
================================================
================================================
FILE: packages/swipe-cell/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
选择
单元格
内容
删除
异步关闭
选择
单元格
内容
删除
主动打开
选择
单元格
内容
删除
`;
================================================
FILE: packages/swipe-cell/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/switch/README.md
================================================
# Switch 开关
### 介绍
用于在打开和关闭状态之间进行切换。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-switch": "@vant/weapp/switch/index"
}
```
## 代码演示
### 基础用法
```html
```
```javascript
Page({
data: {
checked: true,
},
onChange({ detail }) {
// 需要手动对 checked 状态进行更新
this.setData({ checked: detail });
},
});
```
### 禁用状态
```html
```
### 加载状态
```html
```
### 自定义大小
```html
```
### 自定义颜色
```html
```
### 异步控制
```html
```
```js
Page({
data: {
checked: true,
},
onChange({ detail }) {
wx.showModal({
title: '提示',
content: '是否切换开关?',
success: (res) => {
if (res.confirm) {
this.setData({ checked2: detail });
}
},
});
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| -------------- | ---------------------- | --------- | --------- |
| name | 在表单内提交时的标识符 | _string_ | - |
| checked | 开关选中状态 | _any_ | `false` |
| loading | 是否为加载状态 | _boolean_ | `false` |
| disabled | 是否为禁用状态 | _boolean_ | `false` |
| size | 开关尺寸 | _string_ | `30px` |
| active-color | 打开时的背景色 | _string_ | `#1989fa` |
| inactive-color | 关闭时的背景色 | _string_ | `#fff` |
| active-value | 打开时的值 | _any_ | `true` |
| inactive-value | 关闭时的值 | _any_ | `false` |
### Events
| 事件名 | 说明 | 参数 |
| ----------- | ---------------- | -------------------------- |
| bind:change | 开关状态切换回调 | event.detail: 是否选中开关 |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
| node-class | 圆点样式类 |
================================================
FILE: packages/switch/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-switch": "../../switch/index",
"van-dialog": "../../dialog/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/switch/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Dialog from '../../dialog/dialog';
VantComponent({
data: {
checked: true,
checked2: true,
},
methods: {
onChange({ detail }) {
this.setData({ checked: detail });
},
onChange2({ detail }) {
Dialog.confirm({
context: this,
title: '提示',
message: '是否切换开关?',
}).then(() => {
this.setData({ checked2: detail });
});
},
},
});
================================================
FILE: packages/switch/demo/index.wxml
================================================
================================================
FILE: packages/switch/index.json
================================================
{
"component": true,
"usingComponents": {
"van-loading": "../loading/index"
}
}
================================================
FILE: packages/switch/index.less
================================================
@import '../common/style/var.less';
.van-switch {
position: relative;
display: inline-block;
box-sizing: content-box;
width: var(--switch-width, @switch-width);
height: var(--switch-height, @switch-height);
background-color: var(--switch-background-color, @switch-background-color);
border: var(--switch-border, @switch-border);
border-radius: var(--switch-node-size, @switch-node-size);
transition: background-color
var(--switch-transition-duration, @switch-transition-duration);
&__node {
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
z-index: var(--switch-node-z-index, @switch-node-z-index);
width: var(--switch-node-size, @switch-node-size);
height: var(--switch-node-size, @switch-node-size);
background-color: var(
--switch-node-background-color,
@switch-node-background-color
);
box-shadow: var(--switch-node-box-shadow, @switch-node-box-shadow);
transition: var(--switch-transition-duration, @switch-transition-duration)
cubic-bezier(0.3, 1.05, 0.4, 1.05);
}
&__loading {
position: absolute !important;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
}
&--on {
background-color: var(
--switch-on-background-color,
@switch-on-background-color
);
.van-switch__node {
transform: translateX(
calc(
var(--switch-width, @switch-width) -
var(--switch-node-size, @switch-node-size)
)
);
}
}
&--disabled {
opacity: var(--switch-disabled-opacity, @switch-disabled-opacity);
}
}
================================================
FILE: packages/switch/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['node-class'],
props: {
checked: null,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '30',
},
activeValue: {
type: null,
value: true,
},
inactiveValue: {
type: null,
value: false,
},
},
methods: {
onClick() {
const { activeValue, inactiveValue, disabled, loading } = this.data;
if (disabled || loading) {
return;
}
const checked = this.data.checked === activeValue;
const value = checked ? inactiveValue : activeValue;
this.$emit('input', value);
this.$emit('change', value);
},
},
});
================================================
FILE: packages/switch/index.wxml
================================================
================================================
FILE: packages/switch/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
var currentColor = data.checked === data.activeValue ? data.activeColor : data.inactiveColor;
return style({
'font-size': addUnit(data.size),
'background-color': currentColor,
});
}
var BLUE = '#1989fa';
var GRAY_DARK = '#969799';
function loadingColor(data) {
return data.checked === data.activeValue
? data.activeColor || BLUE
: data.inactiveColor || GRAY_DARK;
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
================================================
FILE: packages/switch/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
禁用状态
加载状态
自定义大小
自定义颜色
异步控制
`;
================================================
FILE: packages/switch/test/__snapshots__/index.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`switch should allow to custom active-value and inactive-value 1`] = `
`;
exports[`switch should allow to custom active-value and inactive-value 2`] = `
`;
================================================
FILE: packages/switch/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/switch/test/index.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
describe('switch', () => {
const VanSwitch = simulate.load(
path.resolve(__dirname, '../../switch/index'),
'van-switch',
{
rootPath: path.resolve(__dirname, '../../'),
}
);
test('should allow to custom active-value and inactive-value', async () => {
const comp = simulate.render(
simulate.load({
usingComponents: {
'van-switch': VanSwitch,
},
template: `
`,
data: {
checked: 'on',
},
methods: {
onChange({ detail }) {
this.setData({ checked: detail });
},
},
})
);
comp.attach(document.createElement('parent-wrapper'));
const wrapper = comp.querySelector('#wrapper');
const btn = wrapper?.querySelector('.van-switch');
expect((btn as any).toJSON()).toMatchSnapshot();
btn?.dispatchEvent('tap');
await simulate.sleep(10);
expect((btn as any).toJSON()).toMatchSnapshot();
expect(comp.data.checked).toEqual('off');
});
});
================================================
FILE: packages/tab/README.md
================================================
# Tab 标签页
### 介绍
选项卡组件,用于在不同的内容区域之间进行切换。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index"
}
```
## 代码演示
### 基础用法
通过`active`设定当前激活标签对应的索引值,默认情况下启用第一个标签。
```html
内容 1
内容 2
内容 3
内容 4
```
```js
Page({
data: {
active: 1,
},
onChange(event) {
wx.showToast({
title: `切换到标签 ${event.detail.name}`,
icon: 'none',
});
},
});
```
### 通过名称匹配
在标签指定`name`属性的情况下,`active`的值为当前标签的`name`(此时无法通过索引值来匹配标签)。
```html
内容 1
内容 2
内容 3
```
### 横向滚动
多于 5 个标签时,Tab 可以横向滚动。
```html
内容 1
内容 2
内容 3
内容 4
内容 5
内容 6
```
### 禁用标签
设置`disabled`属性即可禁用标签。如果需要监听禁用标签的点击事件,可以在`van-tabs`上监听`disabled`事件。
```html
内容 1
内容 2
内容 3
```
```javascript
Page({
onClickDisabled(event) {
wx.showToast({
title: `标签 ${event.detail.name} 已被禁用`,
icon: 'none',
});
},
});
```
### 样式风格
`Tab`支持两种样式风格:`line`和`card`,默认为`line`样式,可以通过`type`属性修改样式风格。
```html
内容 1
内容 2
内容 3
```
### 点击事件
可以在`van-tabs`上绑定`click`事件,在回调参数的`event.detail`中可以取得被点击标签的标题和标识符。
```html
内容 1
内容 2
```
```javascript
Page({
onClick(event) {
wx.showToast({
title: `点击标签 ${event.detail.name}`,
icon: 'none',
});
},
});
```
### 粘性布局
通过`sticky`属性可以开启粘性布局,粘性布局下,当 Tab 滚动到顶部时会自动吸顶。
```html
内容 1
内容 2
内容 3
内容 4
```
### 切换动画
可以通过`animated`来设置是否启用切换 tab 时的动画。
```html
内容 1
内容 2
内容 3
内容 4
```
### 滑动切换
通过`swipeable`属性可以开启滑动切换标签页。
```html
内容 1
内容 2
内容 3
内容 4
```
### 嵌套 popup
如果将 van-tabs 嵌套在 van-popup 等会隐藏内容的组件或节点内,当 van-tabs 显示时下划线将不会正常显示。
此时可以通过使用 `wx:if` 手动控制 van-tabs 的渲染来规避这种场景。
```html
内容 1
内容 2
内容 3
内容 4
```
### 异步切换
通过 `before-change` 事件可以在切换标签前执行特定的逻辑,实现切换前校验、异步切换的目的
```html
内容 1
内容 2
内容 3
内容 4
```
```js
Page({
data: {
active: 1,
},
onChange(event) {
wx.showToast({
title: `切换到标签 ${event.detail.name}`,
icon: 'none',
});
},
onBeforeChange(event) {
const { callback, title } = event.detail;
wx.showModal({
title: '异步切换',
content: `确定要切换至 ${title} tab吗?`,
success: (res) => {
if (res.confirm) {
callback(true)
} else if (res.cancel) {
callback(false)
}
},
})
}
});
```
## API
### Tabs Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 样式风格,可选值为`card` | _string_ | `line` |
| color | 标签主题色 | _string_ | `#ee0a24` |
| active | 当前选中标签的标识符 | _string \| number_ | `0` |
| duration | 动画时间,单位秒 | _number_ | `0.3` |
| line-width | 底部条宽度,默认单位`px` | _string \| number_ | `40px` |
| line-height | 底部条高度,默认单位`px` | _string \| number_ | `3px` |
| animated | 是否开启切换标签内容时的转场动画 | _boolean_ | `false` |
| border | 是否展示外边框,仅在 `line` 风格下生效 | _boolean_ | `false` |
| ellipsis | 是否省略过长的标题文字 | _boolean_ | `true` |
| sticky | 是否使用粘性定位布局 | _boolean_ | `false` |
| swipeable | 是否开启手势滑动切换 | _boolean_ | `false` |
| lazy-render | 是否开启标签页内容延迟渲染 | _boolean_ | `true` |
| offset-top | 粘性定位布局下与顶部的最小距离,单位`px` | _number_ | - |
| swipe-threshold | 滚动阈值,标签数量超过阈值且总宽度超过标签栏宽度时开始横向滚动 | _number_ | `5` |
| title-active-color | 标题选中态颜色 | _string_ | - |
| title-inactive-color | 标题默认态颜色 | _string_ | - |
| z-index | z-index 层级 | _number_ | `1` |
| use-before-change `v1.10.10` | 是否开启切换前校验 | _boolean_ | `false` |
### Tab Props
| 参数 | 说明 | 类型 | 默认值 |
| ----------- | -------------------------- | ------------------ | ------------ |
| name | 标签名称,作为匹配的标识符 | _string \| number_ | 标签的索引值 |
| title | 标题 | _string_ | - |
| disabled | 是否禁用标签 | _boolean_ | `false` |
| dot | 是否显示小红点 | _boolean_ | - |
| info | 图标右上角提示信息 | _string \| number_ | - |
| title-style | 自定义标题样式 | _string_ | - |
### Tabs Slot
| 名称 | 说明 |
| --------- | ------------ |
| nav-left | 标题左侧内容 |
| nav-right | 标题右侧内容 |
### Tab Slot
| 名称 | 说明 |
| ---- | ---------- |
| - | 标签页内容 |
### Tabs Event
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| bind:click | 点击标签时触发 | name:标签标识符,title:标题 |
| bind:before-change `v1.10.10` | tab 切换前会触发,在回调函数中返回 `false` 可终止 tab 切换,绑定事件的同时需要将`use-before-change`属性设置为`true` | `event.detail.name`: 当前切换的 tab 标识符, `event.detail.title`: 当前切换的 tab 标题, `event.detail.index`: 当前切换的 tab 下标,`event.detail.callback`: 回调函数,调用`callback(false)`终止 tab 切换 |
| bind:change | 当前激活的标签改变时触发 | name:标签标识符,title:标题 |
| bind:disabled | 点击被禁用的标签时触发 | name:标签标识符,title:标题 |
| bind:scroll | 滚动时触发 | { scrollTop: 距离顶部位置, isFixed: 是否吸顶 } |
### 外部样式类
| 类名 | 说明 |
| ---------------- | ------------------ |
| custom-class | 根节点样式类 |
| nav-class | 标签栏样式类 |
| tab-class | 标签样式类 |
| tab-active-class | 标签激活态样式类 |
| wrap-class | 标签栏根节点样式类 |
### 方法
通过 selectComponent 可以获取到 Tabs 实例并调用实例方法。
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| resize | - | - | 外层元素大小或组件显示状态变化时,可以调用此方法来触发重绘 |
## 常见问题
### 组件从隐藏状态切换到显示状态时,底部条位置错误?
Tabs 组件在挂载时,会获取自身的宽度,并计算出底部条的位置。如果组件一开始处于隐藏状态,则获取到的宽度永远为 0,因此无法展示底部条位置。
#### 解决方法
方法一,使用 `wx:if` 来控制组件展示,使组件重新初始化。
```html
```
方法二,调用组件的 resize 方法来主动触发重绘。
```html
```
```js
this.selectComponent('#tabs').resize();
```
================================================
FILE: packages/tab/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tab": "../../tab/index",
"van-tabs": "../../tabs/index",
"van-icon": "../../icon/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/tab/demo/index.less
================================================
.content {
padding: 20px;
background-color: #fff;
}
.content-2 {
padding: 20px;
}
.right-nav {
padding: 0 10px;
line-height: 44px !important;
background-color: #fff;
}
.special-tab {
transition: all 0.25s ease-in-out;
}
.special-tab-active {
font-size: 1.05em !important;
}
================================================
FILE: packages/tab/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
tabs2: [1, 2],
tabs3: [1, 2, 3],
tabs4: [1, 2, 3, 4],
tabs6: [1, 2, 3, 4, 5, 6],
tabsWithName: [
{ name: 'a', index: 1 },
{ name: 'b', index: 2 },
{ name: 'c', index: 3 },
],
},
methods: {
onClickDisabled(event) {
wx.showToast({
title: `标签 ${event.detail.index + 1} 已被禁用`,
icon: 'none',
});
},
onChange(event) {
wx.showToast({
title: `切换到标签 ${event.detail.index + 1}`,
icon: 'none',
});
},
onClickNavRight() {
wx.showToast({
title: '点击 right nav',
icon: 'none',
});
},
onClick(event) {
wx.showToast({
title: `点击标签 ${event.detail.index + 1}`,
icon: 'none',
});
},
onBeforeChange(event) {
const { callback, title } = event.detail;
wx.showModal({
title: '异步切换',
content: `确定要切换至 ${title} tab吗?`,
success: (res) => {
if (res.confirm) {
callback(true);
} else if (res.cancel) {
callback(false);
}
},
});
},
},
});
================================================
FILE: packages/tab/demo/index.wxml
================================================
{{ '内容' + item }}
{{ '内容' + item.index}}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
{{ '内容' + item }}
================================================
FILE: packages/tab/index.json
================================================
{
"component": true
}
================================================
FILE: packages/tab/index.less
================================================
:host {
flex-shrink: 0;
box-sizing: border-box;
width: 100%;
}
.van-tab__pane {
box-sizing: border-box;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
&--active {
height: auto;
}
&--inactive {
height: 0;
overflow: visible;
}
}
================================================
FILE: packages/tab/index.ts
================================================
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('tabs'),
props: {
dot: {
type: Boolean,
observer: 'update',
},
info: {
type: null,
observer: 'update',
},
title: {
type: String,
observer: 'update',
},
disabled: {
type: Boolean,
observer: 'update',
},
titleStyle: {
type: String,
observer: 'update',
},
name: {
type: null,
value: '',
},
},
data: {
active: false,
},
methods: {
getComputedName() {
if (this.data.name !== '') {
return this.data.name;
}
return this.index;
},
updateRender(active, parent) {
const { data: parentData } = parent;
this.inited = this.inited || active;
this.setData({
active,
shouldRender: this.inited || !parentData.lazyRender,
shouldShow: active || parentData.animated,
});
},
update() {
if (this.parent) {
this.parent.updateTabs();
}
},
},
});
================================================
FILE: packages/tab/index.wxml
================================================
================================================
FILE: packages/tab/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标签 1
标签 2
标签 3
标签 4
内容2
通过名称匹配
标签 1
标签 2
标签 3
内容2
横向滚动
标签 1
标签 2
标签 3
标签 4
标签 5
标签 6
内容1
禁用标签
标签 1
标签 2
标签 3
内容1
样式风格
标签 1
标签 2
标签 3
内容1
点击事件
标签 1
标签 2
内容1
粘性布局
标签 1
标签 2
标签 3
标签 4
内容1
切换动画
标签 1
标签 2
标签 3
标签 4
内容1
滑动切换
标签 1
标签 2
标签 3
标签 4
内容1
自定义标题
标签 1
标签 2
标签 3
99
标签 4
内容2
异步切换
标签 1
标签 2
标签 3
标签 4
内容2
`;
================================================
FILE: packages/tab/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/tabbar/README.md
================================================
# Tabbar 标签栏
### 介绍
底部导航栏,用于在不同页面之间进行切换。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
```
## 代码演示
### 基础用法
```html
标签
标签
标签
标签
```
```javascript
Page({
data: {
active: 0,
},
onChange(event) {
// event.detail 的值为当前选中项的索引
this.setData({ active: event.detail });
},
});
```
### 通过名称匹配
在标签指定`name`属性的情况下,`v-model`的值为当前标签的`name`。
```html
标签
标签
标签
标签
```
```javascript
Page({
data: {
active: 'home',
},
onChange(event) {
this.setData({ active: event.detail });
},
});
```
### 显示徽标
```html
标签
标签
标签
标签
```
### 自定义图标
可以通过 slot 自定义图标,其中 icon slot 代表未选中状态下的图标,icon-active slot 代表选中状态下的图标。
```html
自定义
标签
标签
```
```javascript
Page({
data: {
active: 0,
icon: {
normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
active: 'https://img.yzcdn.cn/vant/user-active.png',
},
},
onChange(event) {
this.setData({ active: event.detail });
},
});
```
### 自定义颜色
```html
标签
标签
标签
标签
```
```javascript
Page({
data: {
active: 0,
},
onChange(event) {
this.setData({ active: event.detail });
},
});
```
### 切换标签事件
```html
标签1
标签2
标签3
标签4
```
```javascript
Page({
data: {
active: 0,
},
onClick(event) {
wx.showToast({
title: `点击标签 ${event.detail + 1}`,
icon: 'none',
});
},
});
```
### 结合自定义 tabBar
请参考 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html) 与 [代码片段](https://developers.weixin.qq.com/s/vaXgTsmQ7hnm)。
## API
### Tabbar Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| active | 当前选中标签的索引 | _number_ | - |
| fixed | 是否固定在底部 | _boolean_ | `true` |
| placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | _boolean_ | `false` |
| border | 是否展示外边框 | _boolean_ | `true` |
| z-index | 元素 z-index | _number_ | `1` |
| active-color | 选中标签的颜色 | _string_ | `#1989fa` |
| inactive-color | 未选中标签的颜色 | _string_ | `#7d7e80` |
| safe-area-inset-bottom | 是否为 iPhoneX 留出底部安全距离 | _boolean_ | `true` |
### Tabbar Event
| 事件名 | 说明 | 参数 |
| ----------- | -------------- | ---------------------------------------- |
| bind:change | 切换标签时触发 | event.detail: 当前选中标签的名称或索引值 |
### TabbarItem Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 标签名称,作为匹配的标识符 | _string \| number_ | 当前标签的索引值 |
| icon | 图标名称或图片链接,可选值见 [Icon 组件](#/icon) | _string_ | - |
| icon-prefix | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/icon#props) | _string_ | `van-icon` |
| dot | 是否显示小红点 | _boolean_ | - |
| info | 图标右上角提示信息 | _string \| number_ | - |
| url `v1.10.13` | 点击后跳转的链接地址, 需要以 `/` 开头 | _string_ | - |
| link-type `v1.10.13` | 链接跳转类型,可选值为 `redirectTo`、`switchTab`、`reLaunch` | _string_ | `redirectTo` |
### TabbarItem Slot
| 名称 | 说明 |
| ----------- | -------------- |
| icon | 未选中时的图标 |
| icon-active | 选中时的图标 |
================================================
FILE: packages/tabbar/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tabbar": "../../tabbar/index",
"van-tabbar-item": "../../tabbar-item/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/tabbar/demo/index.less
================================================
.tabbar-position {
position: relative !important;
}
================================================
FILE: packages/tabbar/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
active: 0,
active2: 'home',
active3: 0,
active4: 0,
active5: 0,
active6: 0,
icon: {
normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
active: 'https://img.yzcdn.cn/vant/user-active.png',
},
},
methods: {
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({ [key]: event.detail });
},
handleChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({ [key]: event.detail });
wx.showToast({ title: `点击标签 ${event.detail + 1}`, icon: 'none' });
},
},
});
================================================
FILE: packages/tabbar/demo/index.wxml
================================================
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
自定义
标签
标签
标签
标签
标签
标签
标签1
标签2
标签3
标签4
================================================
FILE: packages/tabbar/index.json
================================================
{
"component": true
}
================================================
FILE: packages/tabbar/index.less
================================================
@import '../common/style/var.less';
.van-tabbar {
display: flex;
box-sizing: content-box;
width: 100%;
height: var(--tabbar-height, @tabbar-height);
background-color: var(--tabbar-background-color, @tabbar-background-color);
&--fixed {
position: fixed;
bottom: 0;
left: 0;
}
&--safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
}
================================================
FILE: packages/tabbar/index.ts
================================================
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect } from '../common/utils';
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
VantComponent({
relation: useChildren('tabbar-item', function () {
this.updateChildren();
}),
props: {
active: {
type: null,
observer: 'updateChildren',
},
activeColor: {
type: String,
observer: 'updateChildren',
},
inactiveColor: {
type: String,
observer: 'updateChildren',
},
fixed: {
type: Boolean,
value: true,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
data: {
height: 50,
},
methods: {
updateChildren() {
const { children } = this;
if (!Array.isArray(children) || !children.length) {
return;
}
children.forEach((child: TrivialInstance) => child.updateFromParent());
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-tabbar').then((res) => {
this.setData({ height: res.height });
});
});
},
},
});
================================================
FILE: packages/tabbar/index.wxml
================================================
================================================
FILE: packages/tabbar/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标签
标签
标签
标签
通过名称匹配
标签
标签
标签
标签
显示徽标
标签
标签
5
标签
20
标签
自定义图标
3
自定义
标签
标签
自定义颜色
标签
标签
标签
标签
切换标签事件
标签1
标签2
标签3
标签4
`;
================================================
FILE: packages/tabbar/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/tabbar-item/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-info": "../info/index"
}
}
================================================
FILE: packages/tabbar-item/index.less
================================================
@import '../common/style/var.less';
:host {
flex: 1;
}
.van-tabbar-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: var(--tabbar-item-text-color, @tabbar-item-text-color);
font-size: var(--tabbar-item-font-size, @tabbar-item-font-size);
line-height: var(--tabbar-item-line-height, @tabbar-item-line-height);
&__icon {
position: relative;
margin-bottom: var(--tabbar-item-margin-bottom, @tabbar-item-margin-bottom);
font-size: var(--tabbar-item-icon-size, @tabbar-item-icon-size);
&__inner {
display: block;
min-width: 1em;
}
}
&--active {
color: var(--tabbar-item-active-color, @tabbar-item-active-color);
}
&__info {
margin-top: 2px;
}
}
================================================
FILE: packages/tabbar-item/index.ts
================================================
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
props: {
info: null,
name: null,
icon: String,
dot: Boolean,
url: {
type: String,
value: '',
},
linkType: {
type: String,
value: 'redirectTo',
},
iconPrefix: {
type: String,
value: 'van-icon',
},
},
relation: useParent('tabbar'),
data: {
active: false,
activeColor: '',
inactiveColor: '',
},
methods: {
onClick() {
const { parent } = this;
if (parent) {
const index = parent.children.indexOf(this);
const active = this.data.name || index;
if (active !== this.data.active) {
parent.$emit('change', active);
}
}
const { url, linkType } = this.data;
if (url && wx[linkType]) {
return wx[linkType]({ url });
}
this.$emit('click');
},
updateFromParent() {
const { parent } = this;
if (!parent) {
return;
}
const index = parent.children.indexOf(this);
const parentData = parent.data;
const { data } = this;
const active = (data.name || index) === parentData.active;
const patch: Record = {};
if (active !== data.active) {
patch.active = active;
}
if (parentData.activeColor !== data.activeColor) {
patch.activeColor = parentData.activeColor;
}
if (parentData.inactiveColor !== data.inactiveColor) {
patch.inactiveColor = parentData.inactiveColor;
}
if (Object.keys(patch).length > 0) {
this.setData(patch);
}
},
},
});
================================================
FILE: packages/tabbar-item/index.wxml
================================================
================================================
FILE: packages/tabs/index.json
================================================
{
"component": true,
"usingComponents": {
"van-info": "../info/index",
"van-sticky": "../sticky/index"
}
}
================================================
FILE: packages/tabs/index.less
================================================
@import '../common/style/var.less';
.van-tabs {
position: relative;
-webkit-tap-highlight-color: transparent;
&__wrap {
display: flex;
overflow: hidden;
&--scrollable {
.van-tab {
flex: 0 0 22%;
&--complete {
flex: 1 0 auto !important;
padding: 0 @padding-sm;
}
}
.van-tabs__nav {
&--complete {
padding-right: 8px;
padding-left: 8px;
}
}
}
}
&__scroll {
background-color: var(
--tabs-nav-background-color,
@tabs-nav-background-color
);
overflow: auto;
&--line {
box-sizing: content-box;
// 15px padding to hide scrollbar in mobile safari
height: calc(100% + 15px);
}
&--card {
box-sizing: border-box;
margin: 0 var(--padding-md, @padding-md);
border: @border-width-base solid
var(--tabs-default-color, @tabs-default-color);
width: calc(100% - calc(var(--padding-md, @padding-md) * 2));
border-radius: @border-radius-sm;
}
&::-webkit-scrollbar {
display: none;
}
}
&__nav {
position: relative;
display: flex;
user-select: none;
&--card {
box-sizing: border-box;
height: var(--tabs-card-height, @tabs-card-height);
.van-tab {
color: var(--tabs-default-color, @tabs-default-color);
line-height: calc(
var(--tabs-card-height, @tabs-card-height) - 2 * @border-width-base
);
border-right: @border-width-base solid
var(--tabs-default-color, @tabs-default-color);
&:last-child {
border-right: none;
}
&.van-tab--active {
color: @white;
background-color: var(--tabs-default-color, @tabs-default-color);
}
&--disabled {
color: var(--tab-disabled-text-color, @tab-disabled-text-color);
}
}
}
}
&__line {
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
opacity: 0;
height: var(--tabs-bottom-bar-height, @tabs-bottom-bar-height);
border-radius: var(--tabs-bottom-bar-height, @tabs-bottom-bar-height);
background-color: var(--tabs-bottom-bar-color, @tabs-bottom-bar-color);
}
&__track {
position: relative;
width: 100%;
height: 100%;
&--animated {
display: flex;
transition-property: left;
}
}
&__content {
overflow: hidden;
}
&--line {
height: var(--tabs-line-height, @tabs-line-height);
}
&--card {
height: var(--tabs-card-height, @tabs-card-height);
}
}
.van-tab {
position: relative;
flex: 1;
box-sizing: border-box;
min-width: 0; /* hack for flex ellipsis */
padding: 0 5px;
text-align: center;
cursor: pointer;
color: var(--tab-text-color, @tab-text-color);
font-size: var(--tab-font-size, @tab-font-size);
line-height: var(--tabs-line-height, @tabs-line-height);
&--active {
font-weight: var(--font-weight-bold, @font-weight-bold);
color: var(--tab-active-text-color, @tab-active-text-color);
}
&--disabled {
color: var(--tab-disabled-text-color, @tab-disabled-text-color);
}
&__title {
&__info {
position: relative !important;
top: -1px !important;
transform: translateX(0) !important;
}
}
}
================================================
FILE: packages/tabs/index.ts
================================================
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import {
getAllRect,
getRect,
groupSetData,
nextTick,
requestAnimationFrame,
} from '../common/utils';
import { isDef } from '../common/validator';
import { useChildren } from '../common/relation';
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
VantComponent({
mixins: [touch],
classes: [
'nav-class',
'tab-class',
'tab-active-class',
'line-class',
'wrap-class',
],
relation: useChildren('tab', function () {
this.updateTabs();
}),
props: {
sticky: Boolean,
border: Boolean,
swipeable: Boolean,
titleActiveColor: String,
titleInactiveColor: String,
color: String,
animated: {
type: Boolean,
observer() {
this.children.forEach((child, index) =>
child.updateRender(index === this.data.currentIndex, this)
);
},
},
lineWidth: {
type: null,
value: 40,
observer: 'resize',
},
lineHeight: {
type: null,
value: -1,
},
active: {
type: null,
value: 0,
observer(name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
},
},
type: {
type: String,
value: 'line',
},
ellipsis: {
type: Boolean,
value: true,
},
duration: {
type: Number,
value: 0.3,
},
zIndex: {
type: Number,
value: 1,
},
swipeThreshold: {
type: Number,
value: 5,
observer(value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis,
});
},
},
offsetTop: {
type: Number,
value: 0,
},
lazyRender: {
type: Boolean,
value: true,
},
useBeforeChange: {
type: Boolean,
value: false,
},
},
data: {
tabs: [] as Record[],
scrollLeft: 0,
scrollable: false,
currentIndex: 0,
container: null as unknown as () => WechatMiniprogram.NodesRef,
skipTransition: true,
scrollWithAnimation: false,
lineOffsetLeft: 0,
inited: false,
},
mounted() {
requestAnimationFrame(() => {
this.swiping = true;
this.setData({
container: () => this.createSelectorQuery().select('.van-tabs'),
});
this.resize();
this.scrollIntoView();
});
},
methods: {
updateTabs() {
const { children = [], data } = this;
this.setData({
tabs: children.map((child: TrivialInstance) => child.data),
scrollable:
this.children.length > data.swipeThreshold || !data.ellipsis,
});
this.setCurrentIndexByName(data.active || this.getCurrentName());
},
trigger(eventName: string, child?: TrivialInstance) {
const { currentIndex } = this.data;
const data = this.getChildData(currentIndex, child);
if (!isDef(data)) {
return;
}
this.$emit(eventName, data);
},
onTap(event: WechatMiniprogram.TouchEvent) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (child.data.disabled) {
this.trigger('disabled', child);
return;
}
this.onBeforeChange(index).then(() => {
this.setCurrentIndex(index);
nextTick(() => {
this.trigger('click');
});
});
},
// correct the index of active tab
setCurrentIndexByName(name) {
const { children = [] } = this;
const matched = children.filter(
(child: TrivialInstance) => child.getComputedName() === name
);
if (matched.length) {
this.setCurrentIndex(matched[0].index);
}
},
setCurrentIndex(currentIndex) {
const { data, children = [] } = this;
if (
!isDef(currentIndex) ||
currentIndex >= children.length ||
currentIndex < 0
) {
return;
}
groupSetData(this, () => {
children.forEach((item: TrivialInstance, index: number) => {
const active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, this);
}
});
});
if (currentIndex === data.currentIndex) {
if (!data.inited) {
this.resize();
}
return;
}
const shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex });
requestAnimationFrame(() => {
this.resize();
this.scrollIntoView();
});
nextTick(() => {
this.trigger('input');
if (shouldEmitChange) {
this.trigger('change');
}
});
},
getCurrentName() {
const activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
}
},
resize() {
if (this.data.type !== 'line') {
return;
}
const { currentIndex, ellipsis, skipTransition } = this.data;
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__line'),
]).then(([rects = [], lineRect]) => {
const rect = rects[currentIndex];
if (rect == null) {
return;
}
let lineOffsetLeft = rects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
lineOffsetLeft +=
(rect.width - lineRect.width) / 2 + (ellipsis ? 0 : 8);
this.setData({ lineOffsetLeft, inited: true });
this.swiping = true;
if (skipTransition) {
// waiting transition end
setTimeout(() => {
this.setData({ skipTransition: false });
}, this.data.duration);
}
});
},
// scroll active tab into view
scrollIntoView() {
const { currentIndex, scrollable, scrollWithAnimation } = this.data;
if (!scrollable) {
return;
}
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__nav'),
]).then(([tabRects, navRect]) => {
const tabRect = tabRects[currentIndex];
const offsetLeft = tabRects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
});
if (!scrollWithAnimation) {
nextTick(() => {
this.setData({ scrollWithAnimation: true });
});
}
});
},
onTouchScroll(event: WechatMiniprogram.CustomEvent) {
this.$emit('scroll', event.detail);
},
onTouchStart(event: WechatMiniprogram.TouchEvent) {
if (!this.data.swipeable) return;
this.swiping = true;
this.touchStart(event);
},
onTouchMove(event: WechatMiniprogram.TouchEvent) {
if (!this.data.swipeable || !this.swiping) return;
this.touchMove(event);
},
// watch swipe touch end
onTouchEnd() {
if (!this.data.swipeable || !this.swiping) return;
const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
const index = this.getAvaiableTab(deltaX);
if (index !== -1) {
this.onBeforeChange(index).then(() => this.setCurrentIndex(index));
}
}
this.swiping = false;
},
getAvaiableTab(direction: number) {
const { tabs, currentIndex } = this.data;
const step = direction > 0 ? -1 : 1;
for (
let i = step;
currentIndex + i < tabs.length && currentIndex + i >= 0;
i += step
) {
const index = currentIndex + i;
if (
index >= 0 &&
index < tabs.length &&
tabs[index] &&
!tabs[index].disabled
) {
return index;
}
}
return -1;
},
onBeforeChange(index: number): Promise {
const { useBeforeChange } = this.data;
if (!useBeforeChange) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
this.$emit('before-change', {
...this.getChildData(index),
callback: (status) => (status ? resolve() : reject()),
});
});
},
getChildData(index: number, child?: TrivialInstance) {
const currentChild = child || this.children[index];
if (!isDef(currentChild)) {
return;
}
return {
index: currentChild.index,
name: currentChild.getComputedName(),
title: currentChild.data.title,
};
},
},
});
================================================
FILE: packages/tabs/index.wxml
================================================
{{ item.title }}
================================================
FILE: packages/tabs/index.wxs
================================================
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(data) {
var titleColor = data.active
? data.titleActiveColor
: data.titleInactiveColor;
var ellipsis = data.scrollable && data.ellipsis;
// card theme color
if (data.type === 'card') {
return style({
'border-color': data.color,
'background-color': !data.disabled && data.active ? data.color : null,
color: titleColor || (!data.disabled && !data.active ? data.color : null),
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
return style({
color: titleColor,
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
function navStyle(color, type) {
return style({
'border-color': type === 'card' && color ? color : null,
});
}
function trackStyle(data) {
if (!data.animated) {
return '';
}
return style({
left: -100 * data.currentIndex + '%',
'transition-duration': data.duration + 's',
'-webkit-transition-duration': data.duration + 's',
});
}
function lineStyle(data) {
return style({
width: utils.addUnit(data.lineWidth),
opacity: data.inited ? 1 : 0,
transform: 'translateX(' + data.lineOffsetLeft + 'px)',
'-webkit-transform': 'translateX(' + data.lineOffsetLeft + 'px)',
'background-color': data.color,
height: data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'border-radius':
data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'transition-duration': !data.skipTransition ? data.duration + 's' : null,
'-webkit-transition-duration': !data.skipTransition
? data.duration + 's'
: null,
});
}
module.exports = {
tabClass: tabClass,
tabStyle: tabStyle,
trackStyle: trackStyle,
lineStyle: lineStyle,
navStyle: navStyle,
};
================================================
FILE: packages/tag/README.md
================================================
# Tag 标签
### 介绍
用于标记关键词和概括主要内容。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-tag": "@vant/weapp/tag/index"
}
```
## 代码演示
### 基础用法
通过 `type` 属性控制标签颜色,默认为灰色。
```html
标签
标签
标签
标签
```
### 空心样式
设置 `plain` 属性设置为空心样式。
```html
标签
标签
标签
标签
```
### 圆角样式
通过 `round` 设置为圆角样式。
```html
标签
标签
标签
标签
```
### 标记样式
通过 `mark` 设置为标记样式(半圆角)。
```html
标签
标签
标签
标签
```
### 自定义颜色
```html
标签
标签
标签
标签
```
### 标签大小
```html
标签
标签
标签
```
### 可关闭标签
添加 `closeable` 属性表示标签是可关闭的,关闭标签时会触发 `close` 事件,在 `close` 事件中可以执行隐藏标签的逻辑。
```html
标签
标签
```
```js
Page({
data: {
show: {
primary: true,
success: true,
},
},
onClose(event) {
this.setData({
[`show.${event.target.id}`]: false,
});
},
});
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 类型,可选值为 `primary` `success` `danger` `warning` | _string_ | - |
| size | 大小, 可选值为 `large` `medium` | _string_ | - |
| color | 标签颜色 | _string_ | - |
| plain | 是否为空心样式 | _boolean_ | `false` |
| round | 是否为圆角样式 | _boolean_ | `false` |
| mark | 是否为标记样式 | _boolean_ | `false` |
| text-color | 文本颜色,优先级高于 `color` 属性 | _string_ | `white` |
| closeable | 是否为可关闭标签 | _boolean_ | `false` |
### Slot
| 名称 | 说明 |
| ---- | ------------------- |
| - | 自定义 Tag 显示内容 |
### Events
| 事件名 | 说明 | 回调参数 |
| ------ | -------------- | -------- |
| bind:close | 关闭标签时触发 | - |
### 外部样式类
| 类名 | 说明 |
| ------------ | ------------ |
| custom-class | 根节点样式类 |
================================================
FILE: packages/tag/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-tag": "../../tag/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/tag/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show: {
success: true,
primary: true,
},
},
methods: {
onClose(event) {
this.setData({
[`show.${event.target.id}`]: false,
});
},
},
});
================================================
FILE: packages/tag/demo/index.wxml
================================================
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
标签
================================================
FILE: packages/tag/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
================================================
FILE: packages/tag/index.less
================================================
@import '../common/style/var.less';
.van-tag {
position: relative;
display: inline-flex;
align-items: center;
padding: var(--tag-padding, @tag-padding);
color: var(--tag-text-color, @tag-text-color);
font-size: var(--tag-font-size, @tag-font-size);
line-height: var(--tag-line-height, @tag-line-height);
border-radius: var(--tag-border-radius, @tag-border-radius);
&--default {
background-color: var(--tag-default-color, @tag-default-color);
&.van-tag--plain {
color: var(--tag-default-color, @tag-default-color);
}
}
&--danger {
background-color: var(--tag-danger-color, @tag-danger-color);
&.van-tag--plain {
color: var(--tag-danger-color, @tag-danger-color);
}
}
&--primary {
background-color: var(--tag-primary-color, @tag-primary-color);
&.van-tag--plain {
color: var(--tag-primary-color, @tag-primary-color);
}
}
&--success {
background-color: var(--tag-success-color, @tag-success-color);
&.van-tag--plain {
color: var(--tag-success-color, @tag-success-color);
}
}
&--warning {
background-color: var(--tag-warning-color, @tag-warning-color);
&.van-tag--plain {
color: var(--tag-warning-color, @tag-warning-color);
}
}
&--plain {
background-color: var(
--tag-plain-background-color,
@tag-plain-background-color
);
&::before {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 1px solid currentColor;
border-radius: inherit;
content: '';
pointer-events: none;
}
}
&--medium {
padding: var(--tag-medium-padding, @tag-medium-padding);
}
&--large {
padding: var(--tag-large-padding, @tag-large-padding);
font-size: var(--tag-large-font-size, @tag-large-font-size);
border-radius: var(--tag-large-border-radius, @tag-large-border-radius);
}
&--mark {
border-radius: 0
var(
--tag-round-border-radius,
var(--tag-round-border-radius, @tag-round-border-radius)
)
var(
--tag-round-border-radius,
var(--tag-round-border-radius, @tag-round-border-radius)
)
0;
&::after {
display: block;
width: 2px;
content: '';
}
}
&--round {
border-radius: var(--tag-round-border-radius, @tag-round-border-radius);
}
&__close {
min-width: 1em;
margin-left: 2px;
}
}
================================================
FILE: packages/tag/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
size: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String,
type: {
type: String,
value: 'default',
},
closeable: Boolean,
},
methods: {
onClose() {
this.$emit('close');
},
},
});
================================================
FILE: packages/tag/index.wxml
================================================
================================================
FILE: packages/tag/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style({
'background-color': data.plain ? '' : data.color,
color: data.textColor || data.plain ? data.textColor || data.color : '',
});
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/tag/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
标签
标签
标签
标签
圆角样式
标签
标签
标签
标签
标记样式
标签
标签
标签
标签
空心样式
标签
标签
标签
标签
自定义颜色
标签
标签
标签
标签
标签大小
标签
标签
标签
可关闭标签
标签
标签
`;
================================================
FILE: packages/tag/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/toast/README.md
================================================
# Toast 轻提示
### 介绍
在页面中间弹出黑色半透明提示,用于消息通知、加载提示、操作结果提示等场景。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-toast": "@vant/weapp/toast/index"
}
```
## 代码演示
### 文字提示
```javascript
import Toast from '@vant/weapp/toast/toast';
Toast('我是提示文案,建议不超过十五字~');
```
```html
```
### 加载提示
使用 `Toast.loading` 方法展示加载提示,通过 `forbidClick` 属性可以禁用背景点击,通过 `loadingType` 属性可以自定义加载图标类型。
```javascript
Toast.loading({
message: '加载中...',
forbidClick: true,
});
// 自定义加载图标
Toast.loading({
message: '加载中...',
forbidClick: true,
loadingType: 'spinner',
});
```
### 成功/失败提示
```javascript
Toast.success('成功文案');
Toast.fail('失败文案');
```
### 动态更新提示
```javascript
const toast = Toast.loading({
duration: 0, // 持续展示 toast
forbidClick: true,
message: '倒计时 3 秒',
selector: '#custom-selector',
});
let second = 3;
const timer = setInterval(() => {
second--;
if (second) {
toast.setData({
message: `倒计时 ${second} 秒`,
});
} else {
clearInterval(timer);
Toast.clear();
}
}, 1000);
```
```html
```
### OnClose 回调函数
```javascript
Toast({
type: 'success',
message: '提交成功',
onClose: () => {
console.log('执行OnClose函数');
},
});
```
## API
### 方法
| 方法名 | 参数 | 返回值 | 介绍 |
| --- | --- | --- | --- |
| Toast | `options \| message` | toast 实例 | 展示提示 |
| Toast.loading | `options \| message` | toast 实例 | 展示加载提示 |
| Toast.success | `options \| message` | toast 实例 | 展示成功提示 |
| Toast.fail | `options \| message` | toast 实例 | 展示失败提示 |
| Toast.clear | `clearAll` | `void` | 关闭提示 |
| Toast.setDefaultOptions | `options` | `void` | 修改默认配置,对所有 Toast 生效 |
| Toast.resetDefaultOptions | - | `void` | 重置默认配置,对所有 Toast 生效 |
### Options
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 提示类型,可选值为 `loading` `success` `fail` `html` | _string_ | `text` |
| position | 位置,可选值为 `top` `middle` `bottom` | _string_ | `middle` |
| message | 内容 | _string_ | `''` |
| mask | 是否显示遮罩层 | _boolean_ | `false` |
| forbidClick | 是否禁止背景点击 | _boolean_ | `false` |
| loadingType | 加载图标类型, 可选值为 `spinner` | _string_ | `circular` |
| zIndex | z-index 层级 | _number_ | `1000` |
| duration | 展示时长(ms),值为 0 时,toast 不会消失 | _number_ | `2000` |
| selector | 自定义选择器 | _string_ | `van-toast` |
| context | 选择器的选择范围,可以传入自定义组件的 this 作为上下文 | _object_ | 当前页面 |
| onClose | 关闭时的回调函数 | _Function_ | - |
### Slot
| 名称 | 说明 |
| ---- | ---------- |
| - | 自定义内容 |
================================================
FILE: packages/toast/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-toast": "../../toast/index",
"van-button": "../../button/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/toast/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
import Toast from '../../toast/toast';
VantComponent({
methods: {
showToast() {
Toast({ context: this, message: '提示内容' });
},
showLongToast() {
Toast({
context: this,
message: '这是一条长文字提示,超过一定字数就会换行',
});
},
showLoadingToast() {
Toast.loading({ context: this, message: '加载中...', forbidClick: true });
},
showCustomLoadingToast() {
Toast.loading({
context: this,
message: '加载中...',
forbidClick: true,
loadingType: 'spinner',
});
},
showSuccessToast() {
Toast.success({ context: this, message: '成功文案' });
},
showFailToast() {
Toast.fail({ context: this, message: '失败提示' });
},
showCustomizedToast() {
const text = (second) => `倒计时 ${second} 秒`;
const toast = Toast.loading({
context: this,
duration: 0,
forbidClick: true,
message: text(3),
});
let second = 3;
const timer = setInterval(() => {
second--;
if (second) {
toast?.setData({ message: text(second) });
} else {
clearInterval(timer);
Toast.clear();
}
}, 1000);
},
},
});
================================================
FILE: packages/toast/demo/index.wxml
================================================
文字提示
长文字提示
加载提示
自定义加载图标
成功提示
失败提示
动态更新提示
================================================
FILE: packages/toast/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index",
"van-overlay": "../overlay/index",
"van-transition": "../transition/index"
}
}
================================================
FILE: packages/toast/index.less
================================================
@import '../common/style/var.less';
.van-toast {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: content-box;
color: var(--toast-text-color, @toast-text-color);
font-size: var(--toast-font-size, @toast-font-size);
line-height: var(--toast-line-height, @toast-line-height);
// allow newline charactor
white-space: pre-wrap;
word-wrap: break-word;
background-color: var(--toast-background-color, @toast-background-color);
border-radius: var(--toast-border-radius, @toast-border-radius);
&__container {
position: fixed;
top: 50%;
left: 50%;
// hack for avoid max-width when use left & fixed
width: fit-content;
transform: translate(-50%, -50%);
max-width: var(--toast-max-width, @toast-max-width);
}
&--text {
min-width: var(--toast-text-min-width, @toast-text-min-width);
padding: var(--toast-text-padding, @toast-text-padding);
}
&--icon {
width: var(--toast-default-width, @toast-default-width);
min-height: var(--toast-default-min-height, @toast-default-min-height);
padding: var(--toast-default-padding, @toast-default-padding);
.van-toast__icon {
font-size: var(--toast-icon-size, @toast-icon-size);
}
.van-toast__text {
padding-top: @padding-xs;
}
}
&__loading {
margin: 10px 0;
}
&--top {
transform: translate(0, -30vh);
}
&--bottom {
transform: translate(0, 30vh);
}
}
================================================
FILE: packages/toast/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000,
},
type: {
type: String,
value: 'text',
},
loadingType: {
type: String,
value: 'circular',
},
position: {
type: String,
value: 'middle',
},
},
methods: {
// for prevent touchmove
noop() {},
},
});
================================================
FILE: packages/toast/index.wxml
================================================
{{ message }}
{{ message }}
================================================
FILE: packages/toast/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
文字提示
文字提示
长文字提示
加载提示
加载提示
自定义加载图标
成功/失败提示
成功提示
失败提示
动态更新提示
动态更新提示
`;
================================================
FILE: packages/toast/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/toast/toast.ts
================================================
import { isObj } from '../common/validator';
type ToastMessage = string | number;
type ToastContext =
| WechatMiniprogram.Component.TrivialInstance
| WechatMiniprogram.Page.TrivialInstance;
interface ToastOptions {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: (() => ToastContext) | ToastContext;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
onClose?: () => void;
}
const defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 2000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast',
};
let queue: WechatMiniprogram.Component.TrivialInstance[] = [];
let currentOptions: ToastOptions = { ...defaultOptions };
function parseOptions(message): ToastOptions {
return isObj(message) ? message : { message };
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
function Toast(toastOptions: ToastOptions | ToastMessage) {
const options = {
...currentOptions,
...parseOptions(toastOptions),
} as ToastOptions;
const context =
(typeof options.context === 'function'
? options.context()
: options.context) || getContext();
const toast = context.selectComponent(options.selector as string);
if (!toast) {
console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
return;
}
delete options.context;
delete options.selector;
toast.clear = () => {
toast.setData({ show: false });
if (options.onClose) {
options.onClose();
}
};
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration != null && options.duration > 0) {
toast.timer = setTimeout(() => {
toast.clear();
queue = queue.filter((item) => item !== toast);
}, options.duration);
}
return toast;
}
const createMethod = (type: string) => (options: ToastOptions | ToastMessage) =>
Toast({
type,
...parseOptions(options),
});
Toast.loading = createMethod('loading');
Toast.success = createMethod('success');
Toast.fail = createMethod('fail');
Toast.clear = () => {
queue.forEach((toast) => {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = (options: ToastOptions) => {
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = () => {
currentOptions = { ...defaultOptions };
};
export default Toast;
================================================
FILE: packages/transition/README.md
================================================
# Transition 动画
### 介绍
使元素从一种样式逐渐变化为另一种样式的效果。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-transition": "@vant/weapp/transition/index"
}
```
## 代码演示
### 基础用法
将元素包裹在 transition 组件内,在元素展示/隐藏时,会有相应的过渡动画。
```html
内容
```
### 动画类型
transition 组件内置了多种动画,可以通过`name`字段指定动画类型。
```html
```
### 高级用法
可以通过外部样式类自定义过渡效果,还可以定制进入和移出的持续时间。
```html
```
```css
.van-enter-active-class,
.van-leave-active-class {
transition-property: background-color, transform;
}
.van-enter-class,
.van-leave-to-class {
background-color: red;
transform: rotate(-360deg) translate3d(-100%, -100%, 0);
}
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ------------ | -------------------- | ------------------ | ------ |
| name | 动画类型 | _string_ | `fade` |
| show | 是否展示组件 | _boolean_ | `true` |
| duration | 动画时长,单位为毫秒 | _number \| object_ | `300` |
| custom-style | 自定义样式 | _string_ | - |
### Events
| 事件名 | 说明 | 参数 |
| ----------------- | ---------- | ---- |
| bind:before-enter | 进入前触发 | - |
| bind:enter | 进入中触发 | - |
| bind:after-enter | 进入后触发 | - |
| bind:before-leave | 离开前触发 | - |
| bind:leave | 离开中触发 | - |
| bind:after-leave | 离开后触发 | - |
### 外部样式类
| 类名 | 说明 |
| --- | --- |
| custom-class | 根节点样式类 |
| enter-class | 定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 |
| enter-active-class | 定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 |
| enter-to-class | 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 enter-class 被移除),在过渡/动画完成之后移除。 |
| leave-class | 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 |
| leave-active-class | 定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 |
| leave-to-class | 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 leave-class 被删除),在过渡/动画完成之后移除。 |
### 动画类型
| 名称 | 说明 |
| ----------- | -------- |
| fade | 淡入 |
| fade-up | 上滑淡入 |
| fade-down | 下滑淡入 |
| fade-left | 左滑淡入 |
| fade-right | 右滑淡入 |
| slide-up | 上滑进入 |
| slide-down | 下滑进入 |
| slide-left | 左滑进入 |
| slide-right | 右滑进入 |
================================================
FILE: packages/transition/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-cell": "../../cell/index",
"van-transition": "../../transition/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/transition/demo/index.less
================================================
.block {
position: fixed;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
margin: -50px 0 0 -50px;
background-color: #1989fa;
}
.van-enter-active-class,
.van-leave-active-class {
transition-property: background-color, transform;
}
.van-enter-class,
.van-leave-to-class {
background-color: red;
transform: rotate(-360deg) translate3d(-100%, -100%, 0);
}
================================================
FILE: packages/transition/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
show: false,
name: 'fade',
showCustom: false,
},
methods: {
onClickFade() {
this.trigger('fade');
},
onClickFadeUp() {
this.trigger('fade-up');
},
onClickFadeDown() {
this.trigger('fade-down');
},
onClickFadeLeft() {
this.trigger('fade-left');
},
onClickFadeRight() {
this.trigger('fade-right');
},
onClickSlideUp() {
this.trigger('slide-up');
},
onClickSlideDown() {
this.trigger('slide-down');
},
onClickSlideLeft() {
this.trigger('slide-left');
},
onClickSlideRight() {
this.trigger('slide-right');
},
trigger(name) {
this.setData({ name, show: true });
setTimeout(() => {
this.setData({ show: false });
}, 500);
},
onClickCustom() {
this.setData({ showCustom: true });
setTimeout(() => {
this.setData({ showCustom: false });
}, 1000);
},
onBeforeEnter() {
console.log('before enter');
},
onEnter() {
console.log('enter');
},
onAfterEnter() {
console.log('after enter');
},
onBeforeLeave() {
console.log('before leave');
},
onLeave() {
console.log('leave');
},
onAfterLeave() {
console.log('after leave');
},
},
});
================================================
FILE: packages/transition/demo/index.wxml
================================================
================================================
FILE: packages/transition/index.json
================================================
{
"component": true
}
================================================
FILE: packages/transition/index.less
================================================
.van-transition {
transition-timing-function: ease;
}
.van-fade-enter-active,
.van-fade-leave-active {
transition-property: opacity;
}
.van-fade-enter,
.van-fade-leave-to {
opacity: 0;
}
.van-fade-up-enter-active,
.van-fade-up-leave-active,
.van-fade-down-enter-active,
.van-fade-down-leave-active,
.van-fade-left-enter-active,
.van-fade-left-leave-active,
.van-fade-right-enter-active,
.van-fade-right-leave-active {
transition-property: opacity, transform;
}
.van-fade-up-enter,
.van-fade-up-leave-to {
transform: translate3d(0, 100%, 0);
opacity: 0;
}
.van-fade-down-enter,
.van-fade-down-leave-to {
transform: translate3d(0, -100%, 0);
opacity: 0;
}
.van-fade-left-enter,
.van-fade-left-leave-to {
transform: translate3d(-100%, 0, 0);
opacity: 0;
}
.van-fade-right-enter,
.van-fade-right-leave-to {
transform: translate3d(100%, 0, 0);
opacity: 0;
}
.van-slide-up-enter-active,
.van-slide-up-leave-active,
.van-slide-down-enter-active,
.van-slide-down-leave-active,
.van-slide-left-enter-active,
.van-slide-left-leave-active,
.van-slide-right-enter-active,
.van-slide-right-leave-active {
transition-property: transform;
}
.van-slide-up-enter,
.van-slide-up-leave-to {
transform: translate3d(0, 100%, 0);
}
.van-slide-down-enter,
.van-slide-down-leave-to {
transform: translate3d(0, -100%, 0);
}
.van-slide-left-enter,
.van-slide-left-leave-to {
transform: translate3d(-100%, 0, 0);
}
.van-slide-right-enter,
.van-slide-right-leave-to {
transform: translate3d(100%, 0, 0);
}
================================================
FILE: packages/transition/index.ts
================================================
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class',
],
mixins: [transition(true)],
});
================================================
FILE: packages/transition/index.wxml
================================================
================================================
FILE: packages/transition/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style([
{
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
================================================
FILE: packages/transition/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
Fade
Fade Up
Fade Down
Fade Left
Fade Right
Slide Up
Slide Down
Slide Left
Slide Right
Custom
`;
================================================
FILE: packages/transition/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/tree-select/README.md
================================================
# TreeSelect 分类选择
### 介绍
用于从一组相关联的数据集合中进行选择。
### 引入
在`app.json`或`index.json`中引入组件,详细介绍见[快速上手](#/quickstart#yin-ru-zu-jian)。
```json
"usingComponents": {
"van-tree-select": "@vant/weapp/tree-select/index"
}
```
## 代码演示
### 单选模式
可以在任意位置上使用 van-tree-select 标签。传入对应的数据即可。此组件支持单选或多选,具体行为完全基于事件 click-item 的实现逻辑如何为属性 active-id 赋值,当 active-id 为数组时即为多选状态。
```html
```
```javascript
Page({
data: {
mainActiveIndex: 0,
activeId: null,
},
onClickNav({ detail = {} }) {
this.setData({
mainActiveIndex: detail.index || 0,
});
},
onClickItem({ detail = {} }) {
const activeId = this.data.activeId === detail.id ? null : detail.id;
this.setData({ activeId });
},
});
```
### 多选模式
```html
```
```javascript
Page({
data: {
mainActiveIndex: 0,
activeId: [],
max: 2,
},
onClickNav({ detail = {} }) {
this.setData({
mainActiveIndex: detail.index || 0,
});
},
onClickItem({ detail = {} }) {
const { activeId } = this.data;
const index = activeId.indexOf(detail.id);
if (index > -1) {
activeId.splice(index, 1);
} else {
activeId.push(detail.id);
}
this.setData({ activeId });
},
});
```
### 自定义内容
```html
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| items | 分类显示所需的数据 | _Array_ | `[]` |
| height | 高度,默认单位为`px` | _number \| string_ | `300` |
| main-active-index | 左侧选中项的索引 | _number_ | `0` |
| active-id | 右侧选中项的 id,支持传入数组 | _string \| number \| Array_ | `0` |
| max | 右侧项最大选中个数 | _number_ | _Infinity_ |
| selected-icon `v1.5.0` | 自定义右侧栏选中状态的图标 | _string_ | `success` |
### Events
| 事件名 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:click-nav | 左侧导航点击时,触发的事件 | event.detail.index:被点击的导航的索引 |
| bind:click-item | 右侧选择项被点击时,会触发的事件 | event.detail: 该点击项的数据 |
### Slots
| 名称 | 说明 |
| ------- | ------------------------------------------------ |
| content | 自定义右侧区域内容,如果存在 items,则插入在顶部 |
### items 数据结构
`items` 整体为一个数组,数组内包含一系列描述分类的对象。每个分类里,text 表示当前分类的名称。children 表示分类里的可选项,为数组结构,id 被用来唯一标识每个选项。
```javascript
[
{
// 导航名称
text: '所有城市',
// 导航名称右上角徽标,1.5.0 版本开始支持
badge: 3,
// 是否在导航名称右上角显示小红点,1.5.0 版本开始支持
dot: true,
// 禁用选项
disabled: false,
// 该导航下所有的可选项
children: [
{
// 名称
text: '温州',
// id,作为匹配选中状态的标识
id: 1,
// 禁用选项
disabled: true,
},
{
text: '杭州',
id: 2,
},
],
},
];
```
### 外部样式类
| 类名 | 说明 |
| ---------------------- | ------------------ |
| main-item-class | 左侧选项样式类 |
| content-item-class | 右侧选项样式类 |
| main-active-class | 左侧选项选中样式类 |
| content-active-class | 右侧选项选中样式类 |
| main-disabled-class | 左侧选项禁用样式类 |
| content-disabled-class | 右侧选项禁用样式类 |
================================================
FILE: packages/tree-select/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-image": "../../image/index",
"van-tree-select": "../../tree-select/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/tree-select/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
const config = {
pro1Name: '浙江',
pro1: [
{
text: '杭州',
id: 1,
},
{
text: '温州',
id: 2,
},
{
text: '宁波',
id: 3,
disabled: true,
},
{
text: '义乌',
id: 4,
},
],
pro2Name: '江苏',
pro2: [
{
text: '南京',
id: 5,
},
{
text: '无锡',
id: 6,
},
{
text: '徐州',
id: 7,
},
{
text: '苏州',
id: 8,
},
],
pro3Name: '福建',
pro3: [
{
text: '泉州',
id: 9,
},
{
text: '厦门',
id: 10,
},
],
};
const items = [
{
text: config.pro1Name,
children: config.pro1,
},
{
text: config.pro2Name,
children: config.pro2,
},
{
text: config.pro3Name,
disabled: true,
children: config.pro3,
},
];
VantComponent({
data: {
items,
badgeItems: items.slice(0, 2).map((item, index) => {
if (index === 0) {
return { ...item, dot: true };
}
if (index === 1) {
return { ...item, badge: 5 };
}
return item;
}),
mainActiveIndex: 0,
activeId: 0,
mainActiveIndexMulti: 0,
activeIdMulti: [],
},
methods: {
onClickNav({ detail }) {
this.setData({
mainActiveIndex: detail.index || 0,
});
},
onClickItem({ detail }) {
const activeId = this.data.activeId === detail.id ? null : detail.id;
this.setData({ activeId });
},
onClickNavMulti({ detail }) {
this.setData({
mainActiveIndexMulti: detail.index || 0,
});
},
onClickItemMulti({ detail }) {
const { activeIdMulti }: { activeIdMulti: any } = this.data;
const idx = activeIdMulti.indexOf(detail.id);
if (idx > -1) {
activeIdMulti.splice(idx, 1);
} else {
activeIdMulti.push(detail.id);
}
this.setData({ activeIdMulti });
},
},
});
================================================
FILE: packages/tree-select/demo/index.wxml
================================================
================================================
FILE: packages/tree-select/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
}
}
================================================
FILE: packages/tree-select/index.less
================================================
@import '../common/style/var.less';
.van-tree-select {
position: relative;
display: flex;
user-select: none;
font-size: var(--tree-select-font-size, @tree-select-font-size);
&__nav {
flex: 1;
background-color: var(
--tree-select-nav-background-color,
@tree-select-nav-background-color
);
&__inner {
width: 100% !important;
height: 100%;
}
--sidebar-padding: @tree-select-nav-item-padding;
}
&__content {
flex: 2;
background-color: var(
--tree-select-content-background-color,
@tree-select-content-background-color
);
}
&__item {
position: relative;
font-weight: bold;
padding: 0 32px 0 var(--padding-md, @padding-md);
line-height: var(--tree-select-item-height, @tree-select-item-height);
&--active {
color: var(
--tree-select-item-active-color,
@tree-select-item-active-color
);
}
&--disabled {
color: var(
--tree-select-item-disabled-color,
@tree-select-item-disabled-color
);
}
}
&__selected {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: var(--padding-md, @padding-md);
}
}
================================================
FILE: packages/tree-select/index.ts
================================================
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'main-item-class',
'content-item-class',
'main-active-class',
'content-active-class',
'main-disabled-class',
'content-disabled-class',
],
props: {
items: {
type: Array,
observer: 'updateSubItems',
},
activeId: null,
mainActiveIndex: {
type: Number,
value: 0,
observer: 'updateSubItems',
},
height: {
type: null,
value: 300,
},
max: {
type: Number,
value: Infinity,
},
selectedIcon: {
type: String,
value: 'success',
},
},
data: {
subItems: [],
},
methods: {
// 当一个子项被选择时
onSelectItem(event: WechatMiniprogram.TouchEvent) {
const { item } = event.currentTarget.dataset;
const isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
const isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
const isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav(event: WechatMiniprogram.CustomEvent) {
const index = (event.detail as unknown) as number;
const item = this.data.items[index];
if (!item.disabled) {
this.$emit('click-nav', { index });
}
},
// 更新子项列表
updateSubItems() {
const { items, mainActiveIndex } = this.data;
const { children = [] } = items[mainActiveIndex] || {};
this.setData({ subItems: children });
},
},
});
================================================
FILE: packages/tree-select/index.wxml
================================================
{{ item.text }}
================================================
FILE: packages/tree-select/index.wxs
================================================
/* eslint-disable */
var array = require('../wxs/array.wxs');
function isActive (activeList, itemId) {
if (array.isArray(activeList)) {
return activeList.indexOf(itemId) > -1;
}
return activeList === itemId;
}
module.exports.isActive = isActive;
================================================
FILE: packages/tree-select/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
单选模式
杭州
温州
宁波
义乌
多选模式
杭州
温州
宁波
义乌
自定义内容
徽标提示
杭州
温州
宁波
义乌
`;
================================================
FILE: packages/tree-select/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
try {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
} catch (e) {
console.error(e);
}
});
================================================
FILE: packages/uploader/README.md
================================================
# Uploader 文件上传
### 介绍
用于将本地的图片或文件上传至服务器,并在上传过程中展示预览图和上传进度。目前 Uploader 组件不包含将文件上传至服务器的接口逻辑,该步骤需要自行实现。
### 引入
在`app.json`或`index.json`中引入组件,默认为`ES6`版本,`ES5`引入方式参见[快速上手](#/quickstart)。
```json
"usingComponents": {
"van-uploader": "@vant/weapp/uploader/index"
}
```
> Vant Weapp 1.0 版本开始支持此组件,升级方式参见[快速上手](#/quickstart)
## 代码演示
### 基础用法
文件上传完毕后会触发`after-read`回调函数,获取到对应的文件的临时地址,然后再使用`wx.uploadFile`将图片上传到远程服务器上。
```html
```
```js
Page({
data: {
fileList: [],
},
afterRead(event) {
const { file } = event.detail;
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
wx.uploadFile({
url: 'https://example.weixin.qq.com/upload', // 仅为示例,非真实的接口地址
filePath: file.url,
name: 'file',
formData: { user: 'test' },
success(res) {
// 上传完成需要更新 fileList
const { fileList = [] } = this.data;
fileList.push({ ...file, url: res.data });
this.setData({ fileList });
},
});
},
});
```
### 图片预览
通过向组件传入`file-list`属性,可以绑定已经上传的图片列表,并展示图片列表的预览图。file-list 的详细结构可见下方。
```html
```
```js
Page({
data: {
fileList: [
{
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
name: '图片1',
},
// Uploader 根据文件后缀来判断是否为图片文件
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
{
url: 'http://iph.href.lu/60x60?text=default',
name: '图片2',
isImage: true,
deletable: true,
},
],
},
});
```
### 图片可删除状态
通过`deletable`属性可控制是否开启所有图片的可删除状态,`deletable`默认为`true`,即所有图片都可删除。
若希望控制单张图片的可删除状态,可将`deletable`属性设置为`true`,并在`fileList`中为每一项设置`deletable`属性。
```html
```
```js
Page({
data: {
fileList: [
{
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
},
{
url: 'https://img.yzcdn.cn/vant/tree.jpg',
deletable: false,
},
],
},
});
```
### 上传状态
通过`status`属性可以标识上传状态,`uploading`表示上传中,`failed`表示上传失败,`done`表示上传完成。
```html
```
```js
Page({
data: {
fileList: [
{
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
status: 'uploading',
message: '上传中',
},
{
url: 'https://img.yzcdn.cn/vant/tree.jpg',
status: 'failed',
message: '上传失败',
},
],
},
});
```
### 限制上传数量
通过`max-count`属性可以限制上传文件的数量,上传数量达到限制后,会自动隐藏上传区域。
```html
```
### 自定义上传样式
通过插槽可以自定义上传区域的样式。
```html
上传图片
```
### 上传前校验
将`use-before-read`属性设置为`true`,然后绑定 `before-read` 事件可以在上传前进行校验,调用 `callback` 方法传入 `true` 表示校验通过,传入 `false` 表示校验失败。
```html
```
```js
Page({
data: {
fileList: [],
},
beforeRead(event) {
const { file, callback } = event.detail;
callback(file.type === 'image');
},
});
```
## 云开发示例
### 上传图片至云存储
在开发中,可以利用[小程序云开发](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)的云存储能力,将图片上传至云存储内。然后根据返回的`fileiId`来下载图片、删除图片和替换临时链接。
```js
// 上传图片
uploadToCloud() {
wx.cloud.init();
const { fileList } = this.data;
if (!fileList.length) {
wx.showToast({ title: '请选择图片', icon: 'none' });
} else {
const uploadTasks = fileList.map((file, index) => this.uploadFilePromise(`my-photo${index}.png`, file));
Promise.all(uploadTasks)
.then(data => {
wx.showToast({ title: '上传成功', icon: 'none' });
const newFileList = data.map(item => ({ url: item.fileID }));
this.setData({ cloudPath: data, fileList: newFileList });
})
.catch(e => {
wx.showToast({ title: '上传失败', icon: 'none' });
console.log(e);
});
}
}
uploadFilePromise(fileName, chooseResult) {
return wx.cloud.uploadFile({
cloudPath: fileName,
filePath: chooseResult.url
});
}
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| name | 标识符,可以在回调函数的第二项参数中获取 | _string \| number_ | - |
| accept | 接受的文件类型, 可选值为`all` `media` `image` `file` `video` | _string_ | `image` |
| sizeType | 所选的图片的尺寸, 当`accept`为`image` \| `media` 类型时设置所选图片的尺寸可选值为`original` `compressed` | _string[]_ | `['original','compressed']` |
| preview-size | 预览图和上传区域的尺寸,默认单位为`px` | _string \| number_ | `80px` |
| preview-image | 是否在上传完成后展示预览图 | _boolean_ | `true` |
| preview-full-image | 是否在点击预览图后展示全屏图片预览 | _boolean_ | `true` |
| preview-file `v1.11.7` | 是否在点击文件预览图后预览文件 | _boolean_ | `true` |
| multiple | 是否开启图片多选,部分安卓机型不支持 | _boolean_ | `false` |
| disabled | 是否禁用文件上传 | _boolean_ | `false` |
| show-upload | 是否展示文件上传按钮 | _boolean_ | `true` |
| deletable | 是否展示删除按钮 | _boolean_ | `true` |
| capture | 图片或者视频选取模式,当`accept`为`image` \| `media` 类型时设置`capture`可选值为`camera`可以直接调起摄像头 | _string[]_ | `['album', 'camera']` |
| max-size | 文件大小限制,单位为`byte` | _number_ | - |
| max-count | 文件上传数量限制 | _number_ | - |
| upload-text | 上传区域文字提示 | _string_ | - |
| video-fit `1.10.21` | video 封面的预览图模式,可选值参考小程序`video`组件的`object-fit`属性 | _string_ | `contain` |
| image-fit | 预览图裁剪模式,可选值参考小程序`image`组件的`mode`属性 | _string_ | `scaleToFill` |
| use-before-read | 是否开启文件读取前事件 | _boolean_ | - |
| camera | 当 accept 为 `video` \| `media` 时生效,可选值为 `back` `front` | _string_ | - |
| compressed | 当 accept 为 `video` 时生效,是否压缩视频,默认为`true` | _boolean_ | - |
| max-duration | 当 accept 为 `video` \| `media` 时生效,拍摄视频最长拍摄时间,单位秒 | _number_ | `60` |
| media-type `v1.10.8` | 当 accept 为 `media` 时生效,选择的文件的文件类型,可选值为 `image` `video` `mix` | _string[]_ | `['image', 'video', 'mix']` |
| extension `v1.10.11` | 当 accept 为 `file` 时生效,根据文件拓展名过滤可选择文件。每一项都不能是空字符串。默认不过滤 | _string[] \| undefined_ | - |
| showmenu `v1.10.13` | 预览图片时,是否显示长按菜单 | _boolean_ | `true` |
| upload-icon | 上传区域图标,可选值见 [Icon 组件](#/icon) | _string_ | `plus` |
| referrer-policy `v1.11.6` | 当 accept 为 video 时生效,具体用法参考 [微信官方 - 媒体组件 / video](https://developers.weixin.qq.com/miniprogram/dev/component/video.html) | string | `no-referrer` |
#### accept 的合法值
| 参数 | 说明 |
| ------- | ------------------------------------ |
| `media` | 图片和视频 |
| `image` | 图片 |
| `video` | 视频 |
| `file` | 从客户端会话选择图片和视频以外的文件 |
| `all` | 从客户端会话选择所有文件 |
### FileList
`file-list` 为一个对象数组,数组中的每一个对象包含以下 `key`。
| 参数 | 说明 |
| --- | --- |
| `url` | 图片和视频的网络资源地址 |
| `name` | 文件名称,视频将在全屏预览时作为标题显示 |
| `thumb` | 图片缩略图或视频封面的网络资源地址,仅对图片和视频有效,`accept` 为 `video`时,真机不会返回该属性,建议使用 `media` 和 `media-type` 配合完成视频上传 |
| `type` | 文件类型,可选值`image` `video` `file` |
| `isImage` | 手动标记图片资源 |
| `isVideo` | 手动标记视频资源 |
### Slot
| 名称 | 说明 |
| ---- | -------------- |
| - | 自定义上传区域 |
### Events
| 事件名 | 说明 | 回调参数 |
| --- | --- | --- |
| bind:before-read | 文件读取前,在回调函数中返回 `false` 可终止文件读取,绑定事件的同时需要将`use-before-read`属性设置为`true` | `event.detail.file`: 当前读取的文件,`event.detail.callback`: 回调函数,调用`callback(false)`终止文件读取 |
| bind:after-read | 文件读取完成后 | `event.detail.file`: 当前读取的文件 |
| bind:oversize | 文件超出大小限制 | - |
| bind:click-preview | 点击预览图片 | `event.detail.index`: 点击图片的序号值 |
| bind:delete | 删除图片 | `event.detail.index`: 删除图片的序号值 |
================================================
FILE: packages/uploader/demo/index.json
================================================
{
"component": true,
"usingComponents": {
"van-button": "../../button/index",
"van-uploader": "../../uploader/index",
"demo-block": "../../../example/components/demo-block/index"
}
}
================================================
FILE: packages/uploader/demo/index.ts
================================================
import { VantComponent } from '../../common/component';
VantComponent({
data: {
fileList1: [],
fileList2: [
{ url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
{ url: 'https://img.yzcdn.cn/vant/tree.jpg' },
],
fileList3: [{ url: 'https://img.yzcdn.cn/vant/sand.jpg' }],
fileList4: [],
fileList5: [],
fileList6: [],
cloudPath: [],
fileList7: [],
fileList8: [
{
url: 'https://img.yzcdn.cn/vant/leaf.jpg',
status: 'uploading',
message: '上传中',
},
{
url: 'https://img.yzcdn.cn/vant/tree.jpg',
status: 'failed',
message: '上传失败',
},
],
},
methods: {
beforeRead(event) {
const { file, callback = () => {} } = event.detail;
if (file.url.indexOf('jpeg') < 0) {
wx.showToast({ title: '请选择jpg图片上传', icon: 'none' });
callback(false);
return;
}
callback(true);
},
afterRead(event) {
const { file, name } = event.detail;
console.log(JSON.stringify(file, null, 2));
const fileList = this.data[`fileList${name}`];
this.setData({ [`fileList${name}`]: fileList.concat(file) });
},
oversize() {
wx.showToast({ title: '文件超出大小限制', icon: 'none' });
},
delete(event) {
const { index, name } = event.detail;
const fileList = this.data[`fileList${name}`];
fileList.splice(index, 1);
this.setData({ [`fileList${name}`]: fileList });
},
clickPreview() {},
uploadToCloud() {
wx.cloud.init();
const { fileList6: fileList = [] } = this.data;
if (!fileList.length) {
wx.showToast({ title: '请选择图片', icon: 'none' });
} else {
const uploadTasks = fileList.map((file, index) =>
this.uploadFilePromise(`my-photo${index}.png`, file)
);
Promise.all(uploadTasks)
.then((data) => {
wx.showToast({ title: '上传成功', icon: 'none' });
const fileList = data.map((item) => ({ url: item.fileID }));
this.setData({
cloudPath: data as any,
fileList6: fileList as any,
});
})
.catch((e) => {
wx.showToast({ title: '上传失败', icon: 'none' });
console.log(e);
});
}
},
uploadFilePromise(fileName, chooseResult) {
return wx.cloud.uploadFile({
cloudPath: fileName,
filePath: chooseResult.path,
});
},
},
});
================================================
FILE: packages/uploader/demo/index.wxml
================================================
上传图片
上传至云存储
================================================
FILE: packages/uploader/index.json
================================================
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
================================================
FILE: packages/uploader/index.less
================================================
@import '../common/style/var.less';
.van-uploader {
position: relative;
display: inline-block;
&__wrapper {
display: flex;
flex-wrap: wrap;
}
&__slot:empty {
display: none;
}
&__slot:not(:empty) + &__upload {
display: none !important;
}
&__upload {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: var(--uploader-size, @uploader-size);
height: var(--uploader-size, @uploader-size);
margin: 0 @padding-xs @padding-xs 0;
background-color: var(
--uploader-upload-background-color,
@uploader-upload-background-color
);
&:active {
background-color: var(
--uploader-upload-active-color,
@uploader-upload-active-color
);
}
&-icon {
color: var(--uploader-icon-color, @uploader-icon-color);
font-size: var(--uploader-icon-size, @uploader-icon-size);
}
&-text {
margin-top: var(--padding-xs, @padding-xs);
color: var(--uploader-text-color, @uploader-text-color);
font-size: var(--uploader-text-font-size, @uploader-text-font-size);
}
&--disabled {
opacity: var(--uploader-disabled-opacity, @uploader-disabled-opacity);
}
}
&__preview {
position: relative;
cursor: pointer;
margin: 0 @padding-xs @padding-xs 0;
&-image {
display: block;
overflow: hidden;
width: var(--uploader-size, @uploader-size);
height: var(--uploader-size, @uploader-size);
}
&-delete {
position: absolute;
top: 0;
right: 0;
width: var(--uploader-delete-icon-size, @uploader-delete-icon-size);
height: var(--uploader-delete-icon-size, @uploader-delete-icon-size);
&::after {
position: absolute;
top: 0;
right: 0;
content: '';
width: var(--uploader-delete-icon-size, @uploader-delete-icon-size);
height: var(--uploader-delete-icon-size, @uploader-delete-icon-size);
background-color: var(
--uploader-delete-background-color,
@uploader-delete-background-color
);
border-radius: 0 0 0 12px;
}
&-icon {
position: absolute;
top: 0;
right: 0;
z-index: 1;
color: var(--uploader-delete-color, @uploader-delete-color);
font-size: var(--uploader-delete-icon-size, @uploader-delete-icon-size);
transform: scale(0.7) translate(10%, -10%);
}
}
}
&__file {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: var(--uploader-size, @uploader-size);
height: var(--uploader-size, @uploader-size);
background-color: var(
--uploader-file-background-color,
@uploader-file-background-color
);
&-icon {
color: var(--uploader-file-icon-color, @uploader-file-icon-color);
font-size: var(--uploader-file-icon-size, @uploader-file-icon-size);
}
&-name {
box-sizing: border-box;
width: 100%;
text-align: center;
margin-top: var(
--uploader-file-name-margin-top,
@uploader-file-name-margin-top
);
padding: var(--uploader-file-name-padding, @uploader-file-name-padding);
color: var(
--uploader-file-name-text-color,
@uploader-file-name-text-color
);
font-size: var(
--uploader-file-name-font-size,
@uploader-file-name-font-size
);
}
}
&__mask {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: @white;
background-color: var(
--uploader-mask-background-color,
@uploader-mask-background-color
);
&-icon {
font-size: var(--uploader-mask-icon-size, @uploader-mask-icon-size);
}
&-message {
margin-top: 6px;
padding: 0 var(--padding-base, @padding-base);
font-size: var(
--uploader-mask-message-font-size,
@uploader-mask-message-font-size
);
line-height: var(
--uploader-mask-message-line-height,
@uploader-mask-message-line-height
);
}
}
&__loading {
width: var(--uploader-loading-icon-size, @uploader-loading-icon-size);
height: var(--uploader-loading-icon-size, @uploader-loading-icon-size);
color: var(
--uploader-loading-icon-color,
@uploader-loading-icon-color
) !important;
}
}
================================================
FILE: packages/uploader/index.ts
================================================
import { VantComponent } from '../common/component';
import { isBoolean, isPromise } from '../common/validator';
import { imageProps, mediaProps, messageFileProps, videoProps } from './shared';
import { chooseFile, File, isImageFile, isVideoFile } from './utils';
VantComponent({
props: {
disabled: Boolean,
multiple: Boolean,
uploadText: String,
useBeforeRead: Boolean,
afterRead: null,
beforeRead: null,
previewSize: {
type: null,
value: 80,
},
name: {
type: null,
value: '',
},
accept: {
type: String,
value: 'image',
},
fileList: {
type: Array,
value: [],
observer: 'formatFileList',
},
maxSize: {
type: Number,
value: Number.MAX_VALUE,
},
maxCount: {
type: Number,
value: 100,
},
deletable: {
type: Boolean,
value: true,
},
showUpload: {
type: Boolean,
value: true,
},
previewImage: {
type: Boolean,
value: true,
},
previewFullImage: {
type: Boolean,
value: true,
},
videoFit: {
type: String,
value: 'contain',
},
imageFit: {
type: String,
value: 'scaleToFill',
},
uploadIcon: {
type: String,
value: 'photograph',
},
...imageProps,
...videoProps,
...mediaProps,
...messageFileProps,
},
data: {
lists: [] as File[],
isInCount: true,
},
methods: {
formatFileList() {
const { fileList = [], maxCount } = this.data;
const lists = fileList.map((item) => ({
...item,
isImage: isImageFile(item),
isVideo: isVideoFile(item),
deletable: isBoolean(item.deletable) ? item.deletable : true,
}));
this.setData({ lists, isInCount: lists.length < maxCount });
},
getDetail(index?: number) {
return {
name: this.data.name,
index: index == null ? this.data.fileList.length : index,
};
},
startUpload() {
const { maxCount, multiple, lists, disabled } = this.data;
if (disabled) return;
chooseFile({
...this.data,
maxCount: maxCount - lists.length,
})
.then((res) => {
this.onBeforeRead(multiple ? res : res[0]);
})
.catch((error) => {
this.$emit('error', error);
});
},
onBeforeRead(file: File) {
const { beforeRead, useBeforeRead } = this.data;
let res: boolean | Promise = true;
if (typeof beforeRead === 'function') {
res = beforeRead(file, this.getDetail());
}
if (useBeforeRead) {
res = new Promise((resolve, reject) => {
this.$emit('before-read', {
file,
...this.getDetail(),
callback: (ok: boolean) => {
ok ? resolve() : reject();
},
});
});
}
if (!res) {
return;
}
if (isPromise(res)) {
res.then((data: any) => this.onAfterRead(data || file));
} else {
this.onAfterRead(file);
}
},
onAfterRead(file) {
const { maxSize, afterRead } = this.data;
const oversize = Array.isArray(file)
? file.some((item) => item.size > maxSize)
: file.size > maxSize;
if (oversize) {
this.$emit('oversize', { file, ...this.getDetail() });
return;
}
if (typeof afterRead === 'function') {
afterRead(file, this.getDetail());
}
this.$emit('after-read', { file, ...this.getDetail() });
},
deleteItem(event) {
const { index } = event.currentTarget.dataset;
this.$emit('delete', {
...this.getDetail(index),
file: this.data.fileList[index],
});
},
onPreviewImage(event) {
if (!this.data.previewFullImage) return;
const { index } = event.currentTarget.dataset;
const { lists, showmenu } = this.data;
const item = lists[index];
wx.previewImage({
urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
current: item.url,
showmenu,
fail() {
wx.showToast({ title: '预览图片失败', icon: 'none' });
},
});
},
onPreviewVideo(event) {
if (!this.data.previewFullImage) return;
const { index } = event.currentTarget.dataset;
const { lists } = this.data as { lists: File[] };
const sources: WechatMiniprogram.MediaSource[] = [];
const current = lists.reduce((sum, cur, curIndex) => {
if (!isVideoFile(cur)) {
return sum;
}
sources.push({ ...cur, type: 'video' });
if (curIndex < index) {
sum++;
}
return sum;
}, 0);
wx.previewMedia({
sources,
current,
fail() {
wx.showToast({ title: '预览视频失败', icon: 'none' });
},
});
},
onPreviewFile(event: WechatMiniprogram.TouchEvent) {
if (!this.data.previewFile) return;
const { index } = event.currentTarget.dataset;
wx.openDocument({
filePath: this.data.lists[index].url,
showMenu: true,
});
},
onClickPreview(event) {
const { index } = event.currentTarget.dataset;
const item: File = this.data.lists[index];
this.$emit('click-preview', {
...item,
...this.getDetail(index),
});
},
},
});
================================================
FILE: packages/uploader/index.wxml
================================================
{{ item.name || item.url }}
{{ item.message }}
{{ uploadText }}
================================================
FILE: packages/uploader/index.wxs
================================================
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function sizeStyle(data) {
return "Array" === data.previewSize.constructor ? style({
width: addUnit(data.previewSize[0]),
height: addUnit(data.previewSize[1]),
}) : style({
width: addUnit(data.previewSize),
height: addUnit(data.previewSize),
});
}
module.exports = {
sizeStyle: sizeStyle,
};
================================================
FILE: packages/uploader/shared.ts
================================================
// props for image
export const imageProps = {
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
capture: {
type: Array,
value: ['album', 'camera'],
},
showmenu: {
type: Boolean,
value: true,
},
};
// props for video
export const videoProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
referrerPolicy: {
type: String,
value: 'no-referrer',
},
};
// props for media
export const mediaProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
mediaType: {
type: Array,
value: ['image', 'video', 'mix'],
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
};
// props for file
export const messageFileProps = {
extension: null,
previewFile: {
type: Boolean,
value: true,
},
};
================================================
FILE: packages/uploader/test/__snapshots__/demo.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render demo and match snapshot 1`] = `
基础用法
上传视频
文件预览
隐藏上传按钮
上传状态
上传中
上传失败
限制上传数量
自定义上传样式
上传图片
上传前校验
云存储上传
上传至云存储
`;
================================================
FILE: packages/uploader/test/demo.spec.ts
================================================
import path from 'path';
import simulate from 'miniprogram-simulate';
test('should render demo and match snapshot', () => {
const id = simulate.load(path.resolve(__dirname, '../demo/index'), {
rootPath: path.resolve(__dirname, '../../'),
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.toJSON()).toMatchSnapshot();
});
================================================
FILE: packages/uploader/utils.ts
================================================
import { pickExclude, isPC, isWxWork } from '../common/utils';
import { isImageUrl, isVideoUrl } from '../common/validator';
export interface File {
url: string; // 上传临时地址
size?: number; // 上传大小
name?: string;
type: string; // 上传类型
duration?: number; // 上传时间
time?: number; // 消息文件时间
isImage?: boolean;
isVideo?: boolean;
}
export function isImageFile(item: File): boolean {
if (item.isImage != null) {
return item.isImage;
}
if (item.type) {
return item.type === 'image';
}
if (item.url) {
return isImageUrl(item.url);
}
return false;
}
export function isVideoFile(item: File): boolean {
if (item.isVideo != null) {
return item.isVideo;
}
if (item.type) {
return item.type === 'video';
}
if (item.url) {
return isVideoUrl(item.url);
}
return false;
}
function formatImage(
res:
| WechatMiniprogram.ChooseMediaSuccessCallbackResult
| WechatMiniprogram.ChooseImageSuccessCallbackResult
): File[] {
return res.tempFiles.map((item) => ({
...pickExclude(item, ['path']),
type: 'image',
url: item.tempFilePath || item.path,
thumb: item.tempFilePath || item.path,
}));
}
function formatVideo(
res: WechatMiniprogram.ChooseVideoSuccessCallbackResult & Record
) {
return [
{
...pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg']),
type: 'video',
url: res.tempFilePath,
thumb: res.thumbTempFilePath,
},
];
}
function formatMedia(res: WechatMiniprogram.ChooseMediaSuccessCallbackResult) {
return res.tempFiles.map((item) => ({
...pickExclude(item, ['fileType', 'thumbTempFilePath', 'tempFilePath']),
type: item.fileType,
url: item.tempFilePath,
thumb:
item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath,
}));
}
function formatFile(
res: WechatMiniprogram.ChooseMessageFileSuccessCallbackResult
) {
return res.tempFiles.map((item) => ({
...pickExclude(item, ['path']),
url: item.path,
})) as File[];
}
export function chooseFile({
accept,
multiple,
capture,
compressed,
maxDuration,
sizeType,
camera,
maxCount,
mediaType,
extension,
}) {
return new Promise((resolve, reject) => {
switch (accept) {
case 'image':
if (isPC || isWxWork) {
wx.chooseImage({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
sizeType,
success: (res) => resolve(formatImage(res)),
fail: reject,
});
} else {
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType: ['image'],
sourceType: capture,
maxDuration,
sizeType,
camera,
success: (res) => resolve(formatImage(res)),
fail: reject,
});
}
break;
case 'media':
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
mediaType,
sourceType: capture,
maxDuration,
sizeType,
camera,
success: (res) => resolve(formatMedia(res)),
fail: reject,
});
break;
case 'video':
wx.chooseVideo({
sourceType: capture,
compressed,
maxDuration,
camera,
success: (res) => resolve(formatVideo(res)),
fail: reject,
});
break;
default:
wx.chooseMessageFile({
count: multiple ? maxCount : 1,
type: accept,
...(extension ? { extension } : {}),
success: (res) => resolve(formatFile(res)),
fail: reject,
});
break;
}
});
}
================================================
FILE: packages/wxs/add-unit.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
function addUnit(value) {
if (value == null) {
return undefined;
}
return REGEXP.test('' + value) ? value + 'px' : value;
}
module.exports = addUnit;
================================================
FILE: packages/wxs/array.wxs
================================================
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
================================================
FILE: packages/wxs/bem.wxs
================================================
/* eslint-disable */
var array = require('./array.wxs');
var object = require('./object.wxs');
var PREFIX = 'van-';
function join(name, mods) {
name = PREFIX + name;
mods = mods.map(function(mod) {
return name + '--' + mod;
});
mods.unshift(name);
return mods.join(' ');
}
function traversing(mods, conf) {
if (!conf) {
return;
}
if (typeof conf === 'string' || typeof conf === 'number') {
mods.push(conf);
} else if (array.isArray(conf)) {
conf.forEach(function(item) {
traversing(mods, item);
});
} else if (typeof conf === 'object') {
object.keys(conf).forEach(function(key) {
conf[key] && mods.push(key);
});
}
}
function bem(name, conf) {
var mods = [];
traversing(mods, conf);
return join(name, mods);
}
module.exports = bem;
================================================
FILE: packages/wxs/memoize.wxs
================================================
/**
* Simple memoize
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
*/
/* eslint-disable */
function isPrimitive(value) {
var type = typeof value;
return (
type === 'boolean' ||
type === 'number' ||
type === 'string' ||
type === 'undefined' ||
value === null
);
}
// mock simple fn.call in wxs
function call(fn, args) {
if (args.length === 2) {
return fn(args[0], args[1]);
}
if (args.length === 1) {
return fn(args[0]);
}
return fn();
}
function serializer(args) {
if (args.length === 1 && isPrimitive(args[0])) {
return args[0];
}
var obj = {};
for (var i = 0; i < args.length; i++) {
obj['key' + i] = args[i];
}
return JSON.stringify(obj);
}
function memoize(fn) {
var cache = {};
return function() {
var key = serializer(arguments);
if (cache[key] === undefined) {
cache[key] = call(fn, arguments);
}
return cache[key];
};
}
module.exports = memoize;
================================================
FILE: packages/wxs/object.wxs
================================================
/* eslint-disable */
var REGEXP = getRegExp('{|}|"', 'g');
function keys(obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[0];
});
}
module.exports.keys = keys;
================================================
FILE: packages/wxs/style.wxs
================================================
/* eslint-disable */
var object = require('./object.wxs');
var array = require('./array.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
return newWord;
}
function style(styles) {
if (array.isArray(styles)) {
return styles
.filter(function (item) {
return item != null && item !== '';
})
.map(function (item) {
return style(item);
})
.join(';');
}
if ('Object' === styles.constructor) {
return object
.keys(styles)
.filter(function (key) {
return styles[key] != null && styles[key] !== '';
})
.map(function (key) {
return [kebabCase(key), [styles[key]]].join(':');
})
.join(';');
}
return styles;
}
module.exports = style;
================================================
FILE: packages/wxs/utils.wxs
================================================
/* eslint-disable */
var bem = require('./bem.wxs');
var memoize = require('./memoize.wxs');
var addUnit = require('./add-unit.wxs');
module.exports = {
bem: memoize(bem),
memoize: memoize,
addUnit: addUnit
};
================================================
FILE: postcss.config.js
================================================
module.exports = {
plugins: {
autoprefixer: {},
cssnano: {
preset: 'default'
}
}
};
================================================
FILE: rsbuild.config.ts
================================================
export default {
server: {
proxy: {
'/vant/v2': 'https://vant-ui.github.io',
},
},
};
================================================
FILE: tsconfig.example.json
================================================
{
"extends": "./tsconfig.json",
"compilerOptions": {
"watch": true,
"outDir": "example/dist"
},
"exclude": ["packages/**/test/*"]
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"module": "es6",
"esModuleInterop": true,
"target": "es6",
"declaration": true,
"noImplicitAny": false,
"outDir": "dist",
"baseUrl": ".",
"sourceMap": false,
"strict": true,
"lib": ["ESNext", "dom"],
"types": ["@types/jest", "node", "miniprogram-api-typings"],
"paths": {
"definitions/*": ["./packages/definitions/*"]
},
"moduleResolution": "node",
"skipLibCheck": true
},
"include": ["packages/**/*"],
"exclude": ["packages/**/test/*", "packages/**/demo/*"]
}
================================================
FILE: tsconfig.lib.json
================================================
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es2015", "es2017", "dom"],
"declaration": false,
"outDir": "lib"
}
}
================================================
FILE: vant.config.mjs
================================================
export default {
name: 'vant-weapp',
build: {
srcDir: 'packages',
site: {
publicPath: '/vant-weapp/',
},
},
site: {
versions: [{ label: '0.x', link: '/vant-weapp/0.x' }],
title: 'Vant Weapp',
description: '轻量、可靠的小程序 UI 组件库',
logo: 'https://img.yzcdn.cn/vant/logo.png',
simulator: {
url: '/vant/v2/mobile.html?weapp=1',
routeMapper: (path) => {
const map = {
'/common': '/style',
'/transition': '/style',
};
return `/zh-CN${map[path] || path}`;
},
syncPathFromSimulator: false,
},
icpLicense: {
text: '浙ICP备2021036118号',
link: 'https://beian.miit.gov.cn/',
},
headHtml: `
`,
links: [
{
logo: 'https://img.yzcdn.cn/vant/vant-o.svg',
url: '/vant/',
},
{
logo: 'https://b.yzcdn.cn/vant/logo/github.svg',
url: 'https://github.com/youzan/vant-weapp',
},
],
baiduAnalytics: {
seed: 'af5d41bc4e446e76665dbe3ec18d55c3',
},
nav: [
{
title: '开发指南',
items: [
{
path: 'home',
title: '介绍',
},
{
path: 'quickstart',
title: '快速上手',
},
{
path: 'changelog',
title: '更新日志',
},
{
path: 'custom-style',
title: '样式覆盖',
},
{
path: 'theme',
title: '定制主题',
},
],
},
{
title: '基础组件',
items: [
{
path: 'button',
title: 'Button 按钮',
},
{
path: 'cell',
title: 'Cell 单元格',
},
{
path: 'config-provider',
title: 'ConfigProvider 全局配置',
},
{
path: 'icon',
title: 'Icon 图标',
},
{
path: 'image',
title: 'Image 图片',
},
{
path: 'col',
title: 'Layout 布局',
},
{
path: 'popup',
title: 'Popup 弹出层',
},
{
path: 'common',
title: 'Style 内置样式',
},
{
path: 'toast',
title: 'Toast 轻提示',
},
{
path: 'transition',
title: 'transition 动画',
},
],
},
{
title: '表单组件',
items: [
{
path: 'calendar',
title: 'Calendar 日历',
},
{
path: 'cascader',
title: 'Cascader 级联选择',
},
{
path: 'checkbox',
title: 'Checkbox 复选框',
},
{
path: 'datetime-picker',
title: 'DatetimePicker 时间选择',
},
{
path: 'field',
title: 'Field 输入框',
},
{
path: 'picker',
title: 'Picker 选择器',
},
{
path: 'radio',
title: 'Radio 单选框',
},
{
path: 'rate',
title: 'Rate 评分',
},
{
path: 'search',
title: 'Search 搜索',
},
{
path: 'slider',
title: 'Slider 滑块',
},
{
path: 'stepper',
title: 'Stepper 步进器',
},
{
path: 'switch',
title: 'Switch 开关',
},
{
path: 'uploader',
title: 'Uploader 文件上传',
},
],
},
{
title: '反馈组件',
items: [
{
path: 'action-sheet',
title: 'ActionSheet 动作面板',
},
{
path: 'dialog',
title: 'Dialog 弹出框',
},
{
path: 'dropdown-menu',
title: 'DropdownMenu 下拉菜单',
},
{
path: 'loading',
title: 'Loading 加载',
},
{
path: 'notify',
title: 'Notify 消息通知',
},
{
path: 'overlay',
title: 'Overlay 遮罩层',
},
{
path: 'share-sheet',
title: 'ShareSheet 分享面板',
},
{
path: 'swipe-cell',
title: 'SwipeCell 滑动单元格',
},
],
},
{
title: '展示组件',
items: [
{
path: 'circle',
title: 'Circle 环形进度条',
},
{
path: 'collapse',
title: 'Collapse 折叠面板',
},
{
path: 'count-down',
title: 'CountDown 倒计时',
},
{
path: 'divider',
title: 'Divider 分割线',
},
{
path: 'empty',
title: 'Empty 空状态',
},
{
path: 'notice-bar',
title: 'NoticeBar 通知栏',
},
{
path: 'progress',
title: 'Progress 进度条',
},
{
path: 'skeleton',
title: 'Skeleton 骨架屏',
},
{
path: 'steps',
title: 'Steps 步骤条',
},
{
path: 'sticky',
title: 'Sticky 粘性布局',
},
{
path: 'tag',
title: 'Tag 标签',
},
],
},
{
title: '导航组件',
items: [
{
path: 'grid',
title: 'Grid 宫格',
},
{
path: 'index-bar',
title: 'IndexBar 索引栏',
},
{
path: 'nav-bar',
title: 'NavBar 导航栏',
},
{
path: 'sidebar',
title: 'Sidebar 侧边导航',
},
{
path: 'tab',
title: 'Tab 标签页',
},
{
path: 'tabbar',
title: 'Tabbar 标签栏',
},
{
path: 'tree-select',
title: 'TreeSelect 分类选择',
},
],
},
{
title: '业务组件',
items: [
{
path: 'area',
title: 'Area 省市区选择',
},
{
path: 'card',
title: 'Card 商品卡片',
},
{
path: 'submit-bar',
title: 'SubmitBar 提交订单栏',
},
{
path: 'goods-action',
title: 'GoodsAction 商品导航',
},
],
},
{
title: '废弃',
items: [
{
path: 'panel',
title: 'Panel 面板',
},
],
},
],
},
};