├── .commitlintrc.js
├── .eslintignore
├── .eslintrc.js
├── .github
└── workflows
│ ├── codecov.yml
│ └── docs.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .npmrc
├── .prettierrc.js
├── .release-it.json
├── .stylelintignore
├── .stylelintrc.js
├── LICENSE.txt
├── README.md
├── README_ZH.md
├── package.json
├── packages
├── cli
│ ├── cli.js
│ ├── gitClone.js
│ ├── index.js
│ └── package.json
├── components
│ ├── index.ts
│ ├── package.json
│ ├── scripts
│ │ ├── build
│ │ │ └── index.ts
│ │ ├── publish
│ │ │ └── index.ts
│ │ └── utils
│ │ │ ├── delpath.ts
│ │ │ ├── paths.ts
│ │ │ ├── run.ts
│ │ │ └── tools.ts
│ ├── src
│ │ ├── actionsheet
│ │ │ ├── __test__
│ │ │ │ ├── actionSheetFn.test.ts
│ │ │ │ └── actionsheet.test.tsx
│ │ │ ├── actionSheet.ts
│ │ │ ├── actionSheet.vue
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── alert
│ │ │ ├── __test__
│ │ │ │ ├── alert.test.ts
│ │ │ │ └── alertFn.test.ts
│ │ │ ├── alert.ts
│ │ │ ├── alert.vue
│ │ │ └── index.ts
│ │ ├── article
│ │ │ ├── __test__
│ │ │ │ └── article.test.ts
│ │ │ ├── article.vue
│ │ │ └── index.ts
│ │ ├── badge
│ │ │ ├── __test__
│ │ │ │ └── badge.test.ts
│ │ │ ├── badge.less
│ │ │ ├── badge.vue
│ │ │ └── index.ts
│ │ ├── button
│ │ │ ├── __test__
│ │ │ │ └── button.test.ts
│ │ │ ├── button.vue
│ │ │ └── index.ts
│ │ ├── cells
│ │ │ ├── __test__
│ │ │ │ ├── cell.test.ts
│ │ │ │ └── cells.test.ts
│ │ │ ├── cell.vue
│ │ │ ├── cells.vue
│ │ │ └── index.ts
│ │ ├── common
│ │ │ └── styles.less
│ │ ├── components.d.ts
│ │ ├── datePicker
│ │ │ ├── __test__
│ │ │ │ └── datePicker.test.ts
│ │ │ ├── datePicker.less
│ │ │ ├── datePicker.vue
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── dialog
│ │ │ ├── __test__
│ │ │ │ ├── dialog.test.tsx
│ │ │ │ └── dialogFn.test.ts
│ │ │ ├── dialog.ts
│ │ │ ├── dialog.vue
│ │ │ └── index.ts
│ │ ├── flex
│ │ │ ├── __test__
│ │ │ │ └── flex.test.ts
│ │ │ ├── flex.vue
│ │ │ ├── flexItem.vue
│ │ │ └── index.ts
│ │ ├── footer
│ │ │ ├── __test__
│ │ │ │ └── footer.test.ts
│ │ │ ├── footer.vue
│ │ │ ├── footerLink.vue
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── __test__
│ │ │ │ └── form.test.tsx
│ │ │ ├── constants.ts
│ │ │ ├── form.less
│ │ │ ├── form.vue
│ │ │ ├── formGroup.vue
│ │ │ ├── formItem.vue
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── gallery
│ │ │ ├── __test__
│ │ │ │ ├── gallery.test.ts
│ │ │ │ └── galleryFn.test.ts
│ │ │ ├── gallery.less
│ │ │ ├── gallery.ts
│ │ │ ├── gallery.vue
│ │ │ └── index.ts
│ │ ├── grid
│ │ │ ├── __test__
│ │ │ │ ├── grid.test.ts
│ │ │ │ └── grids.test.ts
│ │ │ ├── grid.vue
│ │ │ ├── grids.vue
│ │ │ └── index.ts
│ │ ├── halfScreenDialog
│ │ │ ├── __test__
│ │ │ │ └── halfscreenDialog.test.ts
│ │ │ ├── halfScreenDialog.vue
│ │ │ └── index.ts
│ │ ├── hooks
│ │ │ └── useSlideDialog.ts
│ │ ├── icon
│ │ │ ├── __test__
│ │ │ │ └── icon.test.ts
│ │ │ ├── icon.vue
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── input
│ │ │ ├── __test__
│ │ │ │ └── input.test.ts
│ │ │ ├── index.ts
│ │ │ ├── input.less
│ │ │ └── input.vue
│ │ ├── loading
│ │ │ ├── __test__
│ │ │ │ └── loading.test.ts
│ │ │ ├── index.ts
│ │ │ ├── loading.less
│ │ │ └── loading.vue
│ │ ├── loadmore
│ │ │ ├── __test__
│ │ │ │ └── loadmore.test.ts
│ │ │ ├── index.ts
│ │ │ └── loadmore.vue
│ │ ├── mask
│ │ │ ├── __test__
│ │ │ │ └── mask.test.ts
│ │ │ ├── index.ts
│ │ │ └── mask.vue
│ │ ├── mediabox
│ │ │ ├── __test__
│ │ │ │ └── mediabox.test.ts
│ │ │ ├── index.ts
│ │ │ └── mediaBox.vue
│ │ ├── msg
│ │ │ ├── __test__
│ │ │ │ └── msg.test.ts
│ │ │ ├── index.ts
│ │ │ └── msg.vue
│ │ ├── navbar
│ │ │ ├── __test__
│ │ │ │ └── navbar.test.tsx
│ │ │ ├── constant.ts
│ │ │ ├── index.ts
│ │ │ ├── navbar.vue
│ │ │ ├── navbarItem.vue
│ │ │ └── types.ts
│ │ ├── panel
│ │ │ ├── __test__
│ │ │ │ └── panel.test.ts
│ │ │ ├── index.ts
│ │ │ └── panel.vue
│ │ ├── picker
│ │ │ ├── __test__
│ │ │ │ └── picker.test.ts
│ │ │ ├── index.ts
│ │ │ ├── picker.less
│ │ │ ├── picker.vue
│ │ │ └── types.ts
│ │ ├── preview
│ │ │ ├── __test__
│ │ │ │ ├── preview.test.ts
│ │ │ │ ├── previewBtn.test.ts
│ │ │ │ └── previewItem.test.ts
│ │ │ ├── index.ts
│ │ │ ├── preview.vue
│ │ │ ├── previewBtn.vue
│ │ │ └── previewItem.vue
│ │ ├── progress
│ │ │ ├── __test__
│ │ │ │ └── progress.test.ts
│ │ │ ├── index.ts
│ │ │ ├── progress.less
│ │ │ └── progress.vue
│ │ ├── searchbar
│ │ │ ├── __test__
│ │ │ │ └── searchbar.test.ts
│ │ │ ├── index.ts
│ │ │ └── searchbar.vue
│ │ ├── slider
│ │ │ ├── __test__
│ │ │ │ └── slider.test.ts
│ │ │ ├── index.ts
│ │ │ └── slider.vue
│ │ ├── steps
│ │ │ ├── __test__
│ │ │ │ ├── stepItem.test.ts
│ │ │ │ └── steps.test.tsx
│ │ │ ├── constant.ts
│ │ │ ├── index.ts
│ │ │ ├── stepItem.vue
│ │ │ └── steps.vue
│ │ ├── switch
│ │ │ ├── index.ts
│ │ │ ├── switch.vue
│ │ │ └── test
│ │ │ │ └── switch.test.ts
│ │ ├── tabbar
│ │ │ ├── __test__
│ │ │ │ └── tabbar.test.tsx
│ │ │ ├── constant.ts
│ │ │ ├── index.ts
│ │ │ ├── tabbar.vue
│ │ │ ├── tabbarItem.vue
│ │ │ └── types.ts
│ │ ├── textarea
│ │ │ ├── __test__
│ │ │ │ └── textarea.test.ts
│ │ │ ├── index.ts
│ │ │ ├── textarea.less
│ │ │ └── textarea.vue
│ │ ├── timePicker
│ │ │ ├── __test__
│ │ │ │ └── timePicker.test.ts
│ │ │ ├── cron.ts
│ │ │ ├── index.ts
│ │ │ ├── timePicker.less
│ │ │ ├── timePicker.vue
│ │ │ └── types.ts
│ │ ├── toast
│ │ │ ├── __test__
│ │ │ │ ├── toast.test.ts
│ │ │ │ └── toastFn.test.ts
│ │ │ ├── index.ts
│ │ │ ├── toast.ts
│ │ │ └── toast.vue
│ │ ├── types
│ │ │ └── index.ts
│ │ ├── uploader
│ │ │ ├── __test__
│ │ │ │ └── uploader.test.ts
│ │ │ ├── compress.ts
│ │ │ ├── filehash.ts
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ └── useAccept.ts
│ │ │ ├── index.ts
│ │ │ ├── tools.ts
│ │ │ ├── types.ts
│ │ │ ├── upload.ts
│ │ │ ├── uploader.less
│ │ │ └── uploader.vue
│ │ ├── utils
│ │ │ ├── exports.ts
│ │ │ ├── index.ts
│ │ │ ├── pickerManager.ts
│ │ │ ├── shortid.ts
│ │ │ ├── theme.ts
│ │ │ └── withInstall.ts
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ └── vite.config.ts
└── vue-weui
│ ├── README.md
│ ├── README_ZH.md
│ └── package.json
├── play
├── index.html
├── package.json
├── src
│ ├── App.vue
│ └── main.ts
├── vite.config.ts
└── vue-shim.d.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── site
├── docs
│ ├── .vitepress
│ │ ├── components
│ │ │ ├── ActionSheet.vue
│ │ │ ├── Alert.vue
│ │ │ ├── DatePicker.vue
│ │ │ ├── Dialog.vue
│ │ │ ├── DynamicLayout.vue
│ │ │ ├── FrameDefaultLayout.vue
│ │ │ ├── Gallery.vue
│ │ │ ├── HalfScreenDialog.vue
│ │ │ ├── NavBar.vue
│ │ │ ├── Picker.vue
│ │ │ ├── SlideHalfScreen.vue
│ │ │ ├── TabBar.vue
│ │ │ ├── TimePicker.vue
│ │ │ ├── Toast.vue
│ │ │ ├── Uploader.vue
│ │ │ └── ValidateForm.vue
│ │ ├── config.js
│ │ └── theme
│ │ │ └── index.js
│ ├── components
│ │ ├── actionsheet
│ │ │ └── index.md
│ │ ├── alert
│ │ │ └── index.md
│ │ ├── article
│ │ │ └── index.md
│ │ ├── badge
│ │ │ └── index.md
│ │ ├── button
│ │ │ └── index.md
│ │ ├── cells
│ │ │ └── index.md
│ │ ├── datePicker
│ │ │ └── index.md
│ │ ├── dialog
│ │ │ └── index.md
│ │ ├── flex
│ │ │ └── index.md
│ │ ├── footer
│ │ │ └── index.md
│ │ ├── form
│ │ │ └── index.md
│ │ ├── gallery
│ │ │ └── index.md
│ │ ├── grid
│ │ │ └── index.md
│ │ ├── halfscreen-dialog
│ │ │ └── index.md
│ │ ├── icon
│ │ │ └── index.md
│ │ ├── input
│ │ │ └── index.md
│ │ ├── loading
│ │ │ └── index.md
│ │ ├── loadmore
│ │ │ └── index.md
│ │ ├── mediabox
│ │ │ └── index.md
│ │ ├── msg
│ │ │ └── index.md
│ │ ├── navbar
│ │ │ └── index.md
│ │ ├── panel
│ │ │ └── index.md
│ │ ├── picker
│ │ │ └── index.md
│ │ ├── preview
│ │ │ └── index.md
│ │ ├── progress
│ │ │ └── index.md
│ │ ├── searchbar
│ │ │ └── index.md
│ │ ├── slider
│ │ │ └── index.md
│ │ ├── steps
│ │ │ └── index.md
│ │ ├── switch
│ │ │ └── index.md
│ │ ├── tabbar
│ │ │ └── index.md
│ │ ├── textarea
│ │ │ └── index.md
│ │ ├── timePicker
│ │ │ └── index.md
│ │ ├── toast
│ │ │ └── index.md
│ │ └── uploader
│ │ │ └── index.md
│ ├── guide
│ │ └── index.md
│ └── index.md
└── package.json
└── tsconfig.json
/.commitlintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'type-enum': [
5 | 2,
6 | 'always',
7 | [
8 | 'feat',
9 | 'fix',
10 | 'docs',
11 | 'style',
12 | 'refactor',
13 | 'test',
14 | 'build',
15 | 'revert',
16 | 'merge',
17 | ],
18 | ],
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **.d.ts
2 | /packages/vue-weui
3 | dist
4 | node_modules
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true,
5 | node: true
6 | },
7 | extends: [
8 | 'eslint:recommended',
9 | 'plugin:vue/vue3-essential',
10 | 'plugin:@typescript-eslint/recommended',
11 | 'prettier',
12 | 'plugin:prettier/recommended'
13 | ],
14 | globals: {
15 | defineOptions: true
16 | },
17 | parser: 'vue-eslint-parser',
18 | parserOptions: {
19 | ecmaVersion: 'latest',
20 | sourceType: 'module',
21 | parser: '@typescript-eslint/parser'
22 | },
23 | plugins: ['vue', '@typescript-eslint'],
24 | rules: {
25 | 'prettier/prettier': 'error',
26 | '@typescript-eslint/ban-ts-comment': 'off',
27 | 'vue/multi-word-component-names': 'off',
28 | '@typescript-eslint/no-explicit-any': 'off'
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/.github/workflows/codecov.yml:
--------------------------------------------------------------------------------
1 | # .github/workflows/main.yml
2 | # This is a basic workflow to help you get started with Actions
3 |
4 | name: Coverage
5 |
6 | # Controls when the action will run. Triggers the workflow on push or pull request
7 | # events but only for the master branch
8 | on:
9 | push:
10 | branches: [master]
11 | pull_request:
12 | branches: [master]
13 |
14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
15 | jobs:
16 | CodeCov:
17 | # The type of runner that the job will run on
18 | runs-on: ubuntu-latest
19 | # Steps represent a sequence of tasks that will be executed as part of the job
20 | steps:
21 | - uses: actions/checkout@v4
22 | - uses: pnpm/action-setup@v2.1.0
23 | with:
24 | version: 7.2.1
25 | - name: Install modules
26 | run: pnpm install
27 | - name: Run Test Coverage
28 | run: pnpm run coverage:weui
29 | - name: Upload coverage to Codecov
30 | uses: codecov/codecov-action@v4.0.1
31 | with:
32 | directory: packages/components/coverage
33 | token: ${{ secrets.CODECOV_TOKEN }}
34 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | # 将静态内容部署到 GitHub Pages 的简易工作流程
2 | name: Deploy static content to Pages
3 |
4 | on:
5 | push:
6 | branches: ['master']
7 | workflow_dispatch:
8 |
9 | # 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages。
10 | permissions:
11 | contents: read
12 | pages: write
13 | id-token: write
14 |
15 | # 允许一个并发的部署
16 | concurrency:
17 | group: 'pages'
18 | cancel-in-progress: true
19 |
20 | jobs:
21 | deploy:
22 | environment:
23 | name: github-pages
24 | url: ${{ steps.deployment.outputs.page_url }}
25 | runs-on: ubuntu-latest
26 | steps:
27 | - name: Checkout
28 | uses: actions/checkout@v4
29 | - uses: pnpm/action-setup@v2.1.0
30 | with:
31 | version: 7.2.1
32 | - name: Install dependencies
33 | run: pnpm install
34 | - name: Build weui
35 | run: pnpm run build:weui
36 | - name: Build
37 | run: pnpm run docs:build
38 | - name: Setup Pages
39 | uses: actions/configure-pages@v3
40 | - name: Upload artifact
41 | uses: actions/upload-pages-artifact@v2
42 | with:
43 | # Upload dist repository
44 | path: './site/docs/.vitepress/dist'
45 | - name: Deploy to GitHub Pages
46 | id: deployment
47 | uses: actions/deploy-pages@v2
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific stuff:
2 | .idea/
3 | # CMake
4 | cmake-build-debug/
5 |
6 | # IntelliJ
7 | out/
8 |
9 | # mpeltonen/sbt-idea plugin
10 | .idea_modules/
11 |
12 |
13 | node_modules/
14 |
15 | # Typescript v1 declaration files
16 | typings/
17 |
18 | # JetBrains Rider
19 | .idea/
20 | *.sln.iml
21 |
22 | # CodeRush
23 | .cr/
24 |
25 | ### macOS template
26 | # General
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | =======
35 | # Local
36 | .env
37 | dist
38 | logs
39 | package-lock.json
40 | yarn-error.log
41 | .vscode/
42 | .cache/
43 | cache
44 | es
45 | lib
46 | coverage
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx --no-install commitlint --edit $1
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | pnpm run lint:script && pnpm run lint:style
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
2 | strict-peer-dependencies=false
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | printWidth: 80,
3 | tabWidth: 2,
4 | useTabs: false,
5 | singleQuote: true,
6 | semi: true,
7 | trailingComma: 'none',
8 | bracketSpacing: true
9 | };
10 |
--------------------------------------------------------------------------------
/.release-it.json:
--------------------------------------------------------------------------------
1 | {
2 | "git": {
3 | "commitMessage": "chore(release): v${version}"
4 | }
5 | }
--------------------------------------------------------------------------------
/.stylelintignore:
--------------------------------------------------------------------------------
1 | **.d.ts
2 | /packages/vue-weui
3 | dist
4 | node_modules
--------------------------------------------------------------------------------
/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: ['stylelint-prettier'],
3 | extends: [
4 | 'stylelint-config-standard',
5 | 'stylelint-config-recommended-less',
6 | 'stylelint-config-recess-order',
7 | 'stylelint-config-prettier',
8 | 'stylelint-prettier/recommended'
9 | ],
10 | rules: {
11 | 'prettier/prettier': true,
12 | "custom-property-pattern": null,
13 | "selector-class-pattern": "^[a-z][a-z0-9_-]+$",
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [中文版](./README_ZH.md) | English
2 |
3 |
4 |
5 |
6 |
7 | # vue-weui
8 |
9 | [](https://github.com/bangtz/vue-weui/tree/master/packages/vue-weui)
10 | [](https://pkg-size.dev/vue-weui-next)
11 | [](https://codecov.io/gh/bangtz/vue-weui)
12 | [](https://vuejs.org/)
13 | 
14 |
15 | Weui style UI component library developed and implemented based on Vue3.
16 |
17 | ## Quick start
18 |
19 | Before starting to use it, you need to introduce the weui style file into the html file. ([WeUI](https://github.com/Tencent/weui))
20 |
21 | ```html
22 |
23 | ```
24 |
25 | Install component package.
26 |
27 | ```bash
28 | npm install vue-weui-next
29 |
30 | # or
31 |
32 | yarn install vue-weui-next
33 | ```
34 |
35 | Complete introduction.
36 |
37 | ```ts
38 | import { createApp } from 'vue';
39 | import App from './App.vue';
40 | import Weui from 'vue-weui-next';
41 |
42 | const app = createApp(App);
43 | app.use(Weui);
44 | app.mount('#app');
45 | ```
46 |
47 | Manual import.
48 |
49 | ```html
50 |
51 | button
52 |
53 |
59 | ```
60 |
61 | ## Contact
62 |
63 | Currently, the content of the basic components of weui has been improved. We will continue to update and improve the components related to the weui form form in the future. If you are interested in this project, you are welcome to contribute.
64 |
65 | If you find any code problems, or there are new components or capabilities that you hope to add, please feel free to submit an issue. The author will update and fix them in time. Thank you.
66 |
67 | >  *bangtz* (Add please note vue-weui)
68 |
69 | # License
70 |
71 | [Apache License 2.0](LICENSE)
72 |
--------------------------------------------------------------------------------
/README_ZH.md:
--------------------------------------------------------------------------------
1 | 中文版 | [English](./README.md)
2 |
3 |
4 |
5 |
6 |
7 | # vue-weui
8 |
9 | [](https://github.com/bangtz/vue-weui/tree/master/packages/vue-weui)
10 | [](https://pkg-size.dev/vue-weui-next)
11 | [](https://codecov.io/gh/bangtz/vue-weui)
12 | [](https://vuejs.org/)
13 | 
14 |
15 | 基于 Vue3 开发实现的 WeUI 风格UI组件库。
16 |
17 | ## 快速开始
18 |
19 | 在开始使用之前,需要在html文件中引入weui样式文件。([WeUI](https://github.com/Tencent/weui))
20 |
21 | ```html
22 |
23 | ```
24 |
25 | 安装组件包
26 |
27 | ```bash
28 | npm install vue-weui-next
29 |
30 | # or
31 |
32 | yarn install vue-weui-next
33 | ```
34 |
35 | 完整引入
36 |
37 | ```ts
38 | import { createApp } from 'vue';
39 | import App from './App.vue';
40 | import Weui from 'vue-weui-next';
41 |
42 | const app = createApp(App);
43 | app.use(Weui);
44 | app.mount('#app');
45 | ```
46 |
47 | 手动引入
48 |
49 | ```html
50 |
51 | button
52 |
53 |
59 | ```
60 |
61 | ## 联系
62 |
63 | 当前完善了weui基础组件内容,后续将持续更新完善weui form表单相关的组件,如果对此项目感兴趣,欢迎一起贡献。
64 |
65 | 如果您发现任何代码问题,或者有希望新增的组件或能力,请随时提交问题。作者会及时更新和修复。谢谢
66 |
67 | >  *bangtz* (Add please note vue-weui)
68 |
69 | # License
70 |
71 | [Apache License 2.0](LICENSE)
72 |
--------------------------------------------------------------------------------
/packages/cli/cli.js:
--------------------------------------------------------------------------------
1 | import commandLineArgs from 'command-line-args';
2 | import commandLineUsage from 'command-line-usage';
3 | import { readFile } from 'fs/promises';
4 | import prompts from 'prompts';
5 | import gitClone from './gitClone.js';
6 |
7 | const pkg = JSON.parse(
8 | await readFile(new URL('./package.json', import.meta.url))
9 | );
10 |
11 | // 配置命令参数
12 | const optionDefinitions = [
13 | { name: 'version', alias: 'v', type: Boolean },
14 | { name: 'help', alias: 'h', type: Boolean }
15 | ];
16 | const options = commandLineArgs(optionDefinitions);
17 | const helpSections = [
18 | {
19 | header: 'create-vue-weui',
20 | content: '一个快速生成vue-weui组件库开发环境的脚手架'
21 | },
22 | {
23 | header: 'Options',
24 | optionList: [
25 | {
26 | name: 'version',
27 | alias: 'v',
28 | typeLabel: '{underline boolean}',
29 | description: '版本号'
30 | },
31 | {
32 | name: 'help',
33 | alias: 'h',
34 | typeLabel: '{underline boolean}',
35 | description: '帮助'
36 | }
37 | ]
38 | }
39 | ];
40 |
41 | if (options.version) {
42 | console.log(`v${pkg.version}`);
43 | }
44 | if (options.help) {
45 | console.log(commandLineUsage(helpSections));
46 | }
47 |
48 | const promptsOptions = [
49 | {
50 | type: 'text',
51 | name: 'name',
52 | message: '请输入项目名称'
53 | },
54 | {
55 | type: 'select',
56 | name: 'template',
57 | message: '请选择一个模版',
58 | choices: [{ title: 'vue-weui', value: 1 }]
59 | }
60 | ];
61 |
62 | const remoteList = {
63 | 1: 'https://github.com/webChen725/test-vercel.git'
64 | };
65 | const getUserInfo = async () => {
66 | const res = await prompts(promptsOptions);
67 | if (!res.name || !res.template) {
68 | return;
69 | }
70 | gitClone(`direct:${remoteList[res.template]}`, res.name, {
71 | clone: true
72 | });
73 | };
74 |
75 | getUserInfo();
76 |
--------------------------------------------------------------------------------
/packages/cli/gitClone.js:
--------------------------------------------------------------------------------
1 | import download from 'download-git-repo';
2 | import chalk from 'chalk';
3 | import ora from 'ora';
4 |
5 | export default (remote, name, options) => {
6 | const downSpinner = ora('开始下载模版...').start();
7 | return new Promise((resolve, reject) => {
8 | download(remote, name, options, (err) => {
9 | if (err) {
10 | downSpinner.fail();
11 | console.log('err', chalk.red(err));
12 | reject(err);
13 | return;
14 | }
15 | downSpinner.succeed(chalk.green('模版下载成功!'));
16 | resolve();
17 | });
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/packages/cli/index.js:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 |
3 | import './cli.js';
4 |
--------------------------------------------------------------------------------
/packages/cli/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-vue-weui",
3 | "version": "1.0.0",
4 | "description": "",
5 | "type": "module",
6 | "bin": "index.js",
7 | "keywords": [],
8 | "author": "",
9 | "license": "MIT",
10 | "dependencies": {
11 | "chalk": "^5.3.0",
12 | "command-line-args": "^5.2.1",
13 | "command-line-usage": "^7.0.1",
14 | "download-git-repo": "^3.0.2",
15 | "ora": "^7.0.1",
16 | "prompts": "^2.4.2"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/components/index.ts:
--------------------------------------------------------------------------------
1 | import * as components from './src';
2 | export * from './src';
3 | import { App } from 'vue';
4 |
5 | export default {
6 | install: (app: App) => {
7 | for (const c in components) {
8 | app.use((components as any)[c]);
9 | }
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/packages/components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-weui-component",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.ts",
6 | "scripts": {
7 | "build": "vite build",
8 | "test": "vitest",
9 | "coverage": "vitest run --coverage"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "@types/lodash": "^4.17.0",
16 | "@vitejs/plugin-vue-jsx": "^3.1.0",
17 | "@vitest/coverage-v8": "^1.1.0"
18 | },
19 | "dependencies": {
20 | "async-validator": "^4.2.5",
21 | "dayjs": "^1.11.10",
22 | "lodash": "^4.17.21"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/components/scripts/publish/index.ts:
--------------------------------------------------------------------------------
1 | import { series } from 'gulp';
2 | import run from '../utils/run';
3 | import { pkgPath } from '../utils/paths';
4 |
5 | export const publishComponent = async () => {
6 | run('release-it', `${pkgPath}/vue-weui`);
7 | };
8 |
9 | export default series(async () => publishComponent());
10 |
--------------------------------------------------------------------------------
/packages/components/scripts/utils/delpath.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import { resolve } from 'path';
3 | import { pkgPath } from './paths';
4 |
5 | // 需要保留的文件
6 | const stayFile = ['package.json', 'README.md'];
7 |
8 | const delPath = async (path: string) => {
9 | let files: string[] = [];
10 |
11 | if (fs.existsSync(path)) {
12 | files = fs.readdirSync(path);
13 |
14 | files.forEach(async (file) => {
15 | const curPath = resolve(path, file);
16 |
17 | if (fs.statSync(curPath).isDirectory()) {
18 | if (file !== 'node_modules') {
19 | await delPath(curPath);
20 | }
21 | } else {
22 | if (!stayFile.includes(file)) {
23 | fs.unlinkSync(curPath);
24 | }
25 | }
26 | });
27 |
28 | if (path !== `${pkgPath}/vue-weui`) {
29 | fs.rmdirSync(path);
30 | }
31 | }
32 | };
33 |
34 | export default delPath;
35 |
--------------------------------------------------------------------------------
/packages/components/scripts/utils/paths.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 |
3 | // 组件库根目录
4 | export const componentPath = resolve(__dirname, '../../');
5 | // pkg 根目录
6 | export const pkgPath = resolve(__dirname, '../../../');
7 | export const rootPath = resolve(__dirname, '../../../../');
8 |
--------------------------------------------------------------------------------
/packages/components/scripts/utils/run.ts:
--------------------------------------------------------------------------------
1 | import { spawn } from 'child_process';
2 |
3 | export default async (command: string, path: string) => {
4 | const [cmd, ...args] = command.split(' ');
5 | return new Promise((resolve) => {
6 | const app = spawn(cmd, args, {
7 | cwd: path,
8 | stdio: 'inherit',
9 | shell: true
10 | });
11 | app.on('close', resolve);
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/packages/components/scripts/utils/tools.ts:
--------------------------------------------------------------------------------
1 | export function toPascalCase(str: string) {
2 | return str.replace(/(^\w|_+\w)/g, function (match) {
3 | return match.toUpperCase().replace(/_+/g, '');
4 | });
5 | }
6 |
--------------------------------------------------------------------------------
/packages/components/src/actionsheet/__test__/actionSheetFn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { actionSheet } from '../actionSheet';
3 |
4 | describe('weui-action-sheet-fn', () => {
5 | it('actionSheet api mount', () => {
6 | const menus = [{ label: '菜单1' }, { label: '菜单1' }];
7 | const actions = [{ label: '取消' }];
8 | const fn = vi.fn();
9 | const result = actionSheet({
10 | title: '标题',
11 | actions,
12 | menus,
13 | onClose: fn
14 | });
15 | expect(typeof result).toBe('function');
16 | expect(result()).toBe(undefined);
17 | expect(fn).toHaveBeenCalled();
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/components/src/actionsheet/actionSheet.ts:
--------------------------------------------------------------------------------
1 | import { h, render } from 'vue';
2 | import ActionSheet from './actionSheet.vue';
3 | import { shortid } from '../utils';
4 | import type { ActionSheetMenuOrActions } from './types';
5 |
6 | interface ActionSheetOptions {
7 | title?: string;
8 | menus?: ActionSheetMenuOrActions[];
9 | actions?: ActionSheetMenuOrActions[];
10 | onClick?: (item: ActionSheetMenuOrActions) => void;
11 | onClose?: () => void;
12 | }
13 |
14 | export function actionSheet(options: ActionSheetOptions) {
15 | const { title, menus, actions, onClick, onClose } = options;
16 |
17 | const actionSheetFragment = document.createElement('div');
18 | actionSheetFragment.classList.add(`weui-actionsheet_${shortid(16)}`);
19 | document.body.appendChild(actionSheetFragment);
20 | const closeSheet = () => {
21 | render(null, actionSheetFragment);
22 | document.body.removeChild(actionSheetFragment);
23 | onClose?.();
24 | };
25 |
26 | const vnode = h(ActionSheet, {
27 | title,
28 | menus,
29 | actions,
30 | onClick,
31 | onClose: closeSheet,
32 | modelValue: true
33 | });
34 |
35 | render(vnode, actionSheetFragment);
36 |
37 | return closeSheet;
38 | }
39 |
--------------------------------------------------------------------------------
/packages/components/src/actionsheet/index.ts:
--------------------------------------------------------------------------------
1 | import _ActionSheet from './actionSheet.vue';
2 | import { actionSheet } from './actionSheet';
3 | import { withInstall } from '../utils';
4 |
5 | type ActionSheetType = typeof _ActionSheet & {
6 | actionSheet: typeof actionSheet;
7 | };
8 | export const ActionSheet = withInstall(
9 | _ActionSheet as ActionSheetType
10 | );
11 | ActionSheet.actionSheet = actionSheet;
12 | export default ActionSheet;
13 |
--------------------------------------------------------------------------------
/packages/components/src/actionsheet/types.ts:
--------------------------------------------------------------------------------
1 | export type ActionSheetMenuOrActions = T & {
2 | label: string;
3 | classNames?: string;
4 | [key: string]: any;
5 | };
6 |
--------------------------------------------------------------------------------
/packages/components/src/alert/__test__/alertFn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { alert } from '../alert';
3 |
4 | const sleep = (duration: number) =>
5 | new Promise((resolve) => setTimeout(resolve, duration));
6 | describe('weui-alert-fn', () => {
7 | it('alert api mount', () => {
8 | const text = 'alert text';
9 | const fn = vi.fn();
10 | const result = alert({
11 | text,
12 | showClose: true,
13 | showIcon: true,
14 | type: 'warn-primary',
15 | onClose: fn,
16 | duration: 0
17 | });
18 | expect(typeof result).toBe('function');
19 | expect(result()).toBe(undefined);
20 | expect(fn).toHaveBeenCalled();
21 | });
22 |
23 | it('alert timeout unmount', async () => {
24 | const text = 'alert text';
25 | const fn = vi.fn();
26 | alert({
27 | text,
28 | showClose: true,
29 | showIcon: true,
30 | type: 'warn-primary',
31 | onClose: fn,
32 | duration: 200
33 | });
34 | await sleep(200);
35 | expect(fn).toHaveBeenCalled();
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/components/src/alert/alert.ts:
--------------------------------------------------------------------------------
1 | import { h, render } from 'vue';
2 | import Alert from './alert.vue';
3 | import { shortid } from '../utils';
4 |
5 | interface AlertOptions {
6 | text: string;
7 | type?: 'warn-primary' | 'warn' | 'default' | 'tips-primary' | 'tips';
8 | showIcon?: boolean;
9 | showClose?: boolean;
10 | duration?: number;
11 | onClose?: () => void;
12 | }
13 | export function alert(options: AlertOptions) {
14 | const { text, showIcon, showClose, type, duration = 3000, onClose } = options;
15 |
16 | let timer: NodeJS.Timeout;
17 | const alertFragment = document.createElement('div');
18 | alertFragment.classList.add(`weui-alert_${shortid(16)}`);
19 | document.body.appendChild(alertFragment);
20 |
21 | const closeAlert = () => {
22 | render(null, alertFragment);
23 | document.body.removeChild(alertFragment);
24 | timer && clearTimeout(timer);
25 | onClose?.();
26 | };
27 |
28 | const vnode = h(Alert, {
29 | text,
30 | type,
31 | showClose,
32 | showIcon,
33 | modelValue: true,
34 | onClose: closeAlert
35 | });
36 |
37 | render(vnode, alertFragment);
38 |
39 | if (duration) {
40 | timer = setTimeout(closeAlert, duration);
41 | }
42 |
43 | return closeAlert;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/components/src/alert/alert.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
27 |
28 |
71 |
--------------------------------------------------------------------------------
/packages/components/src/alert/index.ts:
--------------------------------------------------------------------------------
1 | import _Alert from './alert.vue';
2 | import { withInstall } from '../utils';
3 | import { alert } from './alert';
4 |
5 | type AlertType = typeof _Alert & {
6 | alert: typeof alert;
7 | };
8 | export const Alert = withInstall(_Alert as AlertType);
9 | Alert.alert = alert;
10 | export default Alert;
11 |
--------------------------------------------------------------------------------
/packages/components/src/article/__test__/article.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Article from '../article.vue';
4 |
5 | describe('weui-article', () => {
6 | it('render default slot', () => {
7 | const articleText = '这是文章内容';
8 | const wrapper = mount(Article, {
9 | slots: {
10 | default: articleText
11 | }
12 | });
13 | expect(wrapper.text()).toBe(articleText);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/packages/components/src/article/article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/packages/components/src/article/index.ts:
--------------------------------------------------------------------------------
1 | import _Article from './article.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Article = withInstall(_Article);
5 | export default Article;
6 |
--------------------------------------------------------------------------------
/packages/components/src/badge/__test__/badge.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Badge from '../badge.vue';
4 |
5 | describe('weui-badge', () => {
6 | it('render value content', () => {
7 | const wrapper = mount(Badge, {
8 | props: {
9 | value: '50'
10 | }
11 | });
12 | expect(wrapper.find('#b1_n1').text()).toBe('50');
13 | });
14 |
15 | it('render value max handle', async () => {
16 | const wrapperMin = mount(Badge, {
17 | props: {
18 | value: 49,
19 | max: 49
20 | }
21 | });
22 | expect(wrapperMin.find('#b1_n1').text()).toBe('49');
23 | const wrapperMax = mount(Badge, {
24 | props: {
25 | value: 50,
26 | max: 49
27 | }
28 | });
29 | expect(wrapperMax.find('#b1_n1').text()).toBe('49+');
30 | });
31 |
32 | it('render string value max handle', () => {
33 | const wrapper = mount(Badge, {
34 | props: {
35 | value: '50',
36 | max: 49
37 | }
38 | });
39 | expect(wrapper.find('#b1_n1').text()).toBe('50');
40 | });
41 |
42 | it('render value dot', () => {
43 | const wrapper = mount(Badge, {
44 | props: {
45 | dot: true,
46 | value: 50
47 | }
48 | });
49 | expect(wrapper.find('#b1_n1').classes()).toContain('weui-badge_dot');
50 | });
51 |
52 | it('custom render value', () => {
53 | const wrapper = mount(Badge, {
54 | slots: {
55 | default: 'custom'
56 | }
57 | });
58 | expect(wrapper.find('#b1_n1').text()).toBe('custom');
59 | });
60 |
61 | it('custom render content', () => {
62 | const wrapper = mount(Badge, {
63 | slots: {
64 | content: 'content'
65 | }
66 | });
67 | expect(wrapper.classes()).toContain('weui-badge-content');
68 | expect(wrapper.text()).toBe('content');
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/packages/components/src/badge/badge.less:
--------------------------------------------------------------------------------
1 | .weui-badge-content {
2 | position: relative;
3 | display: inline-block;
4 |
5 | .weui-badge {
6 | position: absolute;
7 | top: -0.4em;
8 | right: -0.4em;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/components/src/badge/badge.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
15 | {{ badgeValue }}
16 |
17 |
18 |
19 |
20 |
21 |
51 |
--------------------------------------------------------------------------------
/packages/components/src/badge/index.ts:
--------------------------------------------------------------------------------
1 | import _Badge from './badge.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Badge = withInstall(_Badge);
5 | export default Badge;
6 |
--------------------------------------------------------------------------------
/packages/components/src/button/__test__/button.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Button from '../button.vue';
4 |
5 | describe('weui-button', () => {
6 | it('should render solt', () => {
7 | const wrapper = mount(Button, {
8 | slots: {
9 | default: 'vue-weui'
10 | }
11 | });
12 | expect(wrapper.text()).toContain('vue-weui');
13 | });
14 | it('should type class', () => {
15 | const types: any[] = ['default', 'primary', 'warn'];
16 | for (const type of types) {
17 | const wrapper = mount(Button, {
18 | props: { type }
19 | });
20 | expect(wrapper.classes()).toContain(`weui-btn_${type}`);
21 | }
22 | });
23 | it('should size class', () => {
24 | const sizes: any[] = ['medium', 'mini'];
25 | for (const size of sizes) {
26 | const wrapper = mount(Button, {
27 | props: { size }
28 | });
29 | expect(wrapper.classes()).toContain(`weui-btn_${size}`);
30 | }
31 | });
32 | it('should disabled', async () => {
33 | const wrapper = mount(Button, {
34 | props: {
35 | disabled: true
36 | }
37 | });
38 | expect(wrapper.classes()).toContain(`weui-btn_disabled`);
39 | // 点击事件不可触发
40 | await wrapper.trigger('click');
41 | expect(wrapper.emitted()).toEqual({});
42 | expect(wrapper.props().disabled).toBe(true);
43 | });
44 | it('should render loading', () => {
45 | const wrapper = mount(Button, {
46 | props: {
47 | loading: true
48 | }
49 | });
50 | expect(wrapper.classes()).toContain('weui-btn_loading');
51 | expect(wrapper.find('i.weui-mask-loading').exists()).toBe(true);
52 | });
53 |
54 | it('click event emit', async () => {
55 | const wrapper = mount(Button, {
56 | slots: {
57 | default: 'button'
58 | }
59 | });
60 | // 点击事件不可触发
61 | await wrapper.trigger('click');
62 | expect(wrapper.emitted()).toHaveProperty('click');
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/packages/components/src/button/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
49 |
--------------------------------------------------------------------------------
/packages/components/src/button/index.ts:
--------------------------------------------------------------------------------
1 | import _Button from './button.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Button = withInstall(_Button);
5 | export default Button;
6 |
--------------------------------------------------------------------------------
/packages/components/src/cells/__test__/cell.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Cell from '../cell.vue';
4 |
5 | describe('weui-cell', () => {
6 | it('render cell props', () => {
7 | const wrapper = mount(Cell, {
8 | props: {
9 | arrow: true,
10 | link: true
11 | }
12 | });
13 | expect(wrapper.classes()).toContain('weui-cell_access');
14 | expect(wrapper.classes()).toContain('weui-cell_link');
15 | });
16 |
17 | it('render slots', () => {
18 | const defaultSlotText = 'default slot contet';
19 | const hdSlotText = 'hd slot contet';
20 | const ftSlotText = 'ft slot contet';
21 | const wrapper = mount(Cell, {
22 | slots: {
23 | default: defaultSlotText,
24 | hd: hdSlotText,
25 | ft: ftSlotText
26 | }
27 | });
28 | expect(wrapper.find('.weui-cell__bd').text()).toBe(defaultSlotText);
29 | expect(wrapper.find('.weui-cell__hd').text()).toBe(hdSlotText);
30 | expect(wrapper.find('.weui-cell__ft').text()).toBe(ftSlotText);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/packages/components/src/cells/__test__/cells.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Cells from '../cells.vue';
4 |
5 | describe('weui-cells', () => {
6 | it('render cells title', () => {
7 | const titleText = 'cells标题';
8 | const wrapper = mount(Cells, {
9 | props: {
10 | title: titleText
11 | }
12 | });
13 | expect(wrapper.find('.weui-cells__title').text()).toBe(titleText);
14 | });
15 |
16 | it('render default slot', () => {
17 | const slotText = 'custom slot contet';
18 | const wrapper = mount(Cells, {
19 | slots: {
20 | default: slotText
21 | }
22 | });
23 | expect(wrapper.find('.weui-cells').text()).toBe(slotText);
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/packages/components/src/cells/cell.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
36 |
--------------------------------------------------------------------------------
/packages/components/src/cells/cells.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
23 |
--------------------------------------------------------------------------------
/packages/components/src/cells/index.ts:
--------------------------------------------------------------------------------
1 | import _Cells from './cells.vue';
2 | import _Cell from './cell.vue';
3 | import { withInstall } from '../utils';
4 |
5 | type CellsType = typeof _Cells & {
6 | Cell: typeof _Cell;
7 | };
8 | export const Cells = withInstall(_Cells as CellsType);
9 | export const Cell = withInstall(_Cell);
10 | Cells.Cell = Cell;
11 | export default Cells;
12 |
--------------------------------------------------------------------------------
/packages/components/src/common/styles.less:
--------------------------------------------------------------------------------
1 | /* region fade */
2 | .weui-fade-enter-active,
3 | .weui-fade-leave-active {
4 | transition: opacity 0.3s;
5 | }
6 |
7 | /* vue3 */
8 | .weui-fade-enter-from,
9 | .weui-fade-leave-to {
10 | opacity: 0 !important;
11 | }
12 |
13 | .weui-fade-enter-to,
14 | .weui-fade-leave-from {
15 | opacity: 1 !important;
16 | }
17 |
18 | /* endregion fade */
19 |
20 | /* region slide-up */
21 | .weui-slide-up-enter-active,
22 | .weui-slide-up-leave-active {
23 | transition: transform 0.3s;
24 | }
25 |
26 | /* vue3 */
27 | .weui-slide-up-enter-from,
28 | .weui-slide-up-leave-to {
29 | transform: translateY(100%) !important;
30 | }
31 |
32 | .weui-slide-up-enter-to,
33 | .weui-slide-up-leave-from {
34 | transform: translateY(0) !important;
35 | }
36 |
37 | /* endregion slide-up */
38 |
39 | /* region slide-down */
40 | .weui-slide-down-enter-active,
41 | .weui-slide-down-leave-active {
42 | transition: transform 0.3s;
43 | }
44 |
45 | /* vue3 */
46 | .weui-slide-down-enter-from,
47 | .weui-slide-down-leave-to {
48 | transform: translateY(-100%) !important;
49 | }
50 |
51 | .weui-slide-down-enter-to,
52 | .weui-slide-down-leave-from {
53 | transform: translateY(0) !important;
54 | }
55 |
56 | /* endregion slide-down */
57 |
--------------------------------------------------------------------------------
/packages/components/src/components.d.ts:
--------------------------------------------------------------------------------
1 | import * as components from '.';
2 |
3 | declare module '@vue/runtime-core' {
4 | export interface GlobalComponents {
5 | weuiIcon: typeof components.Icon;
6 | weuiButton: typeof components.Button;
7 | weuiSlider: typeof components.Slider;
8 | weuiLoading: typeof components.Loading;
9 | weuiProgress: typeof components.Progress;
10 | weuiBadge: typeof components.Badge;
11 | weuiArticle: typeof components.Article;
12 | weuiFlex: typeof components.Flex;
13 | weuiFlexItem: typeof components.FlexItem;
14 | weuiFooter: typeof components.Footer;
15 | weuiFooterLink: typeof components.FooterLink;
16 | weuiGrids: typeof components.Grids;
17 | weuiGrid: typeof components.Grid;
18 | weuiLoadmore: typeof components.Loadmore;
19 | weuiCells: typeof components.Cells;
20 | weuiCell: typeof components.Cell;
21 | weuiToast: typeof components.Toast;
22 | weuiPanel: typeof components.Panel;
23 | weuiMediaBox: typeof components.MediaBox;
24 | weuiPreview: typeof components.Preview;
25 | weuiPreviewItem: typeof components.PreviewItem;
26 | weuiPreviewBtn: typeof components.PreviewBtn;
27 | weuiSteps: typeof components.Steps;
28 | weuiStepItem: typeof components.StepItem;
29 | weuiMask: typeof components.Mask;
30 | weuiActionSheet: typeof components.ActionSheet;
31 | weuiDialog: typeof components.Dialog;
32 | weuiHalfScreenDialog: typeof components.HalfScreenDialog;
33 | weuiMsg: typeof components.Msg;
34 | weuiAlert: typeof components.Alert;
35 | weuiNavbar: typeof components.NavBar;
36 | weuiNavbarItem: typeof components.NavBarItem;
37 | weuiTabbar: typeof components.TabBar;
38 | weuiTabbarItem: typeof components.TabBarItem;
39 | weuiSearchbar: typeof components.SearchaBar;
40 | weuiForm: typeof components.Form;
41 | weuiFormGroup: typeof components.FormGroup;
42 | weuiFormItem: typeof components.FormItem;
43 | weuiInput: typeof components.Input;
44 | weuiPicker: typeof components.Picker;
45 | weuiDatePicker: typeof components.DatePicker;
46 | weuiTimePicker: typeof components.TimePicker;
47 | weuiTextarea: typeof components.Textarea;
48 | weuiSwitch: typeof components.Switch;
49 | weuiUploader: typeof components.Uploader;
50 | weuiGallery: typeof components.Gallery;
51 | }
52 | }
53 | export {};
54 |
--------------------------------------------------------------------------------
/packages/components/src/datePicker/__test__/datePicker.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import DatePicker from '../datePicker.vue';
4 | import dayjs from 'dayjs';
5 |
6 | describe('weui-date-picker', () => {
7 | it('render datePicker', async () => {
8 | const wrapper = mount(DatePicker, {
9 | props: {
10 | modelValue: undefined,
11 | placeholder: 'placeholder',
12 | start: new Date('2021-1-1'),
13 | end: new Date('2025-1-1')
14 | }
15 | });
16 | expect(wrapper.find('.weui-date-value').text()).toBe('placeholder');
17 |
18 | // 触发打开选择器
19 | wrapper.trigger('click');
20 | await wrapper.vm.$nextTick();
21 | expect(document.querySelector('.weui-date-picker-selector')).not.toBeNull();
22 |
23 | // 触发picker事件
24 | const pickerGroup = document.querySelector(
25 | '.weui-date-picker-selector .weui-picker__group'
26 | );
27 | if (pickerGroup) {
28 | pickerGroup.scrollTop = 56;
29 | pickerGroup.dispatchEvent(new Event('scroll'));
30 | await wrapper.vm.$nextTick();
31 | expect(wrapper.emitted()).toHaveProperty('selectChange');
32 | // 触发confirm事件
33 | const confirmBtn = document.querySelector(
34 | '.weui-date-picker-selector .weui-picker__btn'
35 | );
36 | confirmBtn?.dispatchEvent(new Event('click'));
37 | expect(wrapper.emitted()).toHaveProperty('change');
38 | expect(wrapper.emitted()).toHaveProperty('update:modelValue');
39 | }
40 | });
41 |
42 | it('render datePicker disabled', async () => {
43 | const wrapper = mount(DatePicker, {
44 | props: {
45 | modelValue: new Date(),
46 | placeholder: 'placeholder',
47 | disabled: true
48 | }
49 | });
50 | expect(wrapper.find('.weui-date-value').text()).toBe(
51 | dayjs().format('YYYY-MM-DD')
52 | );
53 | expect(wrapper.classes()).toContain('weui-picker_diabled');
54 |
55 | wrapper.trigger('click');
56 | });
57 |
58 | it('render datePicker formatter', async () => {
59 | const wrapper = mount(DatePicker, {
60 | props: {
61 | modelValue: new Date(),
62 | placeholder: 'placeholder',
63 | formatter: 'YYYY年MM月DD日'
64 | }
65 | });
66 | expect(wrapper.find('.weui-date-value').text()).toBe(
67 | dayjs().format('YYYY年MM月DD日')
68 | );
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/packages/components/src/datePicker/datePicker.less:
--------------------------------------------------------------------------------
1 | .weui-date-picker-wrapper {
2 | align-items: center;
3 | width: 100%;
4 |
5 | .weui-date-value {
6 | flex: 1;
7 | padding-left: 0;
8 | }
9 |
10 | &.weui-picker_diabled .weui-date-value {
11 | color: var(--weui-FG-1);
12 | }
13 |
14 | &.weui-picker_placeholder .weui-date-value {
15 | color: var(--weui-FG-2);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/components/src/datePicker/index.ts:
--------------------------------------------------------------------------------
1 | import _DatePicker from './datePicker.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const DatePicker = withInstall(_DatePicker);
5 | export default DatePicker;
6 |
--------------------------------------------------------------------------------
/packages/components/src/datePicker/types.ts:
--------------------------------------------------------------------------------
1 | export interface DateItem {
2 | label: string;
3 | value: number;
4 | children?: DateItem[];
5 | }
6 |
--------------------------------------------------------------------------------
/packages/components/src/dialog/__test__/dialogFn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { dialog } from '../dialog';
3 |
4 | describe('weui-dialog-fn', () => {
5 | it('actionSheet api mount', () => {
6 | const cancelFn = vi.fn();
7 | const okFn = vi.fn();
8 | const result = dialog({
9 | title: '标题',
10 | desc: '描述',
11 | onCancel: cancelFn,
12 | onOk: okFn
13 | });
14 | expect(typeof result).toBe('function');
15 | expect(result()).toBe(undefined);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/packages/components/src/dialog/dialog.ts:
--------------------------------------------------------------------------------
1 | import { h, render } from 'vue';
2 | import Dialog from './dialog.vue';
3 | import { shortid } from '../utils';
4 |
5 | interface DialogOptions {
6 | title?: string;
7 | desc?: string;
8 | cancelText?: string;
9 | okText?: string;
10 | onCancel?: () => void;
11 | onOk?: () => void;
12 | }
13 | export function dialog(options: DialogOptions) {
14 | const { title, desc, cancelText, okText, onCancel, onOk } = options;
15 |
16 | const dialogFragment = document.createElement('div');
17 | dialogFragment.classList.add(`weui-dialog_${shortid(16)}`);
18 | document.body.appendChild(dialogFragment);
19 | const closeDialog = () => {
20 | render(null, dialogFragment);
21 | document.body.removeChild(dialogFragment);
22 | };
23 | const eventHandlerFactory = (handler?: () => void) => {
24 | return () => {
25 | closeDialog();
26 | handler?.();
27 | };
28 | };
29 |
30 | const vnode = h(Dialog, {
31 | title,
32 | desc,
33 | cancelText,
34 | okText,
35 | modelValue: true,
36 | onCancel: eventHandlerFactory(onCancel),
37 | onOk: eventHandlerFactory(onOk)
38 | });
39 |
40 | render(vnode, dialogFragment);
41 |
42 | return closeDialog;
43 | }
44 |
--------------------------------------------------------------------------------
/packages/components/src/dialog/index.ts:
--------------------------------------------------------------------------------
1 | import _Dialog from './dialog.vue';
2 | import { dialog } from './dialog';
3 | import { withInstall } from '../utils';
4 |
5 | type DialogType = typeof _Dialog & {
6 | dialog: typeof dialog;
7 | };
8 | export const Dialog = withInstall(_Dialog as DialogType);
9 | Dialog.dialog = dialog;
10 | export default Dialog;
11 |
--------------------------------------------------------------------------------
/packages/components/src/flex/__test__/flex.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Flex from '../flex.vue';
4 | import FlexItem from '../flexItem.vue';
5 |
6 | describe('weui-flex', () => {
7 | it('render flex slot', () => {
8 | const flexText = 'Flex';
9 | const wrapper = mount(Flex, {
10 | slots: {
11 | default: flexText
12 | }
13 | });
14 | expect(wrapper.text()).toBe(flexText);
15 | });
16 | it('render flex gap', () => {
17 | const wrapperNumber = mount(Flex, {
18 | props: {
19 | gap: 20
20 | }
21 | });
22 | expect((wrapperNumber.element as HTMLElement).style.gap).toBe('20px');
23 | const wrapperTuple = mount(Flex, {
24 | props: {
25 | gap: [10, 20]
26 | }
27 | });
28 | expect((wrapperTuple.element as HTMLElement).style.gap).toBe('10px 20px');
29 | });
30 | });
31 |
32 | describe('weui-flex-item', () => {
33 | it('render flex-item slot', () => {
34 | const flexText = 'Flex-item';
35 | const wrapper = mount(FlexItem, {
36 | slots: {
37 | default: flexText
38 | }
39 | });
40 | expect(wrapper.text()).toBe(flexText);
41 | });
42 | it('render flex-item flex', () => {
43 | const wrapper = mount(FlexItem, {
44 | props: {
45 | flex: 2
46 | }
47 | });
48 | expect((wrapper.element as HTMLElement).style.flex).toBe('2 1 0%');
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/packages/components/src/flex/flex.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
28 |
--------------------------------------------------------------------------------
/packages/components/src/flex/flexItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/packages/components/src/flex/index.ts:
--------------------------------------------------------------------------------
1 | import _Flex from './flex.vue';
2 | import _FlexItem from './flexItem.vue';
3 | import { withInstall } from '../utils';
4 |
5 | export const Flex = withInstall(_Flex);
6 | export const FlexItem = withInstall(_FlexItem);
7 | Flex.FlexItem = FlexItem;
8 | export default Flex;
9 |
--------------------------------------------------------------------------------
/packages/components/src/footer/__test__/footer.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Footer from '../footer.vue';
4 | import FooterLink from '../footerLink.vue';
5 |
6 | describe('weui-footer', () => {
7 | it('render footer text', () => {
8 | const footerText = 'Flex';
9 | const wrapper = mount(Footer, {
10 | props: {
11 | text: footerText
12 | }
13 | });
14 | expect(wrapper.find('.weui-footer__text').text()).toBe(footerText);
15 | });
16 | it('render footer default slot', () => {
17 | const footerSlot = 'custom text';
18 | const wrapper = mount(Footer, {
19 | slots: {
20 | default: footerSlot
21 | }
22 | });
23 | expect(wrapper.find('.weui-footer__text').text()).toBe(footerSlot);
24 | });
25 | it('render footer links slot', () => {
26 | const footerSlot = 'custom links';
27 | const wrapper = mount(Footer, {
28 | slots: {
29 | links: footerSlot
30 | }
31 | });
32 | expect(wrapper.find('.weui-footer__links').exists()).toBe(true);
33 | expect(wrapper.find('.weui-footer__links').text()).toBe(footerSlot);
34 | });
35 | });
36 |
37 | describe('weui-footer-link', () => {
38 | it('render footer link props', () => {
39 | const link = 'test link';
40 | const target = '_blank';
41 | const wrapper = mount(FooterLink, {
42 | props: {
43 | link,
44 | target
45 | }
46 | });
47 | expect(wrapper.attributes().href).toBe(link);
48 | expect(wrapper.attributes().target).toBe(target);
49 | });
50 | it('render footer slot', () => {
51 | const linkSlot = 'link slot';
52 | const wrapper = mount(FooterLink, {
53 | slots: {
54 | default: linkSlot
55 | }
56 | });
57 | expect(wrapper.text()).toBe(linkSlot);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/packages/components/src/footer/footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
26 |
--------------------------------------------------------------------------------
/packages/components/src/footer/footerLink.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
21 |
--------------------------------------------------------------------------------
/packages/components/src/footer/index.ts:
--------------------------------------------------------------------------------
1 | import _Footer from './footer.vue';
2 | import _FooterLink from './footerLink.vue';
3 | import { withInstall } from '../utils';
4 |
5 | export const Footer = withInstall(_Footer);
6 | export const FooterLink = withInstall(_FooterLink);
7 | Footer.FooterLink = FooterLink;
8 | export default Footer;
9 |
--------------------------------------------------------------------------------
/packages/components/src/form/constants.ts:
--------------------------------------------------------------------------------
1 | export const REGISTER_NAME_LIST = Symbol('REGISTER_NAME_LIST');
2 | export const REGISTER_RULE = Symbol('REGISTER_RULE');
3 | export const VALIDATE_ERRORS = Symbol('VALIDATE_ERRORS');
4 | export const VALIDATE_SHOW_WARN = Symbol('VALIDATE_SHOW_WARN');
5 | export const REMOVE_VALIDATE_ERROR = Symbol('REMOVE_VALIDATE_ERROR');
6 | export const FORM_MODEL_DATA = Symbol('FORM_MODEL_DATA');
7 |
--------------------------------------------------------------------------------
/packages/components/src/form/form.less:
--------------------------------------------------------------------------------
1 | .weui-form.weui-form-noheader {
2 | padding-top: 0;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/components/src/form/formGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
24 |
--------------------------------------------------------------------------------
/packages/components/src/form/formItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ label }}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
74 |
--------------------------------------------------------------------------------
/packages/components/src/form/index.ts:
--------------------------------------------------------------------------------
1 | import _Form from './form.vue';
2 | import _FormGroup from './formGroup.vue';
3 | import _FormItem from './formItem.vue';
4 | import { withInstall } from '../utils';
5 | export * from './types';
6 |
7 | type FormType = typeof _Form & {
8 | FormGroup: typeof _FormGroup;
9 | FormItem: typeof _FormItem;
10 | };
11 | export const Form = withInstall(_Form as FormType);
12 | export const FormGroup = withInstall(_FormGroup);
13 | export const FormItem = withInstall(_FormItem);
14 | Form.FormGroup = FormGroup;
15 | Form.FormItem = FormItem;
16 | export default Form;
17 |
--------------------------------------------------------------------------------
/packages/components/src/form/types.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | Values,
3 | RuleItem as _RuleItem,
4 | Rule as _Rule,
5 | Rules as _Rules
6 | } from 'async-validator';
7 |
8 | export type Rules = _Rules;
9 | export type Rule = _Rule;
10 | export type RuleItem = _RuleItem;
11 | export interface FormInstance {
12 | validate: (nameList?: string[]) => Promise;
13 | resetFields: (nameList?: string[]) => void;
14 | clearValidate: (nameList?: string[]) => void;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/components/src/gallery/__test__/galleryFn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { gallery } from '../gallery';
3 | import userEvent from '@testing-library/user-event';
4 |
5 | describe('weui-gallery function', () => {
6 | it('gallery api mount', async () => {
7 | const deleteFn = vi.fn();
8 | const closeFn = vi.fn();
9 | const changeFn = vi.fn();
10 | const close = gallery({
11 | current: 0,
12 | urls: ['test1.jpg', 'test2.jpg', 'test3.jpg'],
13 | onDelete: deleteFn,
14 | onClose: closeFn,
15 | onChange: changeFn
16 | });
17 |
18 | const wrapper = document.body.querySelector(
19 | '.weui-gallery__teleport-container'
20 | );
21 | const deleteBtn = wrapper?.querySelector('.weui-gallery__del');
22 | deleteBtn && (await userEvent.click(deleteBtn));
23 | expect(deleteFn).toBeCalled();
24 |
25 | const closeBtn = wrapper?.querySelector('.gallery-close__btn');
26 | closeBtn && (await userEvent.click(closeBtn));
27 | expect(closeFn).toBeCalled();
28 |
29 | const threshold = window.innerWidth / 3;
30 | const imageWrap = wrapper?.querySelector('.weui-gallery__img-wrap');
31 | imageWrap?.dispatchEvent(
32 | new TouchEvent('touchstart', {
33 | changedTouches: [{ clientX: 50 + threshold + 20, clientY: 100 } as any]
34 | })
35 | );
36 | imageWrap?.dispatchEvent(
37 | new TouchEvent('touchmove', {
38 | changedTouches: [{ clientX: 50, clientY: 100 } as any]
39 | })
40 | );
41 | imageWrap?.dispatchEvent(
42 | new TouchEvent('touchend', {
43 | changedTouches: [{ clientX: 50, clientY: 100 } as any]
44 | })
45 | );
46 | expect(changeFn).toBeCalled();
47 | expect(close()).toBe(undefined);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/packages/components/src/gallery/gallery.less:
--------------------------------------------------------------------------------
1 | .weui-gallery__container {
2 | z-index: 100000;
3 | display: flex;
4 | flex-direction: column;
5 |
6 | .weui-gallery__header {
7 | position: relative;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | width: 100%;
12 | height: 60px;
13 | font-size: 15px;
14 | color: var(--weui-WHITE);
15 |
16 | .gallery-close__btn {
17 | position: absolute;
18 | right: 16px;
19 | display: flex;
20 | align-items: center;
21 | justify-content: center;
22 | width: 24px;
23 | height: 24px;
24 |
25 | .weui-icon-close {
26 | width: 16px;
27 | height: 16px;
28 | }
29 | }
30 | }
31 |
32 | .weui-gallery__img-wrap {
33 | display: flex;
34 | flex: 1;
35 | touch-action: none;
36 | transform: translateX(0);
37 |
38 | .weui-gallery__img {
39 | position: relative;
40 | display: flex;
41 | flex-shrink: 0;
42 | align-items: center;
43 | justify-content: center;
44 | width: 100%;
45 | height: 100%;
46 | padding: 44px 0;
47 |
48 | > img {
49 | max-width: 100%;
50 | max-height: 100%;
51 | object-fit: contain;
52 | }
53 | }
54 | }
55 |
56 | .weui-gallery__opr {
57 | position: relative;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/packages/components/src/gallery/gallery.ts:
--------------------------------------------------------------------------------
1 | import { h, render } from 'vue';
2 | import Gallery from './gallery.vue';
3 | import { shortid } from '../utils';
4 |
5 | interface GalleryOptions {
6 | urls: string[];
7 | current?: number;
8 | onChange?: (current: number) => void;
9 | onDelete?: (index: number, url: string) => void;
10 | onClose?: () => void;
11 | }
12 | export function gallery(options: GalleryOptions) {
13 | const { urls, current, onChange, onDelete, onClose } = options;
14 |
15 | const vnode = h(Gallery, {
16 | urls,
17 | initialIndex: current,
18 | visible: true,
19 | onChange,
20 | onDelete,
21 | onClose
22 | });
23 | const galleryFragment = document.createElement('div');
24 | galleryFragment.classList.add(`weui-gallery__teleport-container`);
25 | galleryFragment.classList.add(`weui-gallery_${shortid(16)}`);
26 | document.body.appendChild(galleryFragment);
27 | render(vnode, galleryFragment);
28 |
29 | const closeGallery = () => {
30 | render(null, galleryFragment);
31 | document.body.removeChild(galleryFragment);
32 | };
33 |
34 | return closeGallery;
35 | }
36 |
--------------------------------------------------------------------------------
/packages/components/src/gallery/index.ts:
--------------------------------------------------------------------------------
1 | import _Gallery from './gallery.vue';
2 | import { gallery } from './gallery';
3 | import { withInstall } from '../utils';
4 |
5 | type GalleryType = typeof _Gallery & {
6 | gallery: typeof gallery;
7 | };
8 | export const Gallery = withInstall(_Gallery as GalleryType);
9 | Gallery.gallery = gallery;
10 | export default Gallery;
11 |
--------------------------------------------------------------------------------
/packages/components/src/grid/__test__/grid.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Grid from '../grid.vue';
4 |
5 | describe('weui-grid', () => {
6 | it('render grid props', () => {
7 | const gridIcon = 'https://weui.io//images/icon_tabbar.png';
8 | const gridLabel = 'Grid';
9 | const wrapper = mount(Grid, {
10 | props: {
11 | icon: gridIcon,
12 | label: gridLabel
13 | }
14 | });
15 | expect(wrapper.find('.weui-grid__icon img').attributes().src).toBe(
16 | gridIcon
17 | );
18 | expect(wrapper.find('.weui-grid__label').text()).toBe(gridLabel);
19 | });
20 |
21 | it('render grid slots', () => {
22 | const iconSlot = 'custom Icon';
23 | const labelSlot = 'custom lable';
24 | const wrapper = mount(Grid, {
25 | slots: {
26 | icon: iconSlot,
27 | label: labelSlot
28 | }
29 | });
30 | expect(wrapper.find('.weui-grid__icon').text()).toBe(iconSlot);
31 | expect(wrapper.find('.weui-grid__label').text()).toBe(labelSlot);
32 | });
33 |
34 | it('render grid click event', async () => {
35 | const wrapper = mount(Grid, {
36 | props: {
37 | label: 'Grid'
38 | }
39 | });
40 | await wrapper.trigger('click');
41 | expect(wrapper.emitted()).haveOwnProperty('click');
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/packages/components/src/grid/__test__/grids.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Grids from '../grids.vue';
4 |
5 | describe('weui-grids', () => {
6 | it('render grids slot', () => {
7 | const slotText = 'grids-slot';
8 | const wrapper = mount(Grids, {
9 | slots: {
10 | default: slotText
11 | }
12 | });
13 | expect(wrapper.text()).toBe(slotText);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/packages/components/src/grid/grid.vue:
--------------------------------------------------------------------------------
1 |
2 | $emit('click', ev)"
7 | >
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{ label }}
15 |
16 |
17 |
18 |
19 |
37 |
--------------------------------------------------------------------------------
/packages/components/src/grid/grids.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/packages/components/src/grid/index.ts:
--------------------------------------------------------------------------------
1 | import _Grids from './grids.vue';
2 | import _Grid from './grid.vue';
3 | import { withInstall } from '../utils';
4 |
5 | export const Grids = withInstall(_Grids);
6 | export const Grid = withInstall(_Grid);
7 | Grids.Grid = Grid;
8 | export default Grids;
9 |
--------------------------------------------------------------------------------
/packages/components/src/halfScreenDialog/index.ts:
--------------------------------------------------------------------------------
1 | import _HalfScreenDialoga from './halfScreenDialog.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const HalfScreenDialog = withInstall(_HalfScreenDialoga);
5 | export default HalfScreenDialog;
6 |
--------------------------------------------------------------------------------
/packages/components/src/icon/__test__/icon.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Icon from '../icon.vue';
4 |
5 | describe('weui-loading', () => {
6 | it('render icon type', () => {
7 | const icons = [
8 | 'success',
9 | 'info',
10 | 'waiting',
11 | 'warn',
12 | 'success-no-circle',
13 | 'close',
14 | 'close-thin',
15 | 'slide-down',
16 | 'arrow',
17 | 'outlined-warn'
18 | ];
19 | for (const icon in icons) {
20 | const wrapper = mount(Icon, {
21 | props: {
22 | type: icon as any
23 | }
24 | });
25 | expect(wrapper.classes()).toContain(`weui-icon-${icon}`);
26 | }
27 | });
28 |
29 | it('render icon size', () => {
30 | const wrapperNum = mount(Icon, {
31 | props: {
32 | type: 'success',
33 | size: 20
34 | }
35 | });
36 | expect(wrapperNum.attributes().style).toBe('font-size: 20px;');
37 | const wrapperStr = mount(Icon, {
38 | props: {
39 | type: 'success',
40 | size: '2em'
41 | }
42 | });
43 | expect(wrapperStr.attributes().style).toBe('font-size: 2em;');
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/packages/components/src/icon/icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
37 |
--------------------------------------------------------------------------------
/packages/components/src/icon/index.ts:
--------------------------------------------------------------------------------
1 | import _Icon from './icon.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Icon = withInstall(_Icon);
5 | export default Icon;
6 |
--------------------------------------------------------------------------------
/packages/components/src/index.ts:
--------------------------------------------------------------------------------
1 | import './common/styles.less';
2 | export * from './icon';
3 | export * from './button';
4 | export * from './slider';
5 | export * from './loading';
6 | export * from './progress';
7 | export * from './badge';
8 | export * from './article';
9 | export * from './flex';
10 | export * from './footer';
11 | export * from './grid';
12 | export * from './loadmore';
13 | export * from './cells';
14 | export * from './toast';
15 | export * from './panel';
16 | export * from './mediabox';
17 | export * from './preview';
18 | export * from './steps';
19 | export * from './mask';
20 | export * from './actionsheet';
21 | export * from './dialog';
22 | export * from './halfScreenDialog';
23 | export * from './msg';
24 | export * from './alert';
25 | export * from './navbar';
26 | export * from './tabbar';
27 | export * from './searchbar';
28 | export * from './form';
29 | export * from './input';
30 | export * from './picker';
31 | export * from './datePicker';
32 | export * from './timePicker';
33 | export * from './textarea';
34 | export * from './switch';
35 | export * from './uploader';
36 | export * from './gallery';
37 | export { default as utils } from './utils/exports';
38 |
--------------------------------------------------------------------------------
/packages/components/src/input/__test__/input.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Input from '../input.vue';
4 |
5 | describe('weui-input', () => {
6 | it('render input', () => {
7 | const wrapper = mount(Input, {
8 | props: {
9 | modelValue: 'input',
10 | placeholder: 'placeholder',
11 | type: 'text',
12 | allowClear: true,
13 | disabled: true
14 | }
15 | });
16 | expect(wrapper.find('.weui-input').attributes().type).toBe('text');
17 | expect(wrapper.find('.weui-input').attributes().placeholder).toBe(
18 | 'placeholder'
19 | );
20 | expect(wrapper.find('.weui-input').attributes()).toHaveProperty('disabled');
21 | expect(wrapper.find('.weui-btn_reset').exists()).toBe(true);
22 | expect(wrapper.classes()).toContain('weui-cell_disabled');
23 | });
24 |
25 | it('change input value', () => {
26 | const wrapper = mount(Input, {
27 | props: {
28 | modelValue: 'input',
29 | placeholder: 'placeholder',
30 | type: 'text'
31 | }
32 | });
33 | wrapper.find('.weui-input').setValue('new input');
34 | expect(wrapper.emitted()).toHaveProperty('update:modelValue');
35 | expect(wrapper.emitted()).toHaveProperty('change');
36 | });
37 |
38 | it('clear input value', async () => {
39 | const wrapper = mount(Input, {
40 | props: {
41 | modelValue: 'input',
42 | placeholder: 'placeholder',
43 | type: 'text',
44 | allowClear: true
45 | }
46 | });
47 | await wrapper.find('.weui-btn_reset').trigger('click');
48 | expect((wrapper.emitted().change[0] as any)?.[0]).toBe('');
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/packages/components/src/input/index.ts:
--------------------------------------------------------------------------------
1 | import _Input from './input.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Input = withInstall(_Input);
5 | export default Input;
6 |
--------------------------------------------------------------------------------
/packages/components/src/input/input.less:
--------------------------------------------------------------------------------
1 | .weui-input-wrapper {
2 | width: 100%;
3 |
4 | .weui-btn_reset:active {
5 | display: block;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/components/src/input/input.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
64 |
--------------------------------------------------------------------------------
/packages/components/src/loading/__test__/loading.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Loading from '../loading.vue';
4 |
5 | describe('weui-loading', () => {
6 | it('render loading type', () => {
7 | const wrapper = mount(Loading, {
8 | props: {
9 | type: 'primary'
10 | }
11 | });
12 | expect(wrapper.classes()).toContain('weui-loading-primary');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/packages/components/src/loading/index.ts:
--------------------------------------------------------------------------------
1 | import _Loading from './loading.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Loading = withInstall(_Loading);
5 | export default Loading;
6 |
--------------------------------------------------------------------------------
/packages/components/src/loading/loading.less:
--------------------------------------------------------------------------------
1 | .weui-mask-loading.weui-loading-primary {
2 | color: var(--weui-BRAND);
3 | }
4 |
--------------------------------------------------------------------------------
/packages/components/src/loading/loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
29 |
--------------------------------------------------------------------------------
/packages/components/src/loadmore/__test__/loadmore.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Loadmore from '../loadmore.vue';
4 |
5 | describe('weui-loadmore', () => {
6 | it('render loadmore type', () => {
7 | const types = ['default', 'line', 'dot'];
8 | for (const type in types) {
9 | const wrapper = mount(Loadmore, {
10 | props: {
11 | type: type as any
12 | }
13 | });
14 | expect(wrapper.classes()).toContain('weui-loadmore');
15 | if (type === 'default') {
16 | expect(wrapper.find('.weui-primary-loading').exists()).toBe(true);
17 | }
18 | if (type === 'line') {
19 | expect(wrapper.classes()).toContain('weui-loadmore_line');
20 | }
21 | if (type === 'dot') {
22 | expect(wrapper.classes()).toContain('weui-loadmore_line');
23 | expect(wrapper.classes()).toContain('weui-loadmore_line');
24 | expect(wrapper.find('.weui-loadmore__tips').text()).toBe('');
25 | }
26 | }
27 | });
28 |
29 | it('render loadmore default slot', () => {
30 | const slotText = 'custom text';
31 | const wrapper = mount(Loadmore, {
32 | slots: {
33 | default: slotText
34 | }
35 | });
36 | expect(wrapper.find('.weui-loadmore__tips').text()).toBe(slotText);
37 | });
38 |
39 | it('render loadmore props text', () => {
40 | const propsText = 'custom text';
41 | const wrapper = mount(Loadmore, {
42 | props: {
43 | text: propsText
44 | }
45 | });
46 | expect(wrapper.find('.weui-loadmore__tips').text()).toBe(propsText);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/packages/components/src/loadmore/index.ts:
--------------------------------------------------------------------------------
1 | import _Loadmore from './loadmore.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Loadmore = withInstall(_Loadmore);
5 | export default Loadmore;
6 |
--------------------------------------------------------------------------------
/packages/components/src/loadmore/loadmore.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 | {{ text }}
16 |
17 |
18 |
19 |
20 |
21 |
42 |
--------------------------------------------------------------------------------
/packages/components/src/mask/__test__/mask.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Mask from '../mask.vue';
4 |
5 | describe('weui-mask', () => {
6 | it('render mask type', () => {
7 | const types = ['transparent', 'default'];
8 | for (const type of types) {
9 | const wrapper = mount(Mask, {
10 | props: {
11 | type: type as any
12 | }
13 | });
14 | if (type === 'transparant') {
15 | expect(wrapper.classes()).toContain('weui-mask_transparent');
16 | }
17 | if (type === 'default') {
18 | expect(wrapper.classes()).toContain('weui-mask');
19 | }
20 | }
21 | });
22 |
23 | it('render default slot', () => {
24 | const defaultSlot = 'defaultSlot';
25 | const wrapper = mount(Mask, {
26 | slots: {
27 | default: defaultSlot
28 | }
29 | });
30 | expect(wrapper.text()).toBe(defaultSlot);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/packages/components/src/mask/index.ts:
--------------------------------------------------------------------------------
1 | import _Mask from './mask.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Mask = withInstall(_Mask);
5 | export default Mask;
6 |
--------------------------------------------------------------------------------
/packages/components/src/mask/mask.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/packages/components/src/mediabox/__test__/mediabox.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import MediaBox from '../mediaBox.vue';
4 |
5 | describe('weui-media-box', () => {
6 | it('render props type', () => {
7 | const title = '标题';
8 | const desc = '描述';
9 | const wrapper = mount(MediaBox, {
10 | props: {
11 | title,
12 | desc
13 | }
14 | });
15 | expect(wrapper.find('.weui-media-box__title').text()).toBe(title);
16 | expect(wrapper.find('.weui-media-box__desc').text()).toBe(desc);
17 | });
18 |
19 | it('render default slot', () => {
20 | const defaultSlot = '自定义内容';
21 | const wrapper = mount(MediaBox, {
22 | slots: {
23 | default: defaultSlot
24 | }
25 | });
26 | expect(wrapper.find('.weui-media-box__bd').text()).toBe(defaultSlot);
27 | });
28 |
29 | it('render hd slot', () => {
30 | const hdSlot = '自定义头部内容';
31 | const wrapper = mount(MediaBox, {
32 | slots: {
33 | hd: hdSlot
34 | }
35 | });
36 | expect(wrapper.find('.weui-media-box__hd').exists()).toBe(true);
37 | expect(wrapper.find('.weui-media-box__hd').text()).toBe(hdSlot);
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/packages/components/src/mediabox/index.ts:
--------------------------------------------------------------------------------
1 | import _MediaBox from './mediaBox.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const MediaBox = withInstall(_MediaBox);
5 | export default MediaBox;
6 |
--------------------------------------------------------------------------------
/packages/components/src/mediabox/mediaBox.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
36 |
--------------------------------------------------------------------------------
/packages/components/src/msg/__test__/msg.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Msg from '../msg.vue';
4 |
5 | describe('weui-msg', () => {
6 | it('render msg type', () => {
7 | const types = ['success', 'info', 'waiting', 'warn'];
8 | for (const type of types) {
9 | const wrapper = mount(Msg, {
10 | props: {
11 | type: type as any
12 | }
13 | });
14 | expect(wrapper.find('.weui-icon_msg').classes()).toContain(
15 | `weui-icon-${type}`
16 | );
17 | }
18 | });
19 |
20 | it('render other prrops', () => {
21 | const title = 'title';
22 | const desc = 'desc';
23 | const wrapper = mount(Msg, {
24 | props: {
25 | title: title,
26 | desc: desc
27 | }
28 | });
29 | expect(wrapper.find('.weui-msg__title').text()).toBe(title);
30 | expect(wrapper.find('.weui-msg__desc').text()).toBe(desc);
31 | });
32 |
33 | it('render msg slots', () => {
34 | const iconSlot = 'icon slot';
35 | const titleSlot = 'title slot';
36 | const descSlot = 'title slot';
37 | const customSlot = 'custom slot';
38 | const oprSlot = 'opr slot';
39 | const tipsSlot = 'tips slot';
40 | const extraSlot = 'extra slot';
41 | const wrapper = mount(Msg, {
42 | slots: {
43 | 'icon-area': iconSlot,
44 | title: titleSlot,
45 | desc: descSlot,
46 | 'custom-area': customSlot,
47 | 'opr-area': oprSlot,
48 | 'tips-area': tipsSlot,
49 | 'extra-area': extraSlot
50 | }
51 | });
52 | expect(wrapper.find('.weui-msg__icon-area').text()).toBe(iconSlot);
53 | expect(wrapper.find('.weui-msg__title').text()).toBe(titleSlot);
54 | expect(wrapper.find('.weui-msg__desc').text()).toBe(descSlot);
55 | expect(wrapper.find('.weui-msg__custom-area').text()).toBe(customSlot);
56 | expect(wrapper.find('.weui-msg__opr-area').text()).toBe(oprSlot);
57 | expect(wrapper.find('.weui-msg__tips-area').text()).toBe(tipsSlot);
58 | expect(wrapper.find('.weui-msg__extra-area').text()).toBe(extraSlot);
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/packages/components/src/msg/index.ts:
--------------------------------------------------------------------------------
1 | import _Msg from './msg.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Msg = withInstall(_Msg);
5 | export default Msg;
6 |
--------------------------------------------------------------------------------
/packages/components/src/msg/msg.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ title }}
11 |
12 |
13 |
14 | {{ desc }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
50 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/__test__/navbar.test.tsx:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import { nextTick } from 'vue';
4 | import NavBar from '../navbar.vue';
5 | import NavBarItem from '../navbarItem.vue';
6 |
7 | describe('weui-navbar', () => {
8 | it('render navbar', () => {
9 | const modelTab = 'tab1';
10 | const tabs = [
11 | { label: 'tab1', value: 'tab1' },
12 | { label: 'tab2', value: 'tab2' }
13 | ];
14 | const changeHandler = vi.fn();
15 | const wrapper = mount(
16 |
17 | {tabs.map((item) => (
18 |
19 | ))}
20 |
21 | );
22 | nextTick(async () => {
23 | await wrapper.findAll('.weui-navbar__item')[0].trigger('click');
24 | expect(changeHandler).toBeCalled();
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/constant.ts:
--------------------------------------------------------------------------------
1 | export const ACTIVE_TAB = Symbol('AVTIVE_TAB');
2 |
3 | export const NAVBAR_NAME = 'weui-navbar';
4 | export const NAVBAR_ITEM_NAME = 'weui-navbar-item';
5 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/index.ts:
--------------------------------------------------------------------------------
1 | import _Navbar from './navbar.vue';
2 | import _NavbarItem from './navbarItem.vue';
3 | import { withInstall } from '../utils';
4 |
5 | type NavBarType = typeof _Navbar & {
6 | NavbarItem: typeof _NavbarItem;
7 | };
8 | export const Navbar = withInstall(_Navbar as NavBarType);
9 | export const NavbarItem = withInstall(_NavbarItem);
10 | Navbar.NavbarItem = NavbarItem;
11 | export default Navbar;
12 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 | {{ tab.label }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
70 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/navbarItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
32 |
--------------------------------------------------------------------------------
/packages/components/src/navbar/types.ts:
--------------------------------------------------------------------------------
1 | export interface NavBarItem {
2 | label: string;
3 | value: T;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/components/src/panel/__test__/panel.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Panel from '../panel.vue';
4 |
5 | describe('weui-panel', () => {
6 | it('render default slot', () => {
7 | const defaultSlot = 'default slot';
8 | const wrapper = mount(Panel, {
9 | slots: {
10 | default: defaultSlot
11 | }
12 | });
13 | expect(wrapper.find('.weui-panel__bd').text()).toBe(defaultSlot);
14 | });
15 |
16 | it('render hd slot', () => {
17 | const hdSlot = 'hd slot';
18 | const wrapper = mount(Panel, {
19 | slots: {
20 | hd: hdSlot
21 | }
22 | });
23 | expect(wrapper.find('.weui-panel__hd').exists()).toBe(true);
24 | expect(wrapper.find('.weui-panel__hd').text()).toBe(hdSlot);
25 | });
26 |
27 | it('render ft slot', () => {
28 | const ftSlot = 'ft slot';
29 | const wrapper = mount(Panel, {
30 | slots: {
31 | ft: ftSlot
32 | }
33 | });
34 | expect(wrapper.find('.weui-panel__ft').exists()).toBe(true);
35 | expect(wrapper.find('.weui-panel__ft').text()).toBe(ftSlot);
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/components/src/panel/index.ts:
--------------------------------------------------------------------------------
1 | import _Panel from './panel.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Panel = withInstall(_Panel);
5 | export default Panel;
6 |
--------------------------------------------------------------------------------
/packages/components/src/panel/panel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/packages/components/src/picker/index.ts:
--------------------------------------------------------------------------------
1 | import _Picker from './picker.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Picker = withInstall(_Picker);
5 | export default Picker;
6 |
--------------------------------------------------------------------------------
/packages/components/src/picker/picker.less:
--------------------------------------------------------------------------------
1 | .weui-picker-wrapper {
2 | align-items: center;
3 | width: 100%;
4 |
5 | .weui-picker-value {
6 | flex: 1;
7 | padding-left: 0;
8 | }
9 |
10 | &.weui-picker_diabled .weui-picker-value {
11 | color: var(--weui-FG-1);
12 | }
13 |
14 | &.weui-picker_placeholder .weui-picker-value {
15 | color: var(--weui-FG-2);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/components/src/picker/types.ts:
--------------------------------------------------------------------------------
1 | export interface PickerItem {
2 | label: string;
3 | value: T;
4 | disabled?: boolean;
5 | children?: PickerItem[];
6 | }
7 |
--------------------------------------------------------------------------------
/packages/components/src/preview/__test__/preview.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Preview from '../preview.vue';
4 |
5 | describe('weui-preview', () => {
6 | it('render default slot', () => {
7 | const defaultSlot = 'default slot';
8 | const wrapper = mount(Preview, {
9 | slots: {
10 | default: defaultSlot
11 | }
12 | });
13 | expect(wrapper.find('.weui-form-preview__bd').text()).toBe(defaultSlot);
14 | });
15 |
16 | it('render hd slot', () => {
17 | const hdSlot = 'hd slot';
18 | const wrapper = mount(Preview, {
19 | slots: {
20 | hd: hdSlot
21 | }
22 | });
23 | expect(wrapper.find('.weui-form-preview__hd').exists()).toBe(true);
24 | expect(wrapper.find('.weui-form-preview__hd').text()).toBe(hdSlot);
25 | });
26 |
27 | it('render ft slot', () => {
28 | const ftSlot = 'ft slot';
29 | const wrapper = mount(Preview, {
30 | slots: {
31 | ft: ftSlot
32 | }
33 | });
34 | expect(wrapper.find('.weui-form-preview__ft').exists()).toBe(true);
35 | expect(wrapper.find('.weui-form-preview__ft').text()).toBe(ftSlot);
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/components/src/preview/__test__/previewBtn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import PreviewBtn from '../previewBtn.vue';
4 |
5 | describe('weui-preview-btn', () => {
6 | it('render preview btn type', () => {
7 | const types = ['default', 'primary'];
8 | for (const type of types) {
9 | const wrapper = mount(PreviewBtn, {
10 | props: {
11 | type: type as any
12 | }
13 | });
14 | expect(wrapper.classes()).toContain(`weui-form-preview__btn_${type}`);
15 | }
16 | });
17 |
18 | it('render default slot', () => {
19 | const defaultSlot = 'default slot';
20 | const wrapper = mount(PreviewBtn, {
21 | slots: {
22 | default: defaultSlot
23 | }
24 | });
25 | expect(wrapper.text()).toBe(defaultSlot);
26 | });
27 |
28 | it('click event emit', async () => {
29 | const wrapper = mount(PreviewBtn, {
30 | slots: {
31 | default: 'button'
32 | }
33 | });
34 | await wrapper.trigger('click');
35 | expect(wrapper.emitted()).toHaveProperty('click');
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/components/src/preview/__test__/previewItem.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import PreviewItem from '../previewItem.vue';
4 |
5 | describe('weui-preview-item', () => {
6 | it('render preview item props', () => {
7 | const label = 'label';
8 | const value = 'value';
9 | const wrapper = mount(PreviewItem, {
10 | props: {
11 | label,
12 | value
13 | }
14 | });
15 | expect(wrapper.find('.weui-form-preview__label').text()).toBe(label);
16 | expect(wrapper.find('.weui-form-preview__value').text()).toBe(value);
17 | });
18 |
19 | it('render label slot', () => {
20 | const labelSlot = 'label slot';
21 | const wrapper = mount(PreviewItem, {
22 | slots: {
23 | label: labelSlot
24 | }
25 | });
26 | expect(wrapper.find('.weui-form-preview__label').text()).toBe(labelSlot);
27 | });
28 |
29 | it('render value slot', () => {
30 | const valueSlot = 'value slot';
31 | const wrapper = mount(PreviewItem, {
32 | slots: {
33 | value: valueSlot
34 | }
35 | });
36 | expect(wrapper.find('.weui-form-preview__value').text()).toBe(valueSlot);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/packages/components/src/preview/index.ts:
--------------------------------------------------------------------------------
1 | import _Preview from './preview.vue';
2 | import _PreviewItem from './previewItem.vue';
3 | import _PreviewBtn from './previewBtn.vue';
4 | import { withInstall } from '../utils';
5 |
6 | type PreviewType = typeof _Preview & {
7 | PreviewItem: typeof _PreviewItem;
8 | PreviewBtn: typeof _PreviewBtn;
9 | };
10 |
11 | export const Preview = withInstall(_Preview as PreviewType);
12 | export const PreviewItem = withInstall(_PreviewItem);
13 | export const PreviewBtn = withInstall(_PreviewBtn);
14 | Preview.PreviewItem = PreviewItem;
15 | Preview.PreviewBtn = PreviewBtn;
16 | export default Preview;
17 |
--------------------------------------------------------------------------------
/packages/components/src/preview/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/packages/components/src/preview/previewBtn.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
40 |
--------------------------------------------------------------------------------
/packages/components/src/preview/previewItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ label }}
6 |
7 |
8 |
9 | {{ value }}
10 |
11 |
12 |
13 |
14 |
30 |
--------------------------------------------------------------------------------
/packages/components/src/progress/__test__/progress.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Progress from '../progress.vue';
4 |
5 | describe('weui-progress', () => {
6 | it('render progress count', () => {
7 | const wrapper = mount(Progress, {
8 | props: {
9 | count: 50
10 | }
11 | });
12 | expect(
13 | (wrapper.find('.weui-progress__inner-bar').element as HTMLElement).style
14 | .width
15 | ).toBe('50%');
16 | });
17 |
18 | it('render progress close btn', async () => {
19 | const wrapper = mount(Progress, {
20 | props: {
21 | count: 50,
22 | showClose: true
23 | }
24 | });
25 | expect(wrapper.find('.weui-progress__opr').exists()).toBe(true);
26 | await wrapper.find('.weui-progress__opr').trigger('click');
27 | expect(wrapper.emitted()).toHaveProperty('click');
28 | });
29 |
30 | it('should render solt', () => {
31 | const wrapper = mount(Progress, {
32 | slots: {
33 | extra: '50%'
34 | }
35 | });
36 | expect(wrapper.find('.weui-progress-extra-wrapper').text()).toContain(
37 | '50%'
38 | );
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/packages/components/src/progress/index.ts:
--------------------------------------------------------------------------------
1 | import _Progress from './progress.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Progress = withInstall(_Progress);
5 | export default Progress;
6 |
--------------------------------------------------------------------------------
/packages/components/src/progress/progress.less:
--------------------------------------------------------------------------------
1 | .weui-progress-extra-wrapper {
2 | margin-left: 15px;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/components/src/progress/progress.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
45 |
--------------------------------------------------------------------------------
/packages/components/src/searchbar/__test__/searchbar.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import SearchBar from '../searchbar.vue';
4 |
5 | describe('weui-searchbar', () => {
6 | it('render searchbar count', () => {
7 | const wrapper = mount(SearchBar, {
8 | props: {
9 | modelValue: 'search'
10 | }
11 | });
12 | expect(
13 | (wrapper.find('.weui-search-bar__input').element as HTMLInputElement)
14 | .value
15 | ).toBe('search');
16 | });
17 |
18 | it('input searchbar', () => {
19 | const wrapper = mount(SearchBar, {
20 | props: {
21 | modelValue: 'search'
22 | }
23 | });
24 | wrapper.find('.weui-search-bar__input').setValue('new search');
25 | expect(
26 | (wrapper.find('.weui-search-bar__input').element as HTMLInputElement)
27 | .value
28 | ).toBe('new search');
29 | });
30 |
31 | it('render searchbar clear', async () => {
32 | const wrapper = mount(SearchBar, {
33 | props: {
34 | modelValue: 'search'
35 | }
36 | });
37 | await wrapper.find('.weui-icon-clear').trigger('click');
38 | expect(wrapper.emitted()).toHaveProperty('update:modelValue');
39 | expect((wrapper.emitted()['update:modelValue'][0] as string[])[0]).toBe('');
40 | });
41 |
42 | it('render searchbar search event', async () => {
43 | const wrapper = mount(SearchBar, {
44 | props: {
45 | modelValue: 'search'
46 | }
47 | });
48 | await wrapper.find('.weui-search-bar__label span').trigger('click');
49 | expect(wrapper.emitted()).toHaveProperty('search');
50 | expect((wrapper.emitted()['search'][0] as string[])[0]).toBe('search');
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/packages/components/src/searchbar/index.ts:
--------------------------------------------------------------------------------
1 | import _Searchbar from './searchbar.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Searchbar = withInstall(_Searchbar);
5 | export default Searchbar;
6 |
--------------------------------------------------------------------------------
/packages/components/src/slider/__test__/slider.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Slider from '../slider.vue';
4 |
5 | describe('weui-slider', () => {
6 | it('render slider percent', () => {
7 | const wrapper = mount(Slider, {
8 | props: {
9 | modelValue: 50
10 | }
11 | });
12 | expect(
13 | (wrapper.find('#sliderTrack').element as HTMLElement).style.width
14 | ).toBe('50%');
15 | expect(
16 | (wrapper.find('#sliderHandler').element as HTMLElement).style.left
17 | ).toBe('50%');
18 | });
19 |
20 | it('render slider number', () => {
21 | const wrapper = mount(Slider, {
22 | props: {
23 | modelValue: 50,
24 | showNum: true
25 | }
26 | });
27 | expect(wrapper.find('#sliderValue').text()).toBe('50');
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/packages/components/src/slider/index.ts:
--------------------------------------------------------------------------------
1 | import _Slider from './slider.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Slider = withInstall(_Slider);
5 | export default Slider;
6 |
--------------------------------------------------------------------------------
/packages/components/src/slider/slider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
26 | {{ value }}
27 |
28 |
29 |
30 |
31 |
69 |
--------------------------------------------------------------------------------
/packages/components/src/steps/__test__/stepItem.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import StepItem from '../stepItem.vue';
4 |
5 | describe('weui-steps-item', () => {
6 | it('render props', () => {
7 | const title = 'title';
8 | const desc = 'desc';
9 | const wrapper = mount(StepItem, {
10 | props: {
11 | title,
12 | desc
13 | }
14 | });
15 | expect(wrapper.find('.weui-steps__item__title').text()).toBe(title);
16 | expect(wrapper.find('.weui-steps__item__desc').text()).toBe(desc);
17 | });
18 |
19 | it('render props icon', () => {
20 | const wrapper = mount(StepItem, {
21 | props: {
22 | icon: 'waiting'
23 | }
24 | });
25 | expect(wrapper.classes()).toContain('weui-steps__item_icon');
26 | expect(wrapper.find('.weui-steps__icon').exists()).toBe(true);
27 |
28 | const icons = ['waiting', 'success'];
29 | for (const icon of icons) {
30 | const wrapper = mount(StepItem, {
31 | props: {
32 | icon: icon as any
33 | }
34 | });
35 | expect(wrapper.find('.weui-steps__icon').classes()).toContain(
36 | `weui-icon-${icon}`
37 | );
38 | }
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/packages/components/src/steps/constant.ts:
--------------------------------------------------------------------------------
1 | export const STEP_DIRECTION = Symbol('STEP_DIRECTION');
2 | export const ACTIVE_STEP = Symbol('AVTIVE_STEP');
3 | export const SET_ACTIVE_STEP = Symbol('SET_ACTIVE_STEP');
4 |
--------------------------------------------------------------------------------
/packages/components/src/steps/index.ts:
--------------------------------------------------------------------------------
1 | import _Steps from './steps.vue';
2 | import _StepItem from './stepItem.vue';
3 | import { withInstall } from '../utils';
4 |
5 | type StepsType = typeof _Steps & {
6 | StepItem: typeof _StepItem;
7 | };
8 | export const Steps = withInstall(_Steps as StepsType);
9 | export const StepItem = withInstall(_StepItem);
10 | Steps.StepItem = StepItem;
11 | export default Steps;
12 |
--------------------------------------------------------------------------------
/packages/components/src/steps/stepItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ title }}
7 |
8 |
9 |
10 | {{ desc }}
11 |
12 |
16 |
17 |
18 |
19 |
20 |
60 |
--------------------------------------------------------------------------------
/packages/components/src/steps/steps.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
43 |
--------------------------------------------------------------------------------
/packages/components/src/switch/index.ts:
--------------------------------------------------------------------------------
1 | import _Switch from './switch.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Switch = withInstall(_Switch);
5 | export default Switch;
6 |
--------------------------------------------------------------------------------
/packages/components/src/switch/switch.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
45 |
--------------------------------------------------------------------------------
/packages/components/src/switch/test/switch.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Switch from '../switch.vue';
4 |
5 | describe('weui-switch', () => {
6 | it('render switch', async () => {
7 | const wrapper = mount(Switch, {
8 | props: {
9 | modelValue: true
10 | }
11 | });
12 | expect(
13 | (wrapper.find('.weui-switch-cp__input').element as HTMLInputElement)
14 | .checked
15 | ).toBe(true);
16 | await wrapper.trigger('click');
17 | expect(wrapper.emitted()).toHaveProperty('update:modelValue');
18 | expect(wrapper.emitted()).toHaveProperty('change');
19 | expect((wrapper.emitted().change[0] as any)[0]).toBe(false);
20 | });
21 |
22 | it('render switch disabled', async () => {
23 | const wrapper = mount(Switch, {
24 | props: {
25 | modelValue: false,
26 | disabled: true
27 | }
28 | });
29 | expect(wrapper.classes()).toContain('weui-cell_disabled');
30 | await wrapper.trigger('click');
31 | expect(wrapper.emitted().change).toBeUndefined();
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/__test__/tabbar.test.tsx:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import { nextTick } from 'vue';
4 | import TabBar from '../tabbar.vue';
5 | import TabBarItem from '../tabbarItem.vue';
6 |
7 | describe('weui-tabbar', () => {
8 | it('render tabbar', () => {
9 | const modelTab = 'tab1';
10 | const tabs = [
11 | { label: 'tab1', value: 'tab1' },
12 | { label: 'tab2', value: 'tab2' }
13 | ];
14 | const changeHandler = vi.fn();
15 | const wrapper = mount(
16 |
17 | {tabs.map((item) => (
18 |
19 | ))}
20 |
21 | );
22 | nextTick(async () => {
23 | await wrapper.findAll('.weui-tabbar__item')[0].trigger('click');
24 | expect(changeHandler).toBeCalled();
25 | });
26 | });
27 |
28 | it('render tabbar tab slot', () => {
29 | const modelTab = 'tab1';
30 | const tabs = [
31 | { label: 'tab1', value: 'tab1' },
32 | { label: 'tab2', value: 'tab2' }
33 | ];
34 | const changeHandler = vi.fn();
35 | mount(
36 |
37 | {{
38 | tab: () => tab
39 | }}
40 | {tabs.map((item) => (
41 |
42 | ))}
43 |
44 | );
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/constant.ts:
--------------------------------------------------------------------------------
1 | export const ACTIVE_TAB = Symbol('AVTIVE_TAB');
2 | export const SELECT_TAB = Symbol('SELECT_TAB');
3 |
4 | export const TABBAR_ITEM_NAME = 'weui-tabbar-item';
5 | export const TABBAR_NAME = 'weui-tabbar';
6 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/index.ts:
--------------------------------------------------------------------------------
1 | import _Tabbar from './tabbar.vue';
2 | import _TabbarItem from './tabbarItem.vue';
3 | import { withInstall } from '../utils';
4 |
5 | type TabBarType = typeof _Tabbar & {
6 | TabbarItem: typeof _TabbarItem;
7 | };
8 | export const Tabbar = withInstall(_Tabbar as TabBarType);
9 | export const TabbarItem = withInstall(_TabbarItem);
10 | Tabbar.TabbarItem = TabbarItem;
11 | export default Tabbar;
12 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/tabbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 | {{ item.label }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
78 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/tabbarItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
31 |
--------------------------------------------------------------------------------
/packages/components/src/tabbar/types.ts:
--------------------------------------------------------------------------------
1 | export interface TabBarItem {
2 | label: string;
3 | value: T;
4 | icon: string;
5 | [key: string]: any;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/components/src/textarea/__test__/textarea.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Textarea from '../textarea.vue';
4 |
5 | describe('weui-textarea', () => {
6 | it('render textarea', () => {
7 | const wrapper = mount(Textarea, {
8 | props: {
9 | modelValue: 'input',
10 | placeholder: 'placeholder',
11 | disabled: true
12 | }
13 | });
14 | expect(wrapper.find('.weui-textarea').attributes().placeholder).toBe(
15 | 'placeholder'
16 | );
17 | expect(wrapper.find('.weui-textarea').attributes()).toHaveProperty(
18 | 'disabled'
19 | );
20 | expect(wrapper.classes()).toContain('weui-cell_disabled');
21 | });
22 |
23 | it('change textarea value', () => {
24 | const wrapper = mount(Textarea, {
25 | props: {
26 | modelValue: 'input',
27 | placeholder: 'placeholder',
28 | type: 'text'
29 | }
30 | });
31 | wrapper.find('.weui-textarea').setValue('new input');
32 | expect(wrapper.emitted()).toHaveProperty('update:modelValue');
33 | expect(wrapper.emitted()).toHaveProperty('change');
34 | });
35 |
36 | it('show textarea number', async () => {
37 | const wrapper = mount(Textarea, {
38 | props: {
39 | modelValue: 'input',
40 | placeholder: 'placeholder',
41 | maxlength: 10,
42 | showNum: true
43 | }
44 | });
45 | wrapper.find('weui-textarea-counter').exists();
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/packages/components/src/textarea/index.ts:
--------------------------------------------------------------------------------
1 | import _Textarea from './textarea.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const Textarea = withInstall(_Textarea);
5 | export default Textarea;
6 |
--------------------------------------------------------------------------------
/packages/components/src/textarea/textarea.less:
--------------------------------------------------------------------------------
1 | .weui-textarea-wrapper {
2 | width: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/components/src/textarea/textarea.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
17 | {{ value?.length }} /{{ maxlength }}
19 |
20 |
21 |
22 |
23 |
59 |
--------------------------------------------------------------------------------
/packages/components/src/timePicker/cron.ts:
--------------------------------------------------------------------------------
1 | const regex = /^(\d+)(?:-(\d+))?(?:\/(\d+))?$/g;
2 | const constraints = [
3 | [0, 23],
4 | [0, 59],
5 | [0, 59]
6 | ];
7 |
8 | function parseField(field: string, constraints: number[]) {
9 | const [low, high] = constraints;
10 | const result: number[] = [];
11 | let pointer: number;
12 |
13 | // * 号等于最低到最高
14 | field = field.replace(/\*/g, low + '-' + high);
15 |
16 | // 处理 1,2,5-9 这种情况
17 | const fields = field.split(',');
18 | for (let i = 0, len = fields.length; i < len; i++) {
19 | const f = fields[i];
20 | if (f.match(regex)) {
21 | f.replace(regex, ((
22 | _: any,
23 | lower: number,
24 | upper: number,
25 | step: string | number
26 | ) => {
27 | // ref to `cron-parser`
28 | step = parseInt(step as string) || 1;
29 | // Positive integer higher than constraints[0]
30 | lower = Math.min(Math.max(low, ~~Math.abs(lower)), high);
31 |
32 | // Positive integer lower than constraints[1]
33 | upper = upper ? Math.min(high, ~~Math.abs(upper)) : lower;
34 |
35 | // Count from the lower barrier to the upper
36 | pointer = lower;
37 |
38 | do {
39 | result.push(pointer);
40 | pointer += step;
41 | } while (pointer <= upper);
42 | }) as any);
43 | }
44 | }
45 | return result;
46 | }
47 |
48 | export function parseCron(expr: string) {
49 | const atoms = expr.replace(/^\s\s*|\s\s*$/g, '').split(/\s+/);
50 | const fields: number[][] = [];
51 | atoms.forEach((atom, index) => {
52 | const constraint = constraints[index];
53 | fields.push(parseField(atom, constraint));
54 | });
55 | return fields;
56 | }
57 |
--------------------------------------------------------------------------------
/packages/components/src/timePicker/index.ts:
--------------------------------------------------------------------------------
1 | import _TimePicker from './timePicker.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const TimePicker = withInstall(_TimePicker);
5 | export default TimePicker;
6 |
--------------------------------------------------------------------------------
/packages/components/src/timePicker/timePicker.less:
--------------------------------------------------------------------------------
1 | .weui-time-picker-wrapper {
2 | align-items: center;
3 | width: 100%;
4 |
5 | .weui-time-value {
6 | flex: 1;
7 | padding-left: 0;
8 | }
9 |
10 | &.weui-picker_diabled .weui-time-value {
11 | color: var(--weui-FG-1);
12 | }
13 |
14 | &.weui-picker_placeholder .weui-time-value {
15 | color: var(--weui-FG-2);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/components/src/timePicker/types.ts:
--------------------------------------------------------------------------------
1 | export interface TimeItem {
2 | label: string;
3 | value: number;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/components/src/toast/__test__/toast.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import Toast from '../toast.vue';
4 |
5 | describe('weui-toast', () => {
6 | it('render toast type', () => {
7 | const types = ['success', 'warn', 'text', 'loading'];
8 | for (const type in types) {
9 | const wrapper = mount(Toast, {
10 | props: {
11 | modelValue: true,
12 | type: type as any
13 | }
14 | });
15 | if (type === 'success') {
16 | expect(wrapper.find('.weui-icon_toast').classes()).toContain(
17 | 'weui-icon-success-no-circle'
18 | );
19 | }
20 | if (type === 'warn') {
21 | expect(wrapper.find('.weui-icon_toast').classes()).toContain(
22 | 'weui-icon-warn'
23 | );
24 | }
25 | if (type === 'loading') {
26 | expect(wrapper.find('.weui-icon_toast').classes()).toContain(
27 | 'weui-primary-loading'
28 | );
29 | }
30 | if (type === 'text') {
31 | expect(wrapper.find('.weui-toast').classes()).toContain(
32 | 'weui-toast_text'
33 | );
34 | expect(wrapper.find('.weui-icon_toast').exists()).toBe(false);
35 | }
36 | }
37 | });
38 |
39 | it('render toast long props', () => {
40 | const wrapper = mount(Toast, {
41 | props: {
42 | modelValue: true,
43 | long: true
44 | }
45 | });
46 | expect(wrapper.find('.weui-toast').classes()).toContain(
47 | 'weui-toast_text-more'
48 | );
49 | });
50 |
51 | it('render toast text props', () => {
52 | const toastText = 'test props';
53 | const wrapper = mount(Toast, {
54 | props: {
55 | modelValue: true,
56 | text: toastText
57 | }
58 | });
59 | expect(wrapper.find('.weui-toast__content').text()).toBe(toastText);
60 | });
61 |
62 | it('render toast no visible', () => {
63 | const wrapper = mount(Toast, {
64 | props: {
65 | modelValue: false
66 | }
67 | });
68 | expect(wrapper.attributes().style).toBe('display: none;');
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/packages/components/src/toast/__test__/toastFn.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { toast } from '../toast';
3 |
4 | describe('weui-toast', () => {
5 | it('toast api mount', () => {
6 | const result = toast({
7 | type: 'success',
8 | duration: 2000
9 | });
10 | expect(typeof result).toBe('function');
11 | expect(result()).toBe(undefined);
12 |
13 | const result1 = toast({
14 | type: 'success',
15 | duration: 0
16 | });
17 | expect(typeof result1).toBe('function');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/components/src/toast/index.ts:
--------------------------------------------------------------------------------
1 | import _Toast from './toast.vue';
2 | import { toast } from './toast';
3 | import { withInstall } from '../utils';
4 |
5 | type ToastType = typeof _Toast & {
6 | toast: typeof toast;
7 | };
8 | export const Toast = withInstall(_Toast as ToastType);
9 | Toast.toast = toast;
10 | export default Toast;
11 |
--------------------------------------------------------------------------------
/packages/components/src/toast/toast.ts:
--------------------------------------------------------------------------------
1 | import { h, render } from 'vue';
2 | import Toast from './toast.vue';
3 | import { shortid } from '../utils';
4 |
5 | interface ToastOptions {
6 | text?: string;
7 | type?: 'success' | 'warn' | 'text' | 'loading';
8 | longText?: boolean;
9 | duration?: number;
10 | }
11 | export function toast(options: ToastOptions) {
12 | const { text, type, longText, duration = 2000 } = options;
13 |
14 | const vnode = h(Toast, {
15 | text,
16 | type,
17 | long: longText,
18 | modelValue: true
19 | });
20 | const toastFragment = document.createElement('div');
21 | toastFragment.classList.add(`weui-toast_${shortid(16)}`);
22 | document.body.appendChild(toastFragment);
23 | render(vnode, toastFragment);
24 |
25 | const hide = () => {
26 | render(null, toastFragment);
27 | document.body.removeChild(toastFragment);
28 | };
29 |
30 | let timer: NodeJS.Timeout;
31 | // 当duration <= 0 时,不自动启动定时器关闭toast
32 | if (duration > 0) {
33 | timer = setTimeout(hide, duration);
34 | }
35 |
36 | return () => {
37 | timer && clearTimeout(timer);
38 | hide();
39 | };
40 | }
41 |
--------------------------------------------------------------------------------
/packages/components/src/toast/toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
50 |
--------------------------------------------------------------------------------
/packages/components/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Maybe = T | undefined | null;
2 |
3 | export type PlainObject = Record;
4 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/filehash.ts:
--------------------------------------------------------------------------------
1 | import type CryptoJs from 'crypto-js';
2 | import type encHexJs from 'crypto-js/enc-hex';
3 |
4 | let CryptoJS: typeof CryptoJs;
5 | let encHex: typeof encHexJs;
6 | let cryptoPromise: Promise;
7 | type Hasher = ReturnType;
8 |
9 | export function loadCryptoJs() {
10 | cryptoPromise = new Promise((resolve, reject) => {
11 | const script = document.createElement('script');
12 | script.onload = () => {
13 | CryptoJS = window.CryptoJS;
14 | encHex = window.CryptoJS.enc.Hex;
15 | resolve();
16 | };
17 | script.onerror = () => {
18 | console.error(
19 | '[vue-weui] Failed to load CryptoJS! Please check your network or try again later.'
20 | );
21 | reject();
22 | };
23 | script.src = 'https://cdn.jsdelivr.net/npm/crypto-js@4.2.0/crypto-js.js';
24 | document.head?.appendChild(script);
25 | });
26 | return cryptoPromise;
27 | }
28 |
29 | export default function fileHash(file: File) {
30 | return cryptoPromise.then(() => {
31 | const { size = 0 } = file;
32 |
33 | const chunkSize = 20 * 1024 * 1024; // 20MB 进行分片
34 | const hashFileInternal = (alog: Hasher) => {
35 | const hashBlob = (blob: Blob) => {
36 | return new Promise((resolve, reject) => {
37 | const reader = new FileReader();
38 | reader.onload = ({ target }) => {
39 | if (target?.result) {
40 | const wordArray = CryptoJS.lib.WordArray.create(
41 | target.result as any
42 | );
43 | alog.update(wordArray);
44 | resolve();
45 | } else {
46 | reject();
47 | }
48 | };
49 | reader.onerror = reject;
50 | reader.readAsArrayBuffer(blob);
51 | });
52 | };
53 |
54 | let chain = Promise.resolve();
55 | for (let index = 0; index < size; index += chunkSize) {
56 | chain = chain.then(() => {
57 | return hashBlob(file.slice(index, index + chunkSize));
58 | });
59 | }
60 |
61 | return chain.then(() => encHex.stringify(alog.finalize()));
62 | };
63 |
64 | return hashFileInternal(CryptoJS.algo.SHA256.create());
65 | });
66 | }
67 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './useAccept';
2 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/hooks/useAccept.ts:
--------------------------------------------------------------------------------
1 | import { ShallowRef, computed } from 'vue';
2 | import { AcceptType } from '../types';
3 | import { Maybe } from '@/types';
4 |
5 | export function useAccpect(type?: ShallowRef>) {
6 | return computed(() => {
7 | switch (type?.value) {
8 | case 'all':
9 | return '*';
10 | case 'media':
11 | return 'audio/*,video/*';
12 | case 'image':
13 | return 'image/*';
14 | case 'file':
15 | return '*';
16 | case 'video':
17 | return 'video/*';
18 | default:
19 | return '';
20 | }
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/index.ts:
--------------------------------------------------------------------------------
1 | import _Uploader from './uploader.vue';
2 | import { withInstall } from '../utils';
3 |
4 | export const uploader = withInstall(_Uploader);
5 | export default uploader;
6 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/tools.ts:
--------------------------------------------------------------------------------
1 | import { UploadType } from './types';
2 |
3 | export function getFileType(file: File): UploadType {
4 | if (!file) {
5 | return 'file';
6 | }
7 |
8 | const type = file.type;
9 | if (!type) {
10 | return 'file';
11 | }
12 |
13 | if (type.startsWith('image/')) {
14 | return 'image';
15 | } else if (type.startsWith('video/')) {
16 | return 'video';
17 | } else {
18 | return 'file';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/types.ts:
--------------------------------------------------------------------------------
1 | import { Maybe } from '@/types';
2 |
3 | export type AcceptType = 'all' | 'media' | 'image' | 'file' | 'video';
4 |
5 | export type UploadStatus = 'ready' | 'progress' | 'success' | 'fail';
6 |
7 | export type UploadType = 'image' | 'video' | 'file';
8 |
9 | export type UploadItem = {
10 | id: string;
11 | url: string;
12 | thumb?: string;
13 | type: UploadType;
14 | status: UploadStatus;
15 | percent?: number;
16 | hash?: string;
17 | };
18 |
19 | export type Compress =
20 | | false
21 | | {
22 | width?: number;
23 | height?: number;
24 | quality?: number;
25 | };
26 |
27 | export interface UploadFile extends File {
28 | id: string;
29 | base64?: Maybe;
30 | onProgress?: (file: UploadFile, percent: number) => void;
31 | [key: string]: any;
32 | }
33 |
34 | export interface UploadResult {
35 | status: UploadStatus;
36 | url: string;
37 | }
38 |
--------------------------------------------------------------------------------
/packages/components/src/uploader/uploader.less:
--------------------------------------------------------------------------------
1 | .weui-uploader__input-wrapper {
2 | position: relative;
3 | width: fit-content;
4 | height: fit-content;
5 | overflow: hidden;
6 |
7 | .weui-uploader__input-box {
8 | float: none;
9 | margin-right: 0;
10 | margin-bottom: 0;
11 | }
12 | }
13 |
14 | .weui-uploader {
15 | .weui-uploader__bd {
16 | overflow: visible;
17 | }
18 |
19 | .weui-uploader__file {
20 | position: relative;
21 |
22 | .delete-upload-btn {
23 | position: absolute;
24 | top: -8px;
25 | right: -8px;
26 | z-index: 100;
27 | display: flex;
28 | align-items: center;
29 | justify-content: center;
30 | width: 16px;
31 | height: 16px;
32 | color: var(--weui-FG-1);
33 | background: var(--weui-BG-2);
34 | border-radius: 50%;
35 | box-shadow: 0 0 2px var(--weui-FG-2);
36 |
37 | .close-icon {
38 | width: 12px;
39 | height: 12px;
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/components/src/utils/exports.ts:
--------------------------------------------------------------------------------
1 | import { closeAllPicker, getAllPicker } from './pickerManager';
2 | import * as themeApis from './theme';
3 |
4 | export default {
5 | closeAllPicker,
6 | getAllPicker,
7 | ...themeApis
8 | };
9 |
--------------------------------------------------------------------------------
/packages/components/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './shortid';
2 | export * from './withInstall';
3 |
--------------------------------------------------------------------------------
/packages/components/src/utils/pickerManager.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 管理所有picker实例,提供外部统一控制picker的显示和隐藏
3 | */
4 |
5 | interface PickerInstance {
6 | hide: () => void;
7 | }
8 |
9 | const pickerMap = new Map();
10 | export function registerPicker(picker: HTMLElement & PickerInstance) {
11 | pickerMap.set(picker, true);
12 | }
13 |
14 | export function unregisterPicker(picker: HTMLElement & PickerInstance) {
15 | pickerMap.delete(picker);
16 | }
17 |
18 | export function closeAllPicker() {
19 | for (const [picker] of pickerMap.entries()) {
20 | picker.hide?.();
21 | }
22 | pickerMap.clear();
23 | }
24 |
25 | export function getAllPicker() {
26 | return pickerMap;
27 | }
28 |
--------------------------------------------------------------------------------
/packages/components/src/utils/shortid.ts:
--------------------------------------------------------------------------------
1 | export function shortid(length: number) {
2 | const characters =
3 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
4 | let result = '';
5 |
6 | for (let i = 0; i < length; i++) {
7 | result += characters.charAt(Math.floor(Math.random() * characters.length));
8 | }
9 |
10 | return result;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/components/src/utils/theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 判断当前组件库是否处于暗黑模式
3 | * @returns boolean
4 | */
5 | export function isDarkMode(): boolean {
6 | const eleTheme = document.body.getAttribute('data-weui-theme');
7 | return eleTheme
8 | ? eleTheme === 'dark'
9 | : window.matchMedia('(prefers-color-scheme: dark)').matches;
10 | }
11 |
12 | /**
13 | * 设置组件库主题
14 | * @param theme 'light' | 'dark' | 'system'
15 | */
16 | export function setTheme(theme: 'dark' | 'light' | 'system') {
17 | if (theme === 'system') {
18 | document.body.removeAttribute('data-weui-theme');
19 | } else {
20 | document.body.setAttribute('data-weui-theme', theme);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/components/src/utils/withInstall.ts:
--------------------------------------------------------------------------------
1 | import type { App, Plugin } from 'vue';
2 | export type SFCWithInstall = T & Plugin;
3 | export function withInstall(comp: T) {
4 | (comp as SFCWithInstall).install = (app: App) => {
5 | const name = (comp as any).name || (comp as any).__name;
6 | app.component(name, comp as SFCWithInstall);
7 | };
8 | return comp as SFCWithInstall;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/components/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue';
5 | const component: DefineComponent<{}, {}, any>;
6 | export default component;
7 | }
8 |
9 | declare module 'weui.js';
10 |
--------------------------------------------------------------------------------
/packages/components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "jsx": "preserve",
5 | "strict": true,
6 | "target": "ES2015",
7 | "module": "ESNext",
8 | "skipLibCheck": true,
9 | "esModuleInterop": true,
10 | "moduleResolution": "Node",
11 | "lib": ["esnext", "dom"],
12 | "paths": {
13 | "@/*": ["./src/*"]
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/packages/components/vite.config.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { defineConfig } from 'vite';
3 | import vue from '@vitejs/plugin-vue';
4 | import vueJsx from '@vitejs/plugin-vue-jsx';
5 | import dts from 'vite-plugin-dts';
6 | import DefineOptions from 'unplugin-vue-define-options/vite';
7 | import path from 'path';
8 |
9 | export default defineConfig({
10 | resolve: {
11 | alias: {
12 | '@': path.resolve(__dirname, 'src')
13 | }
14 | },
15 | build: {
16 | rollupOptions: {
17 | external: ['vue', /\.less/],
18 | input: ['./index.ts'],
19 | output: [
20 | {
21 | format: 'es',
22 | entryFileNames: '[name].mjs',
23 | exports: 'named',
24 | dir: '../vue-weui/es'
25 | },
26 | {
27 | format: 'cjs',
28 | entryFileNames: '[name].js',
29 | exports: 'named',
30 | dir: '../vue-weui/lib'
31 | }
32 | ]
33 | },
34 | lib: {
35 | entry: './index.ts',
36 | name: 'vueWeui'
37 | }
38 | },
39 | plugins: [
40 | vue(),
41 | vueJsx(),
42 | dts({
43 | entryRoot: './src',
44 | outputDir: ['../vue-weui/es/src', '../vue-weui/lib/src'],
45 | tsConfigFilePath: '../../tsconfig.json'
46 | }),
47 | DefineOptions(),
48 | {
49 | name: 'style',
50 | generateBundle(config, bundle) {
51 | const keys = Object.keys(bundle);
52 |
53 | for (const key of keys) {
54 | const bundler: any = bundle[key as any];
55 | // 将所有文件引入的less转化为css
56 | this.emitFile({
57 | type: 'asset',
58 | fileName: key,
59 | source: bundler.code.replace(/\.less/g, '.css')
60 | });
61 | }
62 | }
63 | }
64 | ],
65 | test: {
66 | environment: 'happy-dom',
67 | include: ['./src/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
68 | coverage: {
69 | provider: 'v8',
70 | exclude: [
71 | '**/node_modules/**',
72 | '**/dist/**',
73 | '**/cypress/**',
74 | '**/.{idea,git,cache,output,temp}/**',
75 | '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',
76 | '**/scripts/**',
77 | '**/*.d.ts',
78 | '**/index.ts',
79 | '**/types.ts',
80 | '**/src/utils/**'
81 | ]
82 | }
83 | }
84 | });
85 |
--------------------------------------------------------------------------------
/packages/vue-weui/README.md:
--------------------------------------------------------------------------------
1 | [中文版](./README_ZH.md) | English
2 |
3 |
4 |
5 |
6 |
7 | # vue-weui
8 |
9 | [](https://github.com/bangtz/vue-weui/tree/master/packages/vue-weui)
10 | [](https://pkg-size.dev/vue-weui-next)
11 | [](https://codecov.io/gh/bangtz/vue-weui)
12 | [](https://vuejs.org/)
13 | 
14 |
15 | Weui style UI component library developed and implemented based on Vue3.
16 |
17 | ## Quick start
18 |
19 | Before starting to use it, you need to introduce the weui style file into the html file. ([WeUI](https://github.com/Tencent/weui))
20 |
21 | ```html
22 |
23 | ```
24 |
25 | Install component package.
26 |
27 | ```bash
28 | npm install vue-weui-next
29 |
30 | # or
31 |
32 | yarn install vue-weui-next
33 | ```
34 |
35 | Complete introduction.
36 |
37 | ```ts
38 | import { createApp } from 'vue';
39 | import App from './App.vue';
40 | import Weui from 'vue-weui-next';
41 |
42 | const app = createApp(App);
43 | app.use(Weui);
44 | app.mount('#app');
45 | ```
46 |
47 | Manual import.
48 |
49 | ```html
50 |
51 | button
52 |
53 |
59 | ```
60 |
61 | ## Contact
62 |
63 | Currently, the content of the basic components of weui has been improved. We will continue to update and improve the components related to the weui form form in the future. If you are interested in this project, you are welcome to contribute.
64 |
65 | If you find any code problems, or there are new components or capabilities that you hope to add, please feel free to submit an issue. The author will update and fix them in time. Thank you.
66 |
67 | >  *bangtz* (Add please note vue-weui)
68 |
69 | # License
70 |
71 | [Apache License 2.0](LICENSE)
72 |
--------------------------------------------------------------------------------
/packages/vue-weui/README_ZH.md:
--------------------------------------------------------------------------------
1 | 中文版 | [English](./README.md)
2 |
3 |
4 |
5 |
6 |
7 | # vue-weui
8 |
9 | [](https://github.com/bangtz/vue-weui/tree/master/packages/vue-weui)
10 | [](https://pkg-size.dev/vue-weui-next)
11 | [](https://codecov.io/gh/bangtz/vue-weui)
12 | [](https://vuejs.org/)
13 | 
14 |
15 | 基于 Vue3 开发实现的 WeUI 风格UI组件库。
16 |
17 | ## 快速开始
18 |
19 | 在开始使用之前,需要在html文件中引入weui样式文件。([WeUI](https://github.com/Tencent/weui))
20 |
21 | ```html
22 |
23 | ```
24 |
25 | 安装组件包
26 |
27 | ```bash
28 | npm install vue-weui-next
29 |
30 | # or
31 |
32 | yarn install vue-weui-next
33 | ```
34 |
35 | 完整引入
36 |
37 | ```ts
38 | import { createApp } from 'vue';
39 | import App from './App.vue';
40 | import Weui from 'vue-weui-next';
41 |
42 | const app = createApp(App);
43 | app.use(Weui);
44 | app.mount('#app');
45 | ```
46 |
47 | 手动引入
48 |
49 | ```html
50 |
51 | button
52 |
53 |
59 | ```
60 |
61 | ## 联系
62 |
63 | 当前完善了weui基础组件内容,后续将持续更新完善weui form表单相关的组件,如果对此项目感兴趣,欢迎一起贡献。
64 |
65 | 如果您发现任何代码问题,或者有希望新增的组件或能力,请随时提交问题。作者会及时更新和修复。谢谢
66 |
67 | >  *bangtz* (Add please note vue-weui)
68 |
69 | # License
70 |
71 | [Apache License 2.0](LICENSE)
72 |
--------------------------------------------------------------------------------
/packages/vue-weui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-weui-next",
3 | "version": "1.0.25",
4 | "description": "",
5 | "main": "lib/index.js",
6 | "module": "es/index.mjs",
7 | "typings": "lib/index.d.ts",
8 | "files": [
9 | "es",
10 | "lib",
11 | "typings"
12 | ],
13 | "keywords": [
14 | "vue-weui",
15 | "vue3"
16 | ],
17 | "sideEffects": [
18 | "**/*.css"
19 | ],
20 | "author": "mxchensir",
21 | "license": "Apache-2.0",
22 | "scripts": {
23 | "release": "release-it"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "https://github.com/bangtz/vue-weui.git"
28 | },
29 | "publishConfig": {
30 | "registry": "https://registry.npmjs.org"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/play/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 | play
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/play/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "play",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "vite"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@vitejs/plugin-vue": "^4.5.2",
14 | "vite": "^5.0.10"
15 | },
16 | "dependencies": {
17 | "vue-weui-component": "workspace:^"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/play/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './App.vue';
3 | import Weui from 'vue-weui-component';
4 |
5 | const app = createApp(App);
6 | app.use(Weui);
7 | app.mount('#app');
8 |
--------------------------------------------------------------------------------
/play/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 | import DefineOptions from 'unplugin-vue-define-options/vite';
4 |
5 | export default defineConfig({
6 | plugins: [vue(), DefineOptions()]
7 | });
8 |
--------------------------------------------------------------------------------
/play/vue-shim.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import type { DefineComponent } from "vue";
3 | const component: DefineComponent<{}, {}, any>
4 | }
5 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/**'
3 | - 'play'
4 | - 'site'
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/ActionSheet.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开action-sheet
3 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Alert.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开Alert
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/DatePicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Dialog.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开dialog
3 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/DynamicLayout.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/FrameDefaultLayout.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Gallery.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开画廊
3 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/HalfScreenDialog.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开HalfScreen
3 |
10 | HalfScreen
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | {{ nav.label }}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Picker.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/SlideHalfScreen.vue:
--------------------------------------------------------------------------------
1 |
2 | 打开拖拽半屏
3 |
8 | 可拖拽 HalfScreen
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/TabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | {{ tab.label }} ---- Tab
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/TimePicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Toast.vue:
--------------------------------------------------------------------------------
1 |
2 | success
3 | warn
4 | text
5 | loading
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/Uploader.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
45 |
46 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/components/ValidateForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 提交
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/site/docs/.vitepress/theme/index.js:
--------------------------------------------------------------------------------
1 | import DefaultTheme from 'vitepress/theme';
2 | import DynamicLayout from '../components/DynamicLayout.vue'
3 | import Toast from '../components/Toast.vue';
4 | import ActionSheet from '../components/ActionSheet.vue';
5 | import Dialog from '../components/Dialog.vue';
6 | import HalfScreenDialog from '../components/HalfScreenDialog.vue';
7 | import SlideHalfScreen from '../components/SlideHalfScreen.vue';
8 | import Alert from '../components/Alert.vue';
9 | import NavBar from '../components/NavBar.vue';
10 | import TabBar from '../components/TabBar.vue';
11 | import ValidateForm from '../components/ValidateForm.vue';
12 | import Picker from '../components/Picker.vue';
13 | import DatePicker from '../components/DatePicker.vue';
14 | import TimePicker from '../components/TimePicker.vue';
15 | import Uploader from '../components/Uploader.vue';
16 | import Gallery from '../components/Gallery.vue';
17 |
18 | export default {
19 | ...DefaultTheme,
20 | Layout: DynamicLayout,
21 | enhanceApp: async ({ app }) => {
22 | app.mixin({
23 | async mounted() {
24 | import('vue-weui-next').then(module => {
25 | app.use(module.default)
26 | })
27 | },
28 | })
29 | app.component('custom-toast', Toast);
30 | app.component('custom-actionsheet', ActionSheet);
31 | app.component('custom-dialog', Dialog);
32 | app.component('custom-halfscreen-dialog', HalfScreenDialog);
33 | app.component('custom-slide-halfscreen', SlideHalfScreen);
34 | app.component('custom-alert', Alert);
35 | app.component('custom-navbar', NavBar);
36 | app.component('custom-tabbar', TabBar);
37 | app.component('custom-validate-form', ValidateForm);
38 | app.component('custom-picker', Picker);
39 | app.component('custom-date-picker', DatePicker);
40 | app.component('custom-time-picker', TimePicker);
41 | app.component('custom-uploader', Uploader);
42 | app.component('custom-gallery', Gallery);
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/site/docs/components/actionsheet/index.md:
--------------------------------------------------------------------------------
1 | # actionSheet 菜单
2 |
3 | actionsheet 弹出式菜单主要用于一些菜单操作.
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | 打开action-sheet
13 |
19 |
20 |
21 |
31 | ```
32 | :::
33 |
34 | ### API
35 | #### ActionSheet Props
36 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
37 | | ---- | ---- | ----- | ---- | ----- |
38 | | modelValue | boolean | false | 是否显示actionSheet | - |
39 | | title | string | - | 标题内容 | - |
40 | | menus | ActionSheetMenuOrActions[] | [] | 菜单列表 | - |
41 | | actions | ActionSheetMenuOrActions[] | [] | 操作列表 | - |
42 |
43 | #### ActionSheet Slots
44 | | 名称 | 参数 | 说明 | 版本 |
45 | | ---- | ---- | ----- | ---- |
46 | | title | - | 自定义标题区域 | - |
47 | | menu | menu: ActionSheetMenuOrActions | 自定义菜单项 | - |
48 | | action | action: ActionSheetMenuOrActions | 自定义操作项 | - |
49 |
50 | #### ActionSheet Events
51 | | 名称 | 描述 | 参数 | 版本 |
52 | | ---- | ---- | ----- | ---- |
53 | | click | 点击menu或者actions触发 | (item: ActionSheetMenuOrActions) => void | - |
54 | | close | 关闭actionsheet触发 | () => void | - |
55 |
56 | #### ActionSheet API
57 | | 名称 | 描述 | 参数 | 返回值 | 版本 |
58 | | ---- | ---- | ----- | ---- | ---- |
59 | | actionSheet | 通过函数的方式调起actionSheet展示 | ActionSheetOptions | closeActionSheetFn | - |
--------------------------------------------------------------------------------
/site/docs/components/alert/index.md:
--------------------------------------------------------------------------------
1 | # Alert 提示条
2 |
3 | Alert 信息提示条主要用于状态信息提示。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | 打开Alert
13 |
18 |
19 |
20 |
25 | ```
26 | :::
27 |
28 | ### API
29 | #### Alert Props
30 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
31 | | ---- | ---- | ----- | ---- | ----- |
32 | | modelValue | boolean | false | 是否显示 | - |
33 | | type | 'warn-primary' \| 'warn' \| 'default' \| 'tips-primary' \| 'tips' | 'default' | 提示类型 | - |
34 | | text | string | - | 提示的文本 | - |
35 | | showClose | boolean | true | 是否显示关闭按钮 | - |
36 | | showIcon | boolean | true | 是否显示icon | - |
37 |
38 |
39 | #### Alert Slots
40 | | 名称 | 参数 | 说明 | 版本 |
41 | | ---- | ---- | ----- | ---- |
42 | | default | - | 自定义文本内容 | - |
43 | | icon | - | 自定义icon | - |
44 | | extra | - | 自定义尾部区域 | - |
45 |
46 | #### Alert Events
47 | | 名称 | 描述 | 参数 | 版本 |
48 | | ---- | ---- | ----- | ---- |
49 | | update:modelValue | 信息条状态改变回调 | (val: boolean) => void | - |
50 | | close | 信息条关闭时回调 | () => void | - |
51 |
52 | #### Alert API
53 | | 名称 | 描述 | 参数 | 返回值 | 版本 |
54 | | ---- | ---- | ----- | ---- | ---- |
55 | | alert | 通过函数的方式调起alert展示 | AlertOptions | closeAlertFn | - |
--------------------------------------------------------------------------------
/site/docs/components/article/index.md:
--------------------------------------------------------------------------------
1 | # 文章 Article
2 |
3 | Article 组件用于渲染一片文章
4 |
5 | ### 基础使用
6 |
7 |
8 | 这是文章标题
9 | 这是文章内容
10 |
11 |
12 | ::: details 显示代码
13 | ```vue
14 |
15 | 这是文章标题
16 | 这是文章内容
17 |
18 | ```
19 | :::
20 |
21 | ### API
22 | #### Article Slots
23 | | 名称 | 参数 | 说明 | 版本 |
24 | | ---- | ---- | ----- | ---- |
25 | | default | - | 文章的内容 | - |
--------------------------------------------------------------------------------
/site/docs/components/badge/index.md:
--------------------------------------------------------------------------------
1 | # Badge 标记
2 |
3 | Badge用于标识一些红点提示信息,如通知提醒等
4 |
5 | ### 基础用法
6 |
7 | 标记通过 value 可以定义标记显示的值
8 |
9 |
10 |
11 | ::: details 显示代码
12 | ```vue
13 |
14 | ```
15 | :::
16 |
17 | ### 自定义标记显示内容
18 |
19 | 标记可通过 default 插槽自定义编辑内容
20 |
21 |
22 | 这是自定义文本
23 |
24 |
25 | ::: details 显示代码
26 | ```vue
27 |
28 | 这是自定义文本
29 |
30 | ```
31 | :::
32 |
33 | ### 显示在元素右上角
34 |
35 | 标记可显示在指定内容的右上角
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ::: details 显示代码
44 | ```vue
45 |
46 |
47 |
48 |
49 |
50 | ```
51 | :::
52 |
53 | ### 显示为点模式
54 |
55 | 标记可通过 dot 属性指定显示为一个小点
56 |
57 |
58 |
59 | ::: details 显示代码
60 | ```vue
61 |
62 | ```
63 | :::
64 |
65 | ### 数值溢出显示
66 |
67 | 通过指定标记 max 值可以限制标记显示的最大值,超出时做溢出处理
68 |
69 |
70 |
71 | ::: details 显示代码
72 | ```vue
73 |
74 | ```
75 | :::
76 |
77 | ### API
78 | #### Badge Props
79 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
80 | | ---- | ---- | ----- | ---- | ----- |
81 | | dot | boolean | false | 标记是否显示为点 | - |
82 | | value | string \| number | undefined | 标记显示的内容 | - |
83 | | max | number | undefined | 标记显示的最大值,当 value 为 number 时有效 | - |
84 |
85 | #### Badge Slots
86 | | 名称 | 参数 | 说明 | 版本 |
87 | | ---- | ---- | ----- | ---- |
88 | | default | - | 自定义标记内容 | - |
89 | | content | - | 标记显示内容,标记将显示在该元素的右上角 | - |
--------------------------------------------------------------------------------
/site/docs/components/button/index.md:
--------------------------------------------------------------------------------
1 | # 按钮 Button
2 |
3 | 按钮用来触发一些操作。
4 |
5 | ### 按钮类型
6 | weui 按钮有三种类型,default,primary,warn
7 |
8 | 默认按钮
9 | 主要按钮
10 | 警告按钮
11 |
12 | ::: details 显示代码
13 | ```vue
14 | 默认按钮
15 | 主要按钮
16 | 警告按钮
17 | ```
18 | :::
19 |
20 | ### 按钮尺寸
21 | weui 按钮有两种尺寸,medium,mini
22 | medium按钮
23 | mini按钮
24 |
25 | ::: details 显示代码
26 | ```vue
27 | medium按钮
28 | mini按钮
29 | ```
30 | :::
31 |
32 | ### 按钮禁用
33 | weui 按钮可以通过 disabled 控制禁用状态
34 | 禁用按钮
35 |
36 | ::: details 显示代码
37 | ```vue
38 | 禁用按钮
39 | ```
40 | :::
41 |
42 | ### 按钮 loading
43 | weui 按钮可以通过 loading 控制加载状态
44 | 加载按钮
45 |
46 | ::: details 显示代码
47 | ```vue
48 | 加载按钮
49 | ```
50 | :::
51 |
52 |
53 | ### API
54 | #### Button Props
55 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
56 | | ---- | ---- | ----- | ---- | ----- |
57 | | type | 'default' \| 'primary' \| 'warn' | 'default' | 按钮类型 | - |
58 | | size | 'medium' \| 'mini' | - | 按钮尺寸 | - |
59 | | disabled | boolean | false | 按钮是否禁用 | - |
60 | | loading | boolean | false | 按钮是否加载中 | - |
61 |
62 | #### Button Slots
63 | | 名称 | 参数 | 说明 | 版本 |
64 | | ---- | ---- | ----- | ---- |
65 | | default | - | 按钮的内容 | - |
66 |
67 | #### Button Events
68 | | 名称 | 描述 | 参数 | 版本 |
69 | | ---- | ---- | ----- | ---- |
70 | | click | 设置按钮点击事件 | (event: MouseEvent) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/datePicker/index.md:
--------------------------------------------------------------------------------
1 | # 日期选择器 DatePicker
2 |
3 | 日期选择器常用于表单内选择日期选项
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 |
16 |
17 |
18 |
23 | ```
24 | :::
25 |
26 | ### API
27 | #### DatePicker Props
28 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
29 | | ---- | ---- | ----- | ---- | ----- |
30 | | modelValue | Date | Dayjs | - | 当前日期值 | - |
31 | | start | Date \| number \| string \| Dayjs | 2000-1-1 | 开始日期 | - |
32 | | end | Date \| number \| string \| Dayjs | 2030-1-1 | 结束 | - |
33 | | placeholder | string | - | 占位文案 | - |
34 | | disabled | boolean | false | 是否禁用 | - |
35 | | formatter | string |'YYYY-MM-DD' | 格式化字符串 | - |
36 | | cron | string |'* * *' | cron 表达式,三位,分别是 dayOfMonth[1-31],month[1-12] 和 dayOfWeek[0-6](周日-周六) | - |
37 | | container | string | 'body' | picker挂载节点 | - |
38 |
39 | #### DatePicker Events
40 | | 名称 | 描述 | 参数 | 版本 |
41 | | ---- | ---- | ----- | ---- |
42 | | update:modelValue | 选择器选择值变更时回调 | ((val: Date \| Dayjs) => void) | - |
43 | | selectChange | 选择器选择值改变时回调 | ((val: Dayjs) => void) | - |
44 | | change | 选择器选择值确认时回调 | ((val: Dayjs) => void) | - |
--------------------------------------------------------------------------------
/site/docs/components/dialog/index.md:
--------------------------------------------------------------------------------
1 | # Dialog 对话框
2 |
3 | Dialog 对话框主要用于一些交互式提示。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | 打开dialog
13 |
20 |
21 |
22 |
33 | ```
34 | :::
35 |
36 | ### API
37 | #### Dialog Props
38 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
39 | | ---- | ---- | ----- | ---- | ----- |
40 | | modelValue | boolean | false | 是否显示dialog | - |
41 | | title | string | - | 标题内容 | - |
42 | | desc | string | - | 描述内容 | - |
43 | | cancelText | string \| null | '取消' | 取消按钮文本,当传null时不显示 | - |
44 | | okText | string \| null | '确认' | 确认按钮文本,当传null时不显示 | - |
45 |
46 | #### Dialog Slots
47 | | 名称 | 参数 | 说明 | 版本 |
48 | | ---- | ---- | ----- | ---- |
49 | | hd | - | 自定义头部区域 | - |
50 | | default | - | 自定义主体区域 | - |
51 | | ft | - | 自定义底部区域 | - |
52 |
53 | #### Dialog Events
54 | | 名称 | 描述 | 参数 | 版本 |
55 | | ---- | ---- | ----- | ---- |
56 | | cancel | 点击取消按钮触发 | () => void | - |
57 | | ok | 点击确认按钮触发 | () => void | - |
58 |
59 | #### Dialog API
60 | | 名称 | 描述 | 参数 | 返回值 | 版本 |
61 | | ---- | ---- | ----- | ---- | ---- |
62 | | dialog | 通过函数的方式调起dialog展示 | DialogOptions | closeDialogFn | - |
--------------------------------------------------------------------------------
/site/docs/components/footer/index.md:
--------------------------------------------------------------------------------
1 | # 页脚 Footer
2 |
3 | 页脚 Footer 用于显示页面底部信息
4 |
5 | ### 基础使用
6 |
7 | 这是页脚文本
8 |
9 | ::: details 显示代码
10 | ```vue
11 | 这是页脚文本
12 | ```
13 | :::
14 |
15 | ### 带链接的页脚
16 |
17 | footer的 links 插槽可以用于定义底部链接信息,可以结合 footer-link 组件完成链接定义
18 |
19 |
20 | 这是页脚文本
21 |
22 | 底部链接1
23 | 底部链接2
24 |
25 |
26 |
27 | ::: details 显示代码
28 | ```vue
29 |
30 | 这是页脚文本
31 |
32 | 底部链接1
33 | 底部链接2
34 |
35 |
36 | ```
37 | :::
38 |
39 |
40 | ### API
41 | #### Footer Props
42 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
43 | | ---- | ---- | ----- | ---- | ----- |
44 | | text | string | - | 底部文案 | - |
45 |
46 | #### Footer Slots
47 | | 名称 | 参数 | 说明 | 版本 |
48 | | ---- | ---- | ----- | ---- |
49 | | default | - | 自定义底部文案内容 | - |
50 | | links | - | 自定义底部链接 | - |
51 |
52 | #### FooterLink Props
53 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
54 | | ---- | ---- | ----- | ---- | ----- |
55 | | link | string | - | 跳转链接 | - |
56 | | target | '_blank' | - | 打开方式 | - |
57 |
58 | #### FooterLink Slots
59 | | 名称 | 参数 | 说明 | 版本 |
60 | | ---- | ---- | ----- | ---- |
61 | | default | - | 自定义链接内容 | - |
--------------------------------------------------------------------------------
/site/docs/components/gallery/index.md:
--------------------------------------------------------------------------------
1 | # Gallery 画廊
2 |
3 | Gallery 组件主要用于图片预览展示
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | 打开画廊
13 |
19 |
20 |
21 |
31 | ```
32 | :::
33 |
34 | ### API
35 | #### Gallery Props
36 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
37 | | ---- | ---- | ----- | ---- | ----- |
38 | | urls | string[] | - | 预览的图片列表 | - |
39 | | initialIndex | number | 0 | 初始化显示的图片索引 | - |
40 | | visible | boolean | false | 是否显示 | - |
41 |
42 | #### Gallery Slots
43 | | 名称 | 参数 | 说明 | 版本 |
44 | | ---- | ---- | ----- | ---- |
45 | | item | \{ item: string, index: number \} | 自定义图片渲染 | - |
46 |
47 | #### Gallery Events
48 | | 名称 | 描述 | 参数 | 版本 |
49 | | ---- | ---- | ----- | ---- |
50 | | change | 更新图片索引时触发 | (index: number) => void | - |
51 | | delete | 点击底部删除按钮时触发 | (index: number, url: string) => void | - |
52 | | close | 点击关闭按钮时触发 | () => void | - |
53 |
54 | #### Gallery API
55 | | 名称 | 描述 | 参数 | 返回值 | 版本 |
56 | | ---- | ---- | ----- | ---- | ---- |
57 | | gallery | 通过函数的方式打开画廊 | GalleryOptions | 关闭gallery的函数 | - |
58 | | updateIndex | 存在于gallery组件实例上,用于更新当前索引的函数 | number | - | - |
--------------------------------------------------------------------------------
/site/docs/components/grid/index.md:
--------------------------------------------------------------------------------
1 | # Grids 九宫格
2 |
3 | Grids 用于显示九宫格菜单
4 |
5 | ### 基础使用
6 |
7 | Grids 结合 Grid 组件可以快速实现九宫格菜单效果
8 |
9 |
13 |
17 |
21 |
22 |
23 | ::: details 显示代码
24 | ```vue
25 |
26 |
30 |
34 |
38 |
39 | ```
40 | :::
41 |
42 | ### API
43 | #### Grids Slots
44 | | 名称 | 参数 | 说明 | 版本 |
45 | | ---- | ---- | ----- | ---- |
46 | | default | - | Grid元素插槽 | - |
47 |
48 | #### GridItem Props
49 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
50 | | ---- | ---- | ----- | ---- | ----- |
51 | | icon | string | - | Grid显示的Icon链接 | - |
52 | | label | string | - | Grid显示的文本内容 | - |
53 |
54 | #### GridItem Slots
55 | | 名称 | 参数 | 说明 | 版本 |
56 | | ---- | ---- | ----- | ---- |
57 | | icon | - | 自定义Grid Icon内容 | - |
58 | | label | - | 自定义Grid label内容 | - |
59 |
60 | #### GridItem Events
61 | | 名称 | 描述 | 参数 | 版本 |
62 | | ---- | ---- | ----- | ---- |
63 | | click | 点击Grid项的回调 | (event: MouseEvent) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/halfscreen-dialog/index.md:
--------------------------------------------------------------------------------
1 | # HalfScreenDialog 半屏
2 |
3 | HalfScreenDialog 主要用于半屏弹层展示。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | 打开HalfScreen
13 |
20 | HalfScreen
21 |
22 |
23 |
24 |
32 | ```
33 | :::
34 |
35 |
36 | ### Slide 拖拽半屏
37 |
38 |
39 |
40 | ::: details 显示代码
41 | ```vue
42 |
43 | 打开拖拽半屏
44 |
49 | 可拖拽 HalfScreen
50 |
51 |
52 |
53 |
61 | ```
62 |
63 |
64 | ### API
65 | #### HalfScreenDialog Props
66 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
67 | | ---- | ---- | ----- | ---- | ----- |
68 | | modelValue | boolean | false | 是否打开半屏 | - |
69 | | showClose | boolean | trye | 是否显示关闭按钮 | - |
70 | | title | string | - | 标题内容 | - |
71 | | subTitle | string | - | 副标题内容 | - |
72 | | iconType | 'close' \| 'slide-down' | 'close' | 关闭按钮类型 | - |
73 | | slide | boolean | false | 可拖拽半屏(可拖拽半屏无标题和副标题,icon图标配置,相关配置无效) | - |
74 |
75 |
76 | #### HalfScreenDialog Slots
77 | | 名称 | 参数 | 说明 | 版本 |
78 | | ---- | ---- | ----- | ---- |
79 | | default | - | 半屏主题区域 | - |
80 | | hd | - | 自定义头部标题区域 | - |
81 | | extra | - | 自定义头部右上角 | - |
82 | | ft | - | 自定义底部区域 | - |
83 |
84 | #### Button Events
85 | | 名称 | 描述 | 参数 | 版本 |
86 | | ---- | ---- | ----- | ---- |
87 | | update:modelValue | 半屏显示状态更新 | (val: boolean) => void | - |
88 | | close | 半屏关闭时触发 | () => void | - |
--------------------------------------------------------------------------------
/site/docs/components/icon/index.md:
--------------------------------------------------------------------------------
1 | # Icon 图标
2 |
3 | Icon 主要用于一些weui图标展示。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ::: details 显示代码
16 | ```vue
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ```
26 | :::
27 |
28 | ### API
29 | #### Button Props
30 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
31 | | ---- | ---- | ----- | ---- | ----- |
32 | | type | string | - | icon类型 | - |
33 | | size | number \| string | - | icon尺寸 | - |
--------------------------------------------------------------------------------
/site/docs/components/input/index.md:
--------------------------------------------------------------------------------
1 | # Input 输入框
2 |
3 | Input 输入框常用语文本内容输入
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | ```
13 | :::
14 |
15 | ### 清空输入框
16 |
17 |
18 |
19 | ::: details 显示代码
20 | ```vue
21 |
22 | ```
23 | :::
24 |
25 | ### API
26 | #### Input Props
27 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
28 | | ---- | ---- | ----- | ---- | ----- |
29 | | type | 'text' \| 'password' \| 'url' \| 'tel' | 'text' | 输入框类型 | - |
30 | | modelValue | string | - | 输入框值 | - |
31 | | placeholder | string | - | 输入框占位文案 | - |
32 | | allowClear | boolean | false | 清空输入框 | - |
33 | | disabled | boolean | false | 输入框禁用 | - |
34 |
35 |
36 | #### Input Events
37 | | 名称 | 描述 | 参数 | 版本 |
38 | | ---- | ---- | ----- | ---- |
39 | | update:modelValue | 输入框内容改变时触发 | (val: string) => void | - |
40 | | change | 输入框内容改变时触发 | (val: string) => void | - |
41 |
--------------------------------------------------------------------------------
/site/docs/components/loading/index.md:
--------------------------------------------------------------------------------
1 | # 加载中 Loading
2 |
3 | Loading 用于显示正在加载中状态
4 |
5 | ### Loading 类型
6 | weui Loading提供两种类型,default,primary
7 |
8 |
9 |
10 |
11 | ::: details 显示代码
12 | ```vue
13 |
14 |
15 | ```
16 | :::
17 |
18 | ### API
19 | #### Loading Props
20 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
21 | | ---- | ---- | ----- | ---- | ----- |
22 | | type | 'default' \| 'primary' | 'default' | Loading类型 | - |
--------------------------------------------------------------------------------
/site/docs/components/loadmore/index.md:
--------------------------------------------------------------------------------
1 | # 加载中 Loadmore
2 |
3 | Loadmore 常用于一些滚动加载的场景
4 |
5 | ### 加载中类型
6 |
7 | loadmore 有三种展示类型,分别是 default,line,dot
8 |
9 |
10 |
11 |
12 |
13 | ::: details 显示代码
14 | ```vue
15 |
16 |
17 |
18 | ```
19 | :::
20 |
21 | ### 自动义加载文案
22 |
23 | loadmore 提供插槽可以自定义加载中文案内容
24 |
25 |
26 | 加载中,超链接
27 |
28 |
29 | ::: details 显示代码
30 | ```vue
31 |
32 | 加载中,超链接
33 |
34 | ```
35 | :::
36 |
37 | ### API
38 | #### Loadmore Props
39 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
40 | | ---- | ---- | ----- | ---- | ----- |
41 | | type | 'default' \| 'line' \| 'dot' | 'default' | 加载中类型 | - |
42 | | text | string | '正在加载' | 加载中文本 | - |
43 |
44 |
45 | #### Loadmore Slots
46 | | 名称 | 参数 | 说明 | 版本 |
47 | | ---- | ---- | ----- | ---- |
48 | | default | - | 自定义加载中文本 | - |
--------------------------------------------------------------------------------
/site/docs/components/msg/index.md:
--------------------------------------------------------------------------------
1 | # Msg 提示页
2 |
3 | Msg 提示主要用于展示一些操作状态反馈页面。
4 |
5 | ### 基础使用
6 |
7 |
12 | 自定义内容
13 |
14 | 推荐操作
15 |
16 |
17 | 提示详情,可根据实际需要安排,如果换行则不超过规定长度,居中展现文字链接
18 |
19 | 底部链接区域
20 |
21 |
22 | ::: details 显示代码
23 | ```vue
24 |
29 | 自定义内容
30 |
31 | 推荐操作
32 |
33 |
34 | 提示详情,可根据实际需要安排,如果换行则不超过规定长度,居中展现文字链接
35 |
36 | 底部链接区域
37 |
38 | ```
39 | :::
40 |
41 | ### API
42 | #### Msg Props
43 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
44 | | ---- | ---- | ----- | ---- | ----- |
45 | | type | 'success' \| 'info' \| 'waiting' \| 'warn' | - | 提示页类型 | - |
46 | | title | string | - | 标题文案 | - |
47 | | desc | string | - | 描述文案 | - |
48 |
49 |
50 | #### Button Slots
51 | | 名称 | 参数 | 说明 | 版本 |
52 | | ---- | ---- | ----- | ---- |
53 | | icon-area | - | 自定义icon图标区域 | - |
54 | | title | - | 自定义标题 | - |
55 | | desc | - | 自定义描述 | - |
56 | | custom-area | - | 自定义内容区域,位于描述下方 | - |
57 | | opr-area | - | 操作按钮区域 | - |
58 | | tips-area | - | 提示内容区域,位于操作按钮下方 | - |
59 | | extra-area | - | 尾部扩展区域,位于最下方 | - |
60 |
--------------------------------------------------------------------------------
/site/docs/components/navbar/index.md:
--------------------------------------------------------------------------------
1 | # NavBar 顶部导航
2 |
3 | NavBar 主要用于顶部tab栏显示.
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 |
13 |
19 | {{ nav.label }}
20 |
21 |
22 |
23 |
24 |
33 | ```
34 | :::
35 |
36 | ### API
37 | #### NavBar Props
38 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
39 | | ---- | ---- | ----- | ---- | ----- |
40 | | modelValue | any | - | 当前选择的tab | - |
41 |
42 | #### NavBar Slots
43 | | 名称 | 参数 | 说明 | 版本 |
44 | | ---- | ---- | ----- | ---- |
45 | | default | - | 每个Tab的内容 | - |
46 |
47 | #### NavBar Events
48 | | 名称 | 描述 | 参数 | 版本 |
49 | | ---- | ---- | ----- | ---- |
50 | | update:modelValue | 当前选择的tab改变 | (val: any) => void | - |
51 | | change | 当前选择的tab改变 | (val: any) => void | - |
52 |
53 | #### NavBarItem Props
54 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
55 | | ---- | ---- | ----- | ---- | ----- |
56 | | label | string | - | tab栏标题 | - |
57 | | value | any | - | tab栏的值 | - |
58 |
59 | #### NavBarItem Slots
60 | | 名称 | 参数 | 说明 | 版本 |
61 | | ---- | ---- | ----- | ---- |
62 | | default | - | 当前Tab的内容 | - |
--------------------------------------------------------------------------------
/site/docs/components/panel/index.md:
--------------------------------------------------------------------------------
1 | # Panel 面板
2 |
3 | Panel 面板用于展示一些图文组合数据
4 |
5 | ### 基础使用
6 |
7 | Panel title
8 |
12 |
16 |
17 | 查看详情
18 |
19 |
20 |
21 | ::: details 显示代码
22 | ```vue
23 |
24 | Panel title
25 |
26 | 这是一段文本
27 | 这是一段文本
28 |
29 |
30 | 查看详情
31 |
32 |
33 | ```
34 | :::
35 |
36 | ### API
37 | #### Panel Slots
38 | | 名称 | 参数 | 说明 | 版本 |
39 | | ---- | ---- | ----- | ---- |
40 | | default | - | 面板主体区域 | - |
41 | | hd | - | 面板头部区域 | - |
42 | | ft | - | 面板尾部区域 | - |
--------------------------------------------------------------------------------
/site/docs/components/picker/index.md:
--------------------------------------------------------------------------------
1 | # 选择器 Picker
2 |
3 | 选择器常用于选择一些已知选项。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 |
17 |
18 |
19 |
31 | ```
32 | :::
33 |
34 | ### API
35 | #### Picker Props
36 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
37 | | ---- | ---- | ----- | ---- | ----- |
38 | | modelValue | any | - | 选择器的值 | - |
39 | | options | PickerItem\[] | PickerItem\[][]; | [] | 选择项 | - |
40 | | disabled | boolean | false | 选择器是否禁用 | - |
41 | | placeholder | string | - | 默认占位提示 | - |
42 | | isMulti | boolean | - | 是否多列选择器 | - |
43 | | delimiter | string | '/' | 多列选择值分割符 | - |
44 | | confirmText | string | '确定' | 选择器确认按钮 | - |
45 | | title | string | - | 选择器标题 | - |
46 | | desc | string | - | 选择器描述 | - |
47 | | container | string | 'body' | picker挂载节点 | - |
48 |
49 | #### Picker Events
50 | | 名称 | 描述 | 参数 | 版本 |
51 | | ---- | ---- | ----- | ---- |
52 | | update:modelValue | 选择器选择值变更时回调 | ((val: T \| T[]) => void) | - |
53 | | selectChange | 选择器选择值改变时回调 | ((val: PickerItem\[] \| PickerItem\) => void) | - |
54 | | change | 选择器选择值确认时回调 | ((val: PickerItem\[] \| PickerItem\) => void) | - |
55 |
--------------------------------------------------------------------------------
/site/docs/components/preview/index.md:
--------------------------------------------------------------------------------
1 | # Preview 预览
2 |
3 | Preview 主要用于表单数据的预览展示
4 |
5 | 基础使用
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 操作
15 |
16 |
17 |
18 | ::: details 显示代码
19 | ```vue
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 操作
28 |
29 |
30 | ```
31 | :::
32 |
33 | ### API
34 | #### Preview Slots
35 | | 名称 | 参数 | 说明 | 版本 |
36 | | ---- | ---- | ----- | ---- |
37 | | default | - | 面板主体区域 | - |
38 | | hd | - | 面板头部区域 | - |
39 | | ft | - | 面板尾部区域 | - |
40 |
41 | #### PreviewItem Props
42 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
43 | | ---- | ---- | ----- | ---- | ----- |
44 | | label | string | - | 显示label值 | - |
45 | | value | string | - | 显示的value值 | - |
46 |
47 | #### PreviewItem Slots
48 | | 名称 | 参数 | 说明 | 版本 |
49 | | ---- | ---- | ----- | ---- |
50 | | label | - | 自定义label内容 | - |
51 | | value | - | 自定义value内容 | - |
52 |
53 | #### PreviewBtn Props
54 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
55 | | ---- | ---- | ----- | ---- | ----- |
56 | | type | 'primary' \| 'default' | 'default' | 操作按钮类型 | - |
57 |
58 | #### PreviewBtn Slots
59 | | 名称 | 参数 | 说明 | 版本 |
60 | | ---- | ---- | ----- | ---- |
61 | | default | - | 按钮内容 | - |
62 |
63 | #### PreviewBtn Events
64 | | 名称 | 描述 | 参数 | 版本 |
65 | | ---- | ---- | ----- | ---- |
66 | | click | 设置按钮点击事件 | (event: MouseEvent) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/progress/index.md:
--------------------------------------------------------------------------------
1 | # 进度 Progress
2 |
3 | 进度条一般用于文件上传进度显示。
4 |
5 | ### 基础使用
6 |
7 | 进度条组件可以通过 count 属性控制当前进度值
8 |
9 |
10 | ::: details 显示代码
11 | ```vue
12 |
13 | ```
14 | :::
15 |
16 | ### 显示关闭按钮
17 |
18 | 进度条组件可以通过 show-close 属性控制关闭按钮显示
19 |
20 |
21 | ::: details 显示代码
22 | ```vue
23 |
24 | ```
25 | :::
26 |
27 | ### 自定义进度条尾缀
28 |
29 | 进度条组件提供 extra 插槽,用于自定义组件尾缀
30 |
31 |
32 |
33 | 50%
34 |
35 |
36 |
37 | ::: details 显示代码
38 | ```vue
39 |
40 |
41 | 50%
42 |
43 |
44 | ```
45 | :::
46 |
47 |
48 | ### API
49 | #### Progress Props
50 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
51 | | ---- | ---- | ----- | ---- | ----- |
52 | | count | number | 0 | 进度条值 | - |
53 | | showClose | boolean | false | 显示关闭按钮 | - |
54 |
55 | #### Progess Slots
56 | | 名称 | 参数 | 说明 | 版本 |
57 | | ---- | ---- | ----- | ---- |
58 | | extra | - | 自定义进度条尾缀 | - |
59 |
60 | #### Progress Events
61 | | 名称 | 描述 | 参数 | 版本 |
62 | | ---- | ---- | ----- | ---- |
63 | | close | 点击关闭按钮回调 | (event: MouseEvent) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/searchbar/index.md:
--------------------------------------------------------------------------------
1 | # 搜索框 searchBar
2 |
3 | 搜索框searchBar一般用于搜素操作.
4 |
5 | ### 基础使用
6 |
7 |
8 | ::: details 显示代码
9 | ```vue
10 |
11 | ```
12 | :::
13 |
14 | ### API
15 | #### Progress Props
16 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
17 | | ---- | ---- | ----- | ---- | ----- |
18 | | modelValue | string | '' | 搜索内容 | - |
19 |
20 | #### Progress Events
21 | | 名称 | 描述 | 参数 | 版本 |
22 | | ---- | ---- | ----- | ---- |
23 | | update:modelValue | 搜索框内容更新 | (val: string) => void | - |
24 | | change | 搜索框内容更新 | (val: string) => void | - |
25 | | search | 点击搜索按钮 | (val: string) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/slider/index.md:
--------------------------------------------------------------------------------
1 | # 滑块 Slider
2 |
3 | 滑块一般用于控制数字调整
4 |
5 | ### 基础用法
6 | 默认按钮
7 |
8 | ::: details 显示代码
9 | ```vue
10 |
11 | 默认按钮
12 |
13 |
17 | ```
18 | :::
19 |
20 | ### 滑块步长
21 | 通过 step 属性可以控制 slider 滑块每次滑动的步长
22 |
23 | 默认按钮
24 |
25 | ::: details 显示代码
26 | ```vue
27 | 默认按钮
28 | ```
29 | :::
30 |
31 | ### 显示滑块数值
32 | 通过 showNum 属性可以控制 slider 滑块显示当前的数值
33 |
34 | 默认按钮
35 |
36 | ::: details 显示代码
37 | ```vue
38 | 默认按钮
39 | ```
40 | :::
41 |
42 | ### API
43 | #### Button Props
44 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
45 | | ---- | ---- | ----- | ---- | ----- |
46 | | modelValue | number | 0 | 当前滑块的值 | - |
47 | | step | number | 1 | 滑块滑动的步长 | - |
48 | | showNum | boolean | false | 是否显示滑块数值 | - |
49 |
50 | #### Button Events
51 | | 名称 | 描述 | 参数 | 版本 |
52 | | ---- | ---- | ----- | ---- |
53 | | change | 滑块滑动时触发 | (percent: number) => void | - |
54 | | update:modelValue | 滑块滑动时改变 modelValue 值 | (percent: number) => void | - |
--------------------------------------------------------------------------------
/site/docs/components/switch/index.md:
--------------------------------------------------------------------------------
1 | # Switch 开关
2 |
3 | Switch 开关用于表示两种状态之间的切换,多用于触发「开/关」。
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | ```
13 | :::
14 |
15 |
16 | ### API
17 | #### Switch Props
18 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
19 | | ---- | ---- | ----- | ---- | ----- |
20 | | modelValue | boolean | - | 开关状态 | - |
21 | | disabled | boolean | false | 开关禁用 | - |
22 |
23 |
24 | #### Textarea Events
25 | | 名称 | 描述 | 参数 | 版本 |
26 | | ---- | ---- | ----- | ---- |
27 | | update:modelValue | 开关状态改变时触发 | (val: boolean) => void | - |
28 | | change | 开关状态改变时触发 | (val: boolean) => void | - |
29 |
--------------------------------------------------------------------------------
/site/docs/components/tabbar/index.md:
--------------------------------------------------------------------------------
1 | # Tabbar 底部导航
2 |
3 | TabBar 主要用于底部tab栏显示.
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 |
13 |
20 | {{ tab.label }} ---- Tab
21 |
22 |
23 |
24 |
25 |
34 | ```
35 | :::
36 |
37 | ### API
38 | #### Tabbar Props
39 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
40 | | ---- | ---- | ----- | ---- | ----- |
41 | | modelValue | any | - | 当前选择的tab | - |
42 |
43 | #### Tabbar Slots
44 | | 名称 | 参数 | 说明 | 版本 |
45 | | ---- | ---- | ----- | ---- |
46 | | default | - | 每个Tab的内容 | - |
47 |
48 | #### Tabbar Events
49 | | 名称 | 描述 | 参数 | 版本 |
50 | | ---- | ---- | ----- | ---- |
51 | | update:modelValue | 当前选择的tab改变 | (val: any) => void | - |
52 | | change | 当前选择的tab改变 | (val: any) => void | - |
53 |
54 | #### TabbarItem Props
55 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
56 | | ---- | ---- | ----- | ---- | ----- |
57 | | label | string | - | tab栏标题 | - |
58 | | value | any | - | tab栏的值 | - |
59 | | icon | string | - | tab栏显示的icon | - |
60 |
61 |
62 | #### TabbarItem Slots
63 | | 名称 | 参数 | 说明 | 版本 |
64 | | ---- | ---- | ----- | ---- |
65 | | default | - | 当前Tab的内容 | - |
--------------------------------------------------------------------------------
/site/docs/components/textarea/index.md:
--------------------------------------------------------------------------------
1 | # Textarea 文本域
2 |
3 | Textarea 组件常用于多行文本输入
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 | ```
13 | :::
14 |
15 | ### 显示数据数量
16 |
17 |
18 |
19 | ::: details 显示代码
20 | ```vue
21 |
22 | ```
23 | :::
24 |
25 | ### API
26 | #### Textarea Props
27 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
28 | | ---- | ---- | ----- | ---- | ----- |
29 | | modelValue | string | - | 文本域值 | - |
30 | | placeholder | string | - | 文本域占位文案 | - |
31 | | maxlength | number | - | 文本域最大输入长度 | - |
32 | | show-num | boolean | false | 是否显示输入字数 | - |
33 | | disabled | boolean | false | 文本域禁用 | - |
34 |
35 |
36 | #### Textarea Events
37 | | 名称 | 描述 | 参数 | 版本 |
38 | | ---- | ---- | ----- | ---- |
39 | | update:modelValue | 文本内容改变时触发 | (val: string) => void | - |
40 | | change | 文本域内容改变时触发 | (val: string) => void | - |
41 |
--------------------------------------------------------------------------------
/site/docs/components/timePicker/index.md:
--------------------------------------------------------------------------------
1 | # 时间选择器 TimePicker
2 |
3 | 时间选择器常用于表单内选择时间选项
4 |
5 | ### 基础使用
6 |
7 |
8 |
9 | ::: details 显示代码
10 | ```vue
11 |
12 |
16 |
17 |
18 |
23 | ```
24 | :::
25 |
26 | ### API
27 | #### TimePicker Props
28 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
29 | | ---- | ---- | ----- | ---- | ----- |
30 | | modelValue | number[] | - | 当前时间值 | - |
31 | | placeholder | string | - | 占位文案 | - |
32 | | disabled | boolean | false | 是否禁用 | - |
33 | | formatter | (val: number[]) => void; | (val: number[]) => val.join('\:') | 格式化字符串 | - |
34 | | cron | string |'* * *' | cron 表达式,三位,分别是 hout[0-24] minute[0-59] 和 second[0-59](周日-周六) | - |
35 | | hourFormatter | (val: number) => { label: string; disabled?: boolean }; | - | 格式化选择器时显示 | - |
36 | | minuteFormatter | (val: number) => { label: string; disabled?: boolean }; | - | 格式化选择器分显示 | - |
37 | | secondFormatter | (val: number) => { label: string; disabled?: boolean }; | - | 格式化选择器秒显示 | - |
38 | | container | string | 'body' | picker挂载节点 | - |
39 |
40 |
41 | #### TimePicker Events
42 | | 名称 | 描述 | 参数 | 版本 |
43 | | ---- | ---- | ----- | ---- |
44 | | update:modelValue | 选择器选择值变更时回调 | ((val: number[]) => void) | - |
45 | | selectChange | 选择器选择值改变时回调 | ((val: TimeItem[]) => void) | - |
46 | | change | 选择器选择值确认时回调 | ((val: TimeItem[]) => void) | - |
--------------------------------------------------------------------------------
/site/docs/components/toast/index.md:
--------------------------------------------------------------------------------
1 | # Toast 提示
2 |
3 | Toast 常用于一些成功或失败的提示。
4 |
5 | ### Toast 类型
6 | weui toast提示包括以下几种类型: success, warn, text,loading
7 |
8 |
9 |
10 | ::: details 显示代码
11 | ```vue
12 |
13 | success
14 | warn
15 | text
16 | loading
17 |
18 |
19 |
20 |
35 | ```
36 | :::
37 |
38 | ### API
39 | #### Toast Props
40 | | 名称 | 类型 | 默认值 | 说明 | 版本 |
41 | | ---- | ---- | ----- | ---- | ----- |
42 | | type | 'success' \| 'warn' \| 'loading' | 'text' | toast提示类型 | - |
43 | | text | string | - | 提示文本 | - |
44 | | long | boolean | false | 是否长文本 | - |
45 | | modelValue | boolean | false | 是否显示toast | - |
46 |
47 | #### Toast Events
48 | | 名称 | 描述 | 参数 | 版本 |
49 | | ---- | ---- | ----- | ---- |
50 | | update:modelValue | toast状态改变时触发 | (event: MouseEvent, val: boolean) => void | - |
51 |
52 | #### Toast API
53 | | 名称 | 描述 | 参数 | 返回值 | 版本 |
54 | | ---- | ---- | ----- | ---- | ---- |
55 | | toast | 通过函数的方式调起toast展示 | ToastOptions | 关闭toast的函数 | - |
--------------------------------------------------------------------------------
/site/docs/guide/index.md:
--------------------------------------------------------------------------------
1 | ## 快速开始
2 |
3 | 在开始使用之前,需要在html文件中引入weui样式文件。([WeUI](https://github.com/Tencent/weui))
4 |
5 | ```html
6 |
7 | ```
8 |
9 | 安装组件包
10 |
11 | ```bash
12 | npm install vue-weui-next
13 |
14 | # or
15 |
16 | yarn install vue-weui-next
17 | ```
18 |
19 | 完整引入
20 |
21 | ```ts
22 | import { createApp } from 'vue';
23 | import App from './App.vue';
24 | import Weui from 'vue-weui-next';
25 |
26 | const app = createApp(App);
27 | app.use(Weui);
28 | app.mount('#app');
29 | ```
30 |
31 | 手动引入
32 |
33 | ```html
34 |
35 | button
36 |
37 |
43 | ```
--------------------------------------------------------------------------------
/site/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 | title: vue-weui
4 | titleTemplate: 一个Vue3组件库
5 | hero:
6 | name: vue-weui
7 | text: Vue3实现weui组件库
8 | tagline: 基于开源微信weui组件样式实现的vue3版本组件库
9 | actions:
10 | - theme: brand
11 | text: 开始
12 | link: /guide/
13 | - theme: alt
14 | text: WeUI
15 | link: https://weui.io/
16 | - theme: alt
17 | text: GitHub
18 | link: https://github.com/bangtz/vue-weui
19 | image:
20 | src: https://raw.githubusercontent.com/bangtz/vue-weui/main/vue-weui.png
21 | alt: vue-weui
22 |
23 | features:
24 | - icon: 💡
25 | title: Vue3组件库
26 | details: 基于vite打包和TypeScript开发
27 | - icon: 📦
28 | title: 快速创建
29 | details: 通过CLI快速创建组件库项目
30 | - icon: 🛠️
31 | title: 按需引入
32 | details: 直接支持按需引入无需配置任何插件。
33 | ---
--------------------------------------------------------------------------------
/site/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "site",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "docs:dev": "vitepress dev docs",
9 | "docs:build": "vitepress build docs",
10 | "docs:preview": "vitepress preview docs"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "@whyframe/core": "^0.1.10",
17 | "@whyframe/vue": "^0.1.6",
18 | "vitepress": "1.0.0-rc.32",
19 | "vue": "^3.3.13"
20 | },
21 | "dependencies": {
22 | "vue-weui-next": "workspace:^"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "jsx": "preserve",
5 | "strict": true,
6 | "target": "ES2015",
7 | "module": "ESNext",
8 | "skipLibCheck": true,
9 | "esModuleInterop": true,
10 | "moduleResolution": "Node",
11 | "lib": ["esnext", "dom"]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------