├── .babelrc
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── CHANGELOG.en-US.md
├── CHANGELOG.zh-CN.md
├── LICENSE
├── README.md
├── build
├── component
│ ├── buildComponent.js
│ ├── config.js
│ ├── devComponent.js
│ └── webpack.config.prod.js
├── config.js
├── locale.js
├── webpack.config.locale.js
├── webpack.config.prod.js
└── webpack.config.test.js
├── example
├── app.vue
├── index.html
├── index.js
├── pages
│ ├── box
│ │ └── box.vue
│ ├── button
│ │ └── button.vue
│ ├── cascader
│ │ ├── cascader.vue
│ │ └── data.js
│ ├── checkbox
│ │ └── checkbox.vue
│ ├── datepicker
│ │ └── datepicker.vue
│ ├── drawer
│ │ ├── drawer.vue
│ │ └── test.vue
│ ├── form
│ │ └── form.vue
│ ├── icon
│ │ └── icon.vue
│ ├── input
│ │ └── input.vue
│ ├── pagination
│ │ └── pagination.vue
│ ├── poptip
│ │ └── poptip.vue
│ ├── progress
│ │ └── progress.vue
│ ├── radio
│ │ └── radio.vue
│ ├── select
│ │ └── select.vue
│ ├── spin
│ │ └── spin.vue
│ ├── switch
│ │ └── switch.vue
│ ├── table
│ │ └── table.vue
│ ├── timepicker
│ │ └── timepicker.vue
│ └── tooltip
│ │ └── tooltip.vue
├── router
│ └── index.js
└── sass
│ └── index.scss
├── lib
├── ans-ui.min.css
├── ans-ui.min.js
├── font
│ ├── iconfont.eot
│ ├── iconfont.ttf
│ └── iconfont.woff
├── images
│ └── iconfont.svg
└── locale
│ ├── en.js
│ ├── en.js.map
│ ├── zh-CN.js
│ └── zh-CN.js.map
├── package.json
├── packages
├── vue-box
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── base
│ │ ├── Box.vue
│ │ ├── BoxManager.vue
│ │ └── index.js
│ │ └── layer
│ │ ├── message
│ │ └── message.js
│ │ ├── modal
│ │ └── modal.js
│ │ └── notice
│ │ └── notice.js
├── vue-button
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Button.vue
│ │ └── ButtonGroup.vue
├── vue-cascader
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── data.js
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Cascader.vue
│ │ └── Caspanel.vue
├── vue-checkbox
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Checkbox.vue
│ │ └── CheckboxGroup.vue
├── vue-datepicker
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── base
│ │ ├── confirm.vue
│ │ ├── day.vue
│ │ ├── time.vue
│ │ └── years.vue
│ │ ├── datepicker.vue
│ │ ├── panel
│ │ ├── date.vue
│ │ ├── daterange.vue
│ │ ├── month.vue
│ │ ├── time.vue
│ │ └── year.vue
│ │ └── util
│ │ ├── date.js
│ │ ├── isType.js
│ │ ├── isValid.js
│ │ ├── ishms.js
│ │ └── toDate.js
├── vue-drawer
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ ├── index.js
│ │ └── test.vue
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ └── drawer.js
├── vue-form
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Form.vue
│ │ └── FormItem.vue
├── vue-input
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Input.vue
│ │ └── util
│ │ └── calcTextareaHeight.js
├── vue-pagination
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ └── Page.vue
├── vue-poptip
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Poptip.vue
│ │ └── directive.js
├── vue-progress
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ └── Progress.vue
├── vue-radio
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Radio.vue
│ │ └── RadioGroup.vue
├── vue-scroller
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── HorizontalScrollbar.vue
│ │ ├── Scroller.vue
│ │ └── VerticalScrollbar.vue
├── vue-select
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── async.vue
│ │ ├── dynamic.vue
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── manual.vue
│ │ └── navigation.vue
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Option.vue
│ │ ├── OptionGroup.vue
│ │ ├── Select.vue
│ │ └── SelectDropdown.vue
├── vue-spin
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── Spin.vue
│ │ ├── directive.js
│ │ └── service.js
├── vue-switch
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ └── Switch.vue
├── vue-table
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── array.vue
│ │ ├── dynamic.vue
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── indexs.json
│ │ ├── paging.vue
│ │ ├── restrict.vue
│ │ ├── sort.vue
│ │ └── tree.vue
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ ├── CellRenderer.vue
│ │ ├── Table.vue
│ │ ├── TableBody.vue
│ │ ├── TableColumn.vue
│ │ ├── TableHeader.vue
│ │ ├── TableTd.vue
│ │ ├── TableTh.vue
│ │ ├── layout.js
│ │ ├── layoutObserver.js
│ │ ├── store.js
│ │ └── util.js
├── vue-timepicker
│ ├── README.md
│ ├── example
│ │ ├── app.vue
│ │ ├── index.html
│ │ └── index.js
│ └── src
│ │ ├── index.js
│ │ └── source
│ │ └── Timepicker.vue
└── vue-tooltip
│ ├── README.md
│ ├── example
│ ├── app.vue
│ ├── index.html
│ └── index.js
│ └── src
│ ├── index.js
│ └── source
│ ├── Tooltip.vue
│ ├── directive.js
│ └── factory.js
├── src
├── index.js
├── locale
│ ├── format.js
│ ├── index.js
│ └── lang
│ │ ├── en.js
│ │ └── zh-CN.js
├── style
│ ├── animation
│ │ ├── attentionSeekers.scss
│ │ ├── bouncingEntrances.scss
│ │ ├── bouncingExits.scss
│ │ ├── fadingEntrances.scss
│ │ ├── fadingExits.scss
│ │ ├── flippers.scss
│ │ ├── index.scss
│ │ ├── lightspeed.scss
│ │ ├── rotatingEntrances.scss
│ │ ├── rotatingExits.scss
│ │ ├── slidingEntrances.scss
│ │ ├── slidingExits.scss
│ │ ├── specials.scss
│ │ ├── zoomEntrances.scss
│ │ └── zoomExits.scss
│ ├── common.scss
│ ├── components
│ │ ├── box
│ │ │ ├── box.scss
│ │ │ ├── message.scss
│ │ │ ├── modal.scss
│ │ │ └── notice.scss
│ │ ├── button
│ │ │ ├── button.scss
│ │ │ └── mixin.scss
│ │ ├── cascader
│ │ │ └── cascader.scss
│ │ ├── checkbox
│ │ │ └── checkbox.scss
│ │ ├── datepicker
│ │ │ └── datepicker.scss
│ │ ├── drawer
│ │ │ └── drawer.scss
│ │ ├── form
│ │ │ └── form.scss
│ │ ├── index.scss
│ │ ├── input
│ │ │ └── input.scss
│ │ ├── pagination
│ │ │ └── pagination.scss
│ │ ├── poptip
│ │ │ └── poptip.scss
│ │ ├── progress
│ │ │ └── progress.scss
│ │ ├── radio
│ │ │ └── radio.scss
│ │ ├── scroller
│ │ │ └── scroller.scss
│ │ ├── select
│ │ │ └── select.scss
│ │ ├── spin
│ │ │ └── spin.scss
│ │ ├── switch
│ │ │ └── switch.scss
│ │ ├── table
│ │ │ └── table.scss
│ │ └── tooltip
│ │ │ └── tooltip.scss
│ ├── font.scss
│ ├── font
│ │ ├── iconfont.eot
│ │ ├── iconfont.svg
│ │ ├── iconfont.ttf
│ │ └── iconfont.woff
│ ├── index.scss
│ └── vars.scss
└── util
│ ├── assist.js
│ ├── constants.js
│ ├── customRenderer.js
│ ├── directives
│ ├── clickOutside.js
│ ├── index.js
│ └── mousewheel.js
│ ├── dom
│ ├── animatedScroll.js
│ ├── class.js
│ ├── index.js
│ ├── limitedLoop.js
│ ├── scrollIntoView.js
│ ├── scrollbarWidth.js
│ └── style.js
│ ├── event.js
│ ├── index.js
│ ├── lang.js
│ └── mixins
│ ├── emitter.js
│ ├── index.js
│ ├── locale.js
│ └── popper.js
├── test
└── unit
│ ├── .eslintrc.js
│ ├── index.js
│ ├── karma.conf.js
│ ├── specs
│ ├── button.spec.js
│ ├── input.spec.js
│ ├── page.spec.js
│ └── select.spec.js
│ └── util.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "loose": true,
5 | "debug": false,
6 | "useBuiltIns": true,
7 | "targets": {
8 | "browsers": [ "ie > 8", "last 2 version", "safari >= 9" ]
9 | }
10 | }]
11 | ],
12 | "plugins": [
13 | [ "transform-runtime", {
14 | "helpers": false,
15 | "polyfill": false,
16 | "regenerator": true } ],
17 | [ "transform-class-properties", { "spec": true } ],
18 | [ "transform-object-rest-spread", { "useBuiltIns": true } ],
19 | [ "transform-vue-jsx" ],
20 | [ "syntax-dynamic-import" ]
21 | ],
22 | "comments": false,
23 | "env": {
24 | "production": {
25 | "plugins": ["transform-remove-console"]
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true
5 | },
6 | "extends": [
7 | "plugin:vue/essential",
8 | "standard"
9 | ],
10 | "globals": {
11 | "Atomics": "readonly",
12 | "SharedArrayBuffer": "readonly"
13 | },
14 | "parserOptions": {
15 | "ecmaVersion": 2018,
16 | "sourceType": "module"
17 | },
18 | "plugins": [
19 | "vue"
20 | ],
21 | "rules": {
22 | "vue/valid-v-for": 0
23 | }
24 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | .nyc_output
5 | coverage
6 |
7 | # local env files
8 | .env.local
9 | .env.*.local
10 |
11 | # Log files
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
25 | .cache
26 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | build/
2 | example/
3 | test/
4 | .cache
5 | .babelrc
6 | .eslintrc.json
7 | yarn.lock
--------------------------------------------------------------------------------
/CHANGELOG.en-US.md:
--------------------------------------------------------------------------------
1 | ## Changelog
2 |
3 | ### 1.1.7
4 |
5 | *2019-12-20*
6 |
7 | - Add some icons
8 |
9 | ### 1.1.6
10 |
11 | *2019-12-19*
12 |
13 | - Add some icons
14 |
15 | ### 1.1.5
16 |
17 | *2019-12-17*
18 |
19 | - Add some icons
20 |
21 | ### 1.1.4
22 |
23 | *2019-11-28*
24 |
25 | - Cascader
26 | - Add only-show-last prop
27 | - Page
28 | - Add on-size-change event
29 |
30 | ### 1.1.3
31 |
32 | *2019-11-25*
33 |
34 | - Datepicker
35 | - Fix the selected date not highlighted
36 |
37 | ### 1.1.0
38 |
39 | *2019-11-22*
40 |
41 | #### New features
42 |
43 | - Select
44 | - Add ignore-case prop
45 | - Table
46 | - Add hide-expand-icon prop
47 | - TableColumn add min-width prop
48 | - Tooltip
49 | - Add new option manual for triggerEvent
50 | - Add reveal prop
51 | - Timepicker
52 | - Add step prop
53 | - Add input-props prop
54 | - Datepicker
55 | - Add input-props prop
56 | - Form
57 | - Add vertical prop
58 | - Input
59 | - Add validator-icon prop
60 |
61 | #### Bug fixes
62 |
63 | - Table
64 | - Fix index error that occurred when both data cutting and multilevel headers were used
65 | - Fix dispaly error that table header was not displayed when there was no data
66 | - Fix abnormal display after vertical scrolling in some cases
67 | - Datepicker
68 | - Fix week i18n
69 | - Timepicker
70 | - Fix on-change event
71 |
72 | #### Optimization
73 |
74 | - Tooltip
75 | - Change maxWidth default value to 370px
76 | - Scroller
77 | - Change left/top to translate
78 | - Table
79 | - Optimize sort click experience
80 |
--------------------------------------------------------------------------------
/CHANGELOG.zh-CN.md:
--------------------------------------------------------------------------------
1 | ## 更新日志
2 |
3 |
4 | ### 1.1.7
5 |
6 | *2019-12-20*
7 |
8 | - 新增若干图标
9 |
10 | ### 1.1.6
11 |
12 | *2019-12-19*
13 |
14 | - 新增若干图标
15 |
16 | ### 1.1.5
17 |
18 | *2019-12-17*
19 |
20 | - 新增若干图标
21 |
22 | ### 1.1.4
23 |
24 | *2019-11-28*
25 |
26 | - Cascader
27 | - 新增 only-show-last 属性
28 | - Page
29 | - 新增 on-size-change 事件
30 |
31 | ### 1.1.3
32 |
33 | *2019-11-25*
34 |
35 | - Datepicker
36 | - 修复选中日期未高亮的 bug
37 |
38 | ### 1.1.0
39 |
40 | *2019-11-22*
41 |
42 | #### 新特性
43 |
44 | - Select
45 | - 新增 ignore-case 属性
46 | - Table
47 | - 新增 hide-expand-icon 属性
48 | - TableColumn 新增 min-width 属性
49 | - Tooltip
50 | - triggerEvent 新增可选值 manual
51 | - 新增 reveal 属性
52 | - Timepicker
53 | - 新增 step 属性
54 | - 新增 input-props 属性
55 | - Datepicker
56 | - 新增 input-props 属性
57 | - Form
58 | - 新增 vertical 属性
59 | - Input
60 | - 新增 validator-icon 属性
61 |
62 | #### Bug 修复
63 |
64 | - Table
65 | - 修复多级表头时数据切割索引不对的 bug
66 | - 修复无数据时不能显示表头的 bug
67 | - 修复某些情况下垂直滚动之后显示异常的 bug
68 | - Datepicker
69 | - 修复星期显示国际化失效的 bug
70 | - Timepicker
71 | - 修复 on-change 事件无效的 bug
72 |
73 | #### 优化
74 |
75 | - Tooltip
76 | - maxWidth 的默认值改为 370px
77 | - Scroller
78 | - 将 left/top 替换为 translate 变换
79 | - Table
80 | - 优化排序点击体验
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ans UI
2 |
3 | > A Vue-based UI component library for analysys
4 |
5 | [Documentation](https://analysys.github.io/ans-ui_docs/#/)
6 |
7 | ## Installation
8 |
9 | ```sh
10 | yarn add ans-ui
11 | # or
12 | npm i ans-ui
13 | ```
14 |
15 | ## Usage
16 |
17 | Import all components
18 |
19 | ```javascript
20 | import Vue from 'vue'
21 | import AnsUI from 'ans-ui'
22 | import 'ans-ui/lib/ans-ui.min.css'
23 |
24 | Vue.use(AnsUI)
25 | ```
26 |
27 | Or import specified component
28 |
29 | ```javascript
30 | import Vue from 'vue'
31 | import { xButton } from 'ans-ui'
32 | import 'ans-ui/lib/ans-ui.min.css'
33 |
34 | Vue.use(xButton)
35 | ```
36 |
37 | ## Development
38 |
39 | Install parcel-bundler globally
40 |
41 | ```sh
42 | yarn global add parcel-bundler
43 | # or
44 | npm i -g parcel-bundler
45 | ```
46 |
47 | Then
48 |
49 | ```sh
50 | yarn dev
51 | # or
52 | npm run dev
53 | ```
54 |
55 | ## License
56 |
57 | MIT
--------------------------------------------------------------------------------
/build/component/buildComponent.js:
--------------------------------------------------------------------------------
1 | const { spawn } = require('child_process')
2 | const path = require('path')
3 | const fs = require('fs')
4 | const inquirer = require('inquirer')
5 |
6 | const componentName = process.argv[2]
7 |
8 | if (!componentName) {
9 | fs.readdir(path.resolve('./packages'), (err, files) => {
10 | if (err) {
11 | console.log(err)
12 | process.exit(1)
13 | }
14 | inquirer.prompt([
15 | {
16 | type: 'list',
17 | message: '请选择组件',
18 | name: 'name',
19 | choices: files
20 | }
21 | ]).then(answers => {
22 | process.env.COMPONENT_NAME = answers.name
23 | run()
24 | })
25 | })
26 | } else {
27 | const indexPath = `./packages/vue-${componentName}`
28 | if (!fs.existsSync(path.resolve(indexPath))) {
29 | console.log('请输入正确的组件名称! Please input right component name!')
30 | process.exit(1)
31 | }
32 | process.env.COMPONENT_NAME = `vue-${componentName}`
33 | run()
34 | }
35 |
36 | function run () {
37 | process.env.NODE_ENV = 'production'
38 | spawn('webpack', ['--config', './build/component/webpack.config.prod.js'], {
39 | stdio: 'inherit',
40 | // 仅在当前运行环境为 Windows 时,才使用 shell
41 | shell: process.platform === 'win32'
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/build/component/config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const glob = require('globby')
3 |
4 | const isProduction = process.env.NODE_ENV !== 'development'
5 | const componentName = process.env.COMPONENT_NAME
6 | const resolve = dir => path.join(__dirname, `../../packages/${componentName}`, dir)
7 | const assetsDir = resolve('src')
8 | const distDir = resolve('dist')
9 |
10 | const baseConfig = {
11 | entry: {
12 | index: glob.sync(['index.js'], { cwd: assetsDir })
13 | },
14 | output: {
15 | path: distDir
16 | },
17 | module: {
18 | rules: [
19 | {
20 | test: /\.js$/,
21 | exclude: file => (
22 | /node_modules/.test(file) &&
23 | !/\.vue\.js/.test(file)
24 | ),
25 | use: [
26 | {
27 | loader: 'babel-loader',
28 | options: {
29 | cacheDirectory: true,
30 | cacheIdentifier: true
31 | }
32 | }
33 | ]
34 | }
35 | ]
36 | },
37 | resolve: {
38 | modules: [
39 | assetsDir,
40 | 'node_modules'
41 | ],
42 | extensions: ['.js', '.json', '.vue', '.scss']
43 | },
44 | externals: {
45 | vue: {
46 | commonjs: 'vue',
47 | commonjs2: 'vue',
48 | amd: 'vue',
49 | root: 'Vue'
50 | },
51 | 'popper.js': {
52 | commonjs: 'popper.js',
53 | commonjs2: 'popper.js',
54 | amd: 'popper.js',
55 | root: 'Popper'
56 | }
57 | }
58 | }
59 |
60 | module.exports = {
61 | isProduction,
62 | assetsDir,
63 | distDir,
64 | baseConfig
65 | }
66 |
--------------------------------------------------------------------------------
/build/component/devComponent.js:
--------------------------------------------------------------------------------
1 | const { spawn } = require('child_process')
2 | const path = require('path')
3 | const fs = require('fs')
4 | const inquirer = require('inquirer')
5 |
6 | const componentName = process.argv[2]
7 | let indexPath
8 |
9 | if (!componentName) {
10 | fs.readdir(path.resolve('./packages'), (err, files) => {
11 | if (err) {
12 | console.log(err)
13 | process.exit(1)
14 | }
15 | inquirer.prompt([
16 | {
17 | type: 'list',
18 | message: '请选择组件',
19 | name: 'name',
20 | choices: files
21 | }
22 | ]).then(answers => {
23 | indexPath = `./packages/${answers.name}/example/index.html`
24 | run()
25 | })
26 | })
27 | } else {
28 | indexPath = `./packages/vue-${componentName}/example/index.html`
29 | if (!fs.existsSync(path.resolve(indexPath))) {
30 | console.log('请输入正确的组件名称! Please input right component name!')
31 | process.exit(1)
32 | }
33 | run()
34 | }
35 |
36 | function run () {
37 | console.log(`parcel ${indexPath} -p 3000`)
38 |
39 | spawn('parcel', [indexPath, '-p', '3000'], {
40 | stdio: 'inherit',
41 | // 仅在当前运行环境为 Windows 时,才使用 shell
42 | shell: process.platform === 'win32'
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/build/config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { smart } = require('webpack-merge')
3 |
4 | const resolve = dir => path.resolve(__dirname, '..', dir)
5 |
6 | const baseConfig = {
7 | entry: {
8 | 'ans-ui': './src/index.js'
9 | },
10 | output: {
11 | path: resolve('lib'),
12 | filename: '[name].js',
13 | libraryTarget: 'umd',
14 | library: 'ans',
15 | umdNamedDefine: true
16 | },
17 | performance: {
18 | hints: 'warning'
19 | },
20 | module: {
21 | rules: [
22 | {
23 | test: /\.js$/,
24 | exclude: /(node_modules|bower_components)/,
25 | use: [
26 | {
27 | loader: 'babel-loader',
28 | options: {
29 | cacheDirectory: true,
30 | cacheIdentifier: true
31 | }
32 | }
33 | ]
34 | },
35 | {
36 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
37 | loader: 'url-loader',
38 | options: {
39 | limit: 10000,
40 | name: 'font/[name].[ext]'
41 | }
42 | },
43 | {
44 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
45 | loader: 'file-loader',
46 | options: {
47 | name: 'images/[name].[ext]?[hash]'
48 | }
49 | }
50 | ]
51 | },
52 | resolve: {
53 | modules: [
54 | resolve('src'),
55 | resolve('node_modules')
56 | ],
57 | alias: {
58 | '@': resolve('src'),
59 | packages: resolve('packages')
60 | },
61 | extensions: ['.js', '.json', '.vue', '.scss']
62 | },
63 | externals: {
64 | vue: {
65 | commonjs: 'vue',
66 | commonjs2: 'vue',
67 | amd: 'vue',
68 | root: 'Vue'
69 | }
70 | },
71 | plugins: []
72 | }
73 |
74 | module.exports = {
75 | baseConfig,
76 | resolve,
77 | smart
78 | }
79 |
--------------------------------------------------------------------------------
/build/locale.js:
--------------------------------------------------------------------------------
1 | const readDir = require('fs').readdirSync
2 | const files = readDir('./src/locale/lang')
3 | const entry = {}
4 | files.forEach(file => {
5 | const name = file.split('.')[0]
6 | entry[name] = './src/locale/lang/' + file
7 | })
8 | module.exports = entry
9 |
--------------------------------------------------------------------------------
/build/webpack.config.locale.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const webpack = require('webpack')
3 | const entry = require('./locale')
4 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
5 |
6 | process.env.NODE_ENV = 'production'
7 |
8 | module.exports = {
9 | devtool: 'source-map',
10 | entry,
11 | module: {
12 | rules: [
13 | {
14 | test: /\.js$/,
15 | loader: 'babel-loader',
16 | options: {
17 | sourceMap: true
18 | },
19 | exclude: /node_modules/
20 | }
21 | ]
22 | },
23 | output: {
24 | path: path.resolve(__dirname, '../lib/locale'),
25 | publicPath: '/lib/locale/',
26 | filename: '[name].js',
27 | library: 'ans-ui/locale',
28 | libraryTarget: 'umd',
29 | umdNamedDefine: true
30 | },
31 | externals: {
32 | vue: {
33 | root: 'Vue',
34 | commonjs: 'vue',
35 | commonjs2: 'vue',
36 | amd: 'vue'
37 | }
38 | },
39 | plugins: [
40 | new webpack.DefinePlugin({
41 | 'process.env': {
42 | NODE_ENV: '"production"'
43 | }
44 | }),
45 | new UglifyJsPlugin({
46 | parallel: true,
47 | sourceMap: true
48 | })
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/build/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack')
2 | const { baseConfig, smart } = require('./config')
3 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
4 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
5 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
6 | const VueLoaderPlugin = require('vue-loader/lib/plugin')
7 |
8 | const outConfig = smart(baseConfig, {
9 | devtool: 'source-map',
10 | output: {
11 | filename: '[name].min.js'
12 | },
13 | module: {
14 | rules: [
15 | {
16 | test: /\.vue$/,
17 | loader: 'vue-loader',
18 | options: {
19 | hotReload: false // 开启热重载
20 | }
21 | },
22 | {
23 | test: /\.css$/,
24 | loader: ExtractTextPlugin.extract({
25 | use: [
26 | 'css-loader',
27 | {
28 | loader: 'postcss-loader',
29 | options: {
30 | plugins: (loader) => [
31 | require('autoprefixer')({
32 | browsers: ['ie > 8', 'last 2 version', 'safari >= 9']
33 | }),
34 | require('cssnano')
35 | ]
36 | }
37 | }
38 | ],
39 | fallback: ['vue-style-loader']
40 | })
41 | },
42 | {
43 | test: /\.scss$/,
44 | loader: ExtractTextPlugin.extract({
45 | use: [
46 | 'css-loader',
47 | {
48 | loader: 'postcss-loader',
49 | options: {
50 | plugins: (loader) => [
51 | require('autoprefixer')({
52 | browsers: ['ie > 8', 'last 2 version', 'safari >= 9']
53 | }),
54 | require('cssnano')
55 | ]
56 | }
57 | },
58 | 'sass-loader'
59 | ],
60 | fallback: ['vue-style-loader']
61 | })
62 | }
63 | ]
64 | },
65 | plugins: [
66 | new VueLoaderPlugin(),
67 | new ExtractTextPlugin({ filename: '[name].min.css', allChunks: true }),
68 | new webpack.optimize.OccurrenceOrderPlugin(),
69 | new UglifyJSPlugin({
70 | parallel: true,
71 | sourceMap: false,
72 | uglifyOptions: {
73 | compress: {
74 | drop_console: true,
75 | drop_debugger: true
76 | },
77 | comments: function (n, c) {
78 | /*! IMPORTANT: Please preserve 3rd-party library license info */
79 | var text = c.value; var type = c.type
80 | if (type === 'comment2') {
81 | return /^!|@preserve|@license|@cc_on|MIT/i.test(text)
82 | }
83 | }
84 | }
85 | }),
86 | new OptimizeCssAssetsPlugin({
87 | assetNameRegExp: /\.css$/g,
88 | cssProcessor: require('cssnano'),
89 | cssProcessorOptions: { discardComments: { removeAll: true } },
90 | canPrint: true
91 | })
92 | ]
93 | })
94 |
95 | module.exports = outConfig
96 |
--------------------------------------------------------------------------------
/build/webpack.config.test.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack')
2 | const { baseConfig, smart } = require('./config')
3 | const VueLoaderPlugin = require('vue-loader/lib/plugin')
4 |
5 | const outConfig = smart(baseConfig, {
6 | devtool: 'eval-source-map',
7 | module: {
8 | rules: [
9 | {
10 | test: /\.vue$/,
11 | loader: 'vue-loader',
12 | options: {
13 | loaders: {
14 | css: [
15 | 'vue-style-loader',
16 | {
17 | loader: 'css-loader',
18 | options: {
19 | sourceMap: true
20 | }
21 | }
22 | ],
23 | scss: [
24 | 'vue-style-loader',
25 | {
26 | loader: 'css-loader',
27 | options: {
28 | sourceMap: true
29 | }
30 | },
31 | {
32 | loader: 'sass-loader',
33 | options: {
34 | sourceMap: true
35 | }
36 | }
37 | ]
38 | },
39 | postLoaders: {
40 | html: 'babel-loader?sourceMap'
41 | },
42 | sourceMap: true
43 | }
44 | },
45 | {
46 | test: /\.js$/,
47 | loader: 'babel-loader',
48 | options: {
49 | sourceMap: true
50 | },
51 | exclude: /node_modules/
52 | },
53 | {
54 | test: /\.css$/,
55 | loader: [
56 | {
57 | loader: 'style-loader',
58 | options: {
59 | sourceMap: true
60 | }
61 | },
62 | {
63 | loader: 'css-loader',
64 | options: {
65 | sourceMap: true
66 | }
67 | }
68 | ]
69 | },
70 | {
71 | test: /\.scss$/,
72 | loader: [
73 | {
74 | loader: 'style-loader',
75 | options: {
76 | sourceMap: true
77 | }
78 | },
79 | {
80 | loader: 'css-loader',
81 | options: {
82 | sourceMap: true
83 | }
84 | },
85 | {
86 | loader: 'sass-loader',
87 | options: {
88 | sourceMap: true
89 | }
90 | }
91 | ]
92 | }
93 | ]
94 | },
95 | plugins: [
96 | new VueLoaderPlugin(),
97 | new webpack.DefinePlugin({
98 | 'process.env': {
99 | NODE_ENV: '"testing"'
100 | }
101 | })
102 | ],
103 | resolve: {
104 | alias: {
105 | vue$: 'vue/dist/vue.esm.js'
106 | }
107 | }
108 | })
109 |
110 | delete outConfig.externals
111 |
112 | module.exports = outConfig
113 |
--------------------------------------------------------------------------------
/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Hello analysys
4 |
5 |
6 | - Icon
7 | - spin
8 | - switch
9 | - tooltip
10 | - button
11 | - radio
12 | - input
13 | - checkbox
14 | - pagination
15 | - select
16 | - box
17 | - datepicker
18 | - timepicker
19 | - poptip
20 | - progress
21 | - cascader
22 | - drawer
23 | - table
24 | - form
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ans-ui组件库
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 | import router from './router'
4 | import '../lib/ans-ui.min.css'
5 | import ans from '../lib/ans-ui.min.js'
6 |
7 | Vue.use(ans)
8 |
9 | new Vue({
10 | el: '#app',
11 | router,
12 | render: h => h(App),
13 | mounted () {
14 | console.log('success')
15 | }
16 | })
17 |
--------------------------------------------------------------------------------
/example/pages/cascader/cascader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 | 允许选择任意一级的选项
33 |
34 |
39 |
40 |
41 |
42 |
43 | 搜索
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
75 |
76 |
--------------------------------------------------------------------------------
/example/pages/checkbox/checkbox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | 组合
12 |
13 |
14 | 香蕉
15 | 苹果
16 | 橘子
17 |
18 |
19 |
20 |
21 |
22 |
23 |
42 |
43 |
46 |
--------------------------------------------------------------------------------
/example/pages/drawer/drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 | left
7 | right
8 | top
9 | bottom
10 |
11 |
12 |
13 |
14 |
15 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/example/pages/drawer/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 测试文字
4 |
5 |
6 |
7 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/example/pages/pagination/pagination.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | 显示总条数
11 |
12 |
13 |
14 |
15 |
16 | 跳转
17 |
18 |
19 |
20 |
21 |
22 | 每页条数
23 |
24 |
25 |
26 |
27 |
28 | 无边框
29 |
30 |
31 |
32 |
33 |
34 | 迷你版
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/example/pages/poptip/poptip.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基础用法
5 |
6 |
13 |
14 |
15 |
22 |
23 |
24 | hover 激活
25 | click 激活
26 |
27 |
34 | focus 激活
35 | 我是title
36 |
37 |
38 |
48 | manual 激活
49 |
50 |
51 |
52 |
53 | 嵌套操作
54 |
55 |
60 | 这是一段内容这是一段内容确定删除吗?
61 |
62 | 取消
63 | 确定
64 |
65 |
66 |
删除
67 |
68 |
69 |
70 |
71 |
72 |
86 |
87 |
--------------------------------------------------------------------------------
/example/pages/radio/radio.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 单独使用
5 |
6 |
{{ disabledSingle }}
7 |
{{ disabledSingle2 }}
8 |
9 |
10 |
11 | 大小
12 |
13 | large
14 | default
15 | small
16 |
17 |
18 |
19 | 组合
20 |
21 |
22 | small
23 | default
24 | large
25 |
26 |
27 |
28 |
29 | 状态
30 |
31 |
32 | 我是千帆(禁用)
33 | 我是万像
34 | 我是方舟
35 |
36 |
37 |
38 |
39 | 垂直排列
40 |
41 |
42 | 我是千帆(禁用)
43 | 我是万像
44 | 我是方舟
45 |
46 |
47 |
48 |
49 |
50 |
51 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/example/pages/switch/switch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 |
7 | {{checked}}
8 |
9 |
10 |
11 | 禁用状态
12 |
13 |
14 |
15 |
16 |
17 | 文本
18 |
19 |
20 | {{checked}}
21 |
22 |
23 |
24 | 大小
25 |
26 |
27 |
28 |
29 | {{checked}}
30 |
31 |
32 |
33 |
34 |
35 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/example/pages/timepicker/timepicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 | 选择时分
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 时间区间
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
41 |
42 |
45 |
--------------------------------------------------------------------------------
/example/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | const router = new Router({
7 | routes: [
8 | { path: '/icon', name: 'icon', component: () => import('../pages/icon/icon') },
9 | { path: '/spin', name: 'spin', component: () => import('../pages/spin/spin') },
10 | { path: '/switch', name: 'switch', component: () => import('../pages/switch/switch') },
11 | { path: '/radio', name: 'radio', component: () => import('../pages/radio/radio') },
12 | { path: '/pagination', name: 'pagination', component: () => import('../pages/pagination/pagination') },
13 | { path: '/checkbox', name: 'checkbox', component: () => import('../pages/checkbox/checkbox') },
14 | { path: '/button', name: 'button', component: () => import('../pages/button/button') },
15 | { path: '/tooltip', name: 'tooltip', component: () => import('../pages/tooltip/tooltip') },
16 | { path: '/input', name: 'input', component: () => import('../pages/input/input') },
17 | { path: '/select', name: 'select', component: () => import('../pages/select/select') },
18 | { path: '/box', name: 'box', component: () => import('../pages/box/box') },
19 | { path: '/datepicker', name: 'datepicker', component: () => import('../pages/datepicker/datepicker') },
20 | { path: '/timepicker', name: 'timepicker', component: () => import('../pages/timepicker/timepicker') },
21 | { path: '/poptip', name: 'poptip', component: () => import('../pages/poptip/poptip') },
22 | { path: '/progress', name: 'progress', component: () => import('../pages/progress/progress') },
23 | { path: '/cascader', name: 'cascader', component: () => import('../pages/cascader/cascader') },
24 | { path: '/drawer', name: 'drawer', component: () => import('../pages/drawer/drawer') },
25 | { path: '/table', name: 'table', component: () => import('../pages/table/table') },
26 | { path: '/form', name: 'form', component: () => import('../pages/form/form') }
27 | ]
28 | })
29 |
30 | export default router
31 |
--------------------------------------------------------------------------------
/example/sass/index.scss:
--------------------------------------------------------------------------------
1 | .wrapper {
2 | padding: 0 20px;
3 | .h2 {
4 | color: #999;
5 | border-bottom: 1px dashed #eee;
6 | padding: 20px 0;
7 | margin: 0;
8 | }
9 | .compo-list {
10 | border-bottom: 1px dashed #eee;
11 | .compo-ul {
12 | list-style-type: none;
13 | margin: 0;
14 | padding: 15px 0 0 0;
15 | &::after {
16 | display: block;
17 | content: "";
18 | clear: both;
19 | }
20 | li {
21 | float: left;
22 | margin-right: 20px;
23 | margin-bottom: 15px;
24 | a {
25 | display: inline-block;
26 | padding: 5px 10px;
27 | border: 1px solid #eee;
28 | color: #333;
29 | text-decoration: none;
30 | border-radius: 4px;
31 | &:hover {
32 | color: #0097e0;
33 | }
34 | }
35 | }
36 | }
37 | }
38 | .demo-section {
39 | border: 1px solid #eee;
40 | border-radius: 4px;
41 | background-color: #fafafa;
42 | padding: 10px;
43 | margin: 20px 0;
44 | h4 {
45 | margin: 0;
46 | font-size: 13px;
47 | font-weight: normal;
48 | color: #999;
49 | margin-bottom: 10px;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/lib/font/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/lib/font/iconfont.eot
--------------------------------------------------------------------------------
/lib/font/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/lib/font/iconfont.ttf
--------------------------------------------------------------------------------
/lib/font/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/lib/font/iconfont.woff
--------------------------------------------------------------------------------
/lib/locale/en.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("ans-ui/locale",[],t):"object"==typeof exports?exports["ans-ui/locale"]=t():e["ans-ui/locale"]=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,o),a.l=!0,a.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="/lib/locale/",o(o.s=0)}([function(e,t,o){"use strict";t.__esModule=!0,t.default={ans:{modal:{confirm:"OK",cancel:"Cancel"},cascader:{placeholder:"Select",noMatch:"No matching data",noData:"No data"},datepicker:{placeholder:"Select date",cancel:"Cancel",confirm:"OK",year:"",month1:"January",month2:"February",month3:"March",month4:"April",month5:"May",month6:"June",month7:"July",month8:"August",month9:"September",month10:"October",month11:"November",month12:"December",weeks:{sun:"Sun",mon:"Mon",tue:"Tue",wed:"Wed",thu:"Thu",fri:"Fri",sat:"Sat"},selectTime:"Select time",startTime:"Start time",endTime:"End time"},input:{placeholder:"Please enter..."},page:{goto:"Go to",pagesize:"/page",total:"Total {total}",pageClassifier:""},poptip:{confirm:"OK",cancel:"Cancel"},select:{placeholder:"Select",noMatch:"No matching data",noData:"No data",search:"Keyword"},table:{emptyText:"No data"},timepicker:{clear:"Clear",confirm:"OK",placeholder:"Select"}}}}])});
2 | //# sourceMappingURL=en.js.map
--------------------------------------------------------------------------------
/lib/locale/zh-CN.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("ans-ui/locale",[],t):"object"==typeof exports?exports["ans-ui/locale"]=t():e["ans-ui/locale"]=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="/lib/locale/",o(o.s=1)}([,function(e,t,o){"use strict";t.__esModule=!0,t.default={ans:{modal:{confirm:"确定",cancel:"取消"},cascader:{placeholder:"请选择",noMatch:"搜索无结果",noData:"暂无数据"},datepicker:{placeholder:"请选择日期",cancel:"取消",confirm:"确定",year:"年",month1:"1 月",month2:"2 月",month3:"3 月",month4:"4 月",month5:"5 月",month6:"6 月",month7:"7 月",month8:"8 月",month9:"9 月",month10:"10 月",month11:"11 月",month12:"12 月",weeks:{sun:"日",mon:"一",tue:"二",wed:"三",thu:"四",fri:"五",sat:"六"},selectTime:"选择时间",startTime:"开始时间",endTime:"结束时间"},input:{placeholder:"请输入..."},page:{goto:"跳转至",pagesize:"条/页",total:"共 {total} 条",pageClassifier:"页"},poptip:{confirm:"确定",cancel:"取消"},select:{placeholder:"请选择",noMatch:"搜索无结果",noData:"暂无数据",search:"搜索"},table:{emptyText:"暂无数据"},timepicker:{clear:"清空",confirm:"确定",placeholder:"请选择时间"}}}}])});
2 | //# sourceMappingURL=zh-CN.js.map
--------------------------------------------------------------------------------
/packages/vue-box/README.md:
--------------------------------------------------------------------------------
1 | ## Box
2 |
3 | Box包含modal、message、notice三个组件。
4 |
5 | ### Modal options
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | title | 标题 | String / DOM | - | -
10 | content | 内容 | String / DOM | - | -
11 | width | 宽度 | Number / String | - | 520
12 | className | 自定义样式名称 | String | - | -
13 | closable | 是否显示关闭 | Boolean | - | true
14 | escClose | 是否按 esc 键关闭 | Boolean | - | false
15 | ok | 点击确定的回调 | Object | {show [Boolean] ,text [String], handle[Function]} | -
16 | cancel | 点击取消的回调 | Object | {show [Boolean] ,text [String], handle[Function]} | -
17 | render | 自定义内容 | Function | 使用时 content, title ,ok , cancel 失效 | -
18 | showMask | 是否显示遮罩 | Boolean | - | false
19 | maskClosable | 点击遮罩是否关闭 | Boolean | - | false
20 | i18n | 国际化对象 | VueI18n | - | -
21 |
22 | #### Modal 实例方法
23 |
24 | instance.remove() 销毁当前实例
25 |
26 | #### Modal 全局相关
27 |
28 | this.$modal.destroy() 全局销毁所有实例
29 |
30 | ### Message options
31 |
32 | 属性 | 说明 | 类型 | 可选值 | 默认值
33 | --- | --- | --- | --- | ---
34 | content | 内容 | String | - | -
35 | duration | 自动关闭的延时,单位秒,不关闭可以写 0 | Number | - | 1.5
36 | onClose | 关闭时的回调 | Function | - | -
37 | closable | 是否显示关闭图标 | Boolean | - | false
38 | i18n | 国际化对象 | VueI18n | - | -
39 |
40 | #### Message 全局相关
41 |
42 | this.$message.destroy() 全局销毁所有实例
43 |
44 | this.$message.config(options) 全局配置
45 |
46 | 属性 | 说明 | 类型 | 可选值 | 默认值
47 | --- | --- | --- | --- | ---
48 | top | 提示组件距离顶端的距离,单位像素 | Number | - | 60
49 | duration | 默认自动关闭的延时,单位秒 | Number | - | 1.5
50 | transitionName | 默认动画类名 | String | - | x-ani-move-in
51 | fixed | 显示是否固定位置 | String | Boolean | true
52 |
53 | ### Notice options
54 |
55 | 属性 | 说明 | 类型 | 可选值 | 默认值
56 | --- | --- | --- | --- | ---
57 | title | 标题 | String | - | -
58 | content | 内容 | String | - | -
59 | duration | 自动关闭的延时,单位秒,不关闭可以写 0 | Number | - | 1.5
60 | onClose | 关闭时的回调 | Function | - | -
61 | closable | 是否显示关闭图标 | Boolean | - | false
62 | i18n | 国际化对象 | VueI18n | - | -
63 |
64 | #### Notice 全局相关
65 |
66 | this.$notice.destroy() 全局销毁所有实例
67 |
68 | this.$notice.config(options) 全局配置
69 |
70 | 属性 | 说明 | 类型 | 可选值 | 默认值
71 | --- | --- | --- | --- | ---
72 | top | 提示组件距离顶端的距离,单位像素 | Number | - | 60
73 | right | 提示组件距离屏幕右侧的距离,单位像素 | Number | - | 20
74 | duration | 默认自动关闭的延时,单位秒 | Number | - | 1.5
75 | transitionName | 默认动画类名 | String | - | x-ani-move-right
76 | list | 显示是否以列表形式展示 | Boolean | - | true
--------------------------------------------------------------------------------
/packages/vue-box/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-box/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-box/src/index.js:
--------------------------------------------------------------------------------
1 | import xMessage from './source/layer/message/message'
2 | import xModal from './source/layer/modal/modal'
3 | import xNotice from './source/layer/notice/notice'
4 |
5 | export {
6 | xMessage,
7 | xModal,
8 | xNotice
9 | }
10 |
--------------------------------------------------------------------------------
/packages/vue-box/src/source/base/BoxManager.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
21 |
22 |
23 |
107 |
--------------------------------------------------------------------------------
/packages/vue-box/src/source/base/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by tangwei on 17/8/25.
3 | */
4 | import Vue from 'vue'
5 | import BoxManager from './BoxManager.vue'
6 |
7 | BoxManager.newInstance = properties => {
8 | const _props = properties || {}
9 |
10 | const Instance = new Vue({
11 | data: _props,
12 | i18n: _props.i18n,
13 | render (h) {
14 | return h(BoxManager, {
15 | props: _props
16 | })
17 | }
18 | })
19 |
20 | const component = Instance.$mount()
21 | document.body.appendChild(component.$el)
22 | const notification = Instance.$children[0]
23 |
24 | return {
25 | notice (noticeProps) {
26 | notification.add(noticeProps)
27 | },
28 | remove (name) {
29 | notification.close(name)
30 | },
31 | component: notification,
32 | destroy (classname) {
33 | notification.closeAll()
34 | setTimeout(function () {
35 | document.body.removeChild(document.getElementsByClassName(classname)[0])
36 | }, 500)
37 | }
38 | }
39 | }
40 |
41 | export default BoxManager
42 |
--------------------------------------------------------------------------------
/packages/vue-button/README.md:
--------------------------------------------------------------------------------
1 | ## Button
2 |
3 | 常用的操作按钮
4 |
5 | ### Button props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | title | 标题 | String / DOM | - | -
10 | type | 类型 | String | primary、ghost、dashed、text、info、success、warning、error | -
11 | shape | 形状 | String | circle或者不设置 | -
12 | size | 大小 | String | large、small、default、xsmall | -
13 | loading | 是否为加载中状态 | Boolean | - | -
14 | disabled | 是否禁用 | Boolean | - | -
15 | visible | 在按钮组中,按钮是否显示 | Boolean | - | true
16 | html-type | 设置button原生的type | String | button、submit、reset | button
17 | icon | 按钮的图标类型 | String | - | -
18 | long | 开启后,长度为 100% | Boolean | - | false
19 | value | 按钮的值,可用于双向绑定 | any | - | -
20 |
21 | ButtonGroup props
22 |
23 | 属性 | 说明 | 类型 | 可选值 | 默认值
24 | --- | --- | --- | --- | ---
25 | size | 大小 | String | large、default、small、xsmall | -
26 | shape | 形状 | String | - | -
27 | vertical | 是否纵向排列按钮组 | Boolean | - | -
28 | value | 按钮的值,可用于双向绑定 | any | - | -
29 |
--------------------------------------------------------------------------------
/packages/vue-button/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-button/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-button/src/index.js:
--------------------------------------------------------------------------------
1 | import xButton from './source/Button.vue'
2 | import xButtonGroup from './source/ButtonGroup.vue'
3 |
4 | export {
5 | xButton,
6 | xButtonGroup
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-cascader/README.md:
--------------------------------------------------------------------------------
1 | ## Cascader
2 |
3 | ### Cascader props
4 |
5 | | 属性 | 说明 | required | 类型 | 默认值 |
6 | | :----| :------| :--------| :---:| :------|
7 | | options | 可选项数据源,键名可通过 props 属性配置, 配置选项: { value, label, html, children, disabled } | Required | Array | - |
8 | | prop | N/A | Optional | Object | {...} |
9 | | value | 选中项绑定值 `v-model` | Optional | Array | {...} |
10 | | separator | N/A | Optional | String | / |
11 | | placeholder | N/A | Optional | String | 请选择 ... |
12 | | disabled | N/A | Optional | Any | - |
13 | | clearable | 是否支持清空选项 | Optional | Any | - |
14 | | change-on-select | 是否允许选择任意一级的选项 | Optional | Any | - |
15 | | popper-class | 自定义浮层类名 | Optional | Any | - |
16 | | expand-trigger | 次级菜单的展开方式 [ click / hover ] | Optional | String | click |
17 | | filterable | 是否可搜索选项 | Optional | Any | - |
18 | | no-data-text | 无数据提示 | Optional | String | 暂无数据 |
19 | | no-match-text | 搜索无结果提示 | Optional | String | 搜索无结果 |
20 | | multiple | 是否多选 | Optional | Boolean | false |
21 | | placement | 弹出位置 | Optional | String | bottom-start |
22 | | distance | 与参考元素距离,单位为 px | Optional | Number | 1 |
23 | | append-to-body | 弹出层是否插入 body | Optional | Boolean | false |
24 | | position-fixed | 弹出层是否 fixed 定位 | Boolean | — | false |
25 | | viewport | 弹出层是否基于 viewport 定位 | Boolean | — | false |
26 | | popper-options | Popper.js 的可选项 | Optional | Object | — |
27 | | only-show-last | 是否只展示最后一级的值 | Optional | Boolean | — |
28 |
29 | ### Cascader events
30 |
31 | - `on-change` Fired when the selected value is changed.
32 |
33 | ---
34 |
--------------------------------------------------------------------------------
/packages/vue-cascader/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 | 允许选择任意一级的选项
33 |
34 |
39 |
40 |
41 |
42 |
43 | 搜索
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
77 |
78 |
84 |
--------------------------------------------------------------------------------
/packages/vue-cascader/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-cascader/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-cascader/src/index.js:
--------------------------------------------------------------------------------
1 | import xCascader from './source/Cascader.vue'
2 |
3 | /* istanbul ignore next */
4 | xCascader.install = function (Vue) {
5 | Vue.component(xCascader.name, xCascader)
6 | }
7 |
8 | export { xCascader }
9 |
--------------------------------------------------------------------------------
/packages/vue-checkbox/README.md:
--------------------------------------------------------------------------------
1 | ## Checkbox
2 |
3 | 用于一组可选项多项选择,或者单独用于标记切换某种状态。
4 |
5 | ### Checkbox props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | value | 单独使用时有效,可用于v-model双向绑定 | String / Number / Boolean | - | -
10 | label | 组合使用时有效,指定当前选项value值 | String / Number / Boolean | - | -
11 | disabled | 是否禁用 | Boolean | - | false
12 | true-value | 自定义选中时的值 | String / Number / Boolean | - | true
13 | false-value | 自定义未选中时的值 | String / Number / Boolean | - | false
14 | indeterminate | 设置 indeterminate 状态,只负责样式控制 | Boolean | - | false
15 |
16 | ### Checkbox events
17 |
18 | 事件名称 | 说明 | 回调参数
19 | --- | --- | ---
20 | on-change | 在选项状态发生改变时触发,返回当前状态。通过修改外部的数据改变时不会触发 | 选中的 Checkbox value 值
21 |
22 | ### CheckboxGroup props
23 |
24 | 属性 | 说明 | 类型 | 可选值 | 默认值
25 | --- | --- | --- | --- | ---
26 | value | 当前选中的值,可用于v-model双向绑定 | Array | - | []
27 |
28 | ### CheckboxGroup events
29 |
30 | 事件名称 | 说明 | 回调参数
31 | --- | --- | ---
32 | on-change | 在选项状态发生改变时触发,返回当前状态。通过修改外部的数据改变时不会触发 | 选中的 Checkbox label 值
--------------------------------------------------------------------------------
/packages/vue-checkbox/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | 组合
12 |
13 |
14 | 香蕉
15 | 苹果
16 | 橘子
17 |
18 |
19 |
20 |
21 |
22 |
23 |
45 |
46 |
49 |
--------------------------------------------------------------------------------
/packages/vue-checkbox/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-checkbox/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-checkbox/src/index.js:
--------------------------------------------------------------------------------
1 | import xCheckbox from './source/Checkbox.vue'
2 | import xCheckboxGroup from './source/CheckboxGroup.vue'
3 |
4 | export {
5 | xCheckbox,
6 | xCheckboxGroup
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-checkbox/src/source/CheckboxGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
65 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/README.md:
--------------------------------------------------------------------------------
1 | An component project
2 |
3 | ### Setup
4 |
5 | - 安装node > 8的LTS版本,https://nodejs.org/en/
6 |
7 | - 增加npm本地仓库host,106.75.23.50 npm.analysys.cn
8 |
9 | - 没安装yarn的,可以忽略以下yarn命令
10 |
11 | ```sh
12 | # set registry
13 | npm config set registry http://registry.npm.analysys.cn
14 |
15 | # install parcel
16 | yarn global add parcel-bundler | npm i -g parcel-bundler
17 |
18 | # install dependencies
19 | yarn | npm i
20 |
21 | # startup development server (defaults to 3000)
22 | # -> http://localhost:3000
23 | yarn start | npm start
24 | ```
25 |
26 | ### Lint
27 | ```sh
28 | yarn test | npm run test
29 | yarn lint:fix | npm run lint:fix
30 | ```
31 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/index.js:
--------------------------------------------------------------------------------
1 | import xDatepicker from './source/datepicker.vue'
2 | import dateUtil from 'dayjs'
3 |
4 | export { xDatepicker, dateUtil }
5 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/base/confirm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{text}}
5 |
6 | {{text}}
7 |
8 |
9 |
10 |
11 |
12 | {{t('ans.datepicker.cancel')}}
13 |
14 |
15 |
16 |
17 |
18 |
70 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/panel/date.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
115 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/panel/month.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
42 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/panel/time.vue:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/packages/vue-datepicker/src/source/panel/time.vue
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/panel/year.vue:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/packages/vue-datepicker/src/source/panel/year.vue
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/util/isType.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * 判断数据类型
4 | *
5 | */
6 |
7 | function isType (value) {
8 | const type = Object.prototype.toString.call(value)
9 | return type.match(/\[object (.*?)\]/)[1].toLowerCase()
10 | }
11 |
12 | export default isType
13 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/util/isValid.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * 验证日期是否合法
4 | *
5 | */
6 |
7 | import moment from 'dayjs'
8 |
9 | export default (date) => {
10 | // return Date.parse(date) > 0
11 | return moment(date).isValid()
12 | }
13 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/util/ishms.js:
--------------------------------------------------------------------------------
1 | export default (fmt) => {
2 | if (/[HhmsS]/.test(fmt)) {
3 | return 'second'
4 | }
5 |
6 | if (/[Hhm]/.test(fmt)) {
7 | return 'minute'
8 | }
9 |
10 | if (/[Hh]/.test(fmt)) {
11 | return 'hour'
12 | }
13 |
14 | return false
15 | }
16 |
--------------------------------------------------------------------------------
/packages/vue-datepicker/src/source/util/toDate.js:
--------------------------------------------------------------------------------
1 |
2 | export default () => {
3 | const date = new Date()
4 | return {
5 | year: date.getFullYear(),
6 | month: date.getMonth() + 1,
7 | today: date.getDate()
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/vue-drawer/README.md:
--------------------------------------------------------------------------------
1 | ## Drawer
2 |
3 | 抽屉从父窗体边缘滑入,覆盖住部分父窗体内容。
4 |
5 | ### Drawer options
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | direction | 出现位置 | String | left / right / top / bottom | right
10 | className | 自定义样式名称 | String | - | -
11 | closable | 是否显示关闭 | Boolean | - | false
12 | escClose | 是否按 esc 键关闭 | Boolean | - | true
13 | transitionName | 动画类名 | String | - | -
14 | showMask | 是否显示遮罩 | Boolean | - | true
15 | maskClosable | 是否关闭遮罩 | Boolean | - | true
16 | i18n | 国际化对象 | VueI18n | - | -
--------------------------------------------------------------------------------
/packages/vue-drawer/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 | left
7 | right
8 | top
9 | bottom
10 |
11 |
12 |
13 |
14 |
15 |
65 |
66 |
69 |
--------------------------------------------------------------------------------
/packages/vue-drawer/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-drawer/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App)
7 | })
8 |
--------------------------------------------------------------------------------
/packages/vue-drawer/example/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 测试文字
4 |
5 |
6 |
7 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/packages/vue-drawer/src/index.js:
--------------------------------------------------------------------------------
1 | import xDrawer from './source/drawer'
2 |
3 | export {
4 | xDrawer
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vue-drawer/src/source/drawer.js:
--------------------------------------------------------------------------------
1 | import { xModal } from '../../../vue-box/src'
2 | import { LIB_NAME } from '../../../../src/util/constants'
3 |
4 | const prefixCls = `${LIB_NAME}-drawer`
5 | const animationName = `${prefixCls}-animation`
6 |
7 | /**
8 | * @desc 推荐用 render 函数去创建 dom 在打开和关闭的 生命钩子函数由使用者自己通过事件的方式去实现
9 | * @desc 关闭的方法同 box
10 | * @param direction {String} ' left right top bottom | right'
11 | * @param className
12 | * @param showMask
13 | * @param maskClosable
14 | * @param escClose
15 | * @param render
16 | * */
17 | const defaultOpt = {
18 | transitionName: animationName,
19 | className: prefixCls,
20 | closable: false,
21 | direction: 'right',
22 | showMask: true,
23 | maskClosable: true,
24 | escClose: true
25 | }
26 |
27 | export default function (opt) {
28 | const options = Object.assign({}, defaultOpt, opt)
29 | const direction = options.direction
30 | options.className = opt.className ? `${defaultOpt.className} ${prefixCls}-${direction} ${opt.className}` : `${defaultOpt.className} ${prefixCls}-${direction}`
31 | options.transitionName = `${options.transitionName}-${options.direction}`
32 | return xModal.dialog(options)
33 | }
34 |
--------------------------------------------------------------------------------
/packages/vue-form/README.md:
--------------------------------------------------------------------------------
1 | ## Form
2 |
3 | 表单验证组件,基于`async-validator`开发。
4 |
5 | ### Form props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | model | 表单数据对象 | Object | - | -
10 | rules | 表单验证规则,详见`async-validator` | Object | - | -
11 | label-width | 表单域标签的的宽度 | Number / String | - | -
12 | label-height | 表单域标签的的高度 | Number / String | - | -
13 | vertical | 表单的标签和元素是否上下结构 | Boolean | - | false
14 |
15 | ### Form methods
16 |
17 | 方法名 | 说明 | 参数
18 | --- | --- | ---
19 | validate | 对整个表单进行校验,参数为检验完的回调,会返回一个 Boolean 表示成功与失败,支持 Promise | callback
20 | resetFields | 对整个表单进行重置,将所有字段值重置为空并移除校验结果 | —
21 | validateField | 对部分表单字段进行校验的方法,参数1为需校验的 prop,参数2为检验完回调,返回错误信息 | prop, callback
22 |
23 | ### FormItem props
24 |
25 | 属性 | 说明 | 类型 | 可选值 | 默认值
26 | --- | --- | --- | --- | ---
27 | prop | 对应表单域 model 里的字段 | String | - | -
28 | rules | 表单验证规则,会合并父级的规则 | Object / Array | - | -
29 | label | 标签文本 | String | - | -
30 | required | 是否必填,如不设置,则会根据校验规则自动生成 | Boolean | - | false
31 | label-width | 表单域标签的的宽度 | Number / String | - | -
32 | label-height | 表单域标签的的高度 | Number / String | - | -
33 | label-for | 指定原生的 label 标签的 for 属性 | String | - | -
34 |
35 | ### FormItem slots
36 |
37 | 名称 | 说明 | slot-scope 属性
38 | --- | --- | ---
39 | default | 内容 | -
40 | label | label内容 | -
41 | input | 使用原生input时用这个插入内容 | -
42 | select | 使用原生select时用这个插入内容 | -
--------------------------------------------------------------------------------
/packages/vue-form/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-form/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-form/src/index.js:
--------------------------------------------------------------------------------
1 | import xForm from './source/Form'
2 | import xFormItem from './source/FormItem'
3 |
4 | export {
5 | xForm,
6 | xFormItem
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-form/src/source/Form.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
99 |
--------------------------------------------------------------------------------
/packages/vue-input/README.md:
--------------------------------------------------------------------------------
1 | ## Input
2 |
3 | 基本表单组件,支持 input 和 textarea,并在原生控件基础上进行了功能扩展,可以组合使用。
4 |
5 | ### Input props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | type | 类型 | String | text、textarea 和其他原生 input 的 type 值 | text
10 | size | 尺寸,type="textarea" 时无效 | String | large / default / small | default
11 | value | 绑定值 | String / Number | — | —
12 | clearable | 是否可清空 | Boolean | — | false
13 | suffix-icon | 前置图标 | String | — | —
14 | prefix-icon | 后置图标 | String | — | —
15 | label | aria-label 属性 | String | — | —
16 | no-border | 是否无边框 | Boolean | — | false
17 | name | 原生属性 | String | — | —
18 | placeholder | 原生属性 | String | — | 请输入...
19 | disabled | 原生属性 | Boolean | — | false
20 | readonly | 原生属性 | Boolean | — | false
21 | autofocus | 原生属性 | Boolean | — | false
22 | autocomplete | 原生属性 | String | — | off
23 | maxlength | 原生属性 | Number | — | —
24 | minlength | 原生属性 | Number | — | —
25 | tabindex | 原生属性 | Number | — | —
26 | resize | 文本域是否可以拉伸 | String | — | —
27 | autosize | textarea 自适应,如 { minRows: 2, maxRows: 6 } | Boolean / Object | — | false
28 | rows | textarea 原生属性 | Number | — | 2
29 | validator-icon | 是否开启验证性的图标,在 form 表单中可开启 | Boolean | — | true
30 |
31 | ### Input slots
32 |
33 | 名称 | 说明
34 | --- | ---
35 | prefix | 前置图标插槽,插槽显示在输入框内
36 | suffix | 后置图标插槽,插槽显示在输入框内
37 | prepend | 前置内容插槽
38 | append | 后置内容插槽
39 |
40 | ### Input events
41 |
42 | 事件名称 | 说明 | 回调参数
43 | --- | --- | ---
44 | on-enterkey | 输入回车时触发 | event: Event
45 | on-click | 点击时触发 | event: Event
46 | on-blur | 失去焦点时触发 | event: Event
47 | on-focus | 获得焦点时触发 | event: Event
48 | on-change | 失去焦点并且输入值改变时触发 | value: String
49 | on-clear | 点击清空图标时触发 | —
50 | on-click-icon | 点击前置/后置图标时触发 | event: Event
51 |
52 | ### Input methods
53 |
54 | 方法名 | 说明 | 参数
55 | --- | --- | ---
56 | focus | 使 Input 组件获得焦点 | —
57 | blur | 使 Input 组件失去焦点 | —
58 | clear | 清空文本并且获得焦点 | —
--------------------------------------------------------------------------------
/packages/vue-input/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-input/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-input/src/index.js:
--------------------------------------------------------------------------------
1 | import xInput from './source/Input.vue'
2 |
3 | export {
4 | xInput
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vue-pagination/README.md:
--------------------------------------------------------------------------------
1 | ## Pagination
2 |
3 | 当数据量过多时,使用分页分解数据。
4 |
5 | ### Pagination props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | current | 当前页 | Number | - | 1
10 | total | 总数据条数 | Number | - | 0
11 | page-size | 每页数据条数 | Number | - | 10
12 | page-size-options | 每页条数切换的配置 | Array | - | [10, 20, 30, 40, 50]
13 | pager-count | 页码按钮的数量,当总页数超过该值时会折叠(奇数) | Number | - | 7
14 | show-total | 是否显示总条数 | Boolean | - | false
15 | show-elevator | 是否显示跳转页 | Boolean | - | false
16 | show-sizer | 是否显示每页条数切换栏 | Boolean | - | false
17 | simple | 是否使用简洁版 | Boolean | - | false
18 | small | 是否显示迷你版 | Boolean | - | false
19 |
20 | #### Pagination events
21 |
22 | 事件名称 | 说明 | 返回值
23 | --- | --- | ---
24 | on-size-change | pageSize 改变时会触发 | 每页条数
25 | on-change | 页码切换时触发 | 返回当前页码
26 |
--------------------------------------------------------------------------------
/packages/vue-pagination/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | 显示总条数
11 |
12 |
13 |
14 |
15 |
16 | 跳转
17 |
18 |
19 |
20 |
21 |
22 | 每页条数
23 |
24 |
25 |
26 |
27 |
28 | 无边框
29 |
30 |
31 |
32 |
33 |
34 | 迷你版
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/packages/vue-pagination/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-pagination/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-pagination/src/index.js:
--------------------------------------------------------------------------------
1 | import xPage from './source/Page.vue'
2 |
3 | export { xPage }
4 |
--------------------------------------------------------------------------------
/packages/vue-poptip/README.md:
--------------------------------------------------------------------------------
1 | ## Poptip
2 |
3 | 以卡片的形式承载了更多的内容,比如链接、表格、按钮等。
4 |
5 | ### Poptip props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | trigger | 触发方式 | String | hover, click, focus, 在 confirm 模式下,只有 click 有效 | click
10 | placement | 出现位置 | String | 详见popper.js文档 | top
11 | title | 标题 | String | — | —
12 | content | 显示的正文内容,只在非 confirm 模式下有效 | String | — | —
13 | disabled | 是否禁用 | Boolean | — | —
14 | width | 宽度 | Number | — | —
15 | visible-arrow | 是否显示箭头 | Boolean | — | true
16 | confirm | 是否开启对话框模式 | Boolean | — | false
17 | ok-text | 确定按钮的文字,只在 confirm 模式下有效 | String | — | 确定
18 | cancel-text | 取消按钮的文字,只在 confirm 模式下有效 | String | — | 取消
19 | distance | 弹出层与触发元素的距离 | Number | — | 5
20 | popper-class | 弹出层自定义样式 | String | — | —
21 | append-to-body | 弹出层是否插入 body | Boolean | — | false
22 | position-fixed | 弹出层是否 fixed 定位 | Boolean | — | false
23 | viewport | 弹出层是否基于 viewport 定位 | Boolean | — | false
24 | popper-options | Popper.js 的可选项 | Object | — | —
25 |
26 | ### Poptip slots
27 |
28 | 名称 | 说明
29 | --- | ---
30 | default | 内嵌 HTML 文本
31 | reference | 触发元素
32 |
33 | ### Poptip events
34 |
35 | 事件名称 | 说明 | 回调参数
36 | --- | --- | ---
37 | on-ok | 点击确定的回调 | —
38 | on-cancel | 点击取消的回调 | —
--------------------------------------------------------------------------------
/packages/vue-poptip/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基础用法
5 |
6 |
13 |
14 |
15 |
22 |
23 |
24 | hover 激活
25 | click 激活
26 |
27 |
34 | focus 激活
35 | 我是title
36 |
37 |
38 |
48 | manual 激活
49 |
50 |
51 |
52 |
53 | 嵌套操作
54 |
55 |
60 | 这是一段内容这是一段内容确定删除吗?
61 |
62 | 取消
63 | 确定
64 |
65 |
66 |
删除
67 |
68 |
69 |
70 |
71 |
72 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/packages/vue-poptip/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-poptip/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 | import { xPoptip } from '../src'
4 |
5 | Vue.use(xPoptip)
6 |
7 | new Vue({
8 | el: '#app',
9 | render: h => h(App),
10 | mounted () {
11 | console.log('success')
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/packages/vue-poptip/src/index.js:
--------------------------------------------------------------------------------
1 | import xPoptip from './source/Poptip.vue'
2 | import directive from './source/directive'
3 |
4 | xPoptip.directive = directive
5 |
6 | /* istanbul ignore next */
7 | xPoptip.install = Vue => {
8 | Vue.directive('poptip', directive)
9 | }
10 |
11 | export {
12 | xPoptip
13 | }
14 |
--------------------------------------------------------------------------------
/packages/vue-poptip/src/source/directive.js:
--------------------------------------------------------------------------------
1 | export default {
2 | bind (el, binding, vnode) {
3 | // vue 中 v-popover:argument 和 v-popover="variate || expression" 得到的 binding 数据是不同的。
4 | // 后者可以指向动态 popver 组件,可极大的增强popover指令的灵活程度。
5 | const ref = binding.expression ? binding.value : binding.arg
6 | ref && vnode.context.$refs[ref] && (vnode.context.$refs[ref].$refs.reference = el)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/vue-progress/README.md:
--------------------------------------------------------------------------------
1 | ## Progress
2 |
3 | 用于展示操作进度,告知用户当前状态和预期。
4 |
5 | ### Progress props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | percentage | 百分比,必选项 | Number | 0-100 | 0
10 | type | 进度条类型 | String | line / circle | line
11 | stroke-width | 进度条的宽度,单位 px | Number | — | 8
12 | status | 进度条当前状态 | String | success / exception | —
13 | color | 进度条背景色(会覆盖 status 状态颜色) | String | — | —
14 | width | 环形进度条宽度(只在 type=circle 时有效) | Number | — | 100
15 | show-inline-text | 是否显示进度条上(type=line 时)文字内容 | Boolean | — | false
16 | show-outside-text | 是否显示进度条右侧文字内容(只在 type=line 时有效) | Boolean | — | true
17 | show-circle-text | 是否显示环形进度条里面(type=circle 时)文字内容 | Boolean | — | true
18 |
19 | ### Progress slots
20 |
21 | 名称 | 说明
22 | --- | ---
23 | inline | type=line 时进度条上内容插槽
24 | outside | type=line 时进度条右侧的内容插槽
25 | circle | type=circle 时环形进度条里面的内容插槽
--------------------------------------------------------------------------------
/packages/vue-progress/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-progress/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-progress/src/index.js:
--------------------------------------------------------------------------------
1 | import xProgress from './source/Progress.vue'
2 |
3 | export {
4 | xProgress
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vue-radio/README.md:
--------------------------------------------------------------------------------
1 | ## Radio
2 |
3 | 用于一组可选项单项选择,或者单独用于切换到选中状态。
4 |
5 | ### Radio props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | value | 单独使用时有效,可用于v-model双向绑定 | Boolean | - | false
10 | name | 原生name属性 | String | - | -
11 | label | 组合使用时有效,指定当前选项value值 | String / Number | - | -
12 | disabled | 是否禁用 | Boolean | - | false
13 | size | 尺寸 | String | large / default / small | default
14 | true-value | 自定义选中时的值,当使用类似 1 和 0 来判断是否选中时会很有用 | String / Number / Boolean | - | true
15 | false-value | 自定义未选中时的值,当使用类似 1 和 0 来判断是否选中时会很有用 | String / Number / Boolean | - | false
16 |
17 | ### Radio events
18 |
19 | 事件名称 | 说明 | 返回值
20 | --- | --- | ---
21 | on-change | 在选项状态发生改变时触发,返回当前状态。通过修改外部的数据改变时不会触发 | 选中的 Radio value 值
22 |
23 | ### RadioGroup props
24 |
25 | 属性 | 说明 | 类型 | 可选值 | 默认值
26 | --- | --- | --- | --- | ---
27 | value | 当前选中的值,可用于v-model双向绑定 | String / Number / Boolean | - | -
28 | name | 原生name属性,优先级小于radio的 name 属性 | String | - | -
29 | size | 尺寸 | String | large、default、small | default
30 | vertical | 是否垂直显示 | Boolean | - | false
31 |
32 | ### RadioGroup events
33 |
34 | 事件名称 | 说明 | 返回值
35 | --- | --- | ---
36 | on-change | 在选项状态发生改变时触发,返回当前状态。通过修改外部的数据改变时不会触发 | 选中的 Radio label 值
--------------------------------------------------------------------------------
/packages/vue-radio/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 单独使用
5 |
6 |
{{ disabledSingle }}
7 |
{{ disabledSingle2 }}
8 |
9 |
10 |
11 | 大小
12 |
13 | large
14 | default
15 | small
16 |
17 |
18 |
19 | 组合
20 |
21 |
22 | small
23 | default
24 | large
25 |
26 |
27 |
28 |
29 | 状态
30 |
31 |
32 | 我是千帆(禁用)
33 | 我是万像
34 | 我是方舟
35 |
36 |
37 |
38 |
39 | 垂直排列
40 |
41 |
42 | 我是千帆(禁用)
43 | 我是万像
44 | 我是方舟
45 |
46 |
47 |
48 |
49 |
50 |
51 |
68 |
69 |
72 |
--------------------------------------------------------------------------------
/packages/vue-radio/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-radio/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-radio/src/index.js:
--------------------------------------------------------------------------------
1 | import xRadio from './source/Radio.vue'
2 | import xRadioGroup from './source/RadioGroup.vue'
3 |
4 | export {
5 | xRadio,
6 | xRadioGroup
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-radio/src/source/RadioGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
75 |
--------------------------------------------------------------------------------
/packages/vue-scroller/README.md:
--------------------------------------------------------------------------------
1 | ## Scroller
2 |
3 | 滚动视图
4 |
5 | ### Scroller props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | width | 视图宽度,当插槽内容宽度超过该值时出现水平滚动条 | String / Number | — | —
10 | max-width | 视图最大宽度,当插槽内容宽度超过该值时出现水平滚动条 | String / Number | — | —
11 | height | 视图高度,当插槽内容高度超过该值时出现垂直滚动条 | String / Number | — | —
12 | max-height | 视图最大高度,当插槽内容高度超过该值时出现垂直滚动条 | String / Number | — | —
13 | scrollbar-class | 滚动条自定义类 | String | — | —
14 | reverse-scroll-y | 是否反转 Y 轴滚轮,当该值为 true 时,滚动 Y 轴将控制水平方向的滚动 | Boolean | — | false
15 | show-scrollbar | 是否显示滚动条,当设置为`active`时,触发滚动或者鼠标移动到滚动条轨迹上时才会显示滚动条 | Boolean / String | true / false / 'active' | true
16 | check-on-mounted | 是否在 mounted 的时候递归调用 checkScrollable 方法,直到内容的宽度和高度不为 0 | Boolean | — | false
17 | bar-offset-left | 水平滚动条距离视图左侧的偏移 | Number | — | 0
18 | bar-offset-right | 水平滚动条距离视图右侧的偏移 | Number | — | 0
19 | bar-offset-top | 垂直滚动条距离视图顶部的偏移 | Number | — | 0
20 | bar-offset-bottom | 垂直滚动条距离视图底部的偏移 | Number | — | 0
21 |
22 | ### Scroller events
23 |
24 | 事件名称 | 说明 | 回调参数
25 | --- | --- | ---
26 | on-scroll-x | 水平滚动改变时触发 | 当前的 left 值,是否达到最左侧,是否达到最右侧
27 | on-scroll-y | 垂直滚动改变时触发 | 当前的 top 值,是否达到最顶部,是否达到最底部
28 | on-start-drag-bar | 开始拖动滚动条时触发 | 是否垂直滚动条
29 | on-end-drag-bar | 结束拖动滚动条时触发 | 是否垂直滚动条
30 |
31 | ### Scroller methods
32 |
33 | 方法名 | 说明 | 参数
34 | --- | --- | ---
35 | checkScrollable | 检查当前是否需要显示滚动条 | —
36 | setContentLeft | 设置内容区域的 left 值 | left: Number, transition: Boolean
37 | setContentTop | 设置内容区域的 top 值 | top: Number, transition: Boolean
38 | stickToBoundary | 将内容区域设置到指定边界 | vertical: Boolean, start: Boolean, transition: Boolean
39 |
--------------------------------------------------------------------------------
/packages/vue-scroller/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
45 |
--------------------------------------------------------------------------------
/packages/vue-scroller/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/vue-scroller/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-scroller/src/index.js:
--------------------------------------------------------------------------------
1 | import xScroller from './source/Scroller.vue'
2 |
3 | export {
4 | xScroller
5 | }
6 |
--------------------------------------------------------------------------------
/packages/vue-select/README.md:
--------------------------------------------------------------------------------
1 | ## Select
2 |
3 | 使用模拟的增强下拉选择器来代替浏览器原生的选择器。
4 |
5 | ### Select props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | value | 绑定值 | String / Number / Object / Array | — | —
10 | value-key | 当绑定值为对象或者对象数组时,通过该属性值判断 Option 是否被选中,否则将比较对象是否相等 | String | — | —
11 | name | select 组件中 input 的原生属性 | String | — | —
12 | placeholder | select 组件中 input 的原生属性 | String | — | 请选择
13 | input-props | select 组件中 input 组件的属性 | Object | — | —
14 | width | 下拉框的宽度,默认与触发元素的宽度相同 | String / Number | — | —
15 | height | 下拉框的高度,超出该高度出现滚动条 | String / Number | — | —
16 | max-height | 下拉框的最大高度,超出该高度出现滚动条 | String / Number | — | 300
17 | add-title | 是否在选项中增加 title 属性,显示超长的文本 | Boolean | — | false
18 | disabled | select 组件中 input 的原生属性 | Boolean | — | false
19 | clearable | 是否可清空已选项 | Boolean | — | false
20 | multiple | 是否开启多选 | Boolean | — | false
21 | filterable | 是否开启搜索功能 | Boolean | — | false
22 | filter-props | 当 option 的绑定值为对象时,搜索查找的对应属性列表 | Array | — | —
23 | no-data-text | 选项为空时显示的文字 | String | — | 暂无数据
24 | no-data-icon | 选项为空时显示的图标类名 | String | — | ans-icon-no-data
25 | highlight-matched-text | 搜索时是否高亮选项中匹配的文字 | Boolean | — | false
26 | ignore-case | 搜索时是否忽略大小写,可以和 filter-props 以及 highlight-matched-text 配合使用 | Boolean | — | false
27 | no-match-text | 搜索没有任何匹配项时显示的文字 | String | — | 搜索无结果
28 | no-match-icon | 搜索没有任何匹配项时显示的图标类名 | String | — | ans-icon-search-no-data
29 | has-arrow | 下拉框是否显示指示箭头 | Boolean | — | false
30 | append-to-body | 下拉框是否插入 body | Boolean | — | false
31 | position-fixed | 下拉框是否 fixed 定位 | Boolean | — | false
32 | viewport | 下拉框是否基于 viewport 定位 | Boolean | — | false
33 | popper-options | Popper.js 的可选项 | Object | — | —
34 | dropdown-class | 下拉框样式 | String | — | —
35 | scrollbar-class | 滚动条样式 | String | — | —
36 | drop-animation | 下拉框动画 | String | — | —
37 |
38 | ### Select events
39 |
40 | 事件名称 | 说明 | 回调参数
41 | --- | --- | ---
42 | on-change | 选中值发生变化时触发 | 目前的选中值,{ value: value, label: label }
43 | on-visible-change | 下拉框状态改变时触发 | 出现则为 true,隐藏则为 false
44 | on-keyword-change | 搜索关键字改变时触发 | keyword
45 |
46 | ### Select methods
47 |
48 | 方法名 | 说明 | 参数
49 | --- | --- | ---
50 | focus | 使 Input 组件获得焦点 | —
51 | blur | 使 input 失去焦点并且隐藏下拉框 | —
52 | search | 搜索 | keyword
53 | updateScrollbar | 更新下拉框内的滚动条 | —
54 | resetScrollbar | 将滚动条移回到顶部 | —
55 | setDropdownReference | 手动指定下拉框的触发元素 | dom 元素
56 |
57 | ### Select slots
58 |
59 | 名称 | 说明 | slot-scope 属性
60 | --- | --- | ---
61 | trigger | Select 组件触发元素的插槽 | selectedModel
62 | multiple | 开启多选时,控制 input 内如何显示的插槽 | selectedList
63 | header | 下拉框头部插槽,必须使用作用域插槽 | —
64 | footer | 下拉框底部插槽,必须使用作用域插槽 | —
65 |
66 | ### OptionGroup props
67 |
68 | 属性 | 说明 | 类型 | 可选值 | 默认值
69 | --- | --- | --- | --- | ---
70 | label | 分组类别名称 | String | — | —
71 |
72 | ### OptionGroup slots
73 |
74 | 名称 | 说明
75 | --- | ---
76 | content | 控制分组标签如何显示的插槽
77 |
78 | ### Option props
79 |
80 | 属性 | 说明 | 类型 | 可选值 | 默认值
81 | --- | --- | --- | --- | ---
82 | value | 绑定值,可以直接绑定对象,必选项 | String / Number / Object | — | —
83 | label | 选项文本,必选项 | String / Number | — | —
84 | disabled | 是否不可选 | Boolean | — | false
85 | click-handler | 覆盖默认的点击处理,使用该属性意味着需要自己处理选择逻辑 | Function(value, label) | — | —
--------------------------------------------------------------------------------
/packages/vue-select/example/dynamic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 动态 Option
5 |
6 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
74 |
75 |
129 |
--------------------------------------------------------------------------------
/packages/vue-select/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-select/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './navigation.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-select/example/navigation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 键盘导航
5 |
6 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
52 |
53 |
107 |
--------------------------------------------------------------------------------
/packages/vue-select/src/index.js:
--------------------------------------------------------------------------------
1 | import xSelect from './source/Select.vue'
2 | import xOption from './source/Option.vue'
3 | import xOptionGroup from './source/OptionGroup.vue'
4 |
5 | export {
6 | xSelect,
7 | xOption,
8 | xOptionGroup
9 | }
10 |
--------------------------------------------------------------------------------
/packages/vue-select/src/source/OptionGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 | {{label}}
6 |
7 |
8 | -
9 |
12 |
13 |
14 |
15 |
16 |
41 |
--------------------------------------------------------------------------------
/packages/vue-spin/README.md:
--------------------------------------------------------------------------------
1 | ## Spin
2 |
3 | 加载数据时显示遮罩和提示。
4 |
5 | ### Spin 指令修饰符
6 |
7 | 修饰符 | 说明
8 | --- | ---
9 | fullscreen | 全屏
10 | lock | 锁定滚动,隐藏滚动条,仅在 fullscreen 为 true 时可用
11 | body | 指定 DOM 节点插入 body 中
12 |
13 | ### Spin 绑定元素属性
14 |
15 | 属性名称 | 说明
16 | --- | ---
17 | spin-text | 加载图标下方文字
18 | spin-background | 遮罩背景色
19 | spin-icon-class | 自定义加载图标类名
20 | spin-custom-class | spin 的自定义类名
21 |
22 | ### Spin 服务配置
23 |
24 | 属性 | 说明 | 类型 | 可选值 | 默认值
25 | --- | --- | --- | --- | ---
26 | target | spin 需要覆盖的 DOM 节点。可传入一个 DOM 对象或字符串;若传入字符串,则会将其作为参数传 document.querySelector 以获取到对应 DOM 节点 | Object / String | — | document.body
27 | body | 同 v-spin 指令中的 body 修饰符 | Boolean | — | false
28 | fullscreen | 同 v-spin 指令中的 fullscreen 修饰符 | Boolean | — | true
29 | lock | 同 v-spin 指令中的 lock 修饰符 | Boolean |— | false
30 | text | 加载图标下方文字 | String | — | —
31 | background | 遮罩背景色 | String | — | —
32 | iconClass | 自定义加载图标类名 | String | — | —
33 | customClass | spin 的自定义类名 | String | — | —
--------------------------------------------------------------------------------
/packages/vue-spin/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-spin/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 | import { xSpin } from '../src'
4 |
5 | Vue.use(xSpin)
6 |
7 | new Vue({
8 | el: '#app',
9 | render: h => h(App),
10 | mounted () {
11 | console.log('success')
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/packages/vue-spin/src/index.js:
--------------------------------------------------------------------------------
1 | import xSpin from './source/Spin.vue'
2 | import directive from './source/directive'
3 | import { init, defaults } from './source/service'
4 |
5 | xSpin.init = init
6 |
7 | xSpin.install = (Vue, options = {}) => {
8 | const { directiveName = 'spin', text, background, iconClass, customClass } = options
9 | defaults.text = text
10 | defaults.background = background
11 | defaults.iconClass = iconClass
12 | defaults.customClass = customClass
13 | Vue.directive(directiveName, directive)
14 | Vue.prototype.$spin = xSpin.init
15 | }
16 |
17 | export { xSpin }
18 |
--------------------------------------------------------------------------------
/packages/vue-spin/src/source/Spin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
{{ text }}
24 |
25 |
26 |
27 |
28 |
29 |
58 |
--------------------------------------------------------------------------------
/packages/vue-spin/src/source/service.js:
--------------------------------------------------------------------------------
1 | import { addClass, removeClass, getStyle } from '../../../../src/util'
2 | import Vue from 'vue'
3 | import xSpin from './Spin.vue'
4 |
5 | const SpinConstructor = Vue.extend(xSpin)
6 |
7 | const defaults = {
8 | body: false,
9 | fullscreen: true,
10 | lock: false,
11 | text: null,
12 | background: null,
13 | iconClass: '',
14 | customClass: ''
15 | }
16 |
17 | let fullscreenLoading
18 |
19 | SpinConstructor.prototype.originalPosition = ''
20 |
21 | SpinConstructor.prototype.close = function () {
22 | if (this.fullscreen) {
23 | fullscreenLoading = undefined
24 | }
25 | this.visible = false
26 | }
27 |
28 | const addStyle = (options, parent, instance) => {
29 | if (options.fullscreen) {
30 | instance.originalPosition = getStyle(document.body, 'position')
31 | } else if (options.body) {
32 | instance.originalPosition = getStyle(document.body, 'position')
33 | const spinStyle = instance.$el.style
34 | ;['top', 'left'].forEach(property => {
35 | const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft'
36 | spinStyle[property] = options.target.getBoundingClientRect()[property] +
37 | document.body[scroll] +
38 | document.documentElement[scroll] -
39 | parseInt(getStyle(document.body, `margin-${property}`), 10) + 'px'
40 | })
41 | ;['height', 'width'].forEach(property => {
42 | spinStyle[property] = options.target.getBoundingClientRect()[property] + 'px'
43 | })
44 | } else {
45 | instance.originalPosition = getStyle(parent, 'position')
46 | }
47 | }
48 |
49 | const init = (options = {}) => {
50 | options = Object.assign({}, defaults, options)
51 | if (typeof options.target === 'string') {
52 | options.target = document.querySelector(options.target)
53 | }
54 | options.target = options.target || document.body
55 | if (options.target !== document.body) {
56 | options.fullscreen = false
57 | } else {
58 | options.body = true
59 | }
60 | if (options.fullscreen && fullscreenLoading) {
61 | return fullscreenLoading
62 | }
63 |
64 | const parent = options.body ? document.body : options.target
65 | const instance = new SpinConstructor({
66 | el: document.createElement('div'),
67 | data: options
68 | })
69 | options.onAfterLeave = () => {
70 | removeClass(parent, 'spin-relative-parent')
71 | removeClass(parent, 'spin-lock-overflow')
72 | parent.removeChild(instance.$el)
73 | instance.$destroy()
74 | }
75 |
76 | addStyle(options, parent, instance)
77 | if (instance.originalPosition !== 'absolute' && instance.originalPosition !== 'fixed') {
78 | addClass(parent, 'spin-relative-parent')
79 | }
80 | if (options.fullscreen && options.lock) {
81 | addClass(parent, 'spin-lock-overflow')
82 | }
83 | parent.appendChild(instance.$el)
84 | Vue.nextTick(() => {
85 | instance.visible = true
86 | })
87 | if (options.fullscreen) {
88 | fullscreenLoading = instance
89 | }
90 | return instance
91 | }
92 |
93 | export {
94 | init,
95 | defaults
96 | }
97 |
--------------------------------------------------------------------------------
/packages/vue-switch/README.md:
--------------------------------------------------------------------------------
1 | ## Switch
2 |
3 | 在两种状态间切换时用到的开关选择器。
4 |
5 | ### Switch props
6 |
7 | 属性 | 说明 | 类型 | 可选值 | 默认值
8 | --- | --- | --- | --- | ---
9 | name | 表单原始name属性 | String / Number / Boolean | - | -
10 | value | 开关当前值 | Boolean | - | false
11 | text | 开关内显示的文本 | Object | {on: '',off: ''} | {on: '',off: ''}
12 | readonly | 只读状态 | Boolean | - | false
13 | disabled | 禁用状态 | Boolean | - | false
14 | size | 开关大小 | String | large / default / small | default
15 | true-value | 自定义选中时的值,当使用类似 1 和 0 来判断是否选中时会很有用 | String / Number / Boolean | - | true
16 | false-value | 自定义未选中时的值,当使用类似 1 和 0 来判断是否选中时会很有用 | String / Number / Boolean | - | false
17 |
18 | ### Switch events
19 |
20 | 事件名称 | 说明 | 回调参数
21 | --- | --- | ---
22 | on-click | 点击开关时触发 | 当前 value 值
23 | on-change | 开关变化时触发,显示当前状态 | 当前 value 值
--------------------------------------------------------------------------------
/packages/vue-switch/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基本用法
5 |
6 |
7 | {{checked}}
8 |
9 |
10 |
11 | 禁用状态
12 |
13 |
14 |
15 |
16 |
17 | 文本
18 |
19 |
20 | {{checked}}
21 |
22 |
23 |
24 | 大小
25 |
26 |
27 |
28 |
29 | {{checked}}
30 |
31 |
32 |
33 |
34 |
35 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/packages/vue-switch/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-switch/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-switch/src/index.js:
--------------------------------------------------------------------------------
1 | import xSwitch from './source/Switch.vue'
2 |
3 | export { xSwitch }
4 |
--------------------------------------------------------------------------------
/packages/vue-switch/src/source/Switch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
108 |
--------------------------------------------------------------------------------
/packages/vue-table/example/array.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
列表支持
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
32 |
--------------------------------------------------------------------------------
/packages/vue-table/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | demo
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/packages/vue-table/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-table/example/paging.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
性能演示
4 |
5 |
6 |
16 |
17 | 这是前置插槽{{scope.$index}}
18 |
19 |
20 | 这是后置插槽{{scope.$index}}
21 |
22 |
23 | 这是表头文本插槽
24 | {{scope.column.label}}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
84 |
--------------------------------------------------------------------------------
/packages/vue-table/example/restrict.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
restrict 属性
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
75 |
--------------------------------------------------------------------------------
/packages/vue-table/example/sort.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
排序测试
4 |
5 |
12 |
13 |
14 |
15 |
16 |
66 |
--------------------------------------------------------------------------------
/packages/vue-table/example/tree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
table tree
4 |
5 |
10 |
11 | {{content}} + 'abc'
12 |
13 |
14 |
15 |
16 |
17 |
18 |
71 |
--------------------------------------------------------------------------------
/packages/vue-table/src/index.js:
--------------------------------------------------------------------------------
1 | import xTable from './source/Table.vue'
2 | import xTableColumn from './source/TableColumn.vue'
3 |
4 | export {
5 | xTable,
6 | xTableColumn
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue-table/src/source/CellRenderer.vue:
--------------------------------------------------------------------------------
1 |
52 |
--------------------------------------------------------------------------------
/packages/vue-table/src/source/layoutObserver.js:
--------------------------------------------------------------------------------
1 | export default {
2 | created () {
3 | this.tableLayout.addObserver(this)
4 | },
5 |
6 | destroyed () {
7 | this.tableLayout.removeObserver(this)
8 | },
9 |
10 | computed: {
11 | tableLayout () {
12 | let layout = this.layout
13 | if (!layout && this.table) {
14 | layout = this.table.layout
15 | }
16 | if (!layout) {
17 | throw new Error('Layout Observer: Can\'t find table layout.')
18 | }
19 | return layout
20 | }
21 | },
22 |
23 | methods: {
24 | onColumnsChange () {
25 | const cols = this.$el.querySelectorAll('colgroup > col')
26 | if (!cols.length) return
27 | const columnsMap = this.store.states.leafColumnMap
28 | for (let i = 0, j = cols.length; i < j; i++) {
29 | const col = cols[i]
30 | const name = col.getAttribute('name')
31 | const column = columnsMap[name]
32 | if (column) {
33 | col.setAttribute('width', column.currentWidth)
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/vue-timepicker/README.md:
--------------------------------------------------------------------------------
1 | An component project
2 |
3 | ### Setup
4 |
5 | - 安装node > 8的LTS版本,https://nodejs.org/en/
6 |
7 | - 增加npm本地仓库host,106.75.23.50 npm.analysys.cn
8 |
9 | - 没安装yarn的,可以忽略以下yarn命令
10 |
11 | ```sh
12 | # set registry
13 | npm config set registry http://registry.npm.analysys.cn
14 |
15 | # install parcel
16 | yarn global add parcel-bundler | npm i -g parcel-bundler
17 |
18 | # install dependencies
19 | yarn | npm i
20 |
21 | # startup development server (defaults to 3000)
22 | # -> http://localhost:3000
23 | yarn start | npm start
24 | ```
25 |
26 | ### Lint
27 | ```sh
28 | yarn test | npm run test
29 | yarn lint:fix | npm run lint:fix
30 | ```
31 |
--------------------------------------------------------------------------------
/packages/vue-timepicker/example/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 | 选择时分
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 时间区间
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
41 |
--------------------------------------------------------------------------------
/packages/vue-timepicker/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-timepicker/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App),
7 | mounted () {
8 | console.log('success')
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/vue-timepicker/src/index.js:
--------------------------------------------------------------------------------
1 | import xTimepicker from './source/Timepicker.vue'
2 |
3 | export { xTimepicker }
4 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/README.md:
--------------------------------------------------------------------------------
1 | ## Tooltip
2 |
3 | 简单的文字提示工具,用于代替浏览器的 title 提示。
4 |
5 | ### Tooltip 指令修饰符
6 |
7 | 修饰符 | 说明
8 | --- | ---
9 | click | 点击触发提示
10 | top / bottom / left / right | 提示优先方向,分别对应上/下/左/右
11 | start / end | 提示位置,可与方向组合使用
12 | light / dark | 主题,默认为 dark
13 | fixed | 提示是否 fixed 定位
14 | viewport | 提示是否基于 viewport 定位
15 | large | 是否启用大号提示
16 |
17 | ### Tooltip 详细配置
18 |
19 | 属性 | 说明 | 类型 | 可选值 | 默认值
20 | --- | --- | --- | --- | ---
21 | text | 提示文本,支持标签 | String | — | —
22 | placement | 提示优先出现方位 | 详见popper.js文档 | top
23 | triggerEvent | 触发提示事件 | String | click / mouseenter / manual | mouseenter
24 | theme | 主题 | String | light / dark | dark
25 | maxWidth | 提示内容最大宽度,超过该宽度换行 | String | — | 200px
26 | positionFixed | 同 fixed 修饰符 | Boolean | — | false
27 | viewport | 同 viewport 修饰符 | Boolean | — | false
28 | large | 同 large 修饰符 | Boolean | — | false
29 | reveal | 当 triggerEvent 为 `manual` 的时候,控制 tooltip 是否显示 | Boolean | — | false
30 |
31 | ### Tooltip 方法
32 |
33 | tooltip 对应的 dom 节点可以调用 destroy 方法销毁组件,hide 方法隐藏提示
34 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 | import { xTooltip } from '../src'
4 |
5 | Vue.use(xTooltip)
6 |
7 | new Vue({
8 | el: '#app',
9 | render: h => h(App),
10 | mounted () {
11 | console.log('success')
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/src/index.js:
--------------------------------------------------------------------------------
1 | import xTooltip from './source/Tooltip.vue'
2 | import directive from './source/directive'
3 |
4 | xTooltip.install = (Vue, options = {}) => {
5 | const { directiveName = 'tooltip' } = options
6 | Vue.directive(directiveName, directive)
7 | }
8 |
9 | export {
10 | xTooltip
11 | }
12 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/src/source/Tooltip.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
82 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/src/source/directive.js:
--------------------------------------------------------------------------------
1 | import factory from './factory'
2 |
3 | const PLACEMENTS = ['top', 'bottom', 'left', 'right']
4 | const POSITIONS = ['start', 'end']
5 |
6 | export default {
7 | bind (el, binding) {
8 | // 移除事件
9 | removeListeners(el)
10 | // 是否点击触发,是否浅色主题
11 | const { click, light, fixed, viewport, large } = binding.modifiers
12 | // 位置使用第一个修饰符,不传则居中
13 | const positionModifiers = POSITIONS.filter(position => binding.modifiers[position])
14 | const position = positionModifiers.length ? positionModifiers[0] : ''
15 | // 方向使用第一个修饰符,不传则默认为 top
16 | const placementModifiers = PLACEMENTS.filter(placement => binding.modifiers[placement])
17 | let placement = placementModifiers.length ? placementModifiers[0] : 'top'
18 | placement = position ? `${placement}-${position}` : placement
19 | // 默认配置
20 | const defaultOptions = {
21 | placement,
22 | triggerEvent: click ? 'click' : 'mouseenter',
23 | theme: light ? 'light' : 'dark',
24 | maxWidth: '370px',
25 | positionFixed: !!fixed,
26 | viewport: !!viewport,
27 | large: !!large
28 | }
29 | // 可以绑定配置对象
30 | let options = typeof binding.value === 'object' ? binding.value : { text: binding.value }
31 | options = Object.assign({}, defaultOptions, options)
32 | options.el = el
33 | el._ttOptions = options
34 | // 绑定事件监听
35 | el._appearHandler = function appearHandler () {
36 | if (!this._ttInstance) {
37 | // 确保使用最新的配置
38 | this._ttInstance = factory(this._ttOptions)
39 | }
40 | if (this._ttOptions.text) {
41 | this._ttInstance.show()
42 | }
43 | }
44 | el._vanishHandler = function vanishHandler () {
45 | if (this._ttInstance) {
46 | this._ttInstance.hide()
47 | }
48 | }
49 | if (options.triggerEvent === 'manual') {
50 | el._ttInstance = factory(options)
51 | } else {
52 | el.addEventListener(options.triggerEvent, el._appearHandler)
53 | el.addEventListener('mouseleave', el._vanishHandler)
54 | }
55 | },
56 |
57 | update (el, binding) {
58 | // 刷新配置
59 | let options = typeof binding.value === 'object' ? binding.value : { text: binding.value }
60 | options = Object.assign({}, el._ttOptions, options)
61 | options.el = el
62 | el._ttOptions = options
63 | if (el._ttInstance) {
64 | el._ttInstance.update(options)
65 | }
66 | },
67 |
68 | unbind (el) {
69 | const instance = el._ttInstance
70 | if (instance && instance.$destroy) {
71 | instance.$destroy()
72 | }
73 | removeListeners(el)
74 | delete el._appearHandler
75 | delete el._vanishHandler
76 | delete el._ttInstance
77 | delete el._ttOptions
78 | }
79 | }
80 |
81 | function removeListeners (el) {
82 | if (el._appearHandler) {
83 | el.removeEventListener('click', el._appearHandler)
84 | el.removeEventListener('mouseenter', el._appearHandler)
85 | }
86 | if (el._vanishHandler) {
87 | el.removeEventListener('mouseleave', el._vanishHandler)
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/packages/vue-tooltip/src/source/factory.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Tooltip from './Tooltip.vue'
3 |
4 | // 组件构造器
5 | const TooltipConstructor = Vue.extend(Tooltip)
6 |
7 | export default (options = {}) => {
8 | const {
9 | triggerEvent,
10 | text = '',
11 | placement,
12 | theme,
13 | maxWidth,
14 | el,
15 | positionFixed,
16 | viewport,
17 | large,
18 | reveal
19 | } = options
20 | const instance = new TooltipConstructor({
21 | propsData: {
22 | triggerEvent,
23 | content: text,
24 | placement,
25 | theme,
26 | maxWidth,
27 | reference: el,
28 | positionFixed: positionFixed,
29 | viewport: viewport,
30 | large,
31 | reveal
32 | }
33 | }).$mount()
34 | document.body.appendChild(instance.$el)
35 | instance.$el.destroy = () => {
36 | instance.$destroy()
37 | }
38 | instance.$el.hide = () => {
39 | instance.hide()
40 | }
41 | return instance
42 | }
43 |
--------------------------------------------------------------------------------
/src/locale/format.js:
--------------------------------------------------------------------------------
1 | const RE_NARGS = /(%|)\{([0-9a-zA-Z_]+)\}/g
2 | /**
3 | * String format template
4 | * - Inspired:
5 | * https://github.com/Matt-Esch/string-template/index.js
6 | */
7 | export default function (Vue) {
8 | /**
9 | * template
10 | *
11 | * @param {String} string
12 | * @param {Array} ...args
13 | * @return {String}
14 | */
15 |
16 | function template (string, ...args) {
17 | if (args.length === 1 && typeof args[0] === 'object') {
18 | args = args[0]
19 | }
20 |
21 | if (!args || !args.hasOwnProperty) {
22 | args = {}
23 | }
24 |
25 | return string.replace(RE_NARGS, (match, prefix, i, index) => {
26 | let result
27 |
28 | if (string[index - 1] === '{' &&
29 | string[index + match.length] === '}') {
30 | return i
31 | } else {
32 | result = Object.prototype.hasOwnProperty.call(args, i) ? args[i] : null
33 | if (result === null || result === undefined) {
34 | return ''
35 | }
36 |
37 | return result
38 | }
39 | })
40 | }
41 |
42 | return template
43 | }
44 |
--------------------------------------------------------------------------------
/src/locale/index.js:
--------------------------------------------------------------------------------
1 | import defaultLang from './lang/zh-CN'
2 | import Vue from 'vue'
3 | import deepmerge from 'deepmerge'
4 | import Format from './format'
5 |
6 | const format = Format(Vue)
7 | let lang = defaultLang
8 | let merged = false
9 | let i18nHandler = function () {
10 | const vuei18n = Object.getPrototypeOf(this || Vue).$t
11 | if (typeof vuei18n === 'function' && !!Vue.locale) {
12 | if (!merged) {
13 | merged = true
14 | Vue.locale(
15 | Vue.config.lang,
16 | deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true })
17 | )
18 | }
19 | return vuei18n.apply(this, arguments)
20 | }
21 | }
22 |
23 | export const t = function (path, options) {
24 | let value = i18nHandler.apply(this, arguments)
25 | if (value !== null && value !== undefined) return value
26 |
27 | const array = path.split('.')
28 | let current = lang
29 |
30 | for (let i = 0, j = array.length; i < j; i++) {
31 | const property = array[i]
32 | value = current[property]
33 | if (i === j - 1) return format(value, options)
34 | if (!value) return ''
35 | current = value
36 | }
37 | return ''
38 | }
39 |
40 | export const use = function (l) {
41 | lang = l || lang
42 | }
43 |
44 | export const i18n = function (fn) {
45 | i18nHandler = fn || i18nHandler
46 | }
47 |
48 | export default { use, t, i18n }
49 |
--------------------------------------------------------------------------------
/src/locale/lang/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | ans: {
3 | modal: {
4 | confirm: 'OK',
5 | cancel: 'Cancel'
6 | },
7 | cascader: {
8 | placeholder: 'Select',
9 | noMatch: 'No matching data',
10 | noData: 'No data'
11 | },
12 | datepicker: {
13 | placeholder: 'Select date',
14 | cancel: 'Cancel',
15 | confirm: 'OK',
16 | year: '',
17 | month1: 'January',
18 | month2: 'February',
19 | month3: 'March',
20 | month4: 'April',
21 | month5: 'May',
22 | month6: 'June',
23 | month7: 'July',
24 | month8: 'August',
25 | month9: 'September',
26 | month10: 'October',
27 | month11: 'November',
28 | month12: 'December',
29 | weeks: {
30 | sun: 'Sun',
31 | mon: 'Mon',
32 | tue: 'Tue',
33 | wed: 'Wed',
34 | thu: 'Thu',
35 | fri: 'Fri',
36 | sat: 'Sat'
37 | },
38 | selectTime: 'Select time',
39 | startTime: 'Start time',
40 | endTime: 'End time'
41 | },
42 | input: {
43 | placeholder: 'Please enter...'
44 | },
45 | page: {
46 | goto: 'Go to',
47 | pagesize: '/page',
48 | total: 'Total {total}',
49 | pageClassifier: ''
50 | },
51 | poptip: {
52 | confirm: 'OK',
53 | cancel: 'Cancel'
54 | },
55 | select: {
56 | placeholder: 'Select',
57 | noMatch: 'No matching data',
58 | noData: 'No data',
59 | search: 'Keyword'
60 | },
61 | table: {
62 | emptyText: 'No data'
63 | },
64 | timepicker: {
65 | clear: 'Clear',
66 | confirm: 'OK',
67 | placeholder: 'Select'
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/locale/lang/zh-CN.js:
--------------------------------------------------------------------------------
1 | export default {
2 | ans: {
3 | modal: {
4 | confirm: '确定',
5 | cancel: '取消'
6 | },
7 | cascader: {
8 | placeholder: '请选择',
9 | noMatch: '搜索无结果',
10 | noData: '暂无数据'
11 | },
12 | datepicker: {
13 | placeholder: '请选择日期',
14 | cancel: '取消',
15 | confirm: '确定',
16 | year: '年',
17 | month1: '1 月',
18 | month2: '2 月',
19 | month3: '3 月',
20 | month4: '4 月',
21 | month5: '5 月',
22 | month6: '6 月',
23 | month7: '7 月',
24 | month8: '8 月',
25 | month9: '9 月',
26 | month10: '10 月',
27 | month11: '11 月',
28 | month12: '12 月',
29 | weeks: {
30 | sun: '日',
31 | mon: '一',
32 | tue: '二',
33 | wed: '三',
34 | thu: '四',
35 | fri: '五',
36 | sat: '六'
37 | },
38 | selectTime: '选择时间',
39 | startTime: '开始时间',
40 | endTime: '结束时间'
41 | },
42 | input: {
43 | placeholder: '请输入...'
44 | },
45 | page: {
46 | goto: '跳转至',
47 | pagesize: '条/页',
48 | total: '共 {total} 条',
49 | pageClassifier: '页'
50 | },
51 | poptip: {
52 | confirm: '确定',
53 | cancel: '取消'
54 | },
55 | select: {
56 | placeholder: '请选择',
57 | noMatch: '搜索无结果',
58 | noData: '暂无数据',
59 | search: '搜索'
60 | },
61 | table: {
62 | emptyText: '暂无数据'
63 | },
64 | timepicker: {
65 | clear: '清空',
66 | confirm: '确定',
67 | placeholder: '请选择时间'
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/style/animation/index.scss:
--------------------------------------------------------------------------------
1 | @import "./fadingEntrances.scss";
2 | @import "./fadingExits.scss";
3 |
4 | .#{$animation-prefix}fade-enter-active {
5 | animation: fadeIn $animation-time;
6 | }
7 | .#{$animation-prefix}fade-leave-active {
8 | animation: fadeOut $animation-time;
9 | }
10 |
11 | // 弹出下拉框过渡,SelectDropDwon
12 | .#{$animation-prefix}drop-enter-active,
13 | .#{$animation-prefix}drop-leave-active {
14 | opacity: 1;
15 | transform: scaleY(1);
16 | transition: transform $animation-time cubic-bezier(0.23, 1, 0.32, 1),
17 | opacity $animation-time cubic-bezier(0.23, 1, 0.32, 1);
18 | }
19 | [x-placement^="top"] {
20 | &.#{$animation-prefix}drop-enter-active,
21 | &.#{$animation-prefix}drop-leave-active {
22 | transform-origin: center bottom;
23 | }
24 | }
25 | [x-placement^="bottom"] {
26 | &.#{$animation-prefix}drop-enter-active,
27 | &.#{$animation-prefix}drop-leave-active {
28 | transform-origin: center top;
29 | }
30 | }
31 | .#{$animation-prefix}drop-enter,
32 | .#{$animation-prefix}drop-leave-active {
33 | opacity: 0;
34 | transform: scaleY(0);
35 | }
36 |
37 | .animated {
38 | -webkit-animation-duration: 1s;
39 | animation-duration: 1s;
40 | -webkit-animation-fill-mode: both;
41 | animation-fill-mode: both;
42 | }
43 | .animated.infinite {
44 | -webkit-animation-iteration-count: infinite;
45 | animation-iteration-count: infinite;
46 | }
47 | .animated.delay-1s {
48 | -webkit-animation-delay: 1s;
49 | animation-delay: 1s;
50 | }
51 | .animated.delay-2s {
52 | -webkit-animation-delay: 2s;
53 | animation-delay: 2s;
54 | }
55 | .animated.delay-3s {
56 | -webkit-animation-delay: 3s;
57 | animation-delay: 3s;
58 | }
59 | .animated.delay-4s {
60 | -webkit-animation-delay: 4s;
61 | animation-delay: 4s;
62 | }
63 | .animated.delay-5s {
64 | -webkit-animation-delay: 5s;
65 | animation-delay: 5s;
66 | }
67 | .animated.fast {
68 | -webkit-animation-duration: 800ms;
69 | animation-duration: 800ms;
70 | }
71 | .animated.faster {
72 | -webkit-animation-duration: 500ms;
73 | animation-duration: 500ms;
74 | }
75 | .animated.slow {
76 | -webkit-animation-duration: 2s;
77 | animation-duration: 2s;
78 | }
79 | .animated.slower {
80 | -webkit-animation-duration: 3s;
81 | animation-duration: 3s;
82 | }
83 | @media (prefers-reduced-motion) {
84 | .animated {
85 | -webkit-animation: unset !important;
86 | animation: unset !important;
87 | -webkit-transition: none !important;
88 | transition: none !important;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/style/animation/lightspeed.scss:
--------------------------------------------------------------------------------
1 | @-webkit-keyframes lightSpeedIn {
2 | from {
3 | -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
4 | transform: translate3d(100%, 0, 0) skewX(-30deg);
5 | opacity: 0;
6 | }
7 | 60% {
8 | -webkit-transform: skewX(20deg);
9 | transform: skewX(20deg);
10 | opacity: 1;
11 | }
12 | 80% {
13 | -webkit-transform: skewX(-5deg);
14 | transform: skewX(-5deg);
15 | }
16 | to {
17 | -webkit-transform: translate3d(0, 0, 0);
18 | transform: translate3d(0, 0, 0);
19 | }
20 | }
21 | @keyframes lightSpeedIn {
22 | from {
23 | -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
24 | transform: translate3d(100%, 0, 0) skewX(-30deg);
25 | opacity: 0;
26 | }
27 | 60% {
28 | -webkit-transform: skewX(20deg);
29 | transform: skewX(20deg);
30 | opacity: 1;
31 | }
32 | 80% {
33 | -webkit-transform: skewX(-5deg);
34 | transform: skewX(-5deg);
35 | }
36 | to {
37 | -webkit-transform: translate3d(0, 0, 0);
38 | transform: translate3d(0, 0, 0);
39 | }
40 | }
41 | .lightSpeedIn {
42 | -webkit-animation-name: lightSpeedIn;
43 | animation-name: lightSpeedIn;
44 | -webkit-animation-timing-function: ease-out;
45 | animation-timing-function: ease-out;
46 | }
47 | @-webkit-keyframes lightSpeedOut {
48 | from {
49 | opacity: 1;
50 | }
51 | to {
52 | -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
53 | transform: translate3d(100%, 0, 0) skewX(30deg);
54 | opacity: 0;
55 | }
56 | }
57 | @keyframes lightSpeedOut {
58 | from {
59 | opacity: 1;
60 | }
61 | to {
62 | -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
63 | transform: translate3d(100%, 0, 0) skewX(30deg);
64 | opacity: 0;
65 | }
66 | }
67 | .lightSpeedOut {
68 | -webkit-animation-name: lightSpeedOut;
69 | animation-name: lightSpeedOut;
70 | -webkit-animation-timing-function: ease-in;
71 | animation-timing-function: ease-in;
72 | }
--------------------------------------------------------------------------------
/src/style/animation/slidingExits.scss:
--------------------------------------------------------------------------------
1 | @keyframes slideOutDown {
2 | from {
3 | -webkit-transform: translate3d(0, 0, 0);
4 | transform: translate3d(0, 0, 0);
5 | }
6 | to {
7 | visibility: hidden;
8 | -webkit-transform: translate3d(0, 100%, 0);
9 | transform: translate3d(0, 100%, 0);
10 | }
11 | }
12 | .slideOutDown {
13 | -webkit-animation-name: slideOutDown;
14 | animation-name: slideOutDown;
15 | }
16 | @-webkit-keyframes slideOutLeft {
17 | from {
18 | -webkit-transform: translate3d(0, 0, 0);
19 | transform: translate3d(0, 0, 0);
20 | }
21 | to {
22 | visibility: hidden;
23 | -webkit-transform: translate3d(-100%, 0, 0);
24 | transform: translate3d(-100%, 0, 0);
25 | }
26 | }
27 | @keyframes slideOutLeft {
28 | from {
29 | -webkit-transform: translate3d(0, 0, 0);
30 | transform: translate3d(0, 0, 0);
31 | }
32 | to {
33 | visibility: hidden;
34 | -webkit-transform: translate3d(-100%, 0, 0);
35 | transform: translate3d(-100%, 0, 0);
36 | }
37 | }
38 | .slideOutLeft {
39 | -webkit-animation-name: slideOutLeft;
40 | animation-name: slideOutLeft;
41 | }
42 | @-webkit-keyframes slideOutRight {
43 | from {
44 | -webkit-transform: translate3d(0, 0, 0);
45 | transform: translate3d(0, 0, 0);
46 | }
47 | to {
48 | visibility: hidden;
49 | -webkit-transform: translate3d(100%, 0, 0);
50 | transform: translate3d(100%, 0, 0);
51 | }
52 | }
53 | @keyframes slideOutRight {
54 | from {
55 | -webkit-transform: translate3d(0, 0, 0);
56 | transform: translate3d(0, 0, 0);
57 | }
58 | to {
59 | visibility: hidden;
60 | -webkit-transform: translate3d(100%, 0, 0);
61 | transform: translate3d(100%, 0, 0);
62 | }
63 | }
64 | .slideOutRight {
65 | -webkit-animation-name: slideOutRight;
66 | animation-name: slideOutRight;
67 | }
68 | @-webkit-keyframes slideOutUp {
69 | from {
70 | -webkit-transform: translate3d(0, 0, 0);
71 | transform: translate3d(0, 0, 0);
72 | }
73 | to {
74 | visibility: hidden;
75 | -webkit-transform: translate3d(0, -100%, 0);
76 | transform: translate3d(0, -100%, 0);
77 | }
78 | }
79 | @keyframes slideOutUp {
80 | from {
81 | -webkit-transform: translate3d(0, 0, 0);
82 | transform: translate3d(0, 0, 0);
83 | }
84 | to {
85 | visibility: hidden;
86 | -webkit-transform: translate3d(0, -100%, 0);
87 | transform: translate3d(0, -100%, 0);
88 | }
89 | }
90 | .slideOutUp {
91 | -webkit-animation-name: slideOutUp;
92 | animation-name: slideOutUp;
93 | }
--------------------------------------------------------------------------------
/src/style/components/box/box.scss:
--------------------------------------------------------------------------------
1 | @import "./message.scss";
2 | @import "./modal.scss";
3 | @import "./notice.scss";
--------------------------------------------------------------------------------
/src/style/components/box/message.scss:
--------------------------------------------------------------------------------
1 | $prefixCls: $lib-name + "-message";
2 | @keyframes #{$animation-prefix}move-in {
3 | 0% {
4 | transform: translateY(-100%);
5 | opacity: 0;
6 | }
7 | 100% {
8 | transform: translateY(0%);
9 | opacity: 1;
10 | }
11 | }
12 |
13 | .#{$animation-prefix}move-in-enter-active {
14 | animation: #{$animation-prefix}move-in $animation-time;
15 | }
16 | .#{$animation-prefix}move-in-leave-active {
17 | animation: #{$animation-prefix}move-in $animation-time reverse;
18 | }
19 |
20 | .#{$prefixCls}-wrapper {
21 | position: fixed;
22 | z-index: 120;
23 | .#{$prefixCls}-box {
24 | margin-bottom: 10px;
25 | .#{$prefixCls}-box-content {
26 | display: inline-block;
27 | transform: translateX(-50%);
28 | padding: 10px 16px;
29 | font-size: 14px;
30 | color: $title-color-light;
31 | background-color: $background-color-base;
32 | border-radius: 4px;
33 | border: 1px solid $border-color-base;
34 | box-sizing: border-box;
35 | box-shadow: $box-shadow-base;
36 | .#{$prefixCls}-box-content-text {
37 | display: inline-block;
38 | i {
39 | display: inline-block;
40 | line-height: 1;
41 | margin-right: 8px;
42 | font-size: 14px;
43 | &.info {
44 | color: $info-color;
45 | }
46 | &.success {
47 | color: $success-color;
48 | }
49 | &.warning {
50 | color: $warning-color;
51 | }
52 | &.error {
53 | color: $error-color;
54 | }
55 | &.loading {
56 | color: $sub-text-color-light;
57 | }
58 | }
59 | }
60 | .#{$prefixCls}-box-close {
61 | display: inline-block;
62 | margin-left: 20px;
63 | color: $sub-text-color-light;
64 | cursor: pointer;
65 | i {
66 | font-size: 12px;
67 | &:hover {
68 | color: $primary-color;
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
75 | &.#{$prefixCls}-fixed {
76 | .#{$prefixCls}-box {
77 | position: absolute;
78 | top: 0;
79 | white-space: nowrap;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/style/components/box/modal.scss:
--------------------------------------------------------------------------------
1 | $prefixCls: $lib-name + "-modal";
2 |
3 | @keyframes modal-down {
4 | 0% {
5 | opacity: 0;
6 | }
7 | 100% {
8 | opacity: 1;
9 | }
10 | }
11 | @keyframes modal-scale {
12 | 0% {
13 | transform: translate(-50%, -50%) scale(0.8);
14 | }
15 | 100% {
16 | transform: translate(-50%, -50%) scale(1);
17 | }
18 | }
19 |
20 | .#{$animation-prefix}modal-down-enter-active {
21 | animation: modal-down $animation-time;
22 | .#{$prefixCls}-box-content-wrapper {
23 | animation: modal-scale $animation-time;
24 | }
25 | }
26 | .#{$animation-prefix}modal-down-leave-active {
27 | animation: modal-down $animation-time reverse;
28 | .#{$prefixCls}-box-content-wrapper {
29 | animation: modal-scale $animation-time reverse;
30 | }
31 | }
32 |
33 | .#{$prefixCls}-box {
34 | position: fixed;
35 | top: 0;
36 | left: 0;
37 | right: 0;
38 | bottom: 0;
39 | z-index: 120;
40 | .msk {
41 | background-color: $background-color-dark;
42 | position: absolute;
43 | top: 0;
44 | bottom: 0;
45 | left: 0;
46 | right: 0;
47 | }
48 | .#{$prefixCls}-box-content-wrapper {
49 | position: absolute;
50 | left: 50%;
51 | top: 50%;
52 | transform: translate(-50%, -50%);
53 | box-shadow: $box-shadow-base;
54 | .#{$prefixCls}-box-close {
55 | position: absolute;
56 | right: 16px;
57 | top: 10px;
58 | color: $sub-text-color-light;
59 | cursor: pointer;
60 | &:hover {
61 | color: $primary-color;
62 | }
63 | .ans-icon-close {
64 | font-size: 12px;
65 | }
66 | }
67 | .#{$prefixCls}-box-content {
68 | background-color: $background-color-base;
69 | border: 0;
70 | border-radius: 4px;
71 | .#{$prefixCls}-content-header {
72 | .#{$prefixCls}-header-inner {
73 | height: 55px;
74 | padding: 0 25px;
75 | font-size: 16px;
76 | line-height: 55px;
77 | color: $title-color-light;
78 | font-weight: 500;
79 | overflow: hidden;
80 | text-overflow: ellipsis;
81 | white-space: nowrap;
82 | box-sizing: border-box;
83 | border-bottom: 1px solid $border-color-base;
84 | }
85 | }
86 | .#{$prefixCls}-content-body {
87 | padding: 25px;
88 | font-size: 14px;
89 | line-height: 1.5;
90 | color: $content-color-light;
91 | box-sizing: border-box;
92 | }
93 | .#{$prefixCls}-content-footer {
94 | border-top: 1px solid $border-color-base;
95 | padding: 10px 25px;
96 | text-align: right;
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/style/components/button/button.scss:
--------------------------------------------------------------------------------
1 | @import "./mixin.scss";
2 |
3 | $btn-prefix-cls: #{$lib-name}-btn;
4 | $btn-padding-base: 8px 16px;
5 | $btn-padding-large: 11px 20px;
6 | $btn-padding-small: 6px 12px;
7 | $btn-padding-xsmall: 5px 10px;
8 | $btn-circle-size: 64px;
9 | $line-height-base: 1.5;
10 |
11 | .#{$btn-prefix-cls} {
12 | @include btn-common();
13 |
14 | &-long {
15 | width: 100%;
16 | }
17 |
18 | & > .#{$lib-name}-icon + span,
19 | & > span + .#{$lib-name}-icon {
20 | margin-left: 10px;
21 | display: inline-block;
22 | }
23 |
24 | // type
25 | &-primary {
26 | @include dark-bg-btn();
27 | }
28 |
29 | &-ghost {
30 | @include white-bg-btn($title-color-light);
31 | }
32 |
33 | &-dashed {
34 | @include white-bg-btn($title-color-light);
35 | border-style: dashed;
36 | }
37 |
38 | &-text {
39 | @include white-bg-btn($title-color-light);
40 | border: transparent;
41 |
42 | &:active,
43 | &.active {
44 | border: transparent;
45 | }
46 | }
47 |
48 | &-success {
49 | @include dark-bg-btn($success-color);
50 | }
51 |
52 | &-warning {
53 | @include dark-bg-btn($warning-color);
54 | }
55 |
56 | &-error {
57 | @include dark-bg-btn($error-color);
58 | }
59 |
60 | &-info {
61 | @include dark-bg-btn($info-color);
62 | }
63 |
64 | // shape
65 | &-circle {
66 | border-radius: $btn-circle-size;
67 | &.#{$btn-prefix-cls}-icon-only {
68 | @include square(32px);
69 | @include button-size(0, 14px);
70 | border-radius: 50%;
71 |
72 | &.#{$btn-prefix-cls}-large {
73 | @include square(40px);
74 | @include button-size(0, 16px);
75 | }
76 |
77 | &.#{$btn-prefix-cls}-small {
78 | @include square(28px);
79 | @include button-size(0, 12px);
80 | }
81 |
82 | &.#{$btn-prefix-cls}-xsmall {
83 | @include square(26px);
84 | @include button-size(0, 12px);
85 | }
86 | }
87 | }
88 |
89 | // loading mask
90 | &:before {
91 | position: absolute;
92 | top: -1px;
93 | left: -1px;
94 | bottom: -1px;
95 | right: -1px;
96 | background: $background-color-base;
97 | opacity: 0.35;
98 | content: "";
99 | border-radius: inherit;
100 | z-index: 1;
101 | transition: opacity $transition-time;
102 | pointer-events: none;
103 | display: none;
104 | }
105 |
106 | &-loading {
107 | position: relative;
108 | pointer-events: none;
109 | &:before {
110 | display: block;
111 | }
112 | }
113 |
114 | // group
115 | &-group {
116 | @include btn-group($btn-prefix-cls);
117 | }
118 |
119 | &-group-vertical {
120 | @include btn-group-vertical($btn-prefix-cls);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/style/components/form/form.scss:
--------------------------------------------------------------------------------
1 | $form-name: $lib-name + "-form";
2 | $form-item-name: $lib-name + "-form-item";
3 |
4 | .#{$form-name} {
5 | .#{$form-item-name} {
6 | display: flex;
7 | align-items: flex-start;
8 | margin-bottom: 10px;
9 | &::after {
10 | display: block;
11 | clear: both;
12 | content: "";
13 | }
14 | .#{$form-item-name}-label {
15 | text-align: right;
16 | vertical-align: middle;
17 | box-sizing: border-box;
18 | font-size: 14px;
19 | color: $sub-text-color-light;
20 | height: 32px;
21 | line-height: 32px;
22 | padding-right: 16px;
23 | }
24 | .#{$form-item-name}-content {
25 | .#{$lib-name}-radio-group,
26 | .#{$lib-name}-checkbox-group {
27 | line-height: 32px;
28 | }
29 | .#{$form-item-name}-error-tip {
30 | margin: 6px 0 0;
31 | font-size: 12px;
32 | color: $error-color;
33 | }
34 | &.form-item-error {
35 | .input-element.no-border {
36 | border-bottom-color: $error-color;
37 | }
38 | .input-element:not(.no-border) {
39 | border-color: $error-color;
40 | }
41 | }
42 | }
43 | }
44 | &.vertical-form-item {
45 | .#{$form-item-name} {
46 | flex-direction: column;
47 | .#{$form-item-name}-label {
48 | text-align: left;
49 | font-size: 12px;
50 | height: 20px;
51 | line-height: 20px;
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/style/components/index.scss:
--------------------------------------------------------------------------------
1 | @import "./switch/switch.scss";
2 | @import "./pagination/pagination.scss";
3 | @import "./tooltip/tooltip.scss";
4 | @import "./spin/spin.scss";
5 | @import "./radio/radio.scss";
6 | @import "./checkbox/checkbox.scss";
7 | @import "./button/button.scss";
8 | @import "./poptip/poptip.scss";
9 | @import "./progress/progress.scss";
10 | @import "./select/select.scss";
11 | @import "./box/box.scss";
12 | @import "./datepicker/datepicker.scss";
13 | @import "./input/input.scss";
14 | @import "./cascader/cascader.scss";
15 | @import "./drawer/drawer.scss";
16 | @import "./table/table.scss";
17 | @import "./scroller/scroller.scss";
18 | @import "./form/form.scss";
--------------------------------------------------------------------------------
/src/style/components/poptip/poptip.scss:
--------------------------------------------------------------------------------
1 | .#{$lib-name}-poptip {
2 | position: absolute;
3 | background: $background-color-base;
4 | min-width: 150px;
5 | border-radius: $border-radius-base;
6 | border: 1px solid $border-color-base;
7 | padding: 12px;
8 | z-index: 500;
9 | color: $content-color-light;
10 | line-height: 1.5;
11 | text-align: justify;
12 | box-shadow: $box-shadow-base;
13 |
14 | &:focus:active,
15 | &:focus {
16 | outline-width: 0;
17 | }
18 |
19 | &--plain {
20 | padding: 12px 16px;
21 | }
22 |
23 | &__title {
24 | color: $title-color-light;
25 | font-size: 14px;
26 | line-height: 1;
27 | margin-bottom: 12px;
28 | }
29 |
30 | &__reference {
31 | &:focus:not(.focusing),
32 | &:focus:hover {
33 | outline-width: 0;
34 | }
35 | }
36 |
37 | &__content {
38 | font-size: 14px;
39 | color: $content-color-light;
40 | text-align: justify;
41 | }
42 |
43 | &__footer {
44 | text-align: right;
45 | margin-top: 10px;
46 | button {
47 | &:first-child {
48 | margin-right: 15px;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/style/components/progress/progress.scss:
--------------------------------------------------------------------------------
1 | .#{$lib-name}-progress {
2 | display: flex;
3 | align-items: center;
4 | .progress-bar {
5 | flex: 1;
6 | background: $background-color-disabled;
7 | .progress-percentage {
8 | position: relative;
9 | height: 100%;
10 | background: $primary-color;
11 | transition: width $transition-time, background $transition-time;
12 | &.success {
13 | background: $success-color;
14 | }
15 | &.exception {
16 | background: $error-color;
17 | }
18 | .progress-inner {
19 | position: absolute;
20 | z-index: 1;
21 | right: 10px;
22 | height: 100%;
23 | display: flex;
24 | align-items: center;
25 | .inner-text {
26 | font-size: 14px;
27 | color: $title-color-dark;
28 | }
29 | }
30 | }
31 | }
32 | .progress-right {
33 | padding-left: 8px;
34 | width: 50px;
35 | .right-text {
36 | font-size: 14px;
37 | color: $sub-text-color-light;
38 | }
39 | .success {
40 | font-size: 14px;
41 | color: $success-color;
42 | }
43 | .exception {
44 | font-size: 14px;
45 | color: $error-color;
46 | }
47 | }
48 | .progress-ring {
49 | position: relative;
50 | .progress-background {
51 | stroke: $background-color-disabled;
52 | fill: transparent;
53 | }
54 | .progress-percentage {
55 | stroke: $primary-color;
56 | fill: transparent;
57 | transition: stroke $transition-time, stroke-dashoffset $transition-time;
58 | &.success {
59 | stroke: $success-color;
60 | }
61 | &.exception {
62 | stroke: $error-color;
63 | }
64 | }
65 | .progress-center {
66 | position: absolute;
67 | z-index: 1;
68 | top: 0;
69 | left: 0;
70 | display: flex;
71 | justify-content: center;
72 | align-items: center;
73 | width: 100%;
74 | height: 100%;
75 | .progress-inner {
76 | font-size: 16px;
77 | color: $content-color-light;
78 | .success {
79 | font-size: 16px;
80 | color: $success-color;
81 | }
82 | .exception {
83 | font-size: 16px;
84 | color: $error-color;
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/style/components/scroller/scroller.scss:
--------------------------------------------------------------------------------
1 | $scrollbar-width: 4px;
2 | $scrollbar-margin: 2px;
3 |
4 | .#{$lib-name}-scroller {
5 | position: relative;
6 | overflow: hidden;
7 | // fix inline-block gap
8 | line-height: 1px;
9 | .scroll-area-wrapper {
10 | position: relative;
11 | top: 0;
12 | left: 0;
13 | display: inline-block;
14 | &.scroll-transition {
15 | transition: transform $transition-time;
16 | }
17 | }
18 | .#{$lib-name}-v-scrollbar,
19 | .#{$lib-name}-h-scrollbar {
20 | position: absolute;
21 | z-index: 1;
22 | box-sizing: content-box;
23 | .scrollbar-thumb {
24 | position: relative;
25 | border-radius: $scrollbar-width;
26 | background: $border-color-base;
27 | transition: background-color $transition-time;
28 | &.scroll-transition {
29 | transition: transform $transition-time;
30 | }
31 | cursor: pointer;
32 | &:hover {
33 | background: darken($border-color-base, 10);
34 | }
35 | }
36 | }
37 | .#{$lib-name}-v-scrollbar {
38 | top: 0;
39 | right: 0;
40 | width: $scrollbar-width;
41 | height: 100%;
42 | padding: 0 $scrollbar-margin;
43 | .scrollbar-thumb {
44 | top: 0;
45 | width: 100%;
46 | }
47 | }
48 | .#{$lib-name}-h-scrollbar {
49 | left: 0;
50 | bottom: 0;
51 | width: 100%;
52 | height: $scrollbar-width;
53 | padding: $scrollbar-margin 0;
54 | .scrollbar-thumb {
55 | left: 0;
56 | height: 100%;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/style/components/spin/spin.scss:
--------------------------------------------------------------------------------
1 | .#{$lib-name}-spin {
2 | position: absolute;
3 | z-index: 999;
4 | margin: 0;
5 | top: 0;
6 | right: 0;
7 | bottom: 0;
8 | left: 0;
9 | display: flex;
10 | justify-content: center;
11 | align-items: center;
12 | background: rgba($background-color-base, 0.85);
13 | .spin-center-container {
14 | text-align: center;
15 | color: $primary-color;
16 | .loading-text {
17 | font-size: 16px;
18 | line-height: 30px;
19 | }
20 | }
21 | &.is-fullscreen {
22 | position: fixed;
23 | }
24 | }
25 |
26 | .spin-relative-parent {
27 | position: relative !important;
28 | }
29 |
30 | .spin-lock-overflow {
31 | overflow: hidden !important;
32 | }
33 |
34 | @keyframes rotating {
35 | 0% {
36 | transform: rotate(0deg);
37 | }
38 | 100% {
39 | transform: rotate(1turn);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/style/components/tooltip/tooltip.scss:
--------------------------------------------------------------------------------
1 | $tooltip-wrapper-name: $lib-name + "-tooltip";
2 |
3 | $tooltip-dark-bg-color: rgba($title-color-light, 0.95);
4 | $tooltip-dark-text-color: $background-color-disabled;
5 |
6 | $tooltip-light-bg-color: $background-color-base;
7 | $tooltip-light-border-color: $border-color-base;
8 | $tooltip-light-text-color: $title-color-light;
9 |
10 | .#{$tooltip-wrapper-name} {
11 | padding: 8px;
12 | border-radius: 4px;
13 | &.dark {
14 | background: $tooltip-dark-bg-color;
15 | box-shadow: $box-shadow-base;
16 | .tooltip-content {
17 | color: $tooltip-dark-text-color;
18 | }
19 | }
20 | &.light {
21 | background: $tooltip-light-bg-color;
22 | border: 1px solid $tooltip-light-border-color;
23 | box-shadow: $box-shadow-base;
24 | .tooltip-content {
25 | color: $tooltip-light-text-color;
26 | }
27 | }
28 | .tooltip-content {
29 | font-size: 12px;
30 | line-height: 1;
31 | text-align: justify;
32 | }
33 | &.large {
34 | padding: 12px 16px;
35 | border-radius: 6px;
36 | .tooltip-content {
37 | font-size: 13px;
38 | line-height: 21px;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/style/font/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/src/style/font/iconfont.eot
--------------------------------------------------------------------------------
/src/style/font/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/src/style/font/iconfont.ttf
--------------------------------------------------------------------------------
/src/style/font/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/analysys/ans-ui/a3845f638bd5497b06c9456cfee36ee2c5bea863/src/style/font/iconfont.woff
--------------------------------------------------------------------------------
/src/style/index.scss:
--------------------------------------------------------------------------------
1 | @import "./vars.scss";
2 | @import "./animation/index.scss";
3 | @import "./font.scss";
4 | @import "./common.scss";
5 | @import "./components/index.scss";
--------------------------------------------------------------------------------
/src/style/vars.scss:
--------------------------------------------------------------------------------
1 | // 库名
2 | $lib-name: "ans";
3 |
4 | // 字体路径
5 | $icon-path: "./font";
6 |
7 | // 主要颜色
8 | $primary-color: #1489e2 !default;
9 | $primary-color-hover: #1799fc !default;
10 | $primary-color-active: #127ac9 !default;
11 | $sub-color: #ff8c00 !default;
12 | $sub-color-hover: #ff981a !default;
13 | $sub-color-active: #ef6c00 !default;
14 | $info-color: #1489e2 !default;
15 | $success-color: #4caf50 !default;
16 | $warning-color: #ffc107 !default;
17 | $error-color: #f14343 !default;
18 |
19 | // 浅色背景文本颜色
20 | $title-color-light: #252d39 !default;
21 | $content-color-light: #4c6072 !default;
22 | $sub-text-color-light: #6d859e !default;
23 | $disabled-text-color-light: #c5ced8 !default;
24 |
25 | // 深色背景文本颜色
26 | $title-color-dark: #fff !default;
27 | $content-color-dark: #eee !default;
28 | $sub-text-color-dark: #c5ced8 !default;
29 | $disabled-text-color-dark: #888 !default;
30 | $bg-color-in-dark: #4c6072;
31 |
32 | // radius
33 | $border-radius-base: 4px;
34 |
35 | // 边框颜色
36 | $border-color-base: #e4eaf1 !default;
37 | $box-shadow-base: 0 2px 8px 0 rgba(0,0,0,0.14) !default;
38 |
39 | // 背景色
40 | $background-color-base: #fff;
41 | $background-color-disabled: #ecf3f8;
42 | $background-color-dark: rgba(0, 0, 0, 0.6);
43 |
44 | // 动画
45 | $animation-prefix: "x-ani-" !default;
46 | $animation-time: .3s;
47 | $transition-time: .2s;
48 | $ease-in-out: ease-in-out;
--------------------------------------------------------------------------------
/src/util/assist.js:
--------------------------------------------------------------------------------
1 | // base on iview assist.js
2 |
3 | // Find components upward
4 | export function findComponentUpward (context, componentName, componentNames) {
5 | if (typeof componentName === 'string') {
6 | componentNames = [componentName]
7 | } else {
8 | componentNames = componentName
9 | }
10 |
11 | let parent = context.$parent
12 | let name = parent.$options.name
13 | while (parent && (!name || componentNames.indexOf(name) < 0)) {
14 | parent = parent.$parent
15 | if (parent) name = parent.$options.name
16 | }
17 | return parent
18 | }
19 |
20 | // Find component downward
21 | export function findComponentDownward (context, componentName) {
22 | const childrens = context.$children
23 | let children = null
24 |
25 | if (childrens.length) {
26 | for (const child of childrens) {
27 | const name = child.$options.name
28 | if (name === componentName) {
29 | children = child
30 | break
31 | } else {
32 | children = findComponentDownward(child, componentName)
33 | if (children) break
34 | }
35 | }
36 | }
37 | return children
38 | }
39 |
40 | // Find components downward
41 | export function findComponentsDownward (context, componentName) {
42 | return context.$children.reduce((components, child) => {
43 | if (child.$options.name === componentName) components.push(child)
44 | const foundChilds = findComponentsDownward(child, componentName)
45 | return components.concat(foundChilds)
46 | }, [])
47 | }
48 |
49 | // Find components upward
50 | export function findComponentsUpward (context, componentName) {
51 | const parents = []
52 | const parent = context.$parent
53 | if (parent) {
54 | if (parent.$options.name === componentName) parents.push(parent)
55 | return parents.concat(findComponentsUpward(parent, componentName))
56 | } else {
57 | return []
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/util/constants.js:
--------------------------------------------------------------------------------
1 | export const LIB_NAME = 'ans'
2 | export const ANIMATION_PREFIX = 'x-ani-'
3 |
--------------------------------------------------------------------------------
/src/util/customRenderer.js:
--------------------------------------------------------------------------------
1 | export default {
2 | name: 'CustomRenderer',
3 | functional: true,
4 | props: {
5 | render: Function,
6 | params: {
7 | default () {
8 | return {}
9 | }
10 | }
11 | },
12 | render: (h, ctx) => {
13 | return ctx.props.render(h, ctx.params)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/util/directives/clickOutside.js:
--------------------------------------------------------------------------------
1 | import { on } from '../event'
2 |
3 | const nodeList = []
4 | const ctx = '@@clickoutsideContext'
5 |
6 | let startClick
7 | let seed = 0
8 |
9 | on(document, 'mousedown', e => (startClick = e))
10 |
11 | on(document, 'mouseup', e => {
12 | nodeList.forEach(node => node[ctx].documentHandler(e, startClick))
13 | })
14 |
15 | function createDocumentHandler (el, binding, vnode) {
16 | return function (mouseup = {}, mousedown = {}) {
17 | if (!vnode ||
18 | !vnode.context ||
19 | !mouseup.target ||
20 | !mousedown.target ||
21 | el.contains(mouseup.target) ||
22 | el.contains(mousedown.target) ||
23 | el === mouseup.target) return
24 |
25 | if (binding.expression &&
26 | el[ctx].methodName &&
27 | vnode.context[el[ctx].methodName]) {
28 | vnode.context[el[ctx].methodName]()
29 | } else {
30 | el[ctx].bindingFn && el[ctx].bindingFn()
31 | }
32 | }
33 | }
34 |
35 | export default {
36 | bind (el, binding, vnode) {
37 | nodeList.push(el)
38 | const id = seed++
39 | el[ctx] = {
40 | id,
41 | documentHandler: createDocumentHandler(el, binding, vnode),
42 | methodName: binding.expression,
43 | bindingFn: binding.value
44 | }
45 | },
46 |
47 | update (el, binding, vnode) {
48 | el[ctx].documentHandler = createDocumentHandler(el, binding, vnode)
49 | el[ctx].methodName = binding.expression
50 | el[ctx].bindingFn = binding.value
51 | },
52 |
53 | unbind (el) {
54 | const len = nodeList.length
55 | for (let i = 0; i < len; i++) {
56 | if (nodeList[i][ctx].id === el[ctx].id) {
57 | nodeList.splice(i, 1)
58 | break
59 | }
60 | }
61 | delete el[ctx]
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/util/directives/index.js:
--------------------------------------------------------------------------------
1 | import clickOutside from './clickOutside'
2 | import mousewheel from './mousewheel'
3 |
4 | export {
5 | clickOutside,
6 | mousewheel
7 | }
8 |
--------------------------------------------------------------------------------
/src/util/directives/mousewheel.js:
--------------------------------------------------------------------------------
1 | import normalizeWheel from 'normalize-wheel'
2 | import { hasClass } from '../../util'
3 |
4 | const handler = function (event) {
5 | let scrollDom = null
6 | let parent = event.target.parentNode
7 | while (parent) {
8 | if (hasClass(parent, 'ans-scroller')) {
9 | scrollDom = parent
10 | break
11 | } else {
12 | parent = parent.parentNode
13 | }
14 | }
15 | if (scrollDom) {
16 | const callback = scrollDom.__wheel_callback
17 | const normalized = normalizeWheel(event)
18 | callback && callback.apply(this, [event, normalized])
19 | }
20 | }
21 |
22 | const eventType = normalizeWheel.getEventType()
23 |
24 | const mousewheel = function (element, callback) {
25 | if (element && element.addEventListener) {
26 | element.__wheel_callback = callback
27 | element.addEventListener(eventType, handler)
28 | }
29 | }
30 |
31 | export default {
32 | bind (el, binding) {
33 | mousewheel(el, binding.value)
34 | },
35 | unbind (el) {
36 | el.removeEventListener(eventType, el.__wheel_callback)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/util/dom/animatedScroll.js:
--------------------------------------------------------------------------------
1 | const requestAnimFrame = (function () {
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | function (callback) {
6 | window.setTimeout(callback, 1000 / 60)
7 | }
8 | })()
9 |
10 | const linear = function (t, b, c, d) {
11 | return t / d * c + b
12 | }
13 |
14 | const scrollBy = function (element, change, vertical, duration, callback) {
15 | const start = vertical ? element.scrollTop : element.scrollLeft
16 | let to = start + change
17 | if (element.__scroll__controller && element.__scroll__controller.isAnimating()) {
18 | to = element.__scroll__controller.to + change
19 | element.__scroll__controller.stop()
20 | }
21 |
22 | const controller = _scrollTo(element, start, to, vertical, duration, callback)
23 | element.__scroll__controller = controller
24 | return controller
25 | }
26 |
27 | const scrollTo = function (element, to, vertical, duration, callback) {
28 | const start = vertical ? element.scrollTop : element.scrollLeft
29 | if (element.__scroll__controller && element.__scroll__controller.isAnimating()) {
30 | element.__scroll__controller.stop()
31 | }
32 |
33 | const controller = _scrollTo(element, start, to, vertical, duration, callback)
34 | element.__scroll__controller = controller
35 | return controller
36 | }
37 |
38 | function _scrollTo (element, start, to, vertical, duration = 200, callback) {
39 | const change = to - start
40 | const animationStart = +new Date()
41 | let animating = true
42 | let lastValue = null
43 |
44 | const animateScroll = function () {
45 | if (!animating) {
46 | return
47 | }
48 | requestAnimFrame(animateScroll)
49 | const now = +new Date()
50 | const val = Math.floor(linear(now - animationStart, start, change, duration))
51 | if (lastValue) {
52 | const targetValue = vertical ? element.scrollTop : element.scrollLeft
53 | if (lastValue === targetValue) {
54 | lastValue = val
55 | vertical ? (element.scrollTop = val) : (element.scrollLeft = val)
56 | } else {
57 | animating = false
58 | }
59 | } else {
60 | lastValue = val
61 | vertical ? (element.scrollTop = val) : (element.scrollLeft = val)
62 | }
63 | if (now > animationStart + duration) {
64 | vertical ? (element.scrollTop = to) : (element.scrollLeft = to)
65 | animating = false
66 | if (callback) { callback() }
67 | }
68 | }
69 | requestAnimFrame(animateScroll)
70 |
71 | const maxScroll = vertical
72 | ? element.scrollHeight - element.offsetHeight
73 | : element.scrollWidth - element.offsetWidth
74 | const validTo = Math.min(Math.max(to, 0), maxScroll)
75 |
76 | return {
77 | to: validTo,
78 | isAnimating () {
79 | return animating
80 | },
81 | stop () {
82 | animating = false
83 | }
84 | }
85 | }
86 |
87 | export default {
88 | scrollTo,
89 | scrollBy
90 | }
91 |
--------------------------------------------------------------------------------
/src/util/dom/class.js:
--------------------------------------------------------------------------------
1 | /* istanbul ignore next */
2 | export function hasClass (el, cls) {
3 | if (!el || !cls) return false
4 | if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.')
5 | if (el.classList) {
6 | return el.classList.contains(cls)
7 | } else {
8 | return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
9 | }
10 | }
11 |
12 | /* istanbul ignore next */
13 | export function addClass (el, cls) {
14 | if (!el) return
15 | let curClass = el.className
16 | const classes = (cls || '').split(' ')
17 |
18 | for (let i = 0, j = classes.length; i < j; i++) {
19 | const clsName = classes[i]
20 | if (!clsName) continue
21 |
22 | if (el.classList) {
23 | el.classList.add(clsName)
24 | } else {
25 | if (!hasClass(el, clsName)) {
26 | curClass += ' ' + clsName
27 | }
28 | }
29 | }
30 | if (!el.classList) {
31 | el.className = curClass
32 | }
33 | }
34 |
35 | /* istanbul ignore next */
36 | export function removeClass (el, cls) {
37 | if (!el || !cls) return
38 | const classes = cls.split(' ')
39 | let curClass = ' ' + el.className + ' '
40 |
41 | for (let i = 0, j = classes.length; i < j; i++) {
42 | const clsName = classes[i]
43 | if (!clsName) continue
44 |
45 | if (el.classList) {
46 | el.classList.remove(clsName)
47 | } else {
48 | if (hasClass(el, clsName)) {
49 | curClass = curClass.replace(' ' + clsName + ' ', ' ')
50 | }
51 | }
52 | }
53 | if (!el.classList) {
54 | el.className = curClass.trim()
55 | }
56 | }
57 |
58 | const SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g
59 | const MOZ_HACK_REGEXP = /^moz([A-Z])/
60 |
61 | const camelCase = function (name) {
62 | return name.replace(SPECIAL_CHARS_REGEXP, function (_, separator, letter, offset) {
63 | return offset ? letter.toUpperCase() : letter
64 | }).replace(MOZ_HACK_REGEXP, 'Moz$1')
65 | }
66 |
67 | export function getStyle (element, styleName) {
68 | if (!element || !styleName) return null
69 | styleName = camelCase(styleName)
70 | if (styleName === 'float') {
71 | styleName = 'cssFloat'
72 | }
73 | try {
74 | var computed = document.defaultView.getComputedStyle(element, '')
75 | return element.style[styleName] || computed ? computed[styleName] : null
76 | } catch (e) {
77 | return element.style[styleName]
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/util/dom/index.js:
--------------------------------------------------------------------------------
1 | import scrollIntoView from './scrollIntoView'
2 | import scrollbarWidth from './scrollbarWidth'
3 | import animatedScroll from './animatedScroll'
4 | import limitedLoop from './limitedLoop'
5 |
6 | export * from './class'
7 | export * from './style'
8 |
9 | export {
10 | scrollIntoView,
11 | scrollbarWidth,
12 | animatedScroll,
13 | limitedLoop
14 | }
15 |
--------------------------------------------------------------------------------
/src/util/dom/limitedLoop.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | const TIME_LIMIT = 500
4 |
5 | const _nextTick = function (func, thisArg, ...args) {
6 | if (!func || typeof func !== 'function') return
7 | if (!func.startTime) {
8 | func.startTime = new Date()
9 | }
10 | if (new Date() - func.startTime > TIME_LIMIT) {
11 | func.startTime = null
12 | } else {
13 | Vue.nextTick(() => {
14 | func.apply(thisArg, args)
15 | })
16 | }
17 | }
18 |
19 | const _setTimeout = function (func, thisArg, timeout, ...args) {
20 | if (!func || typeof func !== 'function') return
21 | if (!func.startTime) {
22 | func.startTime = new Date()
23 | }
24 | if (new Date() - func.startTime > TIME_LIMIT) {
25 | func.startTime = null
26 | } else {
27 | setTimeout(() => {
28 | func.apply(thisArg, args)
29 | }, timeout)
30 | }
31 | }
32 |
33 | export default {
34 | nextTick: _nextTick,
35 | setTimeout: _setTimeout
36 | }
37 |
--------------------------------------------------------------------------------
/src/util/dom/scrollIntoView.js:
--------------------------------------------------------------------------------
1 | export default function scrollIntoView (container, selected) {
2 | if (!selected) {
3 | container.scrollTop = 0
4 | return
5 | }
6 |
7 | const top = selected.offsetTop
8 | const bottom = selected.offsetTop + selected.offsetHeight
9 | const viewRectTop = container.scrollTop
10 | const viewRectBottom = viewRectTop + container.clientHeight
11 |
12 | if (top < viewRectTop) {
13 | container.scrollTop = top
14 | } else if (bottom > viewRectBottom) {
15 | container.scrollTop = bottom - container.clientHeight
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/util/dom/scrollbarWidth.js:
--------------------------------------------------------------------------------
1 | let scrollbarWidth
2 |
3 | export default function () {
4 | if (scrollbarWidth !== undefined) return scrollbarWidth
5 |
6 | const outer = document.createElement('div')
7 | outer.style.visibility = 'hidden'
8 | outer.style.width = '100px'
9 | outer.style.position = 'absolute'
10 | outer.style.top = '-9999px'
11 | document.body.appendChild(outer)
12 |
13 | const widthNoScroll = outer.offsetWidth
14 | outer.style.overflow = 'scroll'
15 |
16 | const inner = document.createElement('div')
17 | inner.style.width = '100%'
18 | outer.appendChild(inner)
19 |
20 | const widthWithScroll = inner.offsetWidth
21 | outer.parentNode.removeChild(outer)
22 | scrollbarWidth = widthNoScroll - widthWithScroll
23 |
24 | return scrollbarWidth
25 | }
26 |
--------------------------------------------------------------------------------
/src/util/dom/style.js:
--------------------------------------------------------------------------------
1 | const formatSize = (prop) => {
2 | const propType = typeof prop
3 | if (propType === 'number') {
4 | return prop + 'px'
5 | }
6 | if (propType === 'string') {
7 | if (/^\d+$/.test(prop)) return parseInt(prop, 10) + 'px'
8 | return prop
9 | }
10 | return null
11 | }
12 |
13 | export {
14 | formatSize
15 | }
16 |
--------------------------------------------------------------------------------
/src/util/event.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const on = (el, event, handler) => {
4 | if (el && event && handler) {
5 | el.addEventListener(event, handler, false)
6 | }
7 | }
8 |
9 | const off = (el, event, handler) => {
10 | if (el && event && handler) {
11 | el.removeEventListener(event, handler, false)
12 | }
13 | }
14 |
15 | export {
16 | on,
17 | off
18 | }
19 |
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | import xCuctomRender from './customRenderer.js'
2 |
3 | export {
4 | xCuctomRender
5 | }
6 |
7 | export * from './directives'
8 | export * from './dom'
9 | export * from './mixins'
10 | export * from './assist'
11 | export * from './constants'
12 | export * from './event'
13 | export * from './lang'
14 |
--------------------------------------------------------------------------------
/src/util/lang.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * A simple uuid generator, support prefix and template pattern.
5 | *
6 | * @example
7 | *
8 | * uuid('v-') // -> v-xxx
9 | * uuid('v-ani-%{s}-translate') // -> v-ani-xxx
10 | */
11 | function uuid (prefix) {
12 | var id = Math.floor(Math.random() * 10000).toString(36)
13 | return prefix ? (
14 | ~prefix.indexOf('%{s}') ? (
15 | prefix.replace(/%\{s\}/g, id)
16 | ) : (prefix + id)
17 | ) : id
18 | }
19 |
20 | const getValueByPath = (model, path) => {
21 | if (!path || !model) return ''
22 | if (path.indexOf('.') < 0) {
23 | return getArrayValue(model, path)
24 | }
25 | const key = path.split('.')
26 | let current = model
27 | for (let i = 0; i < key.length; i++) {
28 | const currentKey = key[i]
29 | current = getArrayValue(current, currentKey)
30 | }
31 | return current
32 | }
33 |
34 | function getArrayValue (model, key) {
35 | if (key.includes('[')) {
36 | const parts = key.split(/[[\]]/).filter(p => p !== '')
37 | let value = model[parts[0]]
38 | for (const index of parts.slice(1)) {
39 | value = value[index]
40 | }
41 | return value
42 | } else {
43 | return model[key]
44 | }
45 | }
46 |
47 | export {
48 | uuid,
49 | getValueByPath
50 | }
51 |
--------------------------------------------------------------------------------
/src/util/mixins/emitter.js:
--------------------------------------------------------------------------------
1 | function broadcast (componentName, eventName, params) {
2 | this.$children.forEach(child => {
3 | var name = child.$options.name
4 |
5 | if (name === componentName) {
6 | child.$emit.apply(child, [eventName].concat(params))
7 | } else {
8 | broadcast.apply(child, [componentName, eventName].concat(params))
9 | }
10 | })
11 | }
12 |
13 | export default {
14 | methods: {
15 | dispatch (componentName, eventName, params) {
16 | var parent = this.$parent
17 | var name = parent.$options.name
18 |
19 | while (parent && (!name || name !== componentName)) {
20 | parent = parent.$parent
21 |
22 | if (parent) {
23 | name = parent.$options.name
24 | }
25 | }
26 | if (parent) {
27 | parent.$emit.apply(parent, [eventName].concat(params))
28 | }
29 | },
30 | broadcast (componentName, eventName, params) {
31 | broadcast.call(this, componentName, eventName, params)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/util/mixins/index.js:
--------------------------------------------------------------------------------
1 | import emitter from './emitter'
2 | import Popper from './popper'
3 | import Locale from './locale'
4 |
5 | export {
6 | emitter,
7 | Popper,
8 | Locale
9 | }
10 |
--------------------------------------------------------------------------------
/src/util/mixins/locale.js:
--------------------------------------------------------------------------------
1 | import { t } from '../../locale'
2 |
3 | export default {
4 | methods: {
5 | t (...args) {
6 | return t.apply(this, args)
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | mocha: true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/unit/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | Vue.config.productionTip = false
3 |
4 | // require all test files (files that ends with .spec.js)
5 | const testsContext = require.context('./specs', true, /\.spec$/)
6 | testsContext.keys().forEach(testsContext)
7 |
--------------------------------------------------------------------------------
/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | // This is a karma config file. For more details see
2 | // http://karma-runner.github.io/0.13/config/configuration-file.html
3 | // we are also using it with karma-webpack
4 | // https://github.com/webpack/karma-webpack
5 |
6 | var webpackConfig = require('../../build/webpack.config.test')
7 |
8 | module.exports = function (config) {
9 | config.set({
10 | // to run in additional browsers:
11 | // 1. install corresponding karma launcher
12 | // http://karma-runner.github.io/0.13/config/browsers.html
13 | // 2. add it to the `browsers` array below.
14 | browsers: ['ChromeHeadless'],
15 | frameworks: ['mocha', 'sinon-chai'],
16 | reporters: ['spec'],
17 | files: ['./index.js'],
18 | preprocessors: {
19 | './index.js': ['webpack', 'sourcemap']
20 | },
21 | webpack: webpackConfig,
22 | webpackMiddleware: {
23 | noInfo: true
24 | }
25 | })
26 | }
27 |
--------------------------------------------------------------------------------
/test/unit/specs/button.spec.js:
--------------------------------------------------------------------------------
1 | import { createVue, destroyVM } from '../util'
2 | import { expect } from 'chai'
3 |
4 | describe('Button', () => {
5 | let vm
6 | afterEach(() => {
7 | destroyVM(vm)
8 | })
9 |
10 | it('should render as