Repository: arco-design/arco-design-vue Branch: main Commit: 463014760f93 Files: 2232 Total size: 9.7 MB Directory structure: gitextract_qdd6vk9x/ ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── config.yml │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ ├── deploy-site-preview.yml │ ├── issue-duplicate.yml │ ├── issue-labeled.yml │ ├── issue-manager.yml │ ├── issue-remove-inactive.yml │ ├── pr_check.yml │ └── release.yml ├── .gitignore ├── .husky/ │ ├── commit-msg │ └── pre-commit ├── .npmrc ├── .nvmrc ├── .prettierrc.js ├── .vscode/ │ └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTING.zh-CN.md ├── LICENSE ├── README.md ├── README.zh-CN.md ├── commitlint.config.js ├── package.json ├── packages/ │ ├── arco-changelog/ │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── README.md │ │ ├── copy-template.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── .github/ │ │ │ │ └── PULL_REQUEST_TEMPLATE.md │ │ │ ├── .gitlab/ │ │ │ │ └── merge_request_templates/ │ │ │ │ └── CHANGELOG.md │ │ │ ├── changelog.ts │ │ │ ├── cmd.ts │ │ │ ├── config.ts │ │ │ ├── copy-github.js │ │ │ ├── default/ │ │ │ │ ├── emit-files.ts │ │ │ │ ├── template.en-US.njk │ │ │ │ └── template.zh-CN.njk │ │ │ ├── index.ts │ │ │ ├── interface.ts │ │ │ ├── test.md │ │ │ ├── utils/ │ │ │ │ ├── config.ts │ │ │ │ ├── convert-case.ts │ │ │ │ ├── invert.ts │ │ │ │ └── version.ts │ │ │ └── vue/ │ │ │ ├── emit-files.ts │ │ │ ├── template.en-US.njk │ │ │ ├── template.zh-CN.njk │ │ │ └── vue.config.ts │ │ └── tsconfig.json │ ├── arco-vue-docs/ │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── .stylelintrc.js │ │ ├── README.md │ │ ├── app.vue │ │ ├── components/ │ │ │ ├── anchor-head/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── article/ │ │ │ │ ├── context.ts │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── aside-anchor/ │ │ │ │ ├── index.vue │ │ │ │ ├── interface.ts │ │ │ │ └── style.less │ │ │ ├── aside-nav/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── cell-code/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── cell-demo/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── changelog-box/ │ │ │ │ └── index.vue │ │ │ ├── code-block/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── footer/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── logo/ │ │ │ │ └── index.vue │ │ │ ├── navbar/ │ │ │ │ ├── index.vue │ │ │ │ └── style.less │ │ │ ├── theme-box/ │ │ │ │ ├── index.vue │ │ │ │ └── interface.ts │ │ │ └── token-table/ │ │ │ └── token-table.vue │ │ ├── context.ts │ │ ├── docs/ │ │ │ ├── dark.en-US.md │ │ │ ├── dark.zh-CN.md │ │ │ ├── faq.en-US.md │ │ │ ├── faq.zh-CN.md │ │ │ ├── i18n.en-US.md │ │ │ ├── i18n.zh-CN.md │ │ │ ├── pro/ │ │ │ │ ├── build.en-US.md │ │ │ │ ├── build.zh-CN.md │ │ │ │ ├── directory.en-US.md │ │ │ │ ├── directory.zh-CN.md │ │ │ │ ├── faq.en-US.md │ │ │ │ ├── faq.zh-CN.md │ │ │ │ ├── i18n.en-US.md │ │ │ │ ├── i18n.zh-CN.md │ │ │ │ ├── layout.en-US.md │ │ │ │ ├── layout.zh-CN.md │ │ │ │ ├── mock.en-US.md │ │ │ │ ├── mock.zh-CN.md │ │ │ │ ├── npm-scripts.en-US.md │ │ │ │ ├── npm-scripts.zh-CN.md │ │ │ │ ├── permission.en-US.md │ │ │ │ ├── permission.zh-CN.md │ │ │ │ ├── routes-and-menu.en-US.md │ │ │ │ ├── routes-and-menu.zh-CN.md │ │ │ │ ├── start.en-US.md │ │ │ │ ├── start.zh-CN.md │ │ │ │ ├── state-management-pinia.en-US.md │ │ │ │ ├── state-management-pinia.zh-CN.md │ │ │ │ ├── state-management.en-US.md │ │ │ │ └── state-management.zh-CN.md │ │ │ ├── start.en-US.md │ │ │ ├── start.zh-CN.md │ │ │ ├── theme.en-US.md │ │ │ └── theme.zh-CN.md │ │ ├── global.d.ts │ │ ├── hooks/ │ │ │ ├── useLanguage.ts │ │ │ └── useTheme.ts │ │ ├── index.html │ │ ├── index.ts │ │ ├── locale/ │ │ │ ├── en-us.js │ │ │ ├── index.js │ │ │ └── zh-cn.js │ │ ├── package.json │ │ ├── pages/ │ │ │ ├── changelog/ │ │ │ │ ├── changelog.vue │ │ │ │ └── style/ │ │ │ │ └── index.less │ │ │ ├── icon/ │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── icon-font.md │ │ │ │ │ ├── spin.md │ │ │ │ │ └── tree-shaking.md │ │ │ │ ├── icon-demo.vue │ │ │ │ ├── icons.json │ │ │ │ └── style.less │ │ │ └── token/ │ │ │ ├── token.vue │ │ │ └── tokens.ts │ │ ├── router.ts │ │ ├── style/ │ │ │ ├── demo.less │ │ │ └── index.less │ │ ├── tsconfig.json │ │ └── utils/ │ │ ├── api.ts │ │ ├── clipboard.ts │ │ ├── code-sandbox.ts │ │ ├── code-stackblitz.ts │ │ ├── code-template.ts │ │ ├── codepen.ts │ │ ├── join-chart.ts │ │ ├── local-storage.ts │ │ ├── login.ts │ │ └── strings.ts │ ├── arco-vue-docs-navbar/ │ │ ├── .eslintignore │ │ ├── .gitignore │ │ ├── README.md │ │ ├── dist/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── package.json │ │ ├── plugins/ │ │ │ └── rollup-plugin-svgr.ts │ │ ├── src/ │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ ├── navbar.css │ │ │ ├── navbar.less │ │ │ └── style/ │ │ │ ├── history.less │ │ │ ├── hot.less │ │ │ └── list.less │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── arco-vue-scripts/ │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── README.md │ │ ├── copy-template.js │ │ ├── package.json │ │ ├── src/ │ │ │ ├── configs/ │ │ │ │ ├── jest.config.ts │ │ │ │ ├── vite.dev.ts │ │ │ │ ├── vite.material.library.ts │ │ │ │ ├── vite.material.library.umd.ts │ │ │ │ ├── vite.material.prod.ts │ │ │ │ ├── vite.material.style.ts │ │ │ │ ├── vite.prod.style.ts │ │ │ │ ├── vite.prod.ts │ │ │ │ ├── vite.prod.umd.ts │ │ │ │ ├── vite.site.dev.ts │ │ │ │ └── vite.site.prod.ts │ │ │ ├── index.ts │ │ │ ├── plugins/ │ │ │ │ ├── md-vue-jest/ │ │ │ │ │ └── index.js │ │ │ │ ├── vite-plugin-cssjs/ │ │ │ │ │ └── index.ts │ │ │ │ ├── vite-plugin-external/ │ │ │ │ │ └── index.ts │ │ │ │ └── vite-plugin-vue-export-helper/ │ │ │ │ └── index.ts │ │ │ ├── scripts/ │ │ │ │ ├── build-component/ │ │ │ │ │ └── index.ts │ │ │ │ ├── build-material/ │ │ │ │ │ └── index.ts │ │ │ │ ├── build-material-library/ │ │ │ │ │ └── index.ts │ │ │ │ ├── build-site/ │ │ │ │ │ └── index.ts │ │ │ │ ├── build-style/ │ │ │ │ │ └── index.ts │ │ │ │ ├── changelog/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── template/ │ │ │ │ │ │ ├── main.en-US.njk │ │ │ │ │ │ └── main.zh-CN.njk │ │ │ │ │ └── utils.ts │ │ │ │ ├── dev-component/ │ │ │ │ │ └── index.ts │ │ │ │ ├── dev-site/ │ │ │ │ │ └── index.ts │ │ │ │ ├── docgen/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── slot-tag-handler.ts │ │ │ │ │ ├── templates/ │ │ │ │ │ │ ├── events.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── methods.ts │ │ │ │ │ │ ├── props.ts │ │ │ │ │ │ └── slots.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── parse-interface.ts │ │ │ │ │ ├── parse-material.ts │ │ │ │ │ └── print.ts │ │ │ │ ├── dtsgen/ │ │ │ │ │ └── index.ts │ │ │ │ ├── icongen/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── svgo.config.ts │ │ │ │ │ └── vue-template.ts │ │ │ │ ├── jsongen/ │ │ │ │ │ └── index.ts │ │ │ │ ├── lessgen/ │ │ │ │ │ └── index.ts │ │ │ │ └── test/ │ │ │ │ ├── index.ts │ │ │ │ └── screentshot.ts │ │ │ └── utils/ │ │ │ ├── config.ts │ │ │ ├── convert-case.ts │ │ │ ├── get-package.ts │ │ │ ├── paths.ts │ │ │ └── rollup.ts │ │ └── tsconfig.json │ ├── vite-plugin-arco-vue-docs/ │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── descriptor.ts │ │ │ ├── index.ts │ │ │ ├── interface.ts │ │ │ ├── markdown.ts │ │ │ ├── marked.ts │ │ │ ├── parse-changelog.ts │ │ │ ├── utils.ts │ │ │ └── vue-template.ts │ │ └── tsconfig.json │ ├── web-vue/ │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── .stylelintrc.js │ │ ├── CHANGELOG.md │ │ ├── CHANGELOG.zh-CN.md │ │ ├── README.md │ │ ├── README.zh-CN.md │ │ ├── babel.config.js │ │ ├── components/ │ │ │ ├── _components/ │ │ │ │ ├── auto-tooltip/ │ │ │ │ │ ├── auto-tooltip.tsx │ │ │ │ │ └── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.ts │ │ │ │ ├── client-only.tsx │ │ │ │ ├── feedback-icon.vue │ │ │ │ ├── icon-hover.vue │ │ │ │ ├── input-label/ │ │ │ │ │ ├── input-label.tsx │ │ │ │ │ └── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── input-label.less │ │ │ │ │ └── token.less │ │ │ │ ├── picker/ │ │ │ │ │ ├── input-range.vue │ │ │ │ │ ├── input.vue │ │ │ │ │ └── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ └── token.less │ │ │ │ ├── render-function.ts │ │ │ │ ├── resize-observer-v2.ts │ │ │ │ ├── resize-observer.tsx │ │ │ │ ├── resize-trigger.vue │ │ │ │ ├── select-view/ │ │ │ │ │ ├── interface.ts │ │ │ │ │ ├── select-view.tsx │ │ │ │ │ └── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── transition/ │ │ │ │ │ └── expand-transition.vue │ │ │ │ ├── virtual-list/ │ │ │ │ │ ├── filler.vue │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ ├── use-item-height.ts │ │ │ │ │ │ ├── use-range-state.ts │ │ │ │ │ │ ├── use-render-children.tsx │ │ │ │ │ │ ├── use-scroll-to.ts │ │ │ │ │ │ └── use-viewport-height.ts │ │ │ │ │ ├── interface.ts │ │ │ │ │ ├── utils/ │ │ │ │ │ │ ├── algorithm.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── virtual-list.vue │ │ │ │ └── virtual-list-v2/ │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-size.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── virtual-list-item.tsx │ │ │ │ └── virtual-list.vue │ │ │ ├── _hooks/ │ │ │ │ ├── use-children-components.ts │ │ │ │ ├── use-component-ref.ts │ │ │ │ ├── use-cursor.ts │ │ │ │ ├── use-first-element.ts │ │ │ │ ├── use-form-item.ts │ │ │ │ ├── use-index.ts │ │ │ │ ├── use-input.ts │ │ │ │ ├── use-merge-state.ts │ │ │ │ ├── use-overflow.ts │ │ │ │ ├── use-pagination.ts │ │ │ │ ├── use-pick-slots.ts │ │ │ │ ├── use-popup-container.ts │ │ │ │ ├── use-popup-manager.ts │ │ │ │ ├── use-popup-overflow-hidden.ts │ │ │ │ ├── use-pure-prop.ts │ │ │ │ ├── use-resize-observer.ts │ │ │ │ ├── use-responsive.ts │ │ │ │ ├── use-scrollbar.ts │ │ │ │ ├── use-size.ts │ │ │ │ ├── use-state.ts │ │ │ │ ├── use-teleport-container.ts │ │ │ │ └── use-trigger.ts │ │ │ ├── _utils/ │ │ │ │ ├── array.ts │ │ │ │ ├── clipboard.ts │ │ │ │ ├── color.ts │ │ │ │ ├── constant.ts │ │ │ │ ├── convert-case.ts │ │ │ │ ├── date.ts │ │ │ │ ├── debounce.ts │ │ │ │ ├── dom.ts │ │ │ │ ├── get-value-by-path.ts │ │ │ │ ├── global-config.ts │ │ │ │ ├── is-equal.ts │ │ │ │ ├── is.ts │ │ │ │ ├── keyboard.ts │ │ │ │ ├── keycode.ts │ │ │ │ ├── omit.ts │ │ │ │ ├── pad.ts │ │ │ │ ├── pick-sub-comp-slots.ts │ │ │ │ ├── pick.ts │ │ │ │ ├── raf.ts │ │ │ │ ├── responsive-observe.ts │ │ │ │ ├── style.ts │ │ │ │ ├── throttle-by-raf.ts │ │ │ │ ├── to-array.ts │ │ │ │ ├── types.ts │ │ │ │ ├── use-prop-or-slot.ts │ │ │ │ └── vue-utils.ts │ │ │ ├── affix/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── bottom.md │ │ │ │ │ ├── container.md │ │ │ │ │ ├── fix-change.md │ │ │ │ │ └── top.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── affix.vue │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── alert/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── action.md │ │ │ │ │ ├── banner.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── closable.md │ │ │ │ │ ├── close-element.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── title.md │ │ │ │ │ └── type.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── alert.vue │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── anchor/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── affix.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── boundary.md │ │ │ │ │ ├── hash.md │ │ │ │ │ └── line-less.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── anchor-link.vue │ │ │ │ ├── anchor.vue │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── arco-vue.ts │ │ │ ├── auto-complete/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── footer.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── strict.md │ │ │ │ │ └── virtual-list.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── auto-complete.tsx │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── avatar/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── fit.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── image-url.md │ │ │ │ │ └── size.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── avatar-group.tsx │ │ │ │ ├── avatar.vue │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── back-top/ │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── custom.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── back-top.vue │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── badge/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── alone.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── color.md │ │ │ │ │ ├── dot.md │ │ │ │ │ ├── max.md │ │ │ │ │ ├── status.md │ │ │ │ │ └── text.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── badge.tsx │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── breadcrumb/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── dropdown.md │ │ │ │ │ ├── ellipsis.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── routes.md │ │ │ │ │ ├── separator.md │ │ │ │ │ └── size.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── breadcrumb-item.tsx │ │ │ │ ├── breadcrumb.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── button/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── loading.md │ │ │ │ │ ├── long.md │ │ │ │ │ ├── shape.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── status.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── button-group.vue │ │ │ │ ├── button.vue │ │ │ │ ├── constants.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── calendar/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ └── basic.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── calendar.tsx │ │ │ │ ├── header.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── useCellClassName.ts │ │ │ │ ├── index.ts │ │ │ │ ├── month.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── week.tsx │ │ │ │ └── year.tsx │ │ │ ├── card/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── actions.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── bordered.md │ │ │ │ │ ├── content.md │ │ │ │ │ ├── grid.md │ │ │ │ │ ├── hoverable.md │ │ │ │ │ ├── inner.md │ │ │ │ │ ├── meta.md │ │ │ │ │ └── row.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── card-grid.vue │ │ │ │ ├── card-meta.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── carousel/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── auto.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── card.md │ │ │ │ │ ├── direction.md │ │ │ │ │ ├── fade.md │ │ │ │ │ └── indicator.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── carousel-arrow.vue │ │ │ │ ├── carousel-indicator.vue │ │ │ │ ├── carousel-item.vue │ │ │ │ ├── carousel.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ ├── slide.less │ │ │ │ └── token.less │ │ │ ├── cascader/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── check-strictly.md │ │ │ │ │ ├── clear.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── expand.md │ │ │ │ │ ├── fallback.md │ │ │ │ │ ├── field-names.md │ │ │ │ │ ├── format.md │ │ │ │ │ ├── lazy-load.md │ │ │ │ │ ├── loading.md │ │ │ │ │ ├── multiple.md │ │ │ │ │ ├── panel.md │ │ │ │ │ ├── path.md │ │ │ │ │ ├── search.md │ │ │ │ │ └── virtual.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── base-cascader-panel.tsx │ │ │ │ ├── cascader-column.tsx │ │ │ │ ├── cascader-option.tsx │ │ │ │ ├── cascader-panel.vue │ │ │ │ ├── cascader-search-panel.tsx │ │ │ │ ├── cascader.vue │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-selected-path.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── checkbox/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── all.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── layout.md │ │ │ │ │ ├── limit.md │ │ │ │ │ └── options.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── checkbox-group.tsx │ │ │ │ ├── checkbox.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── icon-check.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── collapse/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── accordion.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── border-less.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── destroy.md │ │ │ │ │ ├── expand-icon.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── icon-position.md │ │ │ │ │ └── nested.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── collapse-item.tsx │ │ │ │ ├── collapse.vue │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── color-picker/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── colors.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── format.md │ │ │ │ │ ├── only-panel.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── trigger-element.md │ │ │ │ │ └── trigger.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── color-picker.tsx │ │ │ │ ├── colors.ts │ │ │ │ ├── control-bar.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-control-block.ts │ │ │ │ ├── index.ts │ │ │ │ ├── input-alpha.tsx │ │ │ │ ├── input-hex.tsx │ │ │ │ ├── input-rgb.tsx │ │ │ │ ├── interface.ts │ │ │ │ ├── palette.tsx │ │ │ │ ├── panel.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── comment/ │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── align.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── editor.md │ │ │ │ │ └── nest.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── comment.vue │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── components.ts │ │ │ ├── config-provider/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── empty.md │ │ │ │ │ └── rtl.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── config-provider.vue │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── date-picker/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── date-render.md │ │ │ │ │ ├── default-value.md │ │ │ │ │ ├── disabled-date-advance.md │ │ │ │ │ ├── disabled-date.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── month.md │ │ │ │ │ ├── panel-only.md │ │ │ │ │ ├── prefix.md │ │ │ │ │ ├── quarter.md │ │ │ │ │ ├── range.md │ │ │ │ │ ├── shortcuts-position.md │ │ │ │ │ ├── shortcuts.md │ │ │ │ │ ├── showtime.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── trigger-element.md │ │ │ │ │ ├── week.md │ │ │ │ │ └── year.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-cell-class-name.ts │ │ │ │ │ ├── use-format.ts │ │ │ │ │ ├── use-header-value.ts │ │ │ │ │ ├── use-inject-datepicker-transform.ts │ │ │ │ │ ├── use-is-disabled-date.ts │ │ │ │ │ ├── use-panel-span.ts │ │ │ │ │ ├── use-picker-state.ts │ │ │ │ │ ├── use-provide-datepicker-transform.ts │ │ │ │ │ ├── use-range-header-value.ts │ │ │ │ │ ├── use-range-picker-state.ts │ │ │ │ │ ├── use-range-time-picker-value.ts │ │ │ │ │ ├── use-time-picker-value.ts │ │ │ │ │ └── use-value-format.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── panels/ │ │ │ │ │ ├── body.vue │ │ │ │ │ ├── date/ │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── footer.vue │ │ │ │ │ ├── header.vue │ │ │ │ │ ├── month/ │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── quarter/ │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── shortcuts.vue │ │ │ │ │ ├── week/ │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── week-list.vue │ │ │ │ │ └── year/ │ │ │ │ │ └── index.vue │ │ │ │ ├── picker-panel.vue │ │ │ │ ├── picker.vue │ │ │ │ ├── pickers/ │ │ │ │ │ ├── date-picker.tsx │ │ │ │ │ ├── month-picker.tsx │ │ │ │ │ ├── quarter-picker.tsx │ │ │ │ │ ├── week-picker.tsx │ │ │ │ │ └── year-picker.tsx │ │ │ │ ├── range-picker-panel.vue │ │ │ │ ├── range-picker.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── date.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── month.less │ │ │ │ │ ├── quarter.less │ │ │ │ │ ├── range.less │ │ │ │ │ ├── shortcuts.less │ │ │ │ │ ├── token.less │ │ │ │ │ ├── week.less │ │ │ │ │ └── year.less │ │ │ │ └── utils/ │ │ │ │ └── index.ts │ │ │ ├── descriptions/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── align.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── bordered.md │ │ │ │ │ ├── example.md │ │ │ │ │ ├── layout.md │ │ │ │ │ └── single.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── descriptions-item.vue │ │ │ │ ├── descriptions.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── divider/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── vertical.md │ │ │ │ │ └── with-text.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── divider.tsx │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── drawer/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── async.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── function.md │ │ │ │ │ ├── nested.md │ │ │ │ │ ├── popup-container.md │ │ │ │ │ └── position.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── drawer.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── dropdown/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── button.md │ │ │ │ │ ├── context-menu.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── position.md │ │ │ │ │ ├── submenu.md │ │ │ │ │ └── trigger.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── dropdown-button.vue │ │ │ │ ├── dropdown-group.vue │ │ │ │ ├── dropdown-option.vue │ │ │ │ ├── dropdown-panel.vue │ │ │ │ ├── dropdown-submenu.vue │ │ │ │ ├── dropdown.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── empty/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── custom.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── empty.tsx │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── form/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── async.md │ │ │ │ │ ├── auto-width.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── dynamic.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── grid.md │ │ │ │ │ ├── layout.md │ │ │ │ │ ├── nest.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── status.md │ │ │ │ │ ├── validation.md │ │ │ │ │ └── validation2.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── demo.vue │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── form-item-label.vue │ │ │ │ ├── form-item-message.vue │ │ │ │ ├── form-item.vue │ │ │ │ ├── form.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── status.less │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── grid/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── adaptation-object.md │ │ │ │ │ ├── adaptation.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── flex-align.md │ │ │ │ │ ├── flex-justify.md │ │ │ │ │ ├── flex.md │ │ │ │ │ ├── grid-responsive.md │ │ │ │ │ ├── grid.md │ │ │ │ │ ├── gutter.md │ │ │ │ │ ├── offset.md │ │ │ │ │ └── order.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── grid-col.vue │ │ │ │ ├── grid-item.vue │ │ │ │ ├── grid-row.vue │ │ │ │ ├── grid.vue │ │ │ │ ├── hook/ │ │ │ │ │ ├── use-responsive-state.ts │ │ │ │ │ └── use-responsive-value.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── col.less │ │ │ │ │ ├── grid.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── row.less │ │ │ │ └── utils/ │ │ │ │ └── index.ts │ │ │ ├── icon-component/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── add-from-icon-font-cn.tsx │ │ │ │ ├── icon.vue │ │ │ │ ├── index.ts │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── image/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── caption.md │ │ │ │ │ ├── component-preview-group.md │ │ │ │ │ ├── component-preview.md │ │ │ │ │ ├── custom-preview-actions.md │ │ │ │ │ ├── error.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── loader.md │ │ │ │ │ ├── preview-group.md │ │ │ │ │ ├── preview-popup-container.md │ │ │ │ │ └── progressive-loader.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-image-drag.ts │ │ │ │ │ └── use-image-load-status.ts │ │ │ │ ├── image-footer.vue │ │ │ │ ├── image.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── preview-action.tsx │ │ │ │ ├── preview-arrow.vue │ │ │ │ ├── preview-group.vue │ │ │ │ ├── preview-toolbar.vue │ │ │ │ ├── preview.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── image.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── preview.less │ │ │ │ │ ├── token.less │ │ │ │ │ └── trigger.less │ │ │ │ └── utils/ │ │ │ │ ├── get-fix-translate.ts │ │ │ │ ├── get-scale.ts │ │ │ │ └── index.ts │ │ │ ├── index.less │ │ │ ├── index.ts │ │ │ ├── input/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── password.md │ │ │ │ │ ├── prefix.md │ │ │ │ │ ├── prepend.md │ │ │ │ │ ├── search-button.md │ │ │ │ │ ├── search-loading.md │ │ │ │ │ ├── search.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── status.md │ │ │ │ │ └── word-limit.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── input-group.vue │ │ │ │ ├── input-password.vue │ │ │ │ ├── input-search.tsx │ │ │ │ ├── input.tsx │ │ │ │ └── style/ │ │ │ │ ├── group.less │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ ├── input.less │ │ │ │ ├── password.less │ │ │ │ ├── search.less │ │ │ │ ├── size.less │ │ │ │ ├── textarea.less │ │ │ │ └── token.less │ │ │ ├── input-number/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── format.md │ │ │ │ │ ├── mode.md │ │ │ │ │ ├── model.md │ │ │ │ │ ├── precision.md │ │ │ │ │ ├── prefix.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── step-icon.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── input-number.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── input-tag/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── max.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── status.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── input-tag.tsx │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── input-tag.less │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── layout/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── breakpoint.md │ │ │ │ │ ├── collapsed.md │ │ │ │ │ ├── custom-icon.md │ │ │ │ │ └── resize.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── content.vue │ │ │ │ ├── context.ts │ │ │ │ ├── footer.vue │ │ │ │ ├── header.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── layout.vue │ │ │ │ ├── sider.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── link/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── hoverable.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── loading.md │ │ │ │ │ └── status.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── link.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── list/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── actions-layout.md │ │ │ │ │ ├── actions.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── grid.md │ │ │ │ │ ├── meta.md │ │ │ │ │ ├── responsive-grid.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── virtual-list.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list-item-meta.vue │ │ │ │ ├── list-item.tsx │ │ │ │ ├── list.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── use-pagination.ts │ │ │ ├── locale/ │ │ │ │ ├── __test__/ │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ └── lang/ │ │ │ │ ├── ar-eg.ts │ │ │ │ ├── de-de.ts │ │ │ │ ├── en-us.ts │ │ │ │ ├── es-es.ts │ │ │ │ ├── fr-fr.ts │ │ │ │ ├── id-id.ts │ │ │ │ ├── it-it.ts │ │ │ │ ├── ja-jp.ts │ │ │ │ ├── km-kh.ts │ │ │ │ ├── ko-kr.ts │ │ │ │ ├── ms-my.ts │ │ │ │ ├── nl-nl.ts │ │ │ │ ├── pt-pt.ts │ │ │ │ ├── ru-ru.ts │ │ │ │ ├── th-th.ts │ │ │ │ ├── vi-vn.ts │ │ │ │ ├── zh-cn.ts │ │ │ │ └── zh-tw.ts │ │ │ ├── mention/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── prefix.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── mention.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── menu/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── breakpoint.md │ │ │ │ │ ├── collapse-control.md │ │ │ │ │ ├── dark-horizontal.md │ │ │ │ │ ├── horizontal.md │ │ │ │ │ ├── pop-button.md │ │ │ │ │ ├── pop.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── sub-menu.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── base-menu.vue │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-level.ts │ │ │ │ │ ├── use-menu-context.ts │ │ │ │ │ ├── use-menu-data-collector.ts │ │ │ │ │ ├── use-menu-open-state.ts │ │ │ │ │ └── use-menu.ts │ │ │ │ ├── indent.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── item-group.vue │ │ │ │ ├── item.tsx │ │ │ │ ├── menu.tsx │ │ │ │ ├── overflow-wrap.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── sub-menu-inline.vue │ │ │ │ ├── sub-menu-pop.vue │ │ │ │ ├── sub-menu.tsx │ │ │ │ └── utils/ │ │ │ │ └── index.ts │ │ │ ├── message/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── closeable.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── position.md │ │ │ │ │ ├── type.md │ │ │ │ │ └── update.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── message-list.tsx │ │ │ │ ├── message.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── modal/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── async.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── confirm.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── draggable.md │ │ │ │ │ ├── form.md │ │ │ │ │ ├── fullscreen.md │ │ │ │ │ ├── function.md │ │ │ │ │ ├── notice.md │ │ │ │ │ └── width.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ └── use-draggable.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── interface.ts │ │ │ │ ├── modal.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── notification/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── btn.md │ │ │ │ │ ├── custom-close.md │ │ │ │ │ ├── position.md │ │ │ │ │ ├── style.md │ │ │ │ │ ├── type.md │ │ │ │ │ ├── update_duration.md │ │ │ │ │ └── update_notification.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── notification-list.tsx │ │ │ │ ├── notification.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── overflow-list/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── from.md │ │ │ │ ├── index.ts │ │ │ │ ├── overflow-list.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── page-header/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── breadcrumb.md │ │ │ │ │ ├── content.md │ │ │ │ │ └── transparent.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── page-header.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── pagination/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── all.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── ellipsis.md │ │ │ │ │ ├── jumper.md │ │ │ │ │ ├── page-size.md │ │ │ │ │ ├── simple.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── total.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── page-item-ellipsis.vue │ │ │ │ ├── page-item-step.vue │ │ │ │ ├── page-item.vue │ │ │ │ ├── page-jumper.vue │ │ │ │ ├── page-options.vue │ │ │ │ ├── pagination.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── popconfirm/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── async.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── position.md │ │ │ │ │ └── type.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── popconfirm.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── popover/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── position.md │ │ │ │ │ └── trigger.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── popover.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── progress/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── circle.md │ │ │ │ │ ├── linear.md │ │ │ │ │ ├── mini.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── status.md │ │ │ │ │ ├── steps.md │ │ │ │ │ └── trackColor.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── circle.vue │ │ │ │ ├── index.ts │ │ │ │ ├── line.vue │ │ │ │ ├── progress.vue │ │ │ │ ├── steps.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── radio/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── button.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── direction.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── layout.md │ │ │ │ │ ├── options.md │ │ │ │ │ └── size.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── radio-group.tsx │ │ │ │ ├── radio.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── rate/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── character.md │ │ │ │ │ ├── clear.md │ │ │ │ │ ├── color.md │ │ │ │ │ ├── count.md │ │ │ │ │ ├── grading.md │ │ │ │ │ ├── half.md │ │ │ │ │ └── readonly.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── rate.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── resize-box/ │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── controlled.md │ │ │ │ │ ├── custom-triggers.md │ │ │ │ │ └── layout.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── resize-box.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── result/ │ │ │ │ ├── 403.tsx │ │ │ │ ├── 404.tsx │ │ │ │ ├── 500.tsx │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── 403.md │ │ │ │ │ ├── 404.md │ │ │ │ │ ├── 500.md │ │ │ │ │ ├── all.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── error.md │ │ │ │ │ ├── success.md │ │ │ │ │ └── warning.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── result.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── scrollbar/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── type.md │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── scrollbar.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── thumb.vue │ │ │ ├── select/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── border.md │ │ │ │ │ ├── clear.md │ │ │ │ │ ├── create.md │ │ │ │ │ ├── fallback.md │ │ │ │ │ ├── field-names.md │ │ │ │ │ ├── footer.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── header.md │ │ │ │ │ ├── label.md │ │ │ │ │ ├── linkage.md │ │ │ │ │ ├── loading.md │ │ │ │ │ ├── multiple.md │ │ │ │ │ ├── remote.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── search.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── virtual-list.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-options.ts │ │ │ │ │ └── use-select.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── optgroup.vue │ │ │ │ ├── option.vue │ │ │ │ ├── select-dropdown.vue │ │ │ │ ├── select.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── skeleton/ │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── animation.md │ │ │ │ │ ├── basic.md │ │ │ │ │ └── type.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── line.vue │ │ │ │ ├── shape.vue │ │ │ │ ├── skeleton.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── slider/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── input.md │ │ │ │ │ ├── marks.md │ │ │ │ │ ├── range.md │ │ │ │ │ ├── step.md │ │ │ │ │ ├── tooltip.md │ │ │ │ │ └── vertical.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── slider-button.vue │ │ │ │ ├── slider-dots.vue │ │ │ │ ├── slider-input.vue │ │ │ │ ├── slider-marks.vue │ │ │ │ ├── slider-ticks.vue │ │ │ │ ├── slider.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── space/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── align.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── split.md │ │ │ │ │ ├── vertical.md │ │ │ │ │ └── wrap.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── space.tsx │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── spin/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── container.md │ │ │ │ │ ├── dot.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── tip.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── dot-loading.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── spin.tsx │ │ │ │ └── style/ │ │ │ │ ├── dot-loading.less │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── split/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ └── nested.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── split.vue │ │ │ │ └── style/ │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── token.less │ │ │ ├── statistic/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── animation.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── countdown.md │ │ │ │ │ └── prefix.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── countdown.vue │ │ │ │ ├── index.ts │ │ │ │ ├── statistic.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── utils.ts │ │ │ ├── steps/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── arrow.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── changeable.md │ │ │ │ │ ├── custom-node.md │ │ │ │ │ ├── description.md │ │ │ │ │ ├── dot.md │ │ │ │ │ ├── error.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── label-placement.md │ │ │ │ │ ├── line-less.md │ │ │ │ │ ├── navigation.md │ │ │ │ │ ├── small-arrow.md │ │ │ │ │ ├── small.md │ │ │ │ │ └── vertical.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── step.vue │ │ │ │ ├── steps.vue │ │ │ │ └── style/ │ │ │ │ ├── arrow.less │ │ │ │ ├── circle.less │ │ │ │ ├── dot.less │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ ├── navigation.less │ │ │ │ └── token.less │ │ │ ├── style/ │ │ │ │ ├── animation/ │ │ │ │ │ ├── fade.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── slide.less │ │ │ │ │ └── zoom.less │ │ │ │ ├── color/ │ │ │ │ │ ├── colors.less │ │ │ │ │ ├── css-variables.less │ │ │ │ │ ├── get-rgb-str.js │ │ │ │ │ ├── palette-dark.js │ │ │ │ │ └── palette.js │ │ │ │ ├── icon.less │ │ │ │ ├── index.less │ │ │ │ ├── mixins/ │ │ │ │ │ ├── icon-hover.less │ │ │ │ │ └── index.less │ │ │ │ ├── normalize.less │ │ │ │ └── theme/ │ │ │ │ ├── component.less │ │ │ │ ├── css-variables.less │ │ │ │ ├── global.less │ │ │ │ └── index.less │ │ │ ├── switch/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── change-intercept.md │ │ │ │ │ ├── color.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── loading.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── text.md │ │ │ │ │ ├── type.md │ │ │ │ │ └── value.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── switch.vue │ │ │ ├── table/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom-dom.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── drag-handle.md │ │ │ │ │ ├── drag-row.md │ │ │ │ │ ├── editable.md │ │ │ │ │ ├── ellipsis.md │ │ │ │ │ ├── expand.md │ │ │ │ │ ├── filter.md │ │ │ │ │ ├── fixed-group.md │ │ │ │ │ ├── fixed.md │ │ │ │ │ ├── group.md │ │ │ │ │ ├── lazy-load.md │ │ │ │ │ ├── props.md │ │ │ │ │ ├── radio.md │ │ │ │ │ ├── resize.md │ │ │ │ │ ├── row-selection.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── sort.md │ │ │ │ │ ├── span.md │ │ │ │ │ ├── sticky.md │ │ │ │ │ ├── subtree.md │ │ │ │ │ ├── summary.md │ │ │ │ │ └── virtual-list.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-column-filter.ts │ │ │ │ │ ├── use-column-resize.ts │ │ │ │ │ ├── use-column-sorter.ts │ │ │ │ │ ├── use-drag.ts │ │ │ │ │ ├── use-expand.ts │ │ │ │ │ ├── use-filter.ts │ │ │ │ │ ├── use-pagination.ts │ │ │ │ │ ├── use-row-selection.ts │ │ │ │ │ ├── use-sorter.ts │ │ │ │ │ └── use-span.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── filters-popup.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── table-col-group.vue │ │ │ │ ├── table-column.tsx │ │ │ │ ├── table-operation-td.tsx │ │ │ │ ├── table-operation-th.tsx │ │ │ │ ├── table-tbody.tsx │ │ │ │ ├── table-td.tsx │ │ │ │ ├── table-th.tsx │ │ │ │ ├── table-thead.tsx │ │ │ │ ├── table-tr.tsx │ │ │ │ ├── table.tsx │ │ │ │ └── utils.ts │ │ │ ├── tabs/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── editable.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── lazy.md │ │ │ │ │ ├── position.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── trigger.md │ │ │ │ │ └── type.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── rtl.less │ │ │ │ │ ├── token.less │ │ │ │ │ └── vertical.less │ │ │ │ ├── tab-pane.vue │ │ │ │ ├── tabs-button.tsx │ │ │ │ ├── tabs-nav-ink.vue │ │ │ │ ├── tabs-nav.tsx │ │ │ │ ├── tabs-tab.vue │ │ │ │ ├── tabs.tsx │ │ │ │ └── utils.ts │ │ │ ├── tag/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── bordered.md │ │ │ │ │ ├── checkable.md │ │ │ │ │ ├── closeable.md │ │ │ │ │ ├── color.md │ │ │ │ │ ├── dynamically.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── loading.md │ │ │ │ │ └── size.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── tag.vue │ │ │ ├── textarea/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── auto-size.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── status.md │ │ │ │ │ └── word-limit.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.ts │ │ │ │ ├── textarea.vue │ │ │ │ └── utils.ts │ │ │ ├── time-picker/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── default-value.md │ │ │ │ │ ├── disable-confirm.md │ │ │ │ │ ├── disabled-time.md │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── extra.md │ │ │ │ │ ├── format.md │ │ │ │ │ ├── prefix.md │ │ │ │ │ ├── rangepicker.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── step.md │ │ │ │ │ └── use-12-hours.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-is-disabled-time.ts │ │ │ │ │ ├── use-time-format.ts │ │ │ │ │ ├── use-time-list.ts │ │ │ │ │ └── use-time-state.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── panel.vue │ │ │ │ ├── range-panel.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── time-column.vue │ │ │ │ ├── time-picker.vue │ │ │ │ └── utils/ │ │ │ │ └── index.ts │ │ │ ├── timeline/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── direction.md │ │ │ │ │ ├── dot.md │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── label.md │ │ │ │ │ ├── mode.md │ │ │ │ │ ├── pending.md │ │ │ │ │ ├── type.md │ │ │ │ │ └── vertical.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── item.vue │ │ │ │ ├── style/ │ │ │ │ │ ├── horizontal.less │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── timeline.tsx │ │ │ ├── tooltip/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── color.md │ │ │ │ │ ├── mini.md │ │ │ │ │ └── position.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── tooltip.vue │ │ │ ├── transfer/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── custom-header.md │ │ │ │ │ ├── custom.md │ │ │ │ │ ├── one-way.md │ │ │ │ │ ├── pagination.md │ │ │ │ │ ├── search.md │ │ │ │ │ ├── simple.md │ │ │ │ │ └── tree.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── transfer-list-item.tsx │ │ │ │ ├── transfer-view.vue │ │ │ │ └── transfer.vue │ │ │ ├── tree/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── block-node.md │ │ │ │ │ ├── checkable.md │ │ │ │ │ ├── checked-strategy.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── draggable.md │ │ │ │ │ ├── field-names.md │ │ │ │ │ ├── icons.md │ │ │ │ │ ├── load-more.md │ │ │ │ │ ├── multiple.md │ │ │ │ │ ├── node-icon.md │ │ │ │ │ ├── render-extra.md │ │ │ │ │ ├── search.md │ │ │ │ │ ├── show-line.md │ │ │ │ │ ├── size.md │ │ │ │ │ └── virtual.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── check-utils.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── tree-data.ts │ │ │ │ ├── base-node.vue │ │ │ │ ├── context.ts │ │ │ │ ├── expand-transition.vue │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-checked-state.ts │ │ │ │ │ ├── use-draggable.ts │ │ │ │ │ ├── use-node-key.ts │ │ │ │ │ ├── use-tree-context.ts │ │ │ │ │ └── use-tree-data.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── node-switcher.vue │ │ │ │ ├── node.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── transition-node-list.vue │ │ │ │ ├── tree.vue │ │ │ │ └── utils/ │ │ │ │ ├── check-utils.ts │ │ │ │ ├── index.ts │ │ │ │ └── tree-data.ts │ │ │ ├── tree-select/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── checkable.md │ │ │ │ │ ├── checked-strategy.md │ │ │ │ │ ├── control.md │ │ │ │ │ ├── dropdown-slots.md │ │ │ │ │ ├── fallback.md │ │ │ │ │ ├── field-names.md │ │ │ │ │ ├── label-in-value.md │ │ │ │ │ ├── load-more.md │ │ │ │ │ ├── multiple.md │ │ │ │ │ ├── popup-visible.md │ │ │ │ │ ├── search-remote.md │ │ │ │ │ ├── search.md │ │ │ │ │ ├── size.md │ │ │ │ │ ├── trigger-element.md │ │ │ │ │ └── virtual.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-filter-tree-node.ts │ │ │ │ │ └── use-selected-state.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── panel.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── tree-select.vue │ │ │ ├── trigger/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── align-point.md │ │ │ │ │ ├── arrow.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── nest.md │ │ │ │ │ ├── scroll.md │ │ │ │ │ ├── translate.md │ │ │ │ │ └── triggers.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── trigger.tsx │ │ │ │ └── utils.ts │ │ │ ├── typography/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── ellipsis.md │ │ │ │ │ ├── operations.md │ │ │ │ │ ├── paragraph.md │ │ │ │ │ ├── text.md │ │ │ │ │ └── title.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ └── index.test.ts │ │ │ │ ├── base.tsx │ │ │ │ ├── edit-content.vue │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── operations.vue │ │ │ │ ├── paragraph.tsx │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── text.tsx │ │ │ │ ├── title.tsx │ │ │ │ ├── typography.vue │ │ │ │ └── utils/ │ │ │ │ ├── getInnerText.tsx │ │ │ │ └── measure.tsx │ │ │ ├── upload/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── avatar.md │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── before-remove.md │ │ │ │ │ ├── before-upload.md │ │ │ │ │ ├── custom-button.md │ │ │ │ │ ├── custom-icon.md │ │ │ │ │ ├── directory.md │ │ │ │ │ ├── draggable.md │ │ │ │ │ ├── limit.md │ │ │ │ │ ├── picture-card.md │ │ │ │ │ ├── picture-list.md │ │ │ │ │ ├── request.md │ │ │ │ │ ├── submit.md │ │ │ │ │ └── upload-list.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interfaces.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ ├── upload-button.tsx │ │ │ │ ├── upload-list-item.tsx │ │ │ │ ├── upload-list.tsx │ │ │ │ ├── upload-picture-item.tsx │ │ │ │ ├── upload-progress.tsx │ │ │ │ ├── upload.tsx │ │ │ │ └── utils.ts │ │ │ ├── verification-code/ │ │ │ │ ├── CHANGELOG.md │ │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ │ ├── README.en-US.md │ │ │ │ ├── README.zh-CN.md │ │ │ │ ├── TEMPLATE.md │ │ │ │ ├── __demo__/ │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── form.md │ │ │ │ │ ├── formatter.md │ │ │ │ │ ├── masked.md │ │ │ │ │ ├── separator.md │ │ │ │ │ └── status.md │ │ │ │ ├── __test__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ └── demo.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.less │ │ │ │ └── verification-code.tsx │ │ │ └── watermark/ │ │ │ ├── CHANGELOG.md │ │ │ ├── CHANGELOG.zh-CN.md │ │ │ ├── README.en-US.md │ │ │ ├── README.zh-CN.md │ │ │ ├── TEMPLATE.md │ │ │ ├── __demo__/ │ │ │ │ ├── basic.md │ │ │ │ ├── custom.md │ │ │ │ ├── image.md │ │ │ │ └── multiline.md │ │ │ ├── __test__/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ └── demo.test.ts │ │ │ ├── hooks/ │ │ │ │ ├── use-mutation-observer.ts │ │ │ │ └── use-theme.ts │ │ │ ├── index.ts │ │ │ ├── interface.ts │ │ │ ├── style/ │ │ │ │ └── index.ts │ │ │ ├── utils/ │ │ │ │ └── index.ts │ │ │ └── watermark.tsx │ │ ├── global.d.ts │ │ ├── jest.config.js │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── demo-test.ts │ │ └── tsconfig.json │ └── web-vue-storybook/ │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc.js │ ├── .storybook/ │ │ ├── babel.config.js │ │ ├── main.js │ │ └── preview.js │ ├── README.md │ ├── global.d.ts │ ├── package.json │ ├── stories/ │ │ ├── components/ │ │ │ ├── button.vue │ │ │ ├── custom-menu.vue │ │ │ ├── custom-sub-menu.vue │ │ │ ├── date-picker.vue │ │ │ ├── dropdown.tsx │ │ │ ├── form.vue │ │ │ ├── json.ts │ │ │ ├── menu.vue │ │ │ ├── number-input.vue │ │ │ ├── select.tsx │ │ │ ├── space.vue │ │ │ ├── tree-draggable.vue │ │ │ ├── tree-select.vue │ │ │ ├── tree.vue │ │ │ ├── typography.vue │ │ │ └── virtual-list.vue │ │ └── index.stories.ts │ └── tsconfig.json └── pnpm-workspace.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: .eslintignore ================================================ /*.json /*.js ================================================ FILE: .eslintrc.js ================================================ // Adapt to vscode. // This file will be found in the root directory of vscode. // If it cannot be found, it will report an error and cannot run eslint in the editor. module.exports = {}; ================================================ FILE: .gitattributes ================================================ # This file is inspired by https://github.com/alexkaratarakis/gitattributes # # Auto detect text files and perform LF normalization * text=auto # The above will handle all files NOT found below # These files are text and should be normalized (Convert crlf => lf) # Source code *.coffee text *.css text diff=css *.htm text diff=html *.html text diff=html *.inc text *.ini text *.java text *.js text *.jsx text *.less text *.ls text *.map text -diff *.od text *.onlydata text *.php text diff=php *.pl text *.ps1 text eol=crlf *.py text diff=python *.rb text diff=ruby *.sass text *.scm text *.scss text diff=css .husky/* text eol=lf *.sql text *.styl text *.tag text *.ts text *.xml text *.xhtml text diff=html *.md text eol=lf *.vue text eol=lf *.tsx text eol=lf # Scripts *.bash text eol=lf *.fish text eol=lf *.sh text eol=lf *.zsh text eol=lf # These are explicitly windows files and should use crlf *.bat text eol=crlf *.cmd text eol=crlf *.ps1 text eol=crlf # Serialisation *.json text *.toml text *.xml text *.yaml text *.yml text # Documents *.bibtex text diff=bibtex *.doc diff=astextplain *.DOC diff=astextplain *.docx diff=astextplain *.DOCX diff=astextplain *.dot diff=astextplain *.DOT diff=astextplain *.pdf diff=astextplain *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain *.md text diff=markdown *.mdx text diff=markdown *.tex text diff=tex *.adoc text *.textile text *.mustache text *.csv text *.tab text *.tsv text *.txt text *.sql text *.epub diff=astextplain AUTHORS text CHANGELOG text CHANGES text CONTRIBUTING text COPYING text copyright text *COPYRIGHT* text INSTALL text license text LICENSE text NEWS text readme text *README* text TODO text # Graphics *.ai binary *.bmp binary *.eps binary *.gif binary *.gifv binary *.ico binary *.jng binary *.jp2 binary *.jpg binary *.jpeg binary *.jpx binary *.jxr binary *.pdf binary *.png binary *.psb binary *.psd binary # SVG treated as an asset (binary) by default. If you want to treat it as text, # comment-out the following line and uncomment the line after. *.svg binary #*.svg text *.svgz binary *.tif binary *.tiff binary *.wbmp binary *.webp binary # These files are binary and should be left untouched # (binary is a macro for -text -diff) *.class binary *.jar binary *.war binary ## LINTERS .csslintrc text .eslintrc text .jscsrc text .jshintrc text .jshintignore text .stylelintrc text # Configs *.cnf text *.conf text *.config text .editorconfig text .env text .gitattributes text eol=lf .gitconfig text .htaccess text *.lock text -diff package.json text eol=lf package-lock.json text eol=lf -diff *.npmignore text pnpm-lock.yaml text eol=lf -diff .prettierrc text yarn.lock text -diff browserslist text Makefile text makefile text ## HEROKU Procfile text .slugignore text ## AUDIO *.kar binary *.m4a binary *.mid binary *.midi binary *.mp3 binary *.ogg binary *.ra binary ## VIDEO *.3gpp binary *.3gp binary *.as binary *.asf binary *.asx binary *.fla binary *.flv binary *.m4v binary *.mng binary *.mov binary *.mp4 binary *.mpeg binary *.mpg binary *.swc binary *.swf binary *.webm binary ## ARCHIVES *.7z binary *.gz binary *.rar binary *.tar binary *.zip binary ## FONTS *.ttf binary *.eot binary *.otf binary *.woff binary *.woff2 binary # Executables *.exe binary *.pyc binary # Text files where line endings should be preserved *.patch -text # # Exclude files from exporting # .gitattributes export-ignore .gitignore export-ignore .gitkeep export-ignore ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: true contact_links: - name: Create new issue url: https://arco.design/issue-helper?repo=arco-design-vue about: Please use the following link to create a new issue. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Types of changes - [ ] New feature - [ ] Bug fix - [ ] Enhancement - [ ] Component style change - [ ] Typescript definition change - [ ] Documentation change - [ ] Coding style change - [ ] Refactoring - [ ] Test cases - [ ] Continuous integration - [ ] Breaking change - [ ] Others ## Background and context ## Solution ## How is the change tested? ## Changelog | Component | Changelog(CN) | Changelog(EN) | Related issues | | --------- | ------------- | ------------- | -------------- | | | | | | ## Checklist: - [ ] Test suite passes (`npm run test`) - [ ] Provide changelog for relevant changes (e.g. bug fixes and new features) if applicable. - [ ] Changes are submitted to the appropriate branch (e.g. features should be submitted to `feature` branch and others should be submitted to `main` branch) ## Other information ================================================ FILE: .github/workflows/deploy-site-preview.yml ================================================ name: deploy-site-preview on: pull_request: types: [opened, synchronize, reopened] workflow_dispatch: jobs: deploy-preview: permissions: actions: read runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v4 - name: Setup node uses: actions/setup-node@v4 with: node-version: 18 cache: 'pnpm' - name: Get pnpm store directory id: pnpm-cache run: | echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install deps run: pnpm i - run: pnpm run init - name: build site run: NODE_OPTIONS=--max-old-space-size=8192 AssetsPublicPath=/ pnpm run build:site - name: netlify install run: pnpm add netlify-cli -D - name: get PreviewID run: | if ${{ github.event_name == 'pull_request' }}; then echo "PreviewID=${{ github.event.number }}" >> $GITHUB_ENV else echo "PreviewID=main" >> $GITHUB_ENV fi - name: netlify deploy env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} run: netlify deploy --auth $NETLIFY_AUTH_TOKEN --site $NETLIFY_SITE_ID --dir=packages/arco-vue-docs/dist --alias=pr-preview-${{ env.PreviewID }} add-pr-comment: runs-on: ubuntu-latest needs: deploy-preview if: github.event_name == 'pull_request' steps: - name: PR Comment uses: mshick/add-pr-comment@v2 env: PR_NUMBER: ${{ github.event.number }} with: # Message to comment message: | [📚 📚 Site Preview: https://pr-preview-${{ env.PR_NUMBER }}--arco-design-vue.netlify.app](https://pr-preview-${{ env.PR_NUMBER }}--arco-design-vue.netlify.app) image-test: runs-on: ubuntu-latest needs: deploy-preview steps: - name: checkout uses: actions/checkout@v4 with: fetch-depth: 2 - name: Setup pnpm uses: pnpm/action-setup@v4 - name: Setup node uses: actions/setup-node@v4 with: node-version: 18 - name: Get pnpm store directory id: pnpm-cache run: | echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - run: pnpm i - run: pnpm run init - name: get PreviewID run: | if ${{ github.event_name == 'pull_request' }}; then echo "PreviewID=${{ github.event.number }}" >> $GITHUB_ENV else echo "PreviewID=main" >> $GITHUB_ENV fi - name: gen screenshots run: pnpm run test:screenshot --domain=https://pr-preview-${{ env.PreviewID }}--arco-design-vue.netlify.app - name: upload screenshots to argos-cli run: npx @argos-ci/cli upload ./packages/web-vue/__screenshots__ ================================================ FILE: .github/workflows/issue-duplicate.yml ================================================ name: Issue Mark Duplicate on: issue_comment: types: [created, edited] jobs: mark-duplicate: runs-on: ubuntu-latest steps: - name: mark-duplicate uses: actions-cool/issues-helper@v2 with: actions: 'mark-duplicate' token: ${{ secrets.GITHUB_TOKEN }} duplicate-labels: "🔄 Duplicate" close-issue: true ================================================ FILE: .github/workflows/issue-labeled.yml ================================================ name: Issue Labeled on: issues: types: [labeled] permissions: contents: read jobs: issue-labeled: permissions: issues: write pull-requests: write runs-on: ubuntu-latest steps: - name: PR Welcome if: github.event.label.name == '❤️ PR Welcome' || github.event.label.name == '🙏 Help wanted' uses: actions-cool/issues-helper@v3 with: actions: 'create-comment' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | 我们完全同意该提议/反馈,欢迎直接在此仓库创建 Pull Request 来解决这个问题。贡献前请务必阅读[贡献指南](https://github.com/arco-design/arco-design-vue/blob/main/CONTRIBUTING.zh-CN.md),Pull Request 时根据需改动内容填写[预设模板](https://github.com/arco-design/arco-design-vue/blob/main/.github/PULL_REQUEST_TEMPLATE.md),我们会尽快进行 Review,感谢您的贡献! We agree with this suggestion/feedback and welcome to create a Pull Request in this repository to help address the issue. Before contributing, please make sure to read the [Contributing Guide](https://github.com/arco-design/arco-design-vue/blob/main/CONTRIBUTING.md). When submitting a Pull Request, kindly use the appropriate [PR template](https://github.com/arco-design/arco-design-vue/blob/main/.github/PULL_REQUEST_TEMPLATE.md) based on the changes you’re making. We’ll review it as soon as possible. Thank you for your contribution! - name: Need more info if: github.event.label.name == '📄 Need more info' uses: actions-cool/issues-helper@v3 with: actions: 'create-comment' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | 你好 @${{ github.event.issue.user.login }},我们需要你提供更多的信息或复现链接以便于我们帮你排查定位问题。7 天内未跟进此 issue 将会被自动关闭。 Hello @${{ github.event.issue.user.login }}, we need more information or a reproducible link from you to help us investigate and pinpoint the issue. If there is no follow-up within 7 days, this issue will be automatically closed. - name: Invalid if: github.event.label.name == '🙅 Invalid' uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,close-issue' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | 你好 @${{ github.event.issue.user.login }}, 您的 Issue 已被标记为无效而自动关闭,原因可能如下: - 不符合我们的格式要求、可能缺少足够的上下文或关键信息,无法有效解决问题。 - 非 bug 反馈和需求讨论(如询问如何使用等问题)。 - 它可能是已有 Issue 的重复项。请在提交新的 Issue 之前检查现有的 Issue。 可点击加入[Arco Design 飞书用户群](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=0c2qaa71-ed40-40e7-9389-9f3e182011a5)询问,感谢您的理解与配合! ================================================ FILE: .github/workflows/issue-manager.yml ================================================ name: Issue Manager on: schedule: - cron: "0 0 * * *" permissions: contents: read jobs: issue-close: permissions: issues: write pull-requests: write runs-on: ubuntu-latest if: ${{ github.repository_owner == 'arco-design' }} steps: - name: Needs more info uses: actions-cool/issues-helper@v3 with: actions: 'close-issues' labels: '📄 Need more info' inactive-day: 7 body: | 由于该 issue 被标记为需要更多信息,却 7 天未收到回应。现关闭 issue,若有任何问题,可评论回复或点击加入[Arco Design 飞书用户群](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=0c2qaa71-ed40-40e7-9389-9f3e182011a5)询问。 This issue has been marked as needing more information, but there hasn’t been a response for 7 days, so we’re closing it for now. If you have any questions, feel free to comment here or join the [Arco Design Feishu user group](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=0c2qaa71-ed40-40e7-9389-9f3e182011a5) to ask for help. check-inactive: permissions: issues: write pull-requests: write runs-on: ubuntu-latest if: ${{ github.repository_owner == 'arco-design' }} steps: - name: check-inactive uses: actions-cool/issues-helper@v3 with: actions: 'check-inactive' inactive-label: '💤 Inactive' inactive-day: 30 ================================================ FILE: .github/workflows/issue-remove-inactive.yml ================================================ name: Issue Remove Inactive on: issues: types: [edited] issue_comment: types: [created, edited] permissions: contents: read jobs: issue-remove-inactive: permissions: issues: write pull-requests: write runs-on: ubuntu-latest steps: - name: remove inactive if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login uses: actions-cool/issues-helper@v3 with: actions: 'remove-labels' issue-number: ${{ github.event.issue.number }} labels: '💤 Inactive, 📄 Need more info' ================================================ FILE: .github/workflows/pr_check.yml ================================================ name: pr_check on: pull_request: types: [ opened, synchronize, reopened ] jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v4 - name: Setup node uses: actions/setup-node@v4 with: node-version: 18 cache: 'pnpm' - name: Get pnpm store directory id: pnpm-cache run: | echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - run: pnpm i --frozen-lockfile - run: pnpm run init - name: mock time uses: szenius/set-timezone@v1.0 with: timezoneLinux: 'Asia/Singapore' timezoneMacos: 'Asia/Singapore' timezoneWindows: 'Singapore Standard Time' - name: run test run: pnpm run test ================================================ FILE: .github/workflows/release.yml ================================================ name: auto-release on: create jobs: release: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v2 - name: Get the version id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: create-release if: github.event.ref_type == 'tag' uses: arco-design/arco-auto-release@main with: token: ${{ secrets.GITHUB_TOKEN }} changelogPaths: 'packages/web-vue/CHANGELOG.md,packages/web-vue/CHANGELOG.zh-CN.md' tagName: ${{ steps.get_version.outputs.VERSION }} ================================================ FILE: .gitignore ================================================ .idea/ # .vscode/ node_modules/ storybook-static/ **/.DS_Store package-lock.json lerna-debug.log npm-debug.log pnpm-debug.log package-lock.json yarn.lock ================================================ FILE: .husky/commit-msg ================================================ #!/bin/sh . "$(dirname "$0")/_/husky.sh" pnpm exec commitlint --edit $1 ================================================ FILE: .husky/pre-commit ================================================ #!/bin/sh . "$(dirname "$0")/_/husky.sh" pnpm -r run lint-staged ================================================ FILE: .npmrc ================================================ shell-emulator=true # 提升依赖项 shamefully-hoist=true ================================================ FILE: .nvmrc ================================================ v18 ================================================ FILE: .prettierrc.js ================================================ module.exports = { tabWidth: 2, semi: true, printWidth: 80, singleQuote: true, quoteProps: 'consistent', endOfLine: 'auto', htmlWhitespaceSensitivity: 'strict', }; ================================================ FILE: .vscode/settings.json ================================================ { "eslint.workingDirectories": [{ "pattern": "./packages/*/" }] } ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pengjiyuan@bytendance.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ================================================ FILE: CONTRIBUTING.md ================================================ > English | [简体中文](./CONTRIBUTING.zh-CN.md) # Contributing Thank you for taking your time to contribute and make this project better! Here are some guidelines to help you get started. Please make sure to take a moment and read through them before submitting your contributions. ## Code of Conduct This project is governed by the [Contributor Covenant Code of Conduct](./CODE_OF_CONDUCT.md). By participating, you are expected to adhere to it. ## Open Development All work happens directly on GitHub. Both core team members and external contributors send pull requests which go through the same review process. ## Semantic Versioning This project follows semantic versioning. We release patch versions for bug fixes or other changes that do not change the behavior of the API, minor versions for new features that are backward-compatible, and major versions for any breaking changes. Every significant change is documented in the changelog file. ## Reporting Issues We use [Github issues](https://github.com/arco-design/arco-design-vue/issues) for bug reports and feature requests. Before reporting an issue, please make sure you have searched for similar [issues](https://github.com/arco-design/arco-design-vue/issues) as they may have been already answered or being fixed. A new issue should be submitted via [issue helper](https://arco.design/issue-helper?repo=arco-design-vue). For bug reporting, please include the minimum code that can be used to reproduce the problem. For feature request, please specify what changes you want and what behavior you expect. ## Sending a pull request This project uses [pnpm](https://pnpm.io/) for package management. Please install Yarn before development. ### Contribution Process - **Claim an Issue**: Create an issue on GitHub and claim it (or directly claim an existing issue) to let others know you are working on it, preventing duplicate efforts. - **Development**: After preparing for development, proceed with bug fixes or feature implementation. - **Add Unit Tests**: Write unit tests for your code changes and ensure all test cases pass, aiming for reasonable test coverage. - **Update Snapshots**: If your changes affect the component’s DOM structure, class names, or add/remove demos, update the snapshots accordingly. - **Generate Documentation**: If the component API is modified, run `pnpm run docgen` to regenerate the documentation. - **Submit a Pull Request** ### Development 1. Fork [this repository](https://github.com/arco-design/arco-design-vue) and create a branch from `main`. - For new features, submit a pull request to the `feature` branch. - For other changes, submit to the `main` branch. ```bash git clone git@github.com:arco-design/arco-design-vue.git ``` 2. Install the dependencies of each package in `workspaces`. ```bash pnpm install ``` 3. Initialize the project. ```bash pnpm run init ``` 4. Start and preview the site. ```bash pnpm run start ``` ```bash # Start Storybook (optional, as debugging can also be done on the official website) pnpm run storybook ``` 5. Make changes to the codebase. If applicable, ensure that you have written the corresponding tests. 6. Make sure all tests pass after running `pnpm run test`. 7. Commit your changes, adhering to the [Commit Guidelines](#commit-guidelines). 8. Open a new pull request, [referencing corresponding issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) if available. ## Commit Guidelines Commit messages are required to follow the [conventional-changelog standard](https://www.conventionalcommits.org/en/v1.0.0/): ```bash [optional scope]: [optional body] [optional footer(s)] ``` ### Commit types The following is a list of commit types: - feat: A new feature or functionality - fix: A bug fix - docs: Documentation only changes - style: Code formatting or component style changes - refactor: Code changes that neither fixes a bug nor adds a feature. - perf: Improve performance. - test: Add missing or correct existing tests. - chore: Other commits that don’t modify src or test files. ## Arco-Vue Repository Structure This repository is managed by pnpm workspace and includes the following packages: 1. `web-vue`: UI component library 2. `vue-site`: Component documentation site 3. `arco-vue-scripts`: Component scripts 4. `arco-vue-md-loader`: Webpack loader for markdown parsing 5. `arco-vue-site-nav`: Navigation bar of documentation site (using React materials) ### Web-Vue Component Directory > components/componentName ``` ├── README.zh-CN.md (Note:Don't edit this file, it's generated by script) ├── README.en-US.md (Note:Don't edit this file, it's generated by script) ├── TEMPLATE.md (Template used to generate README file) ├── __test__ │ ├── __snapshots__ │ │ └── demo.test.js.snap (Snapshot) │ ├── demo.test.ts (Snapshot test) │ └── index.test.ts (Unit test) ├── __demo__ (Demos for each component) │ ├── basic.md │ └── advanced.md ├── index.tsx(Component export) └── style └── index.less(Component style) └── index.ts (Component style entry) ``` Please note that if you make changes that will affect README (e.g. API changes), make sure to run `npm run docgen` to update README of the component. For scripts related to the component library, please run under the `web-vue` directory. ## License By contributing your code to the repository, you agree to license your contribution under the [MIT license](./LICENSE). ================================================ FILE: CONTRIBUTING.zh-CN.md ================================================ > [English](./CONTRIBUTING.md) | 简体中文 # 贡献指南 感谢你的宝贵时间。你的贡献将使这个项目变得更好!在提交贡献之前,请务必花点时间阅读下面的入门指南。 ## 行为准则 该项目有一份 [行为准则](./CODE_OF_CONDUCT.md),希望参与项目的贡献者都能严格遵守。 ## 透明的开发 所有工作都直接透明地在 GitHub 上进行。核心团队成员和外部贡献者的 pull requests 都需要经过相同的 review 流程。 ## 语义化版本 该项目遵循语义化版本。我们对重要的漏洞修复发布修订号,对新特性或不重要的变更发布次版本号,对重大且不兼容的变更发布主版本号。 每个重大更改都将记录在 changelog 中。 ## 报告 Issues 我们使用 [Github issues](https://github.com/arco-design/arco-design-vue/issues) 进行 bug 报告和新 feature 建议。在报告 bug 之前,请确保已经搜索过类似的 [问题](https://github.com/arco-design/arco-design-vue/issues),因为它们可能已经得到解答或正在被修复。新问题应通过 [问题助手](https://arco.design/issue-helper?repo=arco-design-vue) 提交。对于 bug 报告,请包含可用于重现问题的代码。对于新 feature 建议,请指出你想要的更改以及期望的行为。 ## 提交 Pull Request 本项目使用 [pnpm](https://pnpm.io/zh/) 进行多包管理,请在开发前准备好开发环境。 ### 共建流程 - 认领 issue: 在 github 建立 issue 并认领(或直接认领已有 issue),告知大家自己正在修复,避免重复工作。 - 项目开发:在完成开发前准备后,进行 bug 修复或功能开发。 - 添加单测:针对代码变动添加单元测试,确认测试用例通过,尽量保证一定的测试覆盖率。 - 更新快照:如果涉及到组件 dom 层级变动,类名增删或新增/删除了 Demo,快照需要重新生成更新。 - 文档生成:组件 API 存在调整时需执行 `pnpm run docgen` 重新生成文档。 - 提交 PR ### 开发 1. Fork [此仓库](https://github.com/arco-design/arco-design-vue),从 `main` 创建分支。新功能实现请发 pull request 到 `feature` 分支。其他更改发到 `main` 分支。 ```bash git clone git@github.com:arco-design/arco-design-vue.git ``` 2. 安装 `workspaces` 中各个包的依赖。 ```bash pnpm install ``` 3. 初始化项目 ```bash pnpm run init ``` 4. 启动和预览站点 ```bash pnpm run start ``` ```bash # 启动 storybook 。 这里启动不启动都可以,官网也可以调试组件 pnpm run storybook ``` 5. 对代码库进行更改。如果适用的话,请确保写了相应的测试。 6. 确认执行 `pnpm run test` 后所有的测试都是通过的。 7. 提交 git commit, 请同时遵守 [Commit 规范](#commit-指南)。 8. 提交 pull request, 如果有对应的 issue,请进行[关联](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)。 ## Commit 指南 Commit messages 请遵循[conventional-changelog 标准](https://www.conventionalcommits.org/en/v1.0.0/): ```bash <类型>[可选 范围]: <描述> [可选 正文] [可选 脚注] ``` ### Commit 类型 以下是 commit 类型列表: - feat: 新特性或功能 - fix: 缺陷修复 - docs: 文档更新 - style: 代码风格或者组件样式更新 - refactor: 代码重构,不引入新功能和缺陷修复 - perf: 性能优化 - test: 单元测试 - chore: 其他不修改 src 或测试文件的提交 ## Web-Vue 项目结构 本仓库多包管理,包括以下packages: 1. `web-vue`: Vue组件库 2. `vue-site`: Vue组件库文档站 3. `arco-vue-scripts`: Vue组件库脚本 4. `arco-vue-md-loader`: Vue组件库中markdown文档的webpack loader 5. `arco-vue-site-nav`: Vue组件库文档站的顶部导航栏(使用React物料) ### Web-Vue 组件目录 > components/componentName ``` ├── README.zh-CN.md (注意:不要编辑这个文件,它是由脚本自动生成的) ├── README.en-US.md (注意:不要编辑这个文件,它是由脚本自动生成的) ├── TEMPLATE.md (用于生成 README 文件的模板) ├── __test__ │ ├── __snapshots__ │ │ └── demo.test.js.snap │ ├── demo.test.ts (快照测试) │ └── index.test.ts (单元测试) ├── __demo__ (组件演示) │ ├── basic.md │ └── advanced.md ├── index.tsx(组件导出) └── style └── index.less(组件样式) └── index.ts (组件样式导出) ``` 请注意: 如果进行了会影响 README 的变更(例如 API 变更),请确保运行 `pnpm run docgen` 来更新组件的 README。 组件库的相关操作在`web-vue`目录下操作. ## License [MIT 协议](./LICENSE). ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Bytedance, Inc. and its affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================
Arco Design Logo

Arco Design

A comprehensive Vue UI components library based on the [Arco Design](https://arco.design/) system. [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/arco-design/arco-design-vue/blob/main/LICENSE)
English | [简体中文](./README.zh-CN.md)
# Features ## Comprehensive With more than 60 crafted components that you can use out of the box. ## Customizable theme Extensive theme tokens can be customized to build your own theme. Two ways of customization are supported: * [With less-loader](https://arco.design/vue/docs/theme) * [Design Lab](https://arco.design/themes) - Recommended! ## TypeScript friendly All components are written in TypeScript so it's type friendly. # Installation Available as an [npm package](https://www.npmjs.com/package/@arco-design/web-vue) ```bash // with npm npm install @arco-design/web-vue // with yarn yarn add @arco-design/web-vue // with pnpm pnpm add @arco-design/web-vue ``` # Examples ```typescript import { createApp } from 'vue' import ArcoVue from '@arco-design/web-vue'; import App from './App.vue'; import '@arco-design/web-vue/dist/arco.css'; const app = createApp(App); app.use(ArcoVue); app.mount('#app'); ``` # Useful Links * [Documentation website](https://arco.design/) * [Dark mode](https://arco.design/vue/docs/dark) * [Theme customization](https://arco.design/vue/docs/theme) * [Figma component library](https://www.figma.com/file/FVu1DydEeXvJqXrkOb90Oi/ArcoDesign%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1_2.0?node-id=5472%3A308) * [Awesome Arco](https://github.com/arco-design/awesome-arco) # Ecosystems | Project | Description | | --------------------- | ------------------------------------------------------- | | [React Component Library] | A comprehensive React UI components library based on the Arco Design system | | [Design Lab] | A platform to create and manage your themes with ease. | | [Material Market] | A platform that provides massive high-quality customized materials to greatly boost development efficiency. | | [Icon Box] | One-stop platform to manage your icons. | | [Arco Pro] | A solution to quickly building applications from scratch. | [React Component Library]: https://arco.design/react/docs/start [Design Lab]: https://arco.design/themes [Material Market]: https://arco.design/material [Icon Box]: https://arco.design/iconbox [Arco Pro]: https://arco.design/pro/ # Contributing Developers interested in contributing should read the [Code of Conduct](./CODE_OF_CONDUCT.md) and the [Contributing Guide](./CONTRIBUTING.md). Thank you to all the people who already contributed to ArcoDesign! # License Ths project is [MIT licensed](./LICENSE). ================================================ FILE: README.zh-CN.md ================================================
Arco Design Logo

Arco Design

基于 [Arco Design](https://arco.design/) 的 Vue UI 组件库。 [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/arco-design/arco-design-vue/blob/main/LICENSE)
[English](./README.md) | 简体中文
# 特性 ## 全面 60多个开箱即用的高质量组件, 可以覆盖绝大部份的业务场景。 ## 主题配置 海量的样式 tokens, 支持全局以及组件级别的主题配置。有以下2种方式可以定制主题: * [Less-loader](https://arco.design/vue/docs/theme) * [风格配置平台](https://arco.design/themes) - 推荐! ## TypeScript 友好 所有组件都是用 TypeScript 编写的,所以天然的类型友好。 # 安装 [npm package](https://www.npmjs.com/package/@arco-design/web-vue) ```bash // npm npm install @arco-design/web-vue // yarn yarn add @arco-design/web-vue // pnpm pnpm add @arco-design/web-vue ``` # 例子 ```typescript import { createApp } from 'vue' import ArcoVue from '@arco-design/web-vue'; import App from './App.vue'; import '@arco-design/web-vue/dist/arco.css'; const app = createApp(App); app.use(ArcoVue); app.mount('#app'); ``` # 相关链接 * [官网](https://arco.design/) * [暗黑模式](https://arco.design/vue/docs/dark) * [主题配置](https://arco.design/vue/docs/theme) * [Figma 设计资源](https://www.figma.com/file/FVu1DydEeXvJqXrkOb90Oi/ArcoDesign%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1_2.0?node-id=5472%3A308) * [Awesome Arco](https://github.com/arco-design/awesome-arco) # 生态 | 项目 | 介绍 | | --------------------- | ------------------------------------------------------- | | [React 组件库] | 基于 [Arco Design](https://arco.design/) 的 React UI 组件库。 | | [风格配置平台] | 精确到组件级的主题视觉配置平台 | | [物料平台] | 丰富可共享的业务定制物料,让效率突破猛进 | | [图标平台] | 一站式图标管理平台 | | [Arco Pro] | 快速构建中后台的前端解决方案 | [React 组件库]: https://arco.design/react/docs/start [风格配置平台]: https://arco.design/themes [物料平台]: https://arco.design/material [图标平台]: https://arco.design/iconbox [Arco Pro]: https://arco.design/pro/ # 参与贡献 贡献之前请先阅读 [行为准则](./CODE_OF_CONDUCT.md) 和 [贡献指南](./CONTRIBUTING.zh-CN.md)。 感谢所有为 ArcoDesign 做过贡献的人! # License [MIT 协议](./LICENSE) ================================================ FILE: commitlint.config.js ================================================ module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'subject-case': [0], 'type-enum': [ 2, 'always', [ 'build', 'chore', 'ci', 'docs', 'feat', 'fix', 'enhance', 'refactor', 'revert', 'style', 'test', ], ], }, }; ================================================ FILE: package.json ================================================ { "name": "arco-design-vue-monorepo", "description": "Arco Design Vue 2.0 Monorepo", "private": true, "scripts": { "postinstall": "husky install", "init": "pnpm -F @arco-design/arco-changelog -F @arco-design/vite-plugin-arco-vue-docs -F @arco-design/arco-vue-scripts run build && pnpm i && pnpm -F @arco-design/web-vue run init", "start": "pnpm --filter @arco-design/arco-vue-docs run start", "build:site": "pnpm --filter @arco-design/arco-vue-docs run build", "test:screenshot": "pnpm --filter @arco-design/web-vue run test:screenshot", "build:component": "pnpm --filter @arco-design/web-vue run build", "docgen": "pnpm --filter @arco-design/web-vue run docgen", "clean": "pnpm -r exec rimraf dist node_modules", "test": "pnpm --filter @arco-design/web-vue run test", "storybook": "pnpm --filter @arco-design/web-vue-storybook run storybook" }, "packageManager": "pnpm@9.5.0", "workspaces": [ "packages/*" ], "author": "ArcoDesign Team", "license": "MIT", "devDependencies": { "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^12.1.4", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-config-prettier": "^8.10.0", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-prettier": "^3.4.1", "eslint-plugin-vue": "^7.20.0", "husky": "^7.0.4", "lint-staged": "^10.5.4", "prettier": "^2.8.8", "rimraf": "^6.0.1", "stylelint": "^13.13.1", "stylelint-config-prettier": "^8.0.2", "stylelint-config-rational-order": "^0.1.2", "stylelint-config-standard": "^20.0.0", "stylelint-order": "^4.1.0", "typescript": "^4.9.5" }, "pnpm": { "peerDependencyRules": { "ignoreMissing": [ "react-dom" ] } } } ================================================ FILE: packages/arco-changelog/.eslintignore ================================================ node_modules/* dist/* /*.json /*.js ================================================ FILE: packages/arco-changelog/.eslintrc.js ================================================ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { sourceType: 'module', ecmaVersion: 2020, }, env: { node: true, }, plugins: ['@typescript-eslint'], extends: [ // Airbnb JavaScript Style Guide https://github.com/airbnb/javascript 'airbnb-base', 'plugin:@typescript-eslint/recommended', 'plugin:import/typescript', 'plugin:prettier/recommended', ], settings: { 'import/resolver': { typescript: { project: './tsconfig.json', }, }, }, rules: { 'prettier/prettier': 1, '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/explicit-module-boundary-types': 0, '@typescript-eslint/no-non-null-assertion': 0, '@typescript-eslint/no-empty-function': 1, '@typescript-eslint/ban-ts-comment': 0, 'import/extensions': [ 'error', 'ignorePackages', { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }, ], 'import/no-extraneous-dependencies': 0, 'import/no-unresolved': [2, { caseSensitive: false }], 'import/prefer-default-export': 0, 'no-underscore-dangle': 0, 'no-nested-ternary': 0, 'no-shadow': 0, 'prefer-template': 1, 'no-param-reassign': 0, 'no-plusplus': 0, 'no-use-before-define': 0, 'no-restricted-syntax': 0, 'no-empty': [2, { allowEmptyCatch: true }], 'no-bitwise': 0, 'no-return-assign': 0, 'no-unused-expressions': [ 'error', { allowShortCircuit: true, allowTernary: true }, ], 'no-continue': 0, }, }; ================================================ FILE: packages/arco-changelog/.gitignore ================================================ .idea/ .vscode/ dist/ node_modules/ **/.DS_Store ================================================ FILE: packages/arco-changelog/.prettierrc.js ================================================ module.exports = { tabWidth: 2, semi: true, printWidth: 80, singleQuote: true, quoteProps: 'consistent', endOfLine: 'auto', htmlWhitespaceSensitivity: 'strict', }; ================================================ FILE: packages/arco-changelog/README.md ================================================ # Arco Changelog A simple github changelog generator ## Installation ``` npm install @arco-design/arco-changelog ``` ## Command + `arco-changelog` 生成日志文件 + `arco-changelog template` + `--gitlab` 生成 Gitlab 项目的 MR 模板 在项目中创建 Github 的 Pull Request 模板 ## Usage 1. Create a 'changelog.config.js' file and fill in the necessary config. You can find all configuration properties below ```js // changelog.config.js module.exports = { repo: 'arco-design/arco-design-vue' } ``` 2. run `arco-changelog` ## Config Options ### repo + Type: string + Required 用于获取 Pull Request 的项目地址 ### type + Type: String + Default: "github" 指定项目仓库的类型 ### merged + Type: boolean + Default: true 是否只获取合并过的 PR ### requestConfig + Type: Function `(config: { repo: string; version: string; merged: boolean; }) => AxiosRequestConfig` + Default: undefined 自定义请求信息,返回结果可参考 [axios](https://github.com/axios/axios#request-config) ### emitFiles + Type: Function `(changelog: Changelog) => EmitFile[]` + Default: undefined 生成更新日志文件的方法 changelog 工具使用 [nunjucks](https://mozilla.github.io/nunjucks/) 作为模板引擎。返回数据中的 `template` 字段指定模板文件的位置,`data` 字段指定模板数据 ### filename + Type: Object `{ zh: string; en: string }` + Default: undefined 指定默认配置生成日志文件的文件名,分为中英文文件。例如:`{ zh: 'changelog/CHANGELOG.zh.md'; en: 'changelog/CHANGELOG.en.md' }` ```ts export interface EmitFile { file: string; template: string; data: Record; } export interface Changelog { version: string; date: string; list: ChangelogData[]; } export interface ChangelogData { type: string; pr: PullRequest; issues?: string[]; [key: string]: any; } export interface PullRequest { id: number; url: string; } ``` ### typeDict + Type: Object + Default: typeDict 更新日志的类型字典 ```js const typeDict = { feature: 'New feature', bugfix: 'Bug fix', docs: 'Documentation change', refactor: 'Refactoring', style: 'Component style change', enhancement: 'Enhancement', test: 'Test cases', ci: 'Continuous integration', typescript: 'Typescript definition change', attention: 'Breaking change', } ``` ### keyDict + Type: Object + Default: keyDict 更新日志数据的 key 所对应的表格标题字典 ```js const keyDict = { type: 'Type', component: 'Component', changelogZh: 'Changelog(CN)', changelogEn: 'Changelog(EN)', issues: 'Related issues', } ``` ================================================ FILE: packages/arco-changelog/copy-template.js ================================================ #!/usr/bin/env node const fs = require('fs-extra'); fs.copySync('src/vue/template.en-US.njk', 'dist/vue/template.en-US.njk', { overwrite: true, }); fs.copySync('src/vue/template.zh-CN.njk', 'dist/vue/template.zh-CN.njk', { overwrite: true, }); fs.copySync( 'src/default/template.en-US.njk', 'dist/default/template.en-US.njk', { overwrite: true, } ); fs.copySync( 'src/default/template.zh-CN.njk', 'dist/default/template.zh-CN.njk', { overwrite: true, } ); fs.copySync('src/.github', 'dist/.github', { overwrite: true, }); fs.copySync('src/.gitlab', 'dist/.gitlab', { overwrite: true, }); ================================================ FILE: packages/arco-changelog/package.json ================================================ { "name": "@arco-design/arco-changelog", "version": "0.3.2", "description": "Arco Changelog", "author": "ArcoDesign Team", "license": "MIT", "main": "dist/index.js", "bin": "dist/cmd.js", "files": [ "dist" ], "repository": { "type": "git", "url": "git+https://github.com/arco-design/arco-design-vue.git" }, "scripts": { "dev": "tsc --watch", "build": "tsc && node copy-template.js", "lint-staged": "npx lint-staged" }, "lint-staged": { "*.{js,ts,jsx,tsx}": [ "eslint --fix", "prettier --write" ] }, "devDependencies": { "@types/fs-extra": "^9.0.13", "@types/inquirer": "^7.3.3", "@types/nunjucks": "^3.2.6", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-config-prettier": "^8.10.0", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-prettier": "^3.4.1", "prettier": "^2.8.8", "ts-node": "^10.9.2" }, "dependencies": { "axios": "^0.21.4", "chalk": "^4.1.2", "commander": "^7.2.0", "comment-parser": "^1.4.1", "fast-glob": "^3.3.3", "fs-extra": "^9.1.0", "glob": "^7.2.3", "inquirer": "^8.2.6", "moment": "^2.30.1", "nunjucks": "^3.2.4", "ora": "^5.4.1", "typescript": "^4.9.5" } } ================================================ FILE: packages/arco-changelog/src/.github/PULL_REQUEST_TEMPLATE.md ================================================ ## Type of changes - [ ] New feature - [ ] Bug fix - [ ] Enhancement - [ ] Component style change - [ ] Typescript definition change - [ ] Documentation change - [ ] Coding style change - [ ] Refactoring - [ ] Test cases - [ ] Continuous integration - [ ] Breaking change - [ ] Others ## Background and context ## Solution ## How is the change tested? ## Changelog | Component | Changelog(CN) | Changelog(EN) | Related issues | | --------- | ------------- | ------------- | -------------- | | | | | | ## Checklist: - [ ] Test suite passes (`npm run test`) - [ ] Provide changelog for relevant changes (e.g. bug fixes and new features) if applicable. - [ ] Changes are submitted to the appropriate branch (e.g. features should be submitted to `feature` branch and others should be submitted to `main` branch) ## Other information ================================================ FILE: packages/arco-changelog/src/.gitlab/merge_request_templates/CHANGELOG.md ================================================ ## Type of changes - [ ] New feature - [ ] Bug fix - [ ] Enhancement - [ ] Component style change - [ ] Typescript definition change - [ ] Documentation change - [ ] Coding style change - [ ] Refactoring - [ ] Test cases - [ ] Continuous integration - [ ] Breaking change - [ ] Others ## Background and context ## Solution ## How is the change tested? ## Changelog | Component | Changelog(CN) | Changelog(EN) | Related issues | | --------- | ------------- | ------------- | -------------- | | | | | | ## Checklist: - [ ] Test suite passes (`npm run test`) - [ ] Provide changelog for relevant changes (e.g. bug fixes and new features) if applicable. - [ ] Changes are submitted to the appropriate branch (e.g. features should be submitted to `feature` branch and others should be submitted to `main` branch) ## Other information ================================================ FILE: packages/arco-changelog/src/changelog.ts ================================================ import marked, { Tokens } from 'marked'; import { invertKeyValues } from './utils/invert'; import { ChangelogData } from './interface'; export const getChangelogList = ( content: string, config: { pr: any; typeDict: Record; keyDict: Record; } ) => { const _content = content.replace(/\r\n/g, '\n'); const _typeDict = invertKeyValues(config.typeDict); const _keyDict = invertKeyValues(config.keyDict); const typeRule = new RegExp( '##\\s*Types? of changes.+?\\[\\s*[xX]\\s*]\\s*(.+?)(?:\\n|$)', 'si' ); const typeMatch = _content.match(typeRule)?.[1].trim(); const defaultType = typeMatch && _typeDict[typeMatch]; const rule = new RegExp('##\\s*Changelog\\n(.+?)(?:##|$)', 'si'); const match = _content.match(rule)?.[1]; if (!match) return undefined; const tokens = marked.lexer(match); const table = tokens.filter( (token) => token.type === 'table' )[0] as Tokens.Table; if (!table) return undefined; const keys = table.header.map((header) => { return _keyDict[header]; }); return table.cells.reduce((list, cur) => { const data = cur.reduce( (data, value, index) => { const key = keys[index]; if (key === 'type') { data[key] = _typeDict[value]; } else if (key === 'issues') { data[key] = value .split(',') .map((item) => item.match(/#\d+/)?.[0]) .filter((item) => Boolean(item)) as string[]; } else { data[key] = value; } return data; }, { type: defaultType, pr: config.pr, } as ChangelogData ); list.push(data); return list; }, [] as ChangelogData[]); }; ================================================ FILE: packages/arco-changelog/src/cmd.ts ================================================ #!/usr/bin/env node import { Command } from 'commander'; import fs from 'fs-extra'; import path from 'path'; import { changelog } from './index'; import { run } from './copy-github'; const program = new Command(); const packageContent = fs.readFileSync( path.resolve(__dirname, '../package.json'), 'utf8' ); const packageData: any = JSON.parse(packageContent); program .name('arco-changelog') .version(packageData.version) .action(async () => { await changelog(); }) .command('template') .option('--gitlab', 'generate gitlab template') .action(async ({ gitlab }) => { run({ gitlab }); }); program.parse(process.argv); ================================================ FILE: packages/arco-changelog/src/config.ts ================================================ import path from 'path'; import fs from 'fs-extra'; import { ChangelogConfig } from './interface'; import { getEmitFiles } from './default/emit-files'; import vueConfig from './vue/vue.config'; export const typeDict = { feature: 'New feature', bugfix: 'Bug fix', docs: 'Documentation change', refactor: 'Refactoring', style: 'Component style change', enhancement: 'Enhancement', test: 'Test cases', ci: 'Continuous integration', typescript: 'Typescript definition change', attention: 'Breaking change', }; export const keyDict = { type: 'Type', component: 'Component', changelogZh: 'Changelog(CN)', changelogEn: 'Changelog(EN)', issues: 'Related issues', }; const defaultConfig: ChangelogConfig = { repo: '', merged: true, type: 'github', emitFiles: getEmitFiles(), typeDict, keyDict, }; export const getConfig = async (): Promise> => { const config = { ...defaultConfig } as Required; const filename = path.resolve(process.cwd(), 'changelog.config.js'); try { await fs.access(filename); const data = (await import(filename)).default as ChangelogConfig; if (data.arcoComponent === 'vue') { Object.assign(config, vueConfig); } Object.assign(config, data); if (data.filename) { config.emitFiles = getEmitFiles({ filename: data.filename }); } } catch (err) { console.log(err); } return config; }; ================================================ FILE: packages/arco-changelog/src/copy-github.js ================================================ import path from 'path'; import fs from 'fs-extra'; export const run = ({ gitlab }) => { if (gitlab) { fs.copySync( path.resolve(__dirname, '.gitlab'), path.resolve(process.cwd(), '.gitlab'), { overwrite: true, } ); } else { fs.copySync( path.resolve(__dirname, '.github'), path.resolve(process.cwd(), '.github'), { overwrite: true, } ); } }; ================================================ FILE: packages/arco-changelog/src/default/emit-files.ts ================================================ import path from 'path'; import { Changelog, EmitFile } from '../interface'; export const getEmitFiles = (config?: any) => { return (changelog: Changelog): EmitFile[] => { const allCN: Record = {}; const addEN: Record = {}; for (const item of changelog.list) { const contentCN = `${item.changelogZh} ([#${item.pr.id}](${item.pr.url}))`; const contentEN = `${item.changelogEn} ([#${item.pr.id}](${item.pr.url}))`; addAll({ ...item, content: contentCN }, allCN); addAll({ ...item, content: contentEN }, addEN); } return [ { file: config?.filename?.zh ?? 'CHANGELOG.zh-CN.md', template: path.resolve(__dirname, 'template.zh-CN.njk'), data: { version: changelog.version, date: changelog.date, ...allCN }, }, { file: config?.filename?.en ?? 'CHANGELOG.md', template: path.resolve(__dirname, 'template.en-US.njk'), data: { version: changelog.version, date: changelog.date, ...addEN }, }, ]; }; }; const addAll = (data: any, changelog: any) => { if (!changelog[data.type]) { changelog[data.type] = []; } if (!data.component || data.component === 'common') { changelog[data.type].push(data.content); } else { changelog[data.type].push(`**${data.component}:** ${data.content}`); } }; ================================================ FILE: packages/arco-changelog/src/default/template.en-US.njk ================================================ ## {{ version }} `{{ date }}` {% if attention -%} ### ⚠️ Important Attention {% for content in attention -%} - {{ content }} {% endfor %} {% endif %} {% if feature -%} ### 🆕 Feature {% for content in feature -%} - {{ content }} {% endfor %} {% endif %} {% if bugfix -%} ### 🐛 BugFix {% for content in bugfix -%} - {{ content }} {% endfor %} {% endif %} {% if enhancement -%} ### 💎 Enhancement {% for content in enhancement -%} - {{ content }} {% endfor %} {% endif %} {% if style -%} ### 💅 Style {% for content in style -%} - {{ content }} {% endfor %} {% endif %} {% if typescript -%} ### 🆎 TypeScript {% for content in typescript -%} - {{ content }} {% endfor %} {% endif %} ================================================ FILE: packages/arco-changelog/src/default/template.zh-CN.njk ================================================ ## {{ version }} `{{ date }}` {% if attention -%} ### ⚠️ 重点注意 {% for content in attention -%} - {{ content }} {% endfor %} {% endif %} {% if feature -%} ### 🆕 新增功能 {% for content in feature -%} - {{ content }} {% endfor %} {% endif %} {% if bugfix -%} ### 🐛 问题修复 {% for content in bugfix -%} - {{ content }} {% endfor %} {% endif %} {% if enhancement -%} ### 💎 功能优化 {% for content in enhancement -%} - {{ content }} {% endfor %} {% endif %} {% if style -%} ### 💅 样式更新 {% for content in style -%} - {{ content }} {% endfor %} {% endif %} {% if typescript -%} ### 🆎 类型修正 {% for content in typescript -%} - {{ content }} {% endfor %} {% endif %} ================================================ FILE: packages/arco-changelog/src/index.ts ================================================ import fs from 'fs-extra'; import inquirer from 'inquirer'; import axios from 'axios'; import moment from 'moment'; import { configure } from 'nunjucks'; import { getConfig } from './config'; import { getPackage } from './utils/config'; import { Changelog, EmitFile } from './interface'; import { getChangelogList } from './changelog'; const nunjucksEnv = configure(__dirname, { autoescape: false, trimBlocks: true, lstripBlocks: true, }); const appendChangelog = async (emit: EmitFile) => { const { file, template, data } = emit; const content = nunjucksEnv.render(template, data); try { await fs.access(file); const origin = await fs.readFile(file, 'utf-8'); const match = origin.match(/^(```yaml\n.*?\n```\n\n)?(.*)$/s); if (match) { await fs.writeFile(file, `${match[1] ?? ''}${content}\n${match[2]}`); } } catch { // eslint-disable-next-line await fs.writeFile(file, '```yaml\nchangelog: true\n```\n\n' + content); } }; const getRequestURL = (config: { repo: string; version: string; merged?: boolean; }) => { let url = `https://api.github.com/search/issues?accept=application/vnd.github.v3+json&q=repo:${config.repo}+is:pr+milestone:${config.version}`; if (config.merged) { url += '+is:merged'; } return url; }; export const changelog = async () => { const config = await getConfig(); const packageData = await getPackage(); let version = (packageData.version ?? '') as string; const answer = await inquirer.prompt({ type: 'input', name: 'version', message: 'Please input the version', default: version, validate(input: any) { return /\d+\.\d+\.\d+(-beta\.\d+)?/.test(input); }, }); version = answer.version; const res = await axios.request( config.requestConfig?.({ repo: config.repo, version, merged: config.merged, }) ?? { method: 'get', url: getRequestURL({ repo: config.repo, version, merged: config.merged, }), } ); if (res.status === 200) { const { data } = res; const changelog: Changelog = { version, date: moment().format('YYYY-MM-DD'), list: [], }; if (config.type === 'gitlab') { for (const item of data ?? []) { if (item.description) { const list = getChangelogList(item.description, { pr: { id: item.iid, url: item.web_url, }, typeDict: config.typeDict, keyDict: config.keyDict, }); if (list) { changelog.list = changelog.list.concat(list); } } } } else { for (const item of data?.items ?? []) { const list = getChangelogList(item.body, { pr: item, typeDict: config.typeDict, keyDict: config.keyDict, }); if (list) { changelog.list = changelog.list.concat(list); } } } if (changelog.list.length > 0) { const emits = config.emitFiles(changelog); for (const item of emits) { // eslint-disable-next-line no-await-in-loop await appendChangelog(item); } } else { // eslint-disable-next-line no-console console.log('No update information found'); } } }; ================================================ FILE: packages/arco-changelog/src/interface.ts ================================================ import { AxiosRequestConfig } from 'axios'; export interface ChangelogConfig { repo: string; merged?: boolean; requestConfig?: (config: { repo: string; version: string; merged: boolean; }) => AxiosRequestConfig; emitFiles?: (changelog: Changelog) => EmitFile[]; typeDict?: Record; type?: 'github' | 'gitlab'; arcoComponent?: 'react' | 'vue'; keyDict?: Record; filename?: { zh: string; en: string }; } export interface PullRequest { id: number; url: string; } export interface ChangelogData { type: string; pr: PullRequest; issues?: string[]; [key: string]: any; } export interface Changelog { version: string; date: string; list: ChangelogData[]; } export interface EmitFile { file: string; template: string; data: Record; } ================================================ FILE: packages/arco-changelog/src/test.md ================================================ ## Types of changes - [x] New feature - [ ] Bug fix - [ ] Enhancement - [ ] Component style change - [ ] Typescript definition change - [ ] Documentation change - [ ] Coding style change - [ ] Refactoring - [ ] Test cases - [ ] Continuous integration - [ ] Breaking change - [ ] Others ## Background and context ## Solution ## How is the change tested? ## Changelog | Component | Changelog(CN) | Changelog(EN) | Related issues | | --------- | ------------- | ------------- | -------------- | | upload | 新增 `bundle-upload` 属性,支持捆绑上传 | Added `bundle-upload` property to support bundle upload | Close #647 | ## Checklist: - [ ] Test suite passes (`npm run test`) - [ ] Provide changelog for relevant changes (e.g. bug fixes and new features) if applicable. - [ ] Changes are submitted to the appropriate branch (e.g. features should be submitted to `feature` branch and others should be submitted to `main` branch) ## Other information ================================================ FILE: packages/arco-changelog/src/utils/config.ts ================================================ import path from 'path'; import fs from 'fs-extra'; export const getConfig = async () => { const filename = path.resolve(process.cwd(), 'changelog.config.ts'); try { await fs.access(filename); return import(filename); } catch { return {}; } }; let packageCache: Record; export const getPackage = async (): Promise> => { if (!packageCache) { const content = await fs.readFile( path.resolve(process.cwd(), 'package.json'), 'utf8' ); try { packageCache = JSON.parse(content); } catch {} } return packageCache ?? {}; }; ================================================ FILE: packages/arco-changelog/src/utils/convert-case.ts ================================================ export const toKebabCase = (string: string): string => { return string.replace(/[A-Z]+/g, (match, offset) => { return `${offset > 0 ? '-' : ''}${match.toLocaleLowerCase()}`; }); }; export const toPascalCase = (string: string): string => { return string .replace(/^./, (match) => match.toLocaleUpperCase()) .replace(/-(.)/g, (match, p1: string) => { return p1.toLocaleUpperCase(); }); }; ================================================ FILE: packages/arco-changelog/src/utils/invert.ts ================================================ export const invertKeyValues = (obj: Record) => { return Object.keys(obj).reduce((acc, key) => { acc[obj[key]] = key; return acc; }, {} as Record); }; ================================================ FILE: packages/arco-changelog/src/utils/version.ts ================================================ const getLastVersion = (content: string) => { const match = content.match(/## (\d+\.\d+\.\d+(-beta\.\d+)?)/); return match?.[1]; }; const getBetaVersions = (content: string) => { const matches = Array.from( content.matchAll(/## (\d+\.\d+\.\d+(-beta\.\d+)?)/g) ); const versions = []; for (const item of matches) { if (/beta/.test(item[1])) { versions.push(item[1]); } else { break; } } return versions; }; const getVersionNumber = (version: string): number => { if (!version) { return 0; } switch (version) { case 'alpha': return -3; case 'beta': return -2; case 'rc': return -1; default: return parseInt(version, 10); } }; export const compareVersion = (v1: string, v2: string) => { const mainArray1 = v1.split('-'); const mainArray2 = v2.split('-'); // Major version const array1 = mainArray1[0].split('.'); const array2 = mainArray2[0].split('.'); const maxL = Math.max(array1.length, array2.length); for (let i = 0; i < maxL; i++) { const v1 = getVersionNumber(array1[i]); const v2 = getVersionNumber(array2[i]); if (v1 !== v2) { return v1 > v2 ? 1 : -1; } } // Beta part const subArray1 = (mainArray1[1] ?? '').split('.'); const subArray2 = (mainArray2[1] ?? '').split('.'); const maxSL = Math.max(subArray1.length, subArray2.length); for (let i = 0; i < maxSL; i++) { const v1 = getVersionNumber(subArray1[i]); const v2 = getVersionNumber(subArray2[i]); if (v1 !== v2) { return v1 > v2 ? 1 : -1; } } return 0; }; ================================================ FILE: packages/arco-changelog/src/vue/emit-files.ts ================================================ import path from 'path'; import { Changelog, EmitFile } from '../interface'; export const emitFiles = (changelog: Changelog): EmitFile[] => { const allCN: Record = {}; const addEN: Record = {}; const componentCN: Record = {}; const componentEN: Record = {}; for (const item of changelog.list) { const contentCN = `${item.changelogZh} ([#${item.pr.id}](${item.pr.url}))`; const contentEN = `${item.changelogEn} ([#${item.pr.id}](${item.pr.url}))`; addAll({ ...item, content: contentCN }, allCN); addAll({ ...item, content: contentEN }, addEN); addComponent({ ...item, content: contentCN }, componentCN); addComponent({ ...item, content: contentEN }, componentEN); } const emits: EmitFile[] = [ { file: 'CHANGELOG.zh-CN.md', template: path.resolve(__dirname, 'template.zh-CN.njk'), data: { version: changelog.version, date: changelog.date, ...allCN }, }, { file: 'CHANGELOG.md', template: path.resolve(__dirname, 'template.en-US.njk'), data: { version: changelog.version, date: changelog.date, ...addEN }, }, ]; emits.push(...getComponentEmits(componentCN, true)); emits.push(...getComponentEmits(componentEN)); return emits; }; const addAll = (data: any, changelog: any) => { if (!changelog[data.type]) { changelog[data.type] = []; } if (!data.component || data.component === 'common') { changelog[data.type].push(data.content); } else { changelog[data.type].push(`**${data.component}:** ${data.content}`); } }; const addComponent = (data: any, changelog: any) => { if (!data.component || data.component === 'common') { return; } if (!changelog[data.component]) { changelog[data.component] = {}; } if (!changelog[data.component][data.type]) { changelog[data.component][data.type] = []; } changelog[data.component][data.type].push(data.content); }; const getComponentEmits = (changelog: Record, zh?: boolean) => { const emits: EmitFile[] = []; for (const component of Object.keys(changelog)) { const file = component === 'icon' ? `components/icon-component/CHANGELOG.${zh ? 'zh-CN.md' : 'md'}` : `components/${component}/CHANGELOG.${zh ? 'zh-CN.md' : 'md'}`; emits.push({ file, template: path.resolve( __dirname, `template.${zh ? 'zh-CN' : 'en-US'}.njk` ), data: { version: changelog.version, date: changelog.date, ...changelog[component], }, }); } return emits; }; ================================================ FILE: packages/arco-changelog/src/vue/template.en-US.njk ================================================ ## {{ version }} `{{ date }}` {% if attention -%} ### ⚠️ Important Attention {% for content in attention -%} - {{ content }} {% endfor %} {% endif %} {% if feature -%} ### 🆕 Feature {% for content in feature -%} - {{ content }} {% endfor %} {% endif %} {% if bugfix -%} ### 🐛 BugFix {% for content in bugfix -%} - {{ content }} {% endfor %} {% endif %} {% if enhancement -%} ### 💎 Enhancement {% for content in enhancement -%} - {{ content }} {% endfor %} {% endif %} {% if style -%} ### 💅 Style {% for content in style -%} - {{ content }} {% endfor %} {% endif %} {% if typescript -%} ### 🆎 TypeScript {% for content in typescript -%} - {{ content }} {% endfor %} {% endif %} ================================================ FILE: packages/arco-changelog/src/vue/template.zh-CN.njk ================================================ ## {{ version }} `{{ date }}` {% if attention -%} ### ⚠️ 重点注意 {% for content in attention -%} - {{ content }} {% endfor %} {% endif %} {% if feature -%} ### 🆕 新增功能 {% for content in feature -%} - {{ content }} {% endfor %} {% endif %} {% if bugfix -%} ### 🐛 问题修复 {% for content in bugfix -%} - {{ content }} {% endfor %} {% endif %} {% if enhancement -%} ### 💎 功能优化 {% for content in enhancement -%} - {{ content }} {% endfor %} {% endif %} {% if style -%} ### 💅 样式更新 {% for content in style -%} - {{ content }} {% endfor %} {% endif %} {% if typescript -%} ### 🆎 类型修正 {% for content in typescript -%} - {{ content }} {% endfor %} {% endif %} ================================================ FILE: packages/arco-changelog/src/vue/vue.config.ts ================================================ import { emitFiles } from './emit-files'; export default { repo: 'arco-design/arco-design-vue', merged: true, emitFiles, }; ================================================ FILE: packages/arco-changelog/tsconfig.json ================================================ { "compilerOptions": { "sourceMap": true, "outDir": "dist", "module": "CommonJS", "target": "ES2015", "allowJs": true, "moduleResolution": "node", "baseUrl": ".", "strict": true, "resolveJsonModule": true, "esModuleInterop": true, "skipLibCheck": true, "lib": [ "DOM", "ES2020" ] }, "include": [ "src" ] } ================================================ FILE: packages/arco-vue-docs/.eslintignore ================================================ /*.json /*.js ================================================ FILE: packages/arco-vue-docs/.eslintrc.js ================================================ module.exports = { parser: 'vue-eslint-parser', parserOptions: { // Parser that checks the content of the ================================================ FILE: packages/arco-vue-docs/components/code-block/index.vue ================================================ ================================================ FILE: packages/arco-vue-docs/components/theme-box/interface.ts ================================================ export interface ThemeData { themeId: number; themeName: string; cover: string; packageName: string; unpkgHost: string; } ================================================ FILE: packages/arco-vue-docs/components/token-table/token-table.vue ================================================ ================================================ FILE: packages/arco-vue-docs/context.ts ================================================ import { InjectionKey } from 'vue'; export interface CollapseContext { showNav: boolean; showAnchor: boolean; toggleNav: () => void; toggleAnchor: () => void; } export const collapseInjectionKey: InjectionKey = Symbol('CollapseContext'); ================================================ FILE: packages/arco-vue-docs/docs/dark.en-US.md ================================================ ```yaml meta: type: Developer Guide title: Dark mode description: The dark theme is built in the component library, and you can easily switch to dark. ``` *Auto translate by google.* ## Switch to dark mode The component library uses the arco-theme attribute on the body tag to indicate the current theme, so you only need to modify this attribute to complete the theme switch. ```ts // Set as dark theme document.body.setAttribute('arco-theme', 'dark') // Restore light theme document.body.removeAttribute('arco-theme'); ``` ## Principle and built-in colors Refer to [Dark Mode](https://arco.design/react/docs/palette) and [Color](https://arco.design/react/docs/palette) ================================================ FILE: packages/arco-vue-docs/docs/dark.zh-CN.md ================================================ ```yaml meta: type: 开发指南 title: 暗黑模式 description: 组件库内置暗色的主题,你可以轻易的切换到暗色。 ``` ## 切换到暗黑模式 组件库通过 body 标签上的 arco-theme 属性来标明当前的主题,所以你只要修改这个属性,即可完成主题的切换。 ```ts // 设置为暗黑主题 document.body.setAttribute('arco-theme', 'dark') // 恢复亮色主题 document.body.removeAttribute('arco-theme'); ``` ## 原理和内置颜色 可参考 [暗黑模式](https://arco.design/react/docs/palette) 和 [颜色](https://arco.design/react/docs/palette) ================================================ FILE: packages/arco-vue-docs/docs/faq.en-US.md ================================================ ```yaml meta: type: Developer Guide title: FAQ description: Frequently Asked Questions in the Use of the Component Library ``` ## Controlled and Uncontrolled The concept of `controlled` is used in the Arco Design Vue component library, as the name suggests, the display state of the component will always be the same as the incoming value. We recommend using input components in controlled mode. At this time, you can modify the value of `model-value` through `two-way binding (v-model)` or `change` event to ensure the same value inside and outside the component. In controlled mode, if you want to control the displayed value, you can use the `change` event to handle it. If we don't want to control the value of the component, we can use the uncontrolled mode, in which case the value of the component will be maintained inside the component, and the initial value can be set by `default-value`. In uncontrolled mode, you can get the value of the component through the `change` event. pay attention: The `default-*` class attributes are used to set initial values in uncontrolled mode and do not affect subsequent states. When this value and the controlled value are used at the same time, the controlled value takes precedence. ## Update At Scroll By default, the drop-down menu will follow the change of the window scroll bar to update the position. If the component containing the drop-down menu is placed in a scrollable container, there will be a problem that the drop-down menu does not update the position when the container is scrolled. At this time, you can use the trigger inside the component. configuration, will `updateAtScroll` Set to `true` to enable rolling update support. If there are many such scenes in the project, you can enable this property globally through the [ConfigProvider](/vue/component/config-provider) component. ## The use of virtual lists Components that support setting up virtual lists [List](/vue/component/list) 、[Select](/vue/component/Select)、[Table](/vue/component/table)、[Tree](/vue/component/tree) set `virtual-list-props` Enable the virtual list function. The rendering of virtual list elements can be divided into two cases: **elements are highly fixed** and **elements are highly dynamic**. |Name|Description|Type|Default|version| |---|---|---|:---:|:---| |height|Viewable area height|`number \| string`|`-`|| |fixedSize| Whether the elements in the list are of fixed size (height) |`boolean`|`false`|2.34.1| |estimatedSize| Estimated size (height) [this value is not valid when `fixedSize` is `true`], and if it is closer to the average size, the scroll bar length will look more accurate. It is recommended to allocate the average calculated by yourself. The default dynamic height will use the average of the first Section |`number`|`-`|2.34.1| |buffer| The number of elements mounted in advance outside the boundary of the viewport. (`Section = buffer * 3`) the default value is `10` (that is, Section defaults to 30). It is recommended to adjust the height of the list viewport. This value will affect performance. |`number`|`10`|2.34.1| ================================================ FILE: packages/arco-vue-docs/docs/faq.zh-CN.md ================================================ ```yaml meta: type: 开发指南 title: 常见问题 description: 组件库使用中的常见问题解答 ``` ## 受控与非受控 Arco Design Vue 组件库中使用了 `受控` 的概念,正如其名,组件的显示状态将始终与传入值相同。我们推荐通过受控模式来使用输入组件。 这时可以通过 `双向绑定(v-model)` 或者 `change` 事件来修改 `model-value` 的值,来保证组件内部与外部的值相同。 在受控模式中,如果希望控制显示的值,可以使用 `change` 事件进行处理。 如果我们不希望控制组件的值,可以使用非受控模式,此时组件的值将维护在组件内部,可以通过 `default-value` 来设置初始值。非受控模式下可以通过 `change` 事件来获取组件的值。 特别注意: `default-*` 类属性用来设置非受控模式下的初始值,不会影响后续的状态。此值与受控值同时使用时,受控值优先生效。 ## 下拉菜单的滚动跟随 下拉菜单默认会跟随 window 滚动条的变化更新位置,如果将包含下拉菜单的组件放置在一个可滚动的容器中,会出现容器滚动时下拉菜单没有更新位置的问题,此时可以通过组件内部的 trigger 配置,将 `updateAtScroll` 设置为 `true` 开启滚动更新的支持。 如果项目内此场景较多,可以通过 [ConfigProvider](/vue/component/config-provider) 组件全局开启此属性。 ## 虚拟列表的使用 支持设置虚拟列表的组件 [List](/vue/component/list) 、[Select](/vue/component/Select)、[Table](/vue/component/table)、[Tree](/vue/component/tree) 设置 `virtual-list-props` 开启虚拟列表功能。 虚拟列表元素的渲染分为 **元素高度固定**,**元素高度动态** 两种情况。 |参数名|描述|类型|默认值|版本| |---|---|---|:---:|:---| |height|可视区域高度|`number \| string`|`-`|| |fixedSize| 列表内元素是否为固定大小(高度)|`boolean`|`false`|2.34.1| |estimatedSize| 预估大小(高度)[当 `fixedSize` 为 `true` 时,此值无效],如果它更接近平均大小,则滚动条长度看起来将更准确。建议分配自己计算的平均值。默认动态高度将使用首个 Section 的平均值|`number`|`-`|2.34.1| |buffer|视口边界外提前挂载的元素数量。(`Section = buffer * 3`)默认值为 `10`(也就是 Section 默认为 30), 建议根据列表视口的高度做调整,此值太大会影响性能。|`number`|`10`|2.34.1| ================================================ FILE: packages/arco-vue-docs/docs/i18n.en-US.md ================================================ ```yaml meta: type: Developer Guide title: Globalization description: All component texts use Chinese by default, and other languages can be used by setting. ``` _Auto translate by google._ Internationalization is achieved through the [ConfigProvider](/vue/component/config-provider) component. ## Basic usage ```vue ``` ## Supported regional languages | Language | Area code | | ------------------- | --------- | | Simple Chinese | zh-CN | | English (US) | en-US | | Japanese | ja-JP | | Traditional Chinese | zh-TW | | Portuguese | pt-PT | | Spanish | es-ES | | Indonesian | id-ID | | French, France | fr-FR | | German, Germany | de-DE | | Korean | ko-KR | | Italian, Italy | it-IT | | Thai | th-TH | | Melayu (Malaysia) | ms-MY | | Vietnamese | vi-VN | | Khmer (Cambodia) | km-KH | | Arabic (Egypt) | ar-EG | | Russian (Russia) | ru-RU | | Dutch (Netherlands) | nl-NL | ================================================ FILE: packages/arco-vue-docs/docs/i18n.zh-CN.md ================================================ ```yaml meta: type: 开发指南 title: 国际化 description: 所有组件文案默认使用的是中文,通过设置可以使用其它语言。 ``` 通过 [ConfigProvider](/vue/component/config-provider) 组件实现国际化。 ## 基本用法 ```vue ``` ## 支持的地区语言 | 语言 | 地区编码 | | -------------------- | -------- | | 简体中文 | zh-CN | | 英文 | en-US | | 日文 | ja-JP | | 繁体中文(中国台湾) | zh-TW | | 葡萄牙语 | pt-PT | | 西班牙语 | es-ES | | 印度尼西亚语 | id-ID | | 法语(法国) | fr-FR | | 德语(德国) | de-DE | | 韩语 | ko-KR | | 意大利语(意大利) | it-IT | | 马来语(马来西亚) | ms-MY | | 泰语 | th-TH | | 越南语 | vi-VN | | 高棉语(柬埔寨) | km-KH | | 阿拉伯语(埃及) | ar-EG | | 俄语(俄罗斯) | ru-RU | | 荷兰语(荷兰) | nl-NL | ================================================ FILE: packages/arco-vue-docs/docs/pro/build.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Package build description: Package code ``` *Auto translate by google.* ## Package and build When the code is written, execute the following command to package the code ```bash npm run build ``` This command calls the packaging command provided by vite. After the packaging is completed, a `dist` folder will be generated in the root directory, which is the code that can be used for deployment. PS: Tips for reducing package size! ! ! Because in the Pro project, the displayed table component requires the vue compile function, so a version with a compiler is introduced. If you don't need the Vue template compilation function, delete the corresponding business code, configure the specified Vue version, and build and package to reduce the package size. If you need the ability to compile vue templates, you can configure it in the vite.config.prod.ts file (see below). ```ts // config/vite.config.build.ts import {defineConfig} from'vite'; export default defineConfig({ mode:'production', ... resolve: { alias: [ { find:'vue', replacement:'vue/dist/vue.esm-bundler.js', // need to compile tmp }, ], }, }); ``` For more specific configuration details, please refer to [vite](https://vitejs.dev/)[Official Website](https://vitejs.dev/). ================================================ FILE: packages/arco-vue-docs/docs/pro/build.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 打包构建 description: 打包代码 ``` ## 打包构建 当代码书写完成后,执行以下命令即可打包代码 ```bash npm run build ``` 该命令调用的是 vite 提供的打包命令,打包完成后,会在根目录生成 `dist` 文件夹,这里面就是可以用于部署的代码。 PS: 打包体积缩减提示!!! 因为在Pro项目中,展示的table组件需要 vue compile 功能,所以引入了带有编译器的版本。 如果不需要vue 模板编译功能,删除对应的业务代码后,配置指定的vue版本,构建打包以缩小打包体积。 如果需要 vue 模板编译 能力,可在 vite.config.prod.ts 文件 中进行配置(如下)。 ```ts // config/vite.config.build.ts import { defineConfig } from 'vite'; export default defineConfig({ mode: 'production', ... resolve: { alias: [ { find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js', // 需要编译tmp }, ], }, }); ``` 更多具体配置详见[vite](https://vitejs.dev/)[官网](https://vitejs.dev/)。 ================================================ FILE: packages/arco-vue-docs/docs/pro/directory.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Directory Structure description: The organizational structure of the project file. ``` *Auto translate by google.* ## Content ``` ├── README.md ├── package.json ├── index.html ├── src │ ├── api # Request interface │ ├── assets # Static resources │ └── style # Global style │ ├── components # General business components │ ├── config # Global configuration (including echarts theme) │ └── settings.json # Configuration file │ ├── directive # Instruction set (if necessary, you can add it yourself) │ ├── filters # filter (if necessary, you can add it yourself) │ ├── hooks # global hooks │ ├── layout # Layout │ ├── locale # Internationalized language pack │ ├── mock # Mock data │ ├── views # Page template | |—— router # Routing configuration │ ├── store # State management center │ ├── types # Typescript types │ └── utils # Tool library │ └── App.vue # View entrance │ └── main.ts # Entry file └── tsconfig.json ``` ps: [Filter description](https://v3-migration.vuejs.org/breaking-changes/filters.html) ================================================ FILE: packages/arco-vue-docs/docs/pro/directory.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 目录结构 description: 项目文件的组织结构 ``` ## 目录 ``` ├── README.md ├── package.json ├── index.html ├── src │ ├── api # 请求接口 │ ├── assets # 静态资源 │ └── style 全局样式 │ ├── components # 通用业务组件 │ ├── config # 全局配置(包含echarts主题) │ └── settings.json # 配置文件 │ ├── directives # 指令集(如需,可自行补充) │ ├── filters # 过滤器(如需,可自行补充) │ ├── hooks # 全局hooks │ ├── layout # 布局 │ ├── locale # 国际化语言包 │ ├── mock # 模拟数据 │ ├── views # 页面模板 │ ├── router # 路由配置 │ ├── store # 状态管理中心 │ ├── types # Typescript 类型 │ └── utils # 工具库 │ └── App.vue # 视图入口 │ └── main.ts # 入口文件 └── tsconfig.json ``` ps:[过滤器说明](https://v3-migration.vuejs.org/breaking-changes/filters.html) ================================================ FILE: packages/arco-vue-docs/docs/pro/faq.en-US.md ================================================ ```yaml meta: type: Arco Pro title: FAQ description: Arco Design Pro Vue FAQ Collection ``` *Auto translate by google.* ## Initialization ### 1. Initialization of arco-cli failed ![](https://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/iShot_2022-05-26_16.12.14.png~tplv-49unhts6dw-image.image) If the dependency installation fails, go to the directory of the initialization project and execute the npm install or yarn install installation operation again. ## Development ### 1. How to set highlight for menu items? See [Routes and menu](/vue/docs/pro/routes-and-menu) for details ### 2.Menu hides children See [Routes and menu](/vue/docs/pro/routes-and-menu) for details ### 3.Configure first-level menu items Due to the architecture, configuring a single first-level menu item requires the cooperation of multiple menu configuration items. See [#85]([/vue/docs/pro/routes-and-menu](https://github.com/arco-design/arco-design-pro-vue/issues/85#issuecomment-1142289501)) for details ### 4.Using jsx in Vue3 详见 [babel-plugin-jsx](https://github.com/vuejs/babel-plugin-jsx) ### 5.Cross-domain proxy See [vite configuration](https://cn.vitejs.dev/config/#server-open) for details ### 6.Code cannot be pushed Because of the use of [husky](https://github.com/typicode/husky), the hook [normalizes](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.greljkmo14y0) the uploaded commit information check. Please follow the documentation for git commit information normalization. If you do not need this function, you can delete husky related files and corresponding scripts. (**Not recommended**) ## Build ### 1. Rollup failed to resolve import "XXXXXX/node_modules/@arco-design/web-vue/es/xxx-xxx/style/css.js” The error comes from loading the build plugin (config/plugin/styleImport.ts) on demand. There are several reasons for this problem. - The new version of the component library has added components. - The component itself is missing and not added. - The unplugin-vue-components dependency library version is too low. Solution please [move](https://github.com/arco-design/arco-design-pro-vue/issues/71). ### 2. Executing build TS type error ![](https://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/iShot_2022-05-26_17.36.59.png~tplv-49unhts6dw-image.image) Reason for error: - There is a problem with the spelling itself. - The new version of the component library has made changes to the type declaration. Solution: - Follow the type hints to make changes. - Turn off vue-tsc checks. (**Not recommended**) ```ts // package.json "build": "vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts" // before fixing "build": "vite build --config ./config/vite.config.prod.ts" // 修改后 ``` ### 3. Vue-tsc builds slowly - Reinstall vue-tsc to the latest version. ```shell # npm npm install vue-tsc@latest # yarn yarn add vue-tsc@latest ``` - Turn off vue-tsc checks. (**Not recommended**) ### 4. Preview the packaged project ```shell # npm npm run preview # yarn yarn preview ``` **PS: The preview command will execute the build operation first in Pro.** ## Deployment ### 1. After the page is deployed successfully, refresh the 404 page [Moving to Vue Router](https://router.vuejs.org/guide/essentials/history-mode.html) ## Other ### 1. Can the developed projects be upgraded to the latest version? Arco Pro, as a project template, does not have the ability to smoothly upgrade to the latest version. If you need a new version capability, you can initialize a project and copy your business code into it, and then make the corresponding changes. ================================================ FILE: packages/arco-vue-docs/docs/pro/faq.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 常见问题 description: Arco Design Pro Vue 常见问题合集 ``` ## 初始化 ### 一、arco-cli初始化失败 ![](https://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/iShot_2022-05-26_16.12.14.png~tplv-49unhts6dw-image.image) 依赖安装失败的问题,进入到初始化项目的目录,重新执行执行npm install 或 yarn install安装操作即可。 ## 开发相关 ### 一、菜单项如何设置高亮? 详见 [路由和菜单](/vue/docs/pro/routes-and-menu) ### 二、菜单隐藏子项 详见 [路由和菜单](/vue/docs/pro/routes-and-menu) ### 三、配置一级菜单项 因为架构缘故,配置单独的一级菜单项,需要多个菜单配置项进行配合。详见 [#85]([/vue/docs/pro/routes-and-menu](https://github.com/arco-design/arco-design-pro-vue/issues/85#issuecomment-1142289501)) ### 四、Vue3 中使用 jsx 写法 详见 [babel-plugin-jsx](https://github.com/vuejs/babel-plugin-jsx) ### 五、跨域代理 详见 [vite配置](https://cn.vitejs.dev/config/#server-open) ### 六、代码无法提交 因为使用了 [husky](https://github.com/typicode/husky) 的缘故,钩子对上传的commit信息进行[规范化](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.greljkmo14y0)校验。 请按照文档进行git commit信息规范化。 如果不需要该功能,可以删除掉husky相关文件和对应脚本。(**不推荐**) ## 构建相关 ### 一. Rollup failed to resolve import "XXXXXX/node_modules/@arco-design/web-vue/es/xxx-xxx/style/css.js” 报错源于按需加载构建插件(config/plugin/styleImport.ts),该问题产生分别有以下几个原因 - 新版组件库新增了组件。 - 组件本身遗漏未进行添加。 - unplugin-vue-components 依赖库版本过低。 解决方法请 [移步](https://github.com/arco-design/arco-design-pro-vue/issues/71)。 ### 二、执行构建TS类型报错 ![](https://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/iShot_2022-05-26_17.36.59.png~tplv-49unhts6dw-image.image) 报错原因: - 写法本身存在问题。 - 新版组件库对类型声明进行了变更修改。 解决方法: - 按照类型提示进行修改。 - 关闭vue-tsc检查。(**不推荐**) ```ts // package.json "build": "vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts" // 修改前 "build": "vite build --config ./config/vite.config.prod.ts" // 修改后 ``` ### 三、vue-tsc构建缓慢 - 重新安装vue-tsc至最新版本。 ```shell # npm npm install vue-tsc@latest # yarn yarn add vue-tsc@latest ``` - 关闭vue-tsc检查。(**不推荐**) ### 四、预览打包项目 ```shell # npm npm run preview # yarn yarn preview ``` **PS: 该预览命令在Pro中会先执行build操作。** ## 部署相关 ### 一、页面部署成功后刷新出现404页面 [移步 Vue Router](https://router.vuejs.org/guide/essentials/history-mode.html) ## 其它 ### 一、已经开发的项目是否能够升级到最新版? Arco Pro作为一个项目模板,不具备平滑升级过渡到最新版本的能力。 如需新版本能力,可以初始化一个项目后将自己的业务代码拷贝进去,在进行相应的更改即可。 ================================================ FILE: packages/arco-vue-docs/docs/pro/i18n.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Internationalization description: Multi-language implementation ``` *Auto translate by google.* ## Language Pack Internationalization is firstly the provision of language packs. In Pro, the language packs are defined in `src/locale`, and then imported into `main` to take effect. ``` ├── locale │ ├── en-US.ts │ └── zh-CN.ts ├── hooks │ ├── locale.ts └── main.ts ``` At the same time, hooks for obtaining the current language and switching the current language are provided in the hooks directory. ```ts import {computed} from'vue'; import {useI18n} from'vue-i18n'; export default function useLocale() { const i18 = useI18n(); const currentLocale = computed(() => { return i18.locale.value; }); const changeLocale = (value: string) => { i18.locale.value = value; localStorage.setItem('arco-locale', value); }; return { currentLocale, changeLocale, }; } ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/i18n.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 国际化 description: 多语言实现 ``` ## 语言包 国际化首先是语言包的提供,Pro 里面将语言包定义在 `src/locale` 中,然后导入 `main` 中生效。 ``` ├── locale │ ├── en-US.ts │ └── zh-CN.ts ├── hooks │ ├── locale.ts └── main.ts ``` 同时在hooks目录中提供获取当前语言以及切换当前语言的hook。 ```ts import { computed } from 'vue'; import { useI18n } from 'vue-i18n'; export default function useLocale() { const i18 = useI18n(); const currentLocale = computed(() => { return i18.locale.value; }); const changeLocale = (value: string) => { i18.locale.value = value; localStorage.setItem('arco-locale', value); }; return { currentLocale, changeLocale, }; } ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/layout.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Layout description: General layout of the page ``` *Auto translate by google.* ## Layout There is only one set of layouts currently provided, which is applied to all routing pages, including side menu bar, top notification bar, footer and content area. The side bar and top notification bar are fixed to facilitate the scrolling process of users Focus on other views. ![](https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/ebd0bd6d4c044c1e945527194384fcaa.png~tplv-uwbnlip3yd-webp.webp) In addition, the responsive sidebar will automatically shrink as follows when the window width is less than `1200px`: ![](https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/c730fddca82cf8c4cda27cef9ecd6683.png~tplv-uwbnlip3yd-webp.webp) ================================================ FILE: packages/arco-vue-docs/docs/pro/layout.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 布局 description: 页面通用布局 ``` ## 布局 目前提供的布局只有一套,应用到了所有路由页面上,包含侧边菜单栏,顶部通知栏,页脚和内容区域,其中侧边栏和顶部通知栏都是 fixed 的,方便用户在滚动的过程中关注到其他视图。 ![](https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/ebd0bd6d4c044c1e945527194384fcaa.png~tplv-uwbnlip3yd-webp.webp) 此外,响应式的侧边栏会在窗口宽度小于 `1200px` 的时候,自动收缩如下: ![](https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/c730fddca82cf8c4cda27cef9ecd6683.png~tplv-uwbnlip3yd-webp.webp) ================================================ FILE: packages/arco-vue-docs/docs/pro/mock.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Interface and Mock description: Network request, interceptor and simulation data ``` *Auto translate by google.* ## Network request Use axios to make remote interface requests. It is recommended to improve the type definition of the returned and requested data. ```ts import axios from'axios'; export interface UserToken { token: string; } export interface UserStateTypes { name: string; location: string; } export function getUserInfo(data: UserToken) { // Get complete type hints by passing generics. return axios.post('/api/user/info', data); } ``` ## Interceptor Multi-layer interceptors can be added according to the needs of your own system. ```ts import axios, {AxiosRequestConfig, AxiosResponse} from'axios'; // Users can modify according to their own background system export interface HttpResponse { status: number; msg: string; code: number; data: T; } axios.interceptors.request.use( (config: AxiosRequestConfig) => { // Configure the request here return config; }, (error) => { // What to do with request errors return Promise.reject(error); } ); // Add response interceptor axios.interceptors.response.use( (response: AxiosResponse) => { const res = response.data; // if the custom code is not 20000, it is judged as an error. if (res.code !== 20000) { // remind users // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if ( [50008, 50012, 50014].includes(res.code) ) { // do something } return Promise.reject(new Error(res.msg ||'Error')); } return res; }, (error) => { return Promise.reject(error); } ); ``` Intercept ajax and return simulated data ## mock solution Parallel development of the front and back ends means that the front end needs to be developed without interface data. In this case, if the function of simulating data requests can be provided, our data request code can be written normally. Pro uses Mock.js to achieve This feature. Mock.js will intercept the ajax request. If there is a matching mock rule, the ajax will not be sent out, but the mock data will be returned. Mock.js has a wealth of simulation data generation methods, it is recommended to read the document first, the document is very clear and easy to understand [MockJs document](http://mockjs.com/) ```ts import Mock from'mockjs'; import { successResponseWrap, } From'@/utils/setup-mock'; Mock.mock(new RegExp('/api/chatList'), () => { const data = Mock.mock(successResponseWrap({ 'data|4-6': [ { 'id|+1': 1, username:'User 7352772', content:'It will start soon, so excited! ', time: '13:09:12', 'isCollect|2': true, }, ], })); return data.data; }); ``` When the request url sent by the client is matched by `new RegExp('/api/chatList')`, Mock.js will intercept the request, execute the corresponding callback function, and return the data returned in the callback function. > Note: Requests that are matched and intercepted by Mock.js will not appear in the network panel of the developer tools. ## Close Mock In order to facilitate the opening and closing of the data simulation function, each `Mock` will be wrapped by `setupMock.setup`, the setupMock is as follows: ```ts import {debug} from'./env'; export default ({ mock, setup }: {mock?: boolean; setup: () => void; }) => { if (mock !== false && debug) setup(); }; ``` Data simulation is started by default in a non-production environment. When we need to debug the interface, we only need to set the mock parameter of setupMock to false, as follows: ```ts import Mock from'mockjs'; import setupMock from'../utils/setupMock'; setupMock({ mock: false setup() { // User Info Mock.mock(new RegExp('/api/userInfo'), () => { return { name:'name', }; }); }, }); ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/mock.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 接口和数据模拟 description: 网络请求、拦截器及模拟数据 ``` ## 网络请求 使用axios进行远程接口请求。 建议完善返回及请求数据的类型定义。 ```ts import axios from 'axios'; export interface UserToken { token: string; } export interface UserStateTypes { name: string; location: string; } export function getUserInfo(data: UserToken) { // 通过传递泛型,以获得完整的类型提示。 return axios.post('/api/user/info', data); } ``` ## 拦截器 可以根据自身系统需要增加多层拦截器。 ```ts import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; // 用户可以根据自身后台系统进行修改 export interface HttpResponse { status: number; msg: string; code: number; data: T; } axios.interceptors.request.use( (config: AxiosRequestConfig) => { // 此处对请求进行配置 return config; }, (error) => { // 对请求错误做些什么 return Promise.reject(error); } ); // 添加响应拦截器 axios.interceptors.response.use( (response: AxiosResponse) => { const res = response.data; // if the custom code is not 20000, it is judged as an error. if (res.code !== 20000) { // remind users // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if ( [50008, 50012, 50014].includes(res.code) ) { // do something } return Promise.reject(new Error(res.msg || 'Error')); } return res; }, (error) => { return Promise.reject(error); } ); ``` 拦截 ajax 并返回模拟的数据 ## mock解决方案 前后端并行开发意味着前端需要在没有接口数据的情况下进行开发,在这种情况下如果能提供模拟数据请求的功能,我们的数据请求代码就能正常书写,Pro 采用了 Mock.js 来实现这个功能。 Mock.js 会拦截 ajax 请求,如果有匹配的 mock 规则,就不会将 ajax 发出去,而是返回 mock 的数据。Mock.js 有着丰富的模拟数据生成方法,建议先读一下文档,文档写的很清晰易懂 [MockJs 文档](http://mockjs.com/) ```ts import Mock from 'mockjs'; import { successResponseWrap, } from '@/utils/setup-mock'; Mock.mock(new RegExp('/api/chatList'), () => { const data = Mock.mock(successResponseWrap({ 'data|4-6': [ { 'id|+1': 1, username: '用户7352772', content: '马上就开始了,好激动!', time: '13:09:12', 'isCollect|2': true, }, ], })); return data.data; }); ``` 当客户端发送请求的 url 被 `new RegExp('/api/chatList')` 匹配到,Mock.js 就会拦截这条请求,并执行对应的回调函数,返回回调函数中 return 的数据。 > 注意:被 Mock.js 匹配并拦截的请求,不会出现在开发者工具的 network 面板中。 ## 关闭 Mock 为了方便开启和关闭数据模拟功能,每个 `Mock` 都会被 `setupMock.setup` 包裹,setupMock 如下: ``` import { debug } from './env'; export default ({ mock, setup }: { mock?: boolean; setup: () => void; }) => { if (mock !== false && debug) setup(); }; ``` 非生产环境下默认启动数据模拟,当我们需要调试接口的时候只需要将 setupMock 的 mock 参数置为 false 即可,如下: ```ts import Mock from 'mockjs'; import setupMock from '../utils/setupMock'; setupMock({ mock: false setup() { // 用户信息 Mock.mock(new RegExp('/api/userInfo'), () => { return { name: 'name', }; }); }, }); ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/npm-scripts.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Npm Scripts description: package.json script presets convenient and practical commands ``` *Auto translate by google.* ## Configuration file ``` ├── README.md ├── config │ ├── plugin # vite plugin │ ├── vite.config.base.ts # Basic Environment Configuration │ ├── vite.config.dev.ts # Development environment configuration │ ├── vite.config.prod.ts # Production environment configuration └── package.json ``` ## Local development ```bash npm run dev ``` The command invoked is as follows ```json { "scripts": { "dev": "vite --config ./config/vite.config.dev.ts", } } ``` ## Build production ```bash npm run build ``` The commands to be called are as follows. According to actual needs, please refer to [vite](https://vitejs.dev/)[Official Website](https://vitejs.dev/) for output configuration. ```json { "scripts": { "build": "vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts", } } ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/npm-scripts.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: npm 命令 description: package.json script 预置方便实用的命令 ``` ## 配置文件 ``` ├── README.md ├── config │ ├── plugin # vite插件 │ ├── vite.config.base.ts # 基础环境配置 │ ├── vite.config.dev.ts # 开发环境配置 │ ├── vite.config.prod.ts # 生产环境配置 └── package.json ``` ## 本地开发 ```bash npm run dev ``` 调用的命令如下 ```json { "scripts": { "dev": "vite --config ./config/vite.config.dev.ts", } } ``` ## 构建生产 ```bash npm run build ``` 调用的命令如下,可以根据实际需要,查阅[vite](https://vitejs.dev/)[官网](https://vitejs.dev/),进行输出配置。 ```json { "scripts": { "build": "vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts", } } ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/permission.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Permission control description: Permission control is a very common basic function in middle and background scenarios. In v2.2.0, the permission control function was integrated into Arco Design Pro ``` *Auto translate by google.* ## Applicable scene The common front-end permission control in the middle and background can be roughly summarized as the following scenarios: 1. Menu permission control, manage permissions for a certain menu/page , you can see this page, otherwise it will show no permission. [//]: # (![](http://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/116622141d7b228ad2259c81cd32d095.gif~tplv-uwbnlip3yd-3.awebp)) 2. Menu permission control, manage permissions for a certain menu/page , you can see this page, otherwise it will show no permission. [//]: # (![](http://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/7b410fa5dad6e47665c264fae910c0c8.gif~tplv-uwbnlip3yd-3.awebp)) ## Usage ### Menu permission management For menu and routing permission control, you can add `roles` parameters . (If not added, the default is to have permission) `roles` can be defined according to their own business. ```ts export default { path: 'dashboard', name: 'dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { locale: 'menu.dashboard', requiresAuth: true, icon: 'icon-dashboard', }, children: [ { path: 'workplace', name: 'workplace', component: () => import('@/views/dashboard/workplace/index.vue'), meta: { locale: 'menu.dashboard.workplace', requiresAuth: true, roles: ['*'], // * Indicates wildcard permissions. Tip: In order to write less code, you can also not define this field. }, }, { path: 'monitor', name: 'monitor', component: () => import('@/views/dashboard/monitor/index.vue'), meta: { locale: 'menu.dashboard.monitor', requiresAuth: true, roles: ['admin'], }, }, ], }; ``` ### A button permission management Arco Design Pro encapsulates the `v-permission` directives . Can be used on components or native elements. As follows, place the authorized role types in the array. ```vue Delete ``` The above is the specific method of using the front-end page for permission control, but it needs to combine the back-end interface to return the specific permissions owned by the user to the front-end. At the same time, in the middle and back-end systems, it is far from enough to have simple front-end permission control, and the back-end is also required to perform interface permission control. In particular, some interfaces involving write operations need to strictly control permissions. ## Accomplish ### Routing authority management Pro provides corresponding permission management hooks. The permission requirements of the business can be customized. ```ts #src/hooks/permission.ts import { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'; import { useUserStore } from '@/store'; export default function usePermission() { const userStore = useUserStore(); return { accessRouter(route: RouteLocationNormalized | RouteRecordRaw) { // Determine whether the current user has permission to the route return ( !route.meta?.requiresAuth || !route.meta?.roles || route.meta?.roles?.includes('*') || route.meta?.roles?.includes(userStore.role) ); }, // You can add any rules you want }; } ``` Set up a route guard, and manage the user's page entry and exit in the route guard. For example, whether the current user has logged in and whether the current user has page permissions. ``` ts router.beforeEach(async (to, from, next) => { const userStore = useUserStore(); async function crossroads() { const Permission = usePermission(); if (Permission.accessRouter(to)) await next(); else { const destination = Permission.findFirstPermissionRoute( appRoutes, userStore.role ) || { name: 'notFound', }; // Go to the first authorized page or 404. await next(destination); } } if (isLogin()) { // Check if the user is logged in if (userStore.role) { // If there is role information, it means that the current user has logged in and obtained user information. crossroads(); } else { try { await userStore.info(); // Obtain user role information and then perform subsequent jump processing crossroads(); } catch (error) { next({ name: 'login', query: { redirect: to.name, ...to.query, } as LocationQueryRaw, }); } } } else { // Redirect to login page if not logged in if (to.name === 'login') { next(); return; } next({ name: 'login', query: { redirect: to.name, ...to.query, } as LocationQueryRaw, }); } }); ``` Custom permission directive ```ts import { DirectiveBinding } from 'vue'; import { useUserStore } from '@/store'; function checkPermission(el: HTMLElement, binding: DirectiveBinding) { const { value } = binding; const userStore = useUserStore(); const { role } = userStore; if (Array.isArray(value)) { if (value.length > 0) { const permissionValues = value; // Compare the role permission of the current user with the permission type of the incoming command. If the current user does not have permission, the node deletion operation will be performed. const hasPermission = permissionValues.includes(role); if (!hasPermission && el.parentNode) { el.parentNode.removeChild(el); } } } else { throw new Error(`need roles! Like v-permission="['admin','user']"`); } } export default { mounted(el: HTMLElement, binding: DirectiveBinding) { checkPermission(el, binding); }, updated(el: HTMLElement, binding: DirectiveBinding) { checkPermission(el, binding); }, }; ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/permission.zh-CN.md ================================================ ```yaml meta: type: Arco Pro 最佳实践 title: 权限控制 description: 权限控制是中后台场景非常常见的基础功能,在 v2.2.0 将权限控制功能集成至 Arco Design Pro ``` ## 适用场景 中后台常见的前端权限控制大概可概括为以下场景: 1. 菜单权限控制,针对**某个菜单/页面**进行权限管理,有则能看到此页面,否则将展示无权限。 [//]: # (![](http://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/116622141d7b228ad2259c81cd32d095.gif~tplv-uwbnlip3yd-3.awebp)) 2. **针对某页面中的某触发器**进行权限管理,例如对列表页的某一条数据进行删除操作。有权限情况下则展示删除按钮。 [//]: # (![](http://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/7b410fa5dad6e47665c264fae910c0c8.gif~tplv-uwbnlip3yd-3.awebp)) ## 使用 ### 菜单权限管理 针对菜单及路由权限控制,可以在 路由配置项 中,对某项增加 `roles` 参数即可。(如果不加,默认为拥有权限) `roles` 可以根据自己的业务进行定义。 ```ts export default { path: 'dashboard', name: 'dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { locale: 'menu.dashboard', requiresAuth: true, icon: 'icon-dashboard', }, children: [ { path: 'workplace', name: 'workplace', component: () => import('@/views/dashboard/workplace/index.vue'), meta: { locale: 'menu.dashboard.workplace', requiresAuth: true, roles: ['*'], // * 表示通配权限。提示:为了少写点代码,也可以不定义这个字段。 }, }, { path: 'monitor', name: 'monitor', component: () => import('@/views/dashboard/monitor/index.vue'), meta: { locale: 'menu.dashboard.monitor', requiresAuth: true, roles: ['admin'], }, }, ], }; ``` ### 某按钮权限管理 Arco Design Pro 封装了 `v-permission` 指令。可在组件或者原生元素上使用。 如下,将有权限的角色类型放置在数组中即可。 ```vue 删除 ``` 以上是前端页面进行权限控制的具体使用方法,但是需要结合后端接口将用户所拥有的具体权限返回至前端。 同时,在中后台系统中,仅仅有简单的前端权限控制是远远不够的,还需要后端进行接口权限控制。特别是涉及到写操作的一些接口,需要严格把控权限。 ## 实现 ### 路由权限管理 Pro提供对应的权限管理钩子。可以自定义业务的权限需求。 ```ts #src/hooks/permission.ts import { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'; import { useUserStore } from '@/store'; export default function usePermission() { const userStore = useUserStore(); return { accessRouter(route: RouteLocationNormalized | RouteRecordRaw) { // 判断当前用户是否有该路由的权限 return ( !route.meta?.requiresAuth || !route.meta?.roles || route.meta?.roles?.includes('*') || route.meta?.roles?.includes(userStore.role) ); }, // You can add any rules you want }; } ``` 设置路由守卫,在路由守卫中对用户的页面进出进行管理。例如 当前用户是否已经登录、当前用户是否有页面权限。 ``` ts router.beforeEach(async (to, from, next) => { const userStore = useUserStore(); async function crossroads() { const Permission = usePermission(); if (Permission.accessRouter(to)) await next(); else { const destination = Permission.findFirstPermissionRoute( appRoutes, userStore.role ) || { name: 'notFound', }; // 前往首个有权限的页面或者404。 await next(destination); } } if (isLogin()) { // 判读用户是否登录 if (userStore.role) { // 有角色信息表示当前用户已经登录且获取过用户信息 crossroads(); } else { try { await userStore.info(); // 获取用户角色信息后再进行后续跳转处理 crossroads(); } catch (error) { next({ name: 'login', query: { redirect: to.name, ...to.query, } as LocationQueryRaw, }); } } } else { // 如果未登录则重定向到登录页面 if (to.name === 'login') { next(); return; } next({ name: 'login', query: { redirect: to.name, ...to.query, } as LocationQueryRaw, }); } }); ``` 自定义权限指令 ```ts import { DirectiveBinding } from 'vue'; import { useUserStore } from '@/store'; function checkPermission(el: HTMLElement, binding: DirectiveBinding) { const { value } = binding; const userStore = useUserStore(); const { role } = userStore; if (Array.isArray(value)) { if (value.length > 0) { const permissionValues = value; // 对当前用户的角色权限和传入指令的权限类型进行比对。如果当前用户无权限则会执行节点删除操作。 const hasPermission = permissionValues.includes(role); if (!hasPermission && el.parentNode) { el.parentNode.removeChild(el); } } } else { throw new Error(`need roles! Like v-permission="['admin','user']"`); } } export default { mounted(el: HTMLElement, binding: DirectiveBinding) { checkPermission(el, binding); }, updated(el: HTMLElement, binding: DirectiveBinding) { checkPermission(el, binding); }, }; ``` ================================================ FILE: packages/arco-vue-docs/docs/pro/routes-and-menu.en-US.md ================================================ ```yaml meta: type: Arco Pro title: Routes and menu description: Route and menu generation ``` *Auto translate by google.* The routing is usually tied to the menu. In order to reduce the amount of maintenance, we directly generate the menu through the routing table. ## Router First, you need to understand the configuration of the routing table. For basic routing configuration, please refer to the official documentation of [Vue-Router](https://router.vuejs.org/) ```ts // In this example, the final path to the page is /dashboard/workplace export default { path: 'dashboard', name: 'dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { locale: 'menu.dashboard', requiresAuth: true, icon: 'icon-dashboard', }, children: [ { path: 'workplace', name: 'workplace', component: () => import('@/views/dashboard/workplace/index.vue'), meta: { locale: 'menu.dashboard.workplace', requiresAuth: true, roles: ['admin'], hideInMenu: false, }, }, ], }; ``` Route `Meta` meta information | Key | Description | Type | default| | ------------- | ------------- | -------------- | -------------- | roles | Configure the role that can access the page. If it does not match, it will be forbidden to access the routing page | string[]| - | requiresAuth | Whether login authentication is required | boolean| false | icon | Menu configuration icon | string| - | locale | First-level menu name (language pack key name) | string| - | hideInMenu | Whether to hide this item in the left menu | boolean| - | hideChildrenInMenu | Force single item to be displayed in left menu | boolean| - | activeMenu | If set name, the menu will be highlighted according to the name you set | string| - | order | Sort routing menu items. If this value is set, the higher the value, the higher the front. | number| - | noAffix | If set to true, the tabs will not be added to the tab-bar. | boolean| - | ignoreCache | If set to true the page will not be cached | boolean| - | ## Menu Front-end menu generation process: - Through the computed property of [appRoute](https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/useMenuTree.ts#L10), a routing tree with routing information is obtained. - Use the routing information obtained in the previous step to filter permissions to generate a menu [tree for rendering](https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/useMenuTree.ts#L23). - Recursively generate menus by [rendering]((https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/index.vue#L48)) the menu tree. Server menu generation process: - Add the [action](https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/store/modules/app/index.ts#L47) of the api request to the Store to obtain the routing configuration of the server. - Add the action of the api request to the Store to obtain the routing configuration of the server. - Through the computed property of [appRoute](https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/useMenuTree.ts#L10), a routing tree with routing information is obtained. - Use the routing information obtained in the previous step to filter permissions to generate a menu [tree for rendering](https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/useMenuTree.ts#L23). - Recursively generate menus by [rendering]((https://github.com/arco-design/arco-design-pro-vue/blob/23a21ceb939e1e2334e8c3b0f1f8a8049503ad9d/arco-design-pro-vite/src/components/menu/index.vue#L48)) the menu tree. **Note: Compared with the local menu generation process, the server menu only has more interface requests and server routing configuration information storage steps.** **Individual companies may have corresponding authority management systems to generate corresponding server-side routing configuration information and store them for front-end interface retrieval. However, the overall situation is similar, as long as the routing configuration information returned by the back-end interface conforms to the above routing configuration specifications and can be correctly parsed by the front-end** ## Steps to add a new menu item After understanding the routing and menu generation, you can configure a new menu item. Take a new monitoring page as an example. - Add a monitor folder in views/dashboard and add index.vue to it ```ts
================================================ FILE: packages/arco-vue-docs/index.ts ================================================ import { createApp } from 'vue'; import { createI18n } from 'vue-i18n'; import ArcoVue, { addI18nMessages, useLocale } from '@web-vue/components/index'; import ArcoVueIcon from '@web-vue/components/icon'; import enUS from '@web-vue/components/locale/lang/en-us'; import renderNavBar from '@arco-design/arco-vue-docs-navbar'; import packages from '@web-vue/package.json'; import router from './router'; import locale from './locale'; import App from './app.vue'; import ArcoArticle from './components/article/index.vue'; import AnchorHead from './components/anchor-head/index.vue'; import CodeBlock from './components/code-block/index.vue'; import CellDemo from './components/cell-demo/index.vue'; import CellCode from './components/cell-code/index.vue'; import 'prismjs/themes/prism.css'; import 'nprogress/nprogress.css'; import '@web-vue/components/index.less'; import '@arco-design/arco-vue-docs-navbar/dist/style.css'; import { getLocalStorage, setLocalStorage } from './utils/local-storage'; import { checkLogin } from './utils/login'; let theme = getLocalStorage('arco-theme') ?? ''; if (!theme) { theme = 'light'; setLocalStorage('arco-theme', theme); } const lang = /en-US/i.test(window.location.href) ? 'en-US' : 'zh-CN'; setLocalStorage('arco-lang', lang); const handleLanguageChange = (lang: string) => { if (lang === 'zh-CN' && /en-US/i.test(window.location.href)) { setLocalStorage('arco-lang', lang); window.location.href = window.location.href.replace(/en-US\//i, ''); } else if (lang === 'en-US' && !/en-US/i.test(window.location.href)) { setLocalStorage('arco-lang', lang); window.location.href = window.location.href.replace('/vue', '/vue/en-US'); } }; // Ensure that localStorage and URL are consistent handleLanguageChange(lang); checkLogin().then(() => { try { renderNavBar({ version: packages.version, lang, handleLanguageChange, }); } catch (e) { // eslint-disable-next-line no-console console.error(e); } const i18n = createI18n({ legacy: false, locale: lang, fallbackLocale: 'zh-CN', messages: locale, }); addI18nMessages({ 'en-US': enUS }); if (lang === 'en-US') { useLocale(lang); } const app = createApp(App, { theme, language: lang, }); app.use(ArcoVue); app.use(ArcoVueIcon); app.use(router); app.use(i18n); app.component(CodeBlock.name, CodeBlock); app.component(CellDemo.name, CellDemo); app.component(CellCode.name, CellCode); app.component(AnchorHead.name, AnchorHead); app.component(ArcoArticle.name, ArcoArticle); app.mount('#root'); }); ================================================ FILE: packages/arco-vue-docs/locale/en-us.js ================================================ export default { docs: { name: 'Developer Guide', start: 'Quick Start', dark: 'Dark Mode', theme: 'Custom Theme', token: 'Design Token', i18n: 'Internationalization', faq: 'FAQ', changelog: 'Changelog', }, group: { common: 'Common', layout: 'Layout', dataDisplay: 'Data Display', dataEntry: 'Data Entry', feedback: 'Feedback', navigation: 'Navigation', other: 'Other', }, component: { name: 'Component', // 组件名称 icon: 'Icon', button: 'Button', link: 'Link', typography: 'Typography', radio: 'Radio', checkbox: 'Checkbox', switch: 'Switch', anchor: 'Anchor', empty: 'Empty', badge: 'Badge', table: 'Table', tooltip: 'Tooltip', popover: 'Popover', input: 'Input', calendar: 'Calendar', inputNumber: 'InputNumber', alert: 'Alert', result: 'Result', spin: 'Spin', message: 'Message', notification: 'Notification', popconfirm: 'Popconfirm', modal: 'Modal', dropdown: 'Dropdown', backTop: 'BackTop', trigger: 'Trigger', affix: 'Affix', grid: 'Grid', space: 'Space', divider: 'Divider', drawer: 'Drawer', breadcrumb: 'Breadcrumb', pageHeader: 'PageHeader', progress: 'Progress', steps: 'Steps', skeleton: 'Skeleton', slider: 'Slider', rate: 'Rate', avatar: 'Avatar', card: 'Card', carousel: 'Carousel', timeline: 'Timeline', comment: 'Comment', tag: 'Tag', select: 'Select', inputTag: 'InputTag', autoComplete: 'AutoComplete', layout: ' Layout', menu: 'Menu', resizeBox: 'ResizeBox', split: 'Split', statistic: 'Statistic', form: 'Form', collapse: 'Collapse', descriptions: 'Descriptions', pagination: 'Pagination', datePicker: 'DatePicker', timePicker: 'TimePicker', configProvider: 'ConfigProvider', image: 'Image', upload: 'Upload', mention: 'Mention', textarea: 'Textarea', cascader: 'Cascader', tabs: 'Tabs', list: 'List', transfer: 'Transfer', tree: 'Tree', treeSelect: 'TreeSelect', overflow: 'OverflowList', scrollbar: 'Scrollbar', watermark: 'Watermark', verificationCode: 'VerificationCode', colorPicker: 'ColorPicker', }, footer: { design: 'Design', component: 'Component', ecosystem: 'Ecosystem', resource: 'Resource', feedback: 'Feedback', about: 'About Arco', overview: 'Overview', spec: 'Specification', principle: 'Principles', start: 'Quick Start', question: 'Question', changelog: 'Changelog', pro: 'ArcoPro Best Practices', componentFigma: 'Figma Of Component', pluginSparrow: 'Figma Plugin Of Sparrow', iconFigma: 'Figma Of Icon', toolMigrate: 'Code migration', toolArcoCli: 'Arco CLI', toolWebpack: 'Webpack Plugin', designLab: 'DesignLab Design System Lab', material: 'ArcoMaterial Component Market', chartSpace: 'ChartSpace Arco Chart Space', fontMall: 'FontMall FontMall', brand: 'BrandStore BrandStore', mobile: 'ArcoMobile React Mobile', team: 'Arco Team', arcoNews: 'Arco News', cli: 'Arco CLI', dashboard: 'Dashboard', }, tooltip: { expand: 'Expand code', collapse: 'Collapse code', copy: 'Copy code', stackblitz: 'Open in Stackblitz', codeSandbox: 'Open in CodeSandbox', }, icon: { styleAll: 'All', styleOutline: 'Stroke', styleFill: 'Fill', styleColor: 'Color', searchPlaceholder: 'Search icon, click to copy usage', iconClassifyModalTitle: 'Upload an image to search for icons', showConfig: 'Show Config', configTitle: 'Icon Config', configDesc1: 'Global configuration (add the following class to css):', configDesc2: `For a single component, you can directly write the above style to the style of IconXXX`, strokeWidth: 'Stroke width', fontSize: 'Size', strokeLinejoin: 'Line Join', strokeLinecap: 'Line Cap', direction: 'Direction indicator icon', tips: 'Prompt suggestion icon', interactiveButton: 'Interactive button icon', edit: 'Edit icon', media: 'Multimedia icon', logo: 'Trademark icon', general: 'Universal icon', }, proDocs: { name: 'Arco Pro', start: 'Quick start', npmScripts: 'Npm Scripts', directory: 'Directory', layout: 'Layout', routesAndMenu: 'Routes and menu', stateManagement: 'State management - Vuex', stateManagementPinia: 'State management - Pinia', i18n: 'Internationalization', mock: 'Interface and Mock', build: 'Build', permission: 'Permission Control', faq: 'FAQ', }, themeBox: { currentTheme: 'Current theme', autoUseTheme: 'Automatically use theme', install: 'Install', installTheme: 'Install theme', search: 'Search', installingTheme: 'Installing theme...', installThemeSuccess: 'Install theme successfully! ', installThemeError: 'Install theme failed, please try again! ', resetTheme: 'Reset theme', resetThemeSuccess: 'Reset theme successfully! ', openInDesignLab: 'Open in the Design Lab', noResult: 'No related themes', createTheme: 'Go to the Design Lab to create', }, changelogBox: { changelog: 'Changelog', version: 'By version', date: 'By Date', attention: 'Attention', enhancement: 'Enhancement', feature: 'Feature', bugfix: 'Bugfix', style: 'Style', typescript: 'Typescript', chore: 'Chore', to: 'To', filter: 'Filter', }, }; ================================================ FILE: packages/arco-vue-docs/locale/index.js ================================================ import zhCN from './zh-cn'; import enUS from './en-us'; export default { 'zh-CN': zhCN, 'en-US': enUS, }; ================================================ FILE: packages/arco-vue-docs/locale/zh-cn.js ================================================ export default { docs: { name: '开发指南', start: '快速上手', dark: '暗黑模式', theme: '定制主题', token: '设计变量', i18n: '国际化', faq: '常见问题', changelog: '更新日志', }, group: { common: '通用', layout: '布局', dataDisplay: '数据展示', dataEntry: '数据输入', feedback: '反馈', navigation: '导航', other: '其他', }, component: { name: '组件', // 组件名称 calendar: '日历 Calendar', icon: '图标 Icon', button: '按钮 Button', link: '链接 Link', typography: '排版 Typography', empty: '空状态 Empty', badge: '徽标 Badge', table: '表格 Table', tooltip: '文字气泡 Tooltip', popover: '气泡卡片 Popover', input: '输入框 Input', inputNumber: '数字输入框 InputNumber', radio: '单选框 Radio', checkbox: '复选框 Checkbox', switch: '开关 Switch', alert: '警告提示 Alert', result: '结果页 Result', spin: '加载中 Spin', message: '全局提示 Message', drawer: '抽屉 Drawer', breadcrumb: '面包屑 Breadcrumb', pageHeader: '页头 PageHeader', notification: '通知提醒框 Notification', popconfirm: '气泡确认框 Popconfirm', modal: '对话框 Modal', dropdown: '下拉菜单 Dropdown', backTop: '返回顶部 BackTop', trigger: '触发器 Trigger', anchor: '锚点 Anchor', affix: '固钉 Affix', grid: '栅格 Grid', space: '间距 Space', divider: '分割线 Divider', progress: '进度条 Progress', steps: '步骤条 Steps', skeleton: '骨架屏 Skeleton', slider: '滑动输入条 Slider', rate: '评分 Rate', tag: '标签 Tag', select: '选择器 Select', inputTag: '标签输入框 InputTag', autoComplete: '自动补全 AutoComplete', avatar: '头像 Avatar', card: '卡片 Card', carousel: '图片轮播 Carousel', timeline: '时间轴 Timeline', comment: '评论 Comment', layout: '布局 Layout', menu: '菜单 Menu', resizeBox: '伸缩框 ResizeBox', split: '面板分割 Split', statistic: '数值显示 Statistic', form: '表单 Form', collapse: '折叠面板 Collapse', descriptions: '描述列表 Descriptions', pagination: '分页 Pagination', datePicker: '日期选择器 DatePicker', timePicker: '时间选择器 TimePicker', image: '图片 Image', configProvider: '全局配置 ConfigProvider', upload: '上传 Upload', cascader: '级联选择 Cascader', tabs: '标签页 Tabs', list: '列表 List', mention: '提及 Mention', textarea: '文本域 Textarea', transfer: '数据穿梭框 Transfer', tree: '树 Tree', treeSelect: '树选择 TreeSelect', overflow: '折叠列表 OverflowList', scrollbar: '滚动条 Scrollbar', watermark: '水印 Watermark', verificationCode: '验证码输入框 VerificationCode', colorPicker: '颜色选择器 ColorPicker', }, footer: { design: '设计', component: '组件', ecosystem: '生态产品', resource: '资源', feedback: '反馈', about: '关于 Arco', overview: '组件索引', spec: '设计规范', principle: '设计原则', start: '快速开始', question: '常见问题', changelog: '更新日志', pro: 'ArcoPro 中后台最佳实践', componentFigma: '组件库 Figma 资源', pluginSparrow: 'Sparrow Figma 插件', iconFigma: '图标 Figma 资源', toolMigrate: '迁移工具', toolArcoCli: 'Arco CLI', toolWebpack: 'Webpack Plugin', designLab: 'DesignLab 设计系统配置平台', material: 'ArcoMaterial 物料平台', chartSpace: 'ChartSpace 图表库', fontMall: 'FontMall 字体库', brand: 'BrandStore 品牌资源', mobile: 'ArcoMobile 移动端组件库', team: '团队介绍', arcoNews: '双周小黑板', cli: 'Arco CLI', dashboard: 'Dashboard', }, tooltip: { expand: '展开代码', collapse: '收起代码', copy: '复制代码', stackblitz: '在 Stackblitz 打开', codeSandbox: '在 CodeSandbox 打开', }, icon: { styleAll: '全部', styleOutline: '线性图标', styleFill: '面性图标', styleColor: '多色图标', searchPlaceholder: '搜索图标,点击可复制图标用法', iconClassifyModalTitle: '上传图片搜索图标', showConfig: '显示配置', configTitle: '图标配置', configDesc1: '全局配置(将以下的类添加到 css 中):', configDesc2: `单个组件的话可以直接将以上样式写到 IconXXXstyle 中`, strokeWidth: '线宽', fontSize: '图标大小', strokeLinejoin: '拐角', strokeLinecap: '端点', direction: '方向指示类图标', tips: '提示建议类图标', interactiveButton: '交互按钮类图标', edit: '编辑类图标', media: '影音类图标', logo: '商标类图标', general: '通用类图标', }, proDocs: { name: 'Arco Pro 最佳实践', start: '快速上手', npmScripts: 'Npm 命令', directory: '目录结构', layout: '布局', routesAndMenu: '路由和菜单', stateManagement: '状态管理-Vuex(已迁移)', stateManagementPinia: '状态管理-Pinia', i18n: '国际化', mock: '接口和数据模拟', build: '打包构建', permission: '权限控制', faq: '常见问题', }, themeBox: { currentTheme: '当前主题', autoUseTheme: '自动应用主题', install: '安装', installTheme: '安装主题', search: '搜索', installingTheme: '正在安装主题...', installThemeSuccess: '主题安装成功!', installThemeError: '主题安装失败,请重试!', resetTheme: '重置主题', resetThemeSuccess: '重置主题成功!', openInDesignLab: '在主题商店打开', noResult: '没有相关主题', createTheme: '前往主题商店创建', }, changelogBox: { changelog: '更新记录', version: '按版本', date: '按日期', attention: '重点注意', enhancement: '功能优化', feature: '功能升级', bugfix: '问题修复', style: '样式更新', typescript: '类型修正', chore: '架构改动', to: '到', filter: '筛选选项', }, }; ================================================ FILE: packages/arco-vue-docs/package.json ================================================ { "name": "@arco-design/arco-vue-docs", "version": "1.0.0", "private": true, "description": "Arco Design Vue 2.0 Docs", "author": "wangchen ", "homepage": "https://arco.design/vue", "license": "MIT", "scripts": { "start": "arco-vue-scripts dev:site", "build": "arco-vue-scripts build:site", "lint-staged": "npx lint-staged" }, "lint-staged": { "*.{js,ts,jsx,tsx,vue}": [ "eslint --fix", "prettier --write" ], "*.{less,css}": [ "stylelint --fix", "prettier --write" ] }, "devDependencies": { "@arco-design/arco-vue-docs-navbar": "workspace:*", "@arco-design/arco-vue-scripts": "workspace:*", "@arco-design/web-vue": "workspace:*", "@stackblitz/sdk": "^1.11.0", "@types/nprogress": "^0.2.3", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", "axios": "^0.21.4", "clipboard": "^2.0.11", "codesandbox": "^2.2.3", "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-config-prettier": "^8.10.0", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-prettier": "^3.4.1", "eslint-plugin-vue": "^7.20.0", "nprogress": "^0.2.0", "prettier": "^2.8.8", "stylelint": "^13.13.1", "stylelint-config-prettier": "^8.0.2", "stylelint-config-rational-order": "^0.1.2", "stylelint-config-standard": "^20.0.0", "stylelint-order": "^4.1.0", "typescript": "^4.9.5", "vue": "^3.5.13", "vue-i18n": "^9.14.3", "vue-router": "^4.5.0" }, "dependencies": { "@arco-materials/site-utils": "^1.2.0" } } ================================================ FILE: packages/arco-vue-docs/pages/changelog/changelog.vue ================================================ ================================================ FILE: packages/arco-vue-docs/pages/changelog/style/index.less ================================================ ================================================ FILE: packages/arco-vue-docs/pages/icon/__demo__/basic.md ================================================ ```yaml title: zh-CN: 基础使用 en-US: Basic Usage ``` ## zh-CN Arco图标是一个独立的库,需要额外引入并注册使用。 ```ts import { createApp } from 'vue' import ArcoVue from '@arco-design/web-vue'; // 额外引入图标库 import ArcoVueIcon from '@arco-design/web-vue/es/icon'; import App from './App.vue'; import '@arco-design/web-vue/dist/arco.css'; const app = createApp(App); app.use(ArcoVue); app.use(ArcoVueIcon); app.mount('#app'); ``` 注册后可以通过 `` 的形式即可使用Icon。 图标使用 `` 方式渲染,可以直接设置 `style`, `class` 以及 `` 属性。 ### `` Props |参数名|描述|类型|默认值| |---|---|---|:---:| |strokeWidth|线宽|`number`|`4`| |strokeLinecap|端点类型|`'butt' \| 'round' \| 'square'`|`'butt'`| |strokeLinejoin|拐角类型|`'arcs' \| 'bevel' \| 'miter' \| 'miter-clip' \| 'round'`|`'miter'`| |rotate|旋转角度|`number`|`-`| |spin|是否旋转|`boolean`|`false`| |size|尺寸|`number` \| `string`|`-`| --- ## en-US The Arco icon is an independent library and needs to be introduced and registered for use. ```ts import { createApp } from 'vue' import ArcoVue from '@arco-design/web-vue'; // import additional icon library import ArcoVueIcon from '@arco-design/web-vue/es/icon'; import App from './App.vue'; import '@arco-design/web-vue/dist/arco.css'; const app = createApp(App); app.use(ArcoVue); app.use(ArcoVueIcon); app.mount('#app'); ``` After registration, you can use the Icon in the form of ``. Icon use `` render,can settings `style`, `class` and `` attributes. |Attribute|Description|Type|Default| |---|---|---|:---:| |strokeWidth|Stroke width|`number`|`4`| |strokeLinecap|Stroke linecap|`'butt' \| 'round' \| 'square'`|`'butt'`| |strokeLinejoin|Stroke linejoin|`'arcs' \| 'bevel' \| 'miter' \| 'miter-clip' \| 'round'`|`'miter'`| |rotate|Rotate angle|`number`|`-`| |spin|Whether to spin|`boolean`|`false`| |size|Size|`number` \| `string`|`-`| --- ```vue ``` ================================================ FILE: packages/arco-vue-docs/pages/icon/__demo__/icon-font.md ================================================ ```yaml title: zh-CN: 使用 iconfont.cn 项目 en-US: Using the iconfont.cn project ``` ## zh-CN 可以把 iconfont.cn 中的项目添加到 `Icon` 组件的 `type` 中。 调用组件库暴露的工具方法 `Icon.addFromIconfontCn`,把 iconfont.cn 中导出 symbol 的代码传入 src 属性中加载项目图标库。 原理是创建了一个使用 `` 标签来渲染图标的组件。 **暂不支持按需加载** ``` vue ``` ### IconFontOptions |参数名|描述|类型|默认值| |---|---|---|:---:| |src|iconfont.cn 项目生成的在线 js 文件地址|`string`|`-`| |extraProps|传递给内部 Icon 组件的额外属性|`object`|`-`| 在 `src` 都设置有效的情况下,组件在渲染前会自动引入 [iconfont.cn](http://iconfont.cn/ "_blank") 项目中的图标符号集,无需手动引入。 见 [iconfont.cn](https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.15&helptype=code "_blank") 使用帮助: 查看如何生成 js 地址。 ### `` Props |Attribute|Description|Type|Default| |---|---|---|:---:| |type|图标类型|`string`|`-`| |size|大小|`number` \| `string`|`-`| |rotate|旋转角度|`number`|`-`| |spin|是否旋转|`boolean`|`false`| --- ## en-US Items from iconfont.cn can be added to the `type` of the `Icon` component. Call the tool method `Icon.addFromIconfontCn` exposed by the component library, and pass the code that exports the symbol in [iconfont.cn](http://iconfont.cn/ "_blank") into the src attribute to load the project icon library. The idea is to create a component that uses the `` tag to render the icon. ** Currently does not support on-demand loading ** ### IconFontOptions |Name|Description|Type|Default| |---|---|---|:---:| |src|The online js file address generated by the iconfont.cn project|`string`|`-`| |extraProps|Extra properties passed to the inner Icon component|`object`|`-`| When both `src` settings are valid, the component automatically introduces the icon symbol set in the iconfont.cn project before rendering, eliminating the need for manual introduction. See [iconfont.cn](https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.15&helptype=code "_blank") for help on how to generate js addresses. ### `` Props |Attribute|Description|Type|Default| |---|---|---|:---:| |type|Icon type|`string`|`-`| |size|Size|`number` \| `string`|`-`| |rotate|Rotate angle|`number`|`-`| |spin|Whether to spin|`boolean`|`false`| --- ```vue ``` ================================================ FILE: packages/arco-vue-docs/pages/icon/__demo__/spin.md ================================================ ```yaml title: zh-CN: 旋转状态 en-US: Spin Icon ``` ## zh-CN 通过设置 `spin`,可以将图标设置为旋转状态。也可以使用 `rotate` 自定义旋转角度。 --- ## en-US By setting `spin`, the icon can be set to a rotating state. You can also use `rotate` to customize the rotation angle. --- ```vue ``` ================================================ FILE: packages/arco-vue-docs/pages/icon/__demo__/tree-shaking.md ================================================ ```yaml title: zh-CN: 按需加载 en-US: Tree shaking ``` ## zh-CN 可以通过单独引入图标的方式实现按需加载。 --- ## en-US The on-demand import can be achieved by separately introducing icons. --- ```vue ``` ================================================ FILE: packages/arco-vue-docs/pages/icon/icon-demo.vue ================================================ ================================================ FILE: packages/arco-vue-docs/pages/token/tokens.ts ================================================ export const tokens = [ { name: '主色', nameEN: 'Primary', type: 'color', tokens: [ { name: 'primary-6', desc: '常规', descEN: 'Normal', value: 'rgb(var(--arcoblue-6))', cssvar: true, }, { name: 'primary-5', desc: '悬浮(hover)', descEN: 'Hover', value: 'rgb(var(--arcoblue-5))', cssvar: true, }, { name: 'primary-7', desc: '点击(click)', descEN: 'Click', value: 'rgb(var(--arcoblue-7))', cssvar: true, }, { name: 'primary-4', desc: '特殊场景', descEN: 'Special scene', value: 'rgb(var(--arcoblue-4))', cssvar: true, }, { name: 'primary-3', desc: '一般禁用', descEN: 'Normally disabled', value: 'rgb(var(--arcoblue-3))', cssvar: true, }, { name: 'primary-2', desc: '文字禁用', descEN: 'Text disabled', value: 'rgb(var(--arcoblue-2))', cssvar: true, }, { name: 'primary-1', desc: '浅色/白底悬浮', descEN: 'Light/white suspension', value: 'rgb(var(--arcoblue-1))', cssvar: true, }, ], }, { name: '成功色', nameEN: 'Success', type: 'color', tokens: [ { name: 'success-6', desc: '常规', descEN: 'Normal', value: 'rgb(var(--green-6))', cssvar: true, }, { name: 'success-5', desc: '悬浮(hover)', descEN: 'Hover', value: 'rgb(var(--green-5))', cssvar: true, }, { name: 'success-7', desc: '点击(click)', descEN: 'Click', value: 'rgb(var(--green-7))', cssvar: true, }, { name: 'success-4', desc: '特殊场景', descEN: 'Special scene', value: 'rgb(var(--green-4))', cssvar: true, }, { name: 'success-3', desc: '一般禁用', descEN: 'Normally disabled', value: 'rgb(var(--green-3))', cssvar: true, }, { name: 'success-2', desc: '文字禁用', descEN: 'Text disabled', value: 'rgb(var(--green-2))', cssvar: true, }, { name: 'success-1', desc: '浅色/白底悬浮', descEN: 'Light/white suspension', value: 'rgb(var(--green-1))', cssvar: true, }, ], }, { name: '警示色', nameEN: 'Warning', type: 'color', tokens: [ { name: 'warning-6', desc: '常规', descEN: 'Normal', value: 'rgb(var(--orange-6))', cssvar: true, }, { name: 'warning-5', desc: '悬浮(hover)', descEN: 'Hover', value: 'rgb(var(--orange-5))', cssvar: true, }, { name: 'warning-7', desc: '点击(click)', descEN: 'Click', value: 'rgb(var(--orange-7))', cssvar: true, }, { name: 'warning-4', desc: '特殊场景', descEN: 'Special scene', value: 'rgb(var(--orange-4))', cssvar: true, }, { name: 'warning-3', desc: '一般禁用', descEN: 'Normally disabled', value: 'rgb(var(--orange-3))', cssvar: true, }, { name: 'warning-2', desc: '文字禁用', descEN: 'Text disabled', value: 'rgb(var(--orange-2))', cssvar: true, }, { name: 'warning-1', desc: '浅色/白底悬浮', descEN: 'Light/white suspension', value: 'rgb(var(--orange-1))', cssvar: true, }, ], }, { name: '错误色', nameEN: 'Danger', type: 'color', tokens: [ { name: 'danger-6', desc: '常规', descEN: 'Normal', value: 'rgb(var(--red-6))', cssvar: true, }, { name: 'danger-5', desc: '悬浮(hover)', descEN: 'Hover', value: 'rgb(var(--red-5))', cssvar: true, }, { name: 'danger-7', desc: '点击(click)', descEN: 'Click', value: 'rgb(var(--red-7))', cssvar: true, }, { name: 'danger-4', desc: '特殊场景', descEN: 'Special scene', value: 'rgb(var(--red-4))', cssvar: true, }, { name: 'danger-3', desc: '一般禁用', descEN: 'Normally disabled', value: 'rgb(var(--red-3))', cssvar: true, }, { name: 'danger-2', desc: '文字禁用', descEN: 'Text disabled', value: 'rgb(var(--red-2))', cssvar: true, }, { name: 'danger-1', desc: '浅色/白底悬浮', descEN: 'Light/white suspension', value: 'rgb(var(--red-1))', cssvar: true, }, ], }, { name: '链接色', nameEN: 'Link', type: 'color', tokens: [ { name: 'link-6', desc: '常规', descEN: 'Normal', value: 'rgb(var(--arcoblue-6))', cssvar: true, }, { name: 'link-5', desc: '悬浮(hover)', descEN: 'Hover', value: 'rgb(var(--arcoblue-5))', cssvar: true, }, { name: 'link-7', desc: '点击(click)', descEN: 'Click', value: 'rgb(var(--arcoblue-7))', cssvar: true, }, { name: 'link-4', desc: '特殊场景', descEN: 'Special scene', value: 'rgb(var(--arcoblue-4))', cssvar: true, }, { name: 'link-3', desc: '一般禁用', descEN: 'Normally disabled', value: 'rgb(var(--arcoblue-3))', cssvar: true, }, { name: 'link-2', desc: '文字禁用', descEN: 'Text disabled', value: 'rgb(var(--arcoblue-2))', cssvar: true, }, { name: 'link-1', desc: '浅色/白底悬浮', descEN: 'Light/white suspension', value: 'rgb(var(--arcoblue-1))', cssvar: true, }, ], }, { name: '边框颜色', nameEN: 'Border Color', type: 'color', tokens: [ { name: 'color-border-1', desc: '浅色', descEN: 'Light color', value: 'var(--color-neutral-2)', cssvar: true, }, { name: 'color-border-2', desc: '一般', descEN: 'Normal', value: 'var(--color-neutral-3)', cssvar: true, }, { name: 'color-border-3', desc: '深/悬浮', descEN: 'Deep/Hover', value: 'var(--color-neutral-4)', cssvar: true, }, { name: 'color-border-4', desc: '重/按钮描边', descEN: 'Heavy/Button Border', value: 'var(--color-neutral-6)', cssvar: true, }, ], }, { name: '填充颜色', nameEN: 'Fill Color', type: 'color', tokens: [ { name: 'color-fill-1', desc: '浅/禁用', descEN: 'Light/Disabled', value: 'var(--color-neutral-1)', darkValue: 'fade(#FFF, 4%)', cssvar: true, }, { name: 'color-fill-2', desc: '常规/白底悬浮', descEN: 'Normal/White Hover', value: 'var(--color-neutral-2)', darkValue: 'fade(#FFF, 8%)', cssvar: true, }, { name: 'color-fill-3', desc: '深/灰底悬浮', descEN: 'Deep/Gray Hover', value: 'var(--color-neutral-3)', darkValue: 'fade(#FFF, 12%)', cssvar: true, }, { name: 'color-fill-4', desc: '重/特殊场景', descEN: 'Heavy/Special scene', value: 'var(--color-neutral-4)', darkValue: 'fade(#FFF, 16%)', cssvar: true, }, ], }, { name: '文字颜色', type: 'color', tokens: [ { name: 'color-text-1', desc: '强调/正文标题', descEN: 'Emphasis/Body Title', value: 'var(--color-neutral-10)', darkValue: 'fade(#FFF, 90%)', cssvar: true, }, { name: 'color-text-2', desc: '次强调/正文标题', descEN: 'Sub-Emphasis/Body Title', value: 'var(--color-neutral-8)', darkValue: 'fade(#FFF, 70%)', cssvar: true, }, { name: 'color-text-3', desc: '次要信息', descEN: 'Secondary information', value: 'var(--color-neutral-6)', darkValue: 'fade(#FFF, 50%)', cssvar: true, }, { name: 'color-text-4', desc: '置灰信息', descEN: 'Grayed out information', value: 'var(--color-neutral-4)', darkValue: 'fade(#FFF, 30%)', cssvar: true, }, ], }, { name: '背景颜色', nameEN: 'Background Color', type: 'color', tokens: [ { name: 'color-bg-1', desc: '整体背景色', descEN: 'Overall background color', value: '#FFF', darkValue: '#17171A', cssvar: true, }, { name: 'color-bg-2', desc: '一级容器背景', descEN: 'Primary container background', value: '#FFF', darkValue: '#232324', cssvar: true, }, { name: 'color-bg-3', desc: '二级容器背景', descEN: 'Secondary container background', value: '#FFF', darkValue: '#2A2A2B', cssvar: true, }, { name: 'color-bg-4', desc: '三级容器背景', descEN: 'Tertiary container background', value: '#FFF', darkValue: '#313132', cssvar: true, }, { name: 'color-bg-5', desc: '下拉弹出框、Tooltip 背景颜色', descEN: 'Popup, Tooltip background color', value: '#FFF', darkValue: '#373739', cssvar: true, }, { name: 'color-bg-white', desc: '白色背景', descEN: 'White background', value: '#FFF', darkValue: '#F6F6F6', cssvar: true, }, ], }, // size { name: '字体大小', nameEN: 'Font Size', type: 'size', tokens: [ { name: 'font-size-body-3', desc: '正文-常规', descEN: 'Body - General', value: '14px', }, { name: 'font-size-body-2', desc: '正文-常规-小', descEN: 'Body - Regular - Small', value: '13px', }, { name: 'font-size-body-1', desc: '辅助文案/次要文案', descEN: 'Auxiliary Copywriting/Secondary Copywriting', value: '12px', }, { name: 'font-size-caption', desc: '水印文本', descEN: 'Watermark text', value: '12px', }, { name: 'font-size-title-1', desc: '标题-小', descEN: 'Title - Small', value: '16px', }, { name: 'font-size-title-2', desc: '标题-中', descEN: 'Title - Medium', value: '20px', }, { name: 'font-size-title-3', desc: '标题-大', descEN: 'Title - Large', value: '24px', }, { name: 'font-size-display-1', desc: '运营标题-小', descEN: 'Operational Title - Small', value: '36px', }, { name: 'font-size-display-2', desc: '运营标题-中', descEN: 'Operational Title - Medium', value: '48px', }, { name: 'font-size-display-3', desc: '运营标题-大', descEN: 'Operational Title - Large', value: '56px', }, ], }, { name: '字重', nameEN: 'Font Wight', type: 'size', tokens: [ { name: 'font-weight-400', desc: '常规', descEN: 'Normal', value: '400', }, { name: 'font-weight-500', desc: '中等(加粗)', descEN: 'Medium (bold)', value: '500', }, { name: 'font-weight-600', desc: '半粗', descEN: 'Half thick', value: '600', }, { name: 'font-weight-700', desc: '粗体', descEN: 'Bold', value: '700', }, { name: 'font-weight-800', desc: '中黑', descEN: 'Medium black', value: '800', }, { name: 'font-weight-900', desc: '黑体', descEN: 'Black body', value: '900', }, { name: 'font-weight-300', desc: '细体', descEN: 'Fine body', value: '300', }, { name: 'font-weight-200', desc: '纤细', descEN: 'Slim', value: '200', }, { name: 'font-weight-100', desc: '极细', descEN: 'Very fine', value: '100', }, ], }, { name: '尺寸', nameEN: 'Size', type: 'size', tokens: [ { name: 'size-none', desc: '0', value: '0', }, { name: 'size-1', desc: '4px', value: '4px', }, { name: 'size-2', desc: '8px', value: '8px', }, { name: 'size-3', desc: '12px', value: '12px', }, { name: 'size-4', desc: '迷你(24px)', value: '16px', }, { name: 'size-5', desc: '20px', value: '20px', }, { name: 'size-N', desc: '变量对应的值为 (4 * N)px 大小', descEN: 'The corresponding value of the variable is (4 * N)px size', value: '(4 * N)px', }, { name: 'size-50', desc: '200px', value: '200px', }, ], }, { name: '组件尺寸', nameEN: 'Component Size', type: 'size', tokens: [ { name: 'size-mini', desc: '迷你(24px)', descEN: 'mini(24px)', value: '@size-6', }, { name: 'size-small', desc: '较小(28px)', descEN: 'small(28px)', value: '@size-7', }, { name: 'size-default', desc: '中等(32px)', descEN: 'medium(32px)', value: '@size-8', }, { name: 'size-large', desc: '较大(36px)', descEN: 'large(36px)', value: '@size-9', }, ], }, { name: '边框宽度', nameEN: 'Border Size', type: 'size', tokens: [ { name: 'border-none', desc: '无边框', descEN: 'None Border', value: '0', }, { name: 'border-1', desc: '常规', descEN: 'Normal', value: '1px', }, { name: 'border-2', desc: '较粗', descEN: 'Thicker', value: '2px', }, { name: 'border-3', desc: '粗', descEN: 'Bold', value: '3px', }, ], }, { name: '边框圆角', nameEN: 'Border Radius', type: 'size', tokens: [ { name: 'border-radius-none', desc: '直角', descEN: 'Right angle', value: '0', cssvar: true, }, { name: 'border-radius-small', desc: '圆角-常规', descEN: 'Rounded Corners - Regular', value: '2px', cssvar: true, }, { name: 'border-radius-medium', desc: '圆角-中等', descEN: 'Rounded Corners - Medium', value: '4px', cssvar: true, }, { name: 'border-radius-large', desc: '圆角-较大', descEN: 'Rounded Corners - Larger', value: '8px', cssvar: true, }, { name: 'border-radius-circle', desc: '圆角-全圆角', descEN: 'Rounded Corners - Full Rounded Corners', value: '50%', cssvar: true, }, ], }, { name: '阴影', nameEN: 'Shadow', type: 'size', tokens: [ { name: 'shadow-special', desc: '特殊阴影', descEN: 'Special shade', value: '0 0 1px rgba(0, 0, 0, 0.3)', }, { name: 'shadow1-center', desc: '阴影样式1', descEN: 'shadow style 1', value: '0 -2px 5px rgba(0, 0, 0, 0.1)', }, { name: 'shadow2-center', desc: '阴影样式2', descEN: 'shadow style 2', value: '0 0 10px rgba(0, 0, 0, 0.1)', }, { name: 'shadow3-center', desc: '阴影样式3', descEN: 'shadow style 3', value: '0 0 20px rgba(0, 0, 0, 0.1)', }, ], }, ]; ================================================ FILE: packages/arco-vue-docs/router.ts ================================================ import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import nProgress from 'nprogress'; const Start = () => import('./docs/start.zh-CN.md'); const StartEn = () => import('./docs/start.en-US.md'); const Dark = () => import('./docs/dark.zh-CN.md'); const DarkEn = () => import('./docs/dark.en-US.md'); const Theme = () => import('./docs/theme.zh-CN.md'); const ThemeEn = () => import('./docs/theme.en-US.md'); const I18n = () => import('./docs/i18n.zh-CN.md'); const I18nEn = () => import('./docs/i18n.en-US.md'); const Changelog = () => import('./pages/changelog/changelog.vue'); const Button = () => import('@web-vue/components/button/README.zh-CN.md'); const ButtonEn = () => import('@web-vue/components/button/README.en-US.md'); const Icon = () => import('./pages/icon/icon-demo.vue'); const Link = () => import('@web-vue/components/link/README.zh-CN.md'); const LinkEn = () => import('@web-vue/components/link/README.en-US.md'); const Typography = () => import('@web-vue/components/typography/README.zh-CN.md'); const TypographyEn = () => import('@web-vue/components/typography/README.en-US.md'); const Divider = () => import('@web-vue/components/divider/README.zh-CN.md'); const DividerEn = () => import('@web-vue/components/divider/README.en-US.md'); const Grid = () => import('@web-vue/components/grid/README.zh-CN.md'); const GridEn = () => import('@web-vue/components/grid/README.en-US.md'); const Layout = () => import('@web-vue/components/layout/README.zh-CN.md'); const LayoutEn = () => import('@web-vue/components/layout/README.en-US.md'); const Space = () => import('@web-vue/components/space/README.zh-CN.md'); const SpaceEn = () => import('@web-vue/components/space/README.en-US.md'); const Avatar = () => import('@web-vue/components/avatar/README.zh-CN.md'); const AvatarEn = () => import('@web-vue/components/avatar/README.en-US.md'); const Badge = () => import('@web-vue/components/badge/README.zh-CN.md'); const BadgeEn = () => import('@web-vue/components/badge/README.en-US.md'); const Card = () => import('@web-vue/components/card/README.zh-CN.md'); const CardEn = () => import('@web-vue/components/card/README.en-US.md'); const Carousel = () => import('@web-vue/components/carousel/README.zh-CN.md'); const CarouselEn = () => import('@web-vue/components/carousel/README.en-US.md'); const Collapse = () => import('@web-vue/components/collapse/README.zh-CN.md'); const CollapseEn = () => import('@web-vue/components/collapse/README.en-US.md'); const Calendar = () => import('@web-vue/components/calendar/README.zh-CN.md'); const CalendarEn = () => import('@web-vue/components/calendar/README.en-US.md'); const Comment = () => import('@web-vue/components/comment/README.zh-CN.md'); const CommentEn = () => import('@web-vue/components/comment/README.en-US.md'); const Descriptions = () => import('@web-vue/components/descriptions/README.zh-CN.md'); const DescriptionsEn = () => import('@web-vue/components/descriptions/README.en-US.md'); const Empty = () => import('@web-vue/components/empty/README.zh-CN.md'); const EmptyEn = () => import('@web-vue/components/empty/README.en-US.md'); const Image = () => import('@web-vue/components/image/README.zh-CN.md'); const ImageEn = () => import('@web-vue/components/image/README.en-US.md'); const List = () => import('@web-vue/components/list/README.zh-CN.md'); const ListEn = () => import('@web-vue/components/list/README.en-US.md'); const Popover = () => import('@web-vue/components/popover/README.zh-CN.md'); const PopoverEn = () => import('@web-vue/components/popover/README.en-US.md'); const Statistic = () => import('@web-vue/components/statistic/README.zh-CN.md'); const StatisticEn = () => import('@web-vue/components/statistic/README.en-US.md'); const Table = () => import('@web-vue/components/table/README.zh-CN.md'); const TableEn = () => import('@web-vue/components/table/README.en-US.md'); const Tabs = () => import('@web-vue/components/tabs/README.zh-CN.md'); const TabsEn = () => import('@web-vue/components/tabs/README.en-US.md'); const Tag = () => import('@web-vue/components/tag/README.zh-CN.md'); const TagEn = () => import('@web-vue/components/tag/README.en-US.md'); const Timeline = () => import('@web-vue/components/timeline/README.zh-CN.md'); const TimelineEn = () => import('@web-vue/components/timeline/README.en-US.md'); const Tooltip = () => import('@web-vue/components/tooltip/README.zh-CN.md'); const TooltipEn = () => import('@web-vue/components/tooltip/README.en-US.md'); const Tree = () => import('@web-vue/components/tree/README.zh-CN.md'); const TreeEn = () => import('@web-vue/components/tree/README.en-US.md'); const AutoComplete = () => import('@web-vue/components/auto-complete/README.zh-CN.md'); const AutoCompleteEn = () => import('@web-vue/components/auto-complete/README.en-US.md'); const Cascader = () => import('@web-vue/components/cascader/README.zh-CN.md'); const CascaderEn = () => import('@web-vue/components/cascader/README.en-US.md'); const Checkbox = () => import('@web-vue/components/checkbox/README.zh-CN.md'); const CheckboxEn = () => import('@web-vue/components/checkbox/README.en-US.md'); const DatePicker = () => import('@web-vue/components/date-picker/README.zh-CN.md'); const DatePickerEn = () => import('@web-vue/components/date-picker/README.en-US.md'); const Form = () => import('@web-vue/components/form/README.zh-CN.md'); const FormEn = () => import('@web-vue/components/form/README.en-US.md'); const Input = () => import('@web-vue/components/input/README.zh-CN.md'); const InputEn = () => import('@web-vue/components/input/README.en-US.md'); const InputNumber = () => import('@web-vue/components/input-number/README.zh-CN.md'); const InputNumberEn = () => import('@web-vue/components/input-number/README.en-US.md'); const InputTag = () => import('@web-vue/components/input-tag/README.zh-CN.md'); const InputTagEn = () => import('@web-vue/components/input-tag/README.en-US.md'); const Mention = () => import('@web-vue/components/mention/README.zh-CN.md'); const MentionEn = () => import('@web-vue/components/mention/README.en-US.md'); const Radio = () => import('@web-vue/components/radio/README.zh-CN.md'); const RadioEn = () => import('@web-vue/components/radio/README.en-US.md'); const Rate = () => import('@web-vue/components/rate/README.zh-CN.md'); const RateEn = () => import('@web-vue/components/rate/README.en-US.md'); const Select = () => import('@web-vue/components/select/README.zh-CN.md'); const SelectEn = () => import('@web-vue/components/select/README.en-US.md'); const Slider = () => import('@web-vue/components/slider/README.zh-CN.md'); const SliderEn = () => import('@web-vue/components/slider/README.en-US.md'); const Switch = () => import('@web-vue/components/switch/README.zh-CN.md'); const SwitchEn = () => import('@web-vue/components/switch/README.en-US.md'); const Textarea = () => import('@web-vue/components/textarea/README.zh-CN.md'); const TextareaEn = () => import('@web-vue/components/textarea/README.en-US.md'); const TimePicker = () => import('@web-vue/components/time-picker/README.zh-CN.md'); const TimePickerEn = () => import('@web-vue/components/time-picker/README.en-US.md'); const Transfer = () => import('@web-vue/components/transfer/README.zh-CN.md'); const TransferEn = () => import('@web-vue/components/transfer/README.en-US.md'); const Upload = () => import('@web-vue/components/upload/README.zh-CN.md'); const UploadEn = () => import('@web-vue/components/upload/README.en-US.md'); const TreeSelect = () => import('@web-vue/components/tree-select/README.zh-CN.md'); const TreeSelectEn = () => import('@web-vue/components/tree-select/README.en-US.md'); const Alert = () => import('@web-vue/components/alert/README.zh-CN.md'); const AlertEn = () => import('@web-vue/components/alert/README.en-US.md'); const Drawer = () => import('@web-vue/components/drawer/README.zh-CN.md'); const DrawerEn = () => import('@web-vue/components/drawer/README.en-US.md'); const Message = () => import('@web-vue/components/message/README.zh-CN.md'); const MessageEn = () => import('@web-vue/components/message/README.en-US.md'); const Modal = () => import('@web-vue/components/modal/README.zh-CN.md'); const ModalEn = () => import('@web-vue/components/modal/README.en-US.md'); const Notification = () => import('@web-vue/components/notification/README.zh-CN.md'); const NotificationEn = () => import('@web-vue/components/notification/README.en-US.md'); const Popconfirm = () => import('@web-vue/components/popconfirm/README.zh-CN.md'); const PopconfirmEn = () => import('@web-vue/components/popconfirm/README.en-US.md'); const Progress = () => import('@web-vue/components/progress/README.zh-CN.md'); const ProgressEn = () => import('@web-vue/components/progress/README.en-US.md'); const Result = () => import('@web-vue/components/result/README.zh-CN.md'); const ResultEn = () => import('@web-vue/components/result/README.en-US.md'); const Spin = () => import('@web-vue/components/spin/README.zh-CN.md'); const SpinEn = () => import('@web-vue/components/spin/README.en-US.md'); const Skeleton = () => import('@web-vue/components/skeleton/README.zh-CN.md'); const SkeletonEn = () => import('@web-vue/components/skeleton/README.en-US.md'); const Breadcrumb = () => import('@web-vue/components/breadcrumb/README.zh-CN.md'); const BreadcrumbEn = () => import('@web-vue/components/breadcrumb/README.en-US.md'); const Dropdown = () => import('@web-vue/components/dropdown/README.zh-CN.md'); const DropdownEn = () => import('@web-vue/components/dropdown/README.en-US.md'); const Menu = () => import('@web-vue/components/menu/README.zh-CN.md'); const MenuEn = () => import('@web-vue/components/menu/README.en-US.md'); const PageHeader = () => import('@web-vue/components/page-header/README.zh-CN.md'); const PageHeaderEn = () => import('@web-vue/components/page-header/README.en-US.md'); const Pagination = () => import('@web-vue/components/pagination/README.zh-CN.md'); const PaginationEn = () => import('@web-vue/components/pagination/README.en-US.md'); const Steps = () => import('@web-vue/components/steps/README.zh-CN.md'); const StepsEn = () => import('@web-vue/components/steps/README.en-US.md'); const Affix = () => import('@web-vue/components/affix/README.zh-CN.md'); const AffixEn = () => import('@web-vue/components/affix/README.en-US.md'); const Anchor = () => import('@web-vue/components/anchor/README.zh-CN.md'); const AnchorEn = () => import('@web-vue/components/anchor/README.en-US.md'); const BackTop = () => import('@web-vue/components/back-top/README.zh-CN.md'); const BackTopEn = () => import('@web-vue/components/back-top/README.en-US.md'); const ConfigProvider = () => import('@web-vue/components/config-provider/README.zh-CN.md'); const ConfigProviderEn = () => import('@web-vue/components/config-provider/README.en-US.md'); const ResizeBox = () => import('@web-vue/components/resize-box/README.zh-CN.md'); const ResizeBoxEn = () => import('@web-vue/components/resize-box/README.en-US.md'); const Trigger = () => import('@web-vue/components/trigger/README.zh-CN.md'); const TriggerEn = () => import('@web-vue/components/trigger/README.en-US.md'); const Split = () => import('@web-vue/components/split/README.zh-CN.md'); const SplitEn = () => import('@web-vue/components/split/README.en-US.md'); const OverflowList = () => import('@web-vue/components/overflow-list/README.zh-CN.md'); const OverflowListEn = () => import('@web-vue/components/overflow-list/README.en-US.md'); const Scrollbar = () => import('@web-vue/components/scrollbar/README.zh-CN.md'); const ScrollbarEn = () => import('@web-vue/components/scrollbar/README.en-US.md'); const Watermark = () => import('@web-vue/components/watermark/README.zh-CN.md'); const WatermarkEn = () => import('@web-vue/components/watermark/README.en-US.md'); const VerificationCode = () => import('@web-vue/components/verification-code/README.zh-CN.md'); const VerificationCodeEn = () => import('@web-vue/components/verification-code/README.en-US.md'); const ColorPicker = () => import('@web-vue/components/color-picker/README.zh-CN.md'); const ColorPickerEn = () => import('@web-vue/components/color-picker/README.en-US.md'); const docs = [ { name: 'start', component: Start, componentEn: StartEn, }, { name: 'dark', component: Dark, componentEn: DarkEn, }, { name: 'theme', component: Theme, componentEn: ThemeEn, }, { name: 'token', component: () => import('./pages/token/token.vue'), }, { name: 'i18n', component: I18n, componentEn: I18nEn, }, { name: 'faq', component: () => import('./docs/faq.zh-CN.md'), componentEn: () => import('./docs/faq.en-US.md'), }, { name: 'changelog', component: Changelog, }, ]; const proDocs = [ { name: 'start', component: () => import('./docs/pro/start.zh-CN.md'), componentEn: () => import('./docs/pro/start.en-US.md'), }, { name: 'npmScripts', component: () => import('./docs/pro/npm-scripts.zh-CN.md'), componentEn: () => import('./docs/pro/npm-scripts.en-US.md'), }, { name: 'directory', component: () => import('./docs/pro/directory.zh-CN.md'), componentEn: () => import('./docs/pro/directory.en-US.md'), }, { name: 'layout', component: () => import('./docs/pro/layout.zh-CN.md'), componentEn: () => import('./docs/pro/layout.en-US.md'), }, { name: 'routesAndMenu', component: () => import('./docs/pro/routes-and-menu.zh-CN.md'), componentEn: () => import('./docs/pro/routes-and-menu.en-US.md'), }, { name: 'permission', component: () => import('./docs/pro/permission.zh-CN.md'), componentEn: () => import('./docs/pro/permission.en-US.md'), }, { name: 'stateManagementPinia', component: () => import('./docs/pro/state-management-pinia.zh-CN.md'), componentEn: () => import('./docs/pro/state-management-pinia.en-US.md'), }, { name: 'stateManagement', component: () => import('./docs/pro/state-management.zh-CN.md'), componentEn: () => import('./docs/pro/state-management.en-US.md'), }, { name: 'i18n', component: () => import('./docs/pro/i18n.zh-CN.md'), componentEn: () => import('./docs/pro/i18n.en-US.md'), }, { name: 'mock', component: () => import('./docs/pro/mock.zh-CN.md'), componentEn: () => import('./docs/pro/mock.en-US.md'), }, { name: 'build', component: () => import('./docs/pro/build.zh-CN.md'), componentEn: () => import('./docs/pro/build.en-US.md'), }, { name: 'faq', component: () => import('./docs/pro/faq.zh-CN.md'), componentEn: () => import('./docs/pro/faq.en-US.md'), }, ]; const components = [ { name: 'common', list: [ { name: 'button', component: Button, componentEn: ButtonEn, }, { name: 'icon', component: Icon, }, { name: 'link', component: Link, componentEn: LinkEn, }, { name: 'typography', component: Typography, componentEn: TypographyEn, }, ], }, { name: 'layout', list: [ { name: 'divider', component: Divider, componentEn: DividerEn, }, { name: 'grid', component: Grid, componentEn: GridEn, }, { name: 'layout', component: Layout, componentEn: LayoutEn, }, { name: 'space', component: Space, componentEn: SpaceEn, }, ], }, { name: 'dataDisplay', list: [ { name: 'avatar', component: Avatar, componentEn: AvatarEn, }, { name: 'badge', component: Badge, componentEn: BadgeEn, }, { name: 'calendar', component: Calendar, componentEn: CalendarEn, }, { name: 'card', component: Card, componentEn: CardEn, }, { name: 'carousel', component: Carousel, componentEn: CarouselEn, }, { name: 'collapse', component: Collapse, componentEn: CollapseEn, }, { name: 'comment', component: Comment, componentEn: CommentEn, }, { name: 'descriptions', component: Descriptions, componentEn: DescriptionsEn, }, { name: 'empty', component: Empty, componentEn: EmptyEn, }, { name: 'image', component: Image, componentEn: ImageEn, }, { name: 'list', component: List, componentEn: ListEn, }, { name: 'popover', component: Popover, componentEn: PopoverEn, }, { name: 'statistic', component: Statistic, componentEn: StatisticEn, }, { name: 'table', component: Table, componentEn: TableEn, }, { name: 'tabs', component: Tabs, componentEn: TabsEn, }, { name: 'tag', component: Tag, componentEn: TagEn, }, { name: 'timeline', component: Timeline, componentEn: TimelineEn, }, { name: 'tooltip', component: Tooltip, componentEn: TooltipEn, }, { name: 'tree', component: Tree, componentEn: TreeEn, }, ], }, { name: 'dataEntry', list: [ { name: 'autoComplete', component: AutoComplete, componentEn: AutoCompleteEn, }, { name: 'cascader', component: Cascader, componentEn: CascaderEn, }, { name: 'checkbox', component: Checkbox, componentEn: CheckboxEn, }, { name: 'colorPicker', component: ColorPicker, componentEn: ColorPickerEn, }, { name: 'datePicker', component: DatePicker, componentEn: DatePickerEn, }, { name: 'form', component: Form, componentEn: FormEn, }, { name: 'input', component: Input, componentEn: InputEn, }, { name: 'inputNumber', component: InputNumber, componentEn: InputNumberEn, }, { name: 'verificationCode', component: VerificationCode, componentEn: VerificationCodeEn, }, { name: 'inputTag', component: InputTag, componentEn: InputTagEn, }, { name: 'mention', component: Mention, componentEn: MentionEn, }, { name: 'radio', component: Radio, componentEn: RadioEn, }, { name: 'rate', component: Rate, componentEn: RateEn, }, { name: 'select', component: Select, componentEn: SelectEn, }, { name: 'slider', component: Slider, componentEn: SliderEn, }, { name: 'switch', component: Switch, componentEn: SwitchEn, }, { name: 'textarea', component: Textarea, componentEn: TextareaEn, }, { name: 'timePicker', component: TimePicker, componentEn: TimePickerEn, }, { name: 'transfer', component: Transfer, componentEn: TransferEn, }, { name: 'treeSelect', component: TreeSelect, componentEn: TreeSelectEn, }, { name: 'upload', component: Upload, componentEn: UploadEn, }, ], }, { name: 'feedback', list: [ { name: 'alert', component: Alert, componentEn: AlertEn, }, { name: 'drawer', component: Drawer, componentEn: DrawerEn, }, { name: 'message', component: Message, componentEn: MessageEn, }, { name: 'modal', component: Modal, componentEn: ModalEn, }, { name: 'notification', component: Notification, componentEn: NotificationEn, }, { name: 'popconfirm', component: Popconfirm, componentEn: PopconfirmEn, }, { name: 'progress', component: Progress, componentEn: ProgressEn, }, { name: 'result', component: Result, componentEn: ResultEn, }, { name: 'spin', component: Spin, componentEn: SpinEn, }, { name: 'skeleton', component: Skeleton, componentEn: SkeletonEn, }, ], }, { name: 'navigation', list: [ { name: 'breadcrumb', component: Breadcrumb, componentEn: BreadcrumbEn, }, { name: 'dropdown', component: Dropdown, componentEn: DropdownEn, }, { name: 'menu', component: Menu, componentEn: MenuEn, }, { name: 'pageHeader', component: PageHeader, componentEn: PageHeaderEn, }, { name: 'pagination', component: Pagination, componentEn: PaginationEn, }, { name: 'steps', component: Steps, componentEn: StepsEn, }, ], }, { name: 'other', list: [ { name: 'affix', component: Affix, componentEn: AffixEn, }, { name: 'anchor', component: Anchor, componentEn: AnchorEn, }, { name: 'backTop', component: BackTop, componentEn: BackTopEn, }, { name: 'configProvider', component: ConfigProvider, componentEn: ConfigProviderEn, }, { name: 'resizeBox', component: ResizeBox, componentEn: ResizeBoxEn, }, { name: 'trigger', component: Trigger, componentEn: TriggerEn, }, { name: 'split', component: Split, componentEn: SplitEn, }, { name: 'overflow', component: OverflowList, componentEn: OverflowListEn, }, { name: 'scrollbar', component: Scrollbar, componentEn: ScrollbarEn, }, { name: 'watermark', component: Watermark, componentEn: WatermarkEn, }, ], }, ]; function toKebabCase(string: string) { return string.replace(/[A-Z]+/g, (match, offset) => { return `${offset > 0 ? '-' : ''}${match.toLocaleLowerCase()}`; }); } interface ComponentMenuGroup { name: string; list: Array<{ name: string; path: string; }>; } const routes: RouteRecordRaw[] = []; const docsMenu = []; for (const item of docs) { const path = `/vue/docs/${toKebabCase(item.name)}`; routes.push( { path, component: item.component, }, { path: `/vue/en-US/docs/${toKebabCase(item.name)}`, component: item.componentEn ?? item.component, } ); docsMenu.push({ name: item.name, path, }); } const componentMenu: ComponentMenuGroup[] = []; for (const group of components) { const menuGroup: ComponentMenuGroup = { name: group.name, list: [], }; for (const item of group.list) { const path = `/vue/component/${toKebabCase(item.name)}`; routes.push( { path, component: item.component, }, { path: `/vue/en-US/component/${toKebabCase(item.name)}`, component: item.componentEn ?? item.component, } ); menuGroup.list.push({ name: item.name, path, }); } componentMenu.push(menuGroup); } const proDocsMenu: { path: string; name: string }[] = []; proDocs.forEach((item) => { const path = `/vue/docs/pro/${toKebabCase(item.name)}`; routes.push( { path, component: item.component, }, { path: `/vue/en-US/docs/pro/${toKebabCase(item.name)}`, component: item.componentEn ?? item.component, } ); proDocsMenu.push({ name: item.name, path, }); }); // Add redirects for unmatched routes at the end routes.push({ path: '/vue/en-US', redirect: '/vue/en-US/docs/start' }); routes.push({ path: '/:pathMatch(.*)*', redirect: '/vue/docs/start' }); nProgress.configure({ minimum: 0.4, showSpinner: false }); const router = createRouter({ history: createWebHistory(), routes, scrollBehavior(to, from, savedPosition) { // Always scroll to the top return { top: 0 }; }, }); router.beforeEach((to, from) => { if (to.path !== from.path) { nProgress.start(); } }); router.afterEach(() => { nProgress.done(); }); const docsMenuList = [ { name: 'docs', menu: docsMenu, }, { name: 'proDocs', menu: proDocsMenu, }, ]; export { docsMenu, componentMenu, proDocsMenu, docsMenuList }; export default router; ================================================ FILE: packages/arco-vue-docs/style/demo.less ================================================ ================================================ FILE: packages/arco-vue-docs/style/index.less ================================================ @import '../../web-vue/components/style/index.less'; @import './demo.less'; .arco-vue-site { color: var(--color-text-2); font-size: 14px; background-color: var(--color-bg-1); h1, h2, h3, h4 { color: var(--color-text-1); font-weight: 500; } .arco-vue-body { padding-top: 61px; } .site-backtop-btn { background: var(--color-bg-5) !important; border: 1px solid var(--color-fill-3) !important; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .link { color: rgb(var(--arcoblue-6)); text-decoration: none; } .arco-vue-body-has-notice { padding-top: 99px; .arco-vue-aside-left, .arco-vue-aside { top: 99px; } } .site-global-notice { position: fixed; top: 60px; z-index: 980; display: flex; justify-content: center; height: 32px; color: var(--color-white); line-height: 32px; background-color: rgb(var(--blue-6)); .arco-alert-body { display: flex; justify-content: center; .arco-alert-content a { color: var(--color-white); text-decoration: none; .content { margin-right: 48px; margin-left: 36px; font-size: 13px; } } } .arco-alert-close-btn { width: 20px; height: 20px; color: var(--color-white); line-height: 20px; text-align: center; border-radius: 4px; & .arco-icon-hover:hover::before { background-color: hsla(0, 0%, 100%, 0.3); } } } } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string { background: none !important; } #nprogress .bar { background: rgb(var(--arcoblue-6)); } #nprogress .peg { box-shadow: 0 0 10px rgb(var(--arcoblue-6)), 0 0 5px rgb(var(--arcoblue-6)); } code[class*='language-'], pre[class*='language-'] { text-shadow: none !important; } ================================================ FILE: packages/arco-vue-docs/tsconfig.json ================================================ { "compilerOptions": { "module": "ES2020", "moduleResolution": "node", "allowJs": true, "strict": true, "isolatedModules": true, "esModuleInterop": true, "resolveJsonModule": true, "jsx": "preserve", "baseUrl": ".", "paths": { "@web-vue/*": [ "../web-vue/*" ] } } } ================================================ FILE: packages/arco-vue-docs/utils/api.ts ================================================ // @ts-ignore const arcoConfig = window.arcoConfig || {}; export const hostname = window.location.hostname !== arcoConfig.externalHostName && window.location.hostname !== arcoConfig.internalHostName ? arcoConfig.externalHostName : window.location.hostname; export const isExternal = window.location.hostname === arcoConfig.externalHostName; export const apiBasename = `https://${hostname || 'arco.design'}`; ================================================ FILE: packages/arco-vue-docs/utils/clipboard.ts ================================================ // https://github.com/feross/clipboard-copy/blob/master/index.js export default function clipboard(text: string) { if (navigator.clipboard && navigator.clipboard.writeText) { return navigator.clipboard.writeText(text).catch((err) => { throw err !== undefined ? err : new DOMException('The request is not allowed', 'NotAllowedError'); }); } const span = document.createElement('span'); span.textContent = text; span.style.whiteSpace = 'pre'; document.body.appendChild(span); const selection = window.getSelection(); const range = window.document.createRange(); selection?.removeAllRanges(); range.selectNode(span); selection?.addRange(range); let success = false; try { success = window.document.execCommand('copy'); } catch (err) { // eslint-disable-next-line console.log('error', err); } selection?.removeAllRanges(); window.document.body.removeChild(span); return success ? Promise.resolve() : Promise.reject( new DOMException('The request is not allowed', 'NotAllowedError') ); } ================================================ FILE: packages/arco-vue-docs/utils/code-sandbox.ts ================================================ import { getParameters } from 'codesandbox/lib/api/define'; import { mainContent, styleContent } from './code-template'; const babelContent = `module.exports = { presets: [ '@vue/cli-plugin-babel/preset' ] } `; const sendPost = (parameters: string) => { const form = document.createElement('form'); form.action = 'https://codesandbox.io/api/v1/sandboxes/define'; form.target = '_blank'; form.method = 'POST'; form.style.display = 'none'; const field = document.createElement('input'); field.name = 'parameters'; field.type = 'hidden'; field.value = parameters; form.appendChild(field); const query = document.createElement('input'); query.name = 'query'; query.type = 'hidden'; query.value = 'file=/src/App.vue'; form.appendChild(query); document.body.appendChild(form); form.submit(); document.body.removeChild(form); }; export const openCodeSandbox = (content: string) => { const parameters = getParameters({ files: { 'package.json': { // @ts-ignore content: { dependencies: { 'vue': '^3.2.0', 'dayjs': '^1.0', '@arco-design/web-vue': 'latest', }, devDependencies: { '@vue/cli-plugin-babel': '^5.0', '@vue/cli-service': '^5.0', '@vue/compiler-sfc': '^3.2.0', }, }, }, // @ts-ignore 'babel.config.js': { content: babelContent, }, // @ts-ignore 'src/style.css': { content: styleContent, }, // @ts-ignore 'src/main.js': { content: mainContent, }, // @ts-ignore 'src/App.vue': { content, }, }, }); sendPost(parameters); }; ================================================ FILE: packages/arco-vue-docs/utils/code-stackblitz.ts ================================================ import stackblitz from '@stackblitz/sdk'; import { mainContent, styleContent } from './code-template'; export const htmlContent = `
`; export const stackblitzRc = ` { "installDependencies": false, "startCommand": "turbo && turbo dev" } `; export const viteConfigContent = ` import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import vueJsx from '@vitejs/plugin-vue-jsx'; export default defineConfig({ plugins: [vue(), vueJsx()], }); `; export const packageJSONContent = JSON.stringify( { name: 'arco-vue-demo', version: '0.0.0', private: true, scripts: { dev: 'vite', build: 'vite build', serve: 'vite preview', }, dependencies: { 'vue': '^3.2.0', 'dayjs': '^1.0', '@arco-design/web-vue': 'latest', }, devDependencies: { 'vite': '^2.9.8', '@vitejs/plugin-vue': '^2.3.2', '@vitejs/plugin-vue-jsx': '^1.3.10', }, }, null, 2 ); export const openStackblitz = (content: string) => { stackblitz.openProject( { title: `arco-design-demo`, description: 'arco-design-demo', template: 'node', files: { 'src/App.vue': content, 'src/style.css': styleContent, 'src/main.js': mainContent, 'index.html': htmlContent, 'package.json': packageJSONContent, 'vite.config.js': viteConfigContent, '.stackblitzrc': stackblitzRc, }, }, { openFile: 'src/App.vue', } ); }; ================================================ FILE: packages/arco-vue-docs/utils/code-template.ts ================================================ export const mainContent = `import { createApp } from 'vue'; import ArcoVue from '@arco-design/web-vue'; import App from './App.vue'; import '@arco-design/web-vue/dist/arco.css'; import './style.css'; const app = createApp(App); app.use(ArcoVue); app.mount('#app');`; export const styleContent = `#app { padding: 20px; }`; ================================================ FILE: packages/arco-vue-docs/utils/codepen.ts ================================================ const CSS_EXTERNAL = [ 'https://unpkg.com/@arco-design/web-vue@2.x/dist/arco.css', ]; const JS_EXTERNAL = [ 'https://unpkg.com/vue@3.x/dist/vue.global.prod.js', 'https://unpkg.com/dayjs@1.x/dayjs.min.js', 'https://unpkg.com/@arco-design/web-vue@2.x/dist/arco-vue.min.js', 'https://unpkg.com/@arco-design/web-vue@2.x/dist/arco-vue-icon.min.js', ]; const parseContent = (content: string) => { const htmlContent = content.match(/