Compare commits

...

52 Commits
main ... master

Author SHA1 Message Date
tanjinzhou 7c1a14bb5e chore: opensource v1-doc 2021-03-12 15:48:30 +08:00
tanjinzhou 28325c0507 chore: opensource v1-doc 2021-03-12 15:47:29 +08:00
zkwolf 5e139a13e8
fix: revert the default ttab size of card (#3788) 2021-03-12 14:54:07 +08:00
John 976b0b409c
feat: add `dialogStyle` prop (#3794) 2021-03-12 14:52:35 +08:00
zkwolf dfcdf92f7a
fix: drawer esc keydown #3148 (#3790) 2021-03-12 14:51:06 +08:00
Kaworus dced59c65c
feat: add prop tab-size for card (#3762)
* feat: add param tab-size for card

* feat: add param tab-size for card
2021-03-09 15:52:18 +08:00
tangjinzhou 48181af9d6 release 1.7.4 2021-02-28 23:50:22 +08:00
tangjinzhou e427ca15bf perf: table 2021-02-28 23:34:04 +08:00
tangjinzhou 7f4eba3e93 docs: udpate changelog 2021-02-16 16:35:30 +08:00
tangjinzhou 961524b0a7 release 1.7.3 2021-02-16 16:07:12 +08:00
tangjinzhou 391309aad7 style: format code & update snap 2021-02-16 16:05:22 +08:00
tangjinzhou 5e063ba9a3 chore: remove colorpicker 2021-02-16 15:41:00 +08:00
tangjinzhou 22dccf46c5 fix: transformFile not work #3636 2021-02-15 16:07:22 +08:00
pengandpeng 1031e46926
fix: table scroll.x throw error when use expandedRowRender (#3626)
表头固定与展开行不存在冲突,结合使用时不应该报错
2021-02-06 13:46:43 +08:00
zkwolf 76d8408045
fix: closeable icon support in modal method (#3642) 2021-02-06 13:42:04 +08:00
Ken 48bf9ff1b5
fix: menu forceSubMenuRender not work #3615 (#3616) 2021-01-29 21:16:03 +08:00
zkwolf 96e5e836b7
fix: disabled tabPane can be actived #3575 (#3604) 2021-01-27 23:16:47 +08:00
Hyphon e179dedb4a
fix(date-picker): fix props(decade) problem for 1.x (#3536)
Co-authored-by: 李艺珅 <l>
2021-01-14 10:05:18 +08:00
Luka Jeran 1e2814608d
refactor: move ConfigConsumerProps to own file (#3524) 2021-01-14 10:03:43 +08:00
ajuner 0f467695e2
fix: add opacity transition (#3510) 2021-01-09 22:09:34 +08:00
John60676 6175fdbb0c
fix: slider accuracy problems 1.x (#3386)
* fix: slider accuracy problems

* refactor: order of operations
2020-12-17 16:28:30 +08:00
言肆 ec064fe8c2
fix(d.ts): space.d.ts #2923 typeScript definition update (#3340)
* fix(d.ts): space.d.ts  #2923

* fix: add Space ts export
2020-12-15 17:03:00 +08:00
tanjinzhou c74c621e7f fix: table sorter not work #3327 2020-12-09 17:32:38 +08:00
zkwolf 8ba75419b6
fix: checkbox can't trigger change (#3285)
* fix: checkbox can't trigger change

* test: add unit test

* chore: update vc-checkbox
2020-12-04 14:01:51 +08:00
John60676 1581ff3057
fix(button): dropdown inside ButtonGroup in the wrong position (#3036) 2020-11-23 13:55:06 +08:00
tanjinzhou 6ecbaaa547 fix: alert close icon style error on safari #3184 2020-11-16 13:03:21 +08:00
Emmanuel Pastor 388ed15e82
Update ValidationRule message type (#3163) 2020-11-13 11:08:27 +08:00
xrkffgg d552a41e96
fix: auto-complete disabled bg (#3143) 2020-11-12 15:53:19 +08:00
tangjinzhou c57df7db0c bump 1.7.2 2020-11-06 22:19:21 +08:00
tangjinzhou bb8bf0e0f8 test: update snap 2020-11-06 22:13:45 +08:00
tangjinzhou 1d2b93c871 fix: textarea height not correct #2974 2020-11-06 21:25:45 +08:00
tanjinzhou ee0470c280 revert: menu to 1.6.5 #3112 2020-11-06 16:44:30 +08:00
tangjinzhou aa1c9b237e fix: tree-select throw error #3126 2020-11-05 22:49:14 +08:00
tangjinzhou 1aca897b97 bump 1.7.1 2020-10-28 23:16:59 +08:00
tangjinzhou 5eb57fb1a9 fix: Menu component, wrong display Tooltip prompt problem 2020-10-28 23:16:41 +08:00
tanjinzhou a60ba677c2 bump 1.7.0 2020-10-28 13:27:32 +08:00
dogrod f194973151
fix(Table): Fix checkbox does not work when Table Filter value is number type (#3052) 2020-10-28 11:36:06 +08:00
tanjinzhou ef9797d337 style: prettier code 2020-10-28 11:32:38 +08:00
tanjinzhou ce1148838b feat: menu support nest component 2020-10-28 11:31:32 +08:00
tanjinzhou dae751368b fix: table ellipsis not work at fixed column #2916 #3021 2020-10-27 16:13:13 +08:00
tanjinzhou 5597ec0a91 fix: auto-complete select tab focus logic #1438 #3015 2020-10-27 14:57:47 +08:00
tanjinzhou f26c0218d5 feat: support webpack5 2020-10-27 14:03:43 +08:00
tanjinzhou aed1ff0660 perf: update some less 2020-10-27 14:03:25 +08:00
tanjinzhou a43b128262 feat: add ga_IE locale 2020-10-27 14:02:40 +08:00
John60676 6c521620b6
fix(modal): title props support render function (#3030) 2020-10-24 23:33:24 +08:00
Sun 4a3e310db7
fix: space can not inherit attrs (#2902) 2020-09-29 18:28:24 +08:00
tanjinzhou 5c8b77957c fix: upload method not work #2837 2020-09-23 14:21:10 +08:00
tanjinzhou 346a5ce2ba fix: modal types error #2790 2020-09-23 14:20:12 +08:00
Fei Teng 4851d10f60
fix bug tree select custom slot cann't use custom name (#2827) 2020-09-17 16:33:47 +08:00
Emmanuel Akhigbe 6e35cec375
Update dropdown.d.ts (#2757)
Correct typo; 'ontainer' to 'container'
2020-08-27 14:46:02 +08:00
tanjinzhou b690b38b7e test: update snap 2020-08-25 16:34:50 +08:00
tanjinzhou ab7bb9068b release 1.6.5 2020-08-25 16:11:18 +08:00
1019 changed files with 50948 additions and 1906 deletions

View File

@ -44,14 +44,6 @@ jobs:
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: Checkout submodules
uses: actions/checkout@v2
with:
repository: tangjinzhou/antdv-demo
token: ${{ secrets.ACCESS_TOKEN }}
path: antdv-demo
submodules: true
- name: restore cache from package-lock.json
uses: actions/cache@v1
with:

1
.gitignore vendored
View File

@ -72,3 +72,4 @@ package-lock.json
list.txt
site/dev.js
v2-doc/

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "antdv-demo"]
path = antdv-demo
url = git@github.com:tangjinzhou/antdv-demo.git

View File

@ -10,6 +10,70 @@
---
## 1.7.4
`2021-02-28`
- 🌟 Optimize the performance of `Table` [#3531](https://github.com/vueComponent/ant-design-vue/issues/3531)
## 1.7.3
`2021-02-16`
- 🌟 `Modal` api method call supports defining close icon [#3642](https://github.com/vueComponent/ant-design-vue/issues/3642)
- 🌟 `Form` message support function [#3163](https://github.com/vueComponent/ant-design-vue/issues/3163)
- 🌟 Optimize the animation effect of `Progress` [#3510](https://github.com/vueComponent/ant-design-vue/issues/3510)
- 🐞 Fix the background color problem when `AutoComplete` is disabled [#3143](https://github.com/vueComponent/ant-design-vue/issues/3143)
- 🐞 Fix the issue that the `Alert` close button is displayed abnormally under safari [#3184](https://github.com/vueComponent/ant-design-vue/issues/3184)
- 🐞 Fix the problem that `Dropdown` shows the wrong position under `ButtonGroup` [#2995](https://github.com/vueComponent/ant-design-vue/issues/2995)
- 🐞 Fix the issue that the change event will no longer be triggered after `RadioGroup` is blocked from being selected [#3047](https://github.com/vueComponent/ant-design-vue/issues/3047)
- 🐞 Fix the problem that `Table` cannot be sorted [#3327](https://github.com/vueComponent/ant-design-vue/issues/3327)
- 🐞 Fix missing `Space` component type file issue [#3340](https://github.com/vueComponent/ant-design-vue/issues/3340)
- 🐞 Fix `Slider`'s position calculation error under decimal precision [#3386](https://github.com/vueComponent/ant-design-vue/issues/3386)
- 🐞 Fix `DatePicker` mode="decade" invalidation issue [#3536](https://github.com/vueComponent/ant-design-vue/issues/3536)
- 🐞 Fix the problem that the keyboard can still be switched in the diabled state of `Tabs` [#3575](https://github.com/vueComponent/ant-design-vue/issues/3575)
- 🐞 Fix the issue that `Menu` `forceSubMenuRender` does not take effect [#3615](https://github.com/vueComponent/ant-design-vue/issues/3615)
- 🐞 Fix `Upload` `transformFile` not executing issue [#3636](https://github.com/vueComponent/ant-design-vue/issues/3636)
## 1.7.2
`2020-11-06`
- 🐞 Fix the problem of incorrect height of Textarea component [#2974](https://github.com/vueComponent/ant-design-vue/issues/2974)
- 🐞 Roll back Menu component to version 1.6.5 to be consistent [#3112](https://github.com/vueComponent/ant-design-vue/issues/3112)
- 🐞 Fix TreeSelect throw error [#3126](https://github.com/vueComponent/ant-design-vue/issues/3126)
## 1.7.1
`2020-10-28`
- 🐞 Fix Menu component, wrong display Tooltip prompt problem
## 1.7.0
`2020-10-28`
- 🌟 Recursive Menu component, supports arbitrary nesting of other elements [#1452](https://github.com/vueComponent/ant-design-vue/issues/1452)
- 🇮🇪 Add Irish language internationalization support
- 🐞 Fix webpack 5 compatibility issues.
- 🐞 Fix the problem that the Upload method attribute does not take effect [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
- 🐞 Fix the problem that Space does not declare properties and does not mount the root node [#2902](https://github.com/vueComponent/ant-design-vue/issues/2902)
- 🐞 Fix the problem that Table component filter does not support number type [#3052](https://github.com/vueComponent/ant-design-vue/issues/3052)
- 🐞 Fix Table fixed column ellipsis not working issue [#2916](https://github.com/vueComponent/ant-design-vue/issues/2916)
- 🐞 Fix AutoComplete component, need two tab keys to focus issue [#1438](https://github.com/vueComponent/ant-design-vue/issues/1438)
- 🐞 Fix the problem that TreeSelect cannot customize slot [#2827](https://github.com/vueComponent/ant-design-vue/issues/2827)
## 1.6.5
`2020-08-25`
- 🔥🔥🔥 Vue 3 compatible [2.0.0-beta.3](https://2x.antdv.com/)
- 🔥 Add Space component [#2669](https://github.com/vueComponent/ant-design-vue/pull/2669)
- 🌟 Optimize zh_TW language pack [#2679](https://github.com/vueComponent/ant-design-vue/pull/2679)
- 🐞 Fix breadcrumb `Breadcrumb` repeated key problem [#2505](https://github.com/vueComponent/ant-design-vue/issues/2505)
- 🐞 Fix the problem of misalignment in the fixed column of Table [#1493](https://github.com/vueComponent/ant-design-vue/issues/1493)
- 🐞 Fix the problem that the Enter key will report an error when the Mentions component is empty [#2662](https://github.com/vueComponent/ant-design-vue/pull/2662)
## 1.6.4
`2020-07-21`

View File

@ -10,6 +10,69 @@
---
## 1.7.4
`2021-02-28`
- 🌟 优化 `Table` 性能 [#3531](https://github.com/vueComponent/ant-design-vue/issues/3531)
## 1.7.3
`2021-02-16`
- 🌟 `Modal` api 方式调用支持定义关闭图标 [#3642](https://github.com/vueComponent/ant-design-vue/issues/3642)
- 🌟 `Form` message 支持函数 [#3163](https://github.com/vueComponent/ant-design-vue/issues/3163)
- 🌟 优化 `Progress` 动画效果 [#3510](https://github.com/vueComponent/ant-design-vue/issues/3510)
- 🐞 修复 `AutoComplete` disabled 时背景颜色异常问题 [#3143](https://github.com/vueComponent/ant-design-vue/issues/3143)
- 🐞 修复 `Alert` 关闭按钮在 safari 下显示异常问题 [#3184](https://github.com/vueComponent/ant-design-vue/issues/3184)
- 🐞 修复 `Dropdown``ButtonGroup` 下显示位置错误问题 [#2995](https://github.com/vueComponent/ant-design-vue/issues/2995)
- 🐞 修复 `RadioGroup` 阻止选中后,不再触发 change 事件问题 [#3047](https://github.com/vueComponent/ant-design-vue/issues/3047)
- 🐞 修复 `Table` 无法排序的问题 [#3327](https://github.com/vueComponent/ant-design-vue/issues/3327)
- 🐞 修复缺失 `Space` 组件类型文件问题 [#3340](https://github.com/vueComponent/ant-design-vue/issues/3340)
- 🐞 修复 `Slider` 在小数精度下位置计算错误问题 [#3386](https://github.com/vueComponent/ant-design-vue/issues/3386)
- 🐞 修复 `DatePicker` mode="decade" 失效问题 [#3536](https://github.com/vueComponent/ant-design-vue/issues/3536)
- 🐞 修复 `Tabs` diabled 状态下依然可以通过键盘切换问题 [#3575](https://github.com/vueComponent/ant-design-vue/issues/3575)
- 🐞 修复 `Menu` `forceSubMenuRender` 不生效问题 [#3615](https://github.com/vueComponent/ant-design-vue/issues/3615)
- 🐞 修复 `Upload` `transformFile` 不执行问题 [#3636](https://github.com/vueComponent/ant-design-vue/issues/3636)
## 1.7.2
`2020-11-06`
- 🐞 修复 Textarea 组件高度不正确问题 [#2974](https://github.com/vueComponent/ant-design-vue/issues/2974)
- 🐞 回滚 Menu 组件到 1.6.5 版本一致 [#3112](https://github.com/vueComponent/ant-design-vue/issues/3112)
- 🐞 修复 TreeSelect throw error [#3126](https://github.com/vueComponent/ant-design-vue/issues/3126)
## 1.7.1
`2020-10-28`
- 🐞 修复 Menu 组件,错误展示 Tooltip 提示的问题
## 1.7.0
`2020-10-28`
- 🌟 递归 Menu 组件,支持任意嵌套其他元素 [#1452](https://github.com/vueComponent/ant-design-vue/issues/1452)
- 🇮🇪 添加爱尔兰语国际化支持
- 🐞 修复 webpack 5 兼容问题。
- 🐞 修复 Upload method 属性不生效问题 [#2837](https://github.com/vueComponent/ant-design-vue/issues/2837)
- 🐞 修复 Space 未声明属性,不挂载根结点上问题 [#2902](https://github.com/vueComponent/ant-design-vue/issues/2902)
- 🐞 修复 Table 组件 filter 不支持 number 类型问题 [#3052](https://github.com/vueComponent/ant-design-vue/issues/3052)
- 🐞 修复 Table 固定列 ellipsis 不生效问题 [#2916](https://github.com/vueComponent/ant-design-vue/issues/2916)
- 🐞 修复 AutoComplete 组件,需要两次 tab 键才可 focus 问题 [#1438](https://github.com/vueComponent/ant-design-vue/issues/1438)
- 🐞 修复 TreeSelect 不能自定义 slot 问题 [#2827](https://github.com/vueComponent/ant-design-vue/issues/2827)
## 1.6.5
`2020-08-25`
- 🔥🔥🔥 兼容 Vue 3 的 [2.0.0-beta.3](https://2x.antdv.com/) 版本发布
- 🔥 新增 Space 组件 [#2669](https://github.com/vueComponent/ant-design-vue/pull/2669)
- 🌟 优化 zh_TW 语言包 [#2679](https://github.com/vueComponent/ant-design-vue/pull/2679)
- 🐞 修复面包屑 `Breadcrumb` 重复 key 问题 [#2505](https://github.com/vueComponent/ant-design-vue/issues/2505)
- 🐞 修复 Table 固定列情况下错位问题 [#1493](https://github.com/vueComponent/ant-design-vue/issues/1493)
- 🐞 修复 Mentions 组件为空时回车键报错的问题 [#2662](https://github.com/vueComponent/ant-design-vue/pull/2662)
## 1.6.4
`2020-07-21`

View File

@ -40,6 +40,7 @@ An enterprise-class UI components based on Ant Design and Vue.
- 提炼自企业级中后台产品的交互语言和视觉风格。
- 开箱即用的高质量 Vue 组件。
- 共享 [Ant Design of React](http://ant-design.gitee.io/docs/spec/introduce-cn) 设计工具体系。
- 从 [2.x](https://2x.antdv.com/) 版本开始支持 Vue 3
## 支持环境

View File

@ -40,6 +40,7 @@ English | [简体中文](./README-zh_CN.md)
- An enterprise-class UI design system for desktop applications.
- A set of high-quality Vue components out of the box.
- Shared [Ant Design of React](https://ant.design/docs/spec/introduce) design resources.
- Support Vue 3 from [2.x](https://2x.antdv.com/)
## Environment Support

View File

@ -23,7 +23,7 @@ function transformLess(lessFile, config = {}) {
.render(data, lessOpts)
.then(result => {
const source = result.css;
return postcss(postcssConfig.plugins).process(source);
return postcss(postcssConfig.plugins).process(source, { from: undefined });
})
.then(r => {
return r.css;

@ -1 +0,0 @@
Subproject commit 84ee25d800ce56d1fc170d9dbd7b150343be9b0e

14
antdv-demo/.babelrc Normal file
View File

@ -0,0 +1,14 @@
{
"env": {
"test": {
"presets": [["env", { "targets": { "node": "current" } }]],
"plugins": [
"transform-vue-jsx",
"transform-object-assign",
"transform-object-rest-spread",
"transform-class-properties",
"transform-runtime"
]
}
}
}

11
antdv-demo/.editorconfig Normal file
View File

@ -0,0 +1,11 @@
# 🎨 editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

8
antdv-demo/.eslintignore Normal file
View File

@ -0,0 +1,8 @@
node_modules/
**/*.spec.*
**/style/
*.html
/components/test/*
_site/
dist/
package.json

53
antdv-demo/.eslintrc Normal file
View File

@ -0,0 +1,53 @@
{
"root": true,
"env": {
"browser": true,
"node": true,
"jasmine": true,
"jest": true,
"es6": true
},
"parserOptions": {
"parser": "babel-eslint"
},
"extends": ["plugin:vue/recommended", "prettier"],
"plugins": ["markdown"],
"overrides": [
{
"files": ["**/demo/*.md"],
"processor": "markdown/markdown",
"rules": {
"no-console": "off"
}
}
],
"rules": {
"comma-dangle": [2, "always-multiline"],
"no-var": "error",
"no-console": [2, { "allow": ["warn", "error"] }],
"object-shorthand": 2,
"no-unused-vars": [2, { "ignoreRestSiblings": true, "argsIgnorePattern": "^h$" }],
"no-undef": 2,
"camelcase": "off",
"no-extra-boolean-cast": "off",
"semi": ["error", "always"],
"vue/require-prop-types": "off",
"vue/require-default-prop": "off",
"vue/no-reserved-keys": "off",
"vue/comment-directive": "off",
"vue/prop-name-casing": "off",
"vue/max-attributes-per-line": [
2,
{
"singleline": 20,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}
]
},
"globals": {
"h": true
}
}

109
antdv-demo/.gitignore vendored Normal file
View File

@ -0,0 +1,109 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
site/dev.js
_site/
package-lock.json
testDemo/

7
antdv-demo/.huskyrc Normal file
View File

@ -0,0 +1,7 @@
{
"hooks": {
"pre-commit": "pretty-quick --staged",
"pre-publish": "npm run lint",
"commit-msg": "commitlint -x @commitlint/config-conventional -e $GIT_PARAMS"
}
}

View File

@ -0,0 +1,29 @@
**/*.svg
package.json
lib/
es/
dist/
_site/
coverage/
CNAME
LICENSE
yarn.lock
netlify.toml
yarn-error.log
*.sh
*.snap
.gitignore
.npmignore
.prettierignore
.DS_Store
.editorconfig
.eslintignore
**/*.yml
components/style/color/*.less
**/assets
.gitattributes
.stylelintrc
.vcmrc
.png
.npmrc.template
.huskyrc

14
antdv-demo/.prettierrc Normal file
View File

@ -0,0 +1,14 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"proseWrap": "never",
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
]
}

23
antdv-demo/.stylelintrc Normal file
View File

@ -0,0 +1,23 @@
{
"extends": ["stylelint-config-standard", "stylelint-config-prettier"],
"rules": {
"comment-empty-line-before": null,
"declaration-empty-line-before": null,
"function-comma-newline-after": null,
"function-name-case": null,
"function-parentheses-newline-inside": null,
"function-max-empty-lines": null,
"function-whitespace-after": null,
"indentation": null,
"number-leading-zero": null,
"number-no-trailing-zeros": null,
"rule-empty-line-before": null,
"selector-combinator-space-after": null,
"selector-list-comma-newline-after": null,
"selector-pseudo-element-colon-notation": null,
"unit-no-unknown": null,
"value-list-max-empty-lines": null,
"font-family-no-missing-generic-family-keyword": null,
"no-descending-specificity": null
}
}

View File

@ -0,0 +1,3 @@
module.exports = {
...require('./mock/user'),
};

5
antdv-demo/build.sh Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
rm -rf dist
mkdir dist
./node_modules/.bin/webpack --config webpack.site.config.js
cp dist/index.html index.html

View File

@ -0,0 +1,5 @@
module.exports = {
dev: {
componentName: 'form', // dev components
},
};

213
antdv-demo/build/dev.js Normal file
View File

@ -0,0 +1,213 @@
process.env.ENTRY_INDEX = 'dev';
const fs = require('fs');
const path = require('path');
const chokidar = require('chokidar');
const importFresh = require('import-fresh');
const replace = require('json-templater/string');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const devWebpack = require('./webpack.dev.conf');
const configPath = path.join(__dirname, './config.js');
/**
* a-bc-d --> aBcD
* @param {string} s
*/
const camelize = s => s.replace(/-(\w)/g, ($, $1) => $1.toUpperCase());
/**
* radio-group --> radio
* @param {string} s
*/
const getUpper = s => s.replace(/(-[a-z]*)/g, '');
let { componentName } = require('./config').dev;
const componentsInPrototype = ['Modal', 'message', 'notification'];
const MAIN_TEMPLATE = `import 'babel-polyfill';
import Vue from 'vue';
import Vuex from 'vuex';
import VueI18n from 'vue-i18n';
import VueRouter from 'vue-router';
import VueClipboard from 'vue-clipboard2';
import Md from '../components/md';
import Api from '../components/api';
import demoBox from '../components/demoBox';
import demoSort from '../components/demoSort';
import demoContainer from '../components/demoContainer';
import { message, notification } from 'ant-design-vue';
{{importComponents}}
{{importStyles}}
import 'ant-design-vue/es/message/style';
import 'ant-design-vue/es/notification/style';
import Test from '../docs/{{name}}/demo/index.vue';
import zhCN from '../theme/zh-CN';
import enUS from '../theme/en-US';
import './index.less';
Vue.use(Vuex);
Vue.use(VueClipboard);
Vue.use(VueRouter);
Vue.use(VueI18n);
Vue.component(Md.name, Md);
Vue.component(Api.name, Api);
Vue.component('demo-box', demoBox);
Vue.component('demo-sort', demoSort);
Vue.component('demo-container', demoContainer);
Vue.prototype.$message = message;
Vue.prototype.$notification = notification;
Vue.prototype.$info = Modal.info;
Vue.prototype.$success = Modal.success;
Vue.prototype.$error = Modal.error;
Vue.prototype.$warning = Modal.warning;
Vue.prototype.$confirm = Modal.confirm;
Vue.prototype.$destroyAll = Modal.destroyAll;
Vue.prototype.$form = Form;
Vue.use(Modal);
{{install}}
const i18n = new VueI18n({
locale: enUS.locale,
messages: {
[enUS.locale]: { message: enUS.messages },
[zhCN.locale]: { message: zhCN.messages },
},
});
const router = new VueRouter({
mode: 'history',
routes: [{
path: '/test',
component: () => import('../testDemo/index.vue'),
}, {
path: '/*', component: Test
}],
});
const store = new Vuex.Store({
state: {
username: 'zeka',
},
mutations: {
update(state, payload) {
state.username = payload.username;
},
},
});
new Vue({
el: '#app',
i18n,
router,
store,
});
`;
const OUTPUT_PATH = path.join(__dirname, '../site/dev.js');
const generateEntry = components =>
Object.keys(components)
.map(component => `import ${component} from 'ant-design-vue/es/${components[component]}';`)
.join('\n');
const generateStyles = components =>
Object.keys(components)
.map(component => `import 'ant-design-vue/es/${components[component]}/style';`)
.join('\n');
const generateInstall = components =>
Object.keys(components)
.map(component => `Vue.use(${component});`)
.join('\n');
const renderTemplate = name => {
const components = {
Tooltip: 'tooltip', // for DemoBox
Icon: 'icon', // Basic
Form: 'form',
Modal: 'modal',
};
const demoPaths = fs
.readdirSync(path.join(__dirname, `../docs/${name}/demo`))
.map(p => `../docs/${name}/demo/${p}`);
const testPaths = fs
.readdirSync(path.join(__dirname, `../testDemo`))
.map(p => `../testDemo/${p}`);
[...demoPaths, ...testPaths].forEach(demoPath => {
const demo = fs.readFileSync(path.join(__dirname, demoPath)).toString();
const componentsInDemo = demo.match(/a-(\w+(-\w+)*)/g) || [];
componentsInDemo.forEach(name => {
const dirName = name.replace(/^a-/, '');
const componentName = camelize(name).replace(/^a/, '');
const upperComponentDir = getUpper(dirName);
const upperComponentName = upperComponentDir.replace(/^[a-z]/, $ => $.toUpperCase());
const componentPath = path.join(__dirname, `../../components/${dirName}`);
if (fs.existsSync(componentPath)) {
if (componentsInPrototype.includes(componentName)) {
return;
}
components[componentName] = dirName;
} else if (fs.existsSync(path.join(__dirname, `../../components/${upperComponentDir}`))) {
components[upperComponentName] = upperComponentDir;
}
});
});
const importComponents = generateEntry(components);
const importStyles = generateStyles(components);
const install = generateInstall(components);
const template = replace(MAIN_TEMPLATE, {
importComponents,
importStyles,
install,
name,
});
fs.writeFileSync(OUTPUT_PATH, template);
};
function fsExistsSync(path) {
try {
fs.accessSync(path, fs.F_OK);
} catch (e) {
return false;
}
return true;
}
if (!fsExistsSync(path.join(__dirname, '../testDemo/index.vue'))) {
if (!fsExistsSync(path.join(__dirname, '../testDemo'))) {
fs.mkdirSync(path.join(__dirname, '../testDemo'));
}
fs.writeFileSync(path.join(__dirname, '../testDemo/index.vue'), `<template></template>`);
}
let demoWatcher;
chokidar.watch(configPath, { ignoreInitial: true }).on('change', async () => {
({ componentName } = importFresh(configPath).dev);
demoWatcher && (await demoWatcher.close());
demoWatcher = chokidar.watch(path.join(__dirname, `../docs/${componentName}/demo`));
demoWatcher.on('change', () => {
renderTemplate(componentName);
});
renderTemplate(componentName);
});
renderTemplate(componentName);
const compiler = webpack(devWebpack);
const configuration = devWebpack.devServer;
const server = new WebpackDevServer(compiler, configuration);
server.listen(configuration.port);

View File

@ -0,0 +1,45 @@
'use strict';
module.exports = function(modules) {
const plugins = [
require.resolve('babel-plugin-transform-vue-jsx'),
require.resolve('babel-plugin-inline-import-data-uri'),
require.resolve('babel-plugin-transform-es3-member-expression-literals'),
require.resolve('babel-plugin-transform-es3-property-literals'),
require.resolve('babel-plugin-transform-object-assign'),
require.resolve('babel-plugin-transform-object-rest-spread'),
require.resolve('babel-plugin-transform-class-properties'),
];
plugins.push([
require.resolve('babel-plugin-transform-runtime'),
{
polyfill: false,
},
]);
return {
presets: [
[
require.resolve('babel-preset-env'),
{
modules,
targets: {
browsers: [
'last 2 versions',
'Firefox ESR',
'> 1%',
'ie >= 9',
'iOS >= 8',
'Android >= 4',
],
},
},
],
],
plugins,
env: {
test: {
plugins: [require.resolve('babel-plugin-istanbul')],
},
},
};
};

View File

@ -0,0 +1,166 @@
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = function(env) {
const isDev = env === 'development';
return {
test: /\.less$/,
oneOf: [
/* config.module.rule('less').oneOf('vue-modules') */
{
resourceQuery: /module/,
use: [
isDev
? {
loader: 'vue-style-loader',
options: {
sourceMap: isDev,
shadowMode: false,
},
}
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: isDev,
importLoaders: 2,
modules: {
localIdentName: '[name]_[local]_[hash:base64:5]',
},
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: isDev,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
sourceMap: isDev,
modifyVars: {},
javascriptEnabled: true,
},
},
},
],
},
/* config.module.rule('less').oneOf('vue') */
{
resourceQuery: /\?vue/,
use: [
isDev
? {
loader: 'vue-style-loader',
options: {
sourceMap: isDev,
shadowMode: false,
},
}
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: isDev,
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: isDev,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
sourceMap: isDev,
modifyVars: {},
javascriptEnabled: true,
},
},
},
],
},
/* config.module.rule('less').oneOf('normal-modules') */
{
test: /\.module\.\w+$/,
use: [
isDev
? {
loader: 'vue-style-loader',
options: {
sourceMap: isDev,
shadowMode: false,
},
}
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: isDev,
importLoaders: 2,
modules: {
localIdentName: '[name]_[local]_[hash:base64:5]',
},
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: isDev,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
sourceMap: isDev,
modifyVars: {},
javascriptEnabled: true,
},
},
},
],
},
/* config.module.rule('less').oneOf('normal') */
{
use: [
isDev
? {
loader: 'vue-style-loader',
options: {
sourceMap: isDev,
shadowMode: false,
},
}
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: isDev,
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: isDev,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
sourceMap: isDev,
modifyVars: {},
javascriptEnabled: true,
},
},
},
],
},
],
};
};

View File

@ -0,0 +1,226 @@
const path = require('path');
const webpack = require('webpack');
const Prism = require('prismjs');
require('prismjs/components/prism-jsx.min.js');
require('prismjs/components/prism-bash.min.js');
require('prismjs/components/prism-json.min.js');
require('prismjs/components/prism-diff.min.js');
require('prismjs/components/prism-less.min.js');
const Token = require('markdown-it/lib/token');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const cheerio = require('cheerio');
const WebpackBar = require('webpackbar');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const getBabelCommonConfig = require('./getBabelCommonConfig');
const babelConfig = getBabelCommonConfig(false);
babelConfig.plugins.push(require.resolve('babel-plugin-syntax-dynamic-import'));
const fetch = (str, tag, scoped) => {
const $ = cheerio.load(str, {
decodeEntities: false,
xmlMode: true,
});
if (!tag) {
return str;
}
if (tag === 'style') {
return scoped
? $(`${tag}[scoped]`).html()
: $(`${tag}`)
.not(`${tag}[scoped]`)
.html();
}
return $(tag).html();
};
/**
* `{{ }}` => `<span>{{</span> <span>}}</span>`
* @param {string} str
* @return {string}
*/
const replaceDelimiters = function(str) {
return str.replace(/({{|}})/g, '<span>$1</span>');
};
/**
* renderHighlight
* @param {string} str
* @param {string} lang
*/
const renderHighlight = function(str, lang) {
if (!(lang && Prism.languages[lang])) {
return '';
}
try {
return replaceDelimiters(Prism.highlight(str, Prism.languages[lang], lang));
} catch (err) {}
};
const md = require('markdown-it')('default', {
html: true,
breaks: true,
highlight: renderHighlight,
}).use(require('markdown-it-anchor'), {
level: 2,
slugify: string =>
string
.trim()
.split(' ')
.join('-'),
permalink: true,
// renderPermalink: (slug, opts, state, permalink) => {},
permalinkClass: 'anchor',
permalinkSymbol: '#',
permalinkBefore: false,
});
// md.renderer.rules.fence = wrap(md.renderer.rules.fence)
const cnReg = new RegExp('<(cn)(?:[^<]|<)+</\\1>', 'g');
const usReg = new RegExp('<(us)(?:[^<]|<)+</\\1>', 'g');
md.core.ruler.push('update_template', function replace({ tokens }) {
let cn = '';
let us = '';
let template = '';
let script = '';
let style = '';
let scopedStyle = '';
let code = '';
let sourceCode = '';
tokens.forEach(token => {
if (token.type === 'html_block') {
if (token.content.match(cnReg)) {
cn = fetch(token.content, 'cn');
token.content = '';
}
if (token.content.match(usReg)) {
us = fetch(token.content, 'us');
token.content = '';
}
}
if (token.type === 'fence' && token.info === 'vue' && token.markup === '```') {
sourceCode = token.content;
code = '```html\n' + token.content + '```';
template = fetch(token.content, 'template');
script = fetch(token.content, 'script');
style = fetch(token.content, 'style');
scopedStyle = fetch(token.content, 'style', true);
token.content = '';
token.type = 'html_block';
}
});
if (template) {
let jsfiddle = {
us,
cn,
sourceCode: Buffer.from(sourceCode).toString('base64'),
};
jsfiddle = md.utils.escapeHtml(JSON.stringify(jsfiddle));
const codeHtml = code ? md.render(code.replace(/@/g, '__at__')).replace(/__at__/g, '@') : '';
const cnHtml = cn ? md.render(cn) : '';
let newContent = `
<template>
<demo-box :jsfiddle="${jsfiddle}">
<template slot="component">${template}</template>
<template slot="description">${cnHtml}</template>
<template slot="us-description">${us ? md.render(us) : ''}</template>
<template slot="code">${Buffer.from(codeHtml).toString('base64')}</template>
</demo-box>
</template>`;
newContent += script
? `
<script>
${script || ''}
</script>
`
: '';
newContent += style ? `<style>${style || ''}</style>` : '';
newContent += scopedStyle ? `<style scoped>${scopedStyle || ''}</style>` : '';
const t = new Token('html_block', '', 0);
t.content = newContent;
tokens.push(t);
}
});
const vueLoaderOptions = {
loaders: {
js: [
{
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: ['transform-vue-jsx', 'transform-object-rest-spread'],
},
},
],
},
};
module.exports = {
mode: 'production',
entry: {
index: [`./site/${process.env.ENTRY_INDEX || 'index'}.js`],
},
module: {
rules: [
{
test: /\.md$/,
use: [
{
loader: 'vue-loader',
options: vueLoaderOptions,
},
{
loader: 'vue-antd-md-loader',
options: Object.assign(md, {
wrapper: 'div',
raw: true,
}),
},
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderOptions,
},
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: babelConfig,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
],
},
resolve:
process.env.NODE_ENV === 'development'
? {
modules: ['node_modules', path.join(__dirname, '../node_modules')],
extensions: ['.js', '.jsx', '.vue', '.md'],
alias: {
vue$: 'vue/dist/vue.esm.js',
'ant-design-vue$': path.join(__dirname, '../../components/index.js'),
'ant-design-vue/es': path.join(__dirname, '../../components'),
'ant-design-vue/lib': path.join(__dirname, '../../components'),
},
}
: {
modules: ['node_modules'],
extensions: ['.js', '.jsx', '.vue', '.md'],
alias: {
vue$: 'vue/dist/vue.esm.js',
},
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new VueLoaderPlugin(),
new WebpackBar(),
new HardSourceWebpackPlugin(),
],
};

View File

@ -0,0 +1,59 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const lessLoaderConfig = require('./lessLoaderConfig');
const { createMockMiddleware } = require('umi-mock-middleware');
module.exports = merge(baseWebpackConfig, {
mode: 'development',
output: {
path: path.resolve(__dirname, '../dist'),
publicPath: '/',
filename: 'build.js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
},
lessLoaderConfig('development'),
],
},
devServer: {
port: process.env.PORT || 3000,
host: '0.0.0.0',
historyApiFallback: {
rewrites: [{ from: /./, to: '/index.html' }],
},
disableHostCheck: true,
hot: true,
open: true,
headers: { 'Access-Control-Allow-Origin': '*' },
// 解析body对接真实服务端环境需要注释掉
before(app) {
// var bodyParser = require("body-parser");
// app.use(bodyParser.json());
if (process.env.MOCK !== 'none') {
app.use(createMockMiddleware());
}
},
proxy: {
'/api': {
target: 'http://localhost:3000',
},
},
},
performance: {
hints: false,
},
devtool: '#source-map',
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
filename: 'index.html',
inject: true,
}),
],
});

View File

@ -0,0 +1,64 @@
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
let lessLoaderConfig = require('./lessLoaderConfig')('production');
module.exports = merge(baseWebpackConfig, {
output: {
path: path.resolve(__dirname, '../_site'),
publicPath: 'https://alicdn.antdv.com/v1/',
filename: '[name].[contenthash:8].js',
chunkFilename: '[contenthash:8].async.js',
},
module: {
rules: [
lessLoaderConfig,
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
},
],
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial',
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true,
},
},
},
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
}),
new HtmlWebpackPlugin({
template: './public/index.html',
inject: true,
production: true,
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[id].[contenthash:8].css',
}),
],
});

View File

@ -0,0 +1,124 @@
<script>
const carbonUrls = {
'www.antdv.com': '//cdn.carbonads.com/carbon.js?serve=CK7DL2JW&placement=antdvcom',
// 'tangjinzhou.gitee.io':
// '//cdn.carbonads.com/carbon.js?serve=CK7DL2JN&placement=tangjinzhougiteeio',
// 'ant-design-vue.gitee.io':
// '//cdn.carbonads.com/carbon.js?serve=CK7DL2JN&placement=antdesignvuegiteeio',
'vue.ant.design': '//cdn.carbonads.com/carbon.js?serve=CK7DL2JW&placement=vueantdesign',
};
const carbonUrl =
carbonUrls[location.host] ||
'//cdn.carbonads.com/carbon.js?serve=CK7DL2JW&placement=vueantdesign';
export default {
props: {
isMobile: Boolean,
},
watch: {
$route(e, t) {
let adId = '#carbonads';
// if(isGitee) {
// adId = '#cf';
// }
if (e.path !== t.path && this.$el.querySelector(adId)) {
this.$el.innerHTML = '';
this.load();
}
this.adInterval && clearInterval(this.adInterval);
this.adInterval = setInterval(() => {
if (!this.$el.querySelector(adId)) {
this.$el.innerHTML = '';
this.load();
}
}, 20000);
},
},
mounted() {
this.load();
},
methods: {
load() {
// if(isGitee) {
// axios.get('https://api.codefund.app/properties/162/funder.html?template=horizontal')
// .then(function (response) {
// document.getElementById("codefund-ads").innerHTML = response.data;
// });
// } else
if (carbonUrl) {
const e = document.createElement('script');
e.id = '_carbonads_js';
e.src = carbonUrl;
this.$el.appendChild(e);
}
},
},
render() {
return <div id="carbon-ads" class={this.isMobile ? 'carbon-mobile' : ''} />;
},
};
</script>
<style lang="less">
#carbon-ads {
width: 280px;
float: right;
margin-top: 75px;
position: relative;
right: 0;
bottom: 0;
padding: 0;
overflow: hidden;
z-index: 9;
background-color: #fff;
border-radius: 3px;
font-size: 13px;
background: #f5f5f5;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
}
#carbonads {
overflow: hidden;
}
#carbon-ads a {
display: inline-block;
color: #7f8c8d;
font-weight: normal;
}
#carbon-ads span {
color: #7f8c8d;
}
#carbon-ads img {
float: left;
padding-right: 10px;
}
#carbon-ads .carbon-img,
#carbon-ads .carbon-text {
display: block;
font-weight: normal;
color: #34495e;
}
#carbon-ads .carbon-text {
padding-top: 6px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
#carbon-ads .carbon-poweredby {
color: #aaa;
font-weight: normal;
line-height: 1.2;
margin-top: 6px;
}
#carbon-ads.carbon-mobile {
width: 100%;
position: relative;
right: 0;
bottom: 0;
padding: 0;
margin-bottom: 15px;
margin-top: 5px;
.carbon-img {
float: left;
margin-right: 10px;
}
}
</style>

View File

@ -0,0 +1,36 @@
<script>
export default {
mounted() {
this.load();
},
methods: {
load() {
if (this.scriptDom) {
this.$el.removeChild(this.scriptDom);
}
this.$refs.ins.innerHTML = '';
const e = document.createElement('script');
e.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
e.async = true;
this.$el.appendChild(e);
this.scriptDom = e;
(window.adsbygoogle = window.adsbygoogle || []).push({});
},
},
render() {
return (
<div class="google-ads" id="API">
<ins
ref="ins"
class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-4801326429087140"
data-ad-slot="7647023136"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</div>
);
},
};
</script>

View File

@ -0,0 +1,35 @@
<script>
export default {
mounted() {
this.load();
},
methods: {
load() {
if (this.scriptDom) {
this.$el.removeChild(this.scriptDom);
}
this.$refs.ins.innerHTML = '';
const e = document.createElement('script');
e.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
e.async = true;
this.$el.appendChild(e);
this.scriptDom = e;
(window.adsbygoogle = window.adsbygoogle || []).push({});
},
},
render() {
return (
<div class="google-ads" id="api">
<ins
ref="ins"
style="display:block"
data-ad-client="ca-pub-4801326429087140"
data-ad-slot="3952358732"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</div>
);
},
};
</script>

View File

@ -0,0 +1,35 @@
<script>
export default {
mounted() {
this.load();
},
methods: {
load() {
if (this.scriptDom) {
this.$el.removeChild(this.scriptDom);
}
this.$refs.ins.innerHTML = '';
const e = document.createElement('script');
e.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
e.async = true;
this.$el.appendChild(e);
this.scriptDom = e;
(window.adsbygoogle = window.adsbygoogle || []).push({});
},
},
render() {
return (
<div class="google-ads">
<ins
ref="ins"
style="display:block"
data-ad-client="ca-pub-4801326429087140"
data-ad-slot="9507921838"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</div>
);
},
};
</script>

View File

@ -0,0 +1,34 @@
<script>
export default {
mounted() {
this.load();
},
methods: {
load() {
if (this.scriptDom) {
this.$el.removeChild(this.scriptDom);
}
this.$refs.ins.innerHTML = '';
const e = document.createElement('script');
e.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
e.async = true;
this.$el.appendChild(e);
this.scriptDom = e;
(window.adsbygoogle = window.adsbygoogle || []).push({});
},
},
render() {
return (
<div style="width: 300px;float: right;margin-top: 75px;position: relative;right: 0;bottom: 0;padding: 0;z-index: 9;">
<ins
ref="ins"
class="adsbygoogle"
style="display:inline-block;width:300px;height:100px"
data-ad-client="ca-pub-4801326429087140"
data-ad-slot="2774992529"
></ins>
</div>
);
},
};
</script>

View File

@ -0,0 +1,35 @@
<script>
export default {
mounted() {
this.load();
},
methods: {
load() {
if (this.scriptDom) {
this.$el.removeChild(this.scriptDom);
}
this.$refs.ins.innerHTML = '';
const e = document.createElement('script');
e.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
e.async = true;
this.$el.appendChild(e);
this.scriptDom = e;
(window.adsbygoogle = window.adsbygoogle || []).push({});
},
},
render() {
return (
<div class="google-ads">
<ins
ref="ins"
style="display:block"
class="adsbygoogle"
data-ad-client="ca-pub-4801326429087140"
data-ad-slot="2425414214"
data-ad-format="auto"
></ins>
</div>
);
},
};
</script>

View File

@ -0,0 +1,28 @@
<template>
<div class="markdown api-container">
<google-ads v-if="showAd" />
<slot v-if="isZhCN" name="cn" />
<slot v-else />
</div>
</template>
<script>
import { isZhCN } from '../utils/util';
import GoogleAds from './GoogleAds';
const showAd = location.host.indexOf('antdv.com') > -1;
export default {
name: 'Api',
components: {
GoogleAds,
},
inject: {
demoContext: { default: {} },
},
data() {
return {
showAd,
isZhCN: isZhCN(this.demoContext.name),
};
},
};
</script>

View File

@ -0,0 +1,230 @@
<template>
<section :id="id" :class="['code-box', codeExpand ? 'expand' : '']">
<section class="code-box-demo">
<template v-if="iframeDemo[iframeDemoKey]">
<div class="browser-mockup with-url">
<iframe :src="iframeDemo[iframeDemoKey]" height="360" />
</div>
</template>
<template v-else>
<slot name="component" />
</template>
</section>
<section class="code-box-meta markdown">
<slot v-if="isZhCN" name="description" />
<slot v-else name="us-description" />
<div class="code-box-actions">
<a-tooltip
:title="copied ? 'Copied!' : 'Copy code'"
:visible="copyTooltipVisible"
@visibleChange="onCopyTooltipVisibleChange"
>
<a-icon
v-clipboard:copy="sourceCode"
v-clipboard:success="handleCodeCopied"
:type="copied && copyTooltipVisible ? 'check' : 'copy'"
class="code-box-code-copy"
/>
</a-tooltip>
<a-tooltip :title="codeExpand ? 'Hide Code' : 'Show Code'">
<span class="code-expand-icon">
<img
width="16"
alt="expand code"
src="https://gw.alipayobjects.com/zos/rmsportal/wSAkBuJFbdxsosKKpqyq.svg"
:class="codeExpand ? 'code-expand-icon-hide' : 'code-expand-icon-show'"
@click="handleCodeExpand"
/>
<img
width="16"
alt="expand code"
src="https://gw.alipayobjects.com/zos/rmsportal/OpROPHYqWmrMDBFMZtKF.svg"
:class="codeExpand ? 'code-expand-icon-show' : 'code-expand-icon-hide'"
@click="handleCodeExpand"
/>
</span>
</a-tooltip>
</div>
</section>
<transition appear :css="false" @enter="enter" @leave="leave">
<section
v-show="codeExpand"
class="highlight-wrapper"
style="position: relative;"
v-html="getCode()"
/>
</transition>
</section>
</template>
<script>
import animate from 'ant-design-vue/es/_util/openAnimation';
import BaseMixin from 'ant-design-vue/es/_util/BaseMixin';
import { isZhCN } from '../utils/util';
import { dev } from '../build/config';
export default {
name: 'DemoBox',
mixins: [BaseMixin],
inject: {
iframeDemo: { default: {} },
demoContext: { default: {} },
},
props: {
jsfiddle: Object,
isIframe: Boolean,
},
data() {
window.test = this;
const { name = '' } = this.demoContext;
const { us, cn, sourceCode } = this.jsfiddle;
const usTitle = (us.split('#### ')[1] || '').split('\n')[0] || '';
const cnTitle = (cn.split('#### ')[1] || '').split('\n')[0] || '';
if (process.env.NODE_ENV !== 'production' && usTitle === '') {
throw new Error(`not have usTitle`);
}
const iframeDemoKey = usTitle
.split(' ')
.join('-')
.toLowerCase();
const id = [
'components',
name.replace(/-cn\/?$/, '') || dev.componentName,
'demo',
...usTitle.split(' '),
]
.join('-')
.toLowerCase();
if (this.demoContext.store) {
const { currentSubMenu } = this.demoContext.store.getState();
this.demoContext.store.setState({
currentSubMenu: [...currentSubMenu, { cnTitle, usTitle, id }],
});
}
return {
codeExpand: false,
isZhCN: isZhCN(name),
copied: false,
copyTooltipVisible: false,
sourceCode: decodeURIComponent(escape(window.atob(sourceCode))),
id,
iframeDemoKey,
isDemo: true,
};
},
methods: {
getCode() {
const { $slots } = this;
return decodeURIComponent(
escape(window.atob(($slots.code && $slots.code[0] && $slots.code[0].text) || '')),
);
},
handleCodeExpand() {
this.codeExpand = !this.codeExpand;
},
enter: animate.enter,
leave: animate.leave,
handleCodeCopied() {
this.setState({ copied: true });
},
onCopyTooltipVisibleChange(visible) {
if (visible) {
this.setState({
copyTooltipVisible: visible,
copied: false,
});
return;
}
this.setState({
copyTooltipVisible: visible,
});
},
},
};
</script>
<style scoped lang="less">
.box-demo {
padding: 0;
border: 1px solid #e9e9e9;
border-radius: 4px;
box-shadow: none;
margin-top: 20px;
margin-bottom: 20px;
}
.box-demo-show {
padding: 20px 25px 30px;
border-bottom: 1px solid #e9e9e9;
}
.box-demo-description {
position: relative;
padding: 17px 16px 15px 20px;
border-radius: 0 0 6px 6px;
-webkit-transition: background-color 0.4s ease;
transition: background-color 0.4s ease;
width: 100%;
font-size: 12px;
&.bordered {
border-bottom: 1px dashed #e9e9e9;
}
h3,
h4 {
position: absolute;
top: -14px;
padding: 1px 8px;
margin-left: -8px;
margin-top: 0;
margin-bottom: 0;
color: #777;
border-radius: 4px;
border-top-left-radius: 0;
background: #fff;
-webkit-transition: background-color 0.4s ease;
transition: background-color 0.4s ease;
.header-anchor {
display: none;
}
}
li {
line-height: 21px;
}
}
.box-demo-code {
-webkit-transition: height 0.2s ease-in-out;
transition: height 0.2s ease-in-out;
overflow: auto;
border-top: 1px dashed #e9e9e9;
pre {
margin: 0;
}
code {
margin: 0;
background: #f7f7f7;
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 0.9em;
border: 1px solid #eee;
}
}
.btn-toggle {
position: absolute;
right: 16px;
bottom: 17px;
cursor: pointer;
width: 18px;
height: 18px;
font-size: 18px;
line-height: 18px;
color: #999;
i {
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
&.open {
i {
-webkit-transform: rotate(-180deg);
-ms-transform: rotate(-180deg);
transform: rotate(-180deg);
}
}
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<div>
<demo-box :jsfiddle="jsfiddle">
<template slot="component">
<slot />
</template>
<template slot="description">
<div class="demo-description" v-html="cnHtml" />
</template>
<template slot="us-description">
<div class="demo-description" v-html="usHtml" />
</template>
<template slot="code">
{{ codeStr }}
</template>
</demo-box>
</div>
</template>
<script>
import marked from 'marked';
import Prism from 'prismjs';
import 'prismjs/components/prism-jsx.min.js';
import 'prismjs/components/prism-bash.min.js';
const replaceDelimiters = function(str) {
return str.replace(/({{|}})/g, '<span>$1</span>');
};
const renderHighlight = function(str, lang) {
if (!(lang && Prism.languages[lang])) {
return '';
}
try {
return replaceDelimiters(Prism.highlight(str, Prism.languages[lang], lang));
} catch (err) {}
};
const renderer = new marked.Renderer();
renderer.heading = function(text, level) {
return (
'<h' + level + ' id="' + text.replace(/[^\w]+/g, '-') + '">' + text + '</h' + level + '>\n'
);
};
marked.setOptions({
renderer,
gfm: true,
tables: true,
breaks: true,
pedantic: true,
sanitize: true,
smartLists: true,
smartypants: true,
html: true,
highlight: renderHighlight,
});
const cnReg = /<cn>([\S\s\t]*?)<\/cn>/;
const usReg = /<us>([\S\s\t]*?)<\/us>/;
export default {
name: 'DemoContainer',
props: ['code'],
data() {
const cn = this.code.match(cnReg) || [];
const us = this.code.match(usReg) || [];
const cnHtml = marked(cn[1].trim());
const usHtml = marked(us[1].trim());
const sourceCode = this.code
.replace(cn[0], '')
.replace(us[0], '')
.trim();
const codeHtml = marked('```html\n' + sourceCode + '```');
return {
codeStr: window.btoa(unescape(encodeURIComponent(codeHtml))),
cnHtml,
usHtml,
jsfiddle: {
sourceCode: window.btoa(unescape(encodeURIComponent(sourceCode))),
cn: cn[1].trim(),
us: us[1].trim(),
},
};
},
};
</script>

View File

@ -0,0 +1,49 @@
import { Col, Row } from '../../components/grid';
import '../../components/grid/style';
function isEmptyElement(c) {
return !(c.tag || (c.text && c.text.trim() !== ''));
}
function filterEmpty(children = []) {
return children.filter(c => !isEmptyElement(c));
}
export default {
props: {
cols: {
type: [Number, String],
default: 2,
},
},
inject: {
demoContext: { default: {} },
},
render() {
const { cols, $slots } = this;
const isSingleCol = cols === 1;
const leftChildren = [];
const rightChildren = [];
const children = filterEmpty($slots.default);
children.forEach((demo, index) => {
if (index % 2 === 0 || isSingleCol) {
leftChildren.push(demo);
} else {
rightChildren.push(demo);
}
});
return (
<Row gutter={16}>
<Col
span={isSingleCol ? 24 : 12}
class={isSingleCol ? 'code-boxes-col-1-1' : 'code-boxes-col-2-1'}
>
{leftChildren}
</Col>
{isSingleCol ? null : (
<Col class="code-boxes-col-2-1" span={12}>
{rightChildren}
</Col>
)}
</Row>
);
},
};

View File

@ -0,0 +1,136 @@
<script>
export default {
props: {
isCN: Boolean,
},
render() {
const isCN = this.isCN;
return (
<footer id="footer">
<div class="footer-wrap">
<a-row>
<a-col md={6} sm={24} xs={24}>
<div class="footer-center">
<h2>Ant Design</h2>
<div>
<a href="https://github.com/vueComponent/ant-design-vue" target="_blank ">
<span>GitHub</span>
</a>
<span></span>
<span>
<i class="anticon anticon-github"></i>
</span>
</div>
<div>
<a href="https://ant.design/docs/react/introduce-cn" target="_blank">
Ant Design
</a>
<span> - </span>
<span>React</span>
</div>
<div>
<a href="https://github.com/NG-ZORRO/ng-zorro-antd" target="_blank">
Ant Design
</a>
<span> - </span>
<span>Angular</span>
</div>
<div>
<a href="https://github.com/websemantics/awesome-ant-design" target="_blank ">
<span>Awesome Ant Design</span>
</a>
</div>
<div>
<a href="http://library.ant.design/" rel="noopener noreferrer" target="_blank">
AntD Library
</a>
</div>
</div>
</a-col>
<a-col md={6} sm={24} xs={24}>
<div class="footer-center">
<h2>{isCN ? '社区' : 'Community'}</h2>
{isCN ? (
<div>
<a href="https://zhuanlan.zhihu.com/ant-design-vue" target="_blank">
<span>知乎专栏</span>
</a>
</div>
) : (
''
)}
<div>
<a href="https://github.com/vueComponent/ant-design-vue/releases" target="_blank">
<span>{isCN ? '更新记录' : 'Change Log'}</span>
</a>
</div>
<div>
<a
rel="noopener noreferrer"
target="_blank"
href={`https://vuecomponent.github.io/issue-helper/${isCN ? '?lang=zh' : ''}`}
>
<span>{isCN ? '报告 Bug' : 'Bug Report'}</span>
</a>
</div>
</div>
</a-col>
<a-col md={6} sm={24} xs={24}>
<div class="footer-center">
<h2>{isCN ? '友情链接' : 'Links'}</h2>
<div>
<a href="https://cn.vuejs.org/" target="_blank">
Vue
</a>
</div>
<div>
<a href="https://cli.vuejs.org/" target="_blank">
Vue CLI
</a>
</div>
<div>
<a href="http://www.jeecg.com/" rel="noopener noreferrer" target="_blank">
Jeecg Boot
</a>
</div>
</div>
</a-col>
<a-col md={6} sm={24} xs={24}>
<div class="footer-center">
<h2>
<img
alt=""
class="title-icon"
src="https://gw.alipayobjects.com/zos/rmsportal/nBVXkrFdWHxbZlmMbsaH.svg"
/>
<span>{isCN ? '更多产品' : 'More Products'}</span>
</h2>
<div>
<a href="https://antv.alipay.com/" rel="noopener noreferrer" target="_blank">
AntV
</a>
<span> - </span>
<span>{isCN ? '数据可视化' : 'Data Visualization'}</span>
</div>
<div>
<a href="https://eggjs.org/" rel="noopener noreferrer" target="_blank">
Egg
</a>
<span> - </span>
<span>{isCN ? '企业级 Node 开发框架' : 'Enterprise Node Framework'}</span>
</div>
</div>
</a-col>
</a-row>
</div>
<div style="padding: 10px 144px;">
备案号
<a href="http://www.beian.miit.gov.cn/" target="_blank">
浙ICP备19034671号
</a>
</div>
</footer>
);
},
};
</script>

View File

@ -0,0 +1,41 @@
<template>
<div v-show="visible" id="geektime">
<a
href="https://time.geekbang.org/course/intro/100024601?code=KHKYcoBU6vZa8nMglg7AWfDxxi3BWrz9INAzAY3umPk%3D"
target="_blank"
>
<img width="150" alt="Vue 实战教程" src="https://qn.antdv.com/geektime-vue.jpeg" />
</a>
<div class="close" @click="visible = false">
<a-icon type="close" />
</div>
</div>
</template>
<script>
export default {
props: ['isMobile'],
data() {
return {
visible: true,
};
},
};
</script>
<style lang="less" scoped>
#geektime {
position: fixed;
bottom: 10px;
right: 10px;
.close {
position: absolute;
text-align: center;
top: -8px;
right: -8px;
font-size: 16px;
padding: 15px;
color: #6e3041;
}
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<div
v-if="isEffective(effectiveTime)"
id="geektime-ads"
:class="isMobile ? 'geektime-ads-mobile' : ''"
>
<a
href="https://time.geekbang.org/column/intro/154?utm_term=zeusGZFFE&utm_source=app&utm_medium=tangjinzhou"
target="_blank"
>
<img height="100" alt="重学前端" src="https://qn.antdv.com/chongxueqianduan.jpg" />
</a>
</div>
</template>
<script>
import moment from 'moment';
export default {
props: ['isMobile'],
data() {
return {
visible: true,
effectiveTime: {
start: '2019-08-05 17:00:00',
end: '2019-09-05 17:00:00',
},
};
},
methods: {
isEffective({ start, end }) {
return moment().isBetween(start, end);
},
},
};
</script>
<style lang="less" scoped>
#geektime-ads {
width: 266px;
position: fixed;
left: 0;
bottom: 0px;
padding: 0;
overflow: hidden;
z-index: 9;
background-color: #fff;
border-radius: 3px;
font-size: 13px;
background: #f5f5f5;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
}
#geektime-ads.geektime-ads-mobile {
width: 100%;
position: relative;
right: 0;
bottom: 0;
padding: 0;
margin-bottom: 15px;
}
</style>

View File

@ -0,0 +1,322 @@
<script>
import { isZhCN } from '../utils/util';
import docsearch from 'docsearch.js';
import packageInfo from '../../package.json';
import logo from '../public/logo.svg';
import antDesignVue from '../public/ant-design-vue.svg';
export default {
inject: {
demoContext: { default: {} },
},
props: {
name: String,
searchData: Array,
},
data() {
return {
visibleAdblockBanner: !!this.demoContext.blocked,
value: null,
showTopBanner: !localStorage.getItem('notification-key-2.0'),
};
},
watch: {
'demoContex.blocked': function blocked(val) {
this.visibleAdblockBanner = !!val;
},
},
mounted() {
this.initDocSearch(this.$i18n.locale);
},
methods: {
handleClose(key) {
localStorage.removeItem(`notification-key-${key}`);
localStorage.setItem(`notification-key-${key}`, true);
this.showTopBanner = false;
},
initDocSearch(locale) {
docsearch({
apiKey: '92003c1d1d07beef165b08446f4224a3',
indexName: 'antdv',
inputSelector: '#search-box input',
algoliaOptions: { facetFilters: [isZhCN(locale) ? 'cn' : 'en'] },
transformData(hits) {
hits.forEach(hit => {
hit.url = hit.url.replace('www.antdv.com', window.location.host);
hit.url = hit.url.replace('https:', window.location.protocol);
});
return hits;
},
debug: false, // Set debug to true if you want to inspect the dropdown
});
},
handleClick() {
const name = this.name;
const path = this.$route.path;
const newName = isZhCN(name) ? name.replace(/-cn\/?$/, '') : `${name}-cn`;
this.$router.push({
path: path.replace(name, newName),
});
this.$i18n.locale = isZhCN(name) ? 'en-US' : 'zh-CN';
},
onSelect(val) {
this.$router.push(val);
this.value = val;
},
closeTopBanner() {},
},
render() {
const name = this.name;
const visibleAdblockBanner = false; // this.visibleAdblockBanner;
const isCN = isZhCN(name);
const path = this.$route.path;
const selectedKeys = path === '/jobs/list-cn' ? ['jobs'] : ['components'];
return (
<header id="header">
{visibleAdblockBanner && (
<div class="adblock-banner">
{isZhCN
? '我们检测到你可能使用了 AdBlock 或 Adblock Plus它会影响到正常功能的使用如复制、展开代码等。'
: 'We have detected that you may use AdBlock or Adblock Plus, which will affect the use of normal functions (such as copying, expanding code, etc.)'}
<br />
{isZhCN
? '你可以将 Ant Design Vue 加入白名单,以便我们更好地提供服务。'
: 'You can add Ant Design Vue to the whitelist so that we can provide better services.'}
<CloseOutlined class="close-icon" onClick={() => (this.visibleAdblockBanner = false)} />
</div>
)}
{isCN && this.showTopBanner && (
<div class="global-notification">
<span>
<a href="https://2x.antdv.com/" target="_blank">
2.0 正式版
</a>
&nbsp;已发布更快更小更易用&nbsp;&nbsp;
</span>
<br />
<span style="padding: 5px 0; display: inline-block;">
支持 Vue 3.0全新 Composition API 文档TSJS 双示例
</span>
<br />
<span>
<a href="https://store.antdv.com/pro/" target="_blank">
Vue3 Admin Pro
</a>
&nbsp; 同步更新支持多种布局多标签页暗黑主题等
</span>
<a-icon
type="close"
style="position: absolute;top: 13px;right: 15px;"
onClick={() => this.handleClose('2.0')}
/>
</div>
)}
{!isCN && this.showTopBanner && (
<div class="global-notification">
<span>
<a href="https://2x.antdv.com/" target="_blank">
2.0 release
</a>
&nbsp; Faster, Smaller, Easier&nbsp;&nbsp;
</span>
<br />
<span style="padding: 5px 0; display: inline-block;">
Support Vue 3New Composition API document TS, JS dual examples
</span>
<br />
<span>
<a href="https://store.antdv.com/pro/?lang=en" target="_blank">
Vue3 Admin Pro
</a>
&nbsp; is updated synchronously, supports multiple layouts, dark themes, etc.
</span>
<a-icon
type="close"
style="position: absolute;top: 8px;right: 15px;"
onClick={() => this.handleClose('2.0')}
/>
</div>
)}
<a-row>
<a-col class="header-left" xxl={4} xl={5} lg={5} md={6} sm={24} xs={24}>
<router-link to={{ path: '/' }} id="logo">
<img alt="logo" height="32" src={logo} />
<img alt="logo" height="16" src={antDesignVue} />
</router-link>
<a-button
ghost
size="small"
onClick={this.handleClick}
class="header-lang-button"
key="lang-button"
>
{isCN ? 'English' : '中文'}
</a-button>
</a-col>
<a-col xxl={20} xl={19} lg={19} md={18} sm={0} xs={0}>
<div id="search-box">
<a-icon type="search" />
<a-input
placeholder={isCN ? '搜索组件...' : 'input search text'}
style="width: 200px"
/>
</div>
<span id="github-btn" class="github-btn">
<a class="gh-btn" href="//github.com/vueComponent/ant-design-vue/" target="_blank">
<span class="gh-ico" aria-hidden="true"></span>
<span class="gh-text">Star</span>
</a>
</span>
<a-button
ghost
size="small"
onClick={this.handleClick}
class="header-lang-button"
key="lang-button"
>
{isCN ? 'English' : '中文'}
</a-button>
<a-select size="small" defaultValue={packageInfo.version} class="version">
<a-select-option value={packageInfo.version}>{packageInfo.version}</a-select-option>
<a-select-option value="2.x" onClick={() => (location.href = 'https://2x.antdv.com')}>
2.x
</a-select-option>
</a-select>
<a-menu selectedKeys={selectedKeys} mode="horizontal" class="menu-site" id="nav">
<a-menu-item key="components">
<router-link to="/docs/vue/introduce">{isCN ? '组件' : 'Components'}</router-link>
</a-menu-item>
{isCN ? (
<a-menu-item key="store">
<a
href="https://store.antdv.com/pro/"
target="_blank"
style="position: relative;"
>
商店 <a-badge color="red" style="position: absolute;top: -10px;right: -10px;" />
</a>
</a-menu-item>
) : (
<a-menu-item key="store">
<a
href="https://store.antdv.com/pro/?lang=en"
target="_blank"
style="position: relative;"
>
Store{' '}
<a-badge color="red" style="position: absolute;top: -10px;right: -10px;" />
</a>
</a-menu-item>
)}
{isCN ? (
<a-menu-item key="geektime">
<a
href="https://time.geekbang.org/course/intro/100024601?code=KHKYcoBU6vZa8nMglg7AWfDxxi3BWrz9INAzAY3umPk%3D"
target="_blank"
style="position: relative;"
>
Vue 实战教程
<a-badge color="red" style="position: absolute;top: -10px;right: -10px;" />
</a>
</a-menu-item>
) : null}
<a-menu-item key="sponsor">
<router-link to={{ path: isCN ? '/docs/vue/sponsor-cn/' : '/docs/vue/sponsor/' }}>
{isCN ? '支持我们' : 'Support us'}
</router-link>
</a-menu-item>
<a-sub-menu key="Ecosystem" title={isCN ? '更多' : 'More'}>
<a-menu-item key="pro">
<a target="_blank" href="https://pro.antdv.com">
Pro (Admin)
</a>
</a-menu-item>
<a-menu-item key="vip">
<a target="_blank" href="https://store.antdv.com/pro/">
Pro For VIP
</a>
</a-menu-item>
<a-menu-item key="design">
<router-link
to={{ path: isCN ? '/docs/vue/download-cn/' : '/docs/vue/download/' }}
>
{isCN ? '设计资源' : 'Design Resources'}
</router-link>
</a-menu-item>
<a-menu-item key="vscode">
<a
target="_blank"
href="https://marketplace.visualstudio.com/items?itemName=ant-design-vue.vscode-ant-design-vue-helper"
>
VS Code Extension
</a>
</a-menu-item>
<a-menu-item key="awesome">
<a target="_blank" href="https://github.com/vueComponent/ant-design-vue-awesome">
Awesome
</a>
</a-menu-item>
<a-menu-item key="wechat">
<a-popover placement="right">
<template slot="content">
<img
width="160"
height="160"
alt="wechat"
src="https://qn.antdv.com/wechat.jpeg"
/>
</template>
<a>{isCN ? '微信' : 'WeChat'}</a>
</a-popover>
</a-menu-item>
<a-menu-item key="qq">
<a-popover placement="right">
<template slot="content">
<img width="160" height="160" alt="qq" src="https://qn.antdv.com/qq.png" />
</template>
<a>{isCN ? 'QQ(217490093)' : 'QQ(217490093)'}</a>
</a-popover>
</a-menu-item>
</a-sub-menu>
</a-menu>
</a-col>
</a-row>
</header>
);
},
};
</script>
<style scope>
.adblock-banner {
position: relative;
z-index: 100;
min-width: 1000px;
padding: 16px;
line-height: 28px;
color: #8590a6;
text-align: center;
background-color: #ebebeb;
}
.close-icon {
position: absolute;
top: 15px;
right: 15px;
}
.global-notification {
text-align: center;
background: #001529;
padding: 20px 0;
font-size: 16px;
position: fixed;
bottom: 0;
width: 100%;
color: #fff;
z-index: 99;
}
.global-notification a {
color: #177ddc;
}
</style>

View File

@ -0,0 +1,30 @@
<script>
// import * as AllDemo from '../demo'
export default {
props: {
name: String,
hash: String,
},
provide() {
return {
demoContext: this,
};
},
render() {
// const name = this.name
// const titleMap = {}
// for (const [title] of Object.entries(AllDemo)) {
// const key = `${title.replace(/(\B[A-Z])/g, '-$1').toLowerCase()}`
// titleMap[key] = title
// }
// const Demo = AllDemo[titleMap[name.replace(/-cn\/?$/, '')]]
// const hash = this.$route.hash.replace('#', '')
return (
<div id="iframe-page">
<router-view></router-view>
</div>
);
},
};
</script>

View File

@ -0,0 +1,374 @@
<script>
import { enquireScreen } from 'enquire-js';
import AllDemo from '../site/demo';
import Header from './header';
import Footer from './footer';
// import Geektime from './geektime';
import GeektimeAds from './geektime_ads';
import RightBottomAd from './right_bottom_ad';
import Sponsors from './sponsors';
import zhCN from 'ant-design-vue/es/locale-provider/zh_CN';
import enUS from 'ant-design-vue/es/locale-provider/default';
import sortBy from 'lodash/sortBy';
import { isZhCN } from '../utils/util';
import { Provider, create } from '../../components/_util/store';
import NProgress from 'nprogress';
import MobileMenu from '../../components/vc-drawer/src';
import TopAd from './top_ad';
import GoogleAds from './GoogleAds';
const docsList = [
{ key: 'introduce', enTitle: 'Ant Design of Vue', title: 'Ant Design of Vue' },
{ key: 'getting-started', enTitle: 'Getting Started', title: '快速上手' },
{ key: 'use-with-vue-cli', enTitle: 'Use in vue-cli', title: '在 vue-cli 中使用' },
{ key: 'customize-theme', enTitle: 'Customize Theme', title: '定制主题' },
{ key: 'changelog', enTitle: 'Change Log', title: '更新日志' },
{ key: 'i18n', enTitle: 'Internationalization', title: '国际化' },
{ key: 'faq', enTitle: 'FAQ', title: '常见问题' },
{ key: 'sponsor', enTitle: 'Sponsor', title: '支持我们' },
{ key: 'download', enTitle: 'Download Design Resources', title: '下载设计资源' },
];
const isGitee = window.location.host.indexOf('gitee.io') > -1;
const showAd = false; // location.host.indexOf('antdv.com') > -1;
export default {
provide() {
return {
demoContext: this,
};
},
props: {
name: String,
showDemo: Boolean,
showApi: Boolean,
},
data() {
this.store = create({
currentSubMenu: [],
});
this.subscribe();
let blocked = false;
setTimeout(() => {
const div = document.createElement('div');
div.className = 'adsbox';
document.body.appendChild(div);
blocked = 'none' === getComputedStyle(div).display;
}, 300);
return {
showSideBars: true,
currentSubMenu: [],
sidebarHeight: document.documentElement.offsetHeight,
isMobile: false,
blocked,
};
},
watch: {
'$route.path'() {
this.store.setState({ currentSubMenu: [] });
this.addSubMenu();
},
},
beforeDestroy() {
if (this.unsubscribe) {
this.unsubscribe();
}
clearTimeout(this.timer);
if (this.resizeEvent) {
this.resizeEvent.remove();
}
if (this.debouncedResize && this.debouncedResize.cancel) {
this.debouncedResize.cancel();
}
},
mounted() {
if (isGitee) {
this.$info({
title: '提示',
content: '访问国内镜像站点的用户请访问 antdv.com 站点',
okText: '立即跳转',
onOk() {
location.href = 'https://www.antdv.com';
},
});
}
this.$nextTick(() => {
this.addSubMenu();
const nprogressHiddenStyle = document.getElementById('nprogress-style');
if (nprogressHiddenStyle) {
this.timer = setTimeout(() => {
nprogressHiddenStyle.parentNode.removeChild(nprogressHiddenStyle);
}, 0);
}
enquireScreen(b => {
this.isMobile = !!b;
});
});
},
methods: {
addSubMenu() {
if (this.$route.path.indexOf('/docs/vue/') !== -1) {
this.$nextTick(() => {
const menus = [];
const doms = [...this.$refs.doc.querySelectorAll(['h2', 'h3'])];
doms.forEach(dom => {
const id = dom.id;
if (id) {
const title = dom.textContent.split('#')[0].trim();
menus.push({ cnTitle: title, usTitle: title, id });
}
});
this.currentSubMenu = menus;
});
}
},
subscribe() {
const { store } = this;
this.unsubscribe = store.subscribe(() => {
this.currentSubMenu = this.store.getState().currentSubMenu;
});
},
getSubMenu(isCN) {
const currentSubMenu = this.currentSubMenu;
const lis = [];
currentSubMenu.forEach(({ cnTitle, usTitle, id }, index) => {
const title = isCN ? cnTitle : usTitle;
lis.push(<a-anchor-link key={id + index} href={`#${id}`} title={title} />);
});
const showApi = this.$route.path.indexOf('/components/') !== -1;
return (
<a-anchor offsetTop={100} class="demo-anchor">
{lis}
{showApi ? <a-anchor-link key="API" title="API" href="#API" /> : ''}
</a-anchor>
);
},
getDocsMenu(isCN, pagesKey) {
const docsMenu = [];
docsList.forEach(({ key, enTitle, title }) => {
const k = isCN ? `${key}-cn` : key;
pagesKey.push({ name: k, url: `/docs/vue/${k}/`, title: isCN ? title : enTitle });
docsMenu.push(
<a-menu-item key={k}>
<router-link to={`/docs/vue/${k}/`}>{isCN ? title : enTitle}</router-link>
</a-menu-item>,
);
});
return docsMenu;
},
resetDocumentTitle(component, name, isCN) {
let titleStr = 'Ant Design Vue';
if (component) {
const { subtitle, title } = component;
const componentName = isCN ? subtitle + ' ' + title : title;
titleStr = componentName + ' - ' + titleStr;
} else {
const currentKey = docsList.filter(item => {
return item.key === name;
});
if (currentKey.length) {
titleStr = (isCN ? currentKey[0]['title'] : currentKey[0]['enTitle']) + ' - ' + titleStr;
}
}
document.title = titleStr;
},
mountedCallback() {
NProgress.done();
document.documentElement.scrollTop = 0;
},
},
render() {
const name = this.name;
const isCN = isZhCN(name);
const titleMap = {};
const menuConfig = {
General: [],
Layout: [],
Navigation: [],
'Data Entry': [],
'Data Display': [],
Feedback: [],
Other: [],
};
const pagesKey = [];
let prevPage = null;
let nextPage = null;
const searchData = [];
for (const [title, d] of Object.entries(AllDemo)) {
const type = d.type || 'Other';
const key = `${title.replace(/(\B[A-Z])/g, '-$1').toLowerCase()}`;
titleMap[key] = title;
AllDemo[title].key = key;
menuConfig[type] = menuConfig[type] || [];
menuConfig[type].push(d);
}
const docsMenu = this.getDocsMenu(isCN, pagesKey);
const reName = name.replace(/-cn\/?$/, '');
const MenuGroup = [];
for (const [type, menus] of Object.entries(menuConfig)) {
const MenuItems = [];
sortBy(menus, ['title']).forEach(({ title, subtitle, key }) => {
const linkValue = isCN
? [<span>{title}</span>, <span class="chinese">{subtitle}</span>]
: [<span>{title}</span>];
if (isCN) {
key = `${key}-cn`;
}
pagesKey.push({
name: key,
url: `/components/${key}/`,
title: isCN ? `${title} ${subtitle}` : title,
});
searchData.push({
title,
subtitle,
url: `/components/${key}/`,
});
MenuItems.push(
<a-menu-item key={key}>
<router-link to={`/components/${key}/`}>{linkValue}</router-link>
</a-menu-item>,
);
});
MenuGroup.push(<a-menu-item-group title={type}>{MenuItems}</a-menu-item-group>);
}
pagesKey.forEach((item, index) => {
if (item.name === name) {
prevPage = pagesKey[index - 1];
nextPage = pagesKey[index + 1];
}
});
let locale = zhCN;
if (!isCN) {
locale = enUS;
}
const config = AllDemo[titleMap[reName]];
this.resetDocumentTitle(config, reName, isCN);
const { isMobile, $route } = this;
return (
<div class="page-wrapper">
<Header searchData={searchData} name={name} />
<a-config-provider locale={locale}>
<div class="main-wrapper">
<a-row>
{isMobile ? (
<MobileMenu ref="sidebar" wrapperClassName="drawer-wrapper">
<a-menu
class="aside-container menu-site"
selectedKeys={[name]}
defaultOpenKeys={['Components']}
inlineIndent={40}
mode="inline"
>
{docsMenu}
<a-sub-menu title={`Components(${searchData.length})`} key="Components">
{MenuGroup}
</a-sub-menu>
</a-menu>
</MobileMenu>
) : (
<a-col
ref="sidebar"
class="site-sidebar main-menu"
xxl={4}
xl={5}
lg={5}
md={6}
sm={8}
xs={12}
>
<a-affix>
<section class="main-menu-inner">
<Sponsors isCN={isCN} />
<a-menu
class="aside-container menu-site"
selectedKeys={[name]}
defaultOpenKeys={['Components']}
inlineIndent={40}
mode="inline"
>
{docsMenu}
<a-sub-menu title={`Components(${searchData.length})`} key="Components">
{MenuGroup}
</a-sub-menu>
</a-menu>
</section>
</a-affix>
</a-col>
)}
<a-col xxl={20} xl={19} lg={19} md={18} sm={24} xs={24}>
<section class="main-container main-container-component">
<TopAd isCN={isCN} />
{showAd ? <GeektimeAds isMobile={isMobile} /> : null}
{!isMobile ? (
<div class={['toc-affix', isCN ? 'toc-affix-cn' : '']} style="width: 150px;">
{this.getSubMenu(isCN)}
</div>
) : null}
{this.showDemo ? (
<Provider store={this.store} key={isCN ? 'cn' : 'en'}>
<router-view
class={`demo-cols-${config.cols || 2}`}
{...{
directives: [
{
name: 'mountedCallback',
value: this.mountedCallback,
},
],
}}
></router-view>
</Provider>
) : (
''
)}
{this.showApi ? (
<div class="markdown api-container" ref="doc">
<router-view
{...{
directives: [
{
name: 'mountedCallback',
value: this.mountedCallback,
},
],
}}
></router-view>
{showAd ? <GoogleAds key={`GoogleAds_${$route.path}`} /> : null}
</div>
) : (
''
)}
</section>
<section class="prev-next-nav">
{prevPage ? (
<router-link class="prev-page" to={`${prevPage.url}`}>
<a-icon type="left" />
&nbsp;&nbsp;{prevPage.title}
</router-link>
) : (
''
)}
{nextPage ? (
<router-link class="next-page" to={`${nextPage.url}`}>
{nextPage.title}&nbsp;&nbsp;
<a-icon type="right" />
</router-link>
) : (
''
)}
</section>
<Footer ref="footer" isCN={isCN} />
</a-col>
</a-row>
</div>
</a-config-provider>
{name.indexOf('back-top') === -1 ? <a-back-top /> : null}
<RightBottomAd isCN={isCN} isMobile={isMobile} />
</div>
);
},
};
</script>

View File

@ -0,0 +1,51 @@
<template>
<div class="markdown" v-html="marked(text)" />
</template>
<script>
import marked from 'marked';
import { isZhCN } from '../utils/util';
const renderer = new marked.Renderer();
renderer.heading = function(text, level) {
return (
'<h' + level + ' id="' + text.replace(/[^\w]+/g, '-') + '">' + text + '</h' + level + '>\n'
);
};
marked.setOptions({
renderer,
gfm: true,
tables: true,
breaks: true,
pedantic: true,
sanitize: true,
smartLists: true,
smartypants: true,
});
export default {
name: 'Md',
props: {
cn: String,
us: String,
},
inject: {
demoContext: { default: {} },
},
data() {
let text = '';
const { cn, us } = this;
if (this.$slots.default && this.$slots.default[0] && this.$slots.default[0].text) {
text = this.$slots.default[0].text;
} else {
text = isZhCN(this.demoContext.name) ? cn : us;
}
text = text || '';
text = text
.split('\n')
.map(t => t.trim())
.join('\n');
return {
marked,
text,
};
},
};
</script>

View File

@ -0,0 +1,57 @@
<template>
<div id="right-bottom">
<img v-if="isCN" width="150" alt="官方公众号" src="https://qn.antdv.com/wechat.jpeg">
<div v-if="isMobile" class="close" @click="visible = false">
<a-icon type="close" />
</div>
<!-- <span v-if="isCN">广</span> -->
</div>
</template>
<script>
import moment from 'moment';
const isEffective = (start, end) => {
return moment().isBetween(start, end);
};
export default {
components: {},
props: ['isCN', 'isMobile'],
data() {
return {
visible: true,
ads: [
{
alt: 'geektime',
img: 'https://qn.antdv.com/geektime-web-small.jpg',
href: 'http://gk.link/a/10l8O',
visible: isEffective('2020-09-03 10:00:00', '2020-10-04 10:00:00'),
},
{
alt: 'powerproject',
img: 'https://qn.antdv.com/powerproject.jpeg?v=20200327',
href: 'http://www.powerproject.com.cn',
visible: isEffective('2020-03-27 17:00:00', '2020-09-28 17:00:00'),
},
],
};
},
};
</script>
<style lang="less" scoped>
#right-bottom {
position: fixed;
bottom: 10px;
right: 10px;
width: 150px;
.close {
position: absolute;
text-align: center;
top: -8px;
right: -8px;
font-size: 16px;
padding: 15px;
color: #6e3041;
}
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<div class="snd-ad">
<div class="sponsorsWrap">
<span v-if="!isCN" class="sponsorsTitle">
{{ isCN ? '赞助商' : 'Sponsors' }}
</span>
<ul>
<!-- <li class="sponsorsItem">
<a href="https://tipe.io/?ref=ant-design-vue" target="_blank">
<img height="51" src="https://cdn.tipe.io/tipe/tipe-cat-no-text.svg" alt="tipe" />
</a>
</li> -->
<li v-if="isCN && isEffective(effectiveTime.kkb)" class="sponsorsItem">
<a href="https://datayi.cn/w/Y9J3M2vR" target="_blank">
<img height="66" src="https://qn.antdv.com/kaikeba_ssr.jpeg" alt="kaikeba">
</a>
<span style="position: absolute; top: 0px;right: 10px">广告</span>
</li>
<!-- <li class="sponsorsItem">
<a-button type="primary" ghost style="font-size: 12px" @click="handleClick">
{{ isCN ? '成为赞助商' : 'Become a Sponsor' }}
</a-button>
</li> -->
</ul>
</div>
<a-modal v-model="visible" title="成为赞助商" @ok="visible = false">
如果您有品牌推广活动推广招聘推广社区合作等需求欢迎联系我们成为赞助商<br>
您的广告将出现在 And Design Vue 文档所有子页面及 GitHub Readme 等页面<br>
咨询邮箱<a href="mailto:antdv@foxmail.com">antdv@foxmail.com</a><br>
</a-modal>
</div>
</template>
<script>
import moment from 'moment';
export default {
props: ['isCN'],
data() {
return {
top: 50,
effectiveTime: {
bmatch: {
start: '2019-03-11',
end: '2019-06-11',
},
kkb: {
start: '2020-11-16 22:00:00',
end: '2021-05-17 22:00:00',
},
},
visible: false,
};
},
methods: {
isEffective({ start, end }) {
return moment().isBetween(start, end);
},
handleClick() {
if (this.isCN) {
this.visible = true;
} else {
window.open('https://opencollective.com/ant-design-vue#sponsor');
}
},
},
};
</script>

View File

@ -0,0 +1,56 @@
<template>
<div>
<template v-if="ads.length">
<a-carousel autoplay>
<template v-for="ad in ads">
<a :key="ad.href" :href="ad.href" target="_blank">
<img style="width: 100%; max-width: 1200px;" :alt="ad.alt || ''" :src="ad.img" />
</a>
</template>
</a-carousel>
</template>
<template v-else-if="showGoogleAd">
<GoogleAdsTop :key="`GoogleAdsTop_${$route.path}`" />
</template>
</div>
</template>
<script>
import moment from 'moment';
import GoogleAdsTop from './GoogleAdsTop';
const isEffective = (start, end) => {
return moment().isBetween(start, end);
};
export default {
components: {
GoogleAdsTop,
},
props: ['isCN', 'isMobile'],
data() {
return {
showGoogleAd: location.host.indexOf('antdv.com') > -1,
cnAds: [
{
img: `https://yidengfe.com/launches/01/yd.png?v=${Date.now()}`,
href: 'https://yidengfe.com/launches/01/yd.html',
visible: isEffective('2020-09-11 17:00:00', '2021-03-11 17:00:00'),
},
].filter(ad => ad.visible),
enAds: [
{
img: 'https://qn.antdv.com/TheBigRichGroup.png',
href: 'https://thebigrichgroup.com/',
visible: isEffective('2020-09-18 17:00:00', '2021-10-11 17:00:00'),
},
].filter(ad => ad.visible),
};
},
computed: {
ads() {
return this.isCN ? this.cnAds : this.enAds;
},
},
};
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,38 @@
<cn>
#### 基本
最简单的用法。
</cn>
<us>
#### basic
The simplest usage.
</us>
```vue
<template>
<div>
<a-affix :offset-top="top">
<a-button type="primary" @click="top += 10">
Affix top
</a-button>
</a-affix>
<br />
<a-affix :offset-bottom="bottom">
<a-button type="primary" @click="bottom += 10">
Affix bottom
</a-button>
</a-affix>
</div>
</template>
<script>
export default {
data() {
return {
top: 10,
bottom: 10,
};
},
};
</script>
```

View File

@ -0,0 +1,44 @@
<script>
import Basic from './basic';
import Onchange from './on-change';
import Target from './target';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# Affix 固钉
将页面元素钉在可视范围
## 何时使用
当内容区域比较长需要滚动页面时这部分内容对应的操作或者导航需要在滚动范围内始终展现常用于侧边菜单和按钮组合
页面可视范围过小时慎用此功能以免遮挡页面内容
## 代码演示`,
us: `# Affix
Make an element stick to viewport.
## When To Use
When user browses a long web page, some content need to stick to the viewport. This is common for menus and actions.
Please note that Affix should not cover other content on the page, especially when the size of the viewport is small.
## Examples `,
};
export default {
category: 'Components',
subtitle: '固钉',
zhType: '导航',
type: 'Navigation',
title: 'Affix',
render() {
return (
<div>
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<Onchange />
<Target />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>

View File

@ -0,0 +1,26 @@
<cn>
#### 固定状态改变的回调
可以获得是否固定的状态。
</cn>
<us>
#### Callback
Callback with affixed state.
</us>
```vue
<template>
<a-affix :offset-top="120" @change="change">
<a-button>120px to affix top</a-button>
</a-affix>
</template>
<script>
export default {
methods: {
change(affixed) {
console.log(affixed);
},
},
};
</script>
```

View File

@ -0,0 +1,34 @@
<cn>
#### 滚动容器
`target` 设置 `Affix` 需要监听其滚动事件的元素,默认为 `window`
</cn>
<us>
#### Container to scroll.
Set a `target` for 'Affix', which is listen to scroll event of target element (default is `window`).
</us>
```vue
<template>
<div id="components-affix-demo-target" ref="container" class="scrollable-container">
<div class="background">
<a-affix :target="() => this.$refs.container">
<a-button type="primary">
Fixed at the top of container
</a-button>
</a-affix>
</div>
</div>
</template>
<style>
#components-affix-demo-target.scrollable-container {
height: 100px;
overflow-y: scroll;
}
#components-affix-demo-target .background {
padding-top: 60px;
height: 300px;
background-image: url('https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg');
}
</style>
```

View File

@ -0,0 +1,29 @@
## API
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| offsetBottom | Offset from the bottom of the viewport (in pixels) | number | - | |
| offsetTop | Offset from the top of the viewport (in pixels) | number | 0 | |
| target | Specifies the scrollable area DOM node | () => HTMLElement | () => window | |
### events
| Events Name | Description | Arguments | Version |
| ----------- | ---------------------------------------- | ----------------- | ------- |
| change | Callback for when Affix state is changed | Function(affixed) |
**Note:** Children of `Affix` must not have the property `position: absolute`, but you can set `position: absolute` on `Affix` itself:
```html
<a-affix :style="{ position: 'absolute', top: y, left: x}">
...
</a-affix>
```
## FAQ
### Affix bind container with `target`, sometime move out of container.
We don't listen window scroll for performance consideration.
Related issues[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)

View File

@ -0,0 +1,29 @@
## API
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | () => HTMLElement | () => window | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------------- | ----------------- | ---- |
| change | 固定状态改变时触发的回调函数 | Function(affixed) | 无 | |
**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
```html
<a-affix :style="{ position: 'absolute', top: y, left: x}">
...
</a-affix>
```
## FAQ
### Affix 使用 `target` 绑定容器时,元素会跑到容器外。
从性能角度考虑,我们只监听容器滚动事件。
相关 issue[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)

View File

@ -0,0 +1,27 @@
<cn>
#### 顶部公告
页面顶部通告形式,默认有图标且`type` 为 'warning'。
</cn>
<us>
#### Banner
Display Alert as a banner at top of page.
</us>
```vue
<template>
<div>
<a-alert message="Warning text" banner />
<br />
<a-alert
message="Very long warning text warning text text text text text text text"
banner
closable
/>
<br />
<a-alert :show-icon="false" message="Warning text without icon" banner />
<br />
<a-alert type="error" message="Error text" banner />
</div>
</template>
```

View File

@ -0,0 +1,15 @@
<cn>
#### 基本
最简单的用法,适用于简短的警告提示。
</cn>
<us>
#### basic
The simplest usage for short messages.
</us>
```vue
<template>
<a-alert message="Success Text" type="success" />
</template>
```

View File

@ -0,0 +1,38 @@
<cn>
#### 可关闭的警告提示
显示关闭按钮,点击可关闭警告提示。
</cn>
<us>
#### Closable
To show close button.
</us>
```vue
<template>
<div>
<a-alert
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
type="warning"
closable
@close="onClose"
/>
<a-alert
message="Error Text"
description="Error Description Error Description Error Description Error Description Error Description Error Description"
type="error"
closable
@close="onClose"
/>
</div>
</template>
<script>
export default {
methods: {
onClose(e) {
console.log(e, 'I was closed.');
},
},
};
</script>
```

View File

@ -0,0 +1,15 @@
<cn>
#### 自定义关闭
可以自定义关闭,自定义的文字会替换原先的关闭 `Icon`
</cn>
<us>
#### Customized Close Text
Replace the default icon with customized text.
</us>
```vue
<template>
<a-alert message="Info Text" type="info" close-text="Close Now" />
</template>
```

View File

@ -0,0 +1,63 @@
<cn>
#### 自定义图标
可口的图标让信息类型更加醒目。
</cn>
<us>
#### Custom Icon
Decent icon make information more clear and more friendly.
</us>
```vue
<template>
<div>
<a-alert message="showIcon = false" type="success">
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert message="Success Tips" type="success" show-icon>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert message="Informational Notes" type="info" show-icon>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert message="Warning" type="warning" show-icon>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert message="Error" type="error" show-icon>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert
message="Success Tips"
description="Detailed description and advices about successful copywriting."
type="success"
show-icon
>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert
message="Informational Notes"
description="Additional description and informations about copywriting."
type="info"
show-icon
>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert
message="Warning"
description="This is a warning notice about copywriting."
type="warning"
show-icon
>
<a-icon slot="icon" type="smile" />
</a-alert>
<a-alert
message="Error"
description="This is an error message about copywriting."
type="error"
show-icon
>
<a-icon slot="icon" type="smile" />
</a-alert>
</div>
</template>
```

View File

@ -0,0 +1,36 @@
<cn>
#### 含有辅助性文字介绍
含有辅助性文字介绍的警告提示。
</cn>
<us>
#### Description
Additional description for alert message.
</us>
```vue
<template>
<div>
<a-alert message="Success Text" type="success">
<p slot="description">
Success Description <span style="color: red">Success</span> Description Success Description
</p>
</a-alert>
<a-alert
message="Info Text"
description="Info Description Info Description Info Description Info Description"
type="info"
/>
<a-alert
message="Warning Text"
description="Warning Description Warning Description Warning Description Warning Description"
type="warning"
/>
<a-alert
message="Error Text"
description="Error Description Error Description Error Description Error Description"
type="error"
/>
</div>
</template>
```

View File

@ -0,0 +1,44 @@
<cn>
#### 图标
可口的图标让信息类型更加醒目。
</cn>
<us>
#### Icon
Decent icon make information more clear and more friendly.
</us>
```vue
<template>
<div>
<a-alert message="Success Tips" type="success" show-icon />
<a-alert message="Informational Notes" type="info" show-icon />
<a-alert message="Warning" type="warning" show-icon />
<a-alert message="Error" type="error" show-icon />
<a-alert
message="Success Tips"
description="Detailed description and advices about successful copywriting."
type="success"
show-icon
/>
<a-alert
message="Informational Notes"
description="Additional description and informations about copywriting."
type="info"
show-icon
/>
<a-alert
message="Warning"
description="This is a warning notice about copywriting."
type="warning"
show-icon
/>
<a-alert
message="Error"
description="This is an error message about copywriting."
type="error"
show-icon
/>
</div>
</template>
```

View File

@ -0,0 +1,61 @@
<script>
import Banner from './banner';
import Basic from './basic';
import Closable from './closable';
import CloseText from './close-text';
import Description from './description';
import Icon from './icon';
import Style from './style';
import SmoothClosed from './smooth-closed';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# Alert 警告提示
警告提示展现需要关注的信息
## 何时使用
- 当某个页面需要向用户显示警告的信息时
- 非浮层的静态展现形式始终展现不会自动消失用户可以点击关闭
## 代码演示`,
us: `# Alert
Alert component for feedback.
## When To Use
- When you need to show alert messages to users.
- When you need a persistent static container which is closable by user actions.
## Examples
`,
};
export default {
category: 'Components',
subtitle: '警告提示',
type: 'Feedback',
zhType: '反馈',
title: 'Alert',
render() {
return (
<div id="components-alert-demo">
<md cn={md.cn} us={md.us} />
<demo-sort>
<Banner />
<Basic />
<Closable />
<CloseText />
<Description />
<Icon />
<Style />
<SmoothClosed />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>
<style>
#components-alert-demo .ant-alert {
margin-bottom: 16px;
}
</style>

View File

@ -0,0 +1,37 @@
<cn>
#### 平滑地卸载
平滑、自然的卸载提示。
</cn>
<us>
#### Smoothly Unmount
Smoothly and unaffectedly unmount Alert.
</us>
```vue
<template>
<div>
<a-alert
v-if="visible"
message="Alert Message Text"
type="success"
closable
:after-close="handleClose"
/>
</div>
</template>
<script>
export default {
data() {
return {
visible: true,
};
},
methods: {
handleClose() {
this.visible = false;
},
},
};
</script>
```

View File

@ -0,0 +1,20 @@
<cn>
#### 四种样式
共有四种样式 `success`、`info`、`warning`、`error`。
</cn>
<us>
#### More types
There are 4 types of Alert: `success`, `info`, `warning`, `error`.
</us>
```vue
<template>
<div>
<a-alert message="Success Text" type="success" />
<a-alert message="Info Text" type="info" />
<a-alert message="Warning Text" type="warning" />
<a-alert message="Error Text" type="error" />
</div>
</template>
```

View File

@ -0,0 +1,19 @@
## API
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| afterClose | Called when close animation is finished | () => void | - | - |
| banner | Whether to show as banner | boolean | false | - |
| closable | Whether Alert can be closed | boolean | - | - |
| closeText | Close text to show | string\|slot | - | - |
| description | Additional content of Alert | string\|slot | - | - |
| icon | Custom icon, effective when `showIcon` is `true` | vnode \| slot | - | - |
| message | Content of Alert | string\|slot | - | - |
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true | - |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` | - |
### events
| Events Name | Description | Arguments | Version |
| ----------- | ----------------------------- | ----------------------- | ------- |
| close | Callback when Alert is closed | (e: MouseEvent) => void | - |

View File

@ -0,0 +1,19 @@
## API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - | - |
| banner | 是否用作顶部公告 | boolean | false | - |
| closable | 默认不显示关闭按钮 | boolean | 无 | - |
| closeText | 自定义关闭按钮 | string\|slot | 无 | - |
| description | 警告提示的辅助性文字介绍 | string\|slot | 无 | - |
| icon | 自定义图标,`showIcon` 为 `true` 时有效 | vnode \| slot | - | - |
| message | 警告提示内容 | string\|slot | 无 | - |
| showIcon | 是否显示辅助图标 | boolean | false`banner` 模式下默认值为 true | - |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info``banner` 模式下默认值为 `warning` | - |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | -------------------- | ----------------------- | ---- |
| close | 关闭时触发的回调函数 | (e: MouseEvent) => void | - |

View File

@ -0,0 +1,27 @@
<cn>
#### 基本
最简单的用法。
</cn>
<us>
#### basic
The simplest usage.
</us>
```vue
<template>
<a-anchor>
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link
href="#components-anchor-demo-basic"
title="Basic demo with Target"
target="_blank"
/>
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
```

View File

@ -0,0 +1,31 @@
<cn>
#### 自定义锚点高亮
自定义锚点高亮。
</cn>
<us>
#### Customize the anchor highlight
Customize the anchor highlight.
</us>
```vue
<template>
<a-anchor :affix="false" :get-current-anchor="getCurrentAnchor">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script>
export default {
methods: {
getCurrentAnchor() {
return '#components-anchor-demo-static';
},
},
};
</script>
```

View File

@ -0,0 +1,61 @@
<script>
import Basic from './basic';
import Static from './static';
import OnClick from './onClick';
import CustomizeHighlight from './customizeHighlight';
import OnChange from './onChange';
import TargetOffset from './targetOffset';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# Anchor 锚点
用于跳转到页面指定位置
## 何时使用
需要展现当前页面上可供跳转的锚点链接以及快速在锚点之间跳转
## 代码演示`,
us: `# Anchor
Hyperlinks to scroll on one page.
## When To Use
For displaying anchor hyperlinks on page and jumping between them.
## Examples
`,
};
export default {
category: 'Components',
subtitle: '锚点',
cols: 2,
type: 'Other',
zhType: '其他',
title: 'Anchor',
render() {
return (
<div id="components-anchor-demo">
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<Static />
<OnClick />
<CustomizeHighlight />
<OnChange />
<TargetOffset />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>
<style>
#components-anchor-demo .ant-affix {
z-index: 11;
}
</style>

View File

@ -0,0 +1,31 @@
<cn>
#### 监听锚点链接改变
监听锚点链接改变
</cn>
<us>
#### Listening for anchor link change
Listening for anchor link change.
</us>
```vue
<template>
<a-anchor :affix="false" @change="onChange">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script>
export default {
methods: {
onChange(link) {
console.log('Anchor:OnChange', link);
},
},
};
</script>
```

View File

@ -0,0 +1,32 @@
<cn>
#### 自定义 click 事件
点击锚点不记录历史。
</cn>
<us>
#### Customize the click event
Clicking on an anchor does not record history.
</us>
```vue
<template>
<a-anchor :affix="false" @click="handleClick">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script>
export default {
methods: {
handleClick(e, link) {
e.preventDefault();
console.log(link);
},
},
};
</script>
```

View File

@ -0,0 +1,22 @@
<cn>
#### 静态位置
不浮动,状态不随页面滚动变化。
</cn>
<us>
#### Static
Do not change state when page is scrolling.
</us>
```vue
<template>
<a-anchor :affix="false">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
```

View File

@ -0,0 +1,34 @@
<cn>
#### 设置锚点滚动偏移量
锚点目标滚动到屏幕正中间。
</cn>
<us>
#### Set Anchor scroll offset
Anchor target scroll to screen center.
</us>
```vue
<template>
<a-anchor :target-offset="targetOffset">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script>
export default {
data() {
return {
targetOffset: undefined,
};
},
mounted() {
this.targetOffset = window.innerHeight / 2;
},
};
</script>
```

View File

@ -0,0 +1,31 @@
## API
### Anchor Props
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| affix | Fixed mode of Anchor | boolean | true | |
| bounds | Bounding distance of anchor area | number | 5(px) | |
| getContainer | Scrolling container | () => HTMLElement | () => window | |
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - | |
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | |
| showInkInFixed | Whether show ink-balls in Fixed mode | boolean | false | |
| wrapperClass | The class name of the container | string | - | |
| wrapperStyle | The style of the container | object | - | |
| getCurrentAnchor | Customize the anchor highlight | () => string | - | 1.5.0 |
| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
### Events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- |
| click | set the handler to handle `click` event | Function(e: Event, link: Object) | |
| change | Listening for anchor link change | (currentActiveLink: string) => void | | 1.5.0 |
### Link Props
| Property | Description | Type | Default | Version |
| -------- | ----------------------------------------- | ------------ | ------- | ------- |
| href | target of hyperlink | string | | |
| title | content of hyperlink | string\|slot | | |
| target | Specifies where to display the linked URL | string | | 1.5.0 |

View File

@ -0,0 +1,31 @@
## API
### Anchor Props
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| affix | 固定模式 | boolean | true | |
| bounds | 锚点区域边界 | number | 5(px) | |
| getContainer | 指定滚动的容器 | () => HTMLElement | () => window | |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| showInkInFixed | 固定模式是否显示小圆点 | boolean | false | |
| wrapperClass | 容器的类名 | string | - | |
| wrapperStyle | 容器样式 | object | - | |
| getCurrentAnchor | 自定义高亮的锚点 | () => string | - | 1.5.0 |
| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------- | ----------------------------------- | ---- |
| click | `click` 事件的 handler | Function(e: Event, link: Object) | |
| change | 监听锚点链接改变 | (currentActiveLink: string) => void | | 1.5.0 |
### Link Props
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| ------ | -------------------------------- | ------------ | ------ | ----- |
| href | 锚点链接 | string | | |
| title | 文字内容 | string\|slot | | |
| target | 该属性指定在何处显示链接的资源。 | string | | 1.5.0 |

View File

@ -0,0 +1,49 @@
<cn>
#### 基本使用
基本使用。通过 dataSource 设置自动完成的数据源
</cn>
<us>
#### Basic Usage
Basic Usage, set datasource of autocomplete with `dataSource` property.
</us>
```vue
<template>
<a-auto-complete
v-model="value"
:data-source="dataSource"
style="width: 200px"
placeholder="input here"
@select="onSelect"
@search="onSearch"
@change="onChange"
/>
</template>
<script>
export default {
data() {
return {
value: '',
dataSource: [],
};
},
watch: {
value(val) {
console.log('value', val);
},
},
methods: {
onSearch(searchText) {
this.dataSource = !searchText ? [] : [searchText, searchText.repeat(2), searchText.repeat(3)];
},
onSelect(value) {
console.log('onSelect', value);
},
onChange(value) {
console.log('onChange', value);
},
},
};
</script>
```

View File

@ -0,0 +1,149 @@
<cn>
#### 查询模式 - 确定类目
查询模式 - 确定类目
</cn>
<us>
#### Lookup-Patterns - Certain Category
Lookup-Patterns - Certain Category
</us>
```vue
<template>
<div class="certain-category-search-wrapper" style="width: 250px">
<a-auto-complete
class="certain-category-search"
dropdown-class-name="certain-category-search-dropdown"
:dropdown-match-select-width="false"
:dropdown-style="{ width: '300px' }"
size="large"
style="width: 100%"
placeholder="input here"
option-label-prop="value"
>
<template slot="dataSource">
<a-select-opt-group v-for="group in dataSource" :key="group.title">
<span slot="label">
{{ group.title }}
<a
style="float: right"
href="https://www.google.com/search?q=antd"
target="_blank"
rel="noopener noreferrer"
>more
</a>
</span>
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.title">
{{ opt.title }}
<span class="certain-search-item-count">{{ opt.count }} people</span>
</a-select-option>
</a-select-opt-group>
<a-select-option key="all" disabled class="show-all">
<a
href="https://www.google.com/search?q=ant-design-vue"
target="_blank"
rel="noopener noreferrer"
>
View all results
</a>
</a-select-option>
</template>
<a-input>
<a-icon slot="suffix" type="search" class="certain-category-icon" />
</a-input>
</a-auto-complete>
</div>
</template>
<script>
const dataSource = [
{
title: 'Libraries',
children: [
{
title: 'AntDesign',
count: 10000,
},
{
title: 'AntDesign UI',
count: 10600,
},
],
},
{
title: 'Solutions',
children: [
{
title: 'AntDesign UI',
count: 60100,
},
{
title: 'AntDesign',
count: 30010,
},
],
},
{
title: 'Articles',
children: [
{
title: 'AntDesign design language',
count: 100000,
},
],
},
];
export default {
data() {
return {
dataSource,
};
},
};
</script>
<style>
.certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title {
color: #666;
font-weight: bold;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item-group {
border-bottom: 1px solid #f6f6f6;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item {
padding-left: 16px;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all {
text-align: center;
cursor: default;
}
.certain-category-search-dropdown .ant-select-dropdown-menu {
max-height: 300px;
}
</style>
<style scoped>
.certain-category-search-wrapper
>>> .certain-category-search.ant-select-auto-complete
.ant-input-affix-wrapper
.ant-input-suffix {
right: 12px;
}
.certain-category-search-wrapper >>> .certain-search-item-count {
position: absolute;
color: #999;
right: 16px;
}
.certain-category-search-wrapper
>>> .certain-category-search.ant-select-focused
.certain-category-icon {
color: #108ee9;
}
.certain-category-search-wrapper >>> .certain-category-icon {
color: #6e6e6e;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
font-size: 16px;
}
</style>
```

View File

@ -0,0 +1,47 @@
<cn>
#### 自定义输入组件
自定义输入组件。
</cn>
<us>
#### Customize Input Component
Customize Input Component
</us>
```vue
<template>
<a-auto-complete
:data-source="dataSource"
style="width: 200px"
@search="handleSearch"
@select="onSelect"
>
<a-textarea
placeholder="input here"
class="custom"
style="height: 50px"
@keypress="handleKeyPress"
/>
</a-auto-complete>
</template>
<script>
export default {
data() {
return {
dataSource: [],
};
},
methods: {
onSelect(value) {
console.log('onSelect', value);
},
handleSearch(value) {
this.dataSource = !value ? [] : [value, value + value, value + value + value];
},
handleKeyPress(ev) {
console.log('handleKeyPress', ev);
},
},
};
</script>
```

View File

@ -0,0 +1,51 @@
<script>
import Basic from './basic';
import CertainCategory from './certain-category';
import Custom from './custom';
import NonCaseSensitive from './non-case-sensitive';
import Options from './options';
import UncertainCategory from './uncertain-category';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# AutoComplete 自动完成
输入框自动完成功能
## 何时使用
需要自动完成时
## 代码演示`,
us: `# AutoComplete
Autocomplete function of input field.
## When To Use
When there is a need for autocomplete functionality.
## Examples
`,
};
export default {
category: 'Components',
subtitle: '自动完成',
type: 'Data Entry',
zhType: '数据录入',
cols: 2,
title: 'AutoComplete',
render() {
return (
<div>
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<CertainCategory />
<Custom />
<NonCaseSensitive />
<Options />
<UncertainCategory />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>

View File

@ -0,0 +1,36 @@
<cn>
#### 不区分大小写
不区分大小写的 AutoComplete
</cn>
<us>
#### Non-case-sensitive AutoComplete
A non-case-sensitive AutoComplete
</us>
```vue
<template>
<a-auto-complete
:data-source="dataSource"
style="width: 200px"
placeholder="input here"
:filter-option="filterOption"
/>
</template>
<script>
export default {
data() {
return {
dataSource: ['Burns Bay Road', 'Downing Street', 'Wall Street'],
};
},
methods: {
filterOption(input, option) {
return (
option.componentOptions.children[0].text.toUpperCase().indexOf(input.toUpperCase()) >= 0
);
},
},
};
</script>
```

View File

@ -0,0 +1,41 @@
<cn>
#### 自定义选项
也可以直接传递slot="dataSource"的Option
</cn>
<us>
#### Customized
You could pass `slot="dataSource` as children of `AutoComplete`, instead of using `dataSource`
</us>
```vue
<template>
<a-auto-complete style="width: 200px" placeholder="input here" @search="handleSearch">
<template slot="dataSource">
<a-select-option v-for="email in result" :key="email">
{{ email }}
</a-select-option>
</template>
</a-auto-complete>
</template>
<script>
export default {
data() {
return {
result: [],
};
},
methods: {
handleSearch(value) {
let result;
if (!value || value.indexOf('@') >= 0) {
result = [];
} else {
result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
}
this.result = result;
},
},
};
</script>
```

View File

@ -0,0 +1,120 @@
<cn>
#### 查询模式 - 不确定类目
查询模式 - 不确定类目
</cn>
<us>
#### Lookup-Patterns - Uncertain Category
Lookup-Patterns - Uncertain Category
</us>
```vue
<template>
<div class="global-search-wrapper" style="width: 300px">
<a-auto-complete
class="global-search"
size="large"
style="width: 100%"
placeholder="input here"
option-label-prop="title"
@select="onSelect"
@search="handleSearch"
>
<template slot="dataSource">
<a-select-option v-for="item in dataSource" :key="item.category" :title="item.category">
Found {{ item.query }} on
<a
:href="`https://s.taobao.com/search?q=${item.query}`"
target="_blank"
rel="noopener noreferrer"
>
{{ item.category }}
</a>
<span className="global-search-item-count">{{ item.count }} results</span>
</a-select-option>
</template>
<a-input>
<a-button
slot="suffix"
style="margin-right: -12px"
class="search-btn"
size="large"
type="primary"
>
<a-icon type="search" />
</a-button>
</a-input>
</a-auto-complete>
</div>
</template>
<script>
export default {
data() {
return {
dataSource: [],
};
},
methods: {
onSelect(value) {
console.log('onSelect', value);
},
handleSearch(value) {
this.dataSource = value ? this.searchResult(value) : [];
},
getRandomInt(max, min = 0) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
searchResult(query) {
return new Array(this.getRandomInt(5))
.join('.')
.split('.')
.map((item, idx) => ({
query,
category: `${query}${idx}`,
count: this.getRandomInt(200, 100),
}));
},
},
};
</script>
<style>
.global-search-wrapper {
padding-right: 50px;
}
.global-search {
width: 100%;
}
.global-search.ant-select-auto-complete .ant-select-selection--single {
margin-right: -46px;
}
.global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input:not(:last-child) {
padding-right: 62px;
}
.global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input-suffix button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.global-search-item {
display: flex;
}
.global-search-item-desc {
flex: auto;
text-overflow: ellipsis;
overflow: hidden;
}
.global-search-item-count {
flex: none;
}
</style>
```

View File

@ -0,0 +1,41 @@
## API
```html
<a-auto-complete :dataSource="dataSource" />
```
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| allowClear | Show clear button, effective in multiple mode only. | boolean | false | |
| autoFocus | get focus when component mounted | boolean | false | |
| backfill | backfill selected item the input when using keyboard | boolean | false | |
| slot="default" (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| dataSource | Data source for autocomplete | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
| defaultValue | Initial selected option. | string\|string\[]\| - | |
| disabled | Whether disabled select | boolean | false | |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded. | boolean or function(inputValue, option) | true | |
| optionLabelProp | Which prop value of option will render as content of select. | string | `children` | |
| placeholder | placeholder of input | string | - | |
| value(v-model) | selected option | string\|string\[]\|{ key: string, label: string\|vNodes }\|Array&lt;{ key: string, label: string\|vNodes }> | - | |
| defaultOpen | Initial open state of dropdown | boolean | - | |
| open | Controlled open state of dropdown | boolean | - | |
### events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- |
| change | Called when select an option or input value change, or value of input is changed | function(value) | |
| blur | Called when leaving the component. | function() | |
| focus | Called when entering the component | function() | |
| search | Called when searching items. | function(value) | - | |
| select | Called when a option is selected. param is option's value and option instance. | function(value, option) | |
| dropdownVisibleChange | Call when dropdown open | function(open) | |
## Methods
| Name | Description | Version |
| ------- | ------------ | ------- |
| blur() | remove focus | |
| focus() | get focus | |

View File

@ -0,0 +1,41 @@
## API
```html
<a-auto-complete :dataSource="dataSource" />
```
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| allowClear | 支持清除, 单选模式有效 | boolean | false | |
| autoFocus | 自动获取焦点 | boolean | false | |
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
| slot="default" (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| dataSource | 自动完成的数据源 | slot \| [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
| defaultValue | 指定默认选中的条目 | string\|string\[]\| 无 | |
| disabled | 是否禁用 | boolean | false | |
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | boolean or function(inputValue, option) | true | |
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。 | string | `children` | |
| placeholder | 输入框提示 | string \| slot | - | |
| value(v-model) | 指定当前选中的条目 | string\|string\[]\|{ key: string, label: string\|vNodes }\|Array&lt;{ key: string, label: string\|vNodes }> | 无 | |
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
| open | 是否展开下拉菜单 | boolean | - | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| --- | --- | --- | --- |
| change | 选中 option或 input 的 value 变化时,调用此函数 | function(value) |
| blur | 失去焦点时的回调 | function() |
| focus | 获得焦点时的回调 | function() |
| search | 搜索补全项的时候调用 | function(value) |
| select | 被选中时调用,参数为选中项的 value 值 | function(value, option) |
| dropdownVisibleChange | 展开下拉菜单的回调 | function(open) |
## 方法
| 名称 | 描述 | 版本 |
| ------- | -------- | ---- |
| blur() | 移除焦点 |
| focus() | 获取焦点 |

View File

@ -0,0 +1,22 @@
<cn>
#### 带徽标的头像
通常用于消息提示。
</cn>
<us>
#### With Badge
Usually used for reminders and notifications.
</us>
```vue
<template>
<div>
<span style="margin-right:24px">
<a-badge :count="1"><a-avatar shape="square" icon="user"/></a-badge>
</span>
<span>
<a-badge dot><a-avatar shape="square" icon="user"/></a-badge>
</span>
</div>
</template>
```

View File

@ -0,0 +1,29 @@
<cn>
#### 基本
头像有三种尺寸,两种形状可选。
</cn>
<us>
#### basic
Three sizes and two shapes are available.
</us>
```vue
<template>
<div>
<div>
<a-avatar :size="64" icon="user" />
<a-avatar size="large" icon="user" />
<a-avatar icon="user" />
<a-avatar size="small" icon="user" />
</div>
<br />
<div>
<a-avatar shape="square" :size="64" icon="user" />
<a-avatar shape="square" size="large" icon="user" />
<a-avatar shape="square" icon="user" />
<a-avatar shape="square" size="small" icon="user" />
</div>
</div>
</template>
```

View File

@ -0,0 +1,49 @@
<cn>
#### 自动调整字符大小
对于字符型的头像,当字符串较长时,字体大小可以根据头像宽度自动调整。
</cn>
<us>
#### Autoset Font Size
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
</us>
```vue
<template>
<div>
<a-avatar
shape="square"
size="large"
:style="{ backgroundColor: color, verticalAlign: 'middle' }"
>
{{ avatarValue }}
</a-avatar>
<a-button
size="small"
:style="{ marginLeft: 16, verticalAlign: 'middle' }"
@click="changeValue"
>
改变
</a-button>
</div>
</template>
<script>
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
export default {
data() {
return {
avatarValue: UserList[0],
color: colorList[0],
};
},
methods: {
changeValue() {
const index = UserList.indexOf(this.avatarValue);
this.avatarValue = index < UserList.length - 1 ? UserList[index + 1] : UserList[0];
this.color = index < colorList.length - 1 ? colorList[index + 1] : colorList[0];
},
},
};
</script>
```

View File

@ -0,0 +1,47 @@
<script>
import Basic from './basic';
import Badge from './badge';
import Type from './type';
import Dynamic from './dynamic';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# Avatar头像
用来代表用户或事物支持图片图标或字符展示
## 设计师专属
安装 [Kitchen Sketch 插件 <EFBFBD>](https://kitchen.alipay.com).
## 代码演示`,
us: `# Avatar
Avatars can be used to represent people or objects. It supports images, 'Icon's, or letters.
## Examples
`,
};
export default {
category: 'Components',
subtitle: '头像',
type: 'Data Display',
zhType: '数据展示',
title: 'Avatar',
render() {
return (
<div>
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<Badge />
<Type />
<Dynamic />
</demo-sort>
<api>
<template slot="cn">
<CN />
</template>
<US />
</api>
</div>
);
},
};
</script>

View File

@ -0,0 +1,27 @@
<cn>
#### 类型
支持三种类型图片、Icon 以及字符,其中 Icon 和字符型可以自定义图标颜色及背景色。
</cn>
<us>
#### Type
Image, Icon and letter are supported, and the latter two kinds avatar can have custom colors and background colors.
</us>
```vue
<template>
<div>
<a-avatar icon="user" />
<a-avatar>
<a-icon slot="icon" type="user" />
</a-avatar>
<a-avatar>U</a-avatar>
<a-avatar>USER</a-avatar>
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<a-avatar style="color: #f56a00; backgroundColor: #fde3cf">
U
</a-avatar>
<a-avatar style="backgroundColor:#87d068" icon="user" />
</div>
</template>
```

View File

@ -0,0 +1,11 @@
## API
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| icon | the `Icon` type for an icon avatar, see `Icon` Component | string | - |
| shape | the shape of avatar | `circle` \| `square` | `circle` |
| size | the size of the avatar | number \| string: `large` `small` `default` | `default` |
| src | the address of the image for an image avatar | string | - |
| srcSet | a list of sources to use for different screen resolutions | string | - |
| alt | This attribute defines the alternative text describing the image | string | - |
| loadError | handler when img load error, return false to prevent default fallback behavior | () => boolean | - |

View File

@ -0,0 +1,11 @@
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| icon | 设置头像的图标类型,可设为 Icon 的 `type` 或 VNode | string \| VNode \| slot | - |
| shape | 指定头像的形状 | Enum{ 'circle', 'square' } | `circle` |
| size | 设置头像的大小 | number \| Enum{ 'large', 'small', 'default' } | `default` |
| src | 图片类头像的资源地址 | string | - |
| srcSet | 设置图片类头像响应式资源地址 | string | - |
| alt | 图像无法显示时的替代文本 | string | - |
| loadError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | () => boolean | - |

View File

@ -0,0 +1,20 @@
<cn>
#### 基本
最简单的用法。
</cn>
<us>
#### basic
The most basic usage.
</us>
```vue
<template>
<div>
<a-back-top />
Scroll down to see the bottom-right
<strong style="color: rgba(64, 64, 64, 0.6)"> gray </strong>
button.
</div>
</template>
```

View File

@ -0,0 +1,39 @@
<cn>
#### 自定义样式
可以自定义回到顶部按钮的样式,限制宽高:`40px * 40px`。
</cn>
<us>
#### Custom style
You can customize the style of the button, just note the size limit: no more than `40px * 40px`.
</us>
```vue
<template>
<div id="components-back-top-demo-custom">
<a-back-top>
<div class="ant-back-top-inner">
UP
</div>
</a-back-top>
Scroll down to see the bottom-right
<strong style="color: #1088e9"> blue </strong>
button.
</div>
</template>
<style scoped>
#components-back-top-demo-custom .ant-back-top {
bottom: 100px;
}
#components-back-top-demo-custom .ant-back-top-inner {
height: 40px;
width: 40px;
line-height: 40px;
border-radius: 4px;
background-color: #1088e9;
color: #fff;
text-align: center;
font-size: 20px;
}
</style>
```

View File

@ -0,0 +1,43 @@
<script>
import Basic from './basic';
import Custom from './custom';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
const md = {
cn: `# BackTop 回到顶部
返回页面顶部的操作按钮
## 何时使用
- 当页面内容区域比较长时
- 当用户需要频繁返回顶部查看相关内容时
## 代码演示`,
us: `# BackTop
\`BackTop\` makes it easy to go back to the top of the page.
## When To Use
- When the page content is very long.
- When you need to go back to the top very frequently in order to view the contents.
## Examples
`,
};
export default {
category: 'Components',
type: 'Other',
zhType: '其他',
subtitle: '回到顶部',
title: 'BackTop',
render() {
return (
<div>
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<Custom />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>

View File

@ -0,0 +1,16 @@
## API
> The distance to the bottom is set to `50px` by default, which is overridable.
>
> If you decide to use custom styles, please note the size limit: no more than `40px * 40px`.
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| target | specifies the scrollable area dom node | () => HTMLElement | () => window | |
| visibilityHeight | the `BackTop` button will not show until the scroll height reaches this value | number | 400 | |
### events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- |
| click | a callback function, which can be executed when you click the button | Function | |

View File

@ -0,0 +1,16 @@
## API
> 有默认样式,距离底部 `50px`,可覆盖。
>
> 自定义样式宽高不大于 40px \* 40px。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| target | 设置需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | Function | () => window | |
| visibilityHeight | 滚动高度达到此参数值才出现 `BackTop` | number | 400 | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ------------------ | -------- | ---- |
| click | 点击按钮的回调函数 | Function | |

View File

@ -0,0 +1,26 @@
<cn>
#### 基本
简单的徽章展示,当 `count``0` 时,默认不显示,但是可以使用 `showZero` 修改为显示。
</cn>
<us>
#### basic
Simplest Usage. Badge will be hidden when `count` is `0`, but we can use `showZero` to show it.
</us>
```vue
<template>
<div>
<a-badge count="5">
<a href="#" class="head-example" />
</a-badge>
<a-badge count="0" show-zero>
<a href="#" class="head-example" />
</a-badge>
<a-badge>
<a-icon slot="count" type="clock-circle" style="color: #f5222d" />
<a href="#" class="head-example" />
</a-badge>
</div>
</template>
```

View File

@ -0,0 +1,57 @@
<cn>
#### 动态
展示动态变化的效果。
</cn>
<us>
#### Dynamic
The count will be animated as it changes.
</us>
```vue
<template>
<div>
<div>
<a-badge :count="count">
<a href="#" class="head-example" />
</a-badge>
<a-button-group>
<a-button @click="decline">
<a-icon type="minus" />
</a-button>
<a-button @click="increase">
<a-icon type="plus" />
</a-button>
</a-button-group>
</div>
<div style="margin-top: 10px">
<a-badge :dot="show">
<a href="#" class="head-example" />
</a-badge>
<a-switch v-model="show" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
count: 5,
show: true,
};
},
methods: {
decline() {
let count = this.count - 1;
if (count < 0) {
count = 0;
}
this.count = count;
},
increase() {
this.count++;
},
},
};
</script>
```

View File

@ -0,0 +1,60 @@
<cn>
#### 多彩徽标
1.5.0 后新增。我们添加了多种预设色彩的徽标样式,用作不同场景使用。如果预设值不能满足你的需求,可以设置为具体的色值。
</cn>
<us>
#### Colorful Badge
New feature after 3.16.0. We preset a series of colorful Badge styles for use in different situations. You can also set it to a hex color string for custom color.
</us>
```vue
<template>
<div>
<h4 style="margin-bottom: 16px">
Presets:
</h4>
<div>
<div v-for="color in colors" :key="color">
<a-badge :color="color" :text="color" />
</div>
</div>
<h4 style="margin: 16px 0">
Custom:
</h4>
<div>
<a-badge color="#f50" text="#f50" />
<br />
<a-badge color="#2db7f5" text="#2db7f5" />
<br />
<a-badge color="#87d068" text="#87d068" />
<br />
<a-badge color="#108ee9" text="#108ee9" />
</div>
</div>
</template>
<script>
const colors = [
'pink',
'red',
'yellow',
'orange',
'cyan',
'green',
'blue',
'purple',
'geekblue',
'magenta',
'volcano',
'gold',
'lime',
];
export default {
data() {
return {
colors,
};
},
};
</script>
```

View File

@ -0,0 +1,34 @@
<cn>
#### 讨嫌的小红点
没有具体的数字。
</cn>
<us>
#### Red badge
This will simply display a red badge, without a specific count.
If count equals 0, it won't display the dot.
</us>
```vue
<template>
<div id="components-badge-demo-dot">
<a-badge dot>
<a-icon type="notification" />
</a-badge>
<a-badge :count="0" dot>
<a-icon type="notification" />
</a-badge>
<a-badge dot>
<a href="#">Link something</a>
</a-badge>
</div>
</template>
<style scoped>
#components-badge-demo-dot .anticon-notification {
width: 16px;
height: 16px;
line-height: 16px;
font-size: 16px;
}
</style>
```

View File

@ -0,0 +1,74 @@
<script>
import Basic from './basic.md';
import NoWapper from './no-wrapper';
import Dot from './dot';
import Change from './change';
import Overflow from './overflow';
import Status from './status';
import Title from './title';
import Colors from './colors';
import CN from './../index.zh-CN.md';
import US from './../index.en_US.md';
const md = {
cn: `# Badge徽标数
图标右上角的圆形徽标数字
## 何时使用
一般出现在通知图标或头像的右上角用于显示需要处理的消息条数通过醒目视觉形式吸引用户处理
## 代码演示
`,
us: `# Badge
Small numerical value or status descriptor for UI elements.
## When To Use
Badge normally appears in proximity to notifications or user avatars with eye-catching appeal, typically displaying unread messages count.
## Examples
`,
};
export default {
category: 'Components',
subtitle: '徽标数',
type: 'Data Display',
zhType: '数据展示',
title: 'Badge',
render() {
return (
<div id="components-badge-demo">
<md cn={md.cn} us={md.us} />
<demo-sort>
<Basic />
<NoWapper />
<Overflow />
<Dot />
<Status />
<Change />
<Title />
<Colors />
</demo-sort>
<api>
<CN slot="cn" />
<US />
</api>
</div>
);
},
};
</script>
<style>
#components-badge-demo .ant-badge:not(.ant-badge-not-a-wrapper) {
margin-right: 20px;
}
#components-badge-demo .head-example {
width: 42px;
height: 42px;
border-radius: 4px;
background: #eee;
display: inline-block;
vertical-align: middle;
}
#components-badge-demo .ant-badge-not-a-wrapper:not(.ant-badge-status) {
margin-right: 8px;
}
</style>

Some files were not shown because too many files have changed in this diff Show More