浏览代码

fix(其它变更): Merge branch 'main' of http://192.168.0.115:3000/4dkankan/4dkankan-components

# Conflicts:
#	playground/src/App.vue
#	playground/src/components/tag/TagView.vue
#	playground/src/sdk.ts
rindy 2 年之前
父节点
当前提交
8f350b4f43
共有 100 个文件被更改,包括 4237 次插入3485 次删除
  1. 1 1
      .changeset/config.json
  2. 14 0
      .changeset/pre.json
  3. 40 34
      .cz-config.js
  4. 10 0
      .editorconfig
  5. 2 2
      .eslintrc.json
  6. 1 0
      .gitignore
  7. 6 0
      .prettierignore
  8. 12 0
      .prettierrc
  9. 33 13
      .vscode/settings.json
  10. 10 10
      commitlint.config.js
  11. 15 12
      docs/.vitepress/build/crowdin-credentials.ts
  12. 92 80
      docs/.vitepress/build/crowdin-generate.ts
  13. 7 7
      docs/.vitepress/build/rebuild-pwa.ts
  14. 56 46
      docs/.vitepress/config.mts
  15. 14 9
      docs/.vitepress/config/analytics.ts
  16. 138 110
      docs/.vitepress/config/head.ts
  17. 13 13
      docs/.vitepress/config/nav.ts
  18. 80 31
      docs/.vitepress/config/plugins.ts
  19. 27 17
      docs/.vitepress/config/sidebars.ts
  20. 37 34
      docs/.vitepress/config/sponsors.ts
  21. 8 4
      docs/.vitepress/dark-mode.js
  22. 10 10
      docs/.vitepress/i18n/component/changelog.json
  23. 24 24
      docs/.vitepress/i18n/component/demo-block.json
  24. 8 8
      docs/.vitepress/i18n/component/edit-link.json
  25. 12 12
      docs/.vitepress/i18n/component/footer.json
  26. 8 8
      docs/.vitepress/i18n/component/icons.json
  27. 6 6
      docs/.vitepress/i18n/component/last-update-at.json
  28. 12 12
      docs/.vitepress/i18n/component/pwa.json
  29. 10 10
      docs/.vitepress/i18n/component/search.json
  30. 12 12
      docs/.vitepress/i18n/component/sponsor.json
  31. 6 6
      docs/.vitepress/i18n/component/translation.json
  32. 36 335
      docs/.vitepress/i18n/pages/component.json
  33. 154 154
      docs/.vitepress/i18n/pages/guide.json
  34. 56 56
      docs/.vitepress/i18n/pages/home.json
  35. 10 10
      docs/.vitepress/i18n/pages/not-found.json
  36. 24 24
      docs/.vitepress/i18n/pages/resource.json
  37. 24 24
      docs/.vitepress/i18n/pages/sidebar.json
  38. 33 24
      docs/.vitepress/lang.js
  39. 40 0
      docs/.vitepress/plugins/api-table.ts
  40. 26 21
      docs/.vitepress/plugins/external-link-icon.ts
  41. 81 61
      docs/.vitepress/plugins/markdown-transform.ts
  42. 2 2
      docs/.vitepress/plugins/table-wrapper.ts
  43. 29 0
      docs/.vitepress/plugins/tooltip.ts
  44. 145 132
      docs/.vitepress/sw.ts
  45. 8 8
      docs/.vitepress/theme/index.ts
  46. 37 33
      docs/.vitepress/utils/highlight.ts
  47. 2 1
      docs/.vitepress/utils/lang.ts
  48. 18 11
      docs/.vitepress/vitepress/components/common/vp-link.vue
  49. 14 8
      docs/.vitepress/vitepress/components/common/vp-markdown.vue
  50. 6 6
      docs/.vitepress/vitepress/components/common/vp-switch.vue
  51. 23 22
      docs/.vitepress/vitepress/components/common/vp-theme-toggler.vue
  52. 33 0
      docs/.vitepress/vitepress/components/demo/dept-home.ts
  53. 82 0
      docs/.vitepress/vitepress/components/demo/dept.js
  54. 10 0
      docs/.vitepress/vitepress/components/demo/main.vue
  55. 121 17
      docs/.vitepress/vitepress/components/demo/vp-example.vue
  56. 10 10
      docs/.vitepress/vitepress/components/demo/vp-source-code.vue
  57. 3 1
      docs/.vitepress/vitepress/components/dev/DeprecatedTag.vue
  58. 4 4
      docs/.vitepress/vitepress/components/dev/VersionTag.vue
  59. 18 12
      docs/.vitepress/vitepress/components/doc-content/vp-edit-link.vue
  60. 20 20
      docs/.vitepress/vitepress/components/doc-content/vp-last-updated-at.vue
  61. 20 20
      docs/.vitepress/vitepress/components/doc-content/vp-page-footer.vue
  62. 49 49
      docs/.vitepress/vitepress/components/doc-content/vp-page-nav.vue
  63. 40 30
      docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue
  64. 22 22
      docs/.vitepress/vitepress/components/full-screen/vp-menu-link.vue
  65. 7 7
      docs/.vitepress/vitepress/components/full-screen/vp-menu.vue
  66. 12 12
      docs/.vitepress/vitepress/components/full-screen/vp-theme-toggler.vue
  67. 56 46
      docs/.vitepress/vitepress/components/full-screen/vp-translation.vue
  68. 20 14
      docs/.vitepress/vitepress/components/globals/contributors.vue
  69. 42 42
      docs/.vitepress/vitepress/components/globals/design-guide.vue
  70. 57 30
      docs/.vitepress/vitepress/components/globals/design/consistency-svg.vue
  71. 55 51
      docs/.vitepress/vitepress/components/globals/design/controllability-svg.vue
  72. 46 33
      docs/.vitepress/vitepress/components/globals/design/efficiency-svg.vue
  73. 36 24
      docs/.vitepress/vitepress/components/globals/design/feedback-svg.vue
  74. 330 302
      docs/.vitepress/vitepress/components/globals/icons-categories.json
  75. 106 96
      docs/.vitepress/vitepress/components/globals/icons.vue
  76. 21 21
      docs/.vitepress/vitepress/components/globals/main-color.vue
  77. 136 106
      docs/.vitepress/vitepress/components/globals/neutral-color.vue
  78. 305 305
      docs/.vitepress/vitepress/components/globals/parallax-home.vue
  79. 104 88
      docs/.vitepress/vitepress/components/globals/resource.vue
  80. 136 88
      docs/.vitepress/vitepress/components/globals/resources/axure-components-svg.vue
  81. 59 44
      docs/.vitepress/vitepress/components/globals/resources/figma-template-svg.vue
  82. 55 46
      docs/.vitepress/vitepress/components/globals/resources/sketch-template-svg.vue
  83. 28 23
      docs/.vitepress/vitepress/components/globals/secondary-colors.vue
  84. 7 0
      docs/.vitepress/vitepress/components/globals/vp-api-bool.vue
  85. 20 0
      docs/.vitepress/vitepress/components/globals/vp-api-enum.vue
  86. 33 0
      docs/.vitepress/vitepress/components/globals/vp-api-external.vue
  87. 40 0
      docs/.vitepress/vitepress/components/globals/vp-api-function.vue
  88. 7 0
      docs/.vitepress/vitepress/components/globals/vp-api-number.vue
  89. 14 0
      docs/.vitepress/vitepress/components/globals/vp-api-primitive.vue
  90. 21 0
      docs/.vitepress/vitepress/components/globals/vp-api-ref.vue
  91. 7 0
      docs/.vitepress/vitepress/components/globals/vp-api-string.vue
  92. 35 0
      docs/.vitepress/vitepress/components/globals/vp-api-typing.vue
  93. 86 73
      docs/.vitepress/vitepress/components/globals/vp-changelog.vue
  94. 89 89
      docs/.vitepress/vitepress/components/globals/vp-footer.vue
  95. 137 135
      docs/.vitepress/vitepress/components/home/home-cards.vue
  96. 49 49
      docs/.vitepress/vitepress/components/home/home-sponsors.vue
  97. 37 25
      docs/.vitepress/vitepress/components/home/sponsor-list.vue
  98. 74 52
      docs/.vitepress/vitepress/components/home/svg/component-svg.vue
  99. 46 36
      docs/.vitepress/vitepress/components/home/svg/guide-svg.vue
  100. 0 0
      docs/.vitepress/vitepress/components/home/svg/left-bottom-layer-svg.vue

+ 1 - 1
.changeset/config.json

@@ -8,4 +8,4 @@
   "baseBranch": "main",
   "updateInternalDependencies": "patch",
   "ignore": []
-}
+}

+ 14 - 0
.changeset/pre.json

@@ -0,0 +1,14 @@
+{
+  "mode": "exit",
+  "tag": "beta",
+  "initialVersions": {
+    "@kankan-components/components": "0.0.1",
+    "@kankan-components/directives": "0.0.1",
+    "@kankan-components/hooks": "0.0.1",
+    "kankan-components": "0.0.1",
+    "@kankan-components/theme-chalk": "0.1.0",
+    "@kankan-components/tokens": "0.0.1",
+    "@kankan-components/utils": "1.0.0"
+  },
+  "changesets": []
+}

+ 40 - 34
.cz-config.js

@@ -1,37 +1,43 @@
 module.exports = {
-    types: [
-        { value: 'feat', name: 'feat 🍄:    新增新的特性' },
-        { value: 'fix', name: 'fix 🐛:    修复 BUG' },
-        { value: 'docs', name: 'docs 📄:    修改文档、注释' },
-        {
-            value: 'refactor',
-            name: 'refactor 🎸:    代码重构,注意和特性、修复区分开',
-        },
-        { value: 'chore', name: 'chore 🧹:   构建过程或辅助工具的变动' },
-        { value: 'perf', name: 'perf ⚡:    提升性能' },
-        { value: 'test', name: 'test 👀:    添加一个测试' },
-        { value: 'tool', name: 'tool 🚗:    开发工具变动(构建、脚手架工具等)' },
-        { value: 'style', name: 'style ✂:    对代码格式的修改不影响逻辑' },
-        { value: 'revert', name: 'revert 🌝:     版本回滚' },
-        { value: 'update', name: 'update ⬆:    第三方库升级 ' },
-    ],
-
-    scopes: [{ name: '组件' }, { name: '样式' }, { name: '文档更改' }, { name: '其它变更' }, { name: '架构调整' }],
-    allowTicketNumber: false,
-    isTicketNumberRequired: false,
-    ticketNumberPrefix: 'TICKET-',
-    ticketNumberRegExp: 'd{1,5}',
-    messages: {
-        type: '选择一种你的提交类型:',
-        scope: '选择一个scope (可选):',
-        customScope: 'Denote the SCOPE of this change:',
-        subject: '简要说明:\n',
-        body: '详细说明,使用"|"换行(可选):\n',
-        breaking: '非兼容性说明 (可选):\n',
-        footer: '关联关闭的issue,例如:#31, #34(可选):\n',
-        confirmCommit: '确定提交?',
+  types: [
+    { value: 'feat', name: 'feat 🍄:    新增新的特性' },
+    { value: 'fix', name: 'fix 🐛:    修复 BUG' },
+    { value: 'docs', name: 'docs 📄:    修改文档、注释' },
+    {
+      value: 'refactor',
+      name: 'refactor 🎸:    代码重构,注意和特性、修复区分开',
     },
-    allowCustomScopes: true,
-    allowBreakingChanges: ['新增', '修复'],
-    subjectLimit: 100,
+    { value: 'chore', name: 'chore 🧹:   构建过程或辅助工具的变动' },
+    { value: 'perf', name: 'perf ⚡:    提升性能' },
+    { value: 'test', name: 'test 👀:    添加一个测试' },
+    { value: 'tool', name: 'tool 🚗:    开发工具变动(构建、脚手架工具等)' },
+    { value: 'style', name: 'style ✂:    对代码格式的修改不影响逻辑' },
+    { value: 'revert', name: 'revert 🌝:     版本回滚' },
+    { value: 'update', name: 'update ⬆:    第三方库升级 ' },
+  ],
+
+  scopes: [
+    { name: '组件' },
+    { name: '样式' },
+    { name: '文档更改' },
+    { name: '其它变更' },
+    { name: '架构调整' },
+  ],
+  allowTicketNumber: false,
+  isTicketNumberRequired: false,
+  ticketNumberPrefix: 'TICKET-',
+  ticketNumberRegExp: 'd{1,5}',
+  messages: {
+    type: '选择一种你的提交类型:',
+    scope: '选择一个scope (可选):',
+    customScope: 'Denote the SCOPE of this change:',
+    subject: '简要说明:\n',
+    body: '详细说明,使用"|"换行(可选):\n',
+    breaking: '非兼容性说明 (可选):\n',
+    footer: '关联关闭的issue,例如:#31, #34(可选):\n',
+    confirmCommit: '确定提交?',
+  },
+  allowCustomScopes: true,
+  allowBreakingChanges: ['新增', '修复'],
+  subjectLimit: 100,
 }

+ 10 - 0
.editorconfig

@@ -0,0 +1,10 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+quote_type = single

+ 2 - 2
.eslintrc.json

@@ -1,4 +1,4 @@
 {
-    "root": true,
-    "extends": ["@kankan-components/eslint-config"]
+  "root": true,
+  "extends": ["@kankan-components/eslint-config"]
 }

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 node_modules
+.eslintcache
 **/dist
 results
 .nyc_output

+ 6 - 0
.prettierignore

@@ -0,0 +1,6 @@
+dist
+node_modules
+coverage
+CHANGELOG.en-US.md
+pnpm-lock.yaml
+docs/components.d.ts

+ 12 - 0
.prettierrc

@@ -0,0 +1,12 @@
+{
+  "semi": false,
+  "singleQuote": true,
+  "overrides": [
+    {
+      "files": ".prettierrc",
+      "options": {
+        "parser": "json"
+      }
+    }
+  ]
+}

+ 33 - 13
.vscode/settings.json

@@ -1,15 +1,35 @@
 {
-    "cSpell.words": [""],
-    "typescript.tsdk": "node_modules/typescript/lib",
-    "editor.formatOnSave": true,
-    "npm.packageManager": "pnpm",
-    "eslint.probe": ["javascript", "javascriptreact", "typescript", "typescriptreact", "html", "vue", "markdown", "json", "jsonc"],
-    "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "html", "vue", "markdown", "json", "jsonc"],
-    "vite.devCommand": "pnpm run dev -- --",
-    "i18n-ally.localesPaths": "packages/locale/lang",
-    "i18n-ally.enabledParsers": ["ts"],
-    "i18n-ally.enabledFrameworks": ["vue", "vue-sfc"],
-    "i18n-ally.keystyle": "nested",
-    "iconify.includes": ["ep"],
-    "unocss.root": "./docs"
+  "cSpell.words": ["", "disablepictureinpicture"],
+  "typescript.tsdk": "node_modules/typescript/lib",
+  "editor.formatOnSave": true,
+  "npm.packageManager": "pnpm",
+  "eslint.probe": [
+    "javascript",
+    "javascriptreact",
+    "typescript",
+    "typescriptreact",
+    "html",
+    "vue",
+    "markdown",
+    "json",
+    "jsonc"
+  ],
+  "eslint.validate": [
+    "javascript",
+    "javascriptreact",
+    "typescript",
+    "typescriptreact",
+    "html",
+    "vue",
+    "markdown",
+    "json",
+    "jsonc"
+  ],
+  "vite.devCommand": "pnpm run dev -- --",
+  "i18n-ally.localesPaths": "packages/locale/lang",
+  "i18n-ally.enabledParsers": ["ts"],
+  "i18n-ally.enabledFrameworks": ["vue", "vue-sfc"],
+  "i18n-ally.keystyle": "nested",
+  "iconify.includes": ["ep"],
+  "unocss.root": "./docs"
 }

+ 10 - 10
commitlint.config.js

@@ -1,13 +1,13 @@
 module.exports = {
-    extends: ['cz'],
-    parserPreset: {
-        parserOpts: {
-            headerPattern: /^(\w*)\(([\u4E00-\u9FA5]*)\)/,
-            headerCorrespondence: ['type', 'scope'],
-        },
-    },
-    rules: {
-        'type-empty': [2, 'never'],
-        'scope-empty': [2, 'never'],
+  extends: ['cz'],
+  parserPreset: {
+    parserOpts: {
+      headerPattern: /^(\w*)\(([\u4E00-\u9FA5]*)\)/,
+      headerCorrespondence: ['type', 'scope'],
     },
+  },
+  rules: {
+    'type-empty': [2, 'never'],
+    'scope-empty': [2, 'never'],
+  },
 }

+ 15 - 12
docs/.vitepress/build/crowdin-credentials.ts

@@ -8,19 +8,22 @@ const credentialPlaceholder = 'API_TOKEN_PLACEHOLDER'
 
 const CREDENTIAL = process.env.CROWDIN_TOKEN
 if (!CREDENTIAL) {
-    errorAndExit(new Error('Environment variable CROWDIN_TOKEN cannot be empty'))
+  errorAndExit(new Error('Environment variable CROWDIN_TOKEN cannot be empty'))
 }
 
 ;(async () => {
-    consola.debug(chalk.cyan('Fetching Crowdin credential'))
-    const configPath = path.resolve(docRoot, 'crowdin.yml')
-    try {
-        const file = await fs.readFile(configPath, {
-            encoding: 'utf-8',
-        })
-        await fs.writeFile(configPath, file.replace(credentialPlaceholder, CREDENTIAL))
-        consola.success(chalk.green('Crowdin credential update successfully'))
-    } catch (e: any) {
-        errorAndExit(e)
-    }
+  consola.debug(chalk.cyan('Fetching Crowdin credential'))
+  const configPath = path.resolve(docRoot, 'crowdin.yml')
+  try {
+    const file = await fs.readFile(configPath, {
+      encoding: 'utf-8',
+    })
+    await fs.writeFile(
+      configPath,
+      file.replace(credentialPlaceholder, CREDENTIAL)
+    )
+    consola.success(chalk.green('Crowdin credential update successfully'))
+  } catch (e: any) {
+    errorAndExit(e)
+  }
 })()

+ 92 - 80
docs/.vitepress/build/crowdin-generate.ts

@@ -10,92 +10,104 @@ const componentLocaleRoot = path.resolve(docRoot, '.vitepress/crowdin')
 const exists = 'File already exists'
 
 async function main() {
-    const localeOutput = path.resolve(docRoot, '.vitepress/i18n')
-    if (fs.existsSync(localeOutput)) {
-        throw new Error(exists)
+  const localeOutput = path.resolve(docRoot, '.vitepress/i18n')
+  if (fs.existsSync(localeOutput)) {
+    throw new Error(exists)
+  }
+
+  consola.trace(chalk.cyan('Starting for build doc for developing'))
+  // all language should be identical since it is mirrored from crowdin.
+  const dirs = await fs.promises.readdir(componentLocaleRoot, {
+    withFileTypes: true,
+  })
+  const languages = dirs.map((dir) => dir.name)
+  const langWithoutEn = languages.filter((l) => l !== 'en-US')
+
+  await fs.promises.mkdir(localeOutput)
+
+  // build lang.json for telling `header>language-select` how many languages are there
+  await fs.promises.writeFile(
+    path.resolve(localeOutput, 'lang.json'),
+    JSON.stringify(languages),
+    'utf-8'
+  )
+
+  // loop through en-US
+
+  const enUS = path.resolve(componentLocaleRoot, 'en-US')
+  // we do not include en-US since we are currently using it as template
+  const languagePaths = langWithoutEn.map((l) => {
+    return {
+      name: l,
+      pathname: path.resolve(componentLocaleRoot, l),
     }
+  })
 
-    consola.trace(chalk.cyan('Starting for build doc for developing'))
-    // all language should be identical since it is mirrored from crowdin.
-    const dirs = await fs.promises.readdir(componentLocaleRoot, {
-        withFileTypes: true,
-    })
-    const languages = dirs.map(dir => dir.name)
-    const langWithoutEn = languages.filter(l => l !== 'en-US')
-
-    await fs.promises.mkdir(localeOutput)
-
-    // build lang.json for telling `header>language-select` how many languages are there
-    await fs.promises.writeFile(path.resolve(localeOutput, 'lang.json'), JSON.stringify(languages), 'utf-8')
+  consola.debug(languagePaths)
+  await traverseDir(enUS, languagePaths, localeOutput)
+}
 
-    // loop through en-US
+async function traverseDir(
+  dir: string,
+  paths: { name: string; pathname: string }[],
+  targetPath: string
+) {
+  const contents = await fs.promises.readdir(dir, { withFileTypes: true })
+
+  await Promise.all(
+    contents.map(async (c) => {
+      if (c.isDirectory()) {
+        await fs.promises.mkdir(path.resolve(targetPath, c.name), {
+          recursive: true,
+        })
 
-    const enUS = path.resolve(componentLocaleRoot, 'en-US')
-    // we do not include en-US since we are currently using it as template
-    const languagePaths = langWithoutEn.map(l => {
-        return {
-            name: l,
-            pathname: path.resolve(componentLocaleRoot, l),
+        return traverseDir(
+          path.resolve(dir, c.name),
+          paths.map((p) => {
+            return {
+              ...p,
+              pathname: path.resolve(p.pathname, c.name),
+            }
+          }),
+          path.resolve(targetPath, c.name)
+        )
+      } else if (c.isFile()) {
+        // eslint-disable-next-line @typescript-eslint/no-var-requires
+        const content = require(path.resolve(dir, c.name))
+
+        const contentToWrite = {
+          'en-US': content,
         }
-    })
-
-    consola.debug(languagePaths)
-    await traverseDir(enUS, languagePaths, localeOutput)
-}
 
-async function traverseDir(dir: string, paths: { name: string; pathname: string }[], targetPath: string) {
-    const contents = await fs.promises.readdir(dir, { withFileTypes: true })
-
-    await Promise.all(
-        contents.map(async c => {
-            if (c.isDirectory()) {
-                await fs.promises.mkdir(path.resolve(targetPath, c.name), {
-                    recursive: true,
-                })
-
-                return traverseDir(
-                    path.resolve(dir, c.name),
-                    paths.map(p => {
-                        return {
-                            ...p,
-                            pathname: path.resolve(p.pathname, c.name),
-                        }
-                    }),
-                    path.resolve(targetPath, c.name)
-                )
-            } else if (c.isFile()) {
-                // eslint-disable-next-line @typescript-eslint/no-var-requires
-                const content = require(path.resolve(dir, c.name))
-
-                const contentToWrite = {
-                    'en-US': content,
-                }
-
-                await Promise.all(
-                    paths.map(async p => {
-                        // eslint-disable-next-line @typescript-eslint/no-var-requires
-                        const content = require(path.resolve(p.pathname, c.name))
-
-                        contentToWrite[p.name] = content
-                    })
-                )
-
-                return fs.promises.writeFile(path.resolve(targetPath, c.name), JSON.stringify(contentToWrite, null, 2), {
-                    encoding: 'utf-8',
-                })
-            }
-        })
-    )
+        await Promise.all(
+          paths.map(async (p) => {
+            // eslint-disable-next-line @typescript-eslint/no-var-requires
+            const content = require(path.resolve(p.pathname, c.name))
+
+            contentToWrite[p.name] = content
+          })
+        )
+
+        return fs.promises.writeFile(
+          path.resolve(targetPath, c.name),
+          JSON.stringify(contentToWrite, null, 2),
+          {
+            encoding: 'utf-8',
+          }
+        )
+      }
+    })
+  )
 }
 
 main()
-    .then(() => {
-        consola.success(chalk.green('Locale for website development generated'))
-    })
-    .catch(err => {
-        if (err.message === exists) {
-            // do nothing
-        } else {
-            errorAndExit(err)
-        }
-    })
+  .then(() => {
+    consola.success(chalk.green('Locale for website development generated'))
+  })
+  .catch((err) => {
+    if (err.message === exists) {
+      // do nothing
+    } else {
+      errorAndExit(err)
+    }
+  })

+ 7 - 7
docs/.vitepress/build/rebuild-pwa.ts

@@ -2,14 +2,14 @@ import { resolveConfig } from 'vite'
 import type { VitePluginPWAAPI } from 'vite-plugin-pwa'
 
 const rebuildPwa = async () => {
-    const config = await resolveConfig({}, 'build', 'production')
-    const pwaPlugin: VitePluginPWAAPI = config.plugins.find(i => {
-        return i.name === 'vite-plugin-pwa'
-    })?.api
+  const config = await resolveConfig({}, 'build', 'production')
+  const pwaPlugin: VitePluginPWAAPI = config.plugins.find((i) => {
+    return i.name === 'vite-plugin-pwa'
+  })?.api
 
-    if (pwaPlugin && pwaPlugin.generateSW && !pwaPlugin.disabled) {
-        await pwaPlugin.generateSW()
-    }
+  if (pwaPlugin && pwaPlugin.generateSW && !pwaPlugin.disabled) {
+    await pwaPlugin.generateSW()
+  }
 }
 
 rebuildPwa()

+ 56 - 46
docs/.vitepress/config.mts

@@ -6,28 +6,37 @@ import { features, head, mdPlugin, nav, sidebars } from './config'
 import type { UserConfig } from 'vitepress'
 
 const buildTransformers = () => {
-    const transformer = () => {
-        return {
-            props: [],
-            needRuntime: true,
-        }
+  const transformer = () => {
+    return {
+      props: [],
+      needRuntime: true,
     }
+  }
 
-    const transformers = {}
-    const directives = ['infinite-scroll', 'loading', 'popover', 'click-outside', 'repeat-click', 'trap-focus', 'mousewheel', 'resize']
-    directives.forEach(k => {
-        transformers[k] = transformer
-    })
+  const transformers = {}
+  const directives = [
+    'infinite-scroll',
+    'loading',
+    'popover',
+    'click-outside',
+    'repeat-click',
+    'trap-focus',
+    'mousewheel',
+    'resize',
+  ]
+  directives.forEach((k) => {
+    transformers[k] = transformer
+  })
 
-    return transformers
+  return transformers
 }
 
 consola.debug(`DOC_ENV: ${process.env.DOC_ENV}`)
 
 const languages = ['zh-CN']
 const locales = {
-    // '/en-US': { label: 'en-US', lang: 'en-US' },
-    '/zh-CN': { label: 'zh-CN', lang: 'zh-CN' },
+  // '/en-US': { label: 'en-US', lang: 'en-US' },
+  '/zh-CN': { label: 'zh-CN', lang: 'zh-CN' },
 }
 
 // languages.forEach(lang => {
@@ -41,45 +50,46 @@ const locales = {
 // consola.log('sidebars', sidebars)
 
 export const config: UserConfig = {
-    title: '看看公共组件',
-    description: '看看组件公共文档中心',
-    lastUpdated: true,
-    head,
-    themeConfig: {
-        repo: 'http://192.168.0.115:3000/4dkankan/4dkankan-components',
-        docsBranch: REPO_BRANCH,
-        docsDir: docsDirName,
+  title: '看看公共组件',
+  description: '看看组件公共文档中心',
+  lastUpdated: true,
+  // base: "/kk-docs/",
+  head,
+  themeConfig: {
+    repo: 'http://192.168.0.115:3000/4dkankan/4dkankan-components',
+    docsBranch: REPO_BRANCH,
+    docsDir: docsDirName,
 
-        editLinks: true,
-        editLinkText: 'Edit this page on GitHub',
-        lastUpdated: 'Last Updated',
+    editLinks: true,
+    editLinkText: 'Edit this page on GitHub',
+    lastUpdated: 'Last Updated',
 
-        logo: '/images/logo.png',
-        logoSmall: '/images/kankan_icon.ico',
-        sidebars,
-        nav,
-        agolia: {
-            apiKey: '377f2b647a96d9b1d62e4780f2344da2',
-            appId: 'BH4D9OD16A',
-        },
-        features,
-        langs: languages,
-    },
+    logo: '/images/logo.png',
+    logoSmall: '/images/kankan_icon.ico',
+    sidebars,
+    nav,
+    // agolia: {
+    //     apiKey: '377f2b647a96d9b1d62e4780f2344da2',
+    //     appId: 'BH4D9OD16A',
+    // },
+    features,
+    langs: languages,
+  },
 
-    locales,
+  locales,
 
-    markdown: {
-        config: md => mdPlugin(md),
-    },
+  markdown: {
+    config: (md) => mdPlugin(md),
+  },
 
-    vue: {
-        template: {
-            ssr: true,
-            compilerOptions: {
-                directiveTransforms: buildTransformers(),
-            },
-        },
+  vue: {
+    template: {
+      ssr: true,
+      compilerOptions: {
+        directiveTransforms: buildTransformers(),
+      },
     },
+  },
 }
 
 export default config

+ 14 - 9
docs/.vitepress/config/analytics.ts

@@ -1,10 +1,15 @@
-export const sendEvent = (action: string, label: string, value?: any, category?: string): void => {
-    const gtag = (window as any).gtag
-    if (gtag) {
-        gtag('event', action, {
-            event_label: label,
-            event_value: value,
-            event_category: category,
-        })
-    }
+export const sendEvent = (
+  action: string,
+  label: string,
+  value?: any,
+  category?: string
+): void => {
+  const gtag = (window as any).gtag
+  if (gtag) {
+    gtag('event', action, {
+      event_label: label,
+      event_value: value,
+      event_category: category,
+    })
+  }
 }

+ 138 - 110
docs/.vitepress/config/head.ts

@@ -6,71 +6,95 @@ import { languages } from '../utils/lang'
 import type { HeadConfig } from 'vitepress'
 
 export const head: HeadConfig[] = [
-    [
-        'link',
-        {
-            rel: 'icon',
-            href: '/images/kankan_icon.ico',
-            type: 'image/ico',
-        },
-    ],
-    [
-        'link',
-        {
-            rel: 'apple-touch-icon',
-            href: '/apple-touch-icon.png',
-            sizes: '180x180',
-        },
-    ],
-    [
-        'link',
-        {
-            rel: 'mask-icon',
-            href: '/safari-pinned-tab.svg',
-            color: '#5bbad5',
-        },
-    ],
-    [
-        'meta',
-        {
-            name: 'theme-color',
-            content: '#ffffff',
-        },
-    ],
-    [
-        'meta',
-        {
-            name: 'msapplication-TileColor',
-            content: '#409eff',
-        },
-    ],
-    [
-        'meta',
-        {
-            name: 'msapplication-config',
-            content: '/browserconfig.xml',
-        },
-    ],
-    [
-        'script',
-        {},
-        `;(() => {
+  // [
+  //     'link',
+  //     {
+  //         rel: 'stylesheet',
+  //         href: '//at.alicdn.com/t/c/font_2596172_5i5zp5tvfj9.css',
+  //     },
+  // ],
+  // [
+  //     'script',
+  //     { id: 'scriptImporter' },
+  //     `
+  //         (function() {
+  //         var script = document.createElement("script");
+  //         script.src="//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk-deps.js?v=4.6.0-alpha.10";
+  //         setTimeout(() => document.body.append(script))
+
+  //         script.onload = function(){
+  //             var script2 = document.createElement("script");
+  //             script2.src = "//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk.js?v=4.6.0-alpha.10";
+  //             setTimeout(() => document.body.append(script2),100)
+  //         }
+  //         })();
+  // `,
+  // ],
+  [
+    'link',
+    {
+      rel: 'icon',
+      href: '/images/kankan_icon.ico',
+      type: 'image/ico',
+    },
+  ],
+  [
+    'link',
+    {
+      rel: 'apple-touch-icon',
+      href: '/apple-touch-icon.png',
+      sizes: '180x180',
+    },
+  ],
+  [
+    'link',
+    {
+      rel: 'mask-icon',
+      href: '/safari-pinned-tab.svg',
+      color: '#5bbad5',
+    },
+  ],
+  [
+    'meta',
+    {
+      name: 'theme-color',
+      content: '#ffffff',
+    },
+  ],
+  [
+    'meta',
+    {
+      name: 'msapplication-TileColor',
+      content: '#409eff',
+    },
+  ],
+  [
+    'meta',
+    {
+      name: 'msapplication-config',
+      content: '/browserconfig.xml',
+    },
+  ],
+  [
+    'script',
+    {},
+    `;(() => {
       window.supportedLangs = ${JSON.stringify(languages)}
     })()`,
-    ],
+  ],
 
-    ['script', {}, fs.readFileSync(path.resolve(vpRoot, 'lang.js'), 'utf-8')],
-    // [
-    //     'script',
-    //     {
-    //         async: 'true',
-    //         src: 'https://www.googletagmanager.com/gtag/js?id=UA-175337989-1',
-    //     },
-    // ],
-    [
-        'script',
-        {},
-        `if ('serviceWorker' in navigator) {
+  ['script', {}, fs.readFileSync(path.resolve(vpRoot, 'lang.js'), 'utf-8')],
+  // [
+  //     'script',
+  //     {
+  //         async: 'true',
+  //         src: 'https://www.googletagmanager.com/gtag/js?id=UA-175337989-1',
+  //     },
+  // ],
+  [
+    'script',
+    {},
+    `if ('serviceWorker' in navigator) {
       navigator.serviceWorker
         .register('/sw.js')
         .then(function(registration) {
@@ -80,53 +104,53 @@ export const head: HeadConfig[] = [
           console.log(err);
         });
     }`,
-    ],
-    //     [
-    //         'script',
-    //         {
-    //             async: 'true',
-    //         },
-    //         `window.dataLayer = window.dataLayer || [];
-    // function gtag(){dataLayer.push(arguments);}
-    // gtag('js', new Date());
-    // gtag('config', 'UA-175337989-1');`,
-    //     ],
-    //     [
-    //         'script',
-    //         {
-    //             async: 'true',
-    //             src: 'https://www.googletagmanager.com/gtag/js?id=G-M74ZHEQ1M1',
-    //         },
-    //     ],
-    //     [
-    //         'script',
-    //         {},
-    //         `
-    //       window.dataLayer = window.dataLayer || [];
-    //       function gtag(){dataLayer.push(arguments);}
-    //       gtag('js', new Date());
+  ],
+  //     [
+  //         'script',
+  //         {
+  //             async: 'true',
+  //         },
+  //         `window.dataLayer = window.dataLayer || [];
+  // function gtag(){dataLayer.push(arguments);}
+  // gtag('js', new Date());
+  // gtag('config', 'UA-175337989-1');`,
+  //     ],
+  //     [
+  //         'script',
+  //         {
+  //             async: 'true',
+  //             src: 'https://www.googletagmanager.com/gtag/js?id=G-M74ZHEQ1M1',
+  //         },
+  //     ],
+  //     [
+  //         'script',
+  //         {},
+  //         `
+  //       window.dataLayer = window.dataLayer || [];
+  //       function gtag(){dataLayer.push(arguments);}
+  //       gtag('js', new Date());
 
-    //       gtag('config', 'G-M74ZHEQ1M1');
-    //     `,
-    //     ],
-    //     [
-    //         'script',
-    //         {},
-    //         `(function(h,o,t,j,a,r){
-    //       h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
-    //       h._hjSettings={hjid:2894908,hjsv:6};
-    //       a=o.getElementsByTagName('head')[0];
-    //       r=o.createElement('script');r.async=1;
-    //       r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
-    //       a.appendChild(r);
-    //   })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`,
-    //     ],
-    [
-        'script',
-        {
-            async: 'true',
-        },
-        `
+  //       gtag('config', 'G-M74ZHEQ1M1');
+  //     `,
+  //     ],
+  //     [
+  //         'script',
+  //         {},
+  //         `(function(h,o,t,j,a,r){
+  //       h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
+  //       h._hjSettings={hjid:2894908,hjsv:6};
+  //       a=o.getElementsByTagName('head')[0];
+  //       r=o.createElement('script');r.async=1;
+  //       r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
+  //       a.appendChild(r);
+  //   })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`,
+  //     ],
+  [
+    'script',
+    {
+      async: 'true',
+    },
+    `
   var resource = document.createElement('link');
   resource.setAttribute("rel", "stylesheet");
   resource.setAttribute("href","//fonts.loli.net/css?family=Inter:300,400,500,600|Open+Sans:400,600;display=swap");
@@ -134,7 +158,11 @@ export const head: HeadConfig[] = [
   var head = document.querySelector('head');
   head.appendChild(resource);
     `,
-    ],
+  ],
 ]
 
-head.push(['script', {}, fs.readFileSync(path.resolve(vpRoot, 'dark-mode.js'), 'utf-8')])
+head.push([
+  'script',
+  {},
+  fs.readFileSync(path.resolve(vpRoot, 'dark-mode.js'), 'utf-8'),
+])

+ 13 - 13
docs/.vitepress/config/nav.ts

@@ -4,20 +4,20 @@ import navLocale from '../i18n/pages/sidebar.json'
 // Mapping the first sub link to the nav link to avoid 404 error.
 
 function getNav() {
-    return Object.fromEntries(
-        Object.entries(navLocale).map(([lang, locales]) => {
-            const item: {
-                link: string
-                text: string
-                activeMatch?: string
-            }[] = Object.values(locales).map(item => ({
-                ...item,
-                link: `${ensureLang(lang)}${item.link}`,
-            }))
+  return Object.fromEntries(
+    Object.entries(navLocale).map(([lang, locales]) => {
+      const item: {
+        link: string
+        text: string
+        activeMatch?: string
+      }[] = Object.values(locales).map((item) => ({
+        ...item,
+        link: `${ensureLang(lang)}${item.link}`,
+      }))
 
-            return [lang, item]
-        })
-    )
+      return [lang, item]
+    })
+  )
 }
 
 export const nav = getNav()

+ 80 - 31
docs/.vitepress/config/plugins.ts

@@ -5,6 +5,8 @@ import mdContainer from 'markdown-it-container'
 import { docRoot } from '@kankan-components/build-utils'
 import externalLinkIcon from '../plugins/external-link-icon'
 import tableWrapper from '../plugins/table-wrapper'
+import tooltip from '../plugins/tooltip'
+import { ApiTableContainer } from '../plugins/api-table'
 import { highlight } from '../utils/highlight'
 import type Token from 'markdown-it/lib/token'
 import type Renderer from 'markdown-it/lib/renderer'
@@ -12,38 +14,85 @@ import type Renderer from 'markdown-it/lib/renderer'
 const localMd = MarkdownIt()
 
 interface ContainerOpts {
-    marker?: string | undefined
-    validate?(params: string): boolean
-    render?(tokens: Token[], index: number, options: any, env: any, self: Renderer): string
+  marker?: string | undefined
+  validate?(params: string): boolean
+  render?(
+    tokens: Token[],
+    index: number,
+    options: any,
+    env: any,
+    self: Renderer
+  ): string
 }
 
 export const mdPlugin = (md: MarkdownIt) => {
-    md.use(externalLinkIcon)
-    md.use(tableWrapper)
-    md.use(mdContainer, 'demo', {
-        validate(params) {
-            return !!params.trim().match(/^demo\s*(.*)$/)
-        },
-
-        render(tokens, idx) {
-            const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)
-            if (tokens[idx].nesting === 1 /* means the tag is opening */) {
-                const description = m && m.length > 1 ? m[1] : ''
-                const sourceFileToken = tokens[idx + 2]
-                let source = ''
-                const sourceFile = sourceFileToken.children?.[0].content ?? ''
-
-                if (sourceFileToken.type === 'inline') {
-                    source = fs.readFileSync(path.resolve(docRoot, 'examples', `${sourceFile}.vue`), 'utf-8')
-                }
-                if (!source) throw new Error(`Incorrect source file: ${sourceFile}`)
-
-                return `<Demo :demos="demos" source="${encodeURIComponent(highlight(source, 'vue'))}" path="${sourceFile}" raw-source="${encodeURIComponent(source)}" description="${encodeURIComponent(
-                    localMd.render(description)
-                )}">`
-            } else {
-                return '</Demo>'
-            }
-        },
-    } as ContainerOpts)
+  md.use(externalLinkIcon)
+  md.use(tableWrapper)
+  md.use(tooltip)
+  // demo apply
+  md.use(mdContainer, 'demo', {
+    validate(params) {
+      return !!params.trim().match(/^demo\s*(.*)$/)
+    },
+
+    render(tokens, idx) {
+      const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)
+      if (tokens[idx].nesting === 1 /* means the tag is opening */) {
+        const description = m && m.length > 1 ? m[1] : ''
+        const sourceFileToken = tokens[idx + 2]
+        let source = ''
+        const sourceFile = sourceFileToken.children?.[0].content ?? ''
+
+        if (sourceFileToken.type === 'inline') {
+          source = fs.readFileSync(
+            path.resolve(docRoot, 'examples', `${sourceFile}.vue`),
+            'utf-8'
+          )
+        }
+        if (!source) throw new Error(`Incorrect source file: ${sourceFile}`)
+
+        return `<Demo :demos="demos" source="${encodeURIComponent(
+          highlight(source, 'vue')
+        )}" path="${sourceFile}" raw-source="${encodeURIComponent(
+          source
+        )}" description="${encodeURIComponent(localMd.render(description))}">`
+      } else {
+        return '</Demo>'
+      }
+    },
+  } as ContainerOpts)
+  // repl apply
+  md.use(mdContainer, 'repl', {
+    validate(params) {
+      return !!params.trim().match(/^repl\s*(.*)$/)
+    },
+
+    render(tokens, idx) {
+      const m = tokens[idx].info.trim().match(/^repl\s*(.*)$/)
+      if (tokens[idx].nesting === 1 /* means the tag is opening */) {
+        const description = m && m.length > 1 ? m[1] : ''
+        const sourceFileToken = tokens[idx + 2]
+        let source = ''
+        const sourceFile = sourceFileToken.children?.[0].content ?? ''
+
+        if (sourceFileToken.type === 'inline') {
+          source = fs.readFileSync(
+            path.resolve(docRoot, 'examples', `${sourceFile}.vue`),
+            'utf-8'
+          )
+        }
+        if (!source) throw new Error(`Incorrect source file: ${sourceFile}`)
+
+        return `<Demo isRepl :demos="demos" source="${encodeURIComponent(
+          highlight(source, 'vue')
+        )}" path="${sourceFile}" raw-source="${encodeURIComponent(
+          source
+        )}" description="${encodeURIComponent(localMd.render(description))}">`
+      } else {
+        return '</Demo>'
+      }
+    },
+  } as ContainerOpts)
+
+  md.use(ApiTableContainer)
 }

+ 27 - 17
docs/.vitepress/config/sidebars.ts

@@ -3,39 +3,49 @@ import guideLocale from '../i18n/pages/guide.json'
 import componentLocale from '../i18n/pages/component.json'
 
 function getGuideSidebar() {
-    return Object.fromEntries(Object.entries(guideLocale).map(([lang, val]) => [lang, Object.values(val).map(item => mapPrefix(item, lang))]))
+  return Object.fromEntries(
+    Object.entries(guideLocale).map(([lang, val]) => [
+      lang,
+      Object.values(val).map((item) => mapPrefix(item, lang)),
+    ])
+  )
 }
 
 function getComponentsSideBar() {
-    return Object.fromEntries(Object.entries(componentLocale).map(([lang, val]) => [lang, Object.values(val).map(item => mapPrefix(item, lang, '/component'))]))
+  return Object.fromEntries(
+    Object.entries(componentLocale).map(([lang, val]) => [
+      lang,
+      Object.values(val).map((item) => mapPrefix(item, lang, '/component')),
+    ])
+  )
 }
 
 // return sidebar with language configs.
 // this might create duplicated data but the overhead is ignorable
 const getSidebars = () => {
-    return {
-        '/guide/': getGuideSidebar(),
-        '/component/': getComponentsSideBar(),
-    }
+  return {
+    '/guide/': getGuideSidebar(),
+    '/component/': getComponentsSideBar(),
+  }
 }
 
 type Item = {
-    text: string
-    children?: Item[]
-    link?: string
+  text: string
+  children?: Item[]
+  link?: string
 }
 
 function mapPrefix(item: Item, lang: string, prefix = '') {
-    if (item.children && item.children.length > 0) {
-        return {
-            ...item,
-            children: item.children.map(child => mapPrefix(child, lang, prefix)),
-        }
-    }
+  if (item.children && item.children.length > 0) {
     return {
-        ...item,
-        link: `${ensureLang(lang)}${prefix}${item.link}`,
+      ...item,
+      children: item.children.map((child) => mapPrefix(child, lang, prefix)),
     }
+  }
+  return {
+    ...item,
+    link: `${ensureLang(lang)}${prefix}${item.link}`,
+  }
 }
 
 export const sidebars = getSidebars()

+ 37 - 34
docs/.vitepress/config/sponsors.ts

@@ -1,45 +1,48 @@
 export const rightRichTextSponsors = []
 
 export const rightLogoSmallSponsors = [
-    {
-        name: 'BuildAdmin',
-        img: '/images/sponsors/buildadmin.png',
-        imgL: '/images/sponsors/buildadmin-l.png',
-        url: 'https://wonderful-code.gitee.io/?from=element-plus',
-        slogan: 'Vue3 opensource admin system',
-        slogan_cn: 'Vue3企业级开源后台管理系统',
-    },
-    {
-        name: 'bit',
-        img: '/images/bit.svg',
-        imgL: '/images/bit-l.png',
-        url: 'https://bit.dev/?from=element-ui',
-        slogan: 'Share Code',
-        isDark: true, // dark theme
-    },
+  {
+    name: 'BuildAdmin',
+    img: '/images/sponsors/buildadmin.png',
+    imgL: '/images/sponsors/buildadmin-l.png',
+    url: 'https://wonderful-code.gitee.io/?from=element-plus',
+    slogan: 'Vue3 opensource admin system',
+    slogan_cn: 'Vue3企业级开源后台管理系统',
+  },
+  {
+    name: 'bit',
+    img: '/images/bit.svg',
+    imgL: '/images/bit-l.png',
+    url: 'https://bit.dev/?from=element-ui',
+    slogan: 'Share Code',
+    isDark: true, // dark theme
+  },
 ]
 
 export const leftCustomImgSponsors = [
-    {
-        name: 'VForm',
-        img: '/images/vform.png',
-        url: 'https://vform666.com/vform3.html?from=element_plus',
-        slogan: 'Vue 2/3 Visual/Low-Code Forms',
-        slogan_cn: 'Vue 2/3 可视化低代码表单',
-        banner_img: '/images/vform-banner.png',
-    },
-    {
-        name: 'JSDesign',
-        name_cn: '即时设计',
-        img: '/images/js-design.png',
-        url: 'https://js.design?source=element-plus',
-        slogan: 'Professional online UI design tool',
-        slogan_cn: '专业在线UI设计工具',
-        banner_img: '/images/js-design-banner.jpg',
-    },
+  {
+    name: 'VForm',
+    img: '/images/vform.png',
+    url: 'https://vform666.com/vform3.html?from=element_plus',
+    slogan: 'Vue 2/3 Visual/Low-Code Forms',
+    slogan_cn: 'Vue 2/3 可视化低代码表单',
+    banner_img: '/images/vform-banner.png',
+  },
+  {
+    name: 'JSDesign',
+    name_cn: '即时设计',
+    img: '/images/js-design.png',
+    url: 'https://js.design?source=element-plus',
+    slogan: 'Professional online UI design tool',
+    slogan_cn: '专业在线UI设计工具',
+    banner_img: '/images/js-design-banner.jpg',
+  },
 ]
 
-export const platinumSponsors = [...leftCustomImgSponsors, ...rightRichTextSponsors]
+export const platinumSponsors = [
+  ...leftCustomImgSponsors,
+  ...rightRichTextSponsors,
+]
 
 export const leftLogoSponsors = []
 

+ 8 - 4
docs/.vitepress/dark-mode.js

@@ -1,6 +1,10 @@
 ;(() => {
-    const saved = localStorage.getItem('el-theme-appearance')
-    if (saved === 'auto' ? window.matchMedia(`(prefers-color-scheme: dark)`).matches : saved === 'dark') {
-        document.documentElement.classList.add('dark')
-    }
+  const saved = localStorage.getItem('el-theme-appearance')
+  if (
+    saved === 'auto'
+      ? window.matchMedia(`(prefers-color-scheme: dark)`).matches
+      : saved === 'dark'
+  ) {
+    document.documentElement.classList.add('dark')
+  }
 })()

+ 10 - 10
docs/.vitepress/i18n/component/changelog.json

@@ -1,12 +1,12 @@
 {
-    "zh-CN": {
-        "published-by": "Published by",
-        "open-link": "Open link",
-        "select-version": "Select a version"
-    },
-    "en-US": {
-        "published-by": "Published by",
-        "open-link": "Open link",
-        "select-version": "Select a version"
-    }
+  "zh-CN": {
+    "published-by": "Published by",
+    "open-link": "Open link",
+    "select-version": "Select a version"
+  },
+  "en-US": {
+    "published-by": "Published by",
+    "open-link": "Open link",
+    "select-version": "Select a version"
+  }
 }

+ 24 - 24
docs/.vitepress/i18n/component/demo-block.json

@@ -1,26 +1,26 @@
 {
-    "zh-CN": {
-        "view-source": "查看代码",
-        "hide-source": "Hide source",
-        "edit-in-editor": "Edit in Playground",
-        "edit-on-github": "在Gogs编辑",
-        "edit-in-codepen": "Edit in Codepen.io",
-        "copy-code": "复制代码",
-        "switch-button-option-text": "Switch to Options API",
-        "switch-button-setup-text": "Switch to Composition API",
-        "copy-success": "Copied!",
-        "copy-error": "This browser does not support automatic copy!"
-    },
-    "en-US": {
-        "view-source": "View source",
-        "hide-source": "Hide source",
-        "edit-in-editor": "Edit in Playground",
-        "edit-on-github": "Edit on GitHub",
-        "edit-in-codepen": "Edit in Codepen.io",
-        "copy-code": "Copy code",
-        "switch-button-option-text": "Switch to Options API",
-        "switch-button-setup-text": "Switch to Composition API",
-        "copy-success": "Copied!",
-        "copy-error": "This browser does not support automatic copy!"
-    }
+  "zh-CN": {
+    "view-source": "查看代码",
+    "hide-source": "Hide source",
+    "edit-in-editor": "Edit in Playground",
+    "edit-on-github": "在Gogs编辑",
+    "edit-in-codepen": "Edit in Codepen.io",
+    "copy-code": "复制代码",
+    "switch-button-option-text": "Switch to Options API",
+    "switch-button-setup-text": "Switch to Composition API",
+    "copy-success": "Copied!",
+    "copy-error": "This browser does not support automatic copy!"
+  },
+  "en-US": {
+    "view-source": "View source",
+    "hide-source": "Hide source",
+    "edit-in-editor": "Edit in Playground",
+    "edit-on-github": "Edit on GitHub",
+    "edit-in-codepen": "Edit in Codepen.io",
+    "copy-code": "Copy code",
+    "switch-button-option-text": "Switch to Options API",
+    "switch-button-setup-text": "Switch to Composition API",
+    "copy-success": "Copied!",
+    "copy-error": "This browser does not support automatic copy!"
+  }
 }

+ 8 - 8
docs/.vitepress/i18n/component/edit-link.json

@@ -1,10 +1,10 @@
 {
-    "zh-CN": {
-        "edit-on-github": "Edit this page on GitHub",
-        "edit-on-crowdin": "Edit this page on Crowdin"
-    },
-    "en-US": {
-        "edit-on-github": "Edit this page on GitHub",
-        "edit-on-crowdin": "Edit this page on Crowdin"
-    }
+  "zh-CN": {
+    "edit-on-github": "Edit this page on GitHub",
+    "edit-on-crowdin": "Edit this page on Crowdin"
+  },
+  "en-US": {
+    "edit-on-github": "Edit this page on GitHub",
+    "edit-on-crowdin": "Edit this page on Crowdin"
+  }
 }

+ 12 - 12
docs/.vitepress/i18n/component/footer.json

@@ -1,14 +1,14 @@
 {
-    "zh-CN": {
-        "source": "Source",
-        "contributors": "Contributors",
-        "component": "Component",
-        "docs": "Docs"
-    },
-    "en-US": {
-        "source": "Source",
-        "contributors": "Contributors",
-        "component": "Component",
-        "docs": "Docs"
-    }
+  "zh-CN": {
+    "source": "资源",
+    "contributors": "Contributors",
+    "component": "Component",
+    "docs": "Docs"
+  },
+  "en-US": {
+    "source": "Source",
+    "contributors": "Contributors",
+    "component": "Component",
+    "docs": "Docs"
+  }
 }

+ 8 - 8
docs/.vitepress/i18n/component/icons.json

@@ -1,10 +1,10 @@
 {
-    "zh-CN": {
-        "copy-success": "Copied!",
-        "copy-error": "Your browser does not support copy :("
-    },
-    "en-US": {
-        "copy-success": "Copied!",
-        "copy-error": "Your browser does not support copy :("
-    }
+  "zh-CN": {
+    "copy-success": "Copied!",
+    "copy-error": "Your browser does not support copy :("
+  },
+  "en-US": {
+    "copy-success": "Copied!",
+    "copy-error": "Your browser does not support copy :("
+  }
 }

+ 6 - 6
docs/.vitepress/i18n/component/last-update-at.json

@@ -1,8 +1,8 @@
 {
-    "zh-CN": {
-        "title": "Last Updated"
-    },
-    "en-US": {
-        "title": "Last Updated"
-    }
+  "zh-CN": {
+    "title": "Last Updated"
+  },
+  "en-US": {
+    "title": "Last Updated"
+  }
 }

+ 12 - 12
docs/.vitepress/i18n/component/pwa.json

@@ -1,14 +1,14 @@
 {
-    "zh-CN": {
-        "message": "New content available, click on refresh button to update.",
-        "refresh": "Refresh",
-        "always-refresh": "Always Refresh",
-        "close": "Close"
-    },
-    "en-US": {
-        "message": "New content available, click on refresh button to update.",
-        "refresh": "Refresh",
-        "always-refresh": "Always Refresh",
-        "close": "Close"
-    }
+  "zh-CN": {
+    "message": "New content available, click on refresh button to update.",
+    "refresh": "Refresh",
+    "always-refresh": "Always Refresh",
+    "close": "Close"
+  },
+  "en-US": {
+    "message": "New content available, click on refresh button to update.",
+    "refresh": "Refresh",
+    "always-refresh": "Always Refresh",
+    "close": "Close"
+  }
 }

+ 10 - 10
docs/.vitepress/i18n/component/search.json

@@ -1,12 +1,12 @@
 {
-    "zh-CN": {
-        "search": "搜索",
-        "empty": "搜索为空",
-        "index": "cn"
-    },
-    "en-US": {
-        "search": "Search",
-        "empty": "No results",
-        "index": "en"
-    }
+  "zh-CN": {
+    "search": "搜索",
+    "empty": "搜索为空",
+    "index": "cn"
+  },
+  "en-US": {
+    "search": "Search",
+    "empty": "No results",
+    "index": "en"
+  }
 }

+ 12 - 12
docs/.vitepress/i18n/component/sponsor.json

@@ -1,14 +1,14 @@
 {
-    "zh-CN": {
-        "title": "Sponsors",
-        "sponsoredBy": "Sponsored by",
-        "platinumSponsor": "Platinum Sponsors",
-        "goldSponsor": "Gold Sponsors"
-    },
-    "en-US": {
-        "title": "Sponsors",
-        "sponsoredBy": "Sponsored by",
-        "platinumSponsor": "Platinum Sponsors",
-        "goldSponsor": "Gold Sponsors"
-    }
+  "zh-CN": {
+    "title": "Sponsors",
+    "sponsoredBy": "Sponsored by",
+    "platinumSponsor": "Platinum Sponsors",
+    "goldSponsor": "Gold Sponsors"
+  },
+  "en-US": {
+    "title": "Sponsors",
+    "sponsoredBy": "Sponsored by",
+    "platinumSponsor": "Platinum Sponsors",
+    "goldSponsor": "Gold Sponsors"
+  }
 }

+ 6 - 6
docs/.vitepress/i18n/component/translation.json

@@ -1,8 +1,8 @@
 {
-    "zh-CN": {
-        "help": "Help Translate 😉"
-    },
-    "en-US": {
-        "help": "Help Translate 😉"
-    }
+  "zh-CN": {
+    "help": "Help Translate 😉"
+  },
+  "en-US": {
+    "help": "Help Translate 😉"
+  }
 }

+ 36 - 335
docs/.vitepress/i18n/pages/component.json

@@ -1,345 +1,46 @@
 {
-    "zh-CN": {
-        "basic": {
-            "text": "基础组件",
-            "children": [
-                {
-                    "link": "/button",
-                    "text": "按钮"
-                },
-                {
-                    "link": "/audio",
-                    "text": "音频"
-                }
-            ]
+  "zh-CN": {
+    "basic": {
+      "text": "基础组件",
+      "children": [
+        {
+          "link": "/icon",
+          "text": "Icon图标"
         },
-        "advance": {
-            "text": "高级组件",
-            "children": [
-                {
-                    "link": "/tagsEditor",
-                    "text": "tag编辑器"
-                }
-            ]
-        }
-    },
-    "en-US": {
-        "basic": {
-            "text": "Basic",
-            "children": [
-                {
-                    "link": "/button",
-                    "text": "Button"
-                },
-                {
-                    "link": "/border",
-                    "text": "Border"
-                },
-                {
-                    "link": "/color",
-                    "text": "Color"
-                },
-                {
-                    "link": "/container",
-                    "text": "Layout Container"
-                },
-                {
-                    "link": "/icon",
-                    "text": "Icon"
-                },
-                {
-                    "link": "/layout",
-                    "text": "Layout"
-                },
-                {
-                    "link": "/link",
-                    "text": "Link"
-                },
-                {
-                    "link": "/scrollbar",
-                    "text": "Scrollbar"
-                },
-                {
-                    "link": "/space",
-                    "text": "Space"
-                },
-                {
-                    "link": "/typography",
-                    "text": "Typography"
-                }
-            ]
-        },
-        "configuration": {
-            "text": "Configuration",
-            "children": [
-                {
-                    "link": "/config-provider",
-                    "text": "Config Provider"
-                }
-            ]
+        {
+          "link": "/button",
+          "text": "Button按钮"
         },
-        "form": {
-            "text": "Form",
-            "children": [
-                {
-                    "link": "/autocomplete",
-                    "text": "Autocomplete"
-                },
-                {
-                    "link": "/cascader",
-                    "text": "Cascader"
-                },
-                {
-                    "link": "/checkbox",
-                    "text": "Checkbox"
-                },
-                {
-                    "link": "/color-picker",
-                    "text": "Color Picker"
-                },
-                {
-                    "link": "/date-picker",
-                    "text": "Date Picker"
-                },
-                {
-                    "link": "/datetime-picker",
-                    "text": "DateTime Picker"
-                },
-                {
-                    "link": "/form",
-                    "text": "Form"
-                },
-                {
-                    "link": "/input",
-                    "text": "Input"
-                },
-                {
-                    "link": "/input-number",
-                    "text": "Input Number"
-                },
-                {
-                    "link": "/radio",
-                    "text": "Radio"
-                },
-                {
-                    "link": "/rate",
-                    "text": "Rate"
-                },
-                {
-                    "link": "/select",
-                    "text": "Select"
-                },
-                {
-                    "link": "/select-v2",
-                    "text": "Virtualized Select"
-                },
-                {
-                    "link": "/slider",
-                    "text": "Slider"
-                },
-                {
-                    "link": "/switch",
-                    "text": "Switch"
-                },
-                {
-                    "link": "/time-picker",
-                    "text": "Time Picker"
-                },
-                {
-                    "link": "/time-select",
-                    "text": "Time Select"
-                },
-                {
-                    "link": "/transfer",
-                    "text": "Transfer"
-                },
-                {
-                    "link": "/upload",
-                    "text": "Upload"
-                }
-            ]
+        {
+          "link": "/audio",
+          "text": "Audio音频"
         },
-        "data": {
-            "text": "Data",
-            "children": [
-                {
-                    "link": "/avatar",
-                    "text": "Avatar"
-                },
-                {
-                    "link": "/badge",
-                    "text": "Badge"
-                },
-                {
-                    "link": "/calendar",
-                    "text": "Calendar"
-                },
-                {
-                    "link": "/card",
-                    "text": "Card"
-                },
-                {
-                    "link": "/carousel",
-                    "text": "Carousel"
-                },
-                {
-                    "link": "/collapse",
-                    "text": "Collapse"
-                },
-                {
-                    "link": "/descriptions",
-                    "text": "Descriptions"
-                },
-                {
-                    "link": "/empty",
-                    "text": "Empty"
-                },
-                {
-                    "link": "/image",
-                    "text": "Image"
-                },
-                {
-                    "link": "/infinite-scroll",
-                    "text": "Infinite Scroll"
-                },
-                {
-                    "link": "/pagination",
-                    "text": "Pagination"
-                },
-                {
-                    "link": "/progress",
-                    "text": "Progress"
-                },
-                {
-                    "link": "/result",
-                    "text": "Result"
-                },
-                {
-                    "link": "/skeleton",
-                    "text": "Skeleton"
-                },
-                {
-                    "link": "/table",
-                    "text": "Table"
-                },
-                {
-                    "link": "/table-v2",
-                    "text": "Virtualized Table",
-                    "promotion": "2.2.0"
-                },
-                {
-                    "link": "/tag",
-                    "text": "Tag"
-                },
-                {
-                    "link": "/timeline",
-                    "text": "Timeline"
-                },
-                {
-                    "link": "/tree",
-                    "text": "Tree"
-                },
-                {
-                    "link": "/tree-select",
-                    "text": "TreeSelect",
-                    "promotion": "2.1.8"
-                },
-                {
-                    "link": "/tree-v2",
-                    "text": "Virtualized Tree"
-                }
-            ]
+        {
+          "link": "/input",
+          "text": "Input 输入框"
         },
-        "navigation": {
-            "text": "Navigation",
-            "children": [
-                {
-                    "link": "/affix",
-                    "text": "Affix"
-                },
-                {
-                    "link": "/backtop",
-                    "text": "Backtop"
-                },
-                {
-                    "link": "/breadcrumb",
-                    "text": "Breadcrumb"
-                },
-                {
-                    "link": "/dropdown",
-                    "text": "Dropdown"
-                },
-                {
-                    "link": "/menu",
-                    "text": "Menu"
-                },
-                {
-                    "link": "/page-header",
-                    "text": "Page Header"
-                },
-                {
-                    "link": "/steps",
-                    "text": "Steps"
-                },
-                {
-                    "link": "/tabs",
-                    "text": "Tabs"
-                }
-            ]
+        {
+          "link": "/dialog",
+          "text": "Dialog对话框"
+        }
+      ]
+    },
+    "advance": {
+      "text": "高级组件",
+      "children": [
+        {
+          "link": "/tag",
+          "text": "tag热点"
         },
-        "feedback": {
-            "text": "Feedback",
-            "children": [
-                {
-                    "link": "/alert",
-                    "text": "Alert"
-                },
-                {
-                    "link": "/dialog",
-                    "text": "Dialog"
-                },
-                {
-                    "link": "/drawer",
-                    "text": "Drawer"
-                },
-                {
-                    "link": "/loading",
-                    "text": "Loading"
-                },
-                {
-                    "link": "/message",
-                    "text": "Message"
-                },
-                {
-                    "link": "/message-box",
-                    "text": "Message Box"
-                },
-                {
-                    "link": "/notification",
-                    "text": "Notification"
-                },
-                {
-                    "link": "/popconfirm",
-                    "text": "Popconfirm"
-                },
-                {
-                    "link": "/popover",
-                    "text": "Popover"
-                },
-                {
-                    "link": "/tooltip",
-                    "text": "Tooltip"
-                }
-            ]
+        {
+          "link": "/daikan",
+          "text": "daikan带看"
         },
-        "others": {
-            "text": "Others",
-            "children": [
-                {
-                    "link": "/divider",
-                    "text": "Divider"
-                }
-            ]
+        {
+          "link": "/minmap",
+          "text": "minmap小地图"
         }
+      ]
     }
+  }
 }

+ 154 - 154
docs/.vitepress/i18n/pages/guide.json

@@ -1,160 +1,160 @@
 {
-    "zh-CN": {
-        "intro": {
-            "text": "Basics",
-            "children": [
-                {
-                    "text": "Design",
-                    "link": "/guide/design"
-                },
-                {
-                    "text": "Navigation",
-                    "link": "/guide/nav"
-                },
-                {
-                    "text": "Installation",
-                    "link": "/guide/installation"
-                },
-                {
-                    "text": "Quick Start",
-                    "link": "/guide/quickstart"
-                }
-            ]
-        },
-        "advanced": {
-            "text": "Advanced",
-            "children": [
-                {
-                    "text": "i18n",
-                    "link": "/guide/i18n"
-                },
-                {
-                    "text": "Migration from ElementUI",
-                    "link": "/guide/migration"
-                },
-                {
-                    "text": "Theming",
-                    "link": "/guide/theming"
-                },
-                {
-                    "text": "Dark Mode",
-                    "link": "/guide/dark-mode",
-                    "promotion": "2.2.0"
-                },
-                {
-                    "text": "Custom Namespace",
-                    "link": "/guide/namespace",
-                    "promotion": "2.2.0"
-                },
-                {
-                    "text": "Built-in Transitions",
-                    "link": "/guide/transitions"
-                },
-                {
-                    "text": "Changelog",
-                    "link": "/guide/changelog"
-                }
-            ]
-        },
-        "development": {
-            "text": "Development",
-            "children": [
-                {
-                    "text": "Development Guide",
-                    "link": "/guide/dev-guide"
-                },
-                {
-                    "text": "Development FAQ",
-                    "link": "/guide/dev-faq"
-                },
-                {
-                    "text": "Commit Examples",
-                    "link": "/guide/commit-examples"
-                },
-                {
-                    "text": "Translation",
-                    "link": "/guide/translation"
-                }
-            ]
+  "zh-CN": {
+    "intro": {
+      "text": "Basics",
+      "children": [
+        {
+          "text": "Design",
+          "link": "/guide/design"
+        },
+        {
+          "text": "Navigation",
+          "link": "/guide/nav"
+        },
+        {
+          "text": "Installation",
+          "link": "/guide/installation"
+        },
+        {
+          "text": "Quick Start",
+          "link": "/guide/quickstart"
+        }
+      ]
+    },
+    "advanced": {
+      "text": "Advanced",
+      "children": [
+        {
+          "text": "i18n",
+          "link": "/guide/i18n"
+        },
+        {
+          "text": "Migration from ElementUI",
+          "link": "/guide/migration"
+        },
+        {
+          "text": "Theming",
+          "link": "/guide/theming"
+        },
+        {
+          "text": "Dark Mode",
+          "link": "/guide/dark-mode",
+          "promotion": "2.2.0"
+        },
+        {
+          "text": "Custom Namespace",
+          "link": "/guide/namespace",
+          "promotion": "2.2.0"
+        },
+        {
+          "text": "Built-in Transitions",
+          "link": "/guide/transitions"
+        },
+        {
+          "text": "Changelog",
+          "link": "/guide/changelog"
+        }
+      ]
+    },
+    "development": {
+      "text": "Development",
+      "children": [
+        {
+          "text": "Development Guide",
+          "link": "/guide/dev-guide"
+        },
+        {
+          "text": "Development FAQ",
+          "link": "/guide/dev-faq"
+        },
+        {
+          "text": "Commit Examples",
+          "link": "/guide/commit-examples"
+        },
+        {
+          "text": "Translation",
+          "link": "/guide/translation"
         }
+      ]
+    }
+  },
+  "en-US": {
+    "intro": {
+      "text": "Basics",
+      "children": [
+        {
+          "text": "Design",
+          "link": "/guide/design"
+        },
+        {
+          "text": "Navigation",
+          "link": "/guide/nav"
+        },
+        {
+          "text": "Installation",
+          "link": "/guide/installation"
+        },
+        {
+          "text": "Quick Start",
+          "link": "/guide/quickstart"
+        }
+      ]
+    },
+    "advanced": {
+      "text": "Advanced",
+      "children": [
+        {
+          "text": "i18n",
+          "link": "/guide/i18n"
+        },
+        {
+          "text": "Migration from ElementUI",
+          "link": "/guide/migration"
+        },
+        {
+          "text": "Theming",
+          "link": "/guide/theming"
+        },
+        {
+          "text": "Dark Mode",
+          "link": "/guide/dark-mode",
+          "promotion": "2.2.0"
+        },
+        {
+          "text": "Custom Namespace",
+          "link": "/guide/namespace",
+          "promotion": "2.2.0"
+        },
+        {
+          "text": "Built-in Transitions",
+          "link": "/guide/transitions"
+        },
+        {
+          "text": "Changelog",
+          "link": "/guide/changelog"
+        }
+      ]
     },
-    "en-US": {
-        "intro": {
-            "text": "Basics",
-            "children": [
-                {
-                    "text": "Design",
-                    "link": "/guide/design"
-                },
-                {
-                    "text": "Navigation",
-                    "link": "/guide/nav"
-                },
-                {
-                    "text": "Installation",
-                    "link": "/guide/installation"
-                },
-                {
-                    "text": "Quick Start",
-                    "link": "/guide/quickstart"
-                }
-            ]
-        },
-        "advanced": {
-            "text": "Advanced",
-            "children": [
-                {
-                    "text": "i18n",
-                    "link": "/guide/i18n"
-                },
-                {
-                    "text": "Migration from ElementUI",
-                    "link": "/guide/migration"
-                },
-                {
-                    "text": "Theming",
-                    "link": "/guide/theming"
-                },
-                {
-                    "text": "Dark Mode",
-                    "link": "/guide/dark-mode",
-                    "promotion": "2.2.0"
-                },
-                {
-                    "text": "Custom Namespace",
-                    "link": "/guide/namespace",
-                    "promotion": "2.2.0"
-                },
-                {
-                    "text": "Built-in Transitions",
-                    "link": "/guide/transitions"
-                },
-                {
-                    "text": "Changelog",
-                    "link": "/guide/changelog"
-                }
-            ]
-        },
-        "development": {
-            "text": "Development",
-            "children": [
-                {
-                    "text": "Development Guide",
-                    "link": "/guide/dev-guide"
-                },
-                {
-                    "text": "Development FAQ",
-                    "link": "/guide/dev-faq"
-                },
-                {
-                    "text": "Commit Examples",
-                    "link": "/guide/commit-examples"
-                },
-                {
-                    "text": "Translation",
-                    "link": "/guide/translation"
-                }
-            ]
+    "development": {
+      "text": "Development",
+      "children": [
+        {
+          "text": "Development Guide",
+          "link": "/guide/dev-guide"
+        },
+        {
+          "text": "Development FAQ",
+          "link": "/guide/dev-faq"
+        },
+        {
+          "text": "Commit Examples",
+          "link": "/guide/commit-examples"
+        },
+        {
+          "text": "Translation",
+          "link": "/guide/translation"
         }
+      ]
     }
+  }
 }

+ 56 - 56
docs/.vitepress/i18n/pages/home.json

@@ -1,58 +1,58 @@
 {
-    "zh-CN": {
-        "1": "",
-        "2": "",
-        "3": "Guide",
-        "4": "Understand the design guidelines, helping designers build product that's logically sound, reasonably structured and easy to use.",
-        "5": "View Detail",
-        "6": "Component",
-        "7": "Experience interaction details by strolling through component demos. Use encapsulated code to improve developing efficiency.",
-        "8": "Resource",
-        "9": "Download relevant design resources for shaping page prototype or visual draft, increasing design efficiency.",
-        "10": "Links",
-        "11": "GitHub",
-        "12": "Changelog",
-        "13": "Element UI for Vue 2",
-        "14": "Online Theme Roller",
-        "15": "Gitter",
-        "16": "Feedback",
-        "17": "Contribution",
-        "18": "SegmentFault",
-        "19": "Community",
-        "20": "Become a Sponsor!",
-        "21": "Please contact us via",
-        "title_release": "Element Plus stable release is coming",
-        "title": "kankan compoents",
-        "title_sub": "四维看看公共组件库",
-        "china_mirror": "China Mirror 🇨🇳",
-        "discord": "Discord"
-    },
-    "en-US": {
-        "1": "",
-        "2": "",
-        "3": "Guide",
-        "4": "Understand the design guidelines, helping designers build product that's logically sound, reasonably structured and easy to use.",
-        "5": "View Detail",
-        "6": "Component",
-        "7": "Experience interaction details by strolling through component demos. Use encapsulated code to improve developing efficiency.",
-        "8": "Resource",
-        "9": "Download relevant design resources for shaping page prototype or visual draft, increasing design efficiency.",
-        "10": "Links",
-        "11": "GitHub",
-        "12": "Changelog",
-        "13": "Element UI for Vue 2",
-        "14": "Online Theme Roller",
-        "15": "Gitter",
-        "16": "Feedback",
-        "17": "Contribution",
-        "18": "SegmentFault",
-        "19": "Community",
-        "20": "Become a Sponsor!",
-        "21": "Please contact us via",
-        "title_release": "Element Plus stable release is coming",
-        "title": "Element Plus",
-        "title_sub": "a Vue 3 based component library for designers and developers",
-        "china_mirror": "China Mirror 🇨🇳",
-        "discord": "Discord"
-    }
+  "zh-CN": {
+    "1": "",
+    "2": "",
+    "3": "Guide",
+    "4": "Understand the design guidelines, helping designers build product that's logically sound, reasonably structured and easy to use.",
+    "5": "View Detail",
+    "6": "Component",
+    "7": "Experience interaction details by strolling through component demos. Use encapsulated code to improve developing efficiency.",
+    "8": "Resource",
+    "9": "Download relevant design resources for shaping page prototype or visual draft, increasing design efficiency.",
+    "10": "Links",
+    "11": "GitHub",
+    "12": "Changelog",
+    "13": "Element UI for Vue 2",
+    "14": "Online Theme Roller",
+    "15": "Gitter",
+    "16": "Feedback",
+    "17": "Contribution",
+    "18": "SegmentFault",
+    "19": "Community",
+    "20": "Become a Sponsor!",
+    "21": "Please contact us via",
+    "title_release": "Element Plus stable release is coming",
+    "title": "kankan compoents",
+    "title_sub": "四维看看公共组件库",
+    "china_mirror": "China Mirror 🇨🇳",
+    "discord": "Discord"
+  },
+  "en-US": {
+    "1": "",
+    "2": "",
+    "3": "Guide",
+    "4": "Understand the design guidelines, helping designers build product that's logically sound, reasonably structured and easy to use.",
+    "5": "View Detail",
+    "6": "Component",
+    "7": "Experience interaction details by strolling through component demos. Use encapsulated code to improve developing efficiency.",
+    "8": "Resource",
+    "9": "Download relevant design resources for shaping page prototype or visual draft, increasing design efficiency.",
+    "10": "Links",
+    "11": "GitHub",
+    "12": "Changelog",
+    "13": "Element UI for Vue 2",
+    "14": "Online Theme Roller",
+    "15": "Gitter",
+    "16": "Feedback",
+    "17": "Contribution",
+    "18": "SegmentFault",
+    "19": "Community",
+    "20": "Become a Sponsor!",
+    "21": "Please contact us via",
+    "title_release": "Element Plus stable release is coming",
+    "title": "Element Plus",
+    "title_sub": "a Vue 3 based component library for designers and developers",
+    "china_mirror": "China Mirror 🇨🇳",
+    "discord": "Discord"
+  }
 }

+ 10 - 10
docs/.vitepress/i18n/pages/not-found.json

@@ -1,12 +1,12 @@
 {
-    "zh-CN": {
-        "title": "Resource not found",
-        "button-title": "Back to Home",
-        "desc": "The page you requested does not exist"
-    },
-    "en-US": {
-        "title": "Resource not found",
-        "button-title": "Back to Home",
-        "desc": "The page you requested does not exist"
-    }
+  "zh-CN": {
+    "title": "资源未找到",
+    "button-title": "回到首页",
+    "desc": "你访问页面不存在"
+  },
+  "en-US": {
+    "title": "Resource not found",
+    "button-title": "Back to Home",
+    "desc": "The page you requested does not exist"
+  }
 }

+ 24 - 24
docs/.vitepress/i18n/pages/resource.json

@@ -1,26 +1,26 @@
 {
-    "zh-CN": {
-        "title": "Resources",
-        "lineOne": "More resources are still under development. ",
-        "lineTwo": "If you are interested in participating in the design of Element Plus, be our guest to contact us via <span><a href=\"mailto:element-plus@outlook.com\" target=\"_blank\">element-plus@outlook.com</a></span>.",
-        "download": "Download",
-        "axure": "Axure Components",
-        "axureIntro": "By importing Element Plus in Axure, you can easily apply all the components we provide during interaction design.",
-        "sketch": "Sketch Template",
-        "sketchIntro": "Newly designed Sketch component library in 2022 with full components for Element Plus to improve design efficiency while keeping a unified visual style.",
-        "figma": "Figma Template",
-        "figmaIntro": "Newly designed Figma component library in 2022 with new features such as Auto-layout and Variants."
-    },
-    "en-US": {
-        "title": "Resources",
-        "lineOne": "More resources are still under development. ",
-        "lineTwo": "If you are interested in participating in the design of Element Plus, be our guest to contact us via <span><a href=\"mailto:element-plus@outlook.com\" target=\"_blank\">element-plus@outlook.com</a></span>.",
-        "download": "Download",
-        "axure": "Axure Components",
-        "axureIntro": "By importing Element Plus in Axure, you can easily apply all the components we provide during interaction design.",
-        "sketch": "Sketch Template",
-        "sketchIntro": "Newly designed Sketch component library in 2022 with full components for Element Plus to improve design efficiency while keeping a unified visual style.",
-        "figma": "Figma Template",
-        "figmaIntro": "Newly designed Figma component library in 2022 with new features such as Auto-layout and Variants."
-    }
+  "zh-CN": {
+    "title": "Resources",
+    "lineOne": "More resources are still under development. ",
+    "lineTwo": "If you are interested in participating in the design of Element Plus, be our guest to contact us via <span><a href=\"mailto:element-plus@outlook.com\" target=\"_blank\">element-plus@outlook.com</a></span>.",
+    "download": "Download",
+    "axure": "Axure Components",
+    "axureIntro": "By importing Element Plus in Axure, you can easily apply all the components we provide during interaction design.",
+    "sketch": "Sketch Template",
+    "sketchIntro": "Newly designed Sketch component library in 2022 with full components for Element Plus to improve design efficiency while keeping a unified visual style.",
+    "figma": "Figma Template",
+    "figmaIntro": "Newly designed Figma component library in 2022 with new features such as Auto-layout and Variants."
+  },
+  "en-US": {
+    "title": "Resources",
+    "lineOne": "More resources are still under development. ",
+    "lineTwo": "If you are interested in participating in the design of Element Plus, be our guest to contact us via <span><a href=\"mailto:element-plus@outlook.com\" target=\"_blank\">element-plus@outlook.com</a></span>.",
+    "download": "Download",
+    "axure": "Axure Components",
+    "axureIntro": "By importing Element Plus in Axure, you can easily apply all the components we provide during interaction design.",
+    "sketch": "Sketch Template",
+    "sketchIntro": "Newly designed Sketch component library in 2022 with full components for Element Plus to improve design efficiency while keeping a unified visual style.",
+    "figma": "Figma Template",
+    "figmaIntro": "Newly designed Figma component library in 2022 with new features such as Auto-layout and Variants."
+  }
 }

+ 24 - 24
docs/.vitepress/i18n/pages/sidebar.json

@@ -1,26 +1,26 @@
 {
-    "zh-CN": [
-        {
-            "text": "组件",
-            "link": "/component/button",
-            "activeMatch": "/component/"
-        }
-    ],
-    "en-US": [
-        {
-            "text": "Guide",
-            "link": "/guide/design",
-            "activeMatch": "/guide/"
-        },
-        {
-            "text": "Component",
-            "link": "/component/button",
-            "activeMatch": "/component/"
-        },
-        {
-            "text": "Resource",
-            "link": "/resource/index",
-            "activeMatch": "/resource/"
-        }
-    ]
+  "zh-CN": [
+    {
+      "text": "组件",
+      "link": "/component/button",
+      "activeMatch": "/component/"
+    }
+  ],
+  "en-US": [
+    {
+      "text": "Guide",
+      "link": "/guide/design",
+      "activeMatch": "/guide/"
+    },
+    {
+      "text": "Component",
+      "link": "/component/button",
+      "activeMatch": "/component/"
+    },
+    {
+      "text": "Resource",
+      "link": "/resource/index",
+      "activeMatch": "/resource/"
+    }
+  ]
 }

+ 33 - 24
docs/.vitepress/lang.js

@@ -1,26 +1,35 @@
 ;(() => {
-    const supportedLangs = window.supportedLangs
-    const cacheKey = 'preferred_lang'
-    const defaultLang = 'zh-CN'
-    // docs supported languages
-    const langAlias = {
-        cn: 'zh-CN',
-        en: 'en-US',
-        fr: 'fr-FR',
-        es: 'es-ES',
-    }
-    let userPreferredLang = localStorage.getItem(cacheKey) || navigator.language
-    const language = langAlias[userPreferredLang] || (supportedLangs.includes(userPreferredLang) ? userPreferredLang : defaultLang)
-    localStorage.setItem(cacheKey, language)
-    userPreferredLang = language
-    if (!location.pathname.startsWith(`/${userPreferredLang}`)) {
-        const toPath = [`/${userPreferredLang}`].concat(location.pathname.split('/').slice(2)).join('/')
-        location.pathname = toPath.endsWith('.html') || toPath.endsWith('/') ? toPath : toPath.concat('/')
-    }
-    if (navigator && navigator.serviceWorker.controller) {
-        navigator.serviceWorker.controller.postMessage({
-            type: 'LANG',
-            lang: userPreferredLang,
-        })
-    }
+  const supportedLangs = window.supportedLangs
+  const cacheKey = 'preferred_lang'
+  const defaultLang = 'zh-CN'
+  // docs supported languages
+  const langAlias = {
+    cn: 'zh-CN',
+    en: 'en-US',
+    fr: 'fr-FR',
+    es: 'es-ES',
+  }
+  let userPreferredLang = localStorage.getItem(cacheKey) || navigator?.language
+  const language =
+    langAlias[userPreferredLang] ||
+    (supportedLangs.includes(userPreferredLang)
+      ? userPreferredLang
+      : defaultLang)
+  localStorage.setItem(cacheKey, language)
+  userPreferredLang = language
+  if (!location.pathname.startsWith(`/${userPreferredLang}`)) {
+    const toPath = [`/${userPreferredLang}`]
+      .concat(location.pathname.split('/').slice(2))
+      .join('/')
+    location.pathname =
+      toPath.endsWith('.html') || toPath.endsWith('/')
+        ? toPath
+        : toPath.concat('/')
+  }
+  if (navigator && navigator.serviceWorker.controller) {
+    navigator.serviceWorker.controller.postMessage({
+      type: 'LANG',
+      lang: userPreferredLang,
+    })
+  }
 })()

+ 40 - 0
docs/.vitepress/plugins/api-table.ts

@@ -0,0 +1,40 @@
+import markdown from 'markdown-it'
+
+import type MarkdownIt from 'markdown-it'
+
+const ApiMd = new markdown()
+
+export const ApiTableContainer = (md: MarkdownIt) => {
+  const fence = md.renderer.rules.fence!
+
+  ApiMd.renderer.rules = md.renderer.rules
+  md.renderer.rules.fence = (...args) => {
+    const [tokens, idx, ...rest] = args
+    const [options, env] = rest
+    const token = tokens[idx]
+    if (token.info === 'api') {
+      const newTokens = md.parse(token.content, env)
+
+      let result = ''
+      const { rules } = md.renderer
+      newTokens.forEach((newToken, idx) => {
+        const { type } = newToken
+        if (type === 'inline') {
+          result += md.renderer.renderInline(newToken.children!, options, env)
+        } else if (typeof rules[type] !== 'undefined') {
+          result += rules[newToken.type]!(
+            newTokens,
+            idx,
+            options,
+            env,
+            md.renderer
+          )
+        } else {
+          result += md.renderer.renderToken(newTokens, idx, options)
+        }
+      })
+      return result
+    }
+    return fence.call(md, ...args)
+  }
+}

+ 26 - 21
docs/.vitepress/plugins/external-link-icon.ts

@@ -2,31 +2,36 @@ import type MarkdownIt from 'markdown-it'
 import type Renderer from 'markdown-it/lib/renderer'
 
 export default (md: MarkdownIt): void => {
-    const renderToken: Renderer.RenderRule = (tokens, idx, options, env, self) => self.renderToken(tokens, idx, options)
-    const defaultLinkOpenRenderer = md.renderer.rules.link_open || renderToken
-    const defaultLinkCloseRenderer = md.renderer.rules.link_close || renderToken
-    let isExternalLink = false
+  const renderToken: Renderer.RenderRule = (tokens, idx, options, env, self) =>
+    self.renderToken(tokens, idx, options)
+  const defaultLinkOpenRenderer = md.renderer.rules.link_open || renderToken
+  const defaultLinkCloseRenderer = md.renderer.rules.link_close || renderToken
+  let isExternalLink = false
 
-    md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
-        const token = tokens[idx]
-        const href = token.attrGet('href')
+  md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
+    const token = tokens[idx]
+    const href = token.attrGet('href')
 
-        if (href) {
-            token.attrJoin('class', 'vp-link')
-            if (/^((ht|f)tps?):\/\/?/.test(href)) {
-                isExternalLink = true
-            }
-        }
-
-        return defaultLinkOpenRenderer(tokens, idx, options, env, self)
+    if (href) {
+      token.attrJoin('class', 'vp-link')
+      if (/^((ht|f)tps?):\/\/?/.test(href)) {
+        isExternalLink = true
+      }
     }
 
-    md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
-        if (isExternalLink) {
-            isExternalLink = false
-            return `<i-ri-external-link-line class="link-icon" />${self.renderToken(tokens, idx, options)}`
-        }
+    return defaultLinkOpenRenderer(tokens, idx, options, env, self)
+  }
 
-        return defaultLinkCloseRenderer(tokens, idx, options, env, self)
+  md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
+    if (isExternalLink) {
+      isExternalLink = false
+      return `<i-ri-external-link-line class="link-icon" />${self.renderToken(
+        tokens,
+        idx,
+        options
+      )}`
     }
+
+    return defaultLinkCloseRenderer(tokens, idx, options, env, self)
+  }
 }

+ 81 - 61
docs/.vitepress/plugins/markdown-transform.ts

@@ -11,92 +11,112 @@ import type { Plugin } from 'vite'
 type Append = Record<'headers' | 'footers' | 'scriptSetups', string[]>
 
 export function MarkdownTransform(): Plugin {
-    return {
-        name: 'element-plus-md-transform',
-        enforce: 'pre',
-        async transform(code, id) {
-            if (!id.endsWith('.md')) return
-
-            const componentId = path.basename(id, '.md')
-            const append: Append = {
-                headers: [],
-                footers: [],
-                scriptSetups: [`const demos = import.meta.globEager('../../examples/${componentId}/*.vue')`],
-            }
-
-            code = transformVpScriptSetup(code, append)
-
-            const pattern = `{${[...languages, languages[0]].join(',')}}/component`
-            const compPaths = await glob(pattern, {
-                cwd: docRoot,
-                absolute: true,
-                onlyDirectories: true,
-            })
-            if (compPaths.some(compPath => id.startsWith(compPath))) {
-                code = transformComponentMarkdown(id, componentId, code, append)
-            }
-
-            return combineMarkdown(code, [combineScriptSetup(append.scriptSetups), ...append.headers], append.footers)
-        },
-    }
+  return {
+    name: 'element-plus-md-transform',
+    enforce: 'pre',
+    async transform(code, id) {
+      if (!id.endsWith('.md')) return
+
+      const componentId = path.basename(id, '.md')
+      const append: Append = {
+        headers: [],
+        footers: [],
+        scriptSetups: [
+          `const demos = import.meta.globEager('../../examples/${componentId}/*.vue')`,
+        ],
+      }
+
+      code = transformVpScriptSetup(code, append)
+
+      const pattern = `{${[...languages, languages[0]].join(',')}}/component`
+      const compPaths = await glob(pattern, {
+        cwd: docRoot,
+        absolute: true,
+        onlyDirectories: true,
+      })
+      if (compPaths.some((compPath) => id.startsWith(compPath))) {
+        code = transformComponentMarkdown(id, componentId, code, append)
+      }
+
+      return combineMarkdown(
+        code,
+        [combineScriptSetup(append.scriptSetups), ...append.headers],
+        append.footers
+      )
+    },
+  }
 }
 
 const combineScriptSetup = (codes: string[]) =>
-    `\n<script setup>
+  `\n<script setup>
 ${codes.join('\n')}
 </script>
 `
 
-const combineMarkdown = (code: string, headers: string[], footers: string[]) => {
-    const frontmatterEnds = code.indexOf('---\n\n') + 4
-    const firstSubheader = code.search(/\n## \w/)
-    const sliceIndex = firstSubheader < 0 ? frontmatterEnds : firstSubheader
-
-    if (headers.length > 0) code = code.slice(0, sliceIndex) + headers.join('\n') + code.slice(sliceIndex)
-    code += footers.join('\n')
-
-    return `${code}\n`
+const combineMarkdown = (
+  code: string,
+  headers: string[],
+  footers: string[]
+) => {
+  const frontmatterEnds = code.indexOf('---\n\n') + 4
+  const firstSubheader = code.search(/\n## \w/)
+  const sliceIndex = firstSubheader < 0 ? frontmatterEnds : firstSubheader
+
+  if (headers.length > 0)
+    code =
+      code.slice(0, sliceIndex) + headers.join('\n') + code.slice(sliceIndex)
+  code += footers.join('\n')
+
+  return `${code}\n`
 }
 
 const vpScriptSetupRE = /<vp-script\s(.*\s)?setup(\s.*)?>([\s\S]*)<\/vp-script>/
 
 const transformVpScriptSetup = (code: string, append: Append) => {
-    const matches = code.match(vpScriptSetupRE)
-    if (matches) code = code.replace(matches[0], '')
-    const scriptSetup = matches?.[3] ?? ''
-    if (scriptSetup) append.scriptSetups.push(scriptSetup)
-    return code
+  const matches = code.match(vpScriptSetupRE)
+  if (matches) code = code.replace(matches[0], '')
+  const scriptSetup = matches?.[3] ?? ''
+  if (scriptSetup) append.scriptSetups.push(scriptSetup)
+  return code
 }
 
 const GITHUB_BLOB_URL = `https://github.com/${REPO_PATH}/blob/${REPO_BRANCH}`
 const GITHUB_TREE_URL = `https://github.com/${REPO_PATH}/tree/${REPO_BRANCH}`
-const transformComponentMarkdown = (id: string, componentId: string, code: string, append: Append) => {
-    const lang = getLang(id)
-    const docUrl = `${GITHUB_BLOB_URL}/${docsDirName}/en-US/component/${componentId}.md`
-    const componentUrl = `${GITHUB_TREE_URL}/packages/components/${componentId}`
-    const componentPath = path.resolve(projRoot, `packages/components/${componentId}`)
-    const isComponent = fs.existsSync(componentPath)
-
-    const links = [[footerLocale[lang].docs, docUrl]]
-    if (isComponent) links.unshift([footerLocale[lang].component, componentUrl])
-    const linksText = links
-        .filter(i => i)
-        .map(([text, link]) => `[${text}](${link})`)
-        .join(' • ')
-
-    const sourceSection = `
+const transformComponentMarkdown = (
+  id: string,
+  componentId: string,
+  code: string,
+  append: Append
+) => {
+  const lang = getLang(id)
+  const docUrl = `${GITHUB_BLOB_URL}/${docsDirName}/en-US/component/${componentId}.md`
+  const componentUrl = `${GITHUB_TREE_URL}/packages/components/${componentId}`
+  const componentPath = path.resolve(
+    projRoot,
+    `packages/components/${componentId}`
+  )
+  const isComponent = fs.existsSync(componentPath)
+
+  const links = [[footerLocale[lang].docs, docUrl]]
+  if (isComponent) links.unshift([footerLocale[lang].component, componentUrl])
+  const linksText = links
+    .filter((i) => i)
+    .map(([text, link]) => `[${text}](${link})`)
+    .join(' • ')
+
+  const sourceSection = `
 ## ${footerLocale[lang].source}
 
 ${linksText}
 `
 
-    const contributorsSection = `
+  const contributorsSection = `
 ## ${footerLocale[lang].contributors}
 
 <Contributors id="${componentId}" />
 `
 
-    append.footers.push(sourceSection, isComponent ? contributorsSection : '')
+  append.footers.push(sourceSection, isComponent ? contributorsSection : '')
 
-    return code
+  return code
 }

+ 2 - 2
docs/.vitepress/plugins/table-wrapper.ts

@@ -1,6 +1,6 @@
 import type MarkdownIt from 'markdown-it'
 
 export default (md: MarkdownIt): void => {
-    md.renderer.rules.table_open = () => '<div class="vp-table"><table>'
-    md.renderer.rules.table_close = () => '</table></div>'
+  md.renderer.rules.table_open = () => '<div class="vp-table"><table>'
+  md.renderer.rules.table_close = () => '</table></div>'
 }

+ 29 - 0
docs/.vitepress/plugins/tooltip.ts

@@ -0,0 +1,29 @@
+import type MarkdownIt from 'markdown-it'
+
+export default (md: MarkdownIt): void => {
+  md.renderer.rules.tooltip = (tokens, idx) => {
+    const token = tokens[idx]
+
+    return `<api-typing type="${token.content}" details="${token.info}" />`
+  }
+
+  md.inline.ruler.before('emphasis', 'tooltip', (state, silent) => {
+    const tooltipRegExp = /^\^\[([^\]]*)\](`[^`]*`)?/
+    const str = state.src.slice(state.pos, state.posMax)
+
+    if (!tooltipRegExp.test(str)) return false
+    if (silent) return true
+
+    const result = str.match(tooltipRegExp)
+
+    if (!result) return false
+
+    const token = state.push('tooltip', 'tooltip', 0)
+    token.content = result[1].replace(/\\\|/g, '|')
+    token.info = (result[2] || '').replace(/^`(.*)`$/, '$1')
+    token.level = state.level
+    state.pos += result[0].length
+
+    return true
+  })
+}

+ 145 - 132
docs/.vitepress/sw.ts

@@ -2,15 +2,15 @@ import { cacheNames, clientsClaim } from 'workbox-core'
 import type { ManifestEntry } from 'workbox-build'
 
 declare let self: ServiceWorkerGlobalScope & {
-    __WB_MANIFEST: ManifestEntry[]
+  __WB_MANIFEST: ManifestEntry[]
 }
 const manifest = self.__WB_MANIFEST
 const cacheName = cacheNames.runtime
-const defaultLang = manifest.some(item => {
-    return item.url.includes(navigator.language)
+const defaultLang = manifest.some((item) => {
+  return item.url.includes(navigator?.language)
 })
-    ? navigator.language
-    : 'en-US'
+  ? navigator?.language
+  : 'zh-CN'
 
 let userPreferredLang = ''
 let cacheEntries: RequestInfo[] = []
@@ -18,159 +18,172 @@ let cacheManifestURLs: string[] = []
 let manifestURLs: string[] = []
 
 class LangDB {
-    private db: IDBDatabase | undefined
-    private databaseName = 'PWA_DB'
-    private version = 1
-    private storeNames = 'lang'
+  private db: IDBDatabase | undefined
+  private databaseName = 'PWA_DB'
+  private version = 1
+  private storeNames = 'lang'
 
-    constructor() {
-        this.initDB()
-    }
-
-    private initDB() {
-        return new Promise<boolean>(resolve => {
-            const request = indexedDB.open(this.databaseName, this.version)
-
-            request.onsuccess = event => {
-                this.db = (event.target as IDBOpenDBRequest).result
-                resolve(true)
-            }
+  constructor() {
+    this.initDB()
+  }
 
-            request.onupgradeneeded = event => {
-                this.db = (event.target as IDBOpenDBRequest).result
+  private initDB() {
+    return new Promise<boolean>((resolve) => {
+      const request = indexedDB.open(this.databaseName, this.version)
 
-                if (!this.db.objectStoreNames.contains(this.storeNames)) {
-                    this.db.createObjectStore(this.storeNames, { keyPath: 'id' })
-                }
-            }
-        })
-    }
+      request.onsuccess = (event) => {
+        this.db = (event.target as IDBOpenDBRequest).result
+        resolve(true)
+      }
 
-    private async initLang() {
-        this.db!.transaction(this.storeNames, 'readwrite').objectStore(this.storeNames).add({ id: 1, lang: defaultLang })
-    }
+      request.onupgradeneeded = (event) => {
+        this.db = (event.target as IDBOpenDBRequest).result
 
-    async getLang() {
-        if (!this.db) await this.initDB()
-
-        return new Promise<string>(resolve => {
-            const request = this.db!.transaction(this.storeNames).objectStore(this.storeNames).get(1)
-
-            request.onsuccess = () => {
-                if (request.result) {
-                    resolve(request.result.lang)
-                } else {
-                    this.initLang()
-                    resolve(defaultLang)
-                }
-            }
-
-            request.onerror = () => {
-                resolve(defaultLang)
-            }
-        })
-    }
-
-    async setLang(lang: string) {
-        if (userPreferredLang !== lang) {
-            userPreferredLang = lang
-            cacheEntries = []
-            cacheManifestURLs = []
-            manifestURLs = []
-
-            if (!this.db) await this.initDB()
-
-            this.db!.transaction(this.storeNames, 'readwrite').objectStore(this.storeNames).put({ id: 1, lang })
+        if (!this.db.objectStoreNames.contains(this.storeNames)) {
+          this.db.createObjectStore(this.storeNames, { keyPath: 'id' })
         }
+      }
+    })
+  }
+
+  private async initLang() {
+    this.db!.transaction(this.storeNames, 'readwrite')
+      .objectStore(this.storeNames)
+      .add({ id: 1, lang: defaultLang })
+  }
+
+  async getLang() {
+    if (!this.db) await this.initDB()
+
+    return new Promise<string>((resolve) => {
+      const request = this.db!.transaction(this.storeNames)
+        .objectStore(this.storeNames)
+        .get(1)
+
+      request.onsuccess = () => {
+        if (request.result) {
+          resolve(request.result.lang)
+        } else {
+          this.initLang()
+          resolve(defaultLang)
+        }
+      }
+
+      request.onerror = () => {
+        resolve(defaultLang)
+      }
+    })
+  }
+
+  async setLang(lang: string) {
+    if (userPreferredLang !== lang) {
+      userPreferredLang = lang
+      cacheEntries = []
+      cacheManifestURLs = []
+      manifestURLs = []
+
+      if (!this.db) await this.initDB()
+
+      this.db!.transaction(this.storeNames, 'readwrite')
+        .objectStore(this.storeNames)
+        .put({ id: 1, lang })
     }
+  }
 }
 
 async function initManifest() {
-    userPreferredLang = userPreferredLang || (await langDB.getLang())
-    // match the data that needs to be cached
-    // NOTE: When the structure of the document dist files changes, it needs to be changed here
-    const cacheList = [userPreferredLang, `assets/(${userPreferredLang}|app|index|style|chunks)`, 'images', 'android-chrome', 'apple-touch-icon', 'manifest.webmanifest']
-    const regExp = new RegExp(`^(${cacheList.join('|')})`)
-
-    for (const item of manifest) {
-        const url = new URL(item.url, self.location.origin)
-        manifestURLs.push(url.href)
-
-        if (regExp.test(item.url) || /^\/$/.test(item.url)) {
-            const request = new Request(url.href, { credentials: 'same-origin' })
-            cacheEntries.push(request)
-            cacheManifestURLs.push(url.href)
-        }
+  userPreferredLang = userPreferredLang || (await langDB.getLang())
+  // match the data that needs to be cached
+  // NOTE: When the structure of the document dist files changes, it needs to be changed here
+  const cacheList = [
+    userPreferredLang,
+    `assets/(${userPreferredLang}|app|index|style|chunks)`,
+    'images',
+    'android-chrome',
+    'apple-touch-icon',
+    'manifest.webmanifest',
+  ]
+  const regExp = new RegExp(`^(${cacheList.join('|')})`)
+
+  for (const item of manifest) {
+    const url = new URL(item.url, self.location.origin)
+    manifestURLs.push(url.href)
+
+    if (regExp.test(item.url) || /^\/$/.test(item.url)) {
+      const request = new Request(url.href, { credentials: 'same-origin' })
+      cacheEntries.push(request)
+      cacheManifestURLs.push(url.href)
     }
+  }
 }
 
 const langDB = new LangDB()
 
-self.addEventListener('install', event => {
-    event.waitUntil(
-        caches.open(cacheName).then(async cache => {
-            if (!cacheEntries.length) await initManifest()
+self.addEventListener('install', (event) => {
+  event.waitUntil(
+    caches.open(cacheName).then(async (cache) => {
+      if (!cacheEntries.length) await initManifest()
 
-            return cache.addAll(cacheEntries)
-        })
-    )
+      return cache.addAll(cacheEntries)
+    })
+  )
 })
 
 self.addEventListener('activate', (event: ExtendableEvent) => {
-    // clean up outdated runtime cache
-    event.waitUntil(
-        caches.open(cacheName).then(async cache => {
-            if (!cacheManifestURLs.length) await initManifest()
-
-            cache.keys().then(keys => {
-                keys.forEach(request => {
-                    // clean up those who are not listed in cacheManifestURLs
-                    !cacheManifestURLs.includes(request.url) && cache.delete(request)
-                })
-            })
+  // clean up outdated runtime cache
+  event.waitUntil(
+    caches.open(cacheName).then(async (cache) => {
+      if (!cacheManifestURLs.length) await initManifest()
+
+      cache.keys().then((keys) => {
+        keys.forEach((request) => {
+          // clean up those who are not listed in cacheManifestURLs
+          !cacheManifestURLs.includes(request.url) && cache.delete(request)
         })
-    )
+      })
+    })
+  )
 })
 
-self.addEventListener('fetch', event => {
-    event.respondWith(
-        caches.match(event.request).then(async response => {
-            // when the cache is hit, it returns directly to the cache
-            if (response) return response
-            if (!manifestURLs.length) await initManifest()
-            const requestClone = event.request.clone()
-
-            // otherwise create a new fetch request
-            return fetch(requestClone)
-                .then(response => {
-                    const responseClone = response.clone()
-
-                    if (response.type !== 'basic' && response.status !== 200) {
-                        return response
-                    }
-
-                    // cache the data contained in the manifestURLs list
-                    manifestURLs.includes(requestClone.url) &&
-                        caches.open(cacheName).then(cache => {
-                            cache.put(requestClone, responseClone)
-                        })
-                    return response
-                })
-                .catch(err => {
-                    throw new Error(`Failed to load resource ${requestClone.url}, ${err}`)
-                })
+self.addEventListener('fetch', (event) => {
+  event.respondWith(
+    caches.match(event.request).then(async (response) => {
+      // when the cache is hit, it returns directly to the cache
+      if (response) return response
+      if (!manifestURLs.length) await initManifest()
+      const requestClone = event.request.clone()
+
+      // otherwise create a new fetch request
+      return fetch(requestClone)
+        .then((response) => {
+          const responseClone = response.clone()
+
+          if (response.type !== 'basic' && response.status !== 200) {
+            return response
+          }
+
+          // cache the data contained in the manifestURLs list
+          manifestURLs.includes(requestClone.url) &&
+            caches.open(cacheName).then((cache) => {
+              cache.put(requestClone, responseClone)
+            })
+          return response
         })
-    )
+        .catch((err) => {
+          throw new Error(`Failed to load resource ${requestClone.url}, ${err}`)
+        })
+    })
+  )
 })
 
-self.addEventListener('message', event => {
-    if (event.data) {
-        if (event.data.type === 'SKIP_WAITING') {
-            self.skipWaiting()
-        } else if (event.data.type === 'LANG') {
-            langDB.setLang(event.data.lang)
-        }
+self.addEventListener('message', (event) => {
+  if (event.data) {
+    if (event.data.type === 'SKIP_WAITING') {
+      self.skipWaiting()
+    } else if (event.data.type === 'LANG') {
+      langDB.setLang(event.data.lang)
     }
+  }
 })
 
 clientsClaim()

+ 8 - 8
docs/.vitepress/theme/index.ts

@@ -7,13 +7,13 @@ import './style.css'
 import type { Theme } from 'vitepress'
 
 export default define<Theme>({
-    NotFound,
-    Layout: VPApp,
-    enhanceApp: ({ app }) => {
-        app.use(ElementPlus)
+  NotFound,
+  Layout: VPApp,
+  enhanceApp: ({ app }) => {
+    app.use(ElementPlus)
 
-        globals.forEach(([name, Comp]) => {
-            app.component(name, Comp)
-        })
-    },
+    globals.forEach(([name, Comp]) => {
+      app.component(name, Comp)
+    })
+  },
 })

+ 37 - 33
docs/.vitepress/utils/highlight.ts

@@ -12,41 +12,45 @@ const loadLanguages = require('prismjs/components/index')
 loadLanguages(['markup', 'css', 'javascript'])
 
 function wrap(code: string, lang: string): string {
-    if (lang === 'text') {
-        code = escapeHtml(code)
-    }
-    return `<pre v-pre><code>${code}</code></pre>`
+  if (lang === 'text') {
+    code = escapeHtml(code)
+  }
+  return `<pre v-pre><code>${code}</code></pre>`
 }
 
 export const highlight = (str: string, lang: string) => {
-    if (!lang) {
-        return wrap(str, 'text')
-    }
-    lang = lang.toLowerCase()
-    const rawLang = lang
-    if (lang === 'vue' || lang === 'html') {
-        lang = 'markup'
-    }
-    if (lang === 'md') {
-        lang = 'markdown'
-    }
-    if (lang === 'ts') {
-        lang = 'typescript'
-    }
-    if (lang === 'py') {
-        lang = 'python'
-    }
-    if (!prism.languages[lang]) {
-        try {
-            loadLanguages([lang])
-        } catch {
-            // eslint-disable-next-line no-console
-            consola.warn(chalk.yellow(`[vitepress] Syntax highlight for language "${lang}" is not supported.`))
-        }
-    }
-    if (prism.languages[lang]) {
-        const code = prism.highlight(str, prism.languages[lang], lang)
-        return wrap(code, rawLang)
-    }
+  if (!lang) {
     return wrap(str, 'text')
+  }
+  lang = lang.toLowerCase()
+  const rawLang = lang
+  if (lang === 'vue' || lang === 'html') {
+    lang = 'markup'
+  }
+  if (lang === 'md') {
+    lang = 'markdown'
+  }
+  if (lang === 'ts') {
+    lang = 'typescript'
+  }
+  if (lang === 'py') {
+    lang = 'python'
+  }
+  if (!prism.languages[lang]) {
+    try {
+      loadLanguages([lang])
+    } catch {
+      // eslint-disable-next-line no-console
+      consola.warn(
+        chalk.yellow(
+          `[vitepress] Syntax highlight for language "${lang}" is not supported.`
+        )
+      )
+    }
+  }
+  if (prism.languages[lang]) {
+    const code = prism.highlight(str, prism.languages[lang], lang)
+    return wrap(code, rawLang)
+  }
+  return wrap(str, 'text')
 }

+ 2 - 1
docs/.vitepress/utils/lang.ts

@@ -7,4 +7,5 @@ export const languages = ['zh-CN']
 
 export const ensureLang = (lang: string) => `/${lang}`
 
-export const getLang = (id: string) => path.relative(docRoot, id).split(path.sep)[0]
+export const getLang = (id: string) =>
+  path.relative(docRoot, id).split(path.sep)[0]

+ 18 - 11
docs/.vitepress/vitepress/components/common/vp-link.vue

@@ -2,29 +2,36 @@
 import { computed } from 'vue'
 
 const props = defineProps<{
-    href?: string
-    noIcon?: boolean
+  href?: string
+  noIcon?: boolean
 }>()
 
 const isExternal = computed(() => props.href && /^[a-z]+:/i.test(props.href))
 </script>
 
 <template>
-    <component :is="href ? 'a' : 'span'" class="link-item" :class="{ link: href }" :href="href" :target="isExternal ? '_blank' : undefined" :rel="isExternal ? 'noopener noreferrer' : undefined">
-        <slot />
-        <ElIcon v-if="isExternal && !noIcon">
-            <i-ri-external-link-line class="link-icon" />
-        </ElIcon>
-    </component>
+  <component
+    :is="href ? 'a' : 'span'"
+    class="link-item"
+    :class="{ link: href }"
+    :href="href"
+    :target="isExternal ? '_blank' : undefined"
+    :rel="isExternal ? 'noopener noreferrer' : undefined"
+  >
+    <slot />
+    <ElIcon v-if="isExternal && !noIcon">
+      <i-ri-external-link-line class="link-icon" />
+    </ElIcon>
+  </component>
 </template>
 
 <style scoped>
 .link-item {
-    display: flex;
-    align-items: center;
+  display: flex;
+  align-items: center;
 }
 
 .el-icon {
-    margin-left: 4px;
+  margin-left: 4px;
 }
 </style>

+ 14 - 8
docs/.vitepress/vitepress/components/common/vp-markdown.vue

@@ -5,26 +5,32 @@ import MarkdownIt from 'markdown-it'
 const md = new MarkdownIt()
 
 const props = defineProps({
-    content: { type: String, required: true },
+  content: { type: String, required: true },
 })
 
 const attr = 'rel="noreferrer noopenner" target="_blank"'
 
 const parsed = computed(() => {
-    // Note this is relatively arbitrary so that this could be buggy.
-    return md
-        .render(props.content)
-        .replace(/#([0-9]+) by/g, `<a href="https://github.com/element-plus/element-plus/pull/$1" ${attr}>#$1</a> by`)
-        .replace(/@([A-Za-z0-9_-]+)/g, `<a href="https://github.com/$1" ${attr}>@$1</a>`)
+  // Note this is relatively arbitrary so that this could be buggy.
+  return md
+    .render(props.content)
+    .replace(
+      /#([0-9]+) by/g,
+      `<a href="https://github.com/element-plus/element-plus/pull/$1" ${attr}>#$1</a> by`
+    )
+    .replace(
+      /@([A-Za-z0-9_-]+)/g,
+      `<a href="https://github.com/$1" ${attr}>@$1</a>`
+    )
 })
 </script>
 
 <template>
-    <div class="markdown-wrapper" v-html="parsed" />
+  <div class="markdown-wrapper" v-html="parsed" />
 </template>
 
 <style>
 .markdown-wrapper h3 {
-    margin-top: 1rem;
+  margin-top: 1rem;
 }
 </style>

+ 6 - 6
docs/.vitepress/vitepress/components/common/vp-switch.vue

@@ -5,11 +5,11 @@
 </script>
 
 <template>
-    <div class="switch" role="switch">
-        <div class="switch__action">
-            <div class="switch__icon">
-                <slot />
-            </div>
-        </div>
+  <div class="switch" role="switch">
+    <div class="switch__action">
+      <div class="switch__icon">
+        <slot />
+      </div>
     </div>
+  </div>
 </template>

+ 23 - 22
docs/.vitepress/vitepress/components/common/vp-theme-toggler.vue

@@ -5,45 +5,46 @@ import VPSwitch from './vp-switch.vue'
 </script>
 
 <template>
-    <VPSwitch>
-        <ElIcon :size="13">
-            <DarkIcon class="dark-icon" />
-            <LightIcon class="light-icon" />
-        </ElIcon>
-    </VPSwitch>
+  <VPSwitch>
+    <ElIcon :size="13">
+      <DarkIcon class="dark-icon" />
+      <LightIcon class="light-icon" />
+    </ElIcon>
+  </VPSwitch>
 </template>
 
 <style lang="scss" scoped>
 .el-icon {
-    cursor: pointer;
+  cursor: pointer;
 }
 
 .dark-icon,
 .light-icon {
-    transition: color var(--el-transition-duration), opacity var(--el-transition-duration);
+  transition: color var(--el-transition-duration),
+    opacity var(--el-transition-duration);
 }
 
 .light-icon {
-    opacity: 1;
-    position: absolute;
-    top: 0;
-    left: 0;
+  opacity: 1;
+  position: absolute;
+  top: 0;
+  left: 0;
 }
 
 .dark-icon {
-    opacity: 0;
-    position: absolute;
-    top: 0;
-    left: 0;
+  opacity: 0;
+  position: absolute;
+  top: 0;
+  left: 0;
 }
 
 @at-root .dark {
-    .dark-icon {
-        opacity: 1;
-    }
+  .dark-icon {
+    opacity: 1;
+  }
 
-    .light-icon {
-        opacity: 0;
-    }
+  .light-icon {
+    opacity: 0;
+  }
 }
 </style>

+ 33 - 0
docs/.vitepress/vitepress/components/demo/dept-home.ts

@@ -0,0 +1,33 @@
+export function loadSDKDep() {
+  return new Promise((resolve, reject) => {
+    const script = document.createElement('script')
+    script.src =
+      '//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk-deps.js?v=4.6.0-alpha.10'
+    script.addEventListener('load', resolve)
+    script.addEventListener('error', reject)
+    document.body.append(script)
+  })
+}
+
+export function loadSDK() {
+  return new Promise((resolve, reject) => {
+    const script = document.createElement('script')
+    script.src =
+      '//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk.js?v=4.6.0-alpha.10'
+    script.addEventListener('load', resolve)
+    script.addEventListener('error', reject)
+    document.body.append(script)
+  })
+}
+
+export function loadKanKanThemeChalkStyle() {
+  return new Promise((resolve, reject) => {
+    const link = document.createElement('link')
+    link.rel = 'stylesheet'
+    link.href =
+      'https://4dkk.4dage.com/npm_test/kankan-components/theme-chalk/index.css'
+    link.addEventListener('load', resolve)
+    link.addEventListener('error', reject)
+    document.body.append(link)
+  })
+}

+ 82 - 0
docs/.vitepress/vitepress/components/demo/dept.js

@@ -0,0 +1,82 @@
+// import { getCurrentInstance } from 'vue'
+let installed = false
+// await loadStyle()
+await loadUnoCss()
+await loadKanKanThemeChalkStyle()
+await loadSDKDep()
+await loadSDK()
+
+export function setupDept() {
+  if (installed) return
+  // const instance = getCurrentInstance()
+
+  // const __sdk = (window.__sdk = new window.KanKan({
+  //   num: 'KJ-t-wOXfx2SDFy',
+  //   // server: 'https://test.4dkankan.com',
+  //   server: '/demoServer',
+  // }))
+  // instance.appContext.app.provide('__sdk', __sdk)
+  // instance.appContext.app.use(ElementPlus)
+  installed = true
+}
+
+export function loadStyle() {
+  return new Promise((resolve, reject) => {
+    const link = document.createElement('link')
+    link.rel = 'stylesheet'
+    link.href = '#STYLE#'
+    link.addEventListener('load', resolve)
+    link.addEventListener('error', reject)
+    document.body.append(link)
+  })
+}
+export function loadSDKDep() {
+  return new Promise((resolve, reject) => {
+    const script = document.createElement('script')
+    script.src =
+      '//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk-deps.js?v=4.6.0-alpha.10'
+    script.addEventListener('load', resolve)
+    script.addEventListener('error', reject)
+    document.body.append(script)
+  })
+}
+
+export function loadSDK() {
+  return new Promise((resolve, reject) => {
+    const script = document.createElement('script')
+    script.src =
+      '//4dkk.4dage.com/v4-test/www/sdk/kankan-sdk.js?v=4.6.0-alpha.10'
+    script.addEventListener('load', resolve)
+    script.addEventListener('error', reject)
+    document.body.append(script)
+  })
+}
+
+export function loadKanKanThemeChalkStyle() {
+  return new Promise((resolve, reject) => {
+    const link = document.createElement('link')
+    link.rel = 'stylesheet'
+    link.href =
+      'https://4dkk.4dage.com/npm_test/kankan-components/theme-chalk/index.css'
+    link.addEventListener('load', resolve)
+    link.addEventListener('error', reject)
+    document.body.append(link)
+  })
+}
+
+export function loadUnoCss() {
+  return new Promise((resolve, reject) => {
+    const link = document.createElement('link')
+    link.rel = 'stylesheet'
+    link.href = 'https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css'
+    link.addEventListener('load', resolve)
+    link.addEventListener('error', reject)
+    document.body.append(link)
+
+    const script = document.createElement('script')
+    script.src = 'https://cdn.jsdelivr.net/npm/@unocss/runtime/mini.global.js'
+    script.addEventListener('load', resolve)
+    script.addEventListener('error', reject)
+    document.body.append(script)
+  })
+}

+ 10 - 0
docs/.vitepress/vitepress/components/demo/main.vue

@@ -0,0 +1,10 @@
+<script setup>
+import App from './App.vue'
+import { setupDept } from './dept.js'
+
+setupDept()
+</script>
+
+<template>
+  <App />
+</template>

+ 121 - 17
docs/.vitepress/vitepress/components/demo/vp-example.vue

@@ -1,28 +1,132 @@
 <script setup lang="ts">
-defineProps({
-    file: {
-        type: String,
-        required: true,
-    },
-    demo: {
-        type: Object,
-        required: true,
-    },
+import { computed, unref, watchEffect } from 'vue'
+import { File, Repl, ReplStore } from '@vue/repl'
+import mainCode from './main.vue?raw'
+import deptCode from './dept.js?raw'
+// import { loadSDK, loadSDKDep } from './dept-home'
+import type { SFCOptions } from '@vue/repl'
+
+const sfcOptions: SFCOptions = {
+  script: {
+    reactivityTransform: true,
+  },
+}
+
+const props = defineProps({
+  file: {
+    type: String,
+    required: true,
+  },
+  raw: {
+    type: String,
+    required: true,
+  },
+  demo: {
+    type: Object,
+    required: true,
+  },
+  isRepl: {
+    type: Boolean,
+    required: false,
+    default: () => false,
+  },
+})
+const isDev = computed(() => {
+  return import.meta.env.MODE === 'development'
+})
+
+const serverLink = computed(() => {
+  return unref(isDev) ? '/demoServer' : 'https://test.4dkankan.com/'
+})
+
+const store = new ReplStore({
+  // initialize repl with previously serialized state
+  // serializedState: unref(loadSingleData),
+
+  // starts on the output pane (mobile only) if the URL has a showOutput query
+  showOutput: true,
+  // starts on a different tab on the output pane if the URL has a outputMode query
+  // and default to the "preview" tab
+  outputMode: 'preview',
+
+  // specify the default URL to import Vue runtime from in the sandbox
+  // default is the CDN link from unpkg.com with version matching Vue's version
+  // from peerDependency
+  defaultVueRuntimeURL:
+    'https://cdn.jsdelivr.net/npm/@vue/runtime-dom@latest/dist/runtime-dom.esm-browser.js',
+})
+
+watchEffect(async () => {
+  if (!unref(props.isRepl)) {
+    // await loadKanKanThemeChalkStyle()
+  } else {
+    if (unref(props.raw)) {
+      store.setImportMap({
+        imports: {
+          vue: 'https://cdn.jsdelivr.net/npm/@vue/runtime-dom@latest/dist/runtime-dom.esm-browser.js',
+          '@vue/shared':
+            'https://cdn.jsdelivr.net/npm/@vue/shared@latest/dist/shared.esm-bundler.js',
+          'kankan-components':
+            'https://4dkk.4dage.com/npm_test/kankan-components/dist/index.full.min.mjs',
+        },
+      })
+      const mainFile = new File('PlaygroundMain.vue', mainCode)
+      const deptFile = new File('dept.js', deptCode)
+
+      const appFile = new File(
+        'App.vue',
+        decodeURIComponent(props.raw).replace('#DEMOSEVER#', unref(serverLink))
+      )
+
+      store.addFile(mainFile)
+      store.addFile(appFile)
+      store.addFile(deptFile)
+      store.state.mainFile = 'PlaygroundMain.vue'
+      store.state.activeFile = appFile
+      store.init()
+    }
+  }
 })
 </script>
 
 <template>
-    <div class="example-showcase">
-        <ClientOnly>
-            <component :is="demo" v-if="demo" v-bind="$attrs" />
-        </ClientOnly>
-    </div>
+  <div class="example-showcase" antialiased>
+    <ClientOnly>
+      <template v-if="demo">
+        <component :is="demo" v-if="!isRepl" v-bind="$attrs" />
+        <Repl
+          v-else
+          ref="repl"
+          :store="store"
+          v-bind="$attrs"
+          :sfc-options="sfcOptions"
+          :clear-console="false"
+          :show-compile-output="true"
+          auto-resize
+        />
+      </template>
+    </ClientOnly>
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .example-showcase {
-    padding: 1.5rem;
-    margin: 0.5px;
-    background-color: var(--bg-color);
+  padding: 1.5rem;
+  margin: 0.5px;
+  background-color: var(--bg-color);
+}
+</style>
+<style lang="scss">
+.vue-repl {
+  height: 650px;
+  .left {
+    display: none;
+  }
+  .right {
+    width: 100% !important;
+  }
+  // .tab-buttons {
+  //     display: none;
+  // }
 }
 </style>

+ 10 - 10
docs/.vitepress/vitepress/components/demo/vp-source-code.vue

@@ -2,26 +2,26 @@
 import { computed } from 'vue'
 
 const props = defineProps({
-    source: {
-        type: String,
-        required: true,
-    },
+  source: {
+    type: String,
+    required: true,
+  },
 })
 
 const decoded = computed(() => {
-    return decodeURIComponent(props.source)
+  return decodeURIComponent(props.source)
 })
 </script>
 
 <template>
-    <div class="example-source-wrapper">
-        <div class="example-source language-vue" v-html="decoded" />
-    </div>
+  <div class="example-source-wrapper">
+    <div class="example-source language-vue" v-html="decoded" />
+  </div>
 </template>
 
 <style scoped lang="scss">
 .language-vue {
-    margin: 0;
-    border-radius: 0;
+  margin: 0;
+  border-radius: 0;
 }
 </style>

+ 3 - 1
docs/.vitepress/vitepress/components/dev/DeprecatedTag.vue

@@ -1,3 +1,5 @@
 <template>
-    <el-tag size="small" type="warning" effect="plain" hit round>deprecated</el-tag>
+  <el-tag size="small" type="warning" effect="plain" hit round
+    >deprecated</el-tag
+  >
 </template>

+ 4 - 4
docs/.vitepress/vitepress/components/dev/VersionTag.vue

@@ -1,11 +1,11 @@
 <script lang="ts" setup>
 defineProps<{
-    version: string
+  version: string
 }>()
 </script>
 
 <template>
-    <el-tag size="small" effect="plain" hit round>
-        {{ version }}
-    </el-tag>
+  <el-tag size="small" effect="plain" hit round>
+    {{ version }}
+  </el-tag>
 </template>

+ 18 - 12
docs/.vitepress/vitepress/components/doc-content/vp-edit-link.vue

@@ -5,24 +5,30 @@ const { url, text } = useEditLink()
 </script>
 
 <template>
-    <div class="edit-link">
-        <a v-if="url" class="link text-sm" :href="url" target="_blank" rel="noopener noreferrer">
-            {{ text }}
-            <ElIcon :size="16" style="vertical-align: text-top; line-height: 24px">
-                <i-ri-external-link-line />
-            </ElIcon>
-        </a>
-    </div>
+  <div class="edit-link">
+    <a
+      v-if="url"
+      class="link text-sm"
+      :href="url"
+      target="_blank"
+      rel="noopener noreferrer"
+    >
+      {{ text }}
+      <ElIcon :size="16" style="vertical-align: text-top; line-height: 24px">
+        <i-ri-external-link-line />
+      </ElIcon>
+    </a>
+  </div>
 </template>
 
 <style scoped>
 .link {
-    display: inline-block;
-    font-weight: 500;
+  display: inline-block;
+  font-weight: 500;
 }
 
 .link:hover {
-    text-decoration: none;
-    color: var(--brand-color);
+  text-decoration: none;
+  color: var(--brand-color);
 }
 </style>

+ 20 - 20
docs/.vitepress/vitepress/components/doc-content/vp-last-updated-at.vue

@@ -8,40 +8,40 @@ const { page } = useData()
 const lang = useLang()
 
 const prefix = computed(() => {
-    return localeData[lang.value].title
+  return localeData[lang.value].title
 })
 
 const datetime = ref('')
 onMounted(() => {
-    datetime.value = new Date(page.value.lastUpdated).toLocaleString(lang.value)
+  datetime.value = new Date(page.value.lastUpdated).toLocaleString(lang.value)
 })
 </script>
 
 <template>
-    <p class="last-updated text-sm">
-        <span class="prefix">{{ prefix }}:</span>
-        <span class="datetime">{{ datetime }}</span>
-    </p>
+  <p class="last-updated text-sm">
+    <span class="prefix">{{ prefix }}:</span>
+    <span class="datetime">{{ datetime }}</span>
+  </p>
 </template>
 
 <style scoped lang="scss">
 @use '../../styles/mixins' as *;
 
 .last-updated {
+  display: inline-block;
+  margin: 0;
+  line-height: 1.4;
+  color: var(--text-color-light);
+
+  .prefix {
+    display: inline-block;
+    font-weight: 500;
+  }
+
+  .datetime {
     display: inline-block;
-    margin: 0;
-    line-height: 1.4;
-    color: var(--text-color-light);
-
-    .prefix {
-        display: inline-block;
-        font-weight: 500;
-    }
-
-    .datetime {
-        display: inline-block;
-        margin-left: 6px;
-        font-weight: 400;
-    }
+    margin-left: 6px;
+    font-weight: 400;
+  }
 }
 </style>

+ 20 - 20
docs/.vitepress/vitepress/components/doc-content/vp-page-footer.vue

@@ -1,35 +1,35 @@
 <script setup lang="ts">
-import VPEditLink from './vp-edit-link.vue'
+// import VPEditLink from './vp-edit-link.vue'
 </script>
 
 <template>
-    <footer class="page-footer">
-        <div class="edit">
-            <VPEditLink />
-        </div>
-    </footer>
+  <footer class="page-footer">
+    <div class="edit">
+      <!-- <VPEditLink /> -->
+    </div>
+  </footer>
 </template>
 
 <style scoped lang="scss">
 @use '../../styles/mixins' as *;
 .page-footer {
-    padding-top: 1rem;
-    padding-bottom: 1rem;
-    overflow: auto;
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+  overflow: auto;
 
-    .updated {
-        padding-top: 4px;
-    }
+  .updated {
+    padding-top: 4px;
+  }
 }
 
 @include respond-to('lg') {
-    .page-footer {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-    }
-    .updated {
-        padding-top: 0;
-    }
+  .page-footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+  .updated {
+    padding-top: 0;
+  }
 }
 </style>

+ 49 - 49
docs/.vitepress/vitepress/components/doc-content/vp-page-nav.vue

@@ -7,87 +7,87 @@ const { hasLinks, prev, next } = usePageNav()
 </script>
 
 <template>
-    <div v-if="hasLinks" class="next-and-prev-link">
-        <div class="container">
-            <div class="prev">
-                <a v-if="prev" class="link" :href="withBase(prev.link)">
-                    <ElIcon class="mr-1">
-                        <ArrowLeft />
-                    </ElIcon>
-                    <span class="text">{{ prev.text }}</span>
-                </a>
-            </div>
-            <div class="next">
-                <a v-if="next" class="link" :href="withBase(next.link)">
-                    <span class="text">{{ next.text }}</span>
-                    <ElIcon class="ml-1">
-                        <ArrowRight />
-                    </ElIcon>
-                </a>
-            </div>
-        </div>
+  <div v-if="hasLinks" class="next-and-prev-link">
+    <div class="container">
+      <div class="prev">
+        <a v-if="prev" class="link" :href="withBase(prev.link)">
+          <ElIcon class="mr-1">
+            <ArrowLeft />
+          </ElIcon>
+          <span class="text">{{ prev.text }}</span>
+        </a>
+      </div>
+      <div class="next">
+        <a v-if="next" class="link" :href="withBase(next.link)">
+          <span class="text">{{ next.text }}</span>
+          <ElIcon class="ml-1">
+            <ArrowRight />
+          </ElIcon>
+        </a>
+      </div>
     </div>
+  </div>
 </template>
 
 <style scoped>
 .next-and-prev-link {
-    padding-top: 1rem;
+  padding-top: 1rem;
 }
 
 .container {
-    display: flex;
-    justify-content: space-between;
-    border-top: 1px solid var(--border-color);
-    padding-top: 1rem;
+  display: flex;
+  justify-content: space-between;
+  border-top: 1px solid var(--border-color);
+  padding-top: 1rem;
 }
 
 .prev,
 .next {
-    display: flex;
-    flex-shrink: 0;
-    width: 50%;
+  display: flex;
+  flex-shrink: 0;
+  width: 50%;
 }
 
 .prev {
-    justify-content: flex-start;
-    padding-right: 12px;
+  justify-content: flex-start;
+  padding-right: 12px;
 }
 
 .next {
-    justify-content: flex-end;
-    padding-left: 12px;
+  justify-content: flex-end;
+  padding-left: 12px;
 }
 
 .link {
-    display: inline-flex;
-    justify-content: center;
-    align-items: center;
+  display: inline-flex;
+  justify-content: center;
+  align-items: center;
 
-    max-width: 100%;
-    height: 24px;
-    font-size: 14px;
-    font-weight: 500;
+  max-width: 100%;
+  height: 24px;
+  font-size: 14px;
+  font-weight: 500;
 }
 
 .text {
-    display: inline-flex;
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
+  display: inline-flex;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
 }
 
 .el-icon {
-    display: inline-flex;
-    flex-shrink: 0;
-    font-size: 12px;
-    color: var(--text-color);
-    transform: translateY(1px);
+  display: inline-flex;
+  flex-shrink: 0;
+  font-size: 12px;
+  color: var(--text-color);
+  transform: translateY(1px);
 }
 
 .icon-prev {
-    margin-right: 8px;
+  margin-right: 8px;
 }
 .icon-next {
-    margin-left: 8px;
+  margin-left: 8px;
 }
 </style>

+ 40 - 30
docs/.vitepress/vitepress/components/doc-content/vp-table-of-content.vue

@@ -1,55 +1,65 @@
 <script setup lang="ts">
-import { computed, ref } from 'vue'
+import { ref } from 'vue'
 import { useToc } from '../../composables/use-toc'
 import { useActiveSidebarLinks } from '../../composables/active-bar'
 
-import sponsorLocale from '../../../i18n/component/sponsor.json'
-import { useLang } from '../../composables/lang'
-import SponsorsButton from '../sponsors/sponsors-button.vue'
-import SponsorRightTextList from '../sponsors/right-richtext-list.vue'
-import SponsorRightLogoSmallList from '../sponsors/right-logo-small-list.vue'
+// import sponsorLocale from '../../../i18n/component/sponsor.json'
+// import { useLang } from '../../composables/lang'
+// import SponsorsButton from '../sponsors/sponsors-button.vue'
+// import SponsorRightTextList from '../sponsors/right-richtext-list.vue'
+// import SponsorRightLogoSmallList from '../sponsors/right-logo-small-list.vue'
 // import SponsorLarge from '../vp-sponsor-large.vue'
 
 const headers = useToc()
 const marker = ref()
 const container = ref()
 useActiveSidebarLinks(container, marker)
-const lang = useLang()
-const sponsor = computed(() => sponsorLocale[lang.value])
+// const lang = useLang()
+// const sponsor = computed(() => sponsorLocale[lang.value])
 </script>
 
 <template>
-    <aside ref="container" class="toc-wrapper">
-        <nav class="toc-content">
-            <h3 class="toc-content__heading">Contents</h3>
-            <ul class="toc-items">
-                <li v-for="{ link, text, children } in headers" :key="link" class="toc-item">
-                    <a class="toc-link" :href="link" :title="text">{{ text }}</a>
-                    <ul v-if="children">
-                        <li v-for="{ link: childLink, text: childText } in children" :key="childLink" class="toc-item">
-                            <a class="toc-link subitem" :href="childLink" :title="text">{{ childText }}</a>
-                        </li>
-                    </ul>
-                </li>
-            </ul>
-            <div ref="marker" class="toc-marker" />
-            <!-- <SponsorLarge
+  <aside ref="container" class="toc-wrapper">
+    <nav class="toc-content">
+      <h3 class="toc-content__heading">Contents</h3>
+      <ul class="toc-items">
+        <li
+          v-for="{ link, text, children } in headers"
+          :key="link"
+          class="toc-item"
+        >
+          <a class="toc-link" :href="link" :title="text">{{ text }}</a>
+          <ul v-if="children">
+            <li
+              v-for="{ link: childLink, text: childText } in children"
+              :key="childLink"
+              class="toc-item"
+            >
+              <a class="toc-link subitem" :href="childLink" :title="text">{{
+                childText
+              }}</a>
+            </li>
+          </ul>
+        </li>
+      </ul>
+      <div ref="marker" class="toc-marker" />
+      <!-- <SponsorLarge
         class="mt-8 toc-ads flex flex-col"
         item-style="width: 180px; height: 55px;"
       /> -->
-            <!-- <p class="text-14px font-300 color-$text-color-secondary">
+      <!-- <p class="text-14px font-300 color-$text-color-secondary">
                 {{ sponsor.sponsoredBy }}
             </p> -->
-            <!-- <sponsors-button class="sponsors-button mt-4 w-100%" />
+      <!-- <sponsors-button class="sponsors-button mt-4 w-100%" />
             <sponsor-right-logo-small-list />
             <sponsor-right-text-list /> -->
-        </nav>
-    </aside>
+    </nav>
+  </aside>
 </template>
 <style scoped lang="scss">
 .sponsors-button:deep {
-    button {
-        width: 100%;
-    }
+  button {
+    width: 100%;
+  }
 }
 </style>

+ 22 - 22
docs/.vitepress/vitepress/components/full-screen/vp-menu-link.vue

@@ -4,37 +4,37 @@ import VPLink from '../common/vp-link.vue'
 import type { Link } from '../../types'
 
 defineProps<{
-    item: Link
+  item: Link
 }>()
 </script>
 
 <template>
-    <VPLink
-        :class="{
-            'is-menu-link': true,
-        }"
-        :href="item.link"
-        :no-icon="true"
-    >
-        {{ item.text }}
-    </VPLink>
+  <VPLink
+    :class="{
+      'is-menu-link': true,
+    }"
+    :href="item.link"
+    :no-icon="true"
+  >
+    {{ item.text }}
+  </VPLink>
 </template>
 
 <style scoped lang="scss">
 .is-menu-link {
-    display: block;
-    font-size: 13px;
-    font-weight: 500;
-    line-height: 24px;
-    color: var(--text-color);
-    transition: color var(--el-transition-duration);
+  display: block;
+  font-size: 13px;
+  font-weight: 500;
+  line-height: 24px;
+  color: var(--text-color);
+  transition: color var(--el-transition-duration);
 
-    &.active {
-        border-bottom: 2px solid var(--brand-color);
-    }
+  &.active {
+    border-bottom: 2px solid var(--brand-color);
+  }
 
-    &:hover {
-        color: var(--brand-color);
-    }
+  &:hover {
+    color: var(--brand-color);
+  }
 }
 </style>

+ 7 - 7
docs/.vitepress/vitepress/components/full-screen/vp-menu.vue

@@ -8,16 +8,16 @@ defineEmits(['close'])
 </script>
 
 <template>
-    <nav v-if="navs" class="full-screen-menu">
-        <div v-for="(item, key) in navs" :key="key" class="full-screen-menu__item">
-            <VPMenuLink :item="item" @click="$emit('close')" />
-        </div>
-    </nav>
+  <nav v-if="navs" class="full-screen-menu">
+    <div v-for="(item, key) in navs" :key="key" class="full-screen-menu__item">
+      <VPMenuLink :item="item" @click="$emit('close')" />
+    </div>
+  </nav>
 </template>
 
 <style lang="scss" scoped>
 .full-screen-menu__item {
-    padding: 12px 0;
-    border-bottom: 1px solid var(--border-color);
+  padding: 12px 0;
+  border-bottom: 1px solid var(--border-color);
 }
 </style>

+ 12 - 12
docs/.vitepress/vitepress/components/full-screen/vp-theme-toggler.vue

@@ -4,21 +4,21 @@ import { toggleDark } from '../../composables/dark'
 </script>
 
 <template>
-    <div class="full-screen-theme-toggler">
-        <span>Theme</span>
-        <CommonThemeToggler @click="toggleDark()" />
-    </div>
+  <div class="full-screen-theme-toggler">
+    <span>Theme</span>
+    <CommonThemeToggler @click="toggleDark()" />
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .full-screen-theme-toggler {
-    display: flex;
-    padding: 12px 14px;
-    align-items: center;
-    justify-content: space-between;
-    margin-top: 16px;
-    font-size: 13px;
-    background-color: var(--bg-color-soft);
-    border-radius: 8px;
+  display: flex;
+  padding: 12px 14px;
+  align-items: center;
+  justify-content: space-between;
+  margin-top: 16px;
+  font-size: 13px;
+  background-color: var(--bg-color-soft);
+  border-radius: 8px;
 }
 </style>

+ 56 - 46
docs/.vitepress/vitepress/components/full-screen/vp-translation.vue

@@ -11,70 +11,80 @@ const { languageMap, langs, lang, switchLang, helpTranslate } = useTranslation()
 const [show, toggle] = useToggle()
 
 const onSwitchLang = (lang: string) => {
-    switchLang(lang)
-    emit('close')
+  switchLang(lang)
+  emit('close')
 }
 </script>
 
 <template>
-    <div class="full-screen-translation">
-        <ElButton style="width: 100%; color: var(--text-color)" text @click="toggle">
-            <div class="translation-toggler">
-                <span> Translations </span>
-                <ElIcon :size="14">
-                    <ExpandIcon class="toggle-icon" :class="{ expanded: show }" />
-                </ElIcon>
-            </div>
-        </ElButton>
-        <div v-show="show" class="translation-items">
-            <p v-for="l in langs" :key="l" :class="{ active: l === lang }" class="translation-item" @click="onSwitchLang(l)">
-                {{ languageMap[l] }}
-            </p>
-            <p class="translation-item">
-                <VPLink :href="`/${lang}/guide/translation`">
-                    {{ helpTranslate }}
-                </VPLink>
-            </p>
-        </div>
+  <div class="full-screen-translation">
+    <ElButton
+      style="width: 100%; color: var(--text-color)"
+      text
+      @click="toggle"
+    >
+      <div class="translation-toggler">
+        <span> Translations </span>
+        <ElIcon :size="14">
+          <ExpandIcon class="toggle-icon" :class="{ expanded: show }" />
+        </ElIcon>
+      </div>
+    </ElButton>
+    <div v-show="show" class="translation-items">
+      <p
+        v-for="l in langs"
+        :key="l"
+        :class="{ active: l === lang }"
+        class="translation-item"
+        @click="onSwitchLang(l)"
+      >
+        {{ languageMap[l] }}
+      </p>
+      <p class="translation-item">
+        <VPLink :href="`/${lang}/guide/translation`">
+          {{ helpTranslate }}
+        </VPLink>
+      </p>
     </div>
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .full-screen-translation {
-    border-bottom: 1px solid var(--border-color);
+  border-bottom: 1px solid var(--border-color);
 }
 .translation-toggler {
-    width: 100%;
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    line-height: 24px;
-    .toggle-icon {
-        transition: transform var(--el-transition-duration);
-        transform: rotate(180deg);
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  line-height: 24px;
+  .toggle-icon {
+    transition: transform var(--el-transition-duration);
+    transform: rotate(180deg);
 
-        &.expanded {
-            transform: rotate(0deg);
-        }
+    &.expanded {
+      transform: rotate(0deg);
     }
+  }
 }
 
 .translation-items {
-    padding-bottom: 12px;
-    .translation-item {
-        cursor: pointer;
-        margin: 0;
-        font-size: 14px;
-        line-height: 32px;
+  padding-bottom: 12px;
+  .translation-item {
+    cursor: pointer;
+    margin: 0;
+    font-size: 14px;
+    line-height: 32px;
 
-        &.active {
-            font-weight: 500;
-            color: var(--brand-color);
-        }
+    &.active {
+      font-weight: 500;
+      color: var(--brand-color);
+    }
 
-        .link-item {
-            font-weight: 500;
-        }
+    .link-item {
+      font-weight: 500;
     }
+  }
 }
 </style>

+ 20 - 14
docs/.vitepress/vitepress/components/globals/contributors.vue

@@ -5,28 +5,34 @@ import VpLink from '../common/vp-link.vue'
 
 const props = defineProps<{ id: string }>()
 
-const contributors = computed(() => _contributors[props.id]?.filter(c => c.login !== 'renovate[bot]'))
+const contributors = computed(() =>
+  _contributors[props.id]?.filter((c) => c.login !== 'renovate[bot]')
+)
 </script>
 
 <template>
-    <div class="mb-4">
-        <div class="flex flex-wrap gap-4 pt-2">
-            <div v-for="c of contributors" :key="c.hash">
-                <vp-link :href="`https://github.com/${c.login}`" class="flex gap-2 items-center link" no-icon>
-                    <img :src="c.avatar" class="w-8 h-8 rounded-full" />
-                    {{ c.name }}
-                </vp-link>
-            </div>
-        </div>
+  <div class="mb-4">
+    <div class="flex flex-wrap gap-4 pt-2">
+      <div v-for="c of contributors" :key="c.hash">
+        <vp-link
+          :href="`https://github.com/${c.login}`"
+          class="flex gap-2 items-center link"
+          no-icon
+        >
+          <img :src="c.avatar" class="w-8 h-8 rounded-full" />
+          {{ c.name }}
+        </vp-link>
+      </div>
     </div>
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .link {
-    color: var(--text-color-light);
+  color: var(--text-color-light);
 
-    &:hover {
-        color: var(--brand-color);
-    }
+  &:hover {
+    color: var(--brand-color);
+  }
 }
 </style>

+ 42 - 42
docs/.vitepress/vitepress/components/globals/design-guide.vue

@@ -1,58 +1,58 @@
 <template>
-    <div class="guide-design">
-        <div class="el-row cards" style="margin-left: -7px; margin-right: -7px">
-            <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
-                <div class="card">
-                    <consistency-svg m="4" w="20" alt="Consistency" />
-                    <p>Consistency</p>
-                </div>
-            </div>
-            <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
-                <div class="card">
-                    <feedback-svg m="4" w="20" alt="Feedback" />
-                    <p>Feedback</p>
-                </div>
-            </div>
-            <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
-                <div class="card">
-                    <efficiency-svg m="4" w="20" alt="Efficiency" />
-                    <p>Efficiency</p>
-                </div>
-            </div>
-            <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
-                <div class="card">
-                    <controllability-svg m="4" w="20" alt="Controllability" />
-                    <p>Controllability</p>
-                </div>
-            </div>
+  <div class="guide-design">
+    <div class="el-row cards" style="margin-left: -7px; margin-right: -7px">
+      <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
+        <div class="card">
+          <consistency-svg m="4" w="20" alt="Consistency" />
+          <p>Consistency</p>
         </div>
+      </div>
+      <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
+        <div class="card">
+          <feedback-svg m="4" w="20" alt="Feedback" />
+          <p>Feedback</p>
+        </div>
+      </div>
+      <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
+        <div class="card">
+          <efficiency-svg m="4" w="20" alt="Efficiency" />
+          <p>Efficiency</p>
+        </div>
+      </div>
+      <div class="el-col el-col-24 el-col-xs-12 el-col-sm-6 is-guttered">
+        <div class="card">
+          <controllability-svg m="4" w="20" alt="Controllability" />
+          <p>Controllability</p>
+        </div>
+      </div>
     </div>
+  </div>
 </template>
 
 <style scoped lang="scss">
 .el-col {
-    padding: 0 7px;
+  padding: 0 7px;
 }
 .card {
-    background: var(--el-fill-color-lighter);
-    height: 204px;
-    text-align: center;
+  background: var(--el-fill-color-lighter);
+  height: 204px;
+  text-align: center;
 
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    flex-direction: column;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
 
-    img {
-        margin: 1rem;
-        width: 5rem;
-        height: 5rem;
-    }
+  img {
+    margin: 1rem;
+    width: 5rem;
+    height: 5rem;
+  }
 }
 
 @media screen and (max-width: 767px) {
-    .el-col {
-        padding-bottom: 8px;
-    }
+  .el-col {
+    padding-bottom: 8px;
+  }
 }
 </style>

+ 57 - 30
docs/.vitepress/vitepress/components/globals/design/consistency-svg.vue

@@ -1,46 +1,73 @@
 <template>
-    <!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 79 79"
-        style="enable-background: new 0 0 79 79"
-        xml:space="preserve"
-    >
-        <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
-        <path class="st1" d="M23.2,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1h3.5c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H23.2z" />
-        <path class="st1" d="M32.6,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1H36c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H32.6z" />
-        <path class="st1" d="M42,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v17.8c0,0.5-0.4,1-1,1H43c-0.5,0-1-0.4-1-1V43z" />
-        <path class="st1" d="M52.3,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1h3.5c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H52.3z" />
-        <path class="st2" d="M22.2,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z" />
-        <path class="st2" d="M31.6,43c0-0.5,0.4-1,1-1H36c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z" />
-        <path class="st2" d="M42,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1H43c-0.5,0-1-0.4-1-1V43z" />
-        <path class="st2" d="M51.3,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z" />
-        <path class="st3" d="M57.3,28.1l-5.9-5.9v4.9H22.7c-0.5,0-1,0.4-1,1c0,0.5,0.4,1,1,1h28.6v4.9L57.3,28.1z" />
-    </svg>
+  <!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 79 79"
+    style="enable-background: new 0 0 79 79"
+    xml:space="preserve"
+  >
+    <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
+    <path
+      class="st1"
+      d="M23.2,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1h3.5c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H23.2z"
+    />
+    <path
+      class="st1"
+      d="M32.6,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1H36c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H32.6z"
+    />
+    <path
+      class="st1"
+      d="M42,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v17.8c0,0.5-0.4,1-1,1H43c-0.5,0-1-0.4-1-1V43z"
+    />
+    <path
+      class="st1"
+      d="M52.3,42c-0.5,0-1,0.4-1,1v17.8c0,0.5,0.4,1,1,1h3.5c0.5,0,1-0.4,1-1V43c0-0.5-0.4-1-1-1H52.3z"
+    />
+    <path
+      class="st2"
+      d="M22.2,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z"
+    />
+    <path
+      class="st2"
+      d="M31.6,43c0-0.5,0.4-1,1-1H36c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z"
+    />
+    <path
+      class="st2"
+      d="M42,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1H43c-0.5,0-1-0.4-1-1V43z"
+    />
+    <path
+      class="st2"
+      d="M51.3,43c0-0.5,0.4-1,1-1h3.5c0.5,0,1,0.4,1,1v15.8c0,0.5-0.4,1-1,1h-3.5c-0.5,0-1-0.4-1-1V43z"
+    />
+    <path
+      class="st3"
+      d="M57.3,28.1l-5.9-5.9v4.9H22.7c-0.5,0-1,0.4-1,1c0,0.5,0.4,1,1,1h28.6v4.9L57.3,28.1z"
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #eff5fd;
+  fill: #eff5fd;
 }
 .st1 {
-    fill: #0077ce;
+  fill: #0077ce;
 }
 .st2 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 .st3 {
-    fill: #7383bf;
+  fill: #7383bf;
 }
 
 .dark {
-    .st0 {
-        fill: #36393d;
-    }
+  .st0 {
+    fill: #36393d;
+  }
 }
 </style>

+ 55 - 51
docs/.vitepress/vitepress/components/globals/design/controllability-svg.vue

@@ -1,76 +1,80 @@
 <template>
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 79 79"
-        style="enable-background: new 0 0 79 79"
-        xml:space="preserve"
-    >
-        <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
-        <g>
-            <defs>
-                <rect id="SVGID_1_" x="15.8" y="17.3" width="47.4" height="43.9" />
-            </defs>
-            <clipPath id="SVGID_00000103965616648291865560000002216192073450902938_">
-                <use xlink:href="#SVGID_1_" style="overflow: visible" />
-            </clipPath>
-            <g style="clip-path: url(#SVGID_00000103965616648291865560000002216192073450902938_)">
-                <path
-                    class="st2"
-                    d="M57.3,23.2L57.3,23.2c0.5,0,1,0.4,1,1v36c0,0.5-0.4,1-1,1l0,0c-0.5,0-1-0.4-1-1v-36
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 79 79"
+    style="enable-background: new 0 0 79 79"
+    xml:space="preserve"
+  >
+    <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
+    <g>
+      <defs>
+        <rect id="SVGID_1_" x="15.8" y="17.3" width="47.4" height="43.9" />
+      </defs>
+      <clipPath id="SVGID_00000103965616648291865560000002216192073450902938_">
+        <use xlink:href="#SVGID_1_" style="overflow: visible" />
+      </clipPath>
+      <g
+        style="
+          clip-path: url(#SVGID_00000103965616648291865560000002216192073450902938_);
+        "
+      >
+        <path
+          class="st2"
+          d="M57.3,23.2L57.3,23.2c0.5,0,1,0.4,1,1v36c0,0.5-0.4,1-1,1l0,0c-0.5,0-1-0.4-1-1v-36
         C56.3,23.6,56.7,23.2,57.3,23.2z"
-                />
-                <ellipse class="st3" cx="57.3" cy="24.7" rx="5.9" ry="5.9" />
-                <ellipse class="st4" cx="57.3" cy="23.2" rx="5.9" ry="5.9" />
-                <path
-                    class="st2"
-                    d="M21.7,17.3L21.7,17.3c0.5,0,1,0.4,1,1v36c0,0.5-0.4,1-1,1h0c-0.5,0-1-0.4-1-1v-36
+        />
+        <ellipse class="st3" cx="57.3" cy="24.7" rx="5.9" ry="5.9" />
+        <ellipse class="st4" cx="57.3" cy="23.2" rx="5.9" ry="5.9" />
+        <path
+          class="st2"
+          d="M21.7,17.3L21.7,17.3c0.5,0,1,0.4,1,1v36c0,0.5-0.4,1-1,1h0c-0.5,0-1-0.4-1-1v-36
         C20.7,17.7,21.2,17.3,21.7,17.3z"
-                />
-                <ellipse class="st3" cx="21.7" cy="55.3" rx="5.9" ry="5.9" />
-                <ellipse class="st4" cx="21.7" cy="53.8" rx="5.9" ry="5.9" />
-                <path
-                    class="st2"
-                    d="M39.5,17.3L39.5,17.3c0.5,0,1,0.4,1,1v42c0,0.5-0.4,1-1,1l0,0c-0.5,0-1-0.4-1-1v-42
+        />
+        <ellipse class="st3" cx="21.7" cy="55.3" rx="5.9" ry="5.9" />
+        <ellipse class="st4" cx="21.7" cy="53.8" rx="5.9" ry="5.9" />
+        <path
+          class="st2"
+          d="M39.5,17.3L39.5,17.3c0.5,0,1,0.4,1,1v42c0,0.5-0.4,1-1,1l0,0c-0.5,0-1-0.4-1-1v-42
         C38.5,17.7,39,17.3,39.5,17.3z"
-                />
-                <ellipse class="st5" cx="39.5" cy="39" rx="5.9" ry="5.9" />
-                <ellipse class="st6" cx="39.5" cy="37.5" rx="5.9" ry="5.9" />
-            </g>
-        </g>
-    </svg>
+        />
+        <ellipse class="st5" cx="39.5" cy="39" rx="5.9" ry="5.9" />
+        <ellipse class="st6" cx="39.5" cy="37.5" rx="5.9" ry="5.9" />
+      </g>
+    </g>
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #eff5fd;
+  fill: #eff5fd;
 }
 .st1 {
-    clip-path: url(#SVGID_00000172405038201111576250000009038874290854515645_);
+  clip-path: url(#SVGID_00000172405038201111576250000009038874290854515645_);
 }
 .st2 {
-    fill: #afcaf1;
+  fill: #afcaf1;
 }
 .st3 {
-    fill: #afb6bb;
+  fill: #afb6bb;
 }
 .st4 {
-    fill: #e7eced;
+  fill: #e7eced;
 }
 .st5 {
-    fill: #0077ce;
+  fill: #0077ce;
 }
 .st6 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 
 .dark {
-    .st0 {
-        fill: #36393d;
-    }
+  .st0 {
+    fill: #36393d;
+  }
 }
 </style>

+ 46 - 33
docs/.vitepress/vitepress/components/globals/design/efficiency-svg.vue

@@ -1,61 +1,74 @@
 <template>
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 79 79"
-        style="enable-background: new 0 0 79 79"
-        xml:space="preserve"
-    >
-        <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
-        <path
-            class="st1"
-            d="M37,16.8c-1.6,0-3,1.3-3,3V22c-3,0.9-5.7,2.5-7.9,4.5l-2-1.1c-1.4-0.8-3.2-0.3-4,1.1l-2.5,4.3
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 79 79"
+    style="enable-background: new 0 0 79 79"
+    xml:space="preserve"
+  >
+    <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
+    <path
+      class="st1"
+      d="M37,16.8c-1.6,0-3,1.3-3,3V22c-3,0.9-5.7,2.5-7.9,4.5l-2-1.1c-1.4-0.8-3.2-0.3-4,1.1l-2.5,4.3
       c-0.8,1.4-0.3,3.2,1.1,4l2,1.1c-0.4,1.5-0.5,3-0.5,4.5c0,1.6,0.2,3.1,0.5,4.5l-2,1.1c-1.4,0.8-1.9,2.6-1.1,4l2.5,4.3
       c0.8,1.4,2.6,1.9,4,1.1l2-1.1c2.2,2.1,4.9,3.7,7.9,4.5v2.3c0,1.6,1.3,3,3,3h4.9c1.6,0,3-1.3,3-3V59c3-0.9,5.7-2.5,7.9-4.5l2,1.1
       c1.4,0.8,3.2,0.3,4-1.1l2.5-4.3c0.8-1.4,0.3-3.2-1.1-4l-2-1.1c0.4-1.5,0.5-3,0.5-4.5c0-1.6-0.2-3.1-0.5-4.5l2-1.1
       c1.4-0.8,1.9-2.6,1.1-4l-2.5-4.3c-0.8-1.4-2.6-1.9-4-1.1l-2,1.1c-2.2-2.1-4.9-3.7-7.9-4.5v-2.3c0-1.6-1.3-3-3-3H37z"
-        />
-        <path
-            class="st2"
-            d="M37,14.8c-1.6,0-3,1.3-3,3V20c-3,0.9-5.7,2.5-7.9,4.5l-2-1.1c-1.4-0.8-3.2-0.3-4,1.1l-2.5,4.3
+    />
+    <path
+      class="st2"
+      d="M37,14.8c-1.6,0-3,1.3-3,3V20c-3,0.9-5.7,2.5-7.9,4.5l-2-1.1c-1.4-0.8-3.2-0.3-4,1.1l-2.5,4.3
       c-0.8,1.4-0.3,3.2,1.1,4l2,1.1c-0.4,1.5-0.5,3-0.5,4.5s0.2,3.1,0.5,4.5l-2,1.1c-1.4,0.8-1.9,2.6-1.1,4l2.5,4.3
       c0.8,1.4,2.6,1.9,4,1.1l2-1.1c2.2,2.1,4.9,3.7,7.9,4.5v2.3c0,1.6,1.3,3,3,3h4.9c1.6,0,3-1.3,3-3V57c3-0.9,5.7-2.5,7.9-4.5l2,1.1
       c1.4,0.8,3.2,0.3,4-1.1l2.5-4.3c0.8-1.4,0.3-3.2-1.1-4l-2-1.1c0.4-1.5,0.5-3,0.5-4.5s-0.2-3.1-0.5-4.5l2-1.1c1.4-0.8,1.9-2.6,1.1-4
       l-2.5-4.3c-0.8-1.4-2.6-1.9-4-1.1l-2,1.1c-2.2-2.1-4.9-3.7-7.9-4.5v-2.3c0-1.6-1.3-3-3-3H37z"
-        />
-        <ellipse transform="matrix(1 -2.392332e-03 2.392332e-03 1 -9.202202e-02 9.445851e-02)" class="st3" cx="39.4" cy="38.5" rx="15.3" ry="15.3" />
-        <path class="st4" d="M38.5,30.6c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1v10.9h-2V30.6z" />
-        <path class="st5" d="M47.3,39.5c0.5,0,1,0.4,1,1c0,0.5-0.4,1-1,1h-8.9v-2H47.3z" />
-    </svg>
+    />
+    <ellipse
+      transform="matrix(1 -2.392332e-03 2.392332e-03 1 -9.202202e-02 9.445851e-02)"
+      class="st3"
+      cx="39.4"
+      cy="38.5"
+      rx="15.3"
+      ry="15.3"
+    />
+    <path
+      class="st4"
+      d="M38.5,30.6c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1v10.9h-2V30.6z"
+    />
+    <path
+      class="st5"
+      d="M47.3,39.5c0.5,0,1,0.4,1,1c0,0.5-0.4,1-1,1h-8.9v-2H47.3z"
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #eff5fd;
+  fill: #eff5fd;
 }
 .st1 {
-    fill: #afb6bb;
+  fill: #afb6bb;
 }
 .st2 {
-    fill: #e7eced;
+  fill: #e7eced;
 }
 .st3 {
-    fill: #ffffff;
+  fill: #ffffff;
 }
 .st4 {
-    fill: #0077ce;
+  fill: #0077ce;
 }
 .st5 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 
 .dark {
-    .st0 {
-        fill: #36393d;
-    }
+  .st0 {
+    fill: #36393d;
+  }
 }
 </style>

+ 36 - 24
docs/.vitepress/vitepress/components/globals/design/feedback-svg.vue

@@ -1,40 +1,52 @@
 <template>
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 79 79"
-        style="enable-background: new 0 0 79 79"
-        xml:space="preserve"
-    >
-        <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
-        <path class="st1" d="M19.8,26.2c0-3.3,2.7-5.9,5.9-5.9h27.7c3.3,0,5.9,2.7,5.9,5.9v23.7c0,3.3-2.7,5.9-5.9,5.9H25.9l-6.2,6.4V26.2z" />
-        <path class="st2" d="M19.8,24.2c0-3.3,2.7-5.9,5.9-5.9h27.7c3.3,0,5.9,2.7,5.9,5.9v23.7c0,3.3-2.7,5.9-5.9,5.9H25.9l-6.2,6.4V24.2z" />
-        <path class="st3" d="M37.5,35.5c0-1.1,0.9-2,2-2s2,0.9,2,2v7.9c0,1.1-0.9,2-2,2s-2-0.9-2-2V35.5z" />
-        <path class="st3" d="M37.5,29.1c0-1.1,0.9-2,2-2s2,0.9,2,2c0,1.1-0.9,2-2,2S37.5,30.2,37.5,29.1z" />
-    </svg>
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 79 79"
+    style="enable-background: new 0 0 79 79"
+    xml:space="preserve"
+  >
+    <circle class="st0" cx="39.5" cy="39.5" r="39.5" />
+    <path
+      class="st1"
+      d="M19.8,26.2c0-3.3,2.7-5.9,5.9-5.9h27.7c3.3,0,5.9,2.7,5.9,5.9v23.7c0,3.3-2.7,5.9-5.9,5.9H25.9l-6.2,6.4V26.2z"
+    />
+    <path
+      class="st2"
+      d="M19.8,24.2c0-3.3,2.7-5.9,5.9-5.9h27.7c3.3,0,5.9,2.7,5.9,5.9v23.7c0,3.3-2.7,5.9-5.9,5.9H25.9l-6.2,6.4V24.2z"
+    />
+    <path
+      class="st3"
+      d="M37.5,35.5c0-1.1,0.9-2,2-2s2,0.9,2,2v7.9c0,1.1-0.9,2-2,2s-2-0.9-2-2V35.5z"
+    />
+    <path
+      class="st3"
+      d="M37.5,29.1c0-1.1,0.9-2,2-2s2,0.9,2,2c0,1.1-0.9,2-2,2S37.5,30.2,37.5,29.1z"
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #eff5fd;
+  fill: #eff5fd;
 }
 .st1 {
-    fill: #0077ce;
+  fill: #0077ce;
 }
 .st2 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 .st3 {
-    fill: #ffffff;
+  fill: #ffffff;
 }
 
 .dark {
-    .st0 {
-        fill: #36393d;
-    }
+  .st0 {
+    fill: #36393d;
+  }
 }
 </style>

+ 330 - 302
docs/.vitepress/vitepress/components/globals/icons-categories.json

@@ -1,304 +1,332 @@
 {
-    "categories": [
-        {
-            "name": "System",
-            "items": [
-                "Plus",
-                "Minus",
-                "CirclePlus",
-                "Search",
-                "Female",
-                "Male",
-                "Aim",
-                "House",
-                "FullScreen",
-                "Loading",
-                "Link",
-                "Service",
-                "Pointer",
-                "Star",
-                "Notification",
-                "Connection",
-                "ChatDotRound",
-                "Setting",
-                "Clock",
-                "Position",
-                "Discount",
-                "Odometer",
-                "ChatSquare",
-                "ChatRound",
-                "ChatLineRound",
-                "ChatLineSquare",
-                "ChatDotSquare",
-                "View",
-                "Hide",
-                "Unlock",
-                "Lock",
-                "RefreshRight",
-                "RefreshLeft",
-                "Refresh",
-                "Bell",
-                "MuteNotification",
-                "User",
-                "Check",
-                "CircleCheck",
-                "Warning",
-                "CircleClose",
-                "Close",
-                "PieChart",
-                "More",
-                "Compass",
-                "Filter",
-                "Switch",
-                "Select",
-                "SemiSelect",
-                "CloseBold",
-                "EditPen",
-                "Edit",
-                "Message",
-                "MessageBox",
-                "TurnOff",
-                "Finished",
-                "Delete",
-                "Crop",
-                "SwitchButton",
-                "Operation",
-                "Open",
-                "Remove",
-                "ZoomOut",
-                "ZoomIn",
-                "InfoFilled",
-                "CircleCheckFilled",
-                "SuccessFilled",
-                "WarningFilled",
-                "CircleCloseFilled",
-                "QuestionFilled",
-                "WarnTriangleFilled",
-                "UserFilled",
-                "MoreFilled",
-                "Tools",
-                "HomeFilled",
-                "Menu",
-                "UploadFilled",
-                "Avatar",
-                "HelpFilled",
-                "Share",
-                "StarFilled",
-                "Comment",
-                "Histogram",
-                "Grid",
-                "Promotion",
-                "DeleteFilled",
-                "RemoveFilled",
-                "CirclePlusFilled"
-            ]
-        },
-        {
-            "name": "Arrow",
-            "items": [
-                "ArrowLeft",
-                "ArrowUp",
-                "ArrowRight",
-                "ArrowDown",
-                "ArrowLeftBold",
-                "ArrowUpBold",
-                "ArrowRightBold",
-                "ArrowDownBold",
-                "DArrowRight",
-                "DArrowLeft",
-                "Download",
-                "Upload",
-                "Top",
-                "Bottom",
-                "Back",
-                "Right",
-                "TopRight",
-                "TopLeft",
-                "BottomRight",
-                "BottomLeft",
-                "Sort",
-                "SortUp",
-                "SortDown",
-                "Rank",
-                "CaretLeft",
-                "CaretTop",
-                "CaretRight",
-                "CaretBottom",
-                "DCaret",
-                "Expand",
-                "Fold"
-            ]
-        },
-        {
-            "name": "Document",
-            "items": [
-                "DocumentAdd",
-                "Document",
-                "Notebook",
-                "Tickets",
-                "Memo",
-                "Collection",
-                "Postcard",
-                "ScaleToOriginal",
-                "SetUp",
-                "DocumentDelete",
-                "DocumentChecked",
-                "DataBoard",
-                "DataAnalysis",
-                "CopyDocument",
-                "FolderChecked",
-                "Files",
-                "Folder",
-                "FolderDelete",
-                "FolderRemove",
-                "FolderOpened",
-                "DocumentCopy",
-                "DocumentRemove",
-                "FolderAdd",
-                "FirstAidKit",
-                "Reading",
-                "DataLine",
-                "Management",
-                "Checked",
-                "Ticket",
-                "Failed",
-                "TrendCharts",
-                "List"
-            ]
-        },
-        {
-            "name": "Media",
-            "items": [
-                "Microphone",
-                "Mute",
-                "Mic",
-                "VideoPause",
-                "VideoCamera",
-                "VideoPlay",
-                "Headset",
-                "Monitor",
-                "Film",
-                "Camera",
-                "Picture",
-                "PictureRounded",
-                "Iphone",
-                "Cellphone",
-                "VideoCameraFilled",
-                "PictureFilled",
-                "Platform",
-                "CameraFilled",
-                "BellFilled"
-            ]
-        },
-        {
-            "name": "Traffic",
-            "items": ["Location", "LocationInformation", "DeleteLocation", "Coordinate", "Bicycle", "OfficeBuilding", "School", "Guide", "AddLocation", "MapLocation", "Place", "LocationFilled", "Van"]
-        },
-        {
-            "name": "Food",
-            "items": [
-                "Watermelon",
-                "Pear",
-                "NoSmoking",
-                "Smoking",
-                "Mug",
-                "GobletSquareFull",
-                "GobletFull",
-                "KnifeFork",
-                "Sugar",
-                "Bowl",
-                "MilkTea",
-                "Lollipop",
-                "Coffee",
-                "Chicken",
-                "Dish",
-                "IceTea",
-                "ColdDrink",
-                "CoffeeCup",
-                "DishDot",
-                "IceDrink",
-                "IceCream",
-                "Dessert",
-                "IceCreamSquare",
-                "ForkSpoon",
-                "IceCreamRound",
-                "Food",
-                "HotWater",
-                "Grape",
-                "Fries",
-                "Apple",
-                "Burger",
-                "Goblet",
-                "GobletSquare",
-                "Orange",
-                "Cherry"
-            ]
-        },
-        {
-            "name": "Items",
-            "items": [
-                "Printer",
-                "Calendar",
-                "CreditCard",
-                "Box",
-                "Money",
-                "Refrigerator",
-                "Cpu",
-                "Football",
-                "Brush",
-                "Suitcase",
-                "SuitcaseLine",
-                "Umbrella",
-                "AlarmClock",
-                "Medal",
-                "GoldMedal",
-                "Present",
-                "Mouse",
-                "Watch",
-                "QuartzWatch",
-                "Magnet",
-                "Help",
-                "Soccer",
-                "ToiletPaper",
-                "ReadingLamp",
-                "Paperclip",
-                "MagicStick",
-                "Basketball",
-                "Baseball",
-                "Coin",
-                "Goods",
-                "Sell",
-                "SoldOut",
-                "Key",
-                "ShoppingCart",
-                "ShoppingCartFull",
-                "ShoppingTrolley",
-                "Phone",
-                "Scissor",
-                "Handbag",
-                "ShoppingBag",
-                "Trophy",
-                "TrophyBase",
-                "Stopwatch",
-                "Timer",
-                "CollectionTag",
-                "Discount",
-                "TakeawayBox",
-                "PriceTag",
-                "Wallet",
-                "Opportunity",
-                "PhoneFilled",
-                "WalletFilled",
-                "GoodsFilled",
-                "Flag",
-                "BrushFilled",
-                "Briefcase",
-                "Stamp"
-            ]
-        },
-        {
-            "name": "Weather",
-            "items": ["Sunrise", "Sunny", "Ship", "MostlyCloudy", "PartlyCloudy", "Sunset", "Sunrise", "Drizzling", "Pouring", "Cloudy", "Moon", "MoonNight", "Lightning"]
-        }
-    ]
+  "categories": [
+    {
+      "name": "System",
+      "items": [
+        "Plus",
+        "Minus",
+        "CirclePlus",
+        "Search",
+        "Female",
+        "Male",
+        "Aim",
+        "House",
+        "FullScreen",
+        "Loading",
+        "Link",
+        "Service",
+        "Pointer",
+        "Star",
+        "Notification",
+        "Connection",
+        "ChatDotRound",
+        "Setting",
+        "Clock",
+        "Position",
+        "Discount",
+        "Odometer",
+        "ChatSquare",
+        "ChatRound",
+        "ChatLineRound",
+        "ChatLineSquare",
+        "ChatDotSquare",
+        "View",
+        "Hide",
+        "Unlock",
+        "Lock",
+        "RefreshRight",
+        "RefreshLeft",
+        "Refresh",
+        "Bell",
+        "MuteNotification",
+        "User",
+        "Check",
+        "CircleCheck",
+        "Warning",
+        "CircleClose",
+        "Close",
+        "PieChart",
+        "More",
+        "Compass",
+        "Filter",
+        "Switch",
+        "Select",
+        "SemiSelect",
+        "CloseBold",
+        "EditPen",
+        "Edit",
+        "Message",
+        "MessageBox",
+        "TurnOff",
+        "Finished",
+        "Delete",
+        "Crop",
+        "SwitchButton",
+        "Operation",
+        "Open",
+        "Remove",
+        "ZoomOut",
+        "ZoomIn",
+        "InfoFilled",
+        "CircleCheckFilled",
+        "SuccessFilled",
+        "WarningFilled",
+        "CircleCloseFilled",
+        "QuestionFilled",
+        "WarnTriangleFilled",
+        "UserFilled",
+        "MoreFilled",
+        "Tools",
+        "HomeFilled",
+        "Menu",
+        "UploadFilled",
+        "Avatar",
+        "HelpFilled",
+        "Share",
+        "StarFilled",
+        "Comment",
+        "Histogram",
+        "Grid",
+        "Promotion",
+        "DeleteFilled",
+        "RemoveFilled",
+        "CirclePlusFilled"
+      ]
+    },
+    {
+      "name": "Arrow",
+      "items": [
+        "ArrowLeft",
+        "ArrowUp",
+        "ArrowRight",
+        "ArrowDown",
+        "ArrowLeftBold",
+        "ArrowUpBold",
+        "ArrowRightBold",
+        "ArrowDownBold",
+        "DArrowRight",
+        "DArrowLeft",
+        "Download",
+        "Upload",
+        "Top",
+        "Bottom",
+        "Back",
+        "Right",
+        "TopRight",
+        "TopLeft",
+        "BottomRight",
+        "BottomLeft",
+        "Sort",
+        "SortUp",
+        "SortDown",
+        "Rank",
+        "CaretLeft",
+        "CaretTop",
+        "CaretRight",
+        "CaretBottom",
+        "DCaret",
+        "Expand",
+        "Fold"
+      ]
+    },
+    {
+      "name": "Document",
+      "items": [
+        "DocumentAdd",
+        "Document",
+        "Notebook",
+        "Tickets",
+        "Memo",
+        "Collection",
+        "Postcard",
+        "ScaleToOriginal",
+        "SetUp",
+        "DocumentDelete",
+        "DocumentChecked",
+        "DataBoard",
+        "DataAnalysis",
+        "CopyDocument",
+        "FolderChecked",
+        "Files",
+        "Folder",
+        "FolderDelete",
+        "FolderRemove",
+        "FolderOpened",
+        "DocumentCopy",
+        "DocumentRemove",
+        "FolderAdd",
+        "FirstAidKit",
+        "Reading",
+        "DataLine",
+        "Management",
+        "Checked",
+        "Ticket",
+        "Failed",
+        "TrendCharts",
+        "List"
+      ]
+    },
+    {
+      "name": "Media",
+      "items": [
+        "Microphone",
+        "Mute",
+        "Mic",
+        "VideoPause",
+        "VideoCamera",
+        "VideoPlay",
+        "Headset",
+        "Monitor",
+        "Film",
+        "Camera",
+        "Picture",
+        "PictureRounded",
+        "Iphone",
+        "Cellphone",
+        "VideoCameraFilled",
+        "PictureFilled",
+        "Platform",
+        "CameraFilled",
+        "BellFilled"
+      ]
+    },
+    {
+      "name": "Traffic",
+      "items": [
+        "Location",
+        "LocationInformation",
+        "DeleteLocation",
+        "Coordinate",
+        "Bicycle",
+        "OfficeBuilding",
+        "School",
+        "Guide",
+        "AddLocation",
+        "MapLocation",
+        "Place",
+        "LocationFilled",
+        "Van"
+      ]
+    },
+    {
+      "name": "Food",
+      "items": [
+        "Watermelon",
+        "Pear",
+        "NoSmoking",
+        "Smoking",
+        "Mug",
+        "GobletSquareFull",
+        "GobletFull",
+        "KnifeFork",
+        "Sugar",
+        "Bowl",
+        "MilkTea",
+        "Lollipop",
+        "Coffee",
+        "Chicken",
+        "Dish",
+        "IceTea",
+        "ColdDrink",
+        "CoffeeCup",
+        "DishDot",
+        "IceDrink",
+        "IceCream",
+        "Dessert",
+        "IceCreamSquare",
+        "ForkSpoon",
+        "IceCreamRound",
+        "Food",
+        "HotWater",
+        "Grape",
+        "Fries",
+        "Apple",
+        "Burger",
+        "Goblet",
+        "GobletSquare",
+        "Orange",
+        "Cherry"
+      ]
+    },
+    {
+      "name": "Items",
+      "items": [
+        "Printer",
+        "Calendar",
+        "CreditCard",
+        "Box",
+        "Money",
+        "Refrigerator",
+        "Cpu",
+        "Football",
+        "Brush",
+        "Suitcase",
+        "SuitcaseLine",
+        "Umbrella",
+        "AlarmClock",
+        "Medal",
+        "GoldMedal",
+        "Present",
+        "Mouse",
+        "Watch",
+        "QuartzWatch",
+        "Magnet",
+        "Help",
+        "Soccer",
+        "ToiletPaper",
+        "ReadingLamp",
+        "Paperclip",
+        "MagicStick",
+        "Basketball",
+        "Baseball",
+        "Coin",
+        "Goods",
+        "Sell",
+        "SoldOut",
+        "Key",
+        "ShoppingCart",
+        "ShoppingCartFull",
+        "ShoppingTrolley",
+        "Phone",
+        "Scissor",
+        "Handbag",
+        "ShoppingBag",
+        "Trophy",
+        "TrophyBase",
+        "Stopwatch",
+        "Timer",
+        "CollectionTag",
+        "Discount",
+        "TakeawayBox",
+        "PriceTag",
+        "Wallet",
+        "Opportunity",
+        "PhoneFilled",
+        "WalletFilled",
+        "GoodsFilled",
+        "Flag",
+        "BrushFilled",
+        "Briefcase",
+        "Stamp"
+      ]
+    },
+    {
+      "name": "Weather",
+      "items": [
+        "Sunrise",
+        "Sunny",
+        "Ship",
+        "MostlyCloudy",
+        "PartlyCloudy",
+        "Sunset",
+        "Sunrise",
+        "Drizzling",
+        "Pouring",
+        "Cloudy",
+        "Moon",
+        "MoonNight",
+        "Lightning"
+      ]
+    }
+  ]
 }

+ 106 - 96
docs/.vitepress/vitepress/components/globals/icons.vue

@@ -9,133 +9,143 @@ import IconCategories from './icons-categories.json'
 import type { DefineComponent } from 'vue'
 
 type CategoriesItem = {
-    name: string
-    icons: DefineComponent[]
+  name: string
+  icons: DefineComponent[]
 }
 
 const lang = useLang()
 const locale = computed(() => localeData[lang.value])
 const copyIcon = ref(true)
 
-const copyContent = async content => {
-    try {
-        await clipboardCopy(content)
+const copyContent = async (content) => {
+  try {
+    await clipboardCopy(content)
 
-        ElMessage({
-            showClose: true,
-            message: locale.value['copy-success'],
-            type: 'success',
-        })
-    } catch {
-        ElMessage({
-            showClose: true,
-            message: locale.value['copy-error'],
-            type: 'error',
-        })
-    }
+    ElMessage({
+      showClose: true,
+      message: locale.value['copy-success'],
+      type: 'success',
+    })
+  } catch {
+    ElMessage({
+      showClose: true,
+      message: locale.value['copy-error'],
+      type: 'error',
+    })
+  }
 }
 
 const copySvgIcon = async (name, refs) => {
-    if (copyIcon.value) {
-        await copyContent(`<el-icon><${name} /></el-icon>`)
-    } else {
-        const content = refs[name]?.[0].querySelector('svg')?.outerHTML ?? ''
-        await copyContent(content)
-    }
+  if (copyIcon.value) {
+    await copyContent(`<el-icon><${name} /></el-icon>`)
+  } else {
+    const content = refs[name]?.[0].querySelector('svg')?.outerHTML ?? ''
+    await copyContent(content)
+  }
 }
 
 const categories = ref<CategoriesItem[]>([])
 const iconMap = new Map(Object.entries(Icons))
 
-IconCategories.categories.forEach(o => {
-    const result: CategoriesItem = {
-        name: o.name,
-        icons: [],
+IconCategories.categories.forEach((o) => {
+  const result: CategoriesItem = {
+    name: o.name,
+    icons: [],
+  }
+  o.items.forEach((i) => {
+    const icon = iconMap.get(i)
+    if (icon) {
+      result.icons.push(icon)
+      iconMap.delete(i)
     }
-    o.items.forEach(i => {
-        const icon = iconMap.get(i)
-        if (icon) {
-            result.icons.push(icon)
-            iconMap.delete(i)
-        }
-    })
-    categories.value.push(result)
+  })
+  categories.value.push(result)
 })
 
 categories.value.push({ name: 'Other', icons: Array.from(iconMap.values()) })
 </script>
 
 <template>
-    <div style="text-align: right">
-        <el-switch v-model="copyIcon" active-text="Copy icon code" inactive-text="Copy SVG content" />
-    </div>
-    <div v-for="item in categories" :key="item.name" class="demo-icon-item">
-        <div class="demo-icon-title">{{ item.name }}</div>
-        <ul class="demo-icon-list">
-            <li v-for="component in item.icons" :key="component.name" :ref="component.name" class="icon-item" @click="copySvgIcon(component.name, $refs)">
-                <span class="demo-svg-icon">
-                    <ElIcon :size="20">
-                        <component :is="component" />
-                    </ElIcon>
-                    <span class="icon-name">{{ component.name }}</span>
-                </span>
-            </li>
-        </ul>
-    </div>
+  <div style="text-align: right">
+    <el-switch
+      v-model="copyIcon"
+      active-text="Copy icon code"
+      inactive-text="Copy SVG content"
+    />
+  </div>
+  <div v-for="item in categories" :key="item.name" class="demo-icon-item">
+    <div class="demo-icon-title">{{ item.name }}</div>
+    <ul class="demo-icon-list">
+      <li
+        v-for="component in item.icons"
+        :key="component.name"
+        :ref="component.name"
+        class="icon-item"
+        @click="copySvgIcon(component.name, $refs)"
+      >
+        <span class="demo-svg-icon">
+          <ElIcon :size="20">
+            <component :is="component" />
+          </ElIcon>
+          <span class="icon-name">{{ component.name }}</span>
+        </span>
+      </li>
+    </ul>
+  </div>
 </template>
 
 <style scoped lang="scss">
 .demo-icon {
-    &-item {
-        margin-top: 24px;
-        &:first-child {
-            margin-top: 0;
-        }
+  &-item {
+    margin-top: 24px;
+    &:first-child {
+      margin-top: 0;
     }
-    &-title {
-        font-weight: 400;
-        font-size: 18px;
-        line-height: 26px;
-    }
-    &-list {
-        overflow: hidden;
-        list-style: none;
-        padding: 0 !important;
-        border-top: 1px solid var(--el-border-color);
-        border-left: 1px solid var(--el-border-color);
-        border-radius: 4px;
-        display: grid;
-        grid-template-columns: repeat(7, 1fr);
+  }
+  &-title {
+    font-weight: 400;
+    font-size: 18px;
+    line-height: 26px;
+  }
+  &-list {
+    overflow: hidden;
+    list-style: none;
+    padding: 0 !important;
+    border-top: 1px solid var(--el-border-color);
+    border-left: 1px solid var(--el-border-color);
+    border-radius: 4px;
+    display: grid;
+    grid-template-columns: repeat(7, 1fr);
 
-        .icon-item {
-            text-align: center;
-            color: var(--el-text-color-regular);
-            height: 90px;
-            font-size: 13px;
-            border-right: 1px solid var(--el-border-color);
-            border-bottom: 1px solid var(--el-border-color);
-            transition: background-color var(--el-transition-duration);
-            &:hover {
-                background-color: var(--el-border-color-extra-light);
-                .el-icon {
-                    color: var(--brand-color-light);
-                }
-                color: var(--brand-color-light);
-            }
+    .icon-item {
+      text-align: center;
+      color: var(--el-text-color-regular);
+      height: 90px;
+      font-size: 13px;
+      border-right: 1px solid var(--el-border-color);
+      border-bottom: 1px solid var(--el-border-color);
+      transition: background-color var(--el-transition-duration);
+      &:hover {
+        background-color: var(--el-border-color-extra-light);
+        .el-icon {
+          color: var(--brand-color-light);
+        }
+        color: var(--brand-color-light);
+      }
 
-            .demo-svg-icon {
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                justify-content: center;
-                height: 100%;
-                cursor: pointer;
+      .demo-svg-icon {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        height: 100%;
+        cursor: pointer;
 
-                .icon-name {
-                    margin-top: 8px;
-                }
-            }
+        .icon-name {
+          margin-top: 8px;
         }
+      }
     }
+  }
 }
 </style>

+ 21 - 21
docs/.vitepress/vitepress/components/globals/main-color.vue

@@ -3,31 +3,31 @@ import { useCssVar } from '@vueuse/core'
 import { useCopyColor } from '../../utils'
 
 const primary = useCssVar('--el-color-primary')
-const colorLevel = [3, 5, 7, 8, 9].map(i => `light-${i}`)
+const colorLevel = [3, 5, 7, 8, 9].map((i) => `light-${i}`)
 colorLevel.unshift('dark-2')
 
 const { copyColor } = useCopyColor()
 </script>
 
 <template>
-    <el-row :gutter="12">
-        <el-col :span="10" :xs="{ span: 12 }">
-            <div class="demo-color-box" :style="{ background: primary }">
-                Brand Color
-                <div class="value" text="xs">{{ primary.toUpperCase() }}</div>
-                <div class="bg-color-sub" :style="{ background: primary }">
-                    <div
-                        v-for="level in colorLevel"
-                        :key="level"
-                        class="bg-blue-sub-item cursor-pointer hover:shadow"
-                        :style="{
-                            width: `${100 / 6}%`,
-                            background: 'var(--el-color-primary-' + level + ')',
-                        }"
-                        @click="copyColor('primary-' + level)"
-                    />
-                </div>
-            </div>
-        </el-col>
-    </el-row>
+  <el-row :gutter="12">
+    <el-col :span="10" :xs="{ span: 12 }">
+      <div class="demo-color-box" :style="{ background: primary }">
+        Brand Color
+        <div class="value" text="xs">{{ primary.toUpperCase() }}</div>
+        <div class="bg-color-sub" :style="{ background: primary }">
+          <div
+            v-for="level in colorLevel"
+            :key="level"
+            class="bg-blue-sub-item cursor-pointer hover:shadow"
+            :style="{
+              width: `${100 / 6}%`,
+              background: 'var(--el-color-primary-' + level + ')',
+            }"
+            @click="copyColor('primary-' + level)"
+          />
+        </div>
+      </div>
+    </el-col>
+  </el-row>
 </template>

+ 136 - 106
docs/.vitepress/vitepress/components/globals/neutral-color.vue

@@ -1,93 +1,111 @@
 <template>
-    <el-row :gutter="12">
-        <el-col :span="6" :xs="{ span: 12 }">
-            <div class="demo-color-box-group">
-                <div
-                    v-for="(text, i) in textColors"
-                    :key="i"
-                    class="demo-color-box demo-color-box-other"
-                    :style="{
-                        color: 'var(--el-bg-color)',
-                        background: text.var.value,
-                    }"
-                >
-                    {{ text.name }}
-                    <div class="value" text="xs">
-                        {{ text.var.value.toUpperCase() }}
-                    </div>
-                </div>
-            </div>
-        </el-col>
+  <el-row :gutter="12">
+    <el-col :span="6" :xs="{ span: 12 }">
+      <div class="demo-color-box-group">
+        <div
+          v-for="(text, i) in textColors"
+          :key="i"
+          class="demo-color-box demo-color-box-other"
+          :style="{
+            color: 'var(--el-bg-color)',
+            background: text.var.value,
+          }"
+        >
+          {{ text.name }}
+          <div class="value" text="xs">
+            {{ text.var.value.toUpperCase() }}
+          </div>
+        </div>
+      </div>
+    </el-col>
 
-        <el-col :span="6" :xs="{ span: 12 }">
-            <div class="demo-color-box-group">
-                <div v-for="(border, i) in borderColors" :key="i" class="demo-color-box demo-color-box-other demo-color-box-lite" :style="{ background: border.var.value }">
-                    {{ border.name }}
-                    <div class="value" text="xs">
-                        {{ border.var.value.toUpperCase() }}
-                    </div>
-                </div>
-            </div>
-        </el-col>
+    <el-col :span="6" :xs="{ span: 12 }">
+      <div class="demo-color-box-group">
+        <div
+          v-for="(border, i) in borderColors"
+          :key="i"
+          class="demo-color-box demo-color-box-other demo-color-box-lite"
+          :style="{ background: border.var.value }"
+        >
+          {{ border.name }}
+          <div class="value" text="xs">
+            {{ border.var.value.toUpperCase() }}
+          </div>
+        </div>
+      </div>
+    </el-col>
 
-        <el-col :span="6" :xs="{ span: 12 }">
-            <div class="demo-color-box-group">
-                <div
-                    v-for="(fill, i) in fillColors"
-                    :key="i"
-                    class="demo-color-box demo-color-box-other demo-color-box-lite"
-                    :style="{
-                        background: fill.var.value,
-                        border: `1px solid ${fill.name === 'Blank Fill' ? 'var(--el-border-color-light)' : 'transparent'}`,
-                    }"
-                >
-                    {{ fill.name }}
-                    <div class="value" text="xs">
-                        {{ fill.var.value.toUpperCase() }}
-                    </div>
-                </div>
-            </div>
-        </el-col>
+    <el-col :span="6" :xs="{ span: 12 }">
+      <div class="demo-color-box-group">
+        <div
+          v-for="(fill, i) in fillColors"
+          :key="i"
+          class="demo-color-box demo-color-box-other demo-color-box-lite"
+          :style="{
+            background: fill.var.value,
+            border: `1px solid ${
+              fill.name === 'Blank Fill'
+                ? 'var(--el-border-color-light)'
+                : 'transparent'
+            }`,
+          }"
+        >
+          {{ fill.name }}
+          <div class="value" text="xs">
+            {{ fill.var.value.toUpperCase() }}
+          </div>
+        </div>
+      </div>
+    </el-col>
 
-        <el-col :span="6" :xs="{ span: 12 }">
-            <div class="demo-color-box-group">
-                <div class="demo-color-box demo-color-box-other" :style="{ background: black }">
-                    Basic Black
-                    <div class="value" text="xs">{{ black }}</div>
-                </div>
-                <div
-                    class="demo-color-box demo-color-box-other"
-                    :style="{
-                        background: white,
-                        color: '#303133',
-                        border: '1px solid #eee',
-                    }"
-                >
-                    Basic White
-                    <div class="value" text="xs">{{ white }}</div>
-                </div>
-                <div class="demo-color-box demo-color-box-other demo-color-box-lite bg-transparent">
-                    Transparent
-                    <div class="value" text="xs">Transparent</div>
-                </div>
+    <el-col :span="6" :xs="{ span: 12 }">
+      <div class="demo-color-box-group">
+        <div
+          class="demo-color-box demo-color-box-other"
+          :style="{ background: black }"
+        >
+          Basic Black
+          <div class="value" text="xs">{{ black }}</div>
+        </div>
+        <div
+          class="demo-color-box demo-color-box-other"
+          :style="{
+            background: white,
+            color: '#303133',
+            border: '1px solid #eee',
+          }"
+        >
+          Basic White
+          <div class="value" text="xs">{{ white }}</div>
+        </div>
+        <div
+          class="demo-color-box demo-color-box-other demo-color-box-lite bg-transparent"
+        >
+          Transparent
+          <div class="value" text="xs">Transparent</div>
+        </div>
 
-                <div
-                    v-for="(bg, i) in backgroundColors"
-                    :key="i"
-                    class="demo-color-box demo-color-box-other demo-color-box-lite"
-                    :style="{
-                        background: bg.var.value,
-                        border: '1px solid ' + (!isDark || bg.name === 'Base Background' ? 'var(--el-border-color-light)' : 'transparent'),
-                    }"
-                >
-                    {{ bg.name }}
-                    <div class="value" text="xs">
-                        {{ bg.var.value.toUpperCase() }}
-                    </div>
-                </div>
-            </div>
-        </el-col>
-    </el-row>
+        <div
+          v-for="(bg, i) in backgroundColors"
+          :key="i"
+          class="demo-color-box demo-color-box-other demo-color-box-lite"
+          :style="{
+            background: bg.var.value,
+            border:
+              '1px solid ' +
+              (!isDark || bg.name === 'Base Background'
+                ? 'var(--el-border-color-light)'
+                : 'transparent'),
+          }"
+        >
+          {{ bg.name }}
+          <div class="value" text="xs">
+            {{ bg.var.value.toUpperCase() }}
+          </div>
+        </div>
+      </div>
+    </el-col>
+  </el-row>
 </template>
 
 <script lang="ts" setup>
@@ -95,35 +113,47 @@ import { isDark } from '~/composables/dark'
 import { getCssVarName, getCssVarValue } from '~/utils/colors'
 
 const backgroundTypes = ['page', '', 'overlay']
-const backgroundColors = backgroundTypes.map(type => {
-    return {
-        name: type ? `${type[0].toUpperCase() + type.slice(1)} Background` : 'Base Background',
-        var: getCssVarValue(getCssVarName('bg-color', type)),
-    }
+const backgroundColors = backgroundTypes.map((type) => {
+  return {
+    name: type
+      ? `${type[0].toUpperCase() + type.slice(1)} Background`
+      : 'Base Background',
+    var: getCssVarValue(getCssVarName('bg-color', type)),
+  }
 })
 
 const borderTypes = ['darker', 'dark', '', 'light', 'lighter', 'extra-light']
-const borderColors = borderTypes.map(type => {
-    return {
-        name: type ? `${type[0].toUpperCase() + type.slice(1)} Border` : 'Base Border',
-        var: getCssVarValue(getCssVarName('border-color', type)),
-    }
+const borderColors = borderTypes.map((type) => {
+  return {
+    name: type
+      ? `${type[0].toUpperCase() + type.slice(1)} Border`
+      : 'Base Border',
+    var: getCssVarValue(getCssVarName('border-color', type)),
+  }
 })
 
-const fillTypes = ['darker', 'dark', '', 'light', 'lighter', 'extra-light', 'blank']
-const fillColors = fillTypes.map(type => {
-    return {
-        name: type ? `${type[0].toUpperCase() + type.slice(1)} Fill` : 'Base Fill',
-        var: getCssVarValue(getCssVarName('fill-color', type)),
-    }
+const fillTypes = [
+  'darker',
+  'dark',
+  '',
+  'light',
+  'lighter',
+  'extra-light',
+  'blank',
+]
+const fillColors = fillTypes.map((type) => {
+  return {
+    name: type ? `${type[0].toUpperCase() + type.slice(1)} Fill` : 'Base Fill',
+    var: getCssVarValue(getCssVarName('fill-color', type)),
+  }
 })
 
 const textTypes = ['primary', 'regular', 'secondary', 'placeholder', 'disabled']
-const textColors = textTypes.map(type => {
-    return {
-        name: `${type[0].toUpperCase() + type.slice(1)} Text`,
-        var: getCssVarValue(getCssVarName('text-color', type)),
-    }
+const textColors = textTypes.map((type) => {
+  return {
+    name: `${type[0].toUpperCase() + type.slice(1)} Text`,
+    var: getCssVarValue(getCssVarName('text-color', type)),
+  }
 })
 
 const black = '#000000'

+ 305 - 305
docs/.vitepress/vitepress/components/globals/parallax-home.vue

@@ -3,8 +3,8 @@ import { computed, reactive, ref } from 'vue'
 import { useEventListener, useParallax, useThrottleFn } from '@vueuse/core'
 import { useLang } from '../../composables/lang'
 import homeLocale from '../../../i18n/pages/home.json'
-import HomeSponsors from '../home/home-sponsors.vue'
-import HomeCards from '../home/home-cards.vue'
+// import HomeSponsors from '../home/home-sponsors.vue'
+// import HomeCards from '../home/home-cards.vue'
 import HomeFooter from './vp-footer.vue'
 import type { CSSProperties } from 'vue'
 const target = ref<HTMLElement | null>(null)
@@ -14,103 +14,103 @@ const jumbotronRef = ref<HTMLElement | null>(null)
 const lang = useLang()
 const homeLang = computed(() => homeLocale[lang.value])
 
-function jumpTo(path: string) {
-    // vitepress has not router
-    location.href = `/${lang.value}/${path}`
-}
+// function jumpTo(path: string) {
+//     // vitepress has not router
+//     location.href = `/${lang.value}/${path}`
+// }
 
-const containerStyle: CSSProperties = {
-    display: 'flex',
-    flexDirection: 'column',
-    justifyContent: 'center',
-    alignItems: 'center',
-    transition: '.3s ease-out all',
+// const containerStyle: CSSProperties = {
+//     display: 'flex',
+//     flexDirection: 'column',
+//     justifyContent: 'center',
+//     alignItems: 'center',
+//     transition: '.3s ease-out all',
 
-    position: 'relative',
+//     position: 'relative',
 
-    perspective: '300px',
-}
+//     perspective: '300px',
+// }
 
-const cardStyle = computed(() => ({
-    height: '30rem',
-    width: '100%',
-    transition: '.3s ease-out all',
-    transform: `rotateX(${parallax.roll}deg) rotateY(${parallax.tilt}deg)`,
-}))
+// const cardStyle = computed(() => ({
+//     height: '30rem',
+//     width: '100%',
+//     transition: '.3s ease-out all',
+//     transform: `rotateX(${parallax.roll}deg) rotateY(${parallax.tilt}deg)`,
+// }))
 
 const layerBase: CSSProperties = {
-    position: 'absolute',
-    width: '100%',
-    height: '100%',
-    transition: '.3s ease-out all',
+  position: 'absolute',
+  width: '100%',
+  height: '100%',
+  transition: '.3s ease-out all',
 }
 
-const screenLayer = computed(() => ({
-    ...layerBase,
-    width: '80%',
-    height: '80%',
-    transform: `translateX(${parallax.tilt * 10 + 80}px) translateY(${parallax.roll * 10 + 50}px)`,
-}))
+// const screenLayer = computed(() => ({
+//     ...layerBase,
+//     width: '80%',
+//     height: '80%',
+//     transform: `translateX(${parallax.tilt * 10 + 80}px) translateY(${parallax.roll * 10 + 50}px)`,
+// }))
 
-const peopleLayer = computed(() => ({
-    ...layerBase,
-    width: '30%',
-    height: '30%',
-    right: 0,
-    bottom: 0,
-    transform: `translateX(${parallax.tilt * 25 + 25}px) translateY(${parallax.roll * 25}px) scale(1)`,
-}))
+// const peopleLayer = computed(() => ({
+//     ...layerBase,
+//     width: '30%',
+//     height: '30%',
+//     right: 0,
+//     bottom: 0,
+//     transform: `translateX(${parallax.tilt * 25 + 25}px) translateY(${parallax.roll * 25}px) scale(1)`,
+// }))
 
 // center layer
-const leftLayer = computed(() => ({
-    ...layerBase,
-    width: '20%',
-    height: '20%',
-    transform: `translateX(${parallax.tilt * 12 + 205}px) translateY(${parallax.roll * 12 + 210}px)`,
-}))
+// const leftLayer = computed(() => ({
+//     ...layerBase,
+//     width: '20%',
+//     height: '20%',
+//     transform: `translateX(${parallax.tilt * 12 + 205}px) translateY(${parallax.roll * 12 + 210}px)`,
+// }))
 
-const leftBottomLayer = computed(() => ({
-    ...layerBase,
-    width: '30%',
-    height: '30%',
-    left: 0,
-    bottom: 0,
-    transform: `translateX(${parallax.tilt * 30 - 10}px) translateY(${parallax.roll * 30}px)`,
-}))
+// const leftBottomLayer = computed(() => ({
+//     ...layerBase,
+//     width: '30%',
+//     height: '30%',
+//     left: 0,
+//     bottom: 0,
+//     transform: `translateX(${parallax.tilt * 30 - 10}px) translateY(${parallax.roll * 30}px)`,
+// }))
 
-const rightLayer = computed(() => ({
-    ...layerBase,
-    width: '33%',
-    height: '33%',
-    top: 0,
-    right: 0,
-    transform: `translateX(${parallax.tilt * 25 + 5}px) translateY(${parallax.roll * 25}px)`,
-}))
+// const rightLayer = computed(() => ({
+//     ...layerBase,
+//     width: '33%',
+//     height: '33%',
+//     top: 0,
+//     right: 0,
+//     transform: `translateX(${parallax.tilt * 25 + 5}px) translateY(${parallax.roll * 25}px)`,
+// }))
 
 const handleScroll = useThrottleFn(() => {
-    const ele = jumbotronRef.value
-    if (ele) {
-        const rect = ele.getBoundingClientRect()
-        const eleHeight = ele.clientHeight
-        let calHeight = (180 - rect.top) * 2
-        if (calHeight < 0) calHeight = 0
-        if (calHeight > eleHeight) calHeight = eleHeight
-        jumbotronRedOffset.value = calHeight
-    }
+  const ele = jumbotronRef.value
+  if (ele) {
+    const rect = ele.getBoundingClientRect()
+    const eleHeight = ele.clientHeight
+    let calHeight = (180 - rect.top) * 2
+    if (calHeight < 0) calHeight = 0
+    if (calHeight > eleHeight) calHeight = eleHeight
+    jumbotronRedOffset.value = calHeight
+  }
 }, 10)
 
 useEventListener(window, 'scroll', handleScroll)
 </script>
 
 <template>
-    <div ref="target" class="home-page">
-        <div class="banner" text="center">
-            <div class="banner-desc" m="t-4">
-                <h1>{{ homeLang['title'] }}</h1>
-                <p m="t-2">{{ homeLang['title_sub'] }}</p>
-            </div>
-        </div>
-        <!-- <div ref="jumbotronRef" class="jumbotron">
+  <div ref="target" class="home-page">
+    <div class="banner" text="center">
+      <div class="banner-desc" m="t-4">
+        <h1>{{ homeLang['title'] }}</h1>
+        <p m="t-2">{{ homeLang['title_sub'] }}</p>
+      </div>
+    </div>
+    <!-- <div ref="jumbotronRef" class="jumbotron">
             <div class="parallax-container" :style="containerStyle">
                 <div :style="cardStyle">
                     <screen-svg :style="screenLayer" alt="banner" />
@@ -121,261 +121,261 @@ useEventListener(window, 'scroll', handleScroll)
                 </div>
             </div>
         </div> -->
-        <!-- <img src="/images/theme-index-blue.png" alt="banner" class="mobile-banner" /> -->
-        <!-- <HomeSponsors /> -->
-        <!-- <HomeCards /> -->
-    </div>
-    <HomeFooter :is-home="true" />
+    <!-- <img src="/images/theme-index-blue.png" alt="banner" class="mobile-banner" /> -->
+    <!-- <HomeSponsors /> -->
+    <!-- <HomeCards /> -->
+  </div>
+  <HomeFooter :is-home="true" />
 </template>
 
 <style lang="scss">
 @use '../../styles/mixins' as *;
 
 .home-page {
-    .mobile-banner {
-        display: none;
-    }
+  .mobile-banner {
+    display: none;
+  }
 
-    .banner-dot h1 span {
-        position: relative;
-        &::after {
-            content: '';
-            position: absolute;
-            right: -12px;
-            bottom: 8px;
-            background: var(--el-color-primary);
-            height: 8px;
-            width: 8px;
-            border-radius: 100%;
-        }
+  .banner-dot h1 span {
+    position: relative;
+    &::after {
+      content: '';
+      position: absolute;
+      right: -12px;
+      bottom: 8px;
+      background: var(--el-color-primary);
+      height: 8px;
+      width: 8px;
+      border-radius: 100%;
+    }
+  }
+  .banner-desc {
+    h1 {
+      font-size: 34px;
+      margin: 0;
+      line-height: 48px;
+      color: var(--text-color);
     }
-    .banner-desc {
-        h1 {
-            font-size: 34px;
-            margin: 0;
-            line-height: 48px;
-            color: var(--text-color);
-        }
 
-        p {
-            font-size: 18px;
-            color: var(--text-color-light);
-        }
+    p {
+      font-size: 18px;
+      color: var(--text-color-light);
     }
+  }
 
-    .count-down {
-        .cd-main {
-            background: #f1f6fe;
-            border-radius: 10px;
-            width: 50%;
-            margin: 60px auto 120px;
-            padding: 30px 0;
-            font-size: 24px;
-            color: #666;
-            text-align: center;
-            font-weight: 600;
-        }
-        .cd-date {
-            font-size: 28px;
-        }
-        .cd-time {
-            display: flex;
-            justify-content: space-between;
-            width: 80%;
-            margin: 10px auto 0;
-        }
-        .cd-num {
-            color: var(--el-color-primary);
-            font-size: 78px;
-            font-weight: bold;
-        }
-        .cd-num span {
-            width: 50%;
-            display: inline-block;
-        }
-        .cd-str {
-            font-size: 22px;
-            margin-top: -5px;
-        }
+  .count-down {
+    .cd-main {
+      background: #f1f6fe;
+      border-radius: 10px;
+      width: 50%;
+      margin: 60px auto 120px;
+      padding: 30px 0;
+      font-size: 24px;
+      color: #666;
+      text-align: center;
+      font-weight: 600;
+    }
+    .cd-date {
+      font-size: 28px;
+    }
+    .cd-time {
+      display: flex;
+      justify-content: space-between;
+      width: 80%;
+      margin: 10px auto 0;
+    }
+    .cd-num {
+      color: var(--el-color-primary);
+      font-size: 78px;
+      font-weight: bold;
     }
+    .cd-num span {
+      width: 50%;
+      display: inline-block;
+    }
+    .cd-str {
+      font-size: 22px;
+      margin-top: -5px;
+    }
+  }
 
-    .jumbotron {
-        width: 800px;
-        margin: 20px auto;
-        position: relative;
+  .jumbotron {
+    width: 800px;
+    margin: 20px auto;
+    position: relative;
 
-        img {
-            width: 100%;
-        }
+    img {
+      width: 100%;
+    }
 
-        .parallax-container {
-            width: 800px;
-        }
+    .parallax-container {
+      width: 800px;
     }
+  }
 
-    @media screen and (max-width: 959px) {
-        .jumbotron {
-            display: none !important;
-        }
+  @media screen and (max-width: 959px) {
+    .jumbotron {
+      display: none !important;
+    }
 
-        .mobile-banner {
-            display: inline-block;
-        }
+    .mobile-banner {
+      display: inline-block;
     }
+  }
 
-    @media (max-width: 768px) {
-        .jumbotron {
-            width: 50%;
-            display: flex;
-            margin: auto;
-            justify-content: center;
-            align-items: center;
+  @media (max-width: 768px) {
+    .jumbotron {
+      width: 50%;
+      display: flex;
+      margin: auto;
+      justify-content: center;
+      align-items: center;
 
-            .parallax-container {
-                width: 100%;
-            }
-        }
+      .parallax-container {
+        width: 100%;
+      }
     }
+  }
 
-    @media (max-width: 768px) {
-        .banner-desc {
-            padding-top: 0px;
-        }
-        .cards {
-            li {
-                width: 80%;
-                margin: 0 auto 20px;
-                float: none;
-            }
-            .card {
-                height: auto;
-                padding-bottom: 54px;
-            }
-        }
-        .banner-stars {
-            display: none;
-        }
-        .banner-desc {
-            h1 {
-                font-size: 22px;
-            }
-            #line2 {
-                display: none;
-            }
-            h2 {
-                font-size: 32px;
-            }
-            p {
-                width: auto;
-            }
-        }
-        .banner-dot h1 span {
-            &::after {
-                right: -8px;
-                bottom: 2px;
-                height: 6px;
-                width: 6px;
-            }
-        }
-        .count-down {
-            .cd-main {
-                width: 90%;
-                margin: 40px auto 40px;
-                padding: 20px 0;
-            }
-            .cd-date {
-                font-size: 22px;
-            }
-            .cd-num {
-                font-size: 38px;
-            }
-            .cd-str {
-                font-size: 12px;
-                margin-top: 0px;
-            }
-        }
-        .sponsors-list {
-            display: flex;
-            flex-direction: column;
-            align-content: center;
-            .sponsor {
-                justify-content: left;
-            }
-        }
+  @media (max-width: 768px) {
+    .banner-desc {
+      padding-top: 0px;
     }
-    .theme-intro-b {
-        position: fixed;
-        left: 0;
-        right: 0;
-        top: 0;
-        bottom: 0;
-        z-index: 200;
-        .intro-banner {
-            position: absolute;
-        }
-        img {
-            width: 300px;
-        }
-        .title {
-            position: absolute;
-            top: 0;
-            bottom: 0;
-            left: 0;
-            right: 0;
-            color: #fff;
-            text-align: center;
-            font-weight: bold;
-            font-size: 20px;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            p {
-                padding: 0;
-                margin: 10px 0;
-            }
-        }
+    .cards {
+      li {
+        width: 80%;
+        margin: 0 auto 20px;
+        float: none;
+      }
+      .card {
+        height: auto;
+        padding-bottom: 54px;
+      }
+    }
+    .banner-stars {
+      display: none;
+    }
+    .banner-desc {
+      h1 {
+        font-size: 22px;
+      }
+      #line2 {
+        display: none;
+      }
+      h2 {
+        font-size: 32px;
+      }
+      p {
+        width: auto;
+      }
+    }
+    .banner-dot h1 span {
+      &::after {
+        right: -8px;
+        bottom: 2px;
+        height: 6px;
+        width: 6px;
+      }
+    }
+    .count-down {
+      .cd-main {
+        width: 90%;
+        margin: 40px auto 40px;
+        padding: 20px 0;
+      }
+      .cd-date {
+        font-size: 22px;
+      }
+      .cd-num {
+        font-size: 38px;
+      }
+      .cd-str {
+        font-size: 12px;
+        margin-top: 0px;
+      }
+    }
+    .sponsors-list {
+      display: flex;
+      flex-direction: column;
+      align-content: center;
+      .sponsor {
+        justify-content: left;
+      }
+    }
+  }
+  .theme-intro-b {
+    position: fixed;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    z-index: 200;
+    .intro-banner {
+      position: absolute;
+    }
+    img {
+      width: 300px;
     }
-    .theme-intro-a {
-        position: fixed;
+    .title {
+      position: absolute;
+      top: 0;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      color: #fff;
+      text-align: center;
+      font-weight: bold;
+      font-size: 20px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      p {
+        padding: 0;
+        margin: 10px 0;
+      }
+    }
+  }
+  .theme-intro-a {
+    position: fixed;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    z-index: 200;
+    .mask {
+      position: fixed;
+      left: 0;
+      right: 0;
+      top: 0;
+      bottom: 0;
+      background: #000;
+      opacity: 0.5;
+    }
+    .intro-banner {
+      top: 50%;
+      left: 50%;
+      position: fixed;
+      transform: translate(-50%, -50%);
+      box-sizing: border-box;
+      text-align: center;
+      z-index: 100;
+      img {
+        width: 100%;
+      }
+      .intro-text {
+        position: absolute;
+        top: 50%;
         left: 0;
         right: 0;
-        top: 0;
-        bottom: 0;
-        z-index: 200;
-        .mask {
-            position: fixed;
-            left: 0;
-            right: 0;
-            top: 0;
-            bottom: 0;
-            background: #000;
-            opacity: 0.5;
-        }
-        .intro-banner {
-            top: 50%;
-            left: 50%;
-            position: fixed;
-            transform: translate(-50%, -50%);
-            box-sizing: border-box;
-            text-align: center;
-            z-index: 100;
-            img {
-                width: 100%;
-            }
-            .intro-text {
-                position: absolute;
-                top: 50%;
-                left: 0;
-                right: 0;
-                p {
-                    padding: 0;
-                    margin: 0;
-                    font-size: 48px;
-                    font-weight: bold;
-                    color: #fff;
-                }
-            }
+        p {
+          padding: 0;
+          margin: 0;
+          font-size: 48px;
+          font-weight: bold;
+          color: #fff;
         }
+      }
     }
+  }
 }
 </style>

+ 104 - 88
docs/.vitepress/vitepress/components/globals/resource.vue

@@ -6,117 +6,133 @@ import resourceLocale from '../../../i18n/pages/resource.json'
 import { sendEvent } from '../../../config/analytics'
 const mirrorUrl = 'element-plus.gitee.io'
 const isMirrorUrl = () => {
-    if (!isClient) return
-    return window.location.hostname === mirrorUrl
+  if (!isClient) return
+  return window.location.hostname === mirrorUrl
 }
 const resourceUrl = {
-    github: {
-        sketch: 'https://github.com/ElementUI/Resources/raw/master/Element_Plus_Design_System_2022_1.0_Beta.zip',
-        axure: 'https://github.com/ElementUI/Resources/raw/master/Element_Components_v2.1.0.rplib',
-    },
-    gitee: {
-        sketch: 'https://gitee.com/element-plus/resources/raw/master/Element_Plus_Design_System_2022_1.0_Beta.zip',
-        axure: 'https://gitee.com/element-plus/resources/raw/master/Element_Components_v2.1.0.rplib',
-    },
+  github: {
+    sketch:
+      'https://github.com/ElementUI/Resources/raw/master/Element_Plus_Design_System_2022_1.0_Beta.zip',
+    axure:
+      'https://github.com/ElementUI/Resources/raw/master/Element_Components_v2.1.0.rplib',
+  },
+  gitee: {
+    sketch:
+      'https://gitee.com/element-plus/resources/raw/master/Element_Plus_Design_System_2022_1.0_Beta.zip',
+    axure:
+      'https://gitee.com/element-plus/resources/raw/master/Element_Components_v2.1.0.rplib',
+  },
 }[isMirrorUrl() ? 'gitee' : 'github']
 
 const lang = useLang()
 const resourceLang = computed(() => resourceLocale[lang.value])
 const onClick = (item: string) => {
-    sendEvent('resource_download', item)
+  sendEvent('resource_download', item)
 }
 </script>
 
 <template>
-    <div class="page-resource">
-        <h1>{{ resourceLang.title }}</h1>
-        <p>{{ resourceLang.lineOne }}</p>
-        <p v-html="resourceLang.lineTwo" />
-        <div class="flex flex-wrap justify-center mt-32px">
-            <div class="inline-flex w-full md:w-1/3" p="2" pl-0>
-                <el-card class="card" shadow="hover">
-                    <axure-components-svg w="30" alt="axure" />
-                    <h3>{{ resourceLang.axure }}</h3>
-                    <p>
-                        {{ resourceLang.axureIntro }}
-                    </p>
-                    <a target="_blank" :href="resourceUrl.axure" @click="onClick('axure')">
-                        <el-button type="primary">{{ resourceLang.download }}</el-button>
-                    </a>
-                </el-card>
-            </div>
-            <div class="inline-flex w-full md:w-1/3" p="2">
-                <el-card class="card" shadow="hover">
-                    <sketch-template-svg w="30" alt="Sketch" />
-                    <h3>{{ resourceLang.sketch }}</h3>
-                    <p>
-                        {{ resourceLang.sketchIntro }}
-                    </p>
-                    <a target="_blank" :href="resourceUrl.sketch" @click="onClick('sketch')">
-                        <el-button type="primary">{{ resourceLang.download }}</el-button>
-                    </a>
-                </el-card>
-            </div>
-            <div class="inline-flex w-full md:w-1/3" p="2">
-                <el-card class="card" shadow="hover">
-                    <figma-template-svg w="30" alt="Figma" />
-                    <h3>{{ resourceLang.figma }}</h3>
-                    <p>
-                        {{ resourceLang.figmaIntro }}
-                    </p>
-                    <a href="https://www.figma.com/community/file/1021254029764378306" target="_blank" @click="onClick('figma')">
-                        <el-button type="primary">{{ resourceLang.download }}</el-button>
-                    </a>
-                </el-card>
-            </div>
-        </div>
+  <div class="page-resource">
+    <h1>{{ resourceLang.title }}</h1>
+    <p>{{ resourceLang.lineOne }}</p>
+    <p v-html="resourceLang.lineTwo" />
+    <div class="flex flex-wrap justify-center mt-32px">
+      <div class="inline-flex w-full md:w-1/3" p="2" pl-0>
+        <el-card class="card" shadow="hover">
+          <axure-components-svg w="30" alt="axure" />
+          <h3>{{ resourceLang.axure }}</h3>
+          <p>
+            {{ resourceLang.axureIntro }}
+          </p>
+          <a
+            target="_blank"
+            :href="resourceUrl.axure"
+            @click="onClick('axure')"
+          >
+            <el-button type="primary">{{ resourceLang.download }}</el-button>
+          </a>
+        </el-card>
+      </div>
+      <div class="inline-flex w-full md:w-1/3" p="2">
+        <el-card class="card" shadow="hover">
+          <sketch-template-svg w="30" alt="Sketch" />
+          <h3>{{ resourceLang.sketch }}</h3>
+          <p>
+            {{ resourceLang.sketchIntro }}
+          </p>
+          <a
+            target="_blank"
+            :href="resourceUrl.sketch"
+            @click="onClick('sketch')"
+          >
+            <el-button type="primary">{{ resourceLang.download }}</el-button>
+          </a>
+        </el-card>
+      </div>
+      <div class="inline-flex w-full md:w-1/3" p="2">
+        <el-card class="card" shadow="hover">
+          <figma-template-svg w="30" alt="Figma" />
+          <h3>{{ resourceLang.figma }}</h3>
+          <p>
+            {{ resourceLang.figmaIntro }}
+          </p>
+          <a
+            href="https://www.figma.com/community/file/1021254029764378306"
+            target="_blank"
+            @click="onClick('figma')"
+          >
+            <el-button type="primary">{{ resourceLang.download }}</el-button>
+          </a>
+        </el-card>
+      </div>
     </div>
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .page-resource {
-    box-sizing: border-box;
-    padding: 0 40px;
+  box-sizing: border-box;
+  padding: 0 40px;
 
-    h1 {
-        color: var(--text-color);
-        margin-bottom: 24px;
-    }
-    p {
-        color: var(--text-color-light);
-        line-height: 24px;
-        margin: 0;
-        &:last-of-type {
-            margin-top: 8px;
-        }
+  h1 {
+    color: var(--text-color);
+    margin-bottom: 24px;
+  }
+  p {
+    color: var(--text-color-light);
+    line-height: 24px;
+    margin: 0;
+    &:last-of-type {
+      margin-top: 8px;
     }
+  }
 }
 
 .card {
-    text-align: center;
-    padding: 32px 0;
+  text-align: center;
+  padding: 32px 0;
 
-    img {
-        margin: auto;
-        margin-bottom: 16px;
-        height: 87px;
-    }
+  img {
+    margin: auto;
+    margin-bottom: 16px;
+    height: 87px;
+  }
 
-    h3 {
-        margin: 10px;
-        font-size: 18px;
-        font-weight: normal;
-    }
+  h3 {
+    margin: 10px;
+    font-size: 18px;
+    font-weight: normal;
+  }
 
-    p {
-        font-size: 14px;
-        color: #99a9bf;
-        padding: 0 30px;
-        margin: 0;
-        word-break: break-word;
-        line-height: 1.8;
-        min-height: 75px;
-        margin-bottom: 16px;
-    }
+  p {
+    font-size: 14px;
+    color: #99a9bf;
+    padding: 0 30px;
+    margin: 0;
+    word-break: break-word;
+    line-height: 1.8;
+    min-height: 75px;
+    margin-bottom: 16px;
+  }
 }
 </style>

+ 136 - 88
docs/.vitepress/vitepress/components/globals/resources/axure-components-svg.vue

@@ -1,121 +1,169 @@
 <template>
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 120 120"
-        style="enable-background: new 0 0 120 120"
-        xml:space="preserve"
-    >
-        <path class="st0" d="M8,16h104c1.7,0,3,1.3,3,3v82c0,1.7-1.3,3-3,3H8c-1.7,0-3-1.3-3-3V19C5,17.3,6.3,16,8,16z" />
-        <path
-            class="st1"
-            d="M13,22c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2s0.9-2,2-2C12.1,20,13,20.9,13,22z M19,22c0,1.1-0.9,2-2,2s-2-0.9-2-2
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 120 120"
+    style="enable-background: new 0 0 120 120"
+    xml:space="preserve"
+  >
+    <path
+      class="st0"
+      d="M8,16h104c1.7,0,3,1.3,3,3v82c0,1.7-1.3,3-3,3H8c-1.7,0-3-1.3-3-3V19C5,17.3,6.3,16,8,16z"
+    />
+    <path
+      class="st1"
+      d="M13,22c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2s0.9-2,2-2C12.1,20,13,20.9,13,22z M19,22c0,1.1-0.9,2-2,2s-2-0.9-2-2
     s0.9-2,2-2S19,20.9,19,22z M23,24c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S21.9,24,23,24z"
-        />
-        <path class="st2" d="M12,28h96c1.7,0,3,1.3,3,3v66c0,1.7-1.3,3-3,3H12c-1.7,0-3-1.3-3-3V31C9,29.3,10.3,28,12,28z" />
-        <path class="st3" d="M39,34h42c1.1,0,2,0.9,2,2v22c0,1.1-0.9,2-2,2H39c-1.1,0-2-0.9-2-2V36C37,34.9,37.9,34,39,34z" />
-        <path class="st4" d="M47,38h26c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H47c-1.1,0-2-0.9-2-2l0,0C45,38.9,45.9,38,47,38z" />
-        <path class="st4" d="M54,52h12c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H54c-1.1,0-2-0.9-2-2l0,0C52,52.9,52.9,52,54,52z" />
-        <path class="st4" d="M43,45h34c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H43c-1.1,0-2-0.9-2-2l0,0C41,45.9,41.9,45,43,45z" />
-        <path class="st5" d="M17,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H17c-1.1,0-2-0.9-2-2V77C15,75.9,15.9,75,17,75z" />
-        <path class="st6" d="M21,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H21c-1.1,0-2-0.9-2-2l0,0C19,79.9,19.9,79,21,79z" />
-        <path class="st6" d="M24,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C22,86.9,22.9,86,24,86z" />
-        <path class="st7" d="M49,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H49c-1.1,0-2-0.9-2-2V77C47,75.9,47.9,75,49,75z" />
-        <path class="st8" d="M53,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H53c-1.1,0-2-0.9-2-2l0,0C51,79.9,51.9,79,53,79z" />
-        <path class="st8" d="M56,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C54,86.9,54.9,86,56,86z" />
-        <path class="st9" d="M81,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H81c-1.1,0-2-0.9-2-2V77C79,75.9,79.9,75,81,75z" />
-        <path class="st10" d="M85,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H85c-1.1,0-2-0.9-2-2l0,0C83,79.9,83.9,79,85,79z" />
-        <path class="st10" d="M88,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C86,86.9,86.9,86,88,86z" />
-        <path class="st11" d="M58,60h4v5h30c1.1,0,2,0.9,2,2v2v6h-4v-6H62v6h-4v-6H30v6h-4v-6v-2c0-1.1,0.9-2,2-2h30V60z" />
-    </svg>
+    />
+    <path
+      class="st2"
+      d="M12,28h96c1.7,0,3,1.3,3,3v66c0,1.7-1.3,3-3,3H12c-1.7,0-3-1.3-3-3V31C9,29.3,10.3,28,12,28z"
+    />
+    <path
+      class="st3"
+      d="M39,34h42c1.1,0,2,0.9,2,2v22c0,1.1-0.9,2-2,2H39c-1.1,0-2-0.9-2-2V36C37,34.9,37.9,34,39,34z"
+    />
+    <path
+      class="st4"
+      d="M47,38h26c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H47c-1.1,0-2-0.9-2-2l0,0C45,38.9,45.9,38,47,38z"
+    />
+    <path
+      class="st4"
+      d="M54,52h12c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H54c-1.1,0-2-0.9-2-2l0,0C52,52.9,52.9,52,54,52z"
+    />
+    <path
+      class="st4"
+      d="M43,45h34c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H43c-1.1,0-2-0.9-2-2l0,0C41,45.9,41.9,45,43,45z"
+    />
+    <path
+      class="st5"
+      d="M17,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H17c-1.1,0-2-0.9-2-2V77C15,75.9,15.9,75,17,75z"
+    />
+    <path
+      class="st6"
+      d="M21,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H21c-1.1,0-2-0.9-2-2l0,0C19,79.9,19.9,79,21,79z"
+    />
+    <path
+      class="st6"
+      d="M24,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C22,86.9,22.9,86,24,86z"
+    />
+    <path
+      class="st7"
+      d="M49,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H49c-1.1,0-2-0.9-2-2V77C47,75.9,47.9,75,49,75z"
+    />
+    <path
+      class="st8"
+      d="M53,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H53c-1.1,0-2-0.9-2-2l0,0C51,79.9,51.9,79,53,79z"
+    />
+    <path
+      class="st8"
+      d="M56,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C54,86.9,54.9,86,56,86z"
+    />
+    <path
+      class="st9"
+      d="M81,75h22c1.1,0,2,0.9,2,2v15c0,1.1-0.9,2-2,2H81c-1.1,0-2-0.9-2-2V77C79,75.9,79.9,75,81,75z"
+    />
+    <path
+      class="st10"
+      d="M85,79h14c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2H85c-1.1,0-2-0.9-2-2l0,0C83,79.9,83.9,79,85,79z"
+    />
+    <path
+      class="st10"
+      d="M88,86h8c1.1,0,2,0.9,2,2l0,0c0,1.1-0.9,2-2,2h-8c-1.1,0-2-0.9-2-2l0,0C86,86.9,86.9,86,88,86z"
+    />
+    <path
+      class="st11"
+      d="M58,60h4v5h30c1.1,0,2,0.9,2,2v2v6h-4v-6H62v6h-4v-6H30v6h-4v-6v-2c0-1.1,0.9-2,2-2h30V60z"
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #f2f8fe;
+  fill: #f2f8fe;
 }
 .st1 {
-    fill-rule: evenodd;
-    clip-rule: evenodd;
-    fill: #ddeafc;
+  fill-rule: evenodd;
+  clip-rule: evenodd;
+  fill: #ddeafc;
 }
 .st2 {
-    fill: #ffffff;
+  fill: #ffffff;
 }
 .st3 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 .st4 {
-    fill: #0d89e5;
+  fill: #0d89e5;
 }
 .st5 {
-    fill: #80a8e1;
+  fill: #80a8e1;
 }
 .st6 {
-    fill: #5289d6;
+  fill: #5289d6;
 }
 .st7 {
-    fill: #ffd6d2;
+  fill: #ffd6d2;
 }
 .st8 {
-    fill: #f8a3a4;
+  fill: #f8a3a4;
 }
 .st9 {
-    fill: #dbedff;
+  fill: #dbedff;
 }
 .st10 {
-    fill: #a2c6eb;
+  fill: #a2c6eb;
 }
 .st11 {
-    fill-rule: evenodd;
-    clip-rule: evenodd;
-    fill: #deebfd;
+  fill-rule: evenodd;
+  clip-rule: evenodd;
+  fill: #deebfd;
 }
 
 .dark {
-    .st0 {
-        fill: #272829;
-    }
-    .st1 {
-        fill-rule: evenodd;
-        clip-rule: evenodd;
-        fill: #494c52;
-    }
-    .st2 {
-        fill: #33383d;
-    }
-    .st3 {
-        fill: #20a0ff;
-    }
-    .st4 {
-        fill: #0d89e5;
-    }
-    .st5 {
-        fill: #80a8e1;
-    }
-    .st6 {
-        fill: #5289d6;
-    }
-    .st7 {
-        fill: #ffd6d2;
-    }
-    .st8 {
-        fill: #f8a3a4;
-    }
-    .st9 {
-        fill: #5d6874;
-    }
-    .st10 {
-        fill: #a2c6eb;
-    }
-    .st11 {
-        fill-rule: evenodd;
-        clip-rule: evenodd;
-        fill: #3e4652;
-    }
+  .st0 {
+    fill: #272829;
+  }
+  .st1 {
+    fill-rule: evenodd;
+    clip-rule: evenodd;
+    fill: #494c52;
+  }
+  .st2 {
+    fill: #33383d;
+  }
+  .st3 {
+    fill: #20a0ff;
+  }
+  .st4 {
+    fill: #0d89e5;
+  }
+  .st5 {
+    fill: #80a8e1;
+  }
+  .st6 {
+    fill: #5289d6;
+  }
+  .st7 {
+    fill: #ffd6d2;
+  }
+  .st8 {
+    fill: #f8a3a4;
+  }
+  .st9 {
+    fill: #5d6874;
+  }
+  .st10 {
+    fill: #a2c6eb;
+  }
+  .st11 {
+    fill-rule: evenodd;
+    clip-rule: evenodd;
+    fill: #3e4652;
+  }
 }
 </style>

+ 59 - 44
docs/.vitepress/vitepress/components/globals/resources/figma-template-svg.vue

@@ -1,71 +1,86 @@
 <template>
-    <!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 120 120"
-        style="enable-background: new 0 0 120 120"
-        xml:space="preserve"
-    >
-        <path class="st0" d="M7,14h106c1.1,0,2,0.9,2,2v68c0,1.1-0.9,2-2,2H7c-1.1,0-2-0.9-2-2V16C5,14.9,5.9,14,7,14z" />
-        <path class="st1" d="M60,46c0-3.3,2.7-6,6-6l0,0c3.3,0,6,2.7,6,6l0,0c0,3.3-2.7,6-6,6l0,0C62.7,52,60,49.3,60,46L60,46z" />
-        <path class="st2" d="M48,58c0-3.3,2.7-6,6-6h6v6c0,3.3-2.7,6-6,6l0,0C50.7,64,48,61.3,48,58L48,58z" />
-        <path class="st3" d="M60,28v12h6c3.3,0,6-2.7,6-6l0,0c0-3.3-2.7-6-6-6H60z" />
-        <path class="st4" d="M48,34c0,3.3,2.7,6,6,6h6V28h-6C50.7,28,48,30.7,48,34L48,34z" />
-        <path class="st5" d="M48,46c0,3.3,2.7,6,6,6h6V40h-6C50.7,40,48,42.7,48,46L48,46z" />
-        <path class="st6" d="M5,74h110v10c0,1.1-0.9,2-2,2H7c-1.1,0-2-0.9-2-2V74z" />
-        <circle class="st7" cx="60" cy="80" r="2" />
-        <path
-            class="st8"
-            d="M46.8,86L38,103.1c-0.7,1.3,0.3,2.9,1.8,2.9H60V86H46.8z M73.2,86l8.7,17.1c0.7,1.3-0.3,2.9-1.8,2.9H60V86H73.2
+  <!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 120 120"
+    style="enable-background: new 0 0 120 120"
+    xml:space="preserve"
+  >
+    <path
+      class="st0"
+      d="M7,14h106c1.1,0,2,0.9,2,2v68c0,1.1-0.9,2-2,2H7c-1.1,0-2-0.9-2-2V16C5,14.9,5.9,14,7,14z"
+    />
+    <path
+      class="st1"
+      d="M60,46c0-3.3,2.7-6,6-6l0,0c3.3,0,6,2.7,6,6l0,0c0,3.3-2.7,6-6,6l0,0C62.7,52,60,49.3,60,46L60,46z"
+    />
+    <path
+      class="st2"
+      d="M48,58c0-3.3,2.7-6,6-6h6v6c0,3.3-2.7,6-6,6l0,0C50.7,64,48,61.3,48,58L48,58z"
+    />
+    <path class="st3" d="M60,28v12h6c3.3,0,6-2.7,6-6l0,0c0-3.3-2.7-6-6-6H60z" />
+    <path
+      class="st4"
+      d="M48,34c0,3.3,2.7,6,6,6h6V28h-6C50.7,28,48,30.7,48,34L48,34z"
+    />
+    <path
+      class="st5"
+      d="M48,46c0,3.3,2.7,6,6,6h6V40h-6C50.7,40,48,42.7,48,46L48,46z"
+    />
+    <path class="st6" d="M5,74h110v10c0,1.1-0.9,2-2,2H7c-1.1,0-2-0.9-2-2V74z" />
+    <circle class="st7" cx="60" cy="80" r="2" />
+    <path
+      class="st8"
+      d="M46.8,86L38,103.1c-0.7,1.3,0.3,2.9,1.8,2.9H60V86H46.8z M73.2,86l8.7,17.1c0.7,1.3-0.3,2.9-1.8,2.9H60V86H73.2
 	z"
-        />
-    </svg>
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #f2f8fe;
+  fill: #f2f8fe;
 }
 .st1 {
-    fill: #1abcfe;
+  fill: #1abcfe;
 }
 .st2 {
-    fill: #0acf83;
+  fill: #0acf83;
 }
 .st3 {
-    fill: #ff7262;
+  fill: #ff7262;
 }
 .st4 {
-    fill: #f24e1e;
+  fill: #f24e1e;
 }
 .st5 {
-    fill: #a259ff;
+  fill: #a259ff;
 }
 .st6 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 .st7 {
-    fill: #ffffff;
+  fill: #ffffff;
 }
 .st8 {
-    fill-rule: evenodd;
-    clip-rule: evenodd;
-    fill: #deecf9;
+  fill-rule: evenodd;
+  clip-rule: evenodd;
+  fill: #deecf9;
 }
 
 .dark {
-    .st0 {
-        fill: #272829;
-    }
-    .st8 {
-        fill-rule: evenodd;
-        clip-rule: evenodd;
-        fill: #373f48;
-    }
+  .st0 {
+    fill: #272829;
+  }
+  .st8 {
+    fill-rule: evenodd;
+    clip-rule: evenodd;
+    fill: #373f48;
+  }
 }
 </style>

+ 55 - 46
docs/.vitepress/vitepress/components/globals/resources/sketch-template-svg.vue

@@ -1,73 +1,82 @@
 <template>
-    <svg
-        id="图层_1"
-        version="1.1"
-        xmlns="http://www.w3.org/2000/svg"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        x="0px"
-        y="0px"
-        viewBox="0 0 120 120"
-        style="enable-background: new 0 0 120 120"
-        xml:space="preserve"
-    >
-        <path class="st0" d="M13,15h48c3.3,0,6,2.7,6,6v33c0,3.3-2.7,6-6,6H13c-3.3,0-6-2.7-6-6V21C7,17.7,9.7,15,13,15z" />
-        <path class="st0" d="M81,15h20c3.3,0,6,2.7,6,6v33c0,3.3-2.7,6-6,6H81c-3.3,0-6-2.7-6-6V21C75,17.7,77.7,15,81,15z" />
-        <path
-            class="st1"
-            d="M12.5,15h49c3,0,5.5,2.5,5.5,5.5l0,0c0,3-2.5,5.5-5.5,5.5h-49c-3,0-5.5-2.5-5.5-5.5l0,0C7,17.5,9.5,15,12.5,15z
+  <svg
+    id="图层_1"
+    version="1.1"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    x="0px"
+    y="0px"
+    viewBox="0 0 120 120"
+    style="enable-background: new 0 0 120 120"
+    xml:space="preserve"
+  >
+    <path
+      class="st0"
+      d="M13,15h48c3.3,0,6,2.7,6,6v33c0,3.3-2.7,6-6,6H13c-3.3,0-6-2.7-6-6V21C7,17.7,9.7,15,13,15z"
+    />
+    <path
+      class="st0"
+      d="M81,15h20c3.3,0,6,2.7,6,6v33c0,3.3-2.7,6-6,6H81c-3.3,0-6-2.7-6-6V21C75,17.7,77.7,15,81,15z"
+    />
+    <path
+      class="st1"
+      d="M12.5,15h49c3,0,5.5,2.5,5.5,5.5l0,0c0,3-2.5,5.5-5.5,5.5h-49c-3,0-5.5-2.5-5.5-5.5l0,0C7,17.5,9.5,15,12.5,15z
       "
-        />
-        <path
-            class="st2"
-            d="M80.5,15h21c3,0,5.5,2.5,5.5,5.5l0,0c0,3-2.5,5.5-5.5,5.5h-21c-3,0-5.5-2.5-5.5-5.5l0,0
+    />
+    <path
+      class="st2"
+      d="M80.5,15h21c3,0,5.5,2.5,5.5,5.5l0,0c0,3-2.5,5.5-5.5,5.5h-21c-3,0-5.5-2.5-5.5-5.5l0,0
       C75,17.5,77.5,15,80.5,15z"
-        />
-        <path class="st0" d="M90,68c3.3,0,6,2.7,6,6v28c0,2.2-1.8,4-4,4H13c-3.3,0-6-2.7-6-6V74c0-3.3,2.7-6,6-6H90z" />
-        <path
-            class="st2"
-            d="M18,73.5v27c0,3-2.5,5.5-5.5,5.5l0,0c-3,0-5.5-2.5-5.5-5.5v-27c0-3,2.5-5.5,5.5-5.5l0,0
+    />
+    <path
+      class="st0"
+      d="M90,68c3.3,0,6,2.7,6,6v28c0,2.2-1.8,4-4,4H13c-3.3,0-6-2.7-6-6V74c0-3.3,2.7-6,6-6H90z"
+    />
+    <path
+      class="st2"
+      d="M18,73.5v27c0,3-2.5,5.5-5.5,5.5l0,0c-3,0-5.5-2.5-5.5-5.5v-27c0-3,2.5-5.5,5.5-5.5l0,0
       C15.5,68,18,70.5,18,73.5z"
-        />
-        <path class="st3" d="M84.3,78.7L79.5,68h13.1L84.3,78.7z" />
-        <path class="st4" d="M102.1,78.7H84.2L92.6,68L102.1,78.7z" />
-        <path class="st5" d="M70,78.7L79.5,68l4.8,10.7H70z" />
-        <path class="st6" d="M92.6,68l9.5,10.7l4.8-10.7H92.6z" />
-        <path class="st5" d="M106.8,68l8.3,10.7h-13.1L106.8,68z" />
-        <path class="st7" d="M93.8,106l21.4-27.3h-13.1L93.8,106z" />
-        <path class="st3" d="M70,78.7L93.8,106l-9.5-27.3H70z" />
-        <path class="st5" d="M93.8,106l8.3-27.3H84.2L93.8,106z" />
-    </svg>
+    />
+    <path class="st3" d="M84.3,78.7L79.5,68h13.1L84.3,78.7z" />
+    <path class="st4" d="M102.1,78.7H84.2L92.6,68L102.1,78.7z" />
+    <path class="st5" d="M70,78.7L79.5,68l4.8,10.7H70z" />
+    <path class="st6" d="M92.6,68l9.5,10.7l4.8-10.7H92.6z" />
+    <path class="st5" d="M106.8,68l8.3,10.7h-13.1L106.8,68z" />
+    <path class="st7" d="M93.8,106l21.4-27.3h-13.1L93.8,106z" />
+    <path class="st3" d="M70,78.7L93.8,106l-9.5-27.3H70z" />
+    <path class="st5" d="M93.8,106l8.3-27.3H84.2L93.8,106z" />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .st0 {
-    fill: #f2f8fe;
+  fill: #f2f8fe;
 }
 .st1 {
-    fill: #ffd6d2;
+  fill: #ffd6d2;
 }
 .st2 {
-    fill: #20a0ff;
+  fill: #20a0ff;
 }
 .st3 {
-    fill: #6496dc;
+  fill: #6496dc;
 }
 .st4 {
-    fill: #afc8ea;
+  fill: #afc8ea;
 }
 .st5 {
-    fill: #80a8e1;
+  fill: #80a8e1;
 }
 .st6 {
-    fill: #93b8ee;
+  fill: #93b8ee;
 }
 .st7 {
-    fill: #afc8eb;
+  fill: #afc8eb;
 }
 
 .dark {
-    .st0 {
-        fill: #3e444a;
-    }
+  .st0 {
+    fill: #3e444a;
+  }
 }
 </style>

+ 28 - 23
docs/.vitepress/vitepress/components/globals/secondary-colors.vue

@@ -3,33 +3,38 @@ import { getColorValue, useCopyColor } from '../../utils'
 
 const colorsType = ['success', 'warning', 'danger', 'info']
 
-const colorLevel = [3, 5, 7, 8, 9].map(item => `light-${item}`)
+const colorLevel = [3, 5, 7, 8, 9].map((item) => `light-${item}`)
 colorLevel.unshift('dark-2')
 
 const { copyColor } = useCopyColor()
 </script>
 
 <template>
-    <el-row :gutter="12">
-        <el-col v-for="(type, i) in colorsType" :key="i" :span="6" :xs="{ span: 12 }">
-            <div class="demo-color-box" :style="{ background: getColorValue(type) }">
-                {{ type.charAt(0).toUpperCase() + type.slice(1) }}
-                <div class="value" text="xs">
-                    {{ getColorValue(type).toUpperCase() }}
-                </div>
-                <div class="bg-color-sub">
-                    <div
-                        v-for="(level, key) in colorLevel"
-                        :key="key"
-                        class="bg-secondary-sub-item transition cursor-pointer hover:shadow"
-                        :style="{
-                            width: `${100 / 6}%`,
-                            background: `var(--el-color-${type}-` + level + ')',
-                        }"
-                        @click="copyColor(type + '-' + level)"
-                    />
-                </div>
-            </div>
-        </el-col>
-    </el-row>
+  <el-row :gutter="12">
+    <el-col
+      v-for="(type, i) in colorsType"
+      :key="i"
+      :span="6"
+      :xs="{ span: 12 }"
+    >
+      <div class="demo-color-box" :style="{ background: getColorValue(type) }">
+        {{ type.charAt(0).toUpperCase() + type.slice(1) }}
+        <div class="value" text="xs">
+          {{ getColorValue(type).toUpperCase() }}
+        </div>
+        <div class="bg-color-sub">
+          <div
+            v-for="(level, key) in colorLevel"
+            :key="key"
+            class="bg-secondary-sub-item transition cursor-pointer hover:shadow"
+            :style="{
+              width: `${100 / 6}%`,
+              background: `var(--el-color-${type}-` + level + ')',
+            }"
+            @click="copyColor(type + '-' + level)"
+          />
+        </div>
+      </div>
+    </el-col>
+  </el-row>
 </template>

+ 7 - 0
docs/.vitepress/vitepress/components/globals/vp-api-bool.vue

@@ -0,0 +1,7 @@
+<script setup lang="ts">
+import Primitive from './vp-api-primitive.vue'
+</script>
+
+<template>
+  <Primitive type="boolean" />
+</template>

+ 20 - 0
docs/.vitepress/vitepress/components/globals/vp-api-enum.vue

@@ -0,0 +1,20 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { isString } from '@vue/shared'
+import ApiTyping from './vp-api-typing.vue'
+
+const props = defineProps({
+  values: {
+    type: Array,
+    required: true,
+  },
+})
+
+const processString = (s: unknown) => (isString(s) ? `'${s}'` : s)
+
+const details = computed(() => props.values.map(processString).join(' | '))
+</script>
+
+<template>
+  <api-typing type="enum" :details="details" />
+</template>

+ 33 - 0
docs/.vitepress/vitepress/components/globals/vp-api-external.vue

@@ -0,0 +1,33 @@
+<script setup lang="ts">
+import VpLink from '../common/vp-link.vue'
+
+defineProps({
+  text: {
+    type: String,
+    required: true,
+  },
+  url: {
+    type: String,
+    required: true,
+  },
+  prefix: {
+    type: String,
+    default: '',
+  },
+})
+</script>
+
+<template>
+  <slot>
+    <span v-if="prefix" class="mr-1">{{ prefix }}</span>
+    <VpLink :href="url">
+      {{ text }}
+    </VpLink>
+  </slot>
+</template>
+
+<style scoped>
+:deep(.el-icon) {
+  font-size: 18px;
+}
+</style>

+ 40 - 0
docs/.vitepress/vitepress/components/globals/vp-api-function.vue

@@ -0,0 +1,40 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import ApiTyping from './vp-api-typing.vue'
+
+import type { PropType } from 'vue'
+
+type ParamType = [string, string]
+
+const props = defineProps({
+  /**
+   * @description params list, shape of Array<[key: string, value: string]>
+   */
+  params: {
+    type: Array as PropType<Array<ParamType>>,
+    default: () => [],
+  },
+  returns: {
+    type: String,
+    default: 'void',
+  },
+})
+
+const mappedParams = computed(() =>
+  props.params
+    .reduce((params, [key, val]) => {
+      let type = val
+      if (Array.isArray(val)) {
+        type = val.join(' | ')
+      }
+      return params.concat([`${key}: ${type}`])
+    }, [] as string[])
+    .join(', ')
+)
+
+const details = computed(() => `(${mappedParams.value}) => ${props.returns}`)
+</script>
+
+<template>
+  <api-typing type="Function" :details="details" />
+</template>

+ 7 - 0
docs/.vitepress/vitepress/components/globals/vp-api-number.vue

@@ -0,0 +1,7 @@
+<script setup lang="ts">
+import Primitive from './vp-api-primitive.vue'
+</script>
+
+<template>
+  <Primitive type="number" />
+</template>

+ 14 - 0
docs/.vitepress/vitepress/components/globals/vp-api-primitive.vue

@@ -0,0 +1,14 @@
+<script setup lang="ts">
+defineProps({
+  type: {
+    type: String,
+    required: true,
+  },
+})
+</script>
+
+<template>
+  <code>
+    {{ type }}
+  </code>
+</template>

+ 21 - 0
docs/.vitepress/vitepress/components/globals/vp-api-ref.vue

@@ -0,0 +1,21 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import ApiTyping from './vp-api-typing.vue'
+
+const props = defineProps({
+  type: {
+    type: String,
+    required: true,
+  },
+  shallow: Boolean,
+})
+
+const type = computed(() => {
+  const wrapperType = props.shallow ? 'ShallowRef' : 'Ref'
+  return `${wrapperType}<${props.type}>`
+})
+</script>
+
+<template>
+  <ApiTyping type="Object" :details="type" />
+</template>

+ 7 - 0
docs/.vitepress/vitepress/components/globals/vp-api-string.vue

@@ -0,0 +1,7 @@
+<script setup lang="ts">
+import Primitive from './vp-api-primitive.vue'
+</script>
+
+<template>
+  <Primitive type="string" />
+</template>

+ 35 - 0
docs/.vitepress/vitepress/components/globals/vp-api-typing.vue

@@ -0,0 +1,35 @@
+<script setup lang="ts">
+import { Warning } from '@element-plus/icons-vue'
+
+defineProps({
+  type: String,
+  details: String,
+})
+</script>
+
+<template>
+  <span class="inline-flex items-center">
+    <code class="api-typing mr-1">
+      {{ type }}
+    </code>
+    <ClientOnly>
+      <ElTooltip v-if="details" effect="light" trigger="click">
+        <ElButton text :icon="Warning" class="p-2 text-4" />
+        <template #content>
+          <slot>
+            <div class="m-1">
+              <code
+                style="
+                  color: var(--code-tooltip-color);
+                  background-color: var(--code-tooltip-bg-color);
+                "
+              >
+                {{ details }}
+              </code>
+            </div>
+          </slot>
+        </template>
+      </ElTooltip>
+    </ClientOnly>
+  </span>
+</template>

+ 86 - 73
docs/.vitepress/vitepress/components/globals/vp-changelog.vue

@@ -8,8 +8,8 @@ import { useLocale } from '../../composables/locale'
 import changelogLocale from '../../../i18n/component/changelog.json'
 
 interface Release {
-    id: number
-    name: string
+  id: number
+  name: string
 }
 
 const loading = ref(true)
@@ -18,93 +18,106 @@ const currentRelease = ref()
 const changelog = useLocale(changelogLocale)
 const lang = useLang()
 
-const onVersionChange = val => {
-    const _releases = releases.value
-    currentRelease.value = _releases[_releases.findIndex(r => r.name === val)]
+const onVersionChange = (val) => {
+  const _releases = releases.value
+  currentRelease.value = _releases[_releases.findIndex((r) => r.name === val)]
 }
 
 onMounted(async () => {
-    try {
-        const { data } = await axios.get<Release[]>('https://api.github.com/repos/element-plus/element-plus/releases')
-        releases.value = data
-        currentRelease.value = data[0]
-    } catch {
-        releases.value = []
-        currentRelease.value = undefined
-        // do something
-    } finally {
-        loading.value = false
-    }
+  try {
+    const { data } = await axios.get<Release[]>(
+      'https://api.github.com/repos/element-plus/element-plus/releases'
+    )
+    releases.value = data
+    currentRelease.value = data[0]
+  } catch {
+    releases.value = []
+    currentRelease.value = undefined
+    // do something
+  } finally {
+    loading.value = false
+  }
 })
 </script>
 
 <template>
-    <div class="changelogs">
-        <ClientOnly>
-            <ElSkeleton :loading="loading">
-                <div class="changelog-versions">
-                    <p>{{ changelog['select-version'] }}:</p>
-                    <ElSelect :model-value="currentRelease.name" :placeholder="changelog['select-version']" style="min-width: 200px" @change="onVersionChange">
-                        <ElOption v-for="release in releases" :key="release.id" :value="release.name">
-                            {{ release.name }}
-                        </ElOption>
-                    </ElSelect>
-                </div>
-                <ElCard v-if="currentRelease">
-                    <template #header>
-                        <div class="changelog-header">
-                            <div class="changelog-meta">
-                                <p class="changelog-by">
-                                    {{ changelog['published-by'] }}
-                                    <strong>{{ currentRelease.author.login }}</strong>
-                                </p>
-                                <p class="changelog-date">
-                                    {{ new Date(currentRelease.published_at).toLocaleString(lang) }}
-                                </p>
-                            </div>
-                            <div class="operators">
-                                <VPLink :href="currentRelease.html_url">
-                                    {{ changelog['open-link'] }}
-                                </VPLink>
-                            </div>
-                        </div>
-                    </template>
-                    <div>
-                        <VPMarkdown :content="currentRelease.body" />
-                    </div>
-                </ElCard>
-            </ElSkeleton>
-        </ClientOnly>
-    </div>
+  <div class="changelogs">
+    <ClientOnly>
+      <ElSkeleton :loading="loading">
+        <div class="changelog-versions">
+          <p>{{ changelog['select-version'] }}:</p>
+          <ElSelect
+            :model-value="currentRelease.name"
+            :placeholder="changelog['select-version']"
+            style="min-width: 200px"
+            @change="onVersionChange"
+          >
+            <ElOption
+              v-for="release in releases"
+              :key="release.id"
+              :value="release.name"
+            >
+              {{ release.name }}
+            </ElOption>
+          </ElSelect>
+        </div>
+        <ElCard v-if="currentRelease">
+          <template #header>
+            <div class="changelog-header">
+              <div class="changelog-meta">
+                <p class="changelog-by">
+                  {{ changelog['published-by'] }}
+                  <strong>{{ currentRelease.author.login }}</strong>
+                </p>
+                <p class="changelog-date">
+                  {{
+                    new Date(currentRelease.published_at).toLocaleString(lang)
+                  }}
+                </p>
+              </div>
+              <div class="operators">
+                <VPLink :href="currentRelease.html_url">
+                  {{ changelog['open-link'] }}
+                </VPLink>
+              </div>
+            </div>
+          </template>
+          <div>
+            <VPMarkdown :content="currentRelease.body" />
+          </div>
+        </ElCard>
+      </ElSkeleton>
+    </ClientOnly>
+  </div>
 </template>
 
 <style lang="scss" scoped>
 .changelog-versions {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    margin-bottom: 1rem;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 1rem;
 
-    p {
-        margin-right: 2rem;
-    }
+  p {
+    margin-right: 2rem;
+  }
 }
 .changelog-header {
-    display: flex;
-    align-items: flex-start;
-    justify-content: space-between;
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
 
-    .changelog-meta {
-        display: flex;
-        flex: 1;
-        flex-direction: column;
-        p {
-            margin: 0;
-        }
+  .changelog-meta {
+    display: flex;
+    flex: 1;
+    flex-direction: column;
+    p {
+      margin: 0;
     }
+  }
 
-    .link-item {
-        line-height: 1.7;
-    }
+  .link-item {
+    line-height: 1.7;
+  }
 }
 </style>

+ 89 - 89
docs/.vitepress/vitepress/components/globals/vp-footer.vue

@@ -4,7 +4,7 @@ import { useLang } from '../../composables/lang'
 import homeLocale from '../../../i18n/pages/home.json'
 
 defineProps<{
-    isHome?: boolean
+  isHome?: boolean
 }>()
 
 const lang = useLang()
@@ -12,9 +12,9 @@ const homeLang = computed(() => homeLocale[lang.value])
 </script>
 
 <template>
-    <footer class="footer" :class="{ 'is-home': isHome }">
-        <div class="footer-main">
-            <!-- <h4>{{ homeLang['10'] }}</h4>
+  <footer class="footer" :class="{ 'is-home': isHome }">
+    <div class="footer-main">
+      <!-- <h4>{{ homeLang['10'] }}</h4>
             <a href="https://github.com/element-plus/element-plus" class="footer-main-link" target="_blank">
                 {{ homeLang['11'] }}
             </a>
@@ -27,10 +27,10 @@ const homeLang = computed(() => homeLocale[lang.value])
             <a href="https://element.eleme.io/" class="footer-main-link" target="_blank">
                 {{ homeLang['13'] }}
             </a> -->
-        </div>
+    </div>
 
-        <div class="footer-main">
-            <!-- <h4>{{ homeLang['19'] }}</h4>
+    <div class="footer-main">
+      <!-- <h4>{{ homeLang['19'] }}</h4>
             <a href="https://discord.link/ElementPlus" class="footer-main-link" target="_blank">
                 {{ homeLang['discord'] }}
             </a>
@@ -43,111 +43,111 @@ const homeLang = computed(() => homeLocale[lang.value])
             <a href="https://segmentfault.com/t/element-plus" class="footer-main-link" target="_blank">
                 {{ homeLang['18'] }}
             </a> -->
-        </div>
-    </footer>
+    </div>
+  </footer>
 </template>
 
 <style lang="scss">
 .dark .footer {
-    background-color: var(--el-fill-color-lighter);
+  background-color: var(--el-fill-color-lighter);
 }
 .footer {
-    background-color: #f5f7fa;
+  background-color: #f5f7fa;
+  box-sizing: border-box;
+  padding: 42px 64px 64px;
+  // height: 340px;
+
+  &.is-home {
+    background-color: var(--bg-color);
+    max-width: 900px;
+    margin: 0 auto;
+    padding: 40px 19px;
+  }
+
+  .container {
     box-sizing: border-box;
-    padding: 42px 64px 64px;
-    // height: 340px;
-
-    &.is-home {
-        background-color: var(--bg-color);
-        max-width: 900px;
-        margin: 0 auto;
-        padding: 40px 19px;
+    width: auto;
+  }
+
+  .footer-main {
+    font-size: 0;
+    display: inline-block;
+    vertical-align: top;
+    margin-right: 130px;
+
+    h4 {
+      font-size: 18px;
+      line-height: 1;
+      margin: 0 0 15px 0;
+      font-weight: 400;
+      color: var(--el-text-color-primary);
     }
 
-    .container {
-        box-sizing: border-box;
-        width: auto;
+    .footer-main-link {
+      display: block;
+      margin: 0;
+      line-height: 2;
+      font-size: 14px;
+      color: var(--text-color-light);
+
+      &:hover {
+        color: var(--text-color);
+      }
+    }
+  }
+
+  .footer-social {
+    float: right;
+    text-align: right;
+
+    .footer-social-title {
+      color: var(--text-color-light);
+      font-size: 18px;
+      line-height: 1;
+      margin: 0 0 20px 0;
+      padding: 0;
+      font-weight: bold;
     }
 
-    .footer-main {
-        font-size: 0;
-        display: inline-block;
-        vertical-align: top;
-        margin-right: 130px;
-
-        h4 {
-            font-size: 18px;
-            line-height: 1;
-            margin: 0 0 15px 0;
-            font-weight: 400;
-            color: var(--el-text-color-primary);
-        }
-
-        .footer-main-link {
-            display: block;
-            margin: 0;
-            line-height: 2;
-            font-size: 14px;
-            color: var(--text-color-light);
-
-            &:hover {
-                color: var(--text-color);
-            }
-        }
+    .ep-icon-github {
+      transition: 0.3s;
+      display: inline-block;
+      line-height: 32px;
+      text-align: center;
+      color: #c8d6e8;
+      background-color: transparent;
+      font-size: 32px;
+      vertical-align: middle;
+      margin-right: 20px;
+      &:hover {
+        transform: scale(1.2);
+        color: #8d99ab;
+      }
     }
 
-    .footer-social {
-        float: right;
-        text-align: right;
-
-        .footer-social-title {
-            color: var(--text-color-light);
-            font-size: 18px;
-            line-height: 1;
-            margin: 0 0 20px 0;
-            padding: 0;
-            font-weight: bold;
-        }
-
-        .ep-icon-github {
-            transition: 0.3s;
-            display: inline-block;
-            line-height: 32px;
-            text-align: center;
-            color: #c8d6e8;
-            background-color: transparent;
-            font-size: 32px;
-            vertical-align: middle;
-            margin-right: 20px;
-            &:hover {
-                transform: scale(1.2);
-                color: #8d99ab;
-            }
-        }
-
-        .doc-icon-gitter {
-            margin-right: 0;
-        }
+    .doc-icon-gitter {
+      margin-right: 0;
     }
+  }
 }
 
 @media (max-width: 1140px) {
-    .footer {
-        height: auto;
-    }
+  .footer {
+    height: auto;
+  }
 }
 
 @media (max-width: 1000px) {
-    .footer-social {
-        display: none;
-    }
+  .footer-social {
+    display: none;
+  }
 }
 
 @media (max-width: 768px) {
-    .footer {
-        .footer-main {
-            margin-bottom: 30px;
-        }
+  .footer {
+    .footer-main {
+      margin-bottom: 30px;
     }
+  }
 }
 </style>

+ 137 - 135
docs/.vitepress/vitepress/components/home/home-cards.vue

@@ -8,157 +8,159 @@ const homeLang = computed(() => homeLocale[lang.value])
 </script>
 
 <template>
-    <div class="cards">
-        <ul class="container">
-            <li>
-                <div class="card">
-                    <guide-svg w="40" m="y-12" />
-                    <h3>{{ homeLang['3'] }}</h3>
-                    <p>{{ homeLang['4'] }}</p>
-                    <a :href="`/${lang}/guide/design.html`">{{ homeLang['5'] }}</a>
-                </div>
-            </li>
-            <li>
-                <div class="card">
-                    <component-svg w="40" m="y-12" />
-                    <h3>{{ homeLang['6'] }}</h3>
-                    <p>{{ homeLang['7'] }}</p>
-                    <a :href="`/${lang}/component/layout.html`">
-                        {{ homeLang['5'] }}
-                    </a>
-                </div>
-            </li>
-            <li>
-                <div class="card">
-                    <resource-svg w="40" m="y-12" />
-                    <h3>{{ homeLang['8'] }}</h3>
-                    <p>{{ homeLang['9'] }}</p>
-                    <a :href="`/${lang}/resource/index.html`"> {{ homeLang['5'] }} </a>
-                </div>
-            </li>
-        </ul>
-    </div>
+  <div class="cards">
+    <ul class="container">
+      <li>
+        <div class="card">
+          <guide-svg w="40" m="y-12" />
+          <h3>{{ homeLang['3'] }}</h3>
+          <p>{{ homeLang['4'] }}</p>
+          <a :href="`/${lang}/guide/design.html`">{{ homeLang['5'] }}</a>
+        </div>
+      </li>
+      <li>
+        <div class="card">
+          <component-svg w="40" m="y-12" />
+          <h3>{{ homeLang['6'] }}</h3>
+          <p>{{ homeLang['7'] }}</p>
+          <a :href="`/${lang}/component/layout.html`">
+            {{ homeLang['5'] }}
+          </a>
+        </div>
+      </li>
+      <li>
+        <div class="card">
+          <resource-svg w="40" m="y-12" />
+          <h3>{{ homeLang['8'] }}</h3>
+          <p>{{ homeLang['9'] }}</p>
+          <a :href="`/${lang}/resource/index.html`"> {{ homeLang['5'] }} </a>
+        </div>
+      </li>
+    </ul>
+  </div>
 </template>
 
 <style lang="scss">
 .home-page {
-    .cards {
-        margin: 0 auto 110px;
-        max-width: 900px;
+  .cards {
+    margin: 0 auto 110px;
+    max-width: 900px;
 
-        .container {
-            padding: 0;
-            margin: 0 -11px;
-            width: auto;
-            &::before,
-            &::after {
-                display: table;
-                content: '';
-            }
-            &::after {
-                clear: both;
-            }
-        }
+    .container {
+      padding: 0;
+      margin: 0 -11px;
+      width: auto;
+      &::before,
+      &::after {
+        display: table;
+        content: '';
+      }
+      &::after {
+        clear: both;
+      }
+    }
 
-        li {
-            width: 33.3%;
-            padding: 0 19px;
-            box-sizing: border-box;
-            float: left;
-            list-style: none;
-        }
+    li {
+      width: 33.3%;
+      padding: 0 19px;
+      box-sizing: border-box;
+      float: left;
+      list-style: none;
+    }
 
-        img {
-            width: 160px;
-            height: 120px;
-        }
+    img {
+      width: 160px;
+      height: 120px;
     }
-    .card {
-        height: 430px;
-        width: 100%;
-        background: var(--bg-color);
-        border: 1px solid var(--border-color);
-        border-radius: 5px;
-        box-sizing: border-box;
-        text-align: center;
-        position: relative;
-        transition: all 0.3s ease-in-out;
-        bottom: 0;
+  }
+  .card {
+    height: 430px;
+    width: 100%;
+    background: var(--bg-color);
+    border: 1px solid var(--border-color);
+    border-radius: 5px;
+    box-sizing: border-box;
+    text-align: center;
+    position: relative;
+    transition: all 0.3s ease-in-out;
+    bottom: 0;
 
-        &:hover {
-            box-shadow: 0px 12px 32px 4px rgba(237, 239, 245, 0.24), 0px 8px 20px rgba(237, 239, 245, 0.48);
-        }
+    &:hover {
+      box-shadow: 0px 12px 32px 4px rgba(237, 239, 245, 0.24),
+        0px 8px 20px rgba(237, 239, 245, 0.48);
+    }
 
-        img {
-            margin: 48px auto;
-        }
-        h3 {
-            margin: 0;
-            font-size: 18px;
-            color: var(--el-text-color-primary);
-            font-weight: normal;
-        }
-        p {
-            font-size: 14px;
-            color: #99a9bf;
-            padding: 0 25px;
-            line-height: 20px;
-        }
-        a {
-            height: 53px;
-            line-height: 52px;
-            font-size: 14px;
-            color: var(--brand-color);
-            text-align: center;
-            border: 0;
-            border-top: 1px solid var(--border-color);
-            padding: 0;
-            cursor: pointer;
-            width: 100%;
-            position: absolute;
-            bottom: 0;
-            left: 0;
-            background-color: var(--bg-color);
-            border-radius: 0 0 5px 5px;
-            transition: all 0.3s;
-            text-decoration: none;
-            display: block;
+    img {
+      margin: 48px auto;
+    }
+    h3 {
+      margin: 0;
+      font-size: 18px;
+      color: var(--el-text-color-primary);
+      font-weight: normal;
+    }
+    p {
+      font-size: 14px;
+      color: #99a9bf;
+      padding: 0 25px;
+      line-height: 20px;
+    }
+    a {
+      height: 53px;
+      line-height: 52px;
+      font-size: 14px;
+      color: var(--brand-color);
+      text-align: center;
+      border: 0;
+      border-top: 1px solid var(--border-color);
+      padding: 0;
+      cursor: pointer;
+      width: 100%;
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      background-color: var(--bg-color);
+      border-radius: 0 0 5px 5px;
+      transition: all 0.3s;
+      text-decoration: none;
+      display: block;
 
-            &:hover {
-                color: #fff;
-                background: var(--brand-color);
-            }
-        }
-        &:hover {
-            bottom: 6px;
-            // box-shadow: 0 6px 18px 0 rgba(232, 237, 250, 0.5);
-        }
+      &:hover {
+        color: #fff;
+        background: var(--brand-color);
+      }
+    }
+    &:hover {
+      bottom: 6px;
+      // box-shadow: 0 6px 18px 0 rgba(232, 237, 250, 0.5);
     }
-    @media (max-width: 1140px) {
-        .cards {
-            width: 100%;
-            .container {
-                width: 100%;
-                margin: 0;
-            }
-        }
-        .banner .container {
-            width: 100%;
-            box-sizing: border-box;
-        }
-        .banner img {
-            right: 0;
-        }
+  }
+  @media (max-width: 1140px) {
+    .cards {
+      width: 100%;
+      .container {
+        width: 100%;
+        margin: 0;
+      }
     }
+    .banner .container {
+      width: 100%;
+      box-sizing: border-box;
+    }
+    .banner img {
+      right: 0;
+    }
+  }
 }
 
 .dark {
-    .home-page {
-        .card {
-            &:hover {
-                box-shadow: 0px 12px 32px 4px rgba(9, 11, 16, 0.24), 0px 8px 20px rgba(9, 11, 16, 0.48);
-            }
-        }
+  .home-page {
+    .card {
+      &:hover {
+        box-shadow: 0px 12px 32px 4px rgba(9, 11, 16, 0.24),
+          0px 8px 20px rgba(9, 11, 16, 0.48);
+      }
     }
+  }
 }
 </style>

+ 49 - 49
docs/.vitepress/vitepress/components/home/home-sponsors.vue

@@ -6,70 +6,70 @@ import SponsorList from './sponsor-list.vue'
 </script>
 
 <template>
-    <div class="sponsors-container" m="auto">
-        <SponsorList :sponsors="platinumSponsors" sponsor-type="platinumSponsor" />
-        <SponsorList :sponsors="goldSponsors" sponsor-type="goldSponsor" />
+  <div class="sponsors-container" m="auto">
+    <SponsorList :sponsors="platinumSponsors" sponsor-type="platinumSponsor" />
+    <SponsorList :sponsors="goldSponsors" sponsor-type="goldSponsor" />
 
-        <sponsors-button round />
-    </div>
+    <sponsors-button round />
+  </div>
 </template>
 
 <style lang="scss">
 .home-page {
-    .sponsors-container {
-        margin-top: 72px;
-        .join {
-            text-align: center;
-            margin: 0 0 52px 0;
-        }
+  .sponsors-container {
+    margin-top: 72px;
+    .join {
+      text-align: center;
+      margin: 0 0 52px 0;
     }
+  }
 
-    .sponsor-list {
-        --min-width: 100%;
-        grid-template-columns: repeat(auto-fit, minmax(var(--min-width), 320px));
-        justify-content: center;
+  .sponsor-list {
+    --min-width: 100%;
+    grid-template-columns: repeat(auto-fit, minmax(var(--min-width), 320px));
+    justify-content: center;
 
-        &.platinum {
-            --min-width: 220px;
-        }
-        &.gold {
-            --min-width: 140px;
+    &.platinum {
+      --min-width: 220px;
+    }
+    &.gold {
+      --min-width: 140px;
 
-            @media (max-width: 720px) {
-                --min-width: 160px;
-            }
-        }
+      @media (max-width: 720px) {
+        --min-width: 160px;
+      }
     }
+  }
 
-    .sponsor {
-        margin: 0 20px 10px;
-        height: calc(var(--min-width) / 2);
-        align-items: center;
-        // for dark mode
-        // background-color: var(--bg-color-soft);
+  .sponsor {
+    margin: 0 20px 10px;
+    height: calc(var(--min-width) / 2);
+    align-items: center;
+    // for dark mode
+    // background-color: var(--bg-color-soft);
 
-        .name {
-            font-weight: bold;
-            color: var(--text-color);
-            font-size: 14px;
-        }
+    .name {
+      font-weight: bold;
+      color: var(--text-color);
+      font-size: 14px;
+    }
 
-        img {
-            margin-right: 16px;
-        }
+    img {
+      margin-right: 16px;
+    }
 
-        div {
-            display: flex;
-            flex-direction: column;
-            justify-content: center;
-        }
+    div {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+    }
 
-        p {
-            margin: 0;
-            line-height: 1.8;
-            color: var(--text-color-light);
-            font-size: 12px;
-        }
+    p {
+      margin: 0;
+      line-height: 1.8;
+      color: var(--text-color-light);
+      font-size: 12px;
     }
+  }
 }
 </style>

+ 37 - 25
docs/.vitepress/vitepress/components/home/sponsor-list.vue

@@ -5,11 +5,11 @@ import { useLang } from '../../composables/lang'
 import sponsorLocale from '../../../i18n/component/sponsor.json'
 import { sendEvent } from '../../../config/analytics'
 const onItemClick = (item: any) => {
-    sendEvent('sp_click', item.name, 'index')
+  sendEvent('sp_click', item.name, 'index')
 }
 defineProps({
-    sponsors: Array,
-    sponsorType: String,
+  sponsors: Array,
+  sponsorType: String,
 })
 
 const lang = useLang()
@@ -17,31 +17,43 @@ const sponsorLang = computed(() => sponsorLocale[lang.value])
 
 const langZhCN = 'zh-CN'
 
-const getSponsorName = sponsor => {
-    if (lang.value === langZhCN) {
-        return sponsor.name_cn || sponsor.name
-    }
-    return sponsor.name
+const getSponsorName = (sponsor) => {
+  if (lang.value === langZhCN) {
+    return sponsor.name_cn || sponsor.name
+  }
+  return sponsor.name
 }
-const getSponsorSlogan = sponsor => {
-    if (lang.value === langZhCN) {
-        return sponsor.slogan_cn || sponsor.slogan
-    }
-    return sponsor.slogan
+const getSponsorSlogan = (sponsor) => {
+  if (lang.value === langZhCN) {
+    return sponsor.slogan_cn || sponsor.slogan
+  }
+  return sponsor.slogan
 }
 </script>
 
 <template>
-    <h2 class="text-center mb-4 text-xl">{{ sponsorLang[sponsorType] }}</h2>
-    <div class="grid gap-1 sponsor-list platinum">
-        <a v-for="(sponsor, i) in sponsors" :key="i" :class="['sponsor flex px-4 rounded-md', sponsor.className]" :href="sponsor.url" target="_blank" @click="onItemClick(sponsor)">
-            <img :class="sponsor.isDark && isDark ? 'filter invert' : ''" width="45" :src="sponsor.img" :alt="sponsor.name" />
-            <div>
-                <p>
-                    <span class="name">{{ getSponsorName(sponsor) }}</span>
-                </p>
-                <p>{{ getSponsorSlogan(sponsor) }}</p>
-            </div>
-        </a>
-    </div>
+  <h2 class="text-center mb-4 text-xl">{{ sponsorLang[sponsorType] }}</h2>
+  <div class="grid gap-1 sponsor-list platinum">
+    <a
+      v-for="(sponsor, i) in sponsors"
+      :key="i"
+      :class="['sponsor flex px-4 rounded-md', sponsor.className]"
+      :href="sponsor.url"
+      target="_blank"
+      @click="onItemClick(sponsor)"
+    >
+      <img
+        :class="sponsor.isDark && isDark ? 'filter invert' : ''"
+        width="45"
+        :src="sponsor.img"
+        :alt="sponsor.name"
+      />
+      <div>
+        <p>
+          <span class="name">{{ getSponsorName(sponsor) }}</span>
+        </p>
+        <p>{{ getSponsorSlogan(sponsor) }}</p>
+      </div>
+    </a>
+  </div>
 </template>

+ 74 - 52
docs/.vitepress/vitepress/components/home/svg/component-svg.vue

@@ -1,61 +1,83 @@
 <template>
-    <svg class="component-svg" width="160" height="120" viewBox="0 0 160 120" fill="none" xmlns="http://www.w3.org/2000/svg">
-        <circle cx="80" cy="60" r="60" fill="var(--component-c-0)" />
-        <path d="M37 23C37 20.7909 38.7909 19 41 19H101C103.209 19 105 20.7909 105 23V97C105 99.2091 103.209 101 101 101H45C40.5817 101 37 97.4183 37 93V23Z" fill="var(--component-c-1)" />
-        <path d="M112.048 91H49.0484C49.8484 95.4 46.715 99.5 45.0484 101H107.548C114.348 100.6 113.382 94.1667 112.048 91Z" fill="var(--component-c-2)" />
-        <path d="M121.5 5.5L114.883 19.2063C114.791 19.3981 115.022 19.5824 115.188 19.4494L127 10L121.5 5.5Z" fill="#FFACAD" />
-        <path
-            d="M121.68 21.3628L115.49 27.0342C115.145 27.3502 115.385 27.9246 115.852 27.9022L124.153 27.5051C124.496 27.4887 124.721 27.1389 124.593 26.8199L122.482 21.5456C122.352 21.2211 121.938 21.1266 121.68 21.3628Z"
-            fill="#FFD6D2"
-        />
-        <path d="M37 22C37 19.7909 38.7909 18 41 18H101C103.209 18 105 19.7909 105 22V32H37V22Z" fill="#0077CE" />
-        <path d="M37 22C37 19.7909 38.7909 18 41 18H101C103.209 18 105 19.7909 105 22V30H37V22Z" fill="#20A0FF" />
-        <circle cx="44" cy="25" r="2" fill="#0077CE" />
-        <circle cx="51" cy="25" r="2" fill="#0077CE" />
-        <circle cx="60" cy="25" r="2" fill="#0077CE" />
-        <rect x="45" y="38" width="14" height="4" fill="var(--component-c-3)" />
-        <rect x="45" y="55" width="14" height="4" fill="var(--component-c-3)" />
-        <rect x="45" y="45" width="50" height="4" fill="var(--component-c-4)" />
-        <rect x="45" y="62" width="50" height="4" fill="var(--component-c-4)" />
-        <rect x="61" y="75" width="20" height="6" rx="3" fill="#20A0FF" />
-        <path
-            fill-rule="evenodd"
-            clip-rule="evenodd"
-            d="M87 42C85.8954 42 85 42.8954 85 44V69C85 70.1046 85.8954 71 87 71H96.6154L98 75.5H100.5L99.15 71H132C133.105 71 134 70.1046 134 69V44C134 42.8954 133.105 42 132 42H87Z"
-            fill="var(--component-c-5)"
-        />
-        <path
-            fill-rule="evenodd"
-            clip-rule="evenodd"
-            d="M89 42C87.8954 42 87 42.8954 87 44V69C87 70.1046 87.8954 71 89 71H98.6154L100 75.5L104.154 71H134C135.105 71 136 70.1046 136 69V44C136 42.8954 135.105 42 134 42H89Z"
-            fill="var(--component-c-6)"
-        />
-        <path
-            d="M103.391 61.7402L94.2305 57.1895V56.4473L103.391 51.3984V53.0879L96.584 56.75V56.7988L103.391 60.0605V61.7402ZM114.943 47.873L107.688 65.5098H105.9L113.156 47.873H114.943ZM126.789 57.1699L117.629 61.7207V60.041L124.445 56.8086V56.7402L117.629 53.0781V51.3887L126.789 56.4277V57.1699Z"
-            fill="var(--component-c-7)"
-        />
-    </svg>
+  <svg
+    class="component-svg"
+    width="160"
+    height="120"
+    viewBox="0 0 160 120"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+  >
+    <circle cx="80" cy="60" r="60" fill="var(--component-c-0)" />
+    <path
+      d="M37 23C37 20.7909 38.7909 19 41 19H101C103.209 19 105 20.7909 105 23V97C105 99.2091 103.209 101 101 101H45C40.5817 101 37 97.4183 37 93V23Z"
+      fill="var(--component-c-1)"
+    />
+    <path
+      d="M112.048 91H49.0484C49.8484 95.4 46.715 99.5 45.0484 101H107.548C114.348 100.6 113.382 94.1667 112.048 91Z"
+      fill="var(--component-c-2)"
+    />
+    <path
+      d="M121.5 5.5L114.883 19.2063C114.791 19.3981 115.022 19.5824 115.188 19.4494L127 10L121.5 5.5Z"
+      fill="#FFACAD"
+    />
+    <path
+      d="M121.68 21.3628L115.49 27.0342C115.145 27.3502 115.385 27.9246 115.852 27.9022L124.153 27.5051C124.496 27.4887 124.721 27.1389 124.593 26.8199L122.482 21.5456C122.352 21.2211 121.938 21.1266 121.68 21.3628Z"
+      fill="#FFD6D2"
+    />
+    <path
+      d="M37 22C37 19.7909 38.7909 18 41 18H101C103.209 18 105 19.7909 105 22V32H37V22Z"
+      fill="#0077CE"
+    />
+    <path
+      d="M37 22C37 19.7909 38.7909 18 41 18H101C103.209 18 105 19.7909 105 22V30H37V22Z"
+      fill="#20A0FF"
+    />
+    <circle cx="44" cy="25" r="2" fill="#0077CE" />
+    <circle cx="51" cy="25" r="2" fill="#0077CE" />
+    <circle cx="60" cy="25" r="2" fill="#0077CE" />
+    <rect x="45" y="38" width="14" height="4" fill="var(--component-c-3)" />
+    <rect x="45" y="55" width="14" height="4" fill="var(--component-c-3)" />
+    <rect x="45" y="45" width="50" height="4" fill="var(--component-c-4)" />
+    <rect x="45" y="62" width="50" height="4" fill="var(--component-c-4)" />
+    <rect x="61" y="75" width="20" height="6" rx="3" fill="#20A0FF" />
+    <path
+      fill-rule="evenodd"
+      clip-rule="evenodd"
+      d="M87 42C85.8954 42 85 42.8954 85 44V69C85 70.1046 85.8954 71 87 71H96.6154L98 75.5H100.5L99.15 71H132C133.105 71 134 70.1046 134 69V44C134 42.8954 133.105 42 132 42H87Z"
+      fill="var(--component-c-5)"
+    />
+    <path
+      fill-rule="evenodd"
+      clip-rule="evenodd"
+      d="M89 42C87.8954 42 87 42.8954 87 44V69C87 70.1046 87.8954 71 89 71H98.6154L100 75.5L104.154 71H134C135.105 71 136 70.1046 136 69V44C136 42.8954 135.105 42 134 42H89Z"
+      fill="var(--component-c-6)"
+    />
+    <path
+      d="M103.391 61.7402L94.2305 57.1895V56.4473L103.391 51.3984V53.0879L96.584 56.75V56.7988L103.391 60.0605V61.7402ZM114.943 47.873L107.688 65.5098H105.9L113.156 47.873H114.943ZM126.789 57.1699L117.629 61.7207V60.041L124.445 56.8086V56.7402L117.629 53.0781V51.3887L126.789 56.4277V57.1699Z"
+      fill="var(--component-c-7)"
+    />
+  </svg>
 </template>
 
 <style scoped lang="scss">
 .component-svg {
-    --component-c-0: #eff5fd;
-    --component-c-1: white;
-    --component-c-2: #d9edfe;
-    --component-c-3: var(--component-c-2);
-    --component-c-4: var(--component-c-2);
-    --component-c-5: #6496dc;
-    --component-c-6: #80a8e1;
-    --component-c-7: #dff2ff;
+  --component-c-0: #eff5fd;
+  --component-c-1: white;
+  --component-c-2: #d9edfe;
+  --component-c-3: var(--component-c-2);
+  --component-c-4: var(--component-c-2);
+  --component-c-5: #6496dc;
+  --component-c-6: #80a8e1;
+  --component-c-7: #dff2ff;
 }
 .dark .component-svg {
-    --component-c-0: #272b31;
-    --component-c-1: #273751;
-    --component-c-2: #394c68;
-    --component-c-3: #20a0ff;
-    --component-c-4: #384692;
-    --component-c-5: #263346;
-    --component-c-6: #3a5a88;
-    --component-c-7: white;
+  --component-c-0: #272b31;
+  --component-c-1: #273751;
+  --component-c-2: #394c68;
+  --component-c-3: #20a0ff;
+  --component-c-4: #384692;
+  --component-c-5: #263346;
+  --component-c-6: #3a5a88;
+  --component-c-7: white;
 }
 </style>

文件差异内容过多而无法显示
+ 46 - 36
docs/.vitepress/vitepress/components/home/svg/guide-svg.vue


+ 0 - 0
docs/.vitepress/vitepress/components/home/svg/left-bottom-layer-svg.vue


部分文件因为文件数量过多而无法显示