From c7c1dded8385d0264431282b8761bb9a52cc9a64 Mon Sep 17 00:00:00 2001 From: LYC Date: Wed, 23 Apr 2025 19:21:45 +0800 Subject: [PATCH] init --- .editorconfig | 11 + .env | 50 + .env.prod | 7 + .env.test | 7 + .gitattributes | 13 + .github/ISSUE_TEMPLATE/bug-report_cn.yaml | 90 + .github/ISSUE_TEMPLATE/bug-report_en.yaml | 90 + .../ISSUE_TEMPLATE/feature_request_cn.yaml | 48 + .../ISSUE_TEMPLATE/feature_request_en.yaml | 48 + .github/PULL_REQUEST_TEMPLATE/pr_cn.md | 50 + .github/PULL_REQUEST_TEMPLATE/pr_en.md | 51 + .github/workflows/linter.yml | 30 + .github/workflows/release.yml | 25 + .gitignore | 36 + .npmrc | 4 + .vscode/extensions.json | 19 + .vscode/launch.json | 20 + .vscode/settings.json | 19 + CHANGELOG.md | 2364 +++++ LICENSE | 21 + README.en_US.md | 187 + README.md | 185 + build/config/index.ts | 2 + build/config/proxy.ts | 36 + build/config/time.ts | 12 + build/plugins/html.ts | 13 + build/plugins/index.ts | 24 + build/plugins/router.ts | 55 + build/plugins/unocss.ts | 32 + build/plugins/unplugin.ts | 49 + eslint.config.js | 24 + index.html | 14 + package.json | 113 + packages/axios/package.json | 21 + packages/axios/src/constant.ts | 5 + packages/axios/src/index.ts | 183 + packages/axios/src/options.ts | 48 + packages/axios/src/shared.ts | 28 + packages/axios/src/type.ts | 115 + packages/axios/tsconfig.json | 20 + packages/color/package.json | 16 + packages/color/src/constant/index.ts | 2 + packages/color/src/constant/name.ts | 1579 +++ packages/color/src/constant/palette.ts | 356 + packages/color/src/index.ts | 7 + packages/color/src/palette/antd.ts | 176 + packages/color/src/palette/index.ts | 45 + packages/color/src/palette/recommend.ts | 152 + packages/color/src/shared/colord.ts | 93 + packages/color/src/shared/index.ts | 2 + packages/color/src/shared/name.ts | 49 + packages/color/src/types/index.ts | 58 + packages/color/tsconfig.json | 20 + packages/hooks/package.json | 16 + packages/hooks/src/index.ts | 10 + packages/hooks/src/use-boolean.ts | 31 + packages/hooks/src/use-context.ts | 96 + packages/hooks/src/use-count-down.ts | 49 + packages/hooks/src/use-loading.ts | 16 + packages/hooks/src/use-request.ts | 79 + packages/hooks/src/use-svg-icon-render.ts | 50 + packages/hooks/src/use-table.ts | 152 + packages/hooks/tsconfig.json | 20 + packages/materials/package.json | 20 + packages/materials/src/index.ts | 7 + .../src/libs/admin-layout/index.module.css | 63 + .../libs/admin-layout/index.module.css.d.ts | 17 + .../materials/src/libs/admin-layout/index.ts | 5 + .../materials/src/libs/admin-layout/index.vue | 237 + .../materials/src/libs/admin-layout/shared.ts | 68 + .../materials/src/libs/color-picker/index.ts | 3 + .../materials/src/libs/color-picker/index.vue | 116 + .../src/libs/page-tab/button-tab.vue | 53 + .../src/libs/page-tab/chrome-tab-bg.vue | 31 + .../src/libs/page-tab/chrome-tab.vue | 58 + .../src/libs/page-tab/index.module.css | 97 + .../src/libs/page-tab/index.module.css.d.ts | 14 + packages/materials/src/libs/page-tab/index.ts | 3 + .../materials/src/libs/page-tab/index.vue | 72 + .../materials/src/libs/page-tab/shared.ts | 31 + .../materials/src/libs/page-tab/svg-close.vue | 31 + .../src/libs/simple-scrollbar/index.ts | 3 + .../src/libs/simple-scrollbar/index.vue | 18 + packages/materials/src/types/index.ts | 294 + packages/materials/tsconfig.json | 20 + packages/ofetch/package.json | 15 + packages/ofetch/src/index.ts | 10 + packages/ofetch/tsconfig.json | 20 + packages/scripts/bin.ts | 3 + packages/scripts/package.json | 27 + packages/scripts/src/commands/changelog.ts | 10 + packages/scripts/src/commands/cleanup.ts | 5 + packages/scripts/src/commands/git-commit.ts | 84 + packages/scripts/src/commands/index.ts | 6 + packages/scripts/src/commands/release.ts | 12 + packages/scripts/src/commands/router.ts | 90 + packages/scripts/src/commands/update-pkg.ts | 5 + packages/scripts/src/config/index.ts | 39 + packages/scripts/src/index.ts | 109 + packages/scripts/src/locales/index.ts | 82 + packages/scripts/src/shared/index.ts | 7 + packages/scripts/src/types/index.ts | 31 + packages/scripts/tsconfig.json | 20 + packages/uno-preset/package.json | 12 + packages/uno-preset/src/index.ts | 54 + packages/uno-preset/tsconfig.json | 20 + packages/utils/package.json | 22 + packages/utils/src/color.ts | 252 + packages/utils/src/crypto.ts | 27 + packages/utils/src/index.ts | 5 + packages/utils/src/klona.ts | 3 + packages/utils/src/nanoid.ts | 3 + packages/utils/src/storage.ts | 76 + pnpm-lock.yaml | 8977 +++++++++++++++++ pnpm-workspace.yaml | 2 + public/favicon.svg | 1 + public/logo.png | Bin 0 -> 23414 bytes src/App.vue | 50 + src/assets/imgs/soybean.jpg | Bin 0 -> 114241 bytes src/assets/svg-icon/activity.svg | 1 + src/assets/svg-icon/at-sign.svg | 1 + src/assets/svg-icon/avatar.svg | 1 + src/assets/svg-icon/banner.svg | 1 + src/assets/svg-icon/cast.svg | 1 + src/assets/svg-icon/chrome.svg | 1 + src/assets/svg-icon/copy.svg | 1 + src/assets/svg-icon/custom-icon.svg | 1 + src/assets/svg-icon/empty-data.svg | 1 + src/assets/svg-icon/expectation.svg | 1 + src/assets/svg-icon/heart.svg | 1 + src/assets/svg-icon/logo.svg | 1 + src/assets/svg-icon/network-error.svg | 1 + src/assets/svg-icon/no-icon.svg | 1 + src/assets/svg-icon/no-permission.svg | 1 + src/assets/svg-icon/not-found.svg | 1 + src/assets/svg-icon/service-error.svg | 1 + src/assets/svg-icon/wind.svg | 1 + .../advanced/table-column-setting.vue | 39 + .../advanced/table-header-operation.vue | 71 + src/components/common/app-provider.vue | 34 + src/components/common/dark-mode-container.vue | 17 + src/components/common/exception-base.vue | 43 + src/components/common/full-screen.vue | 22 + src/components/common/lang-switch.vue | 54 + src/components/common/menu-toggler.vue | 48 + src/components/common/pin-toggler.vue | 22 + src/components/common/reload-button.vue | 21 + src/components/common/system-logo.vue | 9 + src/components/common/theme-schema-switch.vue | 56 + src/components/custom/better-scroll.vue | 53 + src/components/custom/button-icon.vue | 49 + src/components/custom/count-to.vue | 88 + src/components/custom/look-forward.vue | 20 + src/components/custom/soybean-avatar.vue | 13 + src/components/custom/svg-icon.vue | 54 + src/components/custom/wave-bg.vue | 59 + src/constants/app.ts | 63 + src/constants/business.ts | 29 + src/constants/common.ts | 8 + src/constants/reg.ts | 25 + src/enum/index.ts | 7 + src/hooks/business/auth.ts | 21 + src/hooks/business/captcha.ts | 71 + src/hooks/common/echarts.ts | 235 + src/hooks/common/form.ts | 97 + src/hooks/common/icon.ts | 10 + src/hooks/common/router.ts | 120 + src/hooks/common/table.ts | 263 + src/layouts/base-layout/index.vue | 148 + src/layouts/blank-layout/index.vue | 13 + src/layouts/context/index.ts | 83 + .../modules/global-breadcrumb/index.vue | 55 + src/layouts/modules/global-content/index.vue | 58 + src/layouts/modules/global-footer/index.vue | 15 + .../global-header/components/theme-button.vue | 21 + .../global-header/components/user-avatar.vue | 58 + src/layouts/modules/global-header/index.vue | 53 + src/layouts/modules/global-logo/index.vue | 27 + .../components/first-level-menu.vue | 108 + src/layouts/modules/global-menu/index.scss | 49 + src/layouts/modules/global-menu/index.vue | 53 + .../global-menu/modules/horizontal-menu.vue | 40 + .../modules/horizontal-mix-menu.vue | 65 + .../modules/reversed-horizontal-mix-menu.vue | 84 + .../global-menu/modules/vertical-menu.vue | 61 + .../global-menu/modules/vertical-mix-menu.vue | 127 + src/layouts/modules/global-sider/index.vue | 33 + .../modules/global-tab/context-menu.vue | 116 + src/layouts/modules/global-tab/index.vue | 166 + .../components/layout-mode-card.vue | 91 + .../theme-drawer/components/setting-item.vue | 24 + src/layouts/modules/theme-drawer/index.vue | 43 + .../theme-drawer/modules/config-operation.vue | 57 + .../theme-drawer/modules/dark-mode.vue | 90 + .../theme-drawer/modules/layout-mode.vue | 83 + .../modules/theme-drawer/modules/page-fun.vue | 136 + .../theme-drawer/modules/theme-color.vue | 56 + src/locales/antd.ts | 8 + src/locales/dayjs.ts | 20 + src/locales/index.ts | 26 + src/locales/langs/en-us.ts | 490 + src/locales/langs/zh-cn.ts | 490 + src/locales/locale.ts | 9 + src/main.ts | 31 + src/plugins/app.ts | 105 + src/plugins/assets.ts | 3 + src/plugins/dayjs.ts | 9 + src/plugins/iconify.ts | 12 + src/plugins/index.ts | 5 + src/plugins/loading.ts | 45 + src/plugins/nprogress.ts | 9 + src/router/elegant/imports.ts | 40 + src/router/elegant/routes.ts | 343 + src/router/elegant/transform.ts | 227 + src/router/guard/index.ts | 15 + src/router/guard/progress.ts | 11 + src/router/guard/route.ts | 192 + src/router/guard/title.ts | 13 + src/router/index.ts | 30 + src/router/routes/builtin.ts | 31 + src/router/routes/index.ts | 193 + src/service/api/auth.ts | 48 + src/service/api/index.ts | 3 + src/service/api/route.ts | 20 + src/service/api/system-manage.ts | 55 + src/service/request/index.ts | 165 + src/service/request/shared.ts | 62 + src/service/request/type.ts | 6 + src/store/index.ts | 12 + src/store/modules/app/index.ts | 169 + src/store/modules/auth/index.ts | 138 + src/store/modules/auth/shared.ts | 12 + src/store/modules/route/index.ts | 348 + src/store/modules/route/shared.ts | 321 + src/store/modules/tab/index.ts | 296 + src/store/modules/tab/shared.ts | 250 + src/store/modules/theme/index.ts | 221 + src/store/modules/theme/shared.ts | 232 + src/store/plugins/index.ts | 22 + src/styles/css/global.css | 13 + src/styles/css/nprogress.css | 83 + src/styles/css/reset.css | 377 + src/styles/css/transition.css | 82 + src/styles/scss/global.scss | 1 + src/styles/scss/scrollbar.scss | 21 + src/theme/settings.ts | 86 + src/theme/vars.ts | 35 + src/typings/antd.d.ts | 40 + src/typings/api.d.ts | 223 + src/typings/app.d.ts | 736 ++ src/typings/common.d.ts | 25 + src/typings/components.d.ts | 87 + src/typings/elegant-router.d.ts | 320 + src/typings/global.d.ts | 17 + src/typings/router.d.ts | 72 + src/typings/storage.d.ts | 39 + src/typings/union-key.d.ts | 157 + src/typings/vite-env.d.ts | 113 + src/utils/agent.ts | 7 + src/utils/common.ts | 58 + src/utils/icon.ts | 9 + src/utils/service.ts | 75 + src/utils/storage.ts | 9 + src/views/_builtin/403/index.vue | 7 + src/views/_builtin/404/index.vue | 7 + src/views/_builtin/500/index.vue | 7 + src/views/_builtin/iframe-page/[url].vue | 25 + src/views/_builtin/login/index.vue | 89 + .../_builtin/login/modules/bind-wechat.vue | 11 + .../_builtin/login/modules/code-login.vue | 66 + .../_builtin/login/modules/pwd-login.vue | 78 + src/views/_builtin/login/modules/register.vue | 86 + .../_builtin/login/modules/reset-pwd.vue | 80 + src/views/about/index.vue | 79 + src/views/function/hide-child/one/index.vue | 7 + src/views/function/hide-child/three/index.vue | 7 + src/views/function/hide-child/two/index.vue | 7 + src/views/function/multi-tab/index.vue | 24 + src/views/function/request/index.vue | 62 + src/views/function/super-page/index.vue | 7 + src/views/function/tab/index.vue | 62 + src/views/function/toggle-auth/index.vue | 97 + src/views/home/index.vue | 33 + src/views/home/modules/card-data.vue | 109 + src/views/home/modules/creativity-banner.vue | 23 + src/views/home/modules/header-banner.vue | 62 + src/views/home/modules/line-chart.vue | 151 + src/views/home/modules/pie-chart.vue | 109 + src/views/home/modules/project-news.vue | 43 + src/views/manage/menu/index.vue | 260 + .../menu/modules/menu-operate-modal.vue | 571 ++ src/views/manage/menu/modules/shared.ts | 79 + src/views/manage/role/index.vue | 173 + .../manage/role/modules/button-auth-modal.vue | 85 + .../manage/role/modules/menu-auth-modal.vue | 140 + .../role/modules/role-operate-drawer.vue | 134 + src/views/manage/role/modules/role-search.vue | 73 + src/views/manage/user-detail/[id].vue | 15 + src/views/manage/user/index.vue | 209 + .../user/modules/user-operate-drawer.vue | 168 + src/views/manage/user/modules/user-search.vue | 120 + src/views/multi-menu/first_child/index.vue | 7 + .../multi-menu/second_child_home/index.vue | 7 + src/views/user-center/index.vue | 7 + tsconfig.json | 26 + uno.config.ts | 30 + vite.config.ts | 51 + 307 files changed, 33250 insertions(+) create mode 100644 .editorconfig create mode 100644 .env create mode 100644 .env.prod create mode 100644 .env.test create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug-report_cn.yaml create mode 100644 .github/ISSUE_TEMPLATE/bug-report_en.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature_request_cn.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature_request_en.yaml create mode 100644 .github/PULL_REQUEST_TEMPLATE/pr_cn.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/pr_en.md create mode 100644 .github/workflows/linter.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.en_US.md create mode 100644 README.md create mode 100644 build/config/index.ts create mode 100644 build/config/proxy.ts create mode 100644 build/config/time.ts create mode 100644 build/plugins/html.ts create mode 100644 build/plugins/index.ts create mode 100644 build/plugins/router.ts create mode 100644 build/plugins/unocss.ts create mode 100644 build/plugins/unplugin.ts create mode 100644 eslint.config.js create mode 100644 index.html create mode 100644 package.json create mode 100644 packages/axios/package.json create mode 100644 packages/axios/src/constant.ts create mode 100644 packages/axios/src/index.ts create mode 100644 packages/axios/src/options.ts create mode 100644 packages/axios/src/shared.ts create mode 100644 packages/axios/src/type.ts create mode 100644 packages/axios/tsconfig.json create mode 100644 packages/color/package.json create mode 100644 packages/color/src/constant/index.ts create mode 100644 packages/color/src/constant/name.ts create mode 100644 packages/color/src/constant/palette.ts create mode 100644 packages/color/src/index.ts create mode 100644 packages/color/src/palette/antd.ts create mode 100644 packages/color/src/palette/index.ts create mode 100644 packages/color/src/palette/recommend.ts create mode 100644 packages/color/src/shared/colord.ts create mode 100644 packages/color/src/shared/index.ts create mode 100644 packages/color/src/shared/name.ts create mode 100644 packages/color/src/types/index.ts create mode 100644 packages/color/tsconfig.json create mode 100644 packages/hooks/package.json create mode 100644 packages/hooks/src/index.ts create mode 100644 packages/hooks/src/use-boolean.ts create mode 100644 packages/hooks/src/use-context.ts create mode 100644 packages/hooks/src/use-count-down.ts create mode 100644 packages/hooks/src/use-loading.ts create mode 100644 packages/hooks/src/use-request.ts create mode 100644 packages/hooks/src/use-svg-icon-render.ts create mode 100644 packages/hooks/src/use-table.ts create mode 100644 packages/hooks/tsconfig.json create mode 100644 packages/materials/package.json create mode 100644 packages/materials/src/index.ts create mode 100644 packages/materials/src/libs/admin-layout/index.module.css create mode 100644 packages/materials/src/libs/admin-layout/index.module.css.d.ts create mode 100644 packages/materials/src/libs/admin-layout/index.ts create mode 100644 packages/materials/src/libs/admin-layout/index.vue create mode 100644 packages/materials/src/libs/admin-layout/shared.ts create mode 100644 packages/materials/src/libs/color-picker/index.ts create mode 100644 packages/materials/src/libs/color-picker/index.vue create mode 100644 packages/materials/src/libs/page-tab/button-tab.vue create mode 100644 packages/materials/src/libs/page-tab/chrome-tab-bg.vue create mode 100644 packages/materials/src/libs/page-tab/chrome-tab.vue create mode 100644 packages/materials/src/libs/page-tab/index.module.css create mode 100644 packages/materials/src/libs/page-tab/index.module.css.d.ts create mode 100644 packages/materials/src/libs/page-tab/index.ts create mode 100644 packages/materials/src/libs/page-tab/index.vue create mode 100644 packages/materials/src/libs/page-tab/shared.ts create mode 100644 packages/materials/src/libs/page-tab/svg-close.vue create mode 100644 packages/materials/src/libs/simple-scrollbar/index.ts create mode 100644 packages/materials/src/libs/simple-scrollbar/index.vue create mode 100644 packages/materials/src/types/index.ts create mode 100644 packages/materials/tsconfig.json create mode 100644 packages/ofetch/package.json create mode 100644 packages/ofetch/src/index.ts create mode 100644 packages/ofetch/tsconfig.json create mode 100644 packages/scripts/bin.ts create mode 100644 packages/scripts/package.json create mode 100644 packages/scripts/src/commands/changelog.ts create mode 100644 packages/scripts/src/commands/cleanup.ts create mode 100644 packages/scripts/src/commands/git-commit.ts create mode 100644 packages/scripts/src/commands/index.ts create mode 100644 packages/scripts/src/commands/release.ts create mode 100644 packages/scripts/src/commands/router.ts create mode 100644 packages/scripts/src/commands/update-pkg.ts create mode 100644 packages/scripts/src/config/index.ts create mode 100644 packages/scripts/src/index.ts create mode 100644 packages/scripts/src/locales/index.ts create mode 100644 packages/scripts/src/shared/index.ts create mode 100644 packages/scripts/src/types/index.ts create mode 100644 packages/scripts/tsconfig.json create mode 100644 packages/uno-preset/package.json create mode 100644 packages/uno-preset/src/index.ts create mode 100644 packages/uno-preset/tsconfig.json create mode 100644 packages/utils/package.json create mode 100644 packages/utils/src/color.ts create mode 100644 packages/utils/src/crypto.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/src/klona.ts create mode 100644 packages/utils/src/nanoid.ts create mode 100644 packages/utils/src/storage.ts create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 public/favicon.svg create mode 100644 public/logo.png create mode 100644 src/App.vue create mode 100644 src/assets/imgs/soybean.jpg create mode 100644 src/assets/svg-icon/activity.svg create mode 100644 src/assets/svg-icon/at-sign.svg create mode 100644 src/assets/svg-icon/avatar.svg create mode 100644 src/assets/svg-icon/banner.svg create mode 100644 src/assets/svg-icon/cast.svg create mode 100644 src/assets/svg-icon/chrome.svg create mode 100644 src/assets/svg-icon/copy.svg create mode 100644 src/assets/svg-icon/custom-icon.svg create mode 100644 src/assets/svg-icon/empty-data.svg create mode 100644 src/assets/svg-icon/expectation.svg create mode 100644 src/assets/svg-icon/heart.svg create mode 100644 src/assets/svg-icon/logo.svg create mode 100644 src/assets/svg-icon/network-error.svg create mode 100644 src/assets/svg-icon/no-icon.svg create mode 100644 src/assets/svg-icon/no-permission.svg create mode 100644 src/assets/svg-icon/not-found.svg create mode 100644 src/assets/svg-icon/service-error.svg create mode 100644 src/assets/svg-icon/wind.svg create mode 100644 src/components/advanced/table-column-setting.vue create mode 100644 src/components/advanced/table-header-operation.vue create mode 100644 src/components/common/app-provider.vue create mode 100644 src/components/common/dark-mode-container.vue create mode 100644 src/components/common/exception-base.vue create mode 100644 src/components/common/full-screen.vue create mode 100644 src/components/common/lang-switch.vue create mode 100644 src/components/common/menu-toggler.vue create mode 100644 src/components/common/pin-toggler.vue create mode 100644 src/components/common/reload-button.vue create mode 100644 src/components/common/system-logo.vue create mode 100644 src/components/common/theme-schema-switch.vue create mode 100644 src/components/custom/better-scroll.vue create mode 100644 src/components/custom/button-icon.vue create mode 100644 src/components/custom/count-to.vue create mode 100644 src/components/custom/look-forward.vue create mode 100644 src/components/custom/soybean-avatar.vue create mode 100644 src/components/custom/svg-icon.vue create mode 100644 src/components/custom/wave-bg.vue create mode 100644 src/constants/app.ts create mode 100644 src/constants/business.ts create mode 100644 src/constants/common.ts create mode 100644 src/constants/reg.ts create mode 100644 src/enum/index.ts create mode 100644 src/hooks/business/auth.ts create mode 100644 src/hooks/business/captcha.ts create mode 100644 src/hooks/common/echarts.ts create mode 100644 src/hooks/common/form.ts create mode 100644 src/hooks/common/icon.ts create mode 100644 src/hooks/common/router.ts create mode 100644 src/hooks/common/table.ts create mode 100644 src/layouts/base-layout/index.vue create mode 100644 src/layouts/blank-layout/index.vue create mode 100644 src/layouts/context/index.ts create mode 100644 src/layouts/modules/global-breadcrumb/index.vue create mode 100644 src/layouts/modules/global-content/index.vue create mode 100644 src/layouts/modules/global-footer/index.vue create mode 100644 src/layouts/modules/global-header/components/theme-button.vue create mode 100644 src/layouts/modules/global-header/components/user-avatar.vue create mode 100644 src/layouts/modules/global-header/index.vue create mode 100644 src/layouts/modules/global-logo/index.vue create mode 100644 src/layouts/modules/global-menu/components/first-level-menu.vue create mode 100644 src/layouts/modules/global-menu/index.scss create mode 100644 src/layouts/modules/global-menu/index.vue create mode 100644 src/layouts/modules/global-menu/modules/horizontal-menu.vue create mode 100644 src/layouts/modules/global-menu/modules/horizontal-mix-menu.vue create mode 100644 src/layouts/modules/global-menu/modules/reversed-horizontal-mix-menu.vue create mode 100644 src/layouts/modules/global-menu/modules/vertical-menu.vue create mode 100644 src/layouts/modules/global-menu/modules/vertical-mix-menu.vue create mode 100644 src/layouts/modules/global-sider/index.vue create mode 100644 src/layouts/modules/global-tab/context-menu.vue create mode 100644 src/layouts/modules/global-tab/index.vue create mode 100644 src/layouts/modules/theme-drawer/components/layout-mode-card.vue create mode 100644 src/layouts/modules/theme-drawer/components/setting-item.vue create mode 100644 src/layouts/modules/theme-drawer/index.vue create mode 100644 src/layouts/modules/theme-drawer/modules/config-operation.vue create mode 100644 src/layouts/modules/theme-drawer/modules/dark-mode.vue create mode 100644 src/layouts/modules/theme-drawer/modules/layout-mode.vue create mode 100644 src/layouts/modules/theme-drawer/modules/page-fun.vue create mode 100644 src/layouts/modules/theme-drawer/modules/theme-color.vue create mode 100644 src/locales/antd.ts create mode 100644 src/locales/dayjs.ts create mode 100644 src/locales/index.ts create mode 100644 src/locales/langs/en-us.ts create mode 100644 src/locales/langs/zh-cn.ts create mode 100644 src/locales/locale.ts create mode 100644 src/main.ts create mode 100644 src/plugins/app.ts create mode 100644 src/plugins/assets.ts create mode 100644 src/plugins/dayjs.ts create mode 100644 src/plugins/iconify.ts create mode 100644 src/plugins/index.ts create mode 100644 src/plugins/loading.ts create mode 100644 src/plugins/nprogress.ts create mode 100644 src/router/elegant/imports.ts create mode 100644 src/router/elegant/routes.ts create mode 100644 src/router/elegant/transform.ts create mode 100644 src/router/guard/index.ts create mode 100644 src/router/guard/progress.ts create mode 100644 src/router/guard/route.ts create mode 100644 src/router/guard/title.ts create mode 100644 src/router/index.ts create mode 100644 src/router/routes/builtin.ts create mode 100644 src/router/routes/index.ts create mode 100644 src/service/api/auth.ts create mode 100644 src/service/api/index.ts create mode 100644 src/service/api/route.ts create mode 100644 src/service/api/system-manage.ts create mode 100644 src/service/request/index.ts create mode 100644 src/service/request/shared.ts create mode 100644 src/service/request/type.ts create mode 100644 src/store/index.ts create mode 100644 src/store/modules/app/index.ts create mode 100644 src/store/modules/auth/index.ts create mode 100644 src/store/modules/auth/shared.ts create mode 100644 src/store/modules/route/index.ts create mode 100644 src/store/modules/route/shared.ts create mode 100644 src/store/modules/tab/index.ts create mode 100644 src/store/modules/tab/shared.ts create mode 100644 src/store/modules/theme/index.ts create mode 100644 src/store/modules/theme/shared.ts create mode 100644 src/store/plugins/index.ts create mode 100644 src/styles/css/global.css create mode 100644 src/styles/css/nprogress.css create mode 100644 src/styles/css/reset.css create mode 100644 src/styles/css/transition.css create mode 100644 src/styles/scss/global.scss create mode 100644 src/styles/scss/scrollbar.scss create mode 100644 src/theme/settings.ts create mode 100644 src/theme/vars.ts create mode 100644 src/typings/antd.d.ts create mode 100644 src/typings/api.d.ts create mode 100644 src/typings/app.d.ts create mode 100644 src/typings/common.d.ts create mode 100644 src/typings/components.d.ts create mode 100644 src/typings/elegant-router.d.ts create mode 100644 src/typings/global.d.ts create mode 100644 src/typings/router.d.ts create mode 100644 src/typings/storage.d.ts create mode 100644 src/typings/union-key.d.ts create mode 100644 src/typings/vite-env.d.ts create mode 100644 src/utils/agent.ts create mode 100644 src/utils/common.ts create mode 100644 src/utils/icon.ts create mode 100644 src/utils/service.ts create mode 100644 src/utils/storage.ts create mode 100644 src/views/_builtin/403/index.vue create mode 100644 src/views/_builtin/404/index.vue create mode 100644 src/views/_builtin/500/index.vue create mode 100644 src/views/_builtin/iframe-page/[url].vue create mode 100644 src/views/_builtin/login/index.vue create mode 100644 src/views/_builtin/login/modules/bind-wechat.vue create mode 100644 src/views/_builtin/login/modules/code-login.vue create mode 100644 src/views/_builtin/login/modules/pwd-login.vue create mode 100644 src/views/_builtin/login/modules/register.vue create mode 100644 src/views/_builtin/login/modules/reset-pwd.vue create mode 100644 src/views/about/index.vue create mode 100644 src/views/function/hide-child/one/index.vue create mode 100644 src/views/function/hide-child/three/index.vue create mode 100644 src/views/function/hide-child/two/index.vue create mode 100644 src/views/function/multi-tab/index.vue create mode 100644 src/views/function/request/index.vue create mode 100644 src/views/function/super-page/index.vue create mode 100644 src/views/function/tab/index.vue create mode 100644 src/views/function/toggle-auth/index.vue create mode 100644 src/views/home/index.vue create mode 100644 src/views/home/modules/card-data.vue create mode 100644 src/views/home/modules/creativity-banner.vue create mode 100644 src/views/home/modules/header-banner.vue create mode 100644 src/views/home/modules/line-chart.vue create mode 100644 src/views/home/modules/pie-chart.vue create mode 100644 src/views/home/modules/project-news.vue create mode 100644 src/views/manage/menu/index.vue create mode 100644 src/views/manage/menu/modules/menu-operate-modal.vue create mode 100644 src/views/manage/menu/modules/shared.ts create mode 100644 src/views/manage/role/index.vue create mode 100644 src/views/manage/role/modules/button-auth-modal.vue create mode 100644 src/views/manage/role/modules/menu-auth-modal.vue create mode 100644 src/views/manage/role/modules/role-operate-drawer.vue create mode 100644 src/views/manage/role/modules/role-search.vue create mode 100644 src/views/manage/user-detail/[id].vue create mode 100644 src/views/manage/user/index.vue create mode 100644 src/views/manage/user/modules/user-operate-drawer.vue create mode 100644 src/views/manage/user/modules/user-search.vue create mode 100644 src/views/multi-menu/first_child/index.vue create mode 100644 src/views/multi-menu/second_child_home/index.vue create mode 100644 src/views/user-center/index.vue create mode 100644 tsconfig.json create mode 100644 uno.config.ts create mode 100644 vite.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0552777 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# Editor configuration, see http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.env b/.env new file mode 100644 index 0000000..092304b --- /dev/null +++ b/.env @@ -0,0 +1,50 @@ +# the base url of the application, the default is "/" +# if use a sub directory, it must be end with "/", like "/admin/" but not "/admin" +VITE_BASE_URL=/ + +VITE_APP_TITLE=SoybeanAdmin + +VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template + +# the prefix of the icon name +VITE_ICON_PREFIX=icon + +# the prefix of the local svg icon component, must include VITE_ICON_PREFIX +# format {VITE_ICON_PREFIX}-{local icon name} +VITE_ICON_LOCAL_PREFIX=icon-local + +# auth route mode: static | dynamic +VITE_AUTH_ROUTE_MODE=static + +# static auth route home +VITE_ROUTE_HOME=home + +# default menu icon +VITE_MENU_ICON=mdi:menu + +# whether to enable http proxy when is dev mode +VITE_HTTP_PROXY=N + +# vue-router mode: hash | history | memory +VITE_ROUTER_HISTORY_MODE=history + +# success code of backend service, when the code is received, the request is successful +VITE_SERVICE_SUCCESS_CODE=0000 + +# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page +VITE_SERVICE_LOGOUT_CODES=8888,8889 + +# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal +VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778 + +# token expired codes of backend service, when the code is received, it will refresh the token and resend the request +VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333 + +# when the route mode is static, the defined super role +VITE_STATIC_SUPER_ROLE=R_SUPER + +# Used to differentiate storage across different domains +VITE_STORAGE_PREFIX=SOY_ + +# used to control whether the program automatically detects updates +VITE_AUTOMATICALLY_DETECT_UPDATE=Y diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..f567764 --- /dev/null +++ b/.env.prod @@ -0,0 +1,7 @@ +# backend service base url, prod environment +VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default + +# other backend service base url, prod environment +VITE_OTHER_SERVICE_BASE_URL= `{ + "demo": "http://localhost:9529" +}` diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..dd18d7b --- /dev/null +++ b/.env.test @@ -0,0 +1,7 @@ +# backend service base url, test environment +VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default + +# other backend service base url, test environment +VITE_OTHER_SERVICE_BASE_URL= `{ + "demo": "http://localhost:9528" +}` diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9553ccb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +"*.vue" eol=lf +"*.js" eol=lf +"*.ts" eol=lf +"*.jsx" eol=lf +"*.tsx" eol=lf +"*.mjs" eol=lf +"*.json" eol=lf +"*.html" eol=lf +"*.css" eol=lf +"*.scss" eol=lf +"*.md" eol=lf +"*.yaml" eol=lf +"*.yml" eol=lf diff --git a/.github/ISSUE_TEMPLATE/bug-report_cn.yaml b/.github/ISSUE_TEMPLATE/bug-report_cn.yaml new file mode 100644 index 0000000..b1de7e6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report_cn.yaml @@ -0,0 +1,90 @@ +name: 🐞 Bug提交 +description: 在使用软件或功能的过程中遇到了错误 +title: '[Bug]: ' +labels: [ "bug?" ] + +body: + - type: markdown + attributes: + value: | + ## 请按照以下要求进行提交 + ### 1. 提交后需要指定标签和截止时间。 + --- + + - type: markdown + attributes: + value: | + ## 环境信息 + 请根据实际使用环境修改以下信息。 + + - type: input + id: env-program-ver + attributes: + label: 软件版本 + validations: + required: true + + - type: dropdown + id: env-vm-ver + attributes: + label: 运行环境 + description: 选择运行软件的系统版本 + options: + - Windows (64) + - Windows (32/x84) + - MacOS + - Linux + - Ubuntu + - CentOS + - ArchLinux + - UNIX (Android) + - 其它(请在下方说明) + validations: + required: true + + - type: dropdown + id: env-vm-arch + attributes: + label: 运行架构 + description: (可选) 选择运行软件的系统架构 + options: + - AMD64 + - x86 + - ARM [32] (别名:AArch32 / ARMv7) + - ARM [64] (别名:AArch64 / ARMv8) + - 其它 + + - type: textarea + id: reproduce-steps + attributes: + label: 重现步骤 + description: | + 我们需要执行哪些操作才能让 bug 出现? + 简洁清晰的重现步骤能够帮助我们更迅速地定位问题所在。 + validations: + required: true + + - type: textarea + id: expected + attributes: + label: 期望的结果是什么? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: 实际的结果是什么? + validations: + required: true + + - type: textarea + id: logging + attributes: + label: 日志记录(可选) + render: golang + + - type: textarea + id: extra-desc + attributes: + label: 补充说明(可选) diff --git a/.github/ISSUE_TEMPLATE/bug-report_en.yaml b/.github/ISSUE_TEMPLATE/bug-report_en.yaml new file mode 100644 index 0000000..a3a2f12 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report_en.yaml @@ -0,0 +1,90 @@ +name: 🐞 Bug Report +description: Encountered an error while using the software or feature +title: '[Bug]: ' +labels: [ "bug?" ] + +body: + - type: markdown + attributes: + value: | + ## Please submit according to the following requirements + ### 1. After submission, you need to specify the label and deadline. + --- + + - type: markdown + attributes: + value: | + ## Environment Information + Please modify the following information according to the actual usage environment. + + - type: input + id: env-program-ver + attributes: + label: Software Version + validations: + required: true + + - type: dropdown + id: env-vm-ver + attributes: + label: Operating Environment + description: Select the system version on which the software is running + options: + - Windows (64) + - Windows (32/x84) + - MacOS + - Linux + - Ubuntu + - CentOS + - ArchLinux + - UNIX (Android) + - Other (please specify below) + validations: + required: true + + - type: dropdown + id: env-vm-arch + attributes: + label: Operating Architecture + description: (Optional) Select the system architecture on which the software is running + options: + - AMD64 + - x86 + - ARM [32] (Alias:AArch32 / ARMv7) + - ARM [64] (Alias:AArch64 / ARMv8) + - Other + + - type: textarea + id: reproduce-steps + attributes: + label: Reproduce Steps + description: | + What operations do we need to perform to make the bug appear? + The concise and clear reproduction steps can help us locate the problem more quickly. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What is the expected result? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: What is the actual result? + validations: + required: true + + - type: textarea + id: logging + attributes: + label: Logging (Optional) + render: golang + + - type: textarea + id: extra-desc + attributes: + label: Additional Description (Optional) diff --git a/.github/ISSUE_TEMPLATE/feature_request_cn.yaml b/.github/ISSUE_TEMPLATE/feature_request_cn.yaml new file mode 100644 index 0000000..c98162f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request_cn.yaml @@ -0,0 +1,48 @@ +--- +name: 🚀 功能请求 +description: 提出一个想法以帮助我们改进W&B +title: "[功能]: " +labels: + - "功能请求" + +body: + - type: markdown + attributes: + value: | + **感谢 :heart: 您花时间填写此功能请求报告!** + 我们恳请您搜索看看您的功能是否[已经存在](https://github.com/soybeanjs/soybean-admin/issues?q=is%3Aissue+sort%3Acreated-desc+)。 + + 我们也很乐意接受用户的贡献。有关更多详细信息,请参阅[此处](https://github.com/soybeanjs/soybean-admin/blob/main/README.zh_CN.md#%E5%A6%82%E4%BD%95%E8%B4%A1%E7%8C%AE)。 + + - type: textarea + attributes: + label: 描述 + description: | + 对您感兴趣的功能的清晰简洁的描述。 + validations: + required: true + + - type: textarea + attributes: + label: 建议的解决方案 + description: | + 描述您想要的解决方案。对您希望发生的事情的清晰简洁的描述。 + validations: + required: true + + - type: textarea + attributes: + label: 替代方案 + description: | + 描述您考虑过的替代方案。 + 对您考虑过的任何替代解决方案或功能的清晰简洁的描述。 + validations: + required: false + + - type: textarea + attributes: + label: 额外的上下文 + description: | + 在此处添加有关问题的其他上下文。 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request_en.yaml b/.github/ISSUE_TEMPLATE/feature_request_en.yaml new file mode 100644 index 0000000..07fc41c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request_en.yaml @@ -0,0 +1,48 @@ +--- +name: 🚀 Feature Request +description: Suggest an idea to help us improve W&B +title: "[Feature]: " +labels: + - "feature_request" + +body: + - type: markdown + attributes: + value: | + **Thanks :heart: for taking the time to fill out this feature request report!** + We kindly ask that you search to see if an issue [already exists](https://github.com/soybeanjs/soybean-admin/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature. + + We are also happy to accept contributions from our users. For more details see [here](https://github.com/soybeanjs/soybean-admin/blob/main/README.md#how-to-contribute). + + - type: textarea + attributes: + label: Description + description: | + A clear and concise description of the feature you're interested in. + validations: + required: true + + - type: textarea + attributes: + label: Suggested Solution + description: | + Describe the solution you'd like. A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + attributes: + label: Alternatives + description: | + Describe alternatives you've considered. + A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + + - type: textarea + attributes: + label: Additional Context + description: | + Add any other context about the problem here. + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE/pr_cn.md b/.github/PULL_REQUEST_TEMPLATE/pr_cn.md new file mode 100644 index 0000000..d3b86ad --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pr_cn.md @@ -0,0 +1,50 @@ +首先,感谢你的贡献! 😄 + +新特性请提交至 feature 分支,其余可提交至 main 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~ + +[[English Template / 英文模板](./pr_en.md)] + +### 这个变动的性质是 + +- [ ] 新特性提交 +- [ ] 日常 bug 修复 +- [ ] 站点、文档改进 +- [ ] 组件样式改进 +- [ ] TypeScript 定义更新 +- [ ] 重构 +- [ ] 代码风格优化 +- [ ] 分支合并 +- [ ] 其他改动(是关于什么的改动?) + +### 需求背景 + +> 1. 描述相关需求的来源。 +> 2. 要解决的问题。 +> 3. 相关的 issue 讨论链接。 + +### 实现方案和 API(非新功能可选) + +> 1. 基本的解决思路和其他可选方案。 +> 2. 列出最终的 API 实现和用法。 +> 3. 涉及 UI/交互变动需要有截图或 GIF。 + +### 对用户的影响和可能的风险(非新功能可选) + +> 1. 这个改动对用户端是否有影响?影响的方面有哪些? +> 2. 是否有可能隐含的 break change 和其他风险? + +### Changelog 描述(非新功能可选) + +> 1. 英文描述 +> 2. 中文描述(可选) + +### 请求合并前的自查清单 + +- [ ] 文档已补充或无须补充 +- [ ] 代码演示已提供或无须提供 +- [ ] TypeScript 定义已补充或无须补充 +- [ ] Changelog 已提供或无须提供 + +### 后续计划(非新功能可选) + +> 如果这个提交后面还有相关的其他提交和跟进信息,可以写在这里。 diff --git a/.github/PULL_REQUEST_TEMPLATE/pr_en.md b/.github/PULL_REQUEST_TEMPLATE/pr_en.md new file mode 100644 index 0000000..06560ca --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pr_en.md @@ -0,0 +1,51 @@ +First of all, thank you for your contribution! 😄 + +New feature please send pull request to feature branch, and rest to main branch. Pull request will be merged after one of collaborators approve. Please makes sure that these form are filled before submitting your pull request, thank you! + +[[中文版模板 / Chinese template](./pr_cn.md)] + +### This is a ... + +- [ ] New feature +- [ ] Bug fix +- [ ] Site / document update +- [ ] Component style update +- [ ] TypeScript definition update +- [ ] Refactoring +- [ ] Code style optimization +- [ ] Branch merge +- [ ] Other (about what?) + +### What's the background? + +> 1. Describe the source of requirement. +> 2. Resolve what problem. +> 3. Related issue link. + +### API Realization (Optional if not new feature) + +> 1. Basic thought of solution and other optional proposal. +> 2. List final API realization and usage sample. +> 3. GIF or snapshot should be provided if includes UI/interactive modification. + +### What's the effect? (Optional if not new feature) + +> 1. Does this PR affect user? Which part will be affected? +> 2. What will say in changelog? +> 3. Does this PR contains potential break change or other risk? + +### Changelog description (Optional if not new feature) + +> 1. English description +> 2. Chinese description (optional) + +### Self Check before Merge + +- [ ] Doc is updated/provided or not needed +- [ ] Demo is updated/provided or not needed +- [ ] TypeScript definition is updated/provided or not needed +- [ ] Changelog is provided or not needed + +### Additional Plan? (Optional if not new feature) + +> If this PR related with other PR or following info. You can type here. diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000..450ec86 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,30 @@ +--- +name: Lint Code + +permissions: + contents: write + +on: + pull_request: + branches: [main] + +jobs: + lint: + name: Lint All Code + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Lint Code Base + uses: github/super-linter@v4 + env: + VALIDATE_ALL_CODEBASE: false + DEFAULT_BRANCH: main + # To change branch master or main + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FILTER_REGEX_EXCLUDE: (docs|.github) + VALIDATE_MARKDOWN: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0bf7c92 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: Release + +permissions: + contents: write + +on: + push: + tags: + - "v*" + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v3 + with: + node-version: 18.x + + - run: npx githublogen + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..baa93f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +!.vscode/settings.json +!.vscode/launch.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +package-lock.json +yarn.lock + +.VSCodeCounter +**/.vitepress/cache diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..dfc2d68 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +registry=https://registry.npmmirror.com/ +shamefully-hoist=true +ignore-workspace-root-check=true +link-workspace-packages=true diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..00f2223 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,19 @@ +{ + "recommendations": [ + "afzalsayed96.icones", + "antfu.iconify", + "antfu.unocss", + "dbaeumer.vscode-eslint", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "lokalise.i18n-ally", + "mhutchie.git-graph", + "mikestead.dotenv", + "naumovs.color-highlight", + "pkief.material-icon-theme", + "sdras.vue-vscode-snippets", + "vue.volar", + "whtouche.vscode-js-console-utils", + "zhuangtongfa.material-theme" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f6f291d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Vue Debugger", + "url": "http://localhost:9527", + "webRoot": "${workspaceFolder}" + }, + { + "type": "node", + "request": "launch", + "name": "TS Debugger", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/tsx", + "skipFiles": ["/**", "${workspaceFolder}/node_modules/**"], + "program": "${file}" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4fd9e52 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.organizeImports": "never" + }, + "eslint.useFlatConfig": true, + "editor.formatOnSave": false, + "eslint.validate": ["html", "css", "scss", "json", "jsonc"], + "i18n-ally.displayLanguage": "zh-cn", + "i18n-ally.enabledParsers": ["ts"], + "i18n-ally.enabledFrameworks": ["vue"], + "i18n-ally.editor.preferEditor": true, + "i18n-ally.keystyle": "nested", + "i18n-ally.localesPaths": ["src/locales/langs"], + "prettier.enable": false, + "typescript.tsdk": "node_modules/typescript/lib", + "unocss.root": ["./"], + "vue.server.hybridMode": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..45fc43d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2364 @@ +# Changelog + + +## [v1.3.11](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.10...v1.3.11) (2025-01-19) + +###    🐞 Bug Fixes + +- **projects**: + - fix select in theme setting drawer  -  by @soybeanjs [(00ab5)](https://github.com/soybeanjs/soybean-admin-antd/commit/00ab5df) + - fix login success notification  -  by @soybeanjs [(b955f)](https://github.com/soybeanjs/soybean-admin-antd/commit/b955f6f) + - fix update notifications  -  by @soybeanjs [(42586)](https://github.com/soybeanjs/soybean-admin-antd/commit/4258650) + +###    📖 Documentation + +- **projects**: update README  -  by @soybeanjs [(cc3ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc3ae57) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(37c29)](https://github.com/soybeanjs/soybean-admin-antd/commit/37c2930) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.10](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.9...v1.3.10) (2024-12-16) + +###    🚨 Breaking Changes + +- **packages**: + - modify request retry times to 0  -  by @soybeanjs [(d87e9)](https://github.com/soybeanjs/soybean-admin-antd/commit/d87e9c16) +- **projects**: + - refactor global menu & support `reversed-horizontal-mix-menu`. close #365  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/365 [(087e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/087e5326) + - don't reset active menu of vertical-mix layout when it is mixSiderFixed  -  by @soybeanjs [(939c5)](https://github.com/soybeanjs/soybean-admin-antd/commit/939c512f) + - refactor global menu & support reversed-horizontal-mix-menu  -  by @soybeanjs [(2244f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2244f0c7) + - update scss config  -  by @soybeanjs [(24e9e)](https://github.com/soybeanjs/soybean-admin-antd/commit/24e9e57a) + - update scss config  -  by @soybeanjs [(b1cda)](https://github.com/soybeanjs/soybean-admin-antd/commit/b1cda6a1) + - refactor route cache & support reset route cache strategy  -  by @soybeanjs [(b667e)](https://github.com/soybeanjs/soybean-admin-antd/commit/b667eab7) + - refactor route cache & support reset route cache strategy  -  by @soybeanjs [(76270)](https://github.com/soybeanjs/soybean-admin-antd/commit/762704ae) + +###    🚀 Features + +- setting 页面新增 是否显示footer的开关  -  by **zuihou** [(d064f)](https://github.com/soybeanjs/soybean-admin-antd/commit/d064f628) +- 新增 affix 属性,用于将其固定在tab卡  -  by **zuihou** [(e772f)](https://github.com/soybeanjs/soybean-admin-antd/commit/e772ff05) +- internationalized menu search  -  by **Kori** [(9e115)](https://github.com/soybeanjs/soybean-admin-antd/commit/9e115dae) +- **auth**: + - 防止多次刷新token  -  by **liwei** [(0eaa3)](https://github.com/soybeanjs/soybean-admin-antd/commit/0eaa327d) +- **component**: + - 增加剪贴板示例  -  by **Yanbowen** [(f1cd9)](https://github.com/soybeanjs/soybean-admin-antd/commit/f1cd9955) +- **components**: + - 添加主题配置抽屉,添加暗黑主题  -  by **Soybean** [(a8759)](https://github.com/soybeanjs/soybean-admin-antd/commit/a87593f5) + - 添加面包屑  -  by **Soybean** [(c1cdc)](https://github.com/soybeanjs/soybean-admin-antd/commit/c1cdc3a9) + - 添加vertical-mix的导航模式下的菜单  -  by **Soybean** [(f24ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/f24ec1c5) + - 添加图片验证码  -  by **Soybean** [(336c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/336c7766) + - 添加多页签Tab点击后自动往中间滚动  -  by **Soybean** [(8ce62)](https://github.com/soybeanjs/soybean-admin-antd/commit/8ce627a3) + - svgIcon,添加type,调整size方案  -  by **Lsq128** [(ce4e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/ce4e039f) + - Add tree related component instances  -  by **small_happy** [(d203a)](https://github.com/soybeanjs/soybean-admin-antd/commit/d203a358) + - Add routing data related to tree components and page display optimization  -  by **small_happy** [(a0f55)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0f55aca) + - enhance the custom strength of the 'TableHeaderOperation' component  -  by **tnt group** [(fdf64)](https://github.com/soybeanjs/soybean-admin-antd/commit/fdf64f71) + - add GlobalSearch components  -  by **燕博文** [(9ea87)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ea87891) +- **hooks**: + - add useNaiveTable  -  by **Soybean** [(cc13f)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc13fcc8) + - add useHookTable  -  by @soybeanjs [(b3ae7)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3ae7605) + - add @sa/hooks  -  by @soybeanjs [(7677a)](https://github.com/soybeanjs/soybean-admin-antd/commit/7677af5e) + - add use-echarts  -  by @soybeanjs [(726ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/726abe42) + - add use-echarts  -  by @soybeanjs [(ada3f)](https://github.com/soybeanjs/soybean-admin-antd/commit/ada3f984) + - @sa/hooks: add useTable  -  by @soybeanjs [(348b4)](https://github.com/soybeanjs/soybean-admin-antd/commit/348b4f63) + - deleting the route export of useRoutePush, use vue-router  -  by @paynezhuang [(c6648)](https://github.com/soybeanjs/soybean-admin-antd/commit/c6648b6c) + - add state hooks: useRef, useState, useSignal  -  by @soybeanjs [(09f64)](https://github.com/soybeanjs/soybean-admin-antd/commit/09f64646) + - add setOptions for useEcharts  -  by @soybeanjs [(e4d53)](https://github.com/soybeanjs/soybean-admin-antd/commit/e4d53aa7) + - add setOptions for useEcharts  -  by @soybeanjs [(40ceb)](https://github.com/soybeanjs/soybean-admin-antd/commit/40cebabd) +- **layouts**: + - 添加侧边栏/头部的反转模式来增加对比度  -  by **元家怿** [(3c8dd)](https://github.com/soybeanjs/soybean-admin-antd/commit/3c8dd772) + - 添加侧边栏/头部的反转模式来增加对比度  -  by **元家怿** [(861c8)](https://github.com/soybeanjs/soybean-admin-antd/commit/861c8b98) +- **packages**: + - @sa/scripts: add new commit type `optimize` and commit scope `packages`  -  by @soybeanjs [(fbc2e)](https://github.com/soybeanjs/soybean-admin-antd/commit/fbc2e61f) + - @sa/scripts: add new commit type optimize and commit scope packages  -  by @soybeanjs [(ee111)](https://github.com/soybeanjs/soybean-admin-antd/commit/ee1119e1) + - `@sa/scripts`: command `gitCommit` support chinese  -  by @mmdapl in https://github.com/soybeanjs/soybean-admin-antd/issues/548 [(06971)](https://github.com/soybeanjs/soybean-admin-antd/commit/06971f39) + - @sa/axios: replace CancelTokenSource by AbortController. close #530, close #532  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/530 and https://github.com/soybeanjs/soybean-admin-antd/issues/532 [(527fd)](https://github.com/soybeanjs/soybean-admin-antd/commit/527fd79d) + - @sa/scripts: add ignore pattern list for command `gitCommitVerify`. close #504  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/504 [(958d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/958d0baf) + - @sa/axios: add response to flatRequest when success  -  by @soybeanjs [(c4e16)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4e16102) + - @sa/scripts: command gitCommit support Chinese  -  by @soybeanjs [(8eb1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/8eb1d5ed) + - @sa/axios: replace CancelTokenSource by AbortController  -  by @soybeanjs [(91296)](https://github.com/soybeanjs/soybean-admin-antd/commit/91296015) + - @sa/scripts: add ignore pattern list for command gitCommitVerify  -  by @soybeanjs [(5a950)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a950264) + - @sa/scripts: add more commit types according to Apache specifications  -  by @soybeanjs [(5a020)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a020dd6) + - @sa/axios: add response to flatRequest when success  -  by @soybeanjs [(aace8)](https://github.com/soybeanjs/soybean-admin-antd/commit/aace819d) + - add subpackage `@sa/alova`  -  by @JOU-amjs in https://github.com/soybeanjs/soybean-admin-antd/issues/640 [(2072f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2072f585) + - optimistic subpackage `@sa/alova`  -  by @JOU-amjs in https://github.com/soybeanjs/soybean-admin-antd/issues/646 [(4b3ac)](https://github.com/soybeanjs/soybean-admin-antd/commit/4b3ac11b) +- **projects**: + - 项目初始化搭建,集成eslint规范,集成代码提交规范  -  by **Soybean** [(6754d)](https://github.com/soybeanjs/soybean-admin-antd/commit/6754da4d) + - 新增主题配置  -  by **Soybean** [(ed67b)](https://github.com/soybeanjs/soybean-admin-antd/commit/ed67b797) + - 布局调整  -  by **Soybean** [(eda87)](https://github.com/soybeanjs/soybean-admin-antd/commit/eda87f04) + - 新增主题颜色配置  -  by **Soybean** [(d9349)](https://github.com/soybeanjs/soybean-admin-antd/commit/d93493b9) + - 新增导航模式配置  -  by **Soybean** [(49c2d)](https://github.com/soybeanjs/soybean-admin-antd/commit/49c2dc4f) + - 导航栏模式配置:界面实现及主题配置布局调整  -  by **Soybean** [(f0021)](https://github.com/soybeanjs/soybean-admin-antd/commit/f002124e) + - 新增主题配置:页面功能  -  by **Soybean** [(8601c)](https://github.com/soybeanjs/soybean-admin-antd/commit/8601ce2e) + - 主题配置:页面功能和页面显示  -  by **Soybean** [(a0392)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0392b3d) + - 添加全屏显示  -  by **Soybean** [(0a171)](https://github.com/soybeanjs/soybean-admin-antd/commit/0a1711d5) + - 四种基本布局完成  -  by **Soybean** [(86d4a)](https://github.com/soybeanjs/soybean-admin-antd/commit/86d4a207) + - 添加固定路由  -  by **Soybean** [(ff4a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff4a09c4) + - 添加exception页面:403,404,500  -  by **Soybean** [(d012c)](https://github.com/soybeanjs/soybean-admin-antd/commit/d012c4ec) + - 首页更新  -  by **Soybean** [(5c010)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c010063) + - 登录页面实现  -  by **Soybean** [(f1e7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/f1e7cf60) + - 菜单数据及组件接入  -  by **Soybean** [(3226a)](https://github.com/soybeanjs/soybean-admin-antd/commit/3226a724) + - 头部添加菜单折叠按钮和github地址  -  by **Soybean** [(3ec1f)](https://github.com/soybeanjs/soybean-admin-antd/commit/3ec1fc8f) + - 添加multiTab标签页  -  by **Soybean** [(eec0b)](https://github.com/soybeanjs/soybean-admin-antd/commit/eec0b36f) + - 多页签绑定路由  -  by **Soybean** [(f29bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/f29bc05d) + - 添加reload context  -  by **Soybean** [(03ebd)](https://github.com/soybeanjs/soybean-admin-antd/commit/03ebd49c) + - 添加多页签风格:按钮和浏览器两种风格  -  by **Soybean** [(3cfa0)](https://github.com/soybeanjs/soybean-admin-antd/commit/3cfa0f10) + - 添加多页签右键菜单  -  by **Soybean** [(d6f52)](https://github.com/soybeanjs/soybean-admin-antd/commit/d6f5237c) + - 添加环境文件env对应的类型  -  by **Soybean** [(4f050)](https://github.com/soybeanjs/soybean-admin-antd/commit/4f050953) + - 新增顶部菜单  -  by **Soybean** [(221d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/221d2cc0) + - vertical-mix的导航模式的二级菜单显示  -  by **Soybean** [(736f3)](https://github.com/soybeanjs/soybean-admin-antd/commit/736f3146) + - 添加多级菜单页面  -  by **Soybean** [(3f49d)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f49d6db) + - 添加svg logo自适应主题颜色  -  by **Soybean** [(e1e55)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1e5579e) + - 添加项目配置拷贝  -  by **Soybean** [(2d9d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d9d5c03) + - 新增文档页面  -  by **Soybean** [(7654b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7654b2ad) + - 工作台页面布局  -  by **Soybean** [(4c855)](https://github.com/soybeanjs/soybean-admin-antd/commit/4c85569b) + - 分析页更新,添加关于页面  -  by **Soybean** [(8e182)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e182181) + - 添加富文本和markdown编辑器插件及示例页面  -  by **Soybean** [(60c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/60c20647) + - 添加百度地图插件  -  by **Soybean** [(6abe0)](https://github.com/soybeanjs/soybean-admin-antd/commit/6abe094f) + - 新增高德地图插件  -  by **Soybean** [(ea82e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ea82edc1) + - 新增腾讯地图插件  -  by **Soybean** [(3f02c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f02c215) + - 新增视频插件  -  by **Soybean** [(6a692)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a692d4f) + - 工作台页面:添加技术栈官网链接  -  by **Soybean** [(364c6)](https://github.com/soybeanjs/soybean-admin-antd/commit/364c64b4) + - 添加判断是否是移动端的hooks  -  by **Soybean** [(0a9fb)](https://github.com/soybeanjs/soybean-admin-antd/commit/0a9fba90) + - 添加swiper插件  -  by **Soybean** [(27f60)](https://github.com/soybeanjs/soybean-admin-antd/commit/27f600c4) + - 增加Icon以及打印功能示例  -  by **Yanbowen** [(d5bce)](https://github.com/soybeanjs/soybean-admin-antd/commit/d5bce264) + - 新增多页签缓存功能  -  by **Soybean** [(d86f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/d86f891c) + - 新增网址导航页面  -  by **Soybean** [(32aa5)](https://github.com/soybeanjs/soybean-admin-antd/commit/32aa5ee7) + - 新增组件页面:按钮、卡片示例  -  by **Soybean** [(bdc39)](https://github.com/soybeanjs/soybean-admin-antd/commit/bdc39aff) + - 添加路由跳转浏览器新标签  -  by **Soybean** [(987ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/987cef33) + - 添加常用组件、composables函数  -  by **Soybean** [(230a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/230a50a4) + - 添加表格页面示例  -  by **Soybean** [(51c74)](https://github.com/soybeanjs/soybean-admin-antd/commit/51c744c8) + - 增加Icon选择器组件  -  by **Yanbowen** [(9472b)](https://github.com/soybeanjs/soybean-admin-antd/commit/9472b518) + - 图标选择器增加扩展树形  -  by **Yanbowen** [(04101)](https://github.com/soybeanjs/soybean-admin-antd/commit/041012b3) + - 增加项目文档外链  -  by **Yanbowen** [(1901a)](https://github.com/soybeanjs/soybean-admin-antd/commit/1901a0bf) + - 引入mockjs  -  by **Soybean** [(9bc68)](https://github.com/soybeanjs/soybean-admin-antd/commit/9bc682da) + - 增加全局搜索菜单功能  -  by **Yanbowen** [(b9ce6)](https://github.com/soybeanjs/soybean-admin-antd/commit/b9ce6913) + - 菜单搜索增加大小写转换  -  by **Yanbowen** [(29078)](https://github.com/soybeanjs/soybean-admin-antd/commit/29078689) + - 添加cryptojs,对本地缓存数据进行加密  -  by **Soybean** [(7a064)](https://github.com/soybeanjs/soybean-admin-antd/commit/7a0648db) + - 路由页面跳转权限完成  -  by **Soybean** [(0d2a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/0d2a5629) + - 集成naiveUI主题配置,将css vars添加至html  -  by **Soybean** [(2c196)](https://github.com/soybeanjs/soybean-admin-antd/commit/2c196841) + - 初始化加载效果:应用主题颜色  -  by **Soybean** [(035fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/035fa114) + - 登录页面开始迁移  -  by **Soybean** [(f5a36)](https://github.com/soybeanjs/soybean-admin-antd/commit/f5a36a05) + - 迁移登录完成  -  by **Soybean** [(b93b8)](https://github.com/soybeanjs/soybean-admin-antd/commit/b93b80cb) + - 添加NaiveProvider组件  -  by **Soybean** [(c804b)](https://github.com/soybeanjs/soybean-admin-antd/commit/c804b21c) + - 多级路由的所有子路由转换成二级路由  -  by **Soybean** [(85b55)](https://github.com/soybeanjs/soybean-admin-antd/commit/85b55bb3) + - 新增BasicLayout布局  -  by **Soybean** [(00646)](https://github.com/soybeanjs/soybean-admin-antd/commit/006467a0) + - 创建自定义布局组件SoybeanLayout  -  by **Soybean** [(0653f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0653fb14) + - 添加抽屉  -  by **Soybean** [(10e4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/10e4d81b) + - theme store完成  -  by **Soybean** [(bf020)](https://github.com/soybeanjs/soybean-admin-antd/commit/bf020a82) + - 主题配置抽屉:迁移暗黑模式、布局模式、添加颜色选择面板  -  by **Soybean** [(912bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/912bfdf4) + - 主题配置抽屉: 迁移其他功能  -  by **Soybean** [(6d132)](https://github.com/soybeanjs/soybean-admin-antd/commit/6d132c59) + - 添加头部折叠按钮  -  by **Soybean** [(a090d)](https://github.com/soybeanjs/soybean-admin-antd/commit/a090d398) + - 添加侧边菜单  -  by **Soybean** [(e25af)](https://github.com/soybeanjs/soybean-admin-antd/commit/e25afe2f) + - 面包屑  -  by **Soybean** [(09c76)](https://github.com/soybeanjs/soybean-admin-antd/commit/09c7658c) + - 请求拦截器添加刷新token  -  by **Soybean** [(839b8)](https://github.com/soybeanjs/soybean-admin-antd/commit/839b82ba) + - 细节完善  -  by **Soybean** [(cc290)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc290acc) + - 迁移多页签  -  by **Soybean** [(28efb)](https://github.com/soybeanjs/soybean-admin-antd/commit/28efbdbc) + - 细节完善、迁移页面  -  by **Soybean** [(ce531)](https://github.com/soybeanjs/soybean-admin-antd/commit/ce531ce5) + - 添加页面缓存、记录在tab中的缓存页面的滚动条位置  -  by **Soybean** [(1d63a)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d63a838) + - 添加缓存主题色  -  by **Soybean** [(37092)](https://github.com/soybeanjs/soybean-admin-antd/commit/37092974) + - 新版重构完成  -  by **Soybean** [(68b42)](https://github.com/soybeanjs/soybean-admin-antd/commit/68b42304) + - 迁移全局搜索菜单功能  -  by **yanbowen** [(554d7)](https://github.com/soybeanjs/soybean-admin-antd/commit/554d7fd6) + - 添加naiveUI按需引入  -  by **Soybean** [(a810e)](https://github.com/soybeanjs/soybean-admin-antd/commit/a810ef85) + - 添加SvgIcon,配置vite plugin  -  by **Liushengqun** [(378d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/378d55ac) + - 引入soybean-admin-tab、去除vite-plugin-svg-icons,用unplugin-icons实现自定义svg的iconify写法、代码优化  -  by **Soybean** [(a1a57)](https://github.com/soybeanjs/soybean-admin-antd/commit/a1a57a18) + - 新增子菜单图标和多页签图标  -  by **Soybean** [(f5c56)](https://github.com/soybeanjs/soybean-admin-antd/commit/f5c56c35) + - 重构项目的TS类型架构,去除interface文件夹  -  by **Soybean** [(81914)](https://github.com/soybeanjs/soybean-admin-antd/commit/8191490f) + - 添加网络代理  -  by **Soybean** [(094dc)](https://github.com/soybeanjs/soybean-admin-antd/commit/094dca96) + - 添加全局组件自动引入注册  -  by **Soybean** [(f5a04)](https://github.com/soybeanjs/soybean-admin-antd/commit/f5a043b1) + - 新增自定义svg图标动态渲染  -  by **Soybean** [(f83c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/f83c7b59) + - 新增静态路由  -  by **Soybean** [(ca2df)](https://github.com/soybeanjs/soybean-admin-antd/commit/ca2dfa61) + - 插件方式按需引入naiveUI  -  by **Soybean** [(6bed9)](https://github.com/soybeanjs/soybean-admin-antd/commit/6bed9ead) + - 添加请求适配器的请求示例  -  by **Soybean** [(bed42)](https://github.com/soybeanjs/soybean-admin-antd/commit/bed4292e) + - 登录页面适配移动端  -  by **Soybean** [(ec077)](https://github.com/soybeanjs/soybean-admin-antd/commit/ec0776e2) + - 登录页背景图片位置适配移动端  -  by **Soybean** [(24010)](https://github.com/soybeanjs/soybean-admin-antd/commit/24010d05) + - 引入unocss替换windicss  -  by **Soybean** [(c9d3e)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9d3e5a3) + - HTML lang 修改为 zh-cmn-Hans  -  by **相思** [(dbeb5)](https://github.com/soybeanjs/soybean-admin-antd/commit/dbeb595c) + - HTML lang 修改为 zh-cmn-Hans  -  by **相思** [(b9c5c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b9c5c349) + - 权限完善及权限示例页面  -  by **Soybean** [(80744)](https://github.com/soybeanjs/soybean-admin-antd/commit/807448ae) + - mock添加权限过滤  -  by **Soybean** [(7f435)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f4350ae) + - 添加自动跟随系统主题设置  -  by **相思** [(ba07b)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba07b695) + - 引入echarts替换antvG2plot  -  by **Soybean** [(e7ad0)](https://github.com/soybeanjs/soybean-admin-antd/commit/e7ad0868) + - 添加百度地图、升级依赖  -  by **Soybean** [(39854)](https://github.com/soybeanjs/soybean-admin-antd/commit/39854a49) + - 添加插件页面:图表  -  by **Soybean** [(0a46e)](https://github.com/soybeanjs/soybean-admin-antd/commit/0a46ea08) + - 添加antv g2图表示例  -  by **Soybean** [(44b02)](https://github.com/soybeanjs/soybean-admin-antd/commit/44b022ae) + - 补充更多的ECharts示例  -  by **Soybean** [(c7762)](https://github.com/soybeanjs/soybean-admin-antd/commit/c7762490) + - 动态路由根路由重定向只需取决于后端返回的路由首页  -  by **Soybean** [(434ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/434ab1c5) + - 支持同一路由根据不同query和hash同时显示不同Tab  -  by **Soybean** [(41226)](https://github.com/soybeanjs/soybean-admin-antd/commit/41226858) + - 新增Antv G2图表示例  -  by **Soybean** [(2d64a)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d64a2e5) + - 上下结构,菜单支持横向滚动  -  by **tanminglin** [(80805)](https://github.com/soybeanjs/soybean-admin-antd/commit/808051b2) + - 增加设置当前Tab页签名称功能  -  by **燕博文** [(48721)](https://github.com/soybeanjs/soybean-admin-antd/commit/487213b6) + - 本地svg动态渲染图标  -  by **Soybean** [(c3c97)](https://github.com/soybeanjs/soybean-admin-antd/commit/c3c975ee) + - 增加系统消息组件  -  by **燕博文** [(afa01)](https://github.com/soybeanjs/soybean-admin-antd/commit/afa0134f) + - 系统消息组件代码优化  -  by **燕博文** [(95183)](https://github.com/soybeanjs/soybean-admin-antd/commit/9518372f) + - 增加返回顶部功能  -  by **燕博文** [(894b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/894b0f1c) + - 添加生产的主题配置缓存  -  by **Soybean** [(718c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/718c3626) + - 添加provide、inject上下文示例  -  by **Soybean** [(a4447)](https://github.com/soybeanjs/soybean-admin-antd/commit/a444731e) + - 添加组件名称,调整vue文件里面的类型声明位置  -  by **Soybean** [(f64bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/f64bc91c) + - 适配移动端,修复Tab关闭图标的bug  -  by **Soybean** [(296b1)](https://github.com/soybeanjs/soybean-admin-antd/commit/296b154b) + - 添加系统管理的页面  -  by **Soybean** [(c33b5)](https://github.com/soybeanjs/soybean-admin-antd/commit/c33b5ebf) + - useNaiveTable函数:类型部分  -  by **Soybean** [(02992)](https://github.com/soybeanjs/soybean-admin-antd/commit/02992dc0) + - 添加请求适配adapter层应用的示例页面  -  by **Soybean** [(8d11a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8d11a6af) + - 实现用户管理页面  -  by **Soybean** [(472f9)](https://github.com/soybeanjs/soybean-admin-antd/commit/472f93bf) + - 全局搜索菜单及消息通知适配移动端  -  by **燕博文** [(97e2f)](https://github.com/soybeanjs/soybean-admin-antd/commit/97e2ffdd) + - support constant route without login status[支持未登录状态下访问自定义的固定路由]  -  by **Soybean** [(a5391)](https://github.com/soybeanjs/soybean-admin-antd/commit/a539112a) + - add pinia setup syntax example: setup-store[添加setup syntax的pinia示例setup-store]  -  by **Soybean** [(82c4b)](https://github.com/soybeanjs/soybean-admin-antd/commit/82c4b09b) + - add constant route page without login status[添加未登录可访问的固定路由示例页面]  -  by **Soybean** [(78efd)](https://github.com/soybeanjs/soybean-admin-antd/commit/78efd779) + - refactor icon system, unify icon usage [重构图标系统,统一图标用法]  -  by **Soybean** [(811f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/811f8206) + - import i18n [引入i18n]  -  by **Soybean** [(b632b)](https://github.com/soybeanjs/soybean-admin-antd/commit/b632b7ff) + - new router system [新的路由系统]  -  by **Soybean** [(c7b6a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c7b6a3fb) + - add compress script [添加压缩命令]  -  by **Soybean** [(be6d4)](https://github.com/soybeanjs/soybean-admin-antd/commit/be6d4314) + - add script about generating png logo from [添加根据svg生成png图标的命令]  -  by **Soybean** [(70aee)](https://github.com/soybeanjs/soybean-admin-antd/commit/70aeefea) + - add generate logo script  -  by **Soybean** [(25daa)](https://github.com/soybeanjs/soybean-admin-antd/commit/25daa236) + - add new route plugin @soybeanjs/vite-plugin-vue-page-route [集成新的路由插件]  -  by **Soybean** [(3131e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3131e00f) + - custom unocss colors support opacity  -  by **Soybean** [(488e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/488e6e32) + - new layout,tab and add update theme settings  -  by **Soybean** [(912c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/912c3531) + - 返回顶部功能适配新布局  -  by **燕博文** [(54e2c)](https://github.com/soybeanjs/soybean-admin-antd/commit/54e2cb51) + - 增加i18n支持翻译菜单,tab,title  -  by **cc** [(3d48a)](https://github.com/soybeanjs/soybean-admin-antd/commit/3d48aa8b) + - add menu translate [翻译菜单]  -  by **Soybean** [(f6828)](https://github.com/soybeanjs/soybean-admin-antd/commit/f68285fb) + - 增加主题切换过渡效果  -  by **cc** [(8da88)](https://github.com/soybeanjs/soybean-admin-antd/commit/8da8843f) + - support mobile layout [支持移动端布局]  -  by **Soybean** [(f2b51)](https://github.com/soybeanjs/soybean-admin-antd/commit/f2b518ed) + - add websocket demo  -  by **Soybean** [(af53e)](https://github.com/soybeanjs/soybean-admin-antd/commit/af53ec76) + - add switch for customize darkmode transition  -  by **Soybean** [(6e0cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/6e0cce4d) + - new i18n function $t & login page and setting drawer config i18n  -  by @soybeanjs [(854d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/854d0bcf) + - add plugin-web-update-notification  -  by @soybeanjs [(c9164)](https://github.com/soybeanjs/soybean-admin-antd/commit/c91644b8) + - init  -  by @soybeanjs [(77b6e)](https://github.com/soybeanjs/soybean-admin-antd/commit/77b6e97b) + - add switch-lang, add look-forward  -  by @soybeanjs [(0c666)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c66695b) + - add logout  -  by @soybeanjs [(486de)](https://github.com/soybeanjs/soybean-admin-antd/commit/486dec4e) + - add login module  -  by @soybeanjs [(314e8)](https://github.com/soybeanjs/soybean-admin-antd/commit/314e813b) + - add theme palette and colors support unocss color opacity  -  by @soybeanjs [(88e64)](https://github.com/soybeanjs/soybean-admin-antd/commit/88e6438f) + - nprogress color feat theme color  -  by @soybeanjs [(d7621)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7621d8c) + - perf route meta and route i18n  -  by @soybeanjs [(a2e0f)](https://github.com/soybeanjs/soybean-admin-antd/commit/a2e0f479) + - route store  -  by @soybeanjs [(a7784)](https://github.com/soybeanjs/soybean-admin-antd/commit/a77843c3) + - menu in route store  -  by @soybeanjs [(81e59)](https://github.com/soybeanjs/soybean-admin-antd/commit/81e59d39) + - perf menu and add cache in route store  -  by @soybeanjs [(5c60b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c60b151) + - antd menu  -  by @soybeanjs [(542e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/542e5d3b) + - add menu icon  -  by @soybeanjs [(60f29)](https://github.com/soybeanjs/soybean-admin-antd/commit/60f29edf) + - add axios  -  by @soybeanjs [(110fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/110fce62) + - update @elegant-router/vue and fix types  -  by @soybeanjs [(b7632)](https://github.com/soybeanjs/soybean-admin-antd/commit/b76329bc) + - service and proxy  -  by @soybeanjs [(ed68c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ed68c8f0) + - login, antdv useApp, form  -  by @soybeanjs [(53c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/53c2010a) + - router guide  -  by @soybeanjs [(5cf87)](https://github.com/soybeanjs/soybean-admin-antd/commit/5cf87e15) + - add login loading to confirm button  -  by @soybeanjs [(cb6c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb6c7d17) + - add page manage and remove page user  -  by @soybeanjs [(73b02)](https://github.com/soybeanjs/soybean-admin-antd/commit/73b023c5) + - menu click to switch route  -  by @soybeanjs [(60ef0)](https://github.com/soybeanjs/soybean-admin-antd/commit/60ef0af3) + - keep antd menu transition same as system  -  by @soybeanjs [(77c96)](https://github.com/soybeanjs/soybean-admin-antd/commit/77c9623e) + - add tab store, PageTab  -  by @soybeanjs [(ecd0d)](https://github.com/soybeanjs/soybean-admin-antd/commit/ecd0df20) + - add LangSwitch to component, fix login page i18n  -  by @soybeanjs [(e435b)](https://github.com/soybeanjs/soybean-admin-antd/commit/e435b188) + - add tab dropdown, FullScreen  -  by @soybeanjs [(dcc4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/dcc4c86b) + - add ThemeDrawer  -  by @soybeanjs [(22447)](https://github.com/soybeanjs/soybean-admin-antd/commit/22447885) + - add ReloadButton  -  by @soybeanjs [(66b90)](https://github.com/soybeanjs/soybean-admin-antd/commit/66b90702) + - add ButtonIcon with tooltip  -  by @soybeanjs [(4649d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4649dec0) + - support mobile layout  -  by @soybeanjs [(cfcf8)](https://github.com/soybeanjs/soybean-admin-antd/commit/cfcf835f) + - add page animate  -  by @soybeanjs [(41c38)](https://github.com/soybeanjs/soybean-admin-antd/commit/41c384f2) + - add beadcrumb  -  by @soybeanjs [(d9279)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9279896) + - routes cache  -  by @soybeanjs [(073e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/073e6154) + - cache tabs  -  by @soybeanjs [(1f439)](https://github.com/soybeanjs/soybean-admin-antd/commit/1f4398d9) + - add reset routes  -  by @soybeanjs [(76400)](https://github.com/soybeanjs/soybean-admin-antd/commit/76400a83) + - themeDrawer layout mode  -  by @soybeanjs [(8c36d)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c36db7c) + - add horizontal menu  -  by @soybeanjs [(012d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/012d1e8c) + - menu style adapter system  -  by @soybeanjs [(32a2d)](https://github.com/soybeanjs/soybean-admin-antd/commit/32a2d982) + - vertical-mix sider  -  by @soybeanjs [(c9329)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9329f99) + - HorizontalMixMenu  -  by @soybeanjs [(2d59d)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d59dd63) + - theme settings theme colors  -  by @soybeanjs [(5d883)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d883f51) + - finish theme settings  -  by @soybeanjs [(92b4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/92b4c181) + - theme settings copy  -  by @soybeanjs [(95e38)](https://github.com/soybeanjs/soybean-admin-antd/commit/95e38c94) + - iconify offline  -  by @soybeanjs [(388e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/388e5049) + - antd locale, dayjs locale  -  by @soybeanjs [(3b33c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b33ce94) + - 1.0 beta  -  by @soybeanjs [(e918a)](https://github.com/soybeanjs/soybean-admin-antd/commit/e918a2c0) + - support Vite5  -  by @soybeanjs [(8e41a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e41a8fd) + - support Vite5  -  by @soybeanjs [(96e4a)](https://github.com/soybeanjs/soybean-admin-antd/commit/96e4aff5) + - request pkgs  -  by @soybeanjs [(81a31)](https://github.com/soybeanjs/soybean-admin-antd/commit/81a312f0) + - update @sa/axios  -  by @soybeanjs [(fd790)](https://github.com/soybeanjs/soybean-admin-antd/commit/fd790fa9) + - @sa/axios: createRequest, createFlatRequest, createHookRequest  -  by @soybeanjs [(c5c45)](https://github.com/soybeanjs/soybean-admin-antd/commit/c5c456b0) + - @sa/axios: createRequest, createFlatRequest, createHookRequest  -  by @soybeanjs [(bac16)](https://github.com/soybeanjs/soybean-admin-antd/commit/bac16324) + - add sort routes  -  by @soybeanjs [(637c6)](https://github.com/soybeanjs/soybean-admin-antd/commit/637c64aa) + - add app loading  -  by @soybeanjs [(c6545)](https://github.com/soybeanjs/soybean-admin-antd/commit/c65451b3) + - add app loading  -  by @soybeanjs [(a7ef1)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7ef1a51) + - add vitepress docs  -  by @soybeanjs [(5f72f)](https://github.com/soybeanjs/soybean-admin-antd/commit/5f72fa88) + - add copyright, unocss shortcut: card-wrapper, update package.json  -  by @soybeanjs [(affcc)](https://github.com/soybeanjs/soybean-admin-antd/commit/affcc26b) + - add copyright, unocss shortcut: card-wrapper, update package.json  -  by @soybeanjs [(a11b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/a11b9557) + - add page: about  -  by @soybeanjs [(4955f)](https://github.com/soybeanjs/soybean-admin-antd/commit/4955f1af) + - add custom route exception  -  by @soybeanjs [(b43c9)](https://github.com/soybeanjs/soybean-admin-antd/commit/b43c9256) + - filter tabs which are not in routes  -  by @soybeanjs [(f59f3)](https://github.com/soybeanjs/soybean-admin-antd/commit/f59f3488) + - add page: about  -  by @soybeanjs [(a2b6b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a2b6b4e6) + - add custom route exception  -  by @soybeanjs [(0bab9)](https://github.com/soybeanjs/soybean-admin-antd/commit/0bab9413) + - filter tabs which are not in routes  -  by @soybeanjs [(b047c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b047c2e0) + - packages/scripts: add command changelog,release  -  by @soybeanjs [(dafb6)](https://github.com/soybeanjs/soybean-admin-antd/commit/dafb6fa0) + - add script: gen-route  -  by @soybeanjs [(697c1)](https://github.com/soybeanjs/soybean-admin-antd/commit/697c1b61) + - packages/scripts: add command changelog,release  -  by @soybeanjs [(50926)](https://github.com/soybeanjs/soybean-admin-antd/commit/50926f3b) + - add script: gen-route  -  by @soybeanjs [(e9b15)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9b15715) + - @sa/axios: add qs stringify for params  -  by @soybeanjs [(2400c)](https://github.com/soybeanjs/soybean-admin-antd/commit/2400c026) + - @sa/axios: add qs stringify for params  -  by @soybeanjs [(6ee5a)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ee5a217) + - page home & perf useEcharts  -  by @soybeanjs [(62e4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/62e4da05) + - finish page home  -  by @soybeanjs [(7bd1e)](https://github.com/soybeanjs/soybean-admin-antd/commit/7bd1e47a) + - add page function_tab  -  by @soybeanjs [(6ff86)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ff86e77) + - page home & perf useEcharts  -  by @soybeanjs [(37c92)](https://github.com/soybeanjs/soybean-admin-antd/commit/37c928fa) + - add page function_tab  -  by @soybeanjs [(bd645)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd645634) + - page manage_role  -  by @soybeanjs [(237c6)](https://github.com/soybeanjs/soybean-admin-antd/commit/237c6d22) + - page manage_user  -  by @soybeanjs [(8a170)](https://github.com/soybeanjs/soybean-admin-antd/commit/8a170eee) + - page manage_menu  -  by @soybeanjs [(87d65)](https://github.com/soybeanjs/soybean-admin-antd/commit/87d65d3b) + - page manage_menu operateDrawer  -  by @soybeanjs [(db17c)](https://github.com/soybeanjs/soybean-admin-antd/commit/db17c916) + - Add type to TabRoute: matched  -  by @Azir-11 [(2d102)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d102a05) + - support directory menu hide all child menus. fixed #325  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/325 [(7256a)](https://github.com/soybeanjs/soybean-admin-antd/commit/7256ad4e) + - mock manage list data with pagination  -  by @soybeanjs [(1a6be)](https://github.com/soybeanjs/soybean-admin-antd/commit/1a6be003) + - globalSearch add i18n  -  by **燕博文** [(0126d)](https://github.com/soybeanjs/soybean-admin-antd/commit/0126da47) + - Add route meta parameter:fixedQuery  -  by **Azir-11** [(874aa)](https://github.com/soybeanjs/soybean-admin-antd/commit/874aaca5) + - support directory menu hide all child menus.  -  by @soybeanjs [(cd72e)](https://github.com/soybeanjs/soybean-admin-antd/commit/cd72e7a4) + - support route query in menu  -  by @soybeanjs [(063f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/063f5638) + - update  -  by @soybeanjs [(4158a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4158a72b) + - change borderRadius to 6px of naiveUI  -  by @soybeanjs [(49558)](https://github.com/soybeanjs/soybean-admin-antd/commit/49558ca0) + - pef manage role  -  by @soybeanjs [(18709)](https://github.com/soybeanjs/soybean-admin-antd/commit/18709813) + - login page: code-login  -  by @soybeanjs [(c91dd)](https://github.com/soybeanjs/soybean-admin-antd/commit/c91dd282) + - login page: register  -  by @soybeanjs [(1ed33)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ed33dc4) + - add request refresh token & logout  -  by @soybeanjs [(11a6a)](https://github.com/soybeanjs/soybean-admin-antd/commit/11a6a3bd) + - add request exception example page  -  by @soybeanjs [(41e8b)](https://github.com/soybeanjs/soybean-admin-antd/commit/41e8bc44) + - add auth example  -  by @soybeanjs [(c11d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/c11d56da) + - login page: code-login  -  by @soybeanjs [(f4e7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4e7c925) + - login page: register  -  by @soybeanjs [(b6420)](https://github.com/soybeanjs/soybean-admin-antd/commit/b6420329) + - @sa/axios: support instance state, fix flatRequest error type  -  by @soybeanjs [(3f418)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f418116) + - add request exception  -  by @soybeanjs [(0b1ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b1ece51) + - add function page: request  -  by @soybeanjs [(757d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/757d1d6b) + - add function page: hide-child,super-page,toggle-auth  -  by @soybeanjs [(886ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/886ea579) + - manage page: manage_role  -  by @soybeanjs [(658dc)](https://github.com/soybeanjs/soybean-admin-antd/commit/658dc94f) + - support grayscale. fixed #385  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/385 [(d335d)](https://github.com/soybeanjs/soybean-admin-antd/commit/d335df6f) + - perf page manage_role  -  by @soybeanjs [(55945)](https://github.com/soybeanjs/soybean-admin-antd/commit/5594558b) + - Add prefix to local storage  -  by **Azir** [(1fc34)](https://github.com/soybeanjs/soybean-admin-antd/commit/1fc34cc5) + - add table showTotal options  -  by @paynezhuang [(3e61e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e61eab4) + - support iframe page with diffrent url of custom route  -  by @soybeanjs [(da12d)](https://github.com/soybeanjs/soybean-admin-antd/commit/da12d4a5) + - add recommend color switch. closed #388  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/388 [(a1920)](https://github.com/soybeanjs/soybean-admin-antd/commit/a1920fca) + - add menu route field  -  by @paynezhuang [(dbe31)](https://github.com/soybeanjs/soybean-admin-antd/commit/dbe31eb1) + - support repeated request errors occur once in a short time. close #368, close #369  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/368 and https://github.com/soybeanjs/soybean-admin-antd/issues/369 [(e3bd3)](https://github.com/soybeanjs/soybean-admin-antd/commit/e3bd3972) + - close tab by mouse wheel button click  -  by **JianJroh** [(d3849)](https://github.com/soybeanjs/soybean-admin-antd/commit/d3849baa) + - page: support manage_menu more options. close #366  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/366 [(c4b5c)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4b5c656) + - useTable adds expand to display  -  by @paynezhuang [(0a90d)](https://github.com/soybeanjs/soybean-admin-antd/commit/0a90dd37) + - Synchronize role management and menu management  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/13 [(7943c)](https://github.com/soybeanjs/soybean-admin-antd/commit/7943ce2b) + - Syncronize user management list page  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/18 [(64be7)](https://github.com/soybeanjs/soybean-admin-antd/commit/64be7d2b) + - Synchronous user management  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/19 [(68231)](https://github.com/soybeanjs/soybean-admin-antd/commit/6823194b) + - support system new version update notification. close #420  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/420 [(584cd)](https://github.com/soybeanjs/soybean-admin-antd/commit/584cd54d) + - get user info in router guard and remove in localStorage. close #459  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/459 [(5531a)](https://github.com/soybeanjs/soybean-admin-antd/commit/5531a686) + - support grayscale  -  by @soybeanjs [(db2a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/db2a5bb4) + - add prefix to local storage  -  by @soybeanjs [(0423c)](https://github.com/soybeanjs/soybean-admin-antd/commit/0423cb15) + - support iframe page with diffrent url of custom route  -  by @soybeanjs [(4975d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4975d11b) + - add recommend color switch  -  by @soybeanjs [(7fa51)](https://github.com/soybeanjs/soybean-admin-antd/commit/7fa51361) + - support repeated request errors occur once in a short time  -  by @soybeanjs [(6e809)](https://github.com/soybeanjs/soybean-admin-antd/commit/6e809632) + - close tab by mouse wheel button click  -  by @soybeanjs [(31e1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/31e1d4ed) + - support system new version update notification  -  by @soybeanjs [(cee03)](https://github.com/soybeanjs/soybean-admin-antd/commit/cee03ed1) + - get user info in router guard and remove in localStorage  -  by @soybeanjs [(ccbe3)](https://github.com/soybeanjs/soybean-admin-antd/commit/ccbe39df) + - reset scroll position when tab change  -  by @soybeanjs [(9094b)](https://github.com/soybeanjs/soybean-admin-antd/commit/9094b21c) + - reset scroll position when tab change  -  by @soybeanjs [(804f9)](https://github.com/soybeanjs/soybean-admin-antd/commit/804f9e62) + - make branch `main` tiny & modify request retry times to 0  -  by @Azir-11 [(793b1)](https://github.com/soybeanjs/soybean-admin-antd/commit/793b16e9) + - add color fading mode.close #567  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/569 and https://github.com/soybeanjs/soybean-admin-antd/issues/567 [(4dde4)](https://github.com/soybeanjs/soybean-admin-antd/commit/4dde4c22) + - add full screen watermark. close#571  -  by @paynezhuang in https://github.com/soybeanjs/soybean-admin-antd/issues/573 and https://github.com/soybeanjs/soybean-admin-antd/issues/571 [(ea8aa)](https://github.com/soybeanjs/soybean-admin-antd/commit/ea8aa6c4) + - README.zh_CN.md 添加合作推广  -  by @PZ-18664918826 in https://github.com/soybeanjs/soybean-admin-antd/issues/601 [(2fa40)](https://github.com/soybeanjs/soybean-admin-antd/commit/2fa400b1) + - Add more commit types according to Apache specifications  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/610 [(878d9)](https://github.com/soybeanjs/soybean-admin-antd/commit/878d9c39) + - does the configuration support automatic updates. close#612  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/617 and https://github.com/soybeanjs/soybean-admin-antd/issues/612 [(4c9f4)](https://github.com/soybeanjs/soybean-admin-antd/commit/4c9f4e09) + - add app error handler. close #587  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/587 [(be855)](https://github.com/soybeanjs/soybean-admin-antd/commit/be8556cd) + - supports custom menu icon sizes  -  by @soybeanjs [(c8a9e)](https://github.com/soybeanjs/soybean-admin-antd/commit/c8a9e853) + - add color fading mode  -  by @soybeanjs [(719f0)](https://github.com/soybeanjs/soybean-admin-antd/commit/719f02fb) + - add full screen watermark  -  by @soybeanjs [(6bb66)](https://github.com/soybeanjs/soybean-admin-antd/commit/6bb66a05) + - does the configuration support automatic updates  -  by @soybeanjs [(ffe4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffe4cef7) + - add app error handler  -  by @soybeanjs [(60366)](https://github.com/soybeanjs/soybean-admin-antd/commit/60366c27) + - login supports accessible operation.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/637 [(cfaab)](https://github.com/soybeanjs/soybean-admin-antd/commit/cfaab852) + - login supports accessible operation.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/45 [(abe66)](https://github.com/soybeanjs/soybean-admin-antd/commit/abe66bc5) + - support scheduled detection and update system. close #657  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/669 and https://github.com/soybeanjs/soybean-admin-antd/issues/657 [(d088f)](https://github.com/soybeanjs/soybean-admin-antd/commit/d088f813) + - app version notification plugin support sub deploy path. close #668  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/668 [(a53eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/a53eb10c) + - support show tab when not loggedIn  -  by @soybeanjs [(ba381)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba38119e) + - support scheduled detection and update system. close #657  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/669 and https://github.com/soybeanjs/soybean-admin-antd/issues/657 [(18d73)](https://github.com/soybeanjs/soybean-admin-antd/commit/18d73e59) + - app version notification plugin support sub deploy path. close #668  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/668 [(1d8a2)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d8a2544) +- **route**: + - 增加功能示例模块  -  by **Yanbowen** [(efd29)](https://github.com/soybeanjs/soybean-admin-antd/commit/efd29bc3) + - 路由meta新增activeMenu属性  -  by **燕博文** [(ebd16)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebd16a4d) +- **router**: + - add sortRoutesByOrder function  -  by **Azir-11** [(0cf09)](https://github.com/soybeanjs/soybean-admin-antd/commit/0cf09bae) +- **storage**: + - local存储增加有效期  -  by **Yanbowen** [(e6c9b)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6c9b35a) +- **tabs**: + - 多页签增加关闭所有  -  by **燕博文** [(8237a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8237adb9) + +###    🐞 Bug Fixes + +- remove height limit h-360px  -  by **Wang Zheng** [(b5c57)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5c570ad) +- set password attributes  -  by **Wang Zheng** [(a9a37)](https://github.com/soybeanjs/soybean-admin-antd/commit/a9a37036) +- **components**: + - tab组件在黑暗模式下泛白的颜色问题以及chromeTab的重叠问题  -  by **lingdu** [(6797d)](https://github.com/soybeanjs/soybean-admin-antd/commit/6797dbf1) + - 修复tab组件适应暗黑主题模式  -  by **Soybean** [(2fe3d)](https://github.com/soybeanjs/soybean-admin-antd/commit/2fe3d27a) + - 修复按钮Tab自适应主题颜色  -  by **Soybean** [(3d1f4)](https://github.com/soybeanjs/soybean-admin-antd/commit/3d1f4192) + - 修复BaseLayout的HorizontalLayout  -  by **Soybean** [(0344f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0344f46c) + - 修复多页签Tab自动滚动问题  -  by **Soybean** [(20aa3)](https://github.com/soybeanjs/soybean-admin-antd/commit/20aa39f1) + - 修复多页签按钮风格的tab滚动问题  -  by **Soybean** [(c429c)](https://github.com/soybeanjs/soybean-admin-antd/commit/c429cd02) + - 修复HorizontalLayout布局  -  by **Soybean** [(9fb64)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fb641f7) + - 修复Tab在移动端设备无法点击的问题  -  by **Soybean** [(2c966)](https://github.com/soybeanjs/soybean-admin-antd/commit/2c9660fd) + - 修复组件LoadingEmptyWrapper适应暗黑模式  -  by **Soybean** [(811b1)](https://github.com/soybeanjs/soybean-admin-antd/commit/811b15e6) + - 组件LoadingEmptyWrapper添加背景颜色动画过渡  -  by **Soybean** [(7add5)](https://github.com/soybeanjs/soybean-admin-antd/commit/7add5c2e) + - 修复路由在path中包含重复路单词径菜单时,被激活会错误展开  -  by **shabby2333** [(264da)](https://github.com/soybeanjs/soybean-admin-antd/commit/264da00e) + - 页面跳转被拦截, 则会出现 tab 页签与页面不一致的问题  -  by **刘璐** [(bd5dd)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd5dd2cf) + - 修复iconSelect选择器点击事件失效  -  by **燕博文** [(7e505)](https://github.com/soybeanjs/soybean-admin-antd/commit/7e505f9b) + - refresh cached routes  -  by **alue_mobile** [(b0f98)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0f98e4b) + - fix mix-menu layout when the locale is English (fixed 241)  -  by **Soybean** [(5c085)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c085a19) + - 修复动态路由主页404  -  by **lapislazulisch** [(3ae19)](https://github.com/soybeanjs/soybean-admin-antd/commit/3ae19526) + - 修复动态路由home页404  -  by **lapislazulisch** [(ad6ac)](https://github.com/soybeanjs/soybean-admin-antd/commit/ad6ac722) + - fix tooltip zIndex of ButtonIcon  -  by @soybeanjs [(99097)](https://github.com/soybeanjs/soybean-admin-antd/commit/99097b46) + - supplement the `NaiveUI` type  -  by **tnt group** [(ccc2b)](https://github.com/soybeanjs/soybean-admin-antd/commit/ccc2b674) + - fix homeTab closeRight and disable colseLeft  -  by **~li** [(d28bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/d28bf526) + - fix PinToggler label. fixed #407  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/407 [(c0ed1)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0ed1f26) + - 修复主题模式按钮显示与点击的异常  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/21 [(03e09)](https://github.com/soybeanjs/soybean-admin-antd/commit/03e094e8) + - Fix the issue of search box popping up repeatedly due to carriage return  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/468 [(5bd96)](https://github.com/soybeanjs/soybean-admin-antd/commit/5bd96b8d) + - fix click `MenuToggler` throw error  -  by @soybeanjs [(45588)](https://github.com/soybeanjs/soybean-admin-antd/commit/455880b1) + - fix `TableHeaderOperation` style  -  by @soybeanjs [(251d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/251d15ab) + - fix VerticalMixMenu name  -  by @soybeanjs [(20f8e)](https://github.com/soybeanjs/soybean-admin-antd/commit/20f8ed31) +- **deps**: + - 去除图片验证码依赖  -  by **Soybean** [(76a1a)](https://github.com/soybeanjs/soybean-admin-antd/commit/76a1afae) + - 降低vite版本,新版本有些许问题  -  by **Soybean** [(b429c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b429c8b8) + - vite依赖放入devDependencies  -  by **Soybean** [(7527b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7527b1f0) + - 降低vite版本  -  by **Soybean** [(c9c5c)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9c5ca99) + - decrease @types/node version to fix TS type error [降低@types/node版本修复TS的类型错误]  -  by **Soybean** [(149d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/149d22a4) + - move json5 from devDependencies to dependencies to support production usage  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/618 [(7cb43)](https://github.com/soybeanjs/soybean-admin-antd/commit/7cb43fc3) + - reduced eslint version to 9.14.0  -  by @soybeanjs [(af417)](https://github.com/soybeanjs/soybean-admin-antd/commit/af4177e7) +- **hooks**: + - 修复toLogin函数导致登录重定向地址过多  -  by **Soybean** [(b4adf)](https://github.com/soybeanjs/soybean-admin-antd/commit/b4adf678) + - 修复登录页切换登录页参数丢失问题  -  by **Soybean** [(78985)](https://github.com/soybeanjs/soybean-admin-antd/commit/789855a3) + - Fix Naive Pagination's outdated API  -  by **tnt group** [(37436)](https://github.com/soybeanjs/soybean-admin-antd/commit/3743612d) + - Fixed abnormal display of table pagers  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/17 [(cc256)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc2562b9) + - prevent program freezing when pagesize returns 0  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/545 [(f4eeb)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4eeb2ed) + - prevent program freezing when pagesize returns 0  -  by @soybeanjs [(05912)](https://github.com/soybeanjs/soybean-admin-antd/commit/05912b60) +- **packages**: + - @sa/hooks: fix searchParams of useHookTable. fixed #552  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/552 [(96c10)](https://github.com/soybeanjs/soybean-admin-antd/commit/96c1044f) + - @sa/hooks: fix searchParams of useHookTable  -  by @soybeanjs [(cb5bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb5bf072) +- **projects**: + - 修复顶部加载条主题  -  by **Soybean** [(ea591)](https://github.com/soybeanjs/soybean-admin-antd/commit/ea5917d2) + - 修复主题配置  -  by **Soybean** [(ff24f)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff24fda5) + - 修复页面滚动行为  -  by **Soybean** [(57e00)](https://github.com/soybeanjs/soybean-admin-antd/commit/57e00e64) + - 头部logo链接更正  -  by **Soybean** [(5d8c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d8c3f54) + - 修复登录的重定向地址  -  by **Soybean** [(f97f2)](https://github.com/soybeanjs/soybean-admin-antd/commit/f97f2266) + - 修复页面缓存,添加多页签删除  -  by **Soybean** [(24893)](https://github.com/soybeanjs/soybean-admin-antd/commit/24893747) + - 修复多页签删除功能  -  by **Soybean** [(99adb)](https://github.com/soybeanjs/soybean-admin-antd/commit/99adbc5a) + - 修复页面缓存  -  by **Soybean** [(fa0a9)](https://github.com/soybeanjs/soybean-admin-antd/commit/fa0a9079) + - 修复页面滚动和页面100%视高占比  -  by **Soybean** [(fa2cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/fa2cc789) + - 修复同时显示两种multiTab  -  by **Soybean** [(5be2e)](https://github.com/soybeanjs/soybean-admin-antd/commit/5be2e2a2) + - 修复vertical-mix导航模式的二级菜单显示问题  -  by **Soybean** [(6f286)](https://github.com/soybeanjs/soybean-admin-antd/commit/6f286e67) + - 修复多级菜单页面multitab显示问题  -  by **Soybean** [(f0474)](https://github.com/soybeanjs/soybean-admin-antd/commit/f0474bd9) + - 完善侧边菜单展开逻辑  -  by **Soybean** [(b5f05)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5f05128) + - 修复vertical sider自适应主题  -  by **Soybean** [(9097f)](https://github.com/soybeanjs/soybean-admin-antd/commit/9097fa38) + - 修复登录页刷新跳404  -  by **Soybean** [(358d4)](https://github.com/soybeanjs/soybean-admin-antd/commit/358d4e8a) + - 修复没有子页面的路由写法问题  -  by **Soybean** [(b80c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/b80c2246) + - 修复globalFooter适应暗黑模式  -  by **Soybean** [(93f08)](https://github.com/soybeanjs/soybean-admin-antd/commit/93f08d90) + - 修复主题相关,自适应操作系统暗黑模式  -  by **Soybean** [(bfa42)](https://github.com/soybeanjs/soybean-admin-antd/commit/bfa42d76) + - 修复tab过多时样式坍塌,添加tab横向滚动  -  by **Soybean** [(0ec4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/0ec4d218) + - 关于页面:开发环境依赖更正  -  by **Soybean** [(3b3ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b3baf93) + - 修复分析页折线图表布局问题  -  by **Soybean** [(43b83)](https://github.com/soybeanjs/soybean-admin-antd/commit/43b832be) + - 修复multiTab关闭逻辑,添加关闭左边和右边的标签右键操作  -  by **Soybean** [(ed90c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ed90cb8f) + - wangEditor在暗黑模式下的背景色问题  -  by **Yanbowen** [(a7de3)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7de3140) + - 修复百度地图sdk地址  -  by **Soybean** [(9a97d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9a97d23c) + - 腾讯地图容器高自适应  -  by **Soybean** [(d7054)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7054c59) + - 修复在暗黑模式下第一次进入网页不会触发暗黑模式监听  -  by **Yanbowen** [(c4a65)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4a652e2) + - 修复富文本编辑器在亮色主题下全屏后背景色丢失  -  by **14534** [(4ab77)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ab77021) + - 修复tab在移动端无法点击  -  by **Soybean** [(1a76d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1a76de04) + - 页面各部分背景颜色添加自然过渡  -  by **Soybean** [(1c5fd)](https://github.com/soybeanjs/soybean-admin-antd/commit/1c5fdca5) + - 更正dashboard的布局文件  -  by **Soybean** [(31fda)](https://github.com/soybeanjs/soybean-admin-antd/commit/31fda0ce) + - 布局修复:从填充屏幕高的页面切换至滚动页面导致布局坍塌  -  by **Soybean** [(2fdb5)](https://github.com/soybeanjs/soybean-admin-antd/commit/2fdb5f56) + - 修复打包构建时图标错误  -  by **Soybean** [(93f9a)](https://github.com/soybeanjs/soybean-admin-antd/commit/93f9aa95) + - 添加西瓜视频实例在onUnMounted的销毁,多页签居中距离精确  -  by **Soybean** [(73896)](https://github.com/soybeanjs/soybean-admin-antd/commit/738964a7) + - 修复网络请求错误空信息的提示  -  by **Soybean** [(ff921)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff9216b6) + - 请求相关细节修复  -  by **Soybean** [(2ad1a)](https://github.com/soybeanjs/soybean-admin-antd/commit/2ad1ad32) + - 修复redirect-not-found子路由  -  by **Soybean** [(5bfb8)](https://github.com/soybeanjs/soybean-admin-antd/commit/5bfb8199) + - 去除Layout组件冗余代码  -  by **Soybean** [(0e783)](https://github.com/soybeanjs/soybean-admin-antd/commit/0e783bcf) + - 修复面包屑数据  -  by **Soybean** [(28b5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/28b5d224) + - 修复vertical-mix布局、重构初始化的loading  -  by **Soybean** [(579e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/579e0740) + - 修复未登录时会调用获取用户路由的接口  -  by **Soybean** [(21bab)](https://github.com/soybeanjs/soybean-admin-antd/commit/21bab1f7) + - 修复路由守卫的动态路由逻辑  -  by **Soybean** [(b61b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b61b0ce2) + - vite配置修复  -  by **Soybean** [(facc0)](https://github.com/soybeanjs/soybean-admin-antd/commit/facc00e8) + - 修复分析页和工作台的布局问题  -  by **Soybean** [(e93b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/e93b94cb) + - 修复项目配置拷贝功能  -  by **Soybean** [(a7a26)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7a269d6) + - 修复页面切换动画无变化  -  by **Soybean** [(c4546)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4546bdf) + - 修复页面切换动画开关不生效  -  by **bundle** [(9d4ed)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d4ed617) + - 修复 BASE_URL 没有生效的问题  -  by **pany** [(72d7d)](https://github.com/soybeanjs/soybean-admin-antd/commit/72d7dcfa) + - 修复vite alias  -  by **Soybean** [(cd7ca)](https://github.com/soybeanjs/soybean-admin-antd/commit/cd7ca8f4) + - 修复路由守卫的动态路由逻辑  -  by **Soybean** [(e6c26)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6c26fcb) + - 全局搜索弹窗弹出时动画闪屏问题  -  by @yanbowe [(bb1bb)](https://github.com/soybeanjs/soybean-admin-antd/commit/bb1bbf27) + - 去除从环境文件引入端口号导致的错误  -  by **Soybean** [(2d6d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d6d179d) + - 修复在新版vite下环境变量获取不到的问题  -  by **Soybean** [(3fb13)](https://github.com/soybeanjs/soybean-admin-antd/commit/3fb13ca9) + - 修复获取vite环境变量的方式  -  by **Soybean** [(46e1a)](https://github.com/soybeanjs/soybean-admin-antd/commit/46e1ae78) + - 添加获取路由组件文件未找到时的错误提示  -  by **Soybean** [(219f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/219f87f4) + - 添加.npmrc修复无法获取自动引入的全局组件声明类型  -  by **Soybean** [(e8488)](https://github.com/soybeanjs/soybean-admin-antd/commit/e8488e4d) + - 修复样式  -  by **Soybean** [(e8999)](https://github.com/soybeanjs/soybean-admin-antd/commit/e8999144) + - 修复插件不存在的错误提示  -  by **Grazing Wind** [(71652)](https://github.com/soybeanjs/soybean-admin-antd/commit/71652820) + - 修复权限切换路由数据未更新的问题  -  by **Soybean** [(60f91)](https://github.com/soybeanjs/soybean-admin-antd/commit/60f91250) + - 修复页面切换时导致的溢出滚动条  -  by **Soybean** [(e0233)](https://github.com/soybeanjs/soybean-admin-antd/commit/e0233061) + - 修复@antv/g2生产环境报错  -  by **Soybean** [(4558c)](https://github.com/soybeanjs/soybean-admin-antd/commit/4558c24d) + - 修复顶部菜单的位置失效问题  -  by **Soybean** [(4ee0d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ee0d94f) + - 设置tab标题导致meta属性丢失  -  by **燕博文** [(efcfa)](https://github.com/soybeanjs/soybean-admin-antd/commit/efcfa576) + - 修复tab不显示路由首页的问题  -  by **Soybean** [(a792b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a792bb5c) + - 修复多个后端服务时的本地代理  -  by **Soybean** [(2aba5)](https://github.com/soybeanjs/soybean-admin-antd/commit/2aba58c9) + - 修复图标的TS类型  -  by **Soybean** [(dbd67)](https://github.com/soybeanjs/soybean-admin-antd/commit/dbd67609) + - 修复import.meta.env的TS类型  -  by **Soybean** [(19942)](https://github.com/soybeanjs/soybean-admin-antd/commit/19942625) + - 修复构建后mockjs对xhr的影响问题  -  by **Soybean** [(77572)](https://github.com/soybeanjs/soybean-admin-antd/commit/77572855) + - 修复TS类型问题  -  by **Soybean** [(16dce)](https://github.com/soybeanjs/soybean-admin-antd/commit/16dce9a4) + - 修复eslint规则  -  by **Soybean** [(d7f5b)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7f5bf33) + - add iconify json  -  by **Soybean** [(8a1ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/8a1ec938) + - fix vite-pwa plugin config  -  by **Soybean** [(94098)](https://github.com/soybeanjs/soybean-admin-antd/commit/94098d02) + - add router-page.d.ts to git [将router-page.d.ts添加git提交]  -  by **Soybean** [(7a580)](https://github.com/soybeanjs/soybean-admin-antd/commit/7a580355) + - fix router when the dynamic routes api was failed [修复当动态路由接口失败后路由异常问题]  -  by **Soybean** [(f2b58)](https://github.com/soybeanjs/soybean-admin-antd/commit/f2b580fc) + - fix login success message [修复登录成功的消息提示]  -  by **Soybean** [(81039)](https://github.com/soybeanjs/soybean-admin-antd/commit/810398ab) + - 修复tabs在static路由模式下可以关闭首页  -  by **燕博文** [(7211a)](https://github.com/soybeanjs/soybean-admin-antd/commit/7211a17a) + - 修复动态路由模式下路由不排序的问题  -  by **“青菜白玉汤”** [(58b27)](https://github.com/soybeanjs/soybean-admin-antd/commit/58b27c96) + - fix eslint svg cause incorrect icon render  -  by **Soybean** [(0b5af)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b5afda2) + - sortRoutes recursively  -  by **sunhao1256** [(91889)](https://github.com/soybeanjs/soybean-admin-antd/commit/91889414) + - not only `/login` claim dynamic path scenario , but also others , eg:/user/1  -  by **sunhao1256** [(60598)](https://github.com/soybeanjs/soybean-admin-antd/commit/60598915) + - the length of routes children list should greater than 0  -  by **HuangZheng** [(e1afc)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1afc10b) + - fix pwa logo  -  by **Soybean** [(bf2f6)](https://github.com/soybeanjs/soybean-admin-antd/commit/bf2f6172) + - fix github bug-report  -  by **Soybean** [(f73e3)](https://github.com/soybeanjs/soybean-admin-antd/commit/f73e3f64) + - fix router guide [修复路由跳转异常] fixed #216  -  by **Soybean** in https://github.com/soybeanjs/soybean-admin-antd/issues/216 [(59578)](https://github.com/soybeanjs/soybean-admin-antd/commit/5957833a) + - fix better-mock usage [修复better-mock用法]  -  by **Soybean** [(c5764)](https://github.com/soybeanjs/soybean-admin-antd/commit/c57640ac) + - tsconfig missing isolatedModules  -  by **Kirk Lin** [(ab49a)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab49afd3) + - fix mockjs [修复mockjs]  -  by **Soybean** [(9b19f)](https://github.com/soybeanjs/soybean-admin-antd/commit/9b19f96f) + - add prod mockjs switch [添加生产模式的mockjs的开关]  -  by **Soybean** [(9f563)](https://github.com/soybeanjs/soybean-admin-antd/commit/9f5638f1) + - 修复面包屑导航下拉菜单语言显示问题  -  by **cc** [(ee8fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/ee8fa048) + - hide the drawer when it is initial mobile mode [初始化时为移动端布局则隐藏侧边栏] fixed #238  -  by **Soybean** in https://github.com/soybeanjs/soybean-admin-antd/issues/238 [(0abde)](https://github.com/soybeanjs/soybean-admin-antd/commit/0abde46e) + - fix userRoleOptions  -  by **Soybean** [(2ca2b)](https://github.com/soybeanjs/soybean-admin-antd/commit/2ca2b766) + - fix set tab title (fixed #256)  -  by **Soybean** in https://github.com/soybeanjs/soybean-admin-antd/issues/256 [(13f6c)](https://github.com/soybeanjs/soybean-admin-antd/commit/13f6cd8e) + - correct the lang file name & add recommend vscode plugin i18n-ally  -  by @soybeanjs [(864ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/864ec473) + - fix reload button animate  -  by @soybeanjs [(41f23)](https://github.com/soybeanjs/soybean-admin-antd/commit/41f23386) + - 修复路由命名为包含关系时导致导航数据出错的问题  -  by @Particaly [(76636)](https://github.com/soybeanjs/soybean-admin-antd/commit/766369f9) + - fix elegant-router plugin  -  by @soybeanjs [(282b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/282b6027) + - keep hsla and rgba consistent with unocss  -  by @soybeanjs [(566cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/566cce27) + - fix menu style  -  by @soybeanjs [(b80a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b80a0866) + - update tab label when locale change  -  by @soybeanjs [(50b72)](https://github.com/soybeanjs/soybean-admin-antd/commit/50b722ce) + - fix menu style  -  by @soybeanjs [(231fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/231fc8b4) + - fix zIndex  -  by @soybeanjs [(eed33)](https://github.com/soybeanjs/soybean-admin-antd/commit/eed33a6c) + - fix ThemeButton tooltip trigger  -  by @soybeanjs [(19671)](https://github.com/soybeanjs/soybean-admin-antd/commit/196710dd) + - fix menu collapsed  -  by @soybeanjs [(586d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/586d6d71) + - fix siderCollapse  -  by @soybeanjs [(d348b)](https://github.com/soybeanjs/soybean-admin-antd/commit/d348bd81) + - fix tab click when is mobile  -  by @soybeanjs [(ac6c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/ac6c324b) + - notification add auto close  -  by @soybeanjs [(2cfcb)](https://github.com/soybeanjs/soybean-admin-antd/commit/2cfcb440) + - hide some content when is mobile layout  -  by @soybeanjs [(b175f)](https://github.com/soybeanjs/soybean-admin-antd/commit/b175fea6) + - fix breadcrumb when is not route menu  -  by @soybeanjs [(59d35)](https://github.com/soybeanjs/soybean-admin-antd/commit/59d35119) + - fix button style  -  by @soybeanjs [(93f18)](https://github.com/soybeanjs/soybean-admin-antd/commit/93f1806e) + - fix themeVars color  -  by @soybeanjs [(6329c)](https://github.com/soybeanjs/soybean-admin-antd/commit/6329c5d4) + - fix cached tabs locale  -  by @soybeanjs [(0973b)](https://github.com/soybeanjs/soybean-admin-antd/commit/0973b083) + - fix inverted menu when is horizontal-mix  -  by @soybeanjs [(1530d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1530dae3) + - fix horizontal menu style  -  by @soybeanjs [(b3fce)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3fce710) + - theme setting adapter mobile  -  by @soybeanjs [(8c729)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c72966e) + - fix theme colors  -  by @soybeanjs [(ab60e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab60edc7) + - fix customize info color  -  by @soybeanjs [(f0f02)](https://github.com/soybeanjs/soybean-admin-antd/commit/f0f0236a) + - fix scrollbar style  -  by @soybeanjs [(cadf2)](https://github.com/soybeanjs/soybean-admin-antd/commit/cadf2e8f) + - fix ColorPicker  -  by @soybeanjs [(c735f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c735fd3e) + - sider inverted visible  -  by @soybeanjs [(7b46f)](https://github.com/soybeanjs/soybean-admin-antd/commit/7b46f2b1) + - fix override theme  -  by @soybeanjs [(76eda)](https://github.com/soybeanjs/soybean-admin-antd/commit/76edab31) + - fix default menu icon  -  by @soybeanjs [(68e0d)](https://github.com/soybeanjs/soybean-admin-antd/commit/68e0d19a) + - fix vertical-mix menu when collapse  -  by @soybeanjs [(c4e64)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4e6471c) + - fix layout-card  -  by @soybeanjs [(b2b92)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2b9256a) + - rename zh-ch  -  by @soybeanjs [(a8a77)](https://github.com/soybeanjs/soybean-admin-antd/commit/a8a77ea5) + - fix scripts  -  by @soybeanjs [(780eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/780ebf5a) + - Fix welcome notification not closing  -  by @Azir-11 [(748cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/748cfa2c) + - fix i18n vscode settings  -  by @soybeanjs [(fbf4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/fbf4cc43) + - add duration of login success notification  -  by @soybeanjs [(1335d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1335d47a) + - fix menu indent  -  by @soybeanjs [(87143)](https://github.com/soybeanjs/soybean-admin-antd/commit/87143172) + - fix theme mode segment  -  by @soybeanjs [(2372d)](https://github.com/soybeanjs/soybean-admin-antd/commit/2372dc9b) + - fix app loading theme color  -  by @soybeanjs [(0ba19)](https://github.com/soybeanjs/soybean-admin-antd/commit/0ba19d54) + - fix app loading theme color  -  by @soybeanjs [(1ad8d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ad8dbf2) + - fix page about style in mobile  -  by @soybeanjs [(8b6de)](https://github.com/soybeanjs/soybean-admin-antd/commit/8b6de484) + - fix themeDrawer darkMode segement  -  by @soybeanjs [(1b5ca)](https://github.com/soybeanjs/soybean-admin-antd/commit/1b5caa08) + - fix themeDrawer copy  -  by @soybeanjs [(b3779)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3779a63) + - remove space in tab content  -  by @soybeanjs [(4aae6)](https://github.com/soybeanjs/soybean-admin-antd/commit/4aae6a52) + - fix horizontal menu  -  by @soybeanjs [(d886e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d886e50f) + - perf card style  -  by @soybeanjs [(c1afb)](https://github.com/soybeanjs/soybean-admin-antd/commit/c1afb9dc) + - fix base-menu style  -  by @soybeanjs [(dcbb3)](https://github.com/soybeanjs/soybean-admin-antd/commit/dcbb3020) + - remove space in tab content  -  by @soybeanjs [(16c76)](https://github.com/soybeanjs/soybean-admin-antd/commit/16c765f7) + - fix add import $t  -  by @soybeanjs [(2e36f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2e36fbfb) + - fix manage_user title  -  by @soybeanjs [(7770b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7770b378) + - default proxy prefix  -  by @smileluck [(da246)](https://github.com/soybeanjs/soybean-admin-antd/commit/da246427) + - fix request msg  -  by @soybeanjs [(ae6b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/ae6b6134) + - Fix the issue of tab error displaying parent localIcon  -  by @Azir-11 [(a9c98)](https://github.com/soybeanjs/soybean-admin-antd/commit/a9c98d96) + - The matched value of TabRoute should be optional  -  by @Azir-11 [(e6fed)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6fed1fd) + - fix build [unocss]: build failed to load icon "close", fixed #319  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/319 [(c18d8)](https://github.com/soybeanjs/soybean-admin-antd/commit/c18d82f9) + - fix resolve alias  -  by @soybeanjs [(3bdcb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3bdcbc71) + - Missing default value for tab icon  -  by @Azir-11 [(72a46)](https://github.com/soybeanjs/soybean-admin-antd/commit/72a4679c) + - add route icon: fucntion_hide-child  -  by @soybeanjs [(0a3ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/0a3efe34) + - fix table x-scroll. fixed #324  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/324 [(c7e2c)](https://github.com/soybeanjs/soybean-admin-antd/commit/c7e2c559) + - Fix the logic of root route redirection to home  -  by **恕瑞玛的皇帝** [(0123c)](https://github.com/soybeanjs/soybean-admin-antd/commit/0123c37d) + - Fix homepage mount error under dynamic routing  -  by **恕瑞玛的皇帝** [(9cf2a)](https://github.com/soybeanjs/soybean-admin-antd/commit/9cf2a513) + - fix repeat home tab  -  by @soybeanjs [(bccd6)](https://github.com/soybeanjs/soybean-admin-antd/commit/bccd6cb3) + - fix proxy config  -  by @soybeanjs [(c8019)](https://github.com/soybeanjs/soybean-admin-antd/commit/c8019c4f) + - fix proxy config  -  by @soybeanjs [(ffc95)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffc95d2b) + - fix request msg  -  by @soybeanjs [(47b54)](https://github.com/soybeanjs/soybean-admin-antd/commit/47b54b06) + - fix tab error displaying parent localIcon  -  by @soybeanjs [(9d112)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d11258a) + - fix build [unocss]: build failed to load icon "close"  -  by @soybeanjs [(6a5aa)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a5aaecf) + - fix home when is dynamic mode router  -  by @soybeanjs [(3c229)](https://github.com/soybeanjs/soybean-admin-antd/commit/3c2296e2) + - fix table row-key ts type  -  by @soybeanjs [(0cc8f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0cc8f05a) + - fix class name conflict with unocss icon  -  by @soybeanjs [(455e4)](https://github.com/soybeanjs/soybean-admin-antd/commit/455e48f7) + - fix repeat routes  -  by @soybeanjs [(2c543)](https://github.com/soybeanjs/soybean-admin-antd/commit/2c543f19) + - fix route init  -  by @soybeanjs [(23a40)](https://github.com/soybeanjs/soybean-admin-antd/commit/23a4098b) + - fix pin-toggler toolTip zIndex  -  by @soybeanjs [(f89e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/f89e6c03) + - fix flatRequest error type. fixed #376  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/376 [(1ec5e)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ec5ea0f) + - add maxWidth for GlobalTab to fix bg with gap. fixed #350  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/350 [(cc539)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc539974) + - unify border-radius of Tag. fixed #378  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/378 [(2f15a)](https://github.com/soybeanjs/soybean-admin-antd/commit/2f15a2ac) + - fix menu edit rules  -  by @paynezhuang [(00105)](https://github.com/soybeanjs/soybean-admin-antd/commit/001059cc) + - fix SvgIcon inheritAttrs warning  -  by @soybeanjs [(efc0e)](https://github.com/soybeanjs/soybean-admin-antd/commit/efc0e25c) + - fix axios createRequest: add default state  -  by @soybeanjs [(d6eda)](https://github.com/soybeanjs/soybean-admin-antd/commit/d6eda8f9) + - fix homeTab closeRight and disable colseLeft  -  by @soybeanjs [(53f61)](https://github.com/soybeanjs/soybean-admin-antd/commit/53f61662) + - fix GlobalBreadcrumb warning  -  by @soybeanjs [(dd6fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/dd6fce3b) + - add maxWidth for GlobalTab to fix bg with gap  -  by @soybeanjs [(423ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/423ea0da) + - fix css var is inserted repeatedly  -  by @soybeanjs [(e58cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/e58cf266) + - fix SvgIcon inheritAttrs warning  -  by @soybeanjs [(f4305)](https://github.com/soybeanjs/soybean-admin-antd/commit/f430584e) + - fix event name  -  by @soybeanjs [(642b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/642b6f8d) + - update union-key.d.ts  -  by @soybeanjs [(60bef)](https://github.com/soybeanjs/soybean-admin-antd/commit/60beff7e) + - fix axios createRequest: add default state  -  by @soybeanjs [(466bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/466bc7aa) + - fix update theme color  -  by @soybeanjs [(27c53)](https://github.com/soybeanjs/soybean-admin-antd/commit/27c53cd6) + - fix CHANGELOG versions  -  by @soybeanjs [(d9af5)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9af5aa2) + - fix disabled page animate  -  by @soybeanjs [(23f28)](https://github.com/soybeanjs/soybean-admin-antd/commit/23f283aa) + - fix routes data when role is change. fixed #391  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/391 [(cb83d)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb83d6d9) + - fix tabs data when role is change. fixed #392  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/392 [(04aa0)](https://github.com/soybeanjs/soybean-admin-antd/commit/04aa0972) + - recovery pnpm-lock.yaml  -  by @soybeanjs [(c6952)](https://github.com/soybeanjs/soybean-admin-antd/commit/c695208f) + - added responseType judgment. #396  -  by **alleycharming** in https://github.com/soybeanjs/soybean-admin-antd/issues/396 [(82eab)](https://github.com/soybeanjs/soybean-admin-antd/commit/82eabab7) + - supply $t import statement  -  by @soybeanjs [(b2660)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2660358) + - fix type error  -  by @soybeanjs [(77c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/77c20238) + - fix mix-menu blank. fixed #389 & cache mixMenuFixed  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/389 [(93c7f)](https://github.com/soybeanjs/soybean-admin-antd/commit/93c7ff71) + - text level low. #409  -  by **alleycharming** in https://github.com/soybeanjs/soybean-admin-antd/issues/409 [(3ddb1)](https://github.com/soybeanjs/soybean-admin-antd/commit/3ddb17a0) + - menu fixedIndexInTab default null  -  by @paynezhuang [(3d10e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3d10ef1a) + - fix tab fixedIndex as null case  -  by @paynezhuang [(4708e)](https://github.com/soybeanjs/soybean-admin-antd/commit/4708eded) + - recovery the layout config before is mobile. fixed #408, fixed #361  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/408 and https://github.com/soybeanjs/soybean-admin-antd/issues/361 [(dae2a)](https://github.com/soybeanjs/soybean-admin-antd/commit/dae2aa55) + - fix manage page drawer operate about data reset. fixed #415, fixed #417  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/415 and https://github.com/soybeanjs/soybean-admin-antd/issues/417 [(f4513)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4513e1e) + - fix menu-toggler zIndex  -  by @soybeanjs [(7bd43)](https://github.com/soybeanjs/soybean-admin-antd/commit/7bd43df5) + - fix manage_menu modal style  -  by @soybeanjs [(60f3b)](https://github.com/soybeanjs/soybean-admin-antd/commit/60f3b140) + - fix menu data when role is changed. fixed #391  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/391 [(3b47b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b47b5a5) + - fix useRouter. fixed #436  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/436 [(0774a)](https://github.com/soybeanjs/soybean-admin-antd/commit/0774a515) + - add error handle when get routes in dynamic route mode. fixed 440  -  by @soybeanjs [(57b4a)](https://github.com/soybeanjs/soybean-admin-antd/commit/57b4a9d5) + - fix header style & fix button highlight when click global-tab. fixed #446  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/446 [(64fc0)](https://github.com/soybeanjs/soybean-admin-antd/commit/64fc0996) + - fix multi tab page only render once. fixed #441  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/441 [(e379d)](https://github.com/soybeanjs/soybean-admin-antd/commit/e379d6ce) + - fix click menu search. fixed #466, close #467  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/466 and https://github.com/soybeanjs/soybean-admin-antd/issues/467 [(8efdb)](https://github.com/soybeanjs/soybean-admin-antd/commit/8efdb10d) + - fix reCacheRoute. fixed #464  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/464 [(59faf)](https://github.com/soybeanjs/soybean-admin-antd/commit/59faf152) + - fix register name, CodeLogin => Register  -  by @m-xlsea in https://github.com/soybeanjs/soybean-admin-antd/issues/478 [(ddf38)](https://github.com/soybeanjs/soybean-admin-antd/commit/ddf3823a) + - fix disabled page animate  -  by @soybeanjs [(e6910)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6910885) + - fix routes data when role is change  -  by @soybeanjs [(03c80)](https://github.com/soybeanjs/soybean-admin-antd/commit/03c80750) + - fix tabs data when role is change  -  by @soybeanjs [(9fd89)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fd89aa3) + - add missing `$t` import  -  by @soybeanjs [(8f9ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f9ee2e5) + - add responseType judgment  -  by @soybeanjs [(2246f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2246f78d) + - fix mix-menu blank & cache mixMenuFixed  -  by @soybeanjs [(9fdb6)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fdb6c10) + - fix PinToggler label  -  by @soybeanjs [(b1f9c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b1f9c4ce) + - recovery the layout config before is mobile  -  by @soybeanjs [(851ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/851ae38c) + - fix manage page drawer operate about data reset  -  by @soybeanjs [(91dfa)](https://github.com/soybeanjs/soybean-admin-antd/commit/91dfa571) + - fix menu data when role is changed  -  by @soybeanjs [(7cc5f)](https://github.com/soybeanjs/soybean-admin-antd/commit/7cc5f9c2) + - fix useRouter in tab store  -  by @soybeanjs [(962c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/962c403b) + - fix header style & fix button highlight when click global-tab  -  by @soybeanjs [(f2983)](https://github.com/soybeanjs/soybean-admin-antd/commit/f298388c) + - fix multi tab page only render once  -  by @soybeanjs [(b98b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b98b075f) + - fix login Register component name  -  by @soybeanjs [(a3ba5)](https://github.com/soybeanjs/soybean-admin-antd/commit/a3ba5166) + - fix get user info when page reload  -  by @soybeanjs [(ff51b)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff51b72d) + - fix setupAppVersionNotification render  -  by @soybeanjs [(6a6eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a6eb9af) + - fix get user info when page reload  -  by @soybeanjs [(0f6b7)](https://github.com/soybeanjs/soybean-admin-antd/commit/0f6b73fb) + - fix setupAppVersionNotification render  -  by @soybeanjs [(63d5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/63d5dc50) + - hide AppVersionNotification in DEV mode  -  by @sigma-plus in https://github.com/soybeanjs/soybean-admin-antd/issues/482 [(62592)](https://github.com/soybeanjs/soybean-admin-antd/commit/62592872) + - fix menu-toggler hidden in mobile layout. fixed #483  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/483 [(4470c)](https://github.com/soybeanjs/soybean-admin-antd/commit/4470cb4e) + - hide AppVersionNotification in DEV mode  -  by @soybeanjs [(e3d91)](https://github.com/soybeanjs/soybean-admin-antd/commit/e3d91dfc) + - fix menu-toggler hidden in mobile layout  -  by @soybeanjs [(a73d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/a73d2e1c) + - fix mobile browser theme issue by adding color-scheme meta tag to index.html  -  by @KickCashew in https://github.com/soybeanjs/soybean-admin-antd/issues/488 [(c2125)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2125652) + - fix mobile browser theme issue by adding color-scheme meta tag to index.html  -  by @KickCashew in https://github.com/soybeanjs/soybean-admin-antd/issues/27 [(6bf97)](https://github.com/soybeanjs/soybean-admin-antd/commit/6bf972db) + - Fix secondary directory components is empty  -  by @paynezhuang in https://github.com/soybeanjs/soybean-admin-antd/issues/29 [(fb48f)](https://github.com/soybeanjs/soybean-admin-antd/commit/fb48f413) + - Fix secondary directory components is empty  -  by @paynezhuang in https://github.com/soybeanjs/soybean-admin-antd/issues/491 [(aabb2)](https://github.com/soybeanjs/soybean-admin-antd/commit/aabb2a49) + - Fix the issue of abnormal tab caching after logout. fixed #495  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/495 [(3eeac)](https://github.com/soybeanjs/soybean-admin-antd/commit/3eeace94) + - Fix the issue of abnormal tab caching after logout  -  by @soybeanjs [(e6349)](https://github.com/soybeanjs/soybean-admin-antd/commit/e63490e9) + - request modal title use i18n. fixed #507  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/507 [(f7de3)](https://github.com/soybeanjs/soybean-admin-antd/commit/f7de3fd0) + - add `getDataByPage` for `useTable`. fixed #499  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/499 [(425c6)](https://github.com/soybeanjs/soybean-admin-antd/commit/425c69ac) + - fix login redirect to routeHome when routeHome of dynamic route is not same as static route. fixed #511  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/511 [(49f60)](https://github.com/soybeanjs/soybean-admin-antd/commit/49f60b2d) + - request modal title use i18n  -  by @soybeanjs [(f97e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/f97e74ec) + - add `getDataByPage` for `useTable`  -  by @soybeanjs [(cf265)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf2659d1) + - fix login redirect to routeHome when routeHome of dynamic route is not same as static route  -  by @soybeanjs [(f6c66)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6c66ec2) + - fix manage page edit data. fixed #32  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/32 [(740d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/740d6f5d) + - fix the issue of abnormal width of the sidebar in the top menu mix and reverse mode  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/562 [(c4695)](https://github.com/soybeanjs/soybean-admin-antd/commit/c469512b) + - fix HorizontalMixMenu inverted. fixed #563  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/563 [(4e55b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e55b0e9) + - fix vertical-menu will not render when the layout is from mobile  -  by @soybeanjs [(84027)](https://github.com/soybeanjs/soybean-admin-antd/commit/84027347) + - fix vertical-mix menu selected  -  by @soybeanjs [(59f07)](https://github.com/soybeanjs/soybean-admin-antd/commit/59f07d8a) + - fix watermark settings  -  by @soybeanjs [(5646a)](https://github.com/soybeanjs/soybean-admin-antd/commit/5646a50d) + - fix menu style  -  by @soybeanjs [(4355b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4355b6e4) + - avoid retrieving cached HTML  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/605 [(ef6cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/ef6cf93d) + - fix login redirect  -  by @soybeanjs [(3830e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3830ec7a) + - fix vertical-mix-menu when sider collapse. fixed #608  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/608 [(c3f1f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c3f1f698) + - fix breadcrumb when activeMenu is parent menu. fixed #589  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/589 [(79b2a)](https://github.com/soybeanjs/soybean-admin-antd/commit/79b2a28b) + - fix refresh token when meet multi requests. fixed #581  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/581 [(27b52)](https://github.com/soybeanjs/soybean-admin-antd/commit/27b5222c) + - fix abnormal width of the sidebar in the top menu mix and reverse mode  -  by @soybeanjs [(0abce)](https://github.com/soybeanjs/soybean-admin-antd/commit/0abce882) + - fix watermark settings  -  by @soybeanjs [(dbe8e)](https://github.com/soybeanjs/soybean-admin-antd/commit/dbe8ec65) + - avoid retrieving cached HTML  -  by @soybeanjs [(75df1)](https://github.com/soybeanjs/soybean-admin-antd/commit/75df11c0) + - fix breadcrumb when activeMenu is parent menu  -  by @soybeanjs [(49092)](https://github.com/soybeanjs/soybean-admin-antd/commit/4909291b) + - fix refresh token when meet multi requests  -  by @soybeanjs [(5ae17)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ae17e6f) + - fix click global-tab in iPad. fixed #624  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/624 [(04d05)](https://github.com/soybeanjs/soybean-admin-antd/commit/04d05647) + - when the roles filter submenu is empty, the parent menu is not excluded. fixed #621.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/626 and https://github.com/soybeanjs/soybean-admin-antd/issues/621 [(0ac95)](https://github.com/soybeanjs/soybean-admin-antd/commit/0ac95bdc) + - fix click global-tab in iPad  -  by @soybeanjs [(740cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/740cf4cd) + - when the roles filter submenu is empty, the parent menu is not excluded  -  by @soybeanjs [(6b2fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b2fc0a4) + - fix global-tab click conflict with contextmenu  -  by @soybeanjs [(c0e87)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0e87958) + - fix global-tab click conflict with contextmenu  -  by @soybeanjs [(3e72c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e72c3b4) + - fix issue with 'Remind Me Later' button being unclickable. fixed #46  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/47 and https://github.com/soybeanjs/soybean-admin-antd/issues/46 [(a4e8f)](https://github.com/soybeanjs/soybean-admin-antd/commit/a4e8f296) + - fix sass usage  -  by **Redon** in https://github.com/soybeanjs/soybean-admin-antd/issues/49 [(599db)](https://github.com/soybeanjs/soybean-admin-antd/commit/599db449) + - fix route guard hook `onRouteSwitchWhenLoggedIn`. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(ab985)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab9858c7) + - check if init userInfo when initAuthRoute. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(9f4fb)](https://github.com/soybeanjs/soybean-admin-antd/commit/9f4fb8c3) +- **projects): fix(projects**: + - fix login redirect  -  by @soybeanjs [(5ccdb)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ccdb17e) +- **route**: + - 当为左侧混合菜单时activeMenu无效情况  -  by **燕博文** [(3e4f9)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e4f9e28) +- **styles**: + - fix toggle-lang bg  -  by **Soybean** [(47309)](https://github.com/soybeanjs/soybean-admin-antd/commit/473095b0) + - 用户管理页面布局自适应屏幕高度 (fixed #253)  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/253 [(0f7b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/0f7b9d5e) + - fix css var is inserted repeatedly  -  by **燕博文** [(769d8)](https://github.com/soybeanjs/soybean-admin-antd/commit/769d84a7) + - fix useTable type  -  by @soybeanjs [(07124)](https://github.com/soybeanjs/soybean-admin-antd/commit/071241f8) + - fix FirstLevelMenu style. fixed #450  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/450 [(db64b)](https://github.com/soybeanjs/soybean-admin-antd/commit/db64b0e2) + - fix PinToggler style. fixed #451  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/451 [(42b12)](https://github.com/soybeanjs/soybean-admin-antd/commit/42b121a1) + - fix FirstLevelMenu style  -  by @soybeanjs [(5df82)](https://github.com/soybeanjs/soybean-admin-antd/commit/5df82d1b) + - fix PinToggler style  -  by @soybeanjs [(593ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/593ceea3) +- **svg-icon**: + - 自定义图标在Dropdown组件下hover状态无法显示图标  -  by **燕博文** [(0523f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0523f083) +- **types**: + - 修复naive组件回调函数参数类型错误  -  by **Soybean** [(66728)](https://github.com/soybeanjs/soybean-admin-antd/commit/667282f8) + - 数据类型 EnumDataType.boolean 为 [object Boolean]  -  by **liujunzheng** [(e9b55)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9b55608) + - 修复TS类型错误  -  by **Soybean** [(45d31)](https://github.com/soybeanjs/soybean-admin-antd/commit/45d31a0f) + - 添加dotEnv类型的非空判断  -  by **Soybean** [(cff11)](https://github.com/soybeanjs/soybean-admin-antd/commit/cff11d91) + - Fixed the reference type error  -  by **dodu2014** in https://github.com/soybeanjs/soybean-admin-antd/issues/551 [(3e2a9)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e2a993d) + - fix data type of useHookTable  -  by @soybeanjs [(276ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/276ea7fa) + - fix the type of TableApiFn  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/599 [(26c93)](https://github.com/soybeanjs/soybean-admin-antd/commit/26c93dff) + - Fixed the reference type error  -  by @soybeanjs [(6b868)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b868618) + - fix data type of useHookTable  -  by @soybeanjs [(3dd78)](https://github.com/soybeanjs/soybean-admin-antd/commit/3dd78d4f) +- **utils**: + - utils函数名称更正  -  by **Soybean** [(68f4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/68f4d012) + - 修复iconifyRender  -  by **Soybean** [(c37d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/c37d0ac7) + - make AxiosRequestConfig optional for request.handleDelete()  -  by **guuuuo** [(4a6fe)](https://github.com/soybeanjs/soybean-admin-antd/commit/4a6fec8a) + - modalLogout bug when esc is pressed  -  by @sigma-plus in https://github.com/soybeanjs/soybean-admin-antd/issues/470 [(bd69c)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd69c00e) + - fix `isPC`. fixed #644  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/644 [(47264)](https://github.com/soybeanjs/soybean-admin-antd/commit/4726498f) + - fix `isPC`  -  by @soybeanjs [(76f61)](https://github.com/soybeanjs/soybean-admin-antd/commit/76f61609) +- **view-manage-role**: + - fix PopConfirm content to title  -  by @zyhnbyyds [(d95bd)](https://github.com/soybeanjs/soybean-admin-antd/commit/d95bd84b) +- **多页签**: + - 在pc模式下右键某个多页签会切换路由  -  by **Yanbowen** [(a4394)](https://github.com/soybeanjs/soybean-admin-antd/commit/a4394dc3) + +###    🔥 Performance + +- refresh-koken命名  -  by **“Southliu”** [(17155)](https://github.com/soybeanjs/soybean-admin-antd/commit/17155047) +- **components**: + - 添加更多主题颜色设置模态窗的层级  -  by **xiaotao2018** [(ee7eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/ee7eb3ac) + - 添加更多主题颜色设置模态窗的层级,z-index为int  -  by **xiaotao2018** [(e2d65)](https://github.com/soybeanjs/soybean-admin-antd/commit/e2d65543) + - Optimize internationalized menu search code  -  by **燕博文** [(8c1ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c1ef4b0) + - Optimize menu search code  -  by **燕博文** [(296a2)](https://github.com/soybeanjs/soybean-admin-antd/commit/296a2d2f) + - perf count-to  -  by @soybeanjs [(b2c61)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2c61f03) + - components name is converted to uppercase  -  by **燕博文** [(04aa1)](https://github.com/soybeanjs/soybean-admin-antd/commit/04aa10b4) + - perf global-search  -  by @soybeanjs [(72745)](https://github.com/soybeanjs/soybean-admin-antd/commit/72745229) +- **hooks**: + - perf use-table  -  by **Soybean** [(33180)](https://github.com/soybeanjs/soybean-admin-antd/commit/3318041b) + - perf useHookTable  -  by @soybeanjs [(809fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/809fa857) + - perf useSignal  -  by @soybeanjs [(5d45c)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d45cef1) +- **project**: + - Initializing the static routing function does not require asynchronization  -  by **CHENZL** in https://github.com/soybeanjs/soybean-admin-antd/issues/493 [(2198b)](https://github.com/soybeanjs/soybean-admin-antd/commit/2198b982) +- **projects**: + - 添加windicss指定的扫描目录,提升构建性能  -  by **Soybean** [(8e6b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e6b0b29) + - complete dynamic route translate [补充动态路由的翻译]  -  by **Soybean** [(7b746)](https://github.com/soybeanjs/soybean-admin-antd/commit/7b746fa0) + - move changing document title by locale to global event of composables & add appLoading unmount  -  by **Soybean** [(08e19)](https://github.com/soybeanjs/soybean-admin-antd/commit/08e194ef) + - remove useless code  -  by **Soybean** [(eb8e4)](https://github.com/soybeanjs/soybean-admin-antd/commit/eb8e49e2) + - use transformObjectToOption to generate option of object labels  -  by **Soybean** [(da611)](https://github.com/soybeanjs/soybean-admin-antd/commit/da611fb1) + - add type declaration for document startViewTransition  -  by **Soybean** [(d3ebe)](https://github.com/soybeanjs/soybean-admin-antd/commit/d3ebe950) + - remove system logo fill  -  by @soybeanjs [(e02d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/e02d025e) + - perf code  -  by @soybeanjs [(c9e34)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9e34f61) + - remove as any  -  by @soybeanjs [(7f61b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f61bdcd) + - perf code  -  by @soybeanjs [(3f22e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f22efa1) + - perf code  -  by @soybeanjs [(cb369)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb3694c4) + - perf css of base-menu  -  by @soybeanjs [(4046a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4046a8bd) + - perf theme store  -  by @soybeanjs [(b0d95)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0d95f13) + - perf code  -  by @soybeanjs [(324cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/324cffd9) + - perf code  -  by @soybeanjs [(c2aae)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2aaea97) + - perf code  -  by @soybeanjs [(8081e)](https://github.com/soybeanjs/soybean-admin-antd/commit/8081e19e) + - env config  -  by @soybeanjs [(07423)](https://github.com/soybeanjs/soybean-admin-antd/commit/07423267) + - env config  -  by @soybeanjs [(1bac3)](https://github.com/soybeanjs/soybean-admin-antd/commit/1bac3b78) + - add detailed annotations for route role  -  by @soybeanjs [(2a0ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/2a0ec388) + - add detailed annotations for route role  -  by @soybeanjs [(f6bab)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6bab0cc) + - perf code  -  by @soybeanjs [(5c49d)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c49d245) + - remove useless file  -  by @soybeanjs [(da280)](https://github.com/soybeanjs/soybean-admin-antd/commit/da280765) + - remove useless file  -  by @soybeanjs [(c624f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c624f325) + - remove @soybeanjs/cli  -  by @soybeanjs [(41349)](https://github.com/soybeanjs/soybean-admin-antd/commit/41349555) + - perf card style  -  by @soybeanjs [(9895a)](https://github.com/soybeanjs/soybean-admin-antd/commit/9895a379) + - echarts loading style  -  by @soybeanjs [(456c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/456c318a) + - echarts loading style  -  by @soybeanjs [(dca53)](https://github.com/soybeanjs/soybean-admin-antd/commit/dca53b0b) + - perf page manage_role, useTable  -  by @soybeanjs [(39aa7)](https://github.com/soybeanjs/soybean-admin-antd/commit/39aa7aa2) + - perf table columns style  -  by @soybeanjs [(babdb)](https://github.com/soybeanjs/soybean-admin-antd/commit/babdb5d5) + - perf page manage_menu style  -  by @soybeanjs [(0aa75)](https://github.com/soybeanjs/soybean-admin-antd/commit/0aa75c04) + - perf code  -  by @soybeanjs [(7fa87)](https://github.com/soybeanjs/soybean-admin-antd/commit/7fa87f53) + - perf code  -  by @soybeanjs [(05db8)](https://github.com/soybeanjs/soybean-admin-antd/commit/05db8c08) + - perf code  -  by @soybeanjs [(dc24a)](https://github.com/soybeanjs/soybean-admin-antd/commit/dc24a367) + - perf manage page style  -  by @soybeanjs [(779ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/779ba4e4) + - perf code  -  by @soybeanjs [(8b960)](https://github.com/soybeanjs/soybean-admin-antd/commit/8b9607ff) + - remove useless code  -  by @soybeanjs [(3115e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3115ef4d) + - perf code  -  by @soybeanjs [(a1220)](https://github.com/soybeanjs/soybean-admin-antd/commit/a122088a) + - perf manage menu  -  by @soybeanjs [(71f2c)](https://github.com/soybeanjs/soybean-admin-antd/commit/71f2c553) + - manage menu: add transform to component  -  by @soybeanjs [(0abbf)](https://github.com/soybeanjs/soybean-admin-antd/commit/0abbfa5d) + - perf code  -  by @soybeanjs [(a0bad)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0bad57a) + - perf code  -  by @soybeanjs [(b7f07)](https://github.com/soybeanjs/soybean-admin-antd/commit/b7f07491) + - remove useless prop `title` of `NDrawer`  -  by @soybeanjs [(fdde6)](https://github.com/soybeanjs/soybean-admin-antd/commit/fdde679c) + - add tsconfig.json for @sa/color-palette  -  by @soybeanjs [(d460e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d460e5cc) + - perf judgement the fixed tab  -  by @soybeanjs [(b3e9b)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3e9bbae) + - perf judgement the fixed tab  -  by @soybeanjs [(90c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/90c205d4) + +###    🛠 Optimizations + +- **components**: + - accuracy draggable area for TableColumnSetting with animation  -  by @orangelckc in https://github.com/soybeanjs/soybean-admin-antd/issues/465 [(2aa85)](https://github.com/soybeanjs/soybean-admin-antd/commit/2aa85c6f) + - ButtonIcon with smarter class merging and tippy  -  by @mufeng889 [(95960)](https://github.com/soybeanjs/soybean-admin-antd/commit/95960b0c) + - accuracy draggable area for TableColumnSetting with animation  -  by @soybeanjs [(8a2e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/8a2e0ebd) +- **projects**: + - remove deprecated code  -  by @soybeanjs [(72ccb)](https://github.com/soybeanjs/soybean-admin-antd/commit/72ccb6bf) + - optimize code  -  by @soybeanjs [(bc8dc)](https://github.com/soybeanjs/soybean-admin-antd/commit/bc8dc47d) + - unocss border shortcut  -  by @soybeanjs [(40d0f)](https://github.com/soybeanjs/soybean-admin-antd/commit/40d0f8ac) + - optimize RouteMeta remarks  -  by @soybeanjs [(ffb48)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffb48b15) + - optimize manage_menu  -  by @soybeanjs [(bf406)](https://github.com/soybeanjs/soybean-admin-antd/commit/bf406425) + - remove deprecated code  -  by @soybeanjs [(00361)](https://github.com/soybeanjs/soybean-admin-antd/commit/00361721) + - unocss border shortcut  -  by @soybeanjs [(4ebeb)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ebeb908) + - optimize table scrollConfig. fixed #25  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/25 [(d0f8e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0f8e55f) + - optimize table rowSelection  -  by @soybeanjs [(49c57)](https://github.com/soybeanjs/soybean-admin-antd/commit/49c572b1) + - optimize `setupAppVersionNotification`  -  by @soybeanjs [(b5a72)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5a723cb) + - optimize `setupAppVersionNotification`  -  by @soybeanjs [(f061d)](https://github.com/soybeanjs/soybean-admin-antd/commit/f061d8b8) + - get buildTime with timezone 'Asia/Shanghai'  -  by @soybeanjs [(069fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/069fa8a8) + - get buildTime with timezone 'Asia/Shanghai'  -  by @soybeanjs [(b256a)](https://github.com/soybeanjs/soybean-admin-antd/commit/b256a3e0) + - optimize code  -  by @soybeanjs [(b94ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/b94baa18) + - Initializing the static routing function does not require asynchronization  -  by @soybeanjs [(02d66)](https://github.com/soybeanjs/soybean-admin-antd/commit/02d66cb6) + - optimize `getRouteQueryOfLoginRoute`  -  by @soybeanjs [(693f7)](https://github.com/soybeanjs/soybean-admin-antd/commit/693f7046) + - supports custom menu icon sizes  -  by @wynn-w in https://github.com/soybeanjs/soybean-admin-antd/issues/534 [(e035e)](https://github.com/soybeanjs/soybean-admin-antd/commit/e035eab2) + - add type WatermarkProps  -  by @soybeanjs [(f26d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/f26d0a61) + - remove home NAlert closable  -  by @soybeanjs [(98b75)](https://github.com/soybeanjs/soybean-admin-antd/commit/98b75c22) + - optimize response code comparison  -  by @soybeanjs [(cf67d)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf67d55c) + - optimize code  -  by @soybeanjs [(cb1d4)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb1d4452) + - optimize menu selectedKey  -  by @soybeanjs [(531bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/531bfaf1) + - optimize response code comparison  -  by @soybeanjs [(d7025)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7025240) + - optimize code  -  by @soybeanjs [(6e8a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/6e8a55d1) + - optimize type  -  by @soybeanjs [(4679b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4679b17a) + - optimize code  -  by @soybeanjs [(6561f)](https://github.com/soybeanjs/soybean-admin-antd/commit/6561f0b5) + - optimize code  -  by @soybeanjs [(38eeb)](https://github.com/soybeanjs/soybean-admin-antd/commit/38eeb678) + - remove defineModel setting,enabled by default  -  by @yanbowe in https://github.com/soybeanjs/soybean-admin-antd/issues/620 [(60bbd)](https://github.com/soybeanjs/soybean-admin-antd/commit/60bbd2d1) + - remove defineModel setting,enabled by default  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/42 [(05bad)](https://github.com/soybeanjs/soybean-admin-antd/commit/05bad8dc) + - optimize code  -  by @soybeanjs [(9ad5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ad5d717) + - optimize router guard  -  by @soybeanjs [(0dfcf)](https://github.com/soybeanjs/soybean-admin-antd/commit/0dfcf18b) + - use `defu` to fill added theme config  -  by @soybeanjs [(101b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/101b6f90) + - optimize manage page: use `ref` replace `reactive`  -  by @soybeanjs [(e6d2a)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6d2a289) +- **types**: + - Enhance compatibility of global types  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/494 [(cd9d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/cd9d58d4) + - Enhance compatibility of global types  -  by @soybeanjs [(dc359)](https://github.com/soybeanjs/soybean-admin-antd/commit/dc359f5f) + - remove useless types.  -  by **Azir** [(eed61)](https://github.com/soybeanjs/soybean-admin-antd/commit/eed617f9) +- **utils**: + - Reduce code indentation and improve readability  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/496 [(ad2f2)](https://github.com/soybeanjs/soybean-admin-antd/commit/ad2f2470) + - Reduce code indentation and improve readability  -  by @soybeanjs [(54ae8)](https://github.com/soybeanjs/soybean-admin-antd/commit/54ae82b2) + +###    💅 Refactors + +- **auth**: + - 页面跳转逻辑优化  -  by **Soybean** [(c84c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/c84c37d1) +- **components**: + - 用NCard组件替换ShadowCard  -  by **Soybean** [(048ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/048eae67) + - hoverContainer组件属性调整  -  by **Soybean** [(4642e)](https://github.com/soybeanjs/soybean-admin-antd/commit/4642ee62) + - 重构AppProvider  -  by **Soybean** [(e70a3)](https://github.com/soybeanjs/soybean-admin-antd/commit/e70a3282) + - basicLayout布局组件重构完成:根据NavMode拆分为多个布局组件  -  by **Soybean** [(ffe98)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffe98783) + - blankLayout引入GlobalContent  -  by **Soybean** [(1ffb7)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ffb75af) + - 去除packages的soybean-layout,通过npm的方式引入  -  by **Soybean** [(c1182)](https://github.com/soybeanjs/soybean-admin-antd/commit/c1182fef) +- **czg**: + - update cz-git,czg breaking changes  -  by **燕博文** [(fcb7a)](https://github.com/soybeanjs/soybean-admin-antd/commit/fcb7ad96) +- **hooks**: + - 状态管理模块拆分  -  by **Soybean** [(1128a)](https://github.com/soybeanjs/soybean-admin-antd/commit/1128ae18) + - 重构hook函数取消监听方式  -  by **燕博文** [(fd948)](https://github.com/soybeanjs/soybean-admin-antd/commit/fd948867) + - refactor @sa/color-palette  -  by @soybeanjs [(93191)](https://github.com/soybeanjs/soybean-admin-antd/commit/93191737) + - refactor useSignal, useComputed  -  by @soybeanjs [(3b5e4)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b5e4b34) + - deleting the route export of useRoutePush, use vue-router  -  by @soybeanjs [(b81f7)](https://github.com/soybeanjs/soybean-admin-antd/commit/b81f749e) + - refactor @sa/color-palette to @sa/color  -  by @soybeanjs [(fda42)](https://github.com/soybeanjs/soybean-admin-antd/commit/fda42d6f) +- **layouts**: + - layout/header 反转色样式补充  -  by **元家怿** [(01d0b)](https://github.com/soybeanjs/soybean-admin-antd/commit/01d0bcbf) +- **packages**: + - @sa/materials: remove tab close shortcut by mouse  -  by @soybeanjs [(9fb72)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fb722d5) + - @sa/materials: remove tab close shortcut by mouse  -  by @soybeanjs [(4da58)](https://github.com/soybeanjs/soybean-admin-antd/commit/4da588c6) +- **projects**: + - element-plus国际化  -  by **Soybean** [(88320)](https://github.com/soybeanjs/soybean-admin-antd/commit/88320a8e) + - 名称变更  -  by **Soybean** [(93bba)](https://github.com/soybeanjs/soybean-admin-antd/commit/93bbaca8) + - 完善路由配置  -  by **Soybean** [(ab77d)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab77d58e) + - 顶部header和多页签的高度调整  -  by **Soybean** [(e1dc0)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1dc0f29) + - 环境文件重命名  -  by **Soybean** [(e9db6)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9db67ee) + - 重构browser tab初步  -  by **Soybean** [(51b86)](https://github.com/soybeanjs/soybean-admin-antd/commit/51b86035) + - chrome Tab重构完成  -  by **Soybean** [(d4884)](https://github.com/soybeanjs/soybean-admin-antd/commit/d488451f) + - 路由文件夹拆分模块,代码重构  -  by **Soybean** [(73505)](https://github.com/soybeanjs/soybean-admin-antd/commit/73505d91) + - 登录重定向地址相关重构  -  by **Soybean** [(04008)](https://github.com/soybeanjs/soybean-admin-antd/commit/04008b63) + - 路由组件导入拆分  -  by **Soybean** [(3edf4)](https://github.com/soybeanjs/soybean-admin-antd/commit/3edf46eb) + - 路由文件夹重构  -  by **Soybean** [(b2854)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2854d57) + - 精简代码  -  by **Soybean** [(5dc86)](https://github.com/soybeanjs/soybean-admin-antd/commit/5dc8626c) + - 注入全局常量:PROJECT_BUILD_TIME - 构建时间  -  by **Soybean** [(ec907)](https://github.com/soybeanjs/soybean-admin-antd/commit/ec907f06) + - 项目依赖信息直接从package.json获取  -  by **Soybean** [(4487f)](https://github.com/soybeanjs/soybean-admin-antd/commit/4487f9fb) + - 添加exportDefaults替换defineProps  -  by **Soybean** [(e61ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/e61ee32a) + - 去除vicons,统一使用iconify图标  -  by **Soybean** [(cd6db)](https://github.com/soybeanjs/soybean-admin-antd/commit/cd6db3d4) + - 地图插件页面布局重构  -  by **Soybean** [(36e0e)](https://github.com/soybeanjs/soybean-admin-antd/commit/36e0e669) + - 嵌入naive-ui的css vars,替换windicss的extend color  -  by **Soybean** [(2869b)](https://github.com/soybeanjs/soybean-admin-antd/commit/2869b4cd) + - basicLayout重构初步  -  by **Soybean** [(33770)](https://github.com/soybeanjs/soybean-admin-antd/commit/33770d23) + - 路由声明重构,添加composables,BaseLayout进行中,文件夹规范  -  by **Soybean** [(1e84d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e84d13d) + - 系统暗黑主题模式抽离成composables  -  by **Soybean** [(195e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/195e5b9e) + - 优化路由声明,添加路由模块导入,规范路相关文件夹  -  by **Soybean** [(f1997)](https://github.com/soybeanjs/soybean-admin-antd/commit/f199794d) + - 请求函数重构初步  -  by **Soybean** [(9f643)](https://github.com/soybeanjs/soybean-admin-antd/commit/9f64321d) + - axios封装:文件夹规范,错误处理完善  -  by **Soybean** [(451c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/451c7547) + - axios封装完成  -  by **Soybean** [(03b39)](https://github.com/soybeanjs/soybean-admin-antd/commit/03b398af) + - axios处理的请求结果去除网路状态  -  by **Soybean** [(05696)](https://github.com/soybeanjs/soybean-admin-antd/commit/0569666a) + - 文件夹位置规范  -  by **Soybean** [(f5a5f)](https://github.com/soybeanjs/soybean-admin-antd/commit/f5a5f44a) + - 细节完善  -  by **Soybean** [(62611)](https://github.com/soybeanjs/soybean-admin-antd/commit/6261156c) + - 重构路由类型和路由元数据类型,重构多级菜单路由写法  -  by **Soybean** [(d6838)](https://github.com/soybeanjs/soybean-admin-antd/commit/d683894b) + - 优化路由导入页面写法,页面路由调整  -  by **Soybean** [(0b10b)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b10b505) + - 登录模块由query变更为动态路由params  -  by **Soybean** [(225c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/225c4fe0) + - 精简版+动态路由权限初步  -  by **Soybean** [(de205)](https://github.com/soybeanjs/soybean-admin-antd/commit/de2057f1) + - 单独一级路由相关逻辑重构  -  by **Soybean** [(ab9a6)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab9a6a2f) + - 单独路由逻辑重构、路由转换函数优化  -  by **Soybean** [(b36a6)](https://github.com/soybeanjs/soybean-admin-antd/commit/b36a62b1) + - 恢复pinia默认写法  -  by **Soybean** [(b2a4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2a4ddf5) + - 请求构造函数适配不同后端接口的数据结构  -  by **Soybean** [(4f9d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/4f9d544d) + - 细节完善  -  by **Soybean** [(651e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/651e58dc) + - 重构路由页面组件的导入  -  by **Soybean** [(e6503)](https://github.com/soybeanjs/soybean-admin-antd/commit/e65034d9) + - 代码优化  -  by **Soybean** [(4e31a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e31abd4) + - lint命令修改  -  by **Soybean** [(20911)](https://github.com/soybeanjs/soybean-admin-antd/commit/20911dd8) + - 代码优化  -  by **Soybean** [(e8b53)](https://github.com/soybeanjs/soybean-admin-antd/commit/e8b534b8) + - 去除在pinia的getters的函数调用副作用,用watch代替  -  by **Soybean** [(b35ed)](https://github.com/soybeanjs/soybean-admin-antd/commit/b35ed896) + - 代码优化  -  by **Soybean** [(5e276)](https://github.com/soybeanjs/soybean-admin-antd/commit/5e276421) + - mock权限相关数据优化  -  by **Soybean** [(41e46)](https://github.com/soybeanjs/soybean-admin-antd/commit/41e46a5d) + - 代码优化  -  by **Soybean** [(251b5)](https://github.com/soybeanjs/soybean-admin-antd/commit/251b5b96) + - 代码优化  -  by **Soybean** [(a7824)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7824614) + - 细节优化  -  by **Soybean** [(c275f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c275f263) + - layout和tab组件依赖名称变更、样式修复  -  by **Soybean** [(de5fb)](https://github.com/soybeanjs/soybean-admin-antd/commit/de5fb842) + - merge branch unocss to main  -  by **Soybean** [(69d51)](https://github.com/soybeanjs/soybean-admin-antd/commit/69d51318) + - 动态路由权限完善  -  by **Soybean** [(55ddc)](https://github.com/soybeanjs/soybean-admin-antd/commit/55ddc9ca) + - 代码优化  -  by **Soybean** [(14c14)](https://github.com/soybeanjs/soybean-admin-antd/commit/14c145ee) + - 代码优化  -  by **Soybean** [(3590b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3590b65e) + - 代码优化  -  by **Soybean** [(a1c7e)](https://github.com/soybeanjs/soybean-admin-antd/commit/a1c7e105) + - 代码优化  -  by **Soybean** [(44ab5)](https://github.com/soybeanjs/soybean-admin-antd/commit/44ab55d5) + - 代码优化  -  by **Soybean** [(095c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/095c4323) + - 代码优化  -  by **Soybean** [(d28b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/d28b9039) + - 代码优化  -  by **Soybean** [(4c2f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/4c2f535a) + - 代码优化  -  by **Soybean** [(d9ac7)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9ac7e4d) + - 优化菜单支持横向滚动  -  by **Soybean** [(8f3e8)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f3e855f) + - 代码优化  -  by **Soybean** [(5fa82)](https://github.com/soybeanjs/soybean-admin-antd/commit/5fa822f4) + - 代码优化  -  by **燕博文** [(41147)](https://github.com/soybeanjs/soybean-admin-antd/commit/41147b34) + - 添加subscribeAppStore  -  by **Soybean** [(aa2f7)](https://github.com/soybeanjs/soybean-admin-antd/commit/aa2f78a8) + - 代码优化  -  by **Soybean** [(b60db)](https://github.com/soybeanjs/soybean-admin-antd/commit/b60db898) + - 代码优化  -  by **Soybean** [(61436)](https://github.com/soybeanjs/soybean-admin-antd/commit/61436052) + - 请求适配器函数范型重构、优化请求相关的命名  -  by **Soybean** [(7f9c9)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f9c98ab) + - 更新搜索弹窗的图标  -  by **Soybean** [(ed9cd)](https://github.com/soybeanjs/soybean-admin-antd/commit/ed9cd6ce) + - 抽离格式化相关依赖配置  -  by **Soybean** [(f4d37)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4d37cf7) + - 代码优化  -  by **Soybean** [(49f95)](https://github.com/soybeanjs/soybean-admin-antd/commit/49f95c4e) + - cancel autoinstall @iconify-json [取消@iconify-json自动安装]  -  by **Soybean** [(c29b8)](https://github.com/soybeanjs/soybean-admin-antd/commit/c29b887e) + - refactor page: user-management [重构用户管理页面]  -  by **Soybean** [(468b4)](https://github.com/soybeanjs/soybean-admin-antd/commit/468b4bb0) + - format code style [调整代码格式]  -  by **Soybean** [(a9d58)](https://github.com/soybeanjs/soybean-admin-antd/commit/a9d58f88) + - import cz-git, czg replace @soybeanjs/cli [引入cz-git、czg替换@soybeanjs/cli]  -  by **Soybean** [(1bdd8)](https://github.com/soybeanjs/soybean-admin-antd/commit/1bdd81a1) + - perfect scrollbar style [完善滚动条]  -  by **Soybean** [(1a02c)](https://github.com/soybeanjs/soybean-admin-antd/commit/1a02cab9) + - refactor app init loading [重构系统初始化的加载]  -  by **Soybean** [(57bfe)](https://github.com/soybeanjs/soybean-admin-antd/commit/57bfe278) + - new storage system [新的本地数据存储系统]  -  by **Soybean** [(97191)](https://github.com/soybeanjs/soybean-admin-antd/commit/97191594) + - add simple-git-hooks replace husky  -  by **Soybean** [(9110d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9110d875) + - all file and folder use kebab-case  -  by **Soybean** [(cea60)](https://github.com/soybeanjs/soybean-admin-antd/commit/cea600f1) + - update service and proxy config  -  by **Soybean** [(8debf)](https://github.com/soybeanjs/soybean-admin-antd/commit/8debfe7e) + - remove enum  -  by **Soybean** [(21d52)](https://github.com/soybeanjs/soybean-admin-antd/commit/21d52142) + - rename union key  -  by **Soybean** [(e2b32)](https://github.com/soybeanjs/soybean-admin-antd/commit/e2b320ad) + - update useTable  -  by **Soybean** [(211ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/211ae1f9) + - remove page examples: tree [去除tree相关示例页面]  -  by **Soybean** [(f3090)](https://github.com/soybeanjs/soybean-admin-antd/commit/f309003e) + - use better-mock replace mockjs [用better-mock替换mockjs]  -  by **Soybean** [(9d3c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d3c7329) + - upgrade vue3.3, official support defineOptions  -  by **Kirk Lin** [(86a37)](https://github.com/soybeanjs/soybean-admin-antd/commit/86a370fd) + - 生产环境缓存主题变更为sessionStorage  -  by @soybeanjs [(c46a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/c46a5920) + - add reCacheRoute method  -  by @soybeanjs [(f92ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/f92ee770) + - update soybean domain  -  by @soybeanjs [(073fd)](https://github.com/soybeanjs/soybean-admin-antd/commit/073fd16b) + - remove plugin-web-update-notification  -  by @soybeanjs [(f6c6d)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6c6dbd3) + - perf code  -  by @soybeanjs [(0b2e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b2e046b) + - init route store in router guide  -  by @soybeanjs [(bc056)](https://github.com/soybeanjs/soybean-admin-antd/commit/bc056dee) + - remove requiresAuth option of route meta  -  by @soybeanjs [(5a137)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a13749d) + - fix tooltop of ButtonIcon  -  by @soybeanjs [(a5b16)](https://github.com/soybeanjs/soybean-admin-antd/commit/a5b16663) + - useStore variable name  -  by @soybeanjs [(29291)](https://github.com/soybeanjs/soybean-admin-antd/commit/29291779) + - add createRoutes replace export routes directly  -  by @soybeanjs [(16bca)](https://github.com/soybeanjs/soybean-admin-antd/commit/16bca45b) + - refactor ColorPicker  -  by @soybeanjs [(f80c1)](https://github.com/soybeanjs/soybean-admin-antd/commit/f80c1ae5) + - themeStore: isCustomizeInfoColor to isInfoFollowPrimary  -  by @soybeanjs [(0867f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0867f4bf) + - rename zh-cn locale  -  by @soybeanjs [(ba10c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba10c3f2) + - rename zh-cn locale  -  by @soybeanjs [(26714)](https://github.com/soybeanjs/soybean-admin-antd/commit/26714e9e) + - fix conflict with locale file  -  by @soybeanjs [(3346b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3346bcdf) + - split @sa/request to @sa/axios, @sa/fetch  -  by @soybeanjs [(9ecb5)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ecb5162) + - remove @sa/eslint-config  -  by @soybeanjs [(23002)](https://github.com/soybeanjs/soybean-admin-antd/commit/230027ca) + - remove docs to soybean-admin-docs  -  by @soybeanjs [(be008)](https://github.com/soybeanjs/soybean-admin-antd/commit/be0087cf) + - refactor app-loading  -  by @soybeanjs [(b4f3d)](https://github.com/soybeanjs/soybean-admin-antd/commit/b4f3dd2f) + - refactor app-loading  -  by @soybeanjs [(c3c14)](https://github.com/soybeanjs/soybean-admin-antd/commit/c3c143b6) + - use naive-ui color-picker  -  by @soybeanjs [(b5551)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5551d67) + - login components => modules  -  by @soybeanjs [(49237)](https://github.com/soybeanjs/soybean-admin-antd/commit/4923781c) + - perf page home  -  by @soybeanjs [(4c61c)](https://github.com/soybeanjs/soybean-admin-antd/commit/4c61c6ff) + - login components => modules  -  by @soybeanjs [(59bec)](https://github.com/soybeanjs/soybean-admin-antd/commit/59bec2d9) + - perf page function_tab  -  by @soybeanjs [(b5477)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5477e89) + - update mock api  -  by @soybeanjs [(27241)](https://github.com/soybeanjs/soybean-admin-antd/commit/2724169e) + - page manage_role: extract module  -  by @soybeanjs [(0e9e2)](https://github.com/soybeanjs/soybean-admin-antd/commit/0e9e2e1d) + - perf page manage_role  -  by @soybeanjs [(a19f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/a19f895c) + - manage_route => manage_menu  -  by @soybeanjs [(f8467)](https://github.com/soybeanjs/soybean-admin-antd/commit/f8467ceb) + - refactor service env config  -  by @soybeanjs [(43193)](https://github.com/soybeanjs/soybean-admin-antd/commit/43193e28) + - refactor unocss shortcuts: wh-full => size-full  -  by @soybeanjs [(b4c00)](https://github.com/soybeanjs/soybean-admin-antd/commit/b4c00ce1) + - use enquirer replace prompts  -  by @soybeanjs [(b546f)](https://github.com/soybeanjs/soybean-admin-antd/commit/b546ff86) + - keep directory "locales/langs" same with version naive-ui  -  by @soybeanjs [(5ecf3)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ecf3841) + - refactor service env config  -  by @soybeanjs [(d89ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/d89ee4f4) + - refactor unocss shortcuts: wh-full => size-full  -  by @soybeanjs [(835cb)](https://github.com/soybeanjs/soybean-admin-antd/commit/835cb4fc) + - use enquirer replace prompts  -  by @soybeanjs [(64b27)](https://github.com/soybeanjs/soybean-admin-antd/commit/64b272cb) + - refactor useTable  -  by @soybeanjs [(c3efa)](https://github.com/soybeanjs/soybean-admin-antd/commit/c3efa1b6) + - finish refactor useTable  -  by @soybeanjs [(86301)](https://github.com/soybeanjs/soybean-admin-antd/commit/8630175a) + - finish refactor useTable and apply  -  by @soybeanjs [(3fd15)](https://github.com/soybeanjs/soybean-admin-antd/commit/3fd15e56) + - perf code  -  by @soybeanjs [(f91ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/f91ef30b) + - new route guard  -  by @soybeanjs [(37d20)](https://github.com/soybeanjs/soybean-admin-antd/commit/37d20b8e) + - refactor addThemeVarsToHtml  -  by @soybeanjs [(41e47)](https://github.com/soybeanjs/soybean-admin-antd/commit/41e470ed) + - perf code  -  by @soybeanjs [(81f08)](https://github.com/soybeanjs/soybean-admin-antd/commit/81f08f6c) + - constant routes, route guard  -  by @soybeanjs [(ddec7)](https://github.com/soybeanjs/soybean-admin-antd/commit/ddec7d8f) + - update naive-ui.d.ts  -  by @soybeanjs [(bb74d)](https://github.com/soybeanjs/soybean-admin-antd/commit/bb74d994) + - useMixMenuContext replace useMixMenu  -  by @soybeanjs [(1e142)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e14293d) + - refactor @sa/color-palette => @sa/color & perf @sa/utils  -  by @soybeanjs [(34999)](https://github.com/soybeanjs/soybean-admin-antd/commit/34999971) + - `Soybean Admin` to `SoybeanAdmin`  -  by @soybeanjs [(a8dbc)](https://github.com/soybeanjs/soybean-admin-antd/commit/a8dbc03e) + - menu-operate-drawer => menu-operate-modal  -  by @soybeanjs [(003e1)](https://github.com/soybeanjs/soybean-admin-antd/commit/003e145e) + - useMixMenuContext replace useMixMenu  -  by @soybeanjs [(e0aa7)](https://github.com/soybeanjs/soybean-admin-antd/commit/e0aa7523) + - Soybean Admin to SoybeanAdmin  -  by @soybeanjs [(9427d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9427d077) + - replace `cloneDeep` of `lodash-es` with `klona`  -  by @soybeanjs [(a9133)](https://github.com/soybeanjs/soybean-admin-antd/commit/a91335d7) + - combine `theme tokens` and `theme settings`. close #379  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/379 [(1d1b1)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d1b148c) + - change css vars mount to root  -  by @soybeanjs [(00f41)](https://github.com/soybeanjs/soybean-admin-antd/commit/00f41dd2) + - replace `cloneDeep` of `lodash-es` with `klona`  -  by @soybeanjs [(240ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/240ab795) + - combine theme tokens and theme settings  -  by @soybeanjs [(3f289)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f289110) + - change css vars mount to root  -  by @soybeanjs [(47c46)](https://github.com/soybeanjs/soybean-admin-antd/commit/47c46e30) + - refactor router guard. fix #655  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/667 and https://github.com/soybeanjs/soybean-admin-antd/issues/655 [(09144)](https://github.com/soybeanjs/soybean-admin-antd/commit/09144dfe) +- **styles**: + - 样式调整  -  by **Soybean** [(f2910)](https://github.com/soybeanjs/soybean-admin-antd/commit/f29106e4) + - 代码格式  -  by **Soybean** [(8f6d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f6d6ce3) + - sort defineProps, defineEmits with TS type  -  by @soybeanjs [(37a64)](https://github.com/soybeanjs/soybean-admin-antd/commit/37a64a53) + +###    📖 Documentation + +- **other**: + - 注释文案修改  -  by **毛博文** [(d0064)](https://github.com/soybeanjs/soybean-admin-antd/commit/d00643c9) +- **projects**: + - 更新README.md  -  by **Soybean** [(963ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/963aebee) + - 更新README.md  -  by **Soybean** [(848fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/848fa0c0) + - 更新README.md  -  by **Soybean** [(39a74)](https://github.com/soybeanjs/soybean-admin-antd/commit/39a7411d) + - update README.md  -  by **Soybean** [(22f8f)](https://github.com/soybeanjs/soybean-admin-antd/commit/22f8f3f0) + - 添加书写规范文档  -  by **Soybean** [(d9fd9)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9fd91d1) + - 文档更新  -  by **Soybean** [(8d2ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/8d2ba3e5) + - 文档格式规范  -  by **Soybean** [(560b8)](https://github.com/soybeanjs/soybean-admin-antd/commit/560b8a15) + - 文档更新  -  by **Soybean** [(448d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/448d28db) + - 更新README  -  by **Soybean** [(c950a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c950ae9c) + - vscode配置更新  -  by **Soybean** [(7c5ed)](https://github.com/soybeanjs/soybean-admin-antd/commit/7c5ed9d3) + - 更新README.md  -  by **Soybean** [(5790a)](https://github.com/soybeanjs/soybean-admin-antd/commit/5790a4f5) + - 更新README.md  -  by **Soybean** [(1d64e)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d64ebea) + - 更新README.md  -  by **Soybean** [(6940f)](https://github.com/soybeanjs/soybean-admin-antd/commit/6940f376) + - 更新README.md  -  by **Soybean** [(4ef2e)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ef2ea58) + - update README.md  -  by **Soybean** [(54577)](https://github.com/soybeanjs/soybean-admin-antd/commit/54577f10) + - update README.md  -  by **Soybean** [(1b346)](https://github.com/soybeanjs/soybean-admin-antd/commit/1b3463d2) + - update README.md  -  by **Soybean** [(98a7d)](https://github.com/soybeanjs/soybean-admin-antd/commit/98a7d25c) + - update README.md  -  by **Soybean** [(659e4)](https://github.com/soybeanjs/soybean-admin-antd/commit/659e4606) + - update README.md  -  by **Soybean** [(90ddf)](https://github.com/soybeanjs/soybean-admin-antd/commit/90ddf983) + - update README.md  -  by **Soybean** [(5eddb)](https://github.com/soybeanjs/soybean-admin-antd/commit/5eddb491) + - update README.md  -  by **Soybean** [(02c51)](https://github.com/soybeanjs/soybean-admin-antd/commit/02c51e6f) + - update README.md  -  by **Soybean** [(47f28)](https://github.com/soybeanjs/soybean-admin-antd/commit/47f2871c) + - update README.md  -  by **Soybean** [(7ed5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/7ed5d0de) + - update README.md  -  by **Soybean** [(3befb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3befb229) + - update README.md  -  by **Soybean** [(e856c)](https://github.com/soybeanjs/soybean-admin-antd/commit/e856cdb7) + - update README.md  -  by **Soybean** [(3aded)](https://github.com/soybeanjs/soybean-admin-antd/commit/3aded404) + - update README.md  -  by **Soybean** [(225e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/225e7128) + - update README.md  -  by **Soybean** [(5b401)](https://github.com/soybeanjs/soybean-admin-antd/commit/5b401a79) + - update README.md  -  by **Soybean** [(8cdad)](https://github.com/soybeanjs/soybean-admin-antd/commit/8cdad542) + - update README.md  -  by **Soybean** [(a0dfa)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0dfa3d3) + - update README.md  -  by **Soybean** [(b8db2)](https://github.com/soybeanjs/soybean-admin-antd/commit/b8db2116) + - update README.md  -  by **Soybean** [(21645)](https://github.com/soybeanjs/soybean-admin-antd/commit/21645537) + - update README.md  -  by **Soybean** [(9a90f)](https://github.com/soybeanjs/soybean-admin-antd/commit/9a90f18e) + - update README.md  -  by **Soybean** [(60a55)](https://github.com/soybeanjs/soybean-admin-antd/commit/60a55a77) + - update README.md  -  by **Soybean** [(d5c75)](https://github.com/soybeanjs/soybean-admin-antd/commit/d5c75115) + - update README.md  -  by **Soybean** [(3d8be)](https://github.com/soybeanjs/soybean-admin-antd/commit/3d8befa3) + - update README.md  -  by **Soybean** [(21e63)](https://github.com/soybeanjs/soybean-admin-antd/commit/21e63998) + - update README.md  -  by **Soybean** [(0811f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0811ffa5) + - update README.md  -  by **Soybean** [(84cb0)](https://github.com/soybeanjs/soybean-admin-antd/commit/84cb07ba) + - update README.md  -  by **Soybean** [(4b80a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4b80a661) + - update docs  -  by **Soybean** [(e9656)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9656c6e) + - update README.md  -  by **Soybean** [(ae99e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ae99e57c) + - update README.md  -  by **Soybean** [(0c70a)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c70a9e0) + - update README.md  -  by **Soybean** [(e2727)](https://github.com/soybeanjs/soybean-admin-antd/commit/e2727e6f) + - revert docs  -  by **Soybean** [(2c562)](https://github.com/soybeanjs/soybean-admin-antd/commit/2c562331) + - update README  -  by **Soybean** [(828a2)](https://github.com/soybeanjs/soybean-admin-antd/commit/828a2f5b) + - update README  -  by **Soybean** [(a3562)](https://github.com/soybeanjs/soybean-admin-antd/commit/a3562d92) + - update README.md  -  by **Soybean** [(cf8c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf8c7cb2) + - update README.md  -  by **Soybean** [(1ef1b)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ef1b6bd) + - update README.md  -  by **Soybean** [(aaef0)](https://github.com/soybeanjs/soybean-admin-antd/commit/aaef0bec) + - add qq to README.md [文档添加QQ群]  -  by **Soybean** [(f74a6)](https://github.com/soybeanjs/soybean-admin-antd/commit/f74a6424) + - update README.md [更新README.md]  -  by **Soybean** [(39709)](https://github.com/soybeanjs/soybean-admin-antd/commit/397092c2) + - update README.md [更新README.md]  -  by **Soybean** [(5a4f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a4f8427) + - update README.md [更新README.md]  -  by **Soybean** [(a765d)](https://github.com/soybeanjs/soybean-admin-antd/commit/a765da6e) + - update README.md [更新README.md]  -  by **Soybean** [(a989b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a989b44a) + - 优化README.md  -  by **xiaojunnuo** [(6ea75)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ea755f2) + - readme.md 二次开发的项目内容换行  -  by **xiaojunnuo** [(f3a17)](https://github.com/soybeanjs/soybean-admin-antd/commit/f3a1707b) + - update CHANGELOG.md  -  by **Soybean** [(5f6ca)](https://github.com/soybeanjs/soybean-admin-antd/commit/5f6caab3) + - CHANGELOG.md  -  by **Soybean** [(a2521)](https://github.com/soybeanjs/soybean-admin-antd/commit/a2521385) + - update README.md  -  by **Soybean** [(b5839)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5839eab) + - CHANGELOG.md  -  by **Soybean** [(bb2ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/bb2eab60) + - update README.md: update example image url [更新示例图片的链接]  -  by **Soybean** [(4f512)](https://github.com/soybeanjs/soybean-admin-antd/commit/4f512635) + - fix README.md: example image link  -  by **Soybean** [(56ea8)](https://github.com/soybeanjs/soybean-admin-antd/commit/56ea8937) + - CHANGELOG.md  -  by **Soybean** [(ff5bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff5bf629) + - generate full CHANGELOG.md  -  by **Soybean** [(055d4)](https://github.com/soybeanjs/soybean-admin-antd/commit/055d4cce) + - update README.md  -  by **Soybean** [(3c7e1)](https://github.com/soybeanjs/soybean-admin-antd/commit/3c7e1cf4) + - update README.md  -  by **Soybean** [(1681c)](https://github.com/soybeanjs/soybean-admin-antd/commit/1681c34a) + - update README.md picture url  -  by **Soybean** [(4eefc)](https://github.com/soybeanjs/soybean-admin-antd/commit/4eefc95b) + - update README.md  -  by **Soybean** [(8f24a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f24a94e) + - update CHANGELOG.md by regenerate changelog  -  by **Soybean** [(2a9b7)](https://github.com/soybeanjs/soybean-admin-antd/commit/2a9b725c) + - update README.md logo  -  by @soybeanjs [(19141)](https://github.com/soybeanjs/soybean-admin-antd/commit/19141a73) + - update Docker deployment method  -  by **muzzyh** [(00da0)](https://github.com/soybeanjs/soybean-admin-antd/commit/00da0009) + - update git hooks init command  -  by **muzzyh** [(7f35e)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f35e87e) + - update README.md  -  by **Ikko Eltociear Ashimine** [(93ed5)](https://github.com/soybeanjs/soybean-admin-antd/commit/93ed5ad0) + - update README.md  -  by @soybeanjs [(78364)](https://github.com/soybeanjs/soybean-admin-antd/commit/783648f5) + - update README.md  -  by @soybeanjs [(1ea48)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ea4817f) + - add README  -  by @soybeanjs [(67fbf)](https://github.com/soybeanjs/soybean-admin-antd/commit/67fbfc73) + - add README  -  by @soybeanjs [(2371b)](https://github.com/soybeanjs/soybean-admin-antd/commit/2371ba84) + - update README  -  by @soybeanjs [(d16a9)](https://github.com/soybeanjs/soybean-admin-antd/commit/d16a9d58) + - update README.md  -  by @soybeanjs [(6a771)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a771eae) + - update README.md  -  by @soybeanjs [(57b6d)](https://github.com/soybeanjs/soybean-admin-antd/commit/57b6d8a0) + - update README.md  -  by @soybeanjs [(3b31b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b31b19c) + - update README.md  -  by @soybeanjs [(b30c0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b30c0359) + - update README.md  -  by @soybeanjs [(c260f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c260fe26) + - update README.md  -  by @soybeanjs [(43743)](https://github.com/soybeanjs/soybean-admin-antd/commit/43743a0e) + - update README.md  -  by @soybeanjs [(03c42)](https://github.com/soybeanjs/soybean-admin-antd/commit/03c42aa8) + - update README.md  -  by @soybeanjs [(d71b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/d71b6ed6) + - update README.md  -  by @soybeanjs [(0fae9)](https://github.com/soybeanjs/soybean-admin-antd/commit/0fae9932) + - update README.md  -  by @soybeanjs [(4e4d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e4d2de5) + - update README.md  -  by @soybeanjs [(86b44)](https://github.com/soybeanjs/soybean-admin-antd/commit/86b445c2) + - update README.md  -  by @soybeanjs [(e2085)](https://github.com/soybeanjs/soybean-admin-antd/commit/e2085e05) + - update README.md  -  by @soybeanjs [(6ea9b)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ea9b85f) + - update README.md  -  by @soybeanjs [(ef4af)](https://github.com/soybeanjs/soybean-admin-antd/commit/ef4af79a) + - update README.md  -  by @soybeanjs [(41830)](https://github.com/soybeanjs/soybean-admin-antd/commit/418302a3) + - update README.md  -  by @soybeanjs [(427a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/427a0a5a) + - add CHANGELOG.md  -  by @soybeanjs [(46b61)](https://github.com/soybeanjs/soybean-admin-antd/commit/46b61566) + - add communication  -  by @soybeanjs [(8c7ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c7ea235) + - update README.md  -  by @soybeanjs [(07d8d)](https://github.com/soybeanjs/soybean-admin-antd/commit/07d8d25d) + - update README.md  -  by @soybeanjs [(1a707)](https://github.com/soybeanjs/soybean-admin-antd/commit/1a7070f0) + - update README.md  -  by @soybeanjs [(f69e1)](https://github.com/soybeanjs/soybean-admin-antd/commit/f69e1523) + - update README.md  -  by @soybeanjs [(76011)](https://github.com/soybeanjs/soybean-admin-antd/commit/76011af8) + - update README.md  -  by @soybeanjs [(f4a9c)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4a9cf83) + - update README.md  -  by @soybeanjs [(5a523)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a5232bd) + - update README.md  -  by @soybeanjs [(79d9c)](https://github.com/soybeanjs/soybean-admin-antd/commit/79d9c514) + - update CHANGELOG.md  -  by @soybeanjs [(cf5bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf5bc88a) + - add ecosystem to README.md  -  by @soybeanjs [(d0f17)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0f17a44) + - add PanisAdmin to README  -  by @paynezhuang [(ce2a7)](https://github.com/soybeanjs/soybean-admin-antd/commit/ce2a75b5) + - add CHANGELOG.zh_CN.md  -  by @soybeanjs [(18b3f)](https://github.com/soybeanjs/soybean-admin-antd/commit/18b3f053) + - update CHANGELOG  -  by @soybeanjs [(4d17c)](https://github.com/soybeanjs/soybean-admin-antd/commit/4d17cfdc) + - update CHANGELOG  -  by @soybeanjs [(19783)](https://github.com/soybeanjs/soybean-admin-antd/commit/1978397c) + - update README.md  -  by @soybeanjs [(fa56e)](https://github.com/soybeanjs/soybean-admin-antd/commit/fa56e9c9) + - update README.md  -  by @soybeanjs [(419ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/419ea423) + - update CHANGELOG  -  by @soybeanjs [(87b18)](https://github.com/soybeanjs/soybean-admin-antd/commit/87b18386) + - update CHANGELOG  -  by @soybeanjs [(756f8)](https://github.com/soybeanjs/soybean-admin-antd/commit/756f84ab) + - update Node&pnpm version  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/472 [(9b05d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9b05d73e) + - update CHANGELOG  -  by @soybeanjs [(2bec8)](https://github.com/soybeanjs/soybean-admin-antd/commit/2bec8990) + - update CHANGELOG  -  by @soybeanjs [(fe06b)](https://github.com/soybeanjs/soybean-admin-antd/commit/fe06b8c4) + - update README  -  by @soybeanjs [(4045e)](https://github.com/soybeanjs/soybean-admin-antd/commit/4045e41a) + - add CHANGELOG  -  by @soybeanjs [(01fbb)](https://github.com/soybeanjs/soybean-admin-antd/commit/01fbbacd) + - update README  -  by @soybeanjs [(8f9a7)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f9a7050) + - update README  -  by @soybeanjs [(bab68)](https://github.com/soybeanjs/soybean-admin-antd/commit/bab68176) + - Fixed the hyperlink pointing error  -  by **Azir** [(20a81)](https://github.com/soybeanjs/soybean-admin-antd/commit/20a81274) + - Fixed the hyperlink pointing error  -  by **Azir** [(d5602)](https://github.com/soybeanjs/soybean-admin-antd/commit/d5602ed9) + - update README  -  by @soybeanjs [(70261)](https://github.com/soybeanjs/soybean-admin-antd/commit/7026126a) + - update README  -  by @soybeanjs [(9527e)](https://github.com/soybeanjs/soybean-admin-antd/commit/9527ead2) + - update CHANGELOG  -  by @soybeanjs [(b3368)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3368415) + - update CHANGELOG  -  by @soybeanjs [(5c67d)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c67d065) + - update README  -  by @soybeanjs [(1e67a)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e67ae8c) + - update README  -  by @soybeanjs [(a769b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a769b1a3) + - update CHANGELOG  -  by @soybeanjs [(58fc0)](https://github.com/soybeanjs/soybean-admin-antd/commit/58fc0962) + - update CHANGELOG  -  by @soybeanjs [(a0b76)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0b76dae) + - update CHANGELOG  -  by @soybeanjs [(613c8)](https://github.com/soybeanjs/soybean-admin-antd/commit/613c836e) + - update CHANGELOG  -  by @soybeanjs [(d3759)](https://github.com/soybeanjs/soybean-admin-antd/commit/d37591dd) + - update CHANGELOG  -  by @soybeanjs [(ebc83)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebc838c3) + - update README  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/594 [(a8f92)](https://github.com/soybeanjs/soybean-admin-antd/commit/a8f923eb) + - update README  -  by @soybeanjs [(e9a2e)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9a2ee4a) + - update README  -  by @soybeanjs [(73e91)](https://github.com/soybeanjs/soybean-admin-antd/commit/73e917ad) + - update the location of important information in the document  -  by **Azir** [(9c012)](https://github.com/soybeanjs/soybean-admin-antd/commit/9c012c7d) + - update CHANGELOG  -  by @soybeanjs [(5baf1)](https://github.com/soybeanjs/soybean-admin-antd/commit/5baf19d2) + - update QQ group link.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/43 [(589ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/589ecae4) + - set the Chinese version of README as default  -  by @soybeanjs [(9d28b)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d28b31c) + - ✏️ add element-plus version link  -  by **一寸灰** in https://github.com/soybeanjs/soybean-admin-antd/issues/679 [(5c6ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c6ab0b5) + - set the Chinese version of README as default  -  by @soybeanjs [(e1ef1)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1ef14a5) +- **projects): docs(projects**: + - 更新README  -  by **Soybean** [(fb0dd)](https://github.com/soybeanjs/soybean-admin-antd/commit/fb0dd3f2) +- **projects): docs(projects): docs(projects**: + - 更新README  -  by **Soybean** [(1b440)](https://github.com/soybeanjs/soybean-admin-antd/commit/1b440403) + +###    📦 Build + +- **deps**: + - 添加多种插件:element-plus、iconify、windicss  -  by **Soybean** [(afd4d)](https://github.com/soybeanjs/soybean-admin-antd/commit/afd4d041) + - 添加smooth-scroll插件、axios封装  -  by **Soybean** [(82411)](https://github.com/soybeanjs/soybean-admin-antd/commit/82411cc5) + - 添加打包时跳过对依赖的类型校验  -  by **Soybean** [(f5220)](https://github.com/soybeanjs/soybean-admin-antd/commit/f5220e5a) + - 依赖升级  -  by **Soybean** [(4382b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4382bfa9) + - 修复element-plus国际化引入问题  -  by **Soybean** [(aa16d)](https://github.com/soybeanjs/soybean-admin-antd/commit/aa16dc65) + - 升级依赖  -  by **Soybean** [(1e393)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e393eb9) + - 依赖升级  -  by **Soybean** [(97820)](https://github.com/soybeanjs/soybean-admin-antd/commit/97820a4e) + - 依赖升级  -  by **Soybean** [(78a28)](https://github.com/soybeanjs/soybean-admin-antd/commit/78a28a45) + - 依赖升级  -  by **Soybean** [(6b7f4)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b7f4cfc) + - 升级依赖  -  by **Soybean** [(50c1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/50c1d51e) + - 更新依赖  -  by **Soybean** [(ffe50)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffe50143) + - 更新依赖  -  by **Soybean** [(d2464)](https://github.com/soybeanjs/soybean-admin-antd/commit/d246450d) + - 更新依赖  -  by **Soybean** [(0fb01)](https://github.com/soybeanjs/soybean-admin-antd/commit/0fb011f6) + - 更新依赖  -  by **Soybean** [(e59b8)](https://github.com/soybeanjs/soybean-admin-antd/commit/e59b85a8) + - 升级依赖  -  by **Soybean** [(9c7bd)](https://github.com/soybeanjs/soybean-admin-antd/commit/9c7bdb67) + - 升级依赖  -  by **Soybean** [(4e1a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e1a09c7) + - 升级依赖  -  by **Soybean** [(6de48)](https://github.com/soybeanjs/soybean-admin-antd/commit/6de48ad9) + - 升级依赖  -  by **Soybean** [(4e04a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e04a8f8) + - 升级依赖  -  by **Soybean** [(c8122)](https://github.com/soybeanjs/soybean-admin-antd/commit/c81221ef) + - 升级依赖  -  by **Soybean** [(a6bdc)](https://github.com/soybeanjs/soybean-admin-antd/commit/a6bdc380) + - 升级依赖  -  by **Soybean** [(ae7ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/ae7ec99a) + - 升级依赖  -  by **Soybean** [(e755c)](https://github.com/soybeanjs/soybean-admin-antd/commit/e755caab) + - 升级依赖  -  by **Soybean** [(f3c86)](https://github.com/soybeanjs/soybean-admin-antd/commit/f3c86efb) + - 升级依赖  -  by **Soybean** [(e776d)](https://github.com/soybeanjs/soybean-admin-antd/commit/e776df49) + - 升级依赖  -  by **Soybean** [(777cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/777cf8e0) + - 升级依赖  -  by **Soybean** [(284af)](https://github.com/soybeanjs/soybean-admin-antd/commit/284af63c) + - 升级依赖  -  by **Soybean** [(57c69)](https://github.com/soybeanjs/soybean-admin-antd/commit/57c692be) + - 升级依赖  -  by **Soybean** [(7ba33)](https://github.com/soybeanjs/soybean-admin-antd/commit/7ba332cd) + - upgrade deps  -  by **Soybean** [(50c8b)](https://github.com/soybeanjs/soybean-admin-antd/commit/50c8b9da) + - upgrade deps  -  by **Soybean** [(8d00b)](https://github.com/soybeanjs/soybean-admin-antd/commit/8d00b238) + - upgrade deps  -  by **Soybean** [(b298a)](https://github.com/soybeanjs/soybean-admin-antd/commit/b298af1d) + - update deps  -  by **Soybean** [(cecce)](https://github.com/soybeanjs/soybean-admin-antd/commit/cecce83b) + - update deps  -  by **Soybean** [(5c75e)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c75e9d9) + - update deps  -  by **Soybean** [(518f7)](https://github.com/soybeanjs/soybean-admin-antd/commit/518f7eed) + - update deps  -  by **Soybean** [(92b84)](https://github.com/soybeanjs/soybean-admin-antd/commit/92b84064) + - update deps  -  by **Soybean** [(50d7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/50d7ccd8) + - update deps  -  by **Soybean** [(3f822)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f822a7d) + - update deps  -  by **Soybean** [(02809)](https://github.com/soybeanjs/soybean-admin-antd/commit/028096e5) + - update deps  -  by **Soybean** [(be45d)](https://github.com/soybeanjs/soybean-admin-antd/commit/be45d837) + - update deps  -  by **Soybean** [(6a5a3)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a5a357f) + - 依赖升级  -  by **Soybean** [(e3c4a)](https://github.com/soybeanjs/soybean-admin-antd/commit/e3c4a6ec) + - update deps  -  by **Soybean** [(906ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/906aed5e) + - update deps  -  by **Soybean** [(9917b)](https://github.com/soybeanjs/soybean-admin-antd/commit/9917b5e5) + - update deps  -  by **Soybean** [(83301)](https://github.com/soybeanjs/soybean-admin-antd/commit/833018a8) + - update deps  -  by **Soybean** [(69e39)](https://github.com/soybeanjs/soybean-admin-antd/commit/69e39c14) + - update deps  -  by **Soybean** [(ea1a3)](https://github.com/soybeanjs/soybean-admin-antd/commit/ea1a3365) + - update deps  -  by **Soybean** [(73fa3)](https://github.com/soybeanjs/soybean-admin-antd/commit/73fa3d14) + - update deps  -  by **Soybean** [(973ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/973ab144) + - update deps  -  by **Soybean** [(75000)](https://github.com/soybeanjs/soybean-admin-antd/commit/750000ec) + - update deps  -  by **Soybean** [(8dcfb)](https://github.com/soybeanjs/soybean-admin-antd/commit/8dcfbb29) + - update deps  -  by **Soybean** [(1523c)](https://github.com/soybeanjs/soybean-admin-antd/commit/1523c7b0) + - update deps  -  by **Soybean** [(da407)](https://github.com/soybeanjs/soybean-admin-antd/commit/da407b66) + - update deps  -  by **Soybean** [(cec0f)](https://github.com/soybeanjs/soybean-admin-antd/commit/cec0f25c) + - update deps  -  by **Soybean** [(d9cfe)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9cfeabb) + - update deps  -  by **Soybean** [(dd113)](https://github.com/soybeanjs/soybean-admin-antd/commit/dd113248) + - update deps  -  by **Soybean** [(d0823)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0823b03) + - update deps  -  by **Soybean** [(94ff7)](https://github.com/soybeanjs/soybean-admin-antd/commit/94ff7870) + - update deps  -  by **Soybean** [(b32bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/b32bca49) + - update deps  -  by **Soybean** [(f6b61)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6b61418) + - update deps  -  by **Soybean** [(0f0cd)](https://github.com/soybeanjs/soybean-admin-antd/commit/0f0cd0b7) + - 更新@soybeanjs/eslint-config  -  by **Soybean** [(36f06)](https://github.com/soybeanjs/soybean-admin-antd/commit/36f06bc8) + - update deps  -  by **Soybean** [(d9324)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9324f07) + - update deps  -  by **Soybean** [(1ad92)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ad92a2d) + - 升级依赖  -  by **Soybean** [(7240b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7240be84) + - update deps  -  by **Soybean** [(c5ba6)](https://github.com/soybeanjs/soybean-admin-antd/commit/c5ba6318) + - update deps  -  by **Soybean** [(3e0cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e0cc8c2) + - update deps  -  by **Soybean** [(21b6f)](https://github.com/soybeanjs/soybean-admin-antd/commit/21b6fb69) + - update deps  -  by **Soybean** [(d823e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d823ee56) + - unplugin-vue-define-options替换为unplugin-vue-macros  -  by **Soybean** [(22c90)](https://github.com/soybeanjs/soybean-admin-antd/commit/22c90257) + - update deps  -  by **Soybean** [(7dd7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/7dd7c71d) + - update deps  -  by **Soybean** [(fe8ca)](https://github.com/soybeanjs/soybean-admin-antd/commit/fe8cab3d) + - unplugin-icon autoinstall @iconify-json [unplugin-icon自动安装@iconify-json]  -  by **Soybean** [(c045e)](https://github.com/soybeanjs/soybean-admin-antd/commit/c045e3fe) + - update deps [升级依赖]  -  by **Soybean** [(331b1)](https://github.com/soybeanjs/soybean-admin-antd/commit/331b14e7) + - update deps  -  by **Soybean** [(88e53)](https://github.com/soybeanjs/soybean-admin-antd/commit/88e535f6) + - update deps  -  by **Soybean** [(89985)](https://github.com/soybeanjs/soybean-admin-antd/commit/8998581b) + - update deps  -  by **Soybean** [(65ac6)](https://github.com/soybeanjs/soybean-admin-antd/commit/65ac69ef) + - update deps  -  by **Soybean** [(abd02)](https://github.com/soybeanjs/soybean-admin-antd/commit/abd02d19) + - update deps  -  by **Soybean** [(d6b15)](https://github.com/soybeanjs/soybean-admin-antd/commit/d6b15307) + - update deps  -  by **Soybean** [(8e801)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e801dd7) + - update deps  -  by **Soybean** [(41b3b)](https://github.com/soybeanjs/soybean-admin-antd/commit/41b3bcb4) + - update deps  -  by **Soybean** [(1f3e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/1f3e6e4f) + - update deps  -  by **Soybean** [(74772)](https://github.com/soybeanjs/soybean-admin-antd/commit/74772a1f) + - update deps  -  by **Soybean** [(84567)](https://github.com/soybeanjs/soybean-admin-antd/commit/84567509) + - update deps  -  by **Soybean** [(fcc65)](https://github.com/soybeanjs/soybean-admin-antd/commit/fcc65c37) + - update deps  -  by **Soybean** [(c097b)](https://github.com/soybeanjs/soybean-admin-antd/commit/c097b568) + - update deps  -  by **Soybean** [(61998)](https://github.com/soybeanjs/soybean-admin-antd/commit/61998886) + - update deps  -  by **Soybean** [(db629)](https://github.com/soybeanjs/soybean-admin-antd/commit/db629593) + - update deps [升级依赖]  -  by **Soybean** [(f2e82)](https://github.com/soybeanjs/soybean-admin-antd/commit/f2e82da7) + - update deps and remove vite-plugin-html [升级依赖,去除vite-plugin-html]  -  by **Soybean** [(eaf36)](https://github.com/soybeanjs/soybean-admin-antd/commit/eaf36787) + - update deps [升级依赖]  -  by **Soybean** [(bae17)](https://github.com/soybeanjs/soybean-admin-antd/commit/bae17671) + - update deps [升级依赖]  -  by **Soybean** [(c2642)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2642160) + - update deps [升级依赖]  -  by **Soybean** [(40f85)](https://github.com/soybeanjs/soybean-admin-antd/commit/40f8587f) +- **other**: + - update cz config  -  by **Soybean** [(07baa)](https://github.com/soybeanjs/soybean-admin-antd/commit/07baac7c) +- **projects**: + - 依赖升级,规范目录  -  by **Soybean** [(a0ec8)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0ec8458) + - 依赖升级  -  by **Soybean** [(025a9)](https://github.com/soybeanjs/soybean-admin-antd/commit/025a9bea) + - 依赖升级  -  by **Soybean** [(09a28)](https://github.com/soybeanjs/soybean-admin-antd/commit/09a28d8e) + - pnpm替换yarn  -  by **Soybean** [(36491)](https://github.com/soybeanjs/soybean-admin-antd/commit/36491310) + - 依赖升级  -  by **Soybean** [(f1649)](https://github.com/soybeanjs/soybean-admin-antd/commit/f1649de6) + - 依赖升级  -  by **Soybean** [(d00bb)](https://github.com/soybeanjs/soybean-admin-antd/commit/d00bb228) + - 主题配置完善  -  by **Soybean** [(20503)](https://github.com/soybeanjs/soybean-admin-antd/commit/20503739) + - 添加构建打包的不同环境配置  -  by **Soybean** [(ef57d)](https://github.com/soybeanjs/soybean-admin-antd/commit/ef57d9e6) + - 更新README.md  -  by **Soybean** [(f2ad7)](https://github.com/soybeanjs/soybean-admin-antd/commit/f2ad76df) + - 项目名称变更,添加README内容:项目基本介绍  -  by **Soybean** [(638a8)](https://github.com/soybeanjs/soybean-admin-antd/commit/638a8e98) + - 添加vscode插件推荐配置和设置配置  -  by **Soybean** [(b9395)](https://github.com/soybeanjs/soybean-admin-antd/commit/b9395221) + - 取消打包显示brotliSize  -  by **Soybean** [(9af89)](https://github.com/soybeanjs/soybean-admin-antd/commit/9af89885) + - 添加构建大小可视化分析的插件  -  by **Soybean** [(8ba8a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8ba8a4fe) + - vite配置更新  -  by **Soybean** [(e5d99)](https://github.com/soybeanjs/soybean-admin-antd/commit/e5d9962a) + - 环境变量获取方式变更  -  by **Soybean** [(21c2f)](https://github.com/soybeanjs/soybean-admin-antd/commit/21c2f5a8) + - 修改vscode配置  -  by **Soybean** [(0c577)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c5770df) + - 添加vercel打包的环境  -  by **Soybean** [(371fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/371fad4f) + - add license  -  by **Soybean** [(b1672)](https://github.com/soybeanjs/soybean-admin-antd/commit/b16721b2) + - 更新tsconfig.json  -  by **Soybean** [(f42ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/f42ee9db) + - update tsconfig、eslintrc  -  by **Soybean** [(75de2)](https://github.com/soybeanjs/soybean-admin-antd/commit/75de2b06) + - vite.config代码优化  -  by **Soybean** [(ca707)](https://github.com/soybeanjs/soybean-admin-antd/commit/ca707a45) + - 细节调整  -  by **Soybean** [(401f0)](https://github.com/soybeanjs/soybean-admin-antd/commit/401f0c74) + - update config  -  by **Soybean** [(a0c40)](https://github.com/soybeanjs/soybean-admin-antd/commit/a0c405da) + - 代码优化  -  by **Soybean** [(de09f)](https://github.com/soybeanjs/soybean-admin-antd/commit/de09f825) + - 配置优化  -  by **Soybean** [(fd787)](https://github.com/soybeanjs/soybean-admin-antd/commit/fd787912) + - 配置更改  -  by **Soybean** [(c8717)](https://github.com/soybeanjs/soybean-admin-antd/commit/c8717c25) + - update deps, update config  -  by **Soybean** [(8e6e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e6e7875) + - 代码优化  -  by **Soybean** [(5c1b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c1b086c) + - update tsconfig  -  by **Soybean** [(9ce58)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ce58073) + - update vscode settings  -  by **Soybean** [(3fe4e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3fe4e92f) + - 添加.gitattributes  -  by **Soybean** [(896e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/896e6f2e) + - 代码优化  -  by **Soybean** [(6a9a3)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a9a362c) + - 升级依赖,添加对json的eslint检测及格式化  -  by **Soybean** [(711a4)](https://github.com/soybeanjs/soybean-admin-antd/commit/711a4ae3) + - update deps and README.md  -  by **Soybean** [(35aee)](https://github.com/soybeanjs/soybean-admin-antd/commit/35aeedf3) + - 升级依赖、vite配置optimizeDeps  -  by **Soybean** [(ee434)](https://github.com/soybeanjs/soybean-admin-antd/commit/ee434b46) + - 去除prettier,已集成进@soybeanjs/eslint-config  -  by **Soybean** [(182da)](https://github.com/soybeanjs/soybean-admin-antd/commit/182dac0d) + - update eslint  -  by **Soybean** [(907cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/907cf44c) + - 引入pwa插件,更新配置  -  by **Soybean** [(695ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/695ec7e5) + - 更新依赖、调整页面  -  by **Soybean** [(40ecc)](https://github.com/soybeanjs/soybean-admin-antd/commit/40ecc320) + - 引入vite-plugin-progress  -  by **Soybean** [(44ab0)](https://github.com/soybeanjs/soybean-admin-antd/commit/44ab0777) + - 升级依赖、修复T标签右键菜单连续显示问题  -  by **Soybean** [(639c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/639c4458) + - 引入TS高级类型库  -  by **Soybean** [(71a75)](https://github.com/soybeanjs/soybean-admin-antd/commit/71a753f3) + - 更换eslint依赖为eslint-config-soybeanjs-vue  -  by **Soybean** [(07325)](https://github.com/soybeanjs/soybean-admin-antd/commit/07325a42) + - 升级依赖,降低naive-ui版本修复打包问题  -  by **Soybean** [(f408e)](https://github.com/soybeanjs/soybean-admin-antd/commit/f408ea01) + - 升级依赖,修复TS类型  -  by **Soybean** [(73ce5)](https://github.com/soybeanjs/soybean-admin-antd/commit/73ce53a3) + - 引入@unocss/vite替换unocss,精简体积  -  by **Soybean** [(3540b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3540b755) + - update deps, update logos  -  by **Soybean** [(22c05)](https://github.com/soybeanjs/soybean-admin-antd/commit/22c05674) + - add constant page content  -  by **Soybean** [(13d0c)](https://github.com/soybeanjs/soybean-admin-antd/commit/13d0c415) + - add tauri scripts, change tauri icon, fix mockjs [添加tauri相关的命令,变更tauri图标,修复mockjs]  -  by **Soybean** [(1b45b)](https://github.com/soybeanjs/soybean-admin-antd/commit/1b45b71f) + - use @soybeanjs/cli replace commitizen  -  by **Soybean** [(428d4)](https://github.com/soybeanjs/soybean-admin-antd/commit/428d41b4) + - use pnpm patch replace @milahu/patch-package  -  by **Soybean** [(9455a)](https://github.com/soybeanjs/soybean-admin-antd/commit/9455ad9a) + - remove useless file: commitlint.config.js  -  by **Soybean** [(67736)](https://github.com/soybeanjs/soybean-admin-antd/commit/6773659e) + - move tauri to branch tauri  -  by **Soybean** [(6c14b)](https://github.com/soybeanjs/soybean-admin-antd/commit/6c14bfe6) + - update deps and update config  -  by **Soybean** [(7d699)](https://github.com/soybeanjs/soybean-admin-antd/commit/7d699926) + - new router branch  -  by **Soybean** [(288d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/288d586d) + - add vite plugin @soybeanjs/router-page  -  by **Soybean** [(40c1e)](https://github.com/soybeanjs/soybean-admin-antd/commit/40c1e13b) + - update plugin config  -  by **Soybean** [(6a344)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a344ff2) + - update deps and perfect the details [升级依赖,完善细节]  -  by **Soybean** [(61a43)](https://github.com/soybeanjs/soybean-admin-antd/commit/61a43b8e) + - update deps and update config  -  by **Soybean** [(b08c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/b08c389e) + - update lint-staged config  -  by **Soybean** [(0882c)](https://github.com/soybeanjs/soybean-admin-antd/commit/0882c250) + - add VSCode debug config file  -  by **Soybean** [(0c126)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c12665f) + - update deps  -  by **Soybean** [(f7181)](https://github.com/soybeanjs/soybean-admin-antd/commit/f71812d6) + - update deps and fix project config  -  by **Soybean** [(da521)](https://github.com/soybeanjs/soybean-admin-antd/commit/da521b35) + - perf logo  -  by **Soybean** [(a8a6e)](https://github.com/soybeanjs/soybean-admin-antd/commit/a8a6ed97) + - update vscode config  -  by **Soybean** [(608d7)](https://github.com/soybeanjs/soybean-admin-antd/commit/608d7fb3) + - update unocss config  -  by **Soybean** [(3503d)](https://github.com/soybeanjs/soybean-admin-antd/commit/3503dff6) + - update deps, add prettier format command  -  by **Soybean** [(36e5f)](https://github.com/soybeanjs/soybean-admin-antd/commit/36e5feac) + - remove old layout,tab package [去除旧的布局和页签依赖]  -  by **Soybean** [(42e6d)](https://github.com/soybeanjs/soybean-admin-antd/commit/42e6de39) + - update deps and fix type error [升级依赖并修复类型问题]  -  by **Soybean** [(34f02)](https://github.com/soybeanjs/soybean-admin-antd/commit/34f023c4) + - update deps and fix style [升级依赖&修复代码格式]  -  by **Soybean** [(c1c43)](https://github.com/soybeanjs/soybean-admin-antd/commit/c1c4335c) + +###    🏡 Chore + +- rename env.d.ts to vite-env.d.ts  -  by @wzc520pyfm in https://github.com/soybeanjs/soybean-admin-antd/issues/675 [(b93c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/b93c2036) +- **deps**: + - update deps  -  by **Soybean** [(4eb46)](https://github.com/soybeanjs/soybean-admin-antd/commit/4eb46ea3) + - update deps  -  by **Soybean** [(a70e4)](https://github.com/soybeanjs/soybean-admin-antd/commit/a70e4161) + - update deps  -  by **Soybean** [(7487a)](https://github.com/soybeanjs/soybean-admin-antd/commit/7487ab79) + - update deps  -  by **Soybean** [(cebbe)](https://github.com/soybeanjs/soybean-admin-antd/commit/cebbef68) + - update deps  -  by **Soybean** [(f9d47)](https://github.com/soybeanjs/soybean-admin-antd/commit/f9d47c08) + - update deps  -  by **Soybean** [(47ab0)](https://github.com/soybeanjs/soybean-admin-antd/commit/47ab0184) + - decrease vite-plugin-page-route  -  by **Soybean** [(882f2)](https://github.com/soybeanjs/soybean-admin-antd/commit/882f2814) + - update deps  -  by **Soybean** [(e6abf)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6abf934) + - update deps  -  by **Soybean** [(bba68)](https://github.com/soybeanjs/soybean-admin-antd/commit/bba68bff) + - update deps  -  by **Soybean** [(0e6d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/0e6d2891) + - update deps  -  by @soybeanjs [(135ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/135ce772) + - update deps  -  by @soybeanjs [(44ba3)](https://github.com/soybeanjs/soybean-admin-antd/commit/44ba3273) + - update deps  -  by @soybeanjs [(9296e)](https://github.com/soybeanjs/soybean-admin-antd/commit/9296e698) + - update deps  -  by @soybeanjs [(751de)](https://github.com/soybeanjs/soybean-admin-antd/commit/751ded44) + - update deps  -  by @soybeanjs [(305d9)](https://github.com/soybeanjs/soybean-admin-antd/commit/305d9567) + - update deps  -  by @soybeanjs [(3eaf0)](https://github.com/soybeanjs/soybean-admin-antd/commit/3eaf05bd) + - update deps  -  by @soybeanjs [(4caa4)](https://github.com/soybeanjs/soybean-admin-antd/commit/4caa45d3) + - update deps  -  by @soybeanjs [(bd3ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd3efe6b) + - update deps  -  by @soybeanjs [(56931)](https://github.com/soybeanjs/soybean-admin-antd/commit/56931a26) + - update deps  -  by @soybeanjs [(56e7d)](https://github.com/soybeanjs/soybean-admin-antd/commit/56e7dc3b) + - update deps  -  by @soybeanjs [(892e2)](https://github.com/soybeanjs/soybean-admin-antd/commit/892e2d6b) + - updtae deps  -  by @soybeanjs [(7088d)](https://github.com/soybeanjs/soybean-admin-antd/commit/7088ddcf) + - update deps  -  by @soybeanjs [(b0b48)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0b4830a) + - update deps  -  by @soybeanjs [(7f049)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f049ba3) + - update deps  -  by @soybeanjs [(854ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/854ce363) + - update deps  -  by @soybeanjs [(82ccf)](https://github.com/soybeanjs/soybean-admin-antd/commit/82ccfbcd) + - update deps  -  by @soybeanjs [(36fe1)](https://github.com/soybeanjs/soybean-admin-antd/commit/36fe1dad) + - update deps  -  by @soybeanjs [(b0546)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0546614) + - update deps  -  by @soybeanjs [(55342)](https://github.com/soybeanjs/soybean-admin-antd/commit/55342941) + - update deps  -  by @soybeanjs [(adc36)](https://github.com/soybeanjs/soybean-admin-antd/commit/adc36565) + - update deps  -  by @soybeanjs [(f1b86)](https://github.com/soybeanjs/soybean-admin-antd/commit/f1b86ccb) + - update deps  -  by @soybeanjs [(c655a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c655a240) + - update deps  -  by @soybeanjs [(840e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/840e7f99) + - update deps  -  by @soybeanjs [(345b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/345b6878) + - update deps  -  by @soybeanjs [(6114b)](https://github.com/soybeanjs/soybean-admin-antd/commit/6114b9f9) + - update deps  -  by @soybeanjs [(70962)](https://github.com/soybeanjs/soybean-admin-antd/commit/70962f5b) + - update deps  -  by @soybeanjs [(9cc7e)](https://github.com/soybeanjs/soybean-admin-antd/commit/9cc7ee5c) + - update deps  -  by @soybeanjs [(2d4d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d4d1077) + - update deps  -  by @soybeanjs [(9c4ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/9c4ba665) + - update deps  -  by @soybeanjs [(fb3b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/fb3b94b1) + - update deps  -  by @soybeanjs [(14aa8)](https://github.com/soybeanjs/soybean-admin-antd/commit/14aa856a) + - update deps  -  by @soybeanjs [(02d4b)](https://github.com/soybeanjs/soybean-admin-antd/commit/02d4b0a5) + - update deps  -  by @soybeanjs [(b2ee9)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2ee9eef) + - update deps  -  by @soybeanjs [(9e493)](https://github.com/soybeanjs/soybean-admin-antd/commit/9e493e54) + - update deps  -  by @soybeanjs [(0fee1)](https://github.com/soybeanjs/soybean-admin-antd/commit/0fee104b) + - update deps  -  by @soybeanjs [(c0a65)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0a65a16) + - update deps  -  by @soybeanjs [(6b513)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b5132c1) + - update deps  -  by @soybeanjs [(82b53)](https://github.com/soybeanjs/soybean-admin-antd/commit/82b53d7e) + - update deps  -  by @soybeanjs [(a1b48)](https://github.com/soybeanjs/soybean-admin-antd/commit/a1b484a8) + - update deps  -  by @soybeanjs [(eba20)](https://github.com/soybeanjs/soybean-admin-antd/commit/eba2014a) + - update deps  -  by @soybeanjs [(ac928)](https://github.com/soybeanjs/soybean-admin-antd/commit/ac928173) + - update deps  -  by @soybeanjs [(3ceeb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3ceeb6f9) + - update deps  -  by @soybeanjs [(9a669)](https://github.com/soybeanjs/soybean-admin-antd/commit/9a66979f) + - update deps  -  by @soybeanjs [(e57bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/e57bf0b0) + - update deps  -  by @soybeanjs [(fbd80)](https://github.com/soybeanjs/soybean-admin-antd/commit/fbd80c28) + - update deps  -  by @soybeanjs [(1cb38)](https://github.com/soybeanjs/soybean-admin-antd/commit/1cb3816e) + - update deps  -  by @soybeanjs [(413a8)](https://github.com/soybeanjs/soybean-admin-antd/commit/413a8b29) + - update deps  -  by @soybeanjs [(734ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/734ef985) + - update deps  -  by @soybeanjs [(599b4)](https://github.com/soybeanjs/soybean-admin-antd/commit/599b4e19) + - update deps  -  by @soybeanjs [(d0380)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0380ce5) + - update deps  -  by @soybeanjs [(1f464)](https://github.com/soybeanjs/soybean-admin-antd/commit/1f4647b9) + - update deps  -  by @soybeanjs [(060c0)](https://github.com/soybeanjs/soybean-admin-antd/commit/060c0a91) + - update deps  -  by @soybeanjs [(909ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/909ceb8d) + - update deps  -  by @soybeanjs [(08827)](https://github.com/soybeanjs/soybean-admin-antd/commit/08827a42) + - update deps  -  by @soybeanjs [(a6c0e)](https://github.com/soybeanjs/soybean-admin-antd/commit/a6c0eaee) + - update deps  -  by @soybeanjs [(813d8)](https://github.com/soybeanjs/soybean-admin-antd/commit/813d8ce4) + - update deps  -  by @soybeanjs [(9954c)](https://github.com/soybeanjs/soybean-admin-antd/commit/9954c8e3) + - update deps  -  by @soybeanjs [(d9f9f)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9f9f9fd) + - update deps  -  by @soybeanjs [(bf718)](https://github.com/soybeanjs/soybean-admin-antd/commit/bf718374) + - update deps  -  by @soybeanjs [(423fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/423fafc6) + - update deps  -  by @soybeanjs [(b094d)](https://github.com/soybeanjs/soybean-admin-antd/commit/b094d688) + - update deps. close #510  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/510 [(53143)](https://github.com/soybeanjs/soybean-admin-antd/commit/531432d5) + - update deps.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/30 [(e110d)](https://github.com/soybeanjs/soybean-admin-antd/commit/e110dd09) + - update deps  -  by @soybeanjs [(c7f6f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c7f6f2a5) + - update deps  -  by @soybeanjs [(72ede)](https://github.com/soybeanjs/soybean-admin-antd/commit/72ede8bf) + - update deps  -  by @soybeanjs [(be13c)](https://github.com/soybeanjs/soybean-admin-antd/commit/be13ca27) + - update deps  -  by @soybeanjs [(5fcf2)](https://github.com/soybeanjs/soybean-admin-antd/commit/5fcf2bd6) + - update deps  -  by @soybeanjs [(752ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/752ec1e9) + - update deps  -  by @soybeanjs [(cf019)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf0192ad) + - update deps  -  by @soybeanjs [(f6bd6)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6bd6b86) + - update deps  -  by @soybeanjs [(993e9)](https://github.com/soybeanjs/soybean-admin-antd/commit/993e9caf) + - update deps  -  by @soybeanjs [(a1c14)](https://github.com/soybeanjs/soybean-admin-antd/commit/a1c14a15) + - update deps  -  by @soybeanjs [(7fa55)](https://github.com/soybeanjs/soybean-admin-antd/commit/7fa55905) + - update deps  -  by @soybeanjs [(a44ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/a44ea624) + - update deps  -  by @soybeanjs [(7bc1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/7bc1d987) + - update deps  -  by @soybeanjs [(207d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/207d6eb6) + - update deps  -  by @soybeanjs [(f3562)](https://github.com/soybeanjs/soybean-admin-antd/commit/f35627e1) + - update deps  -  by @soybeanjs [(5e0c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/5e0c288e) + - update deps  -  by @soybeanjs [(baefd)](https://github.com/soybeanjs/soybean-admin-antd/commit/baefdfd8) + - update deps  -  by @soybeanjs [(3453c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3453c814) + - update deps  -  by @soybeanjs [(8dcda)](https://github.com/soybeanjs/soybean-admin-antd/commit/8dcda385) + - update deps  -  by @soybeanjs [(91de4)](https://github.com/soybeanjs/soybean-admin-antd/commit/91de4a8e) + - update deps  -  by @soybeanjs [(0c809)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c809de6) + - update deps  -  by @soybeanjs [(0f15c)](https://github.com/soybeanjs/soybean-admin-antd/commit/0f15c335) +- **other**: + - correct spell mistake  -  by @orangelckc in https://github.com/soybeanjs/soybean-admin-antd/issues/460 [(086ba)](https://github.com/soybeanjs/soybean-admin-antd/commit/086bad47) + - correct spell mistake  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/462 [(f1850)](https://github.com/soybeanjs/soybean-admin-antd/commit/f1850416) + - correct spell mistake  -  by @soybeanjs [(308bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/308bff69) +- **project**: + - delete src/locales/lang/zh-CN.ts  -  by @soybeanjs [(377db)](https://github.com/soybeanjs/soybean-admin-antd/commit/377db829) +- **projects**: + - 更新.cz-config  -  by **Soybean** [(b18c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/b18c49e9) + - 更新eslint配置  -  by **Soybean** [(872bb)](https://github.com/soybeanjs/soybean-admin-antd/commit/872bb845) + - add github action  -  by **lixin** [(f355a)](https://github.com/soybeanjs/soybean-admin-antd/commit/f355a698) + - 修复issue模板格式问题  -  by **lixin59** [(d8bab)](https://github.com/soybeanjs/soybean-admin-antd/commit/d8baba58) + - remove useless packages, update lint-staged config, add githublogen  -  by **Soybean** [(5aaa3)](https://github.com/soybeanjs/soybean-admin-antd/commit/5aaa3181) + - add switch for pageRoute plugin [添加自动生成路由的插件的开关]  -  by **Soybean** [(780ac)](https://github.com/soybeanjs/soybean-admin-antd/commit/780ac75b) + - update deps and use soy lint-staged replace lint-staged  -  by **Soybean** [(9a238)](https://github.com/soybeanjs/soybean-admin-antd/commit/9a238174) + - remove bumpp & add release script  -  by **Soybean** [(a3dfe)](https://github.com/soybeanjs/soybean-admin-antd/commit/a3dfe61a) + - update @soybeanjs/cli and generate total changelog  -  by **Soybean** [(58591)](https://github.com/soybeanjs/soybean-admin-antd/commit/58591f66) + - update deps & update unocss deprecated api exclude  -  by **Soybean** [(0907d)](https://github.com/soybeanjs/soybean-admin-antd/commit/0907d38c) + - update deps & update package.json  -  by **Soybean** [(0b2f6)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b2f68ac) + - add vite-plugin-vue-devtools  -  by **Soybean** [(c1bee)](https://github.com/soybeanjs/soybean-admin-antd/commit/c1bee404) + - update deps and fix swiper  -  by @soybeanjs [(9d105)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d1051b0) + - update package.json  -  by @soybeanjs [(d7aea)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7aea9d1) + - update deps & fix eslint code  -  by @soybeanjs [(08e0c)](https://github.com/soybeanjs/soybean-admin-antd/commit/08e0cf5a) + - update pnpm-lock.yaml  -  by @soybeanjs [(94644)](https://github.com/soybeanjs/soybean-admin-antd/commit/94644739) + - update VSCode setting  -  by @soybeanjs [(56c77)](https://github.com/soybeanjs/soybean-admin-antd/commit/56c770c4) + - correct the word spell  -  by @soybeanjs [(458e3)](https://github.com/soybeanjs/soybean-admin-antd/commit/458e387b) + - correct word spell & eslint fix code  -  by @soybeanjs [(cffc3)](https://github.com/soybeanjs/soybean-admin-antd/commit/cffc30af) + - When tab is switched, keep the page without refreshing  -  by @linjiangl [(83f25)](https://github.com/soybeanjs/soybean-admin-antd/commit/83f25144) + - rename project  -  by @soybeanjs [(5dfe9)](https://github.com/soybeanjs/soybean-admin-antd/commit/5dfe9688) + - update version and perf code  -  by @soybeanjs [(97035)](https://github.com/soybeanjs/soybean-admin-antd/commit/970352c7) + - fix pkg version  -  by @soybeanjs [(4b375)](https://github.com/soybeanjs/soybean-admin-antd/commit/4b37577d) + - add sourcemap  -  by @soybeanjs [(d25ed)](https://github.com/soybeanjs/soybean-admin-antd/commit/d25ed445) + - add pnpm-lock  -  by @soybeanjs [(0e4cb)](https://github.com/soybeanjs/soybean-admin-antd/commit/0e4cbd91) + - update deps and perf code  -  by @soybeanjs [(19c12)](https://github.com/soybeanjs/soybean-admin-antd/commit/19c1200b) + - update gitignore  -  by @soybeanjs [(910fe)](https://github.com/soybeanjs/soybean-admin-antd/commit/910fe4ec) + - update pnpm-lock  -  by @soybeanjs [(1d0b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d0b0614) + - update vscode settings  -  by @soybeanjs [(c2b6a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2b6aa61) + - use eslint flat config  -  by @soybeanjs [(11adc)](https://github.com/soybeanjs/soybean-admin-antd/commit/11adc8c2) + - add config files  -  by @soybeanjs [(87aa0)](https://github.com/soybeanjs/soybean-admin-antd/commit/87aa0695) + - update deps & update @sa/scripts config  -  by @soybeanjs [(31f67)](https://github.com/soybeanjs/soybean-admin-antd/commit/31f676ae) + - use eslint flat config & update config  -  by @soybeanjs [(a176d)](https://github.com/soybeanjs/soybean-admin-antd/commit/a176dc44) + - update @sa/scripts  -  by @soybeanjs [(d7785)](https://github.com/soybeanjs/soybean-admin-antd/commit/d778560d) + - update pnpm version  -  by @soybeanjs [(47819)](https://github.com/soybeanjs/soybean-admin-antd/commit/478194dc) + - create LICENSE  -  by @soybeanjs [(853f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/853f5c1e) + - update pnpm version  -  by @soybeanjs [(91121)](https://github.com/soybeanjs/soybean-admin-antd/commit/91121939) + - update pnpm version  -  by @soybeanjs [(55f76)](https://github.com/soybeanjs/soybean-admin-antd/commit/55f76385) + - update eslint config  -  by @soybeanjs [(5023f)](https://github.com/soybeanjs/soybean-admin-antd/commit/5023f371) + - update eslint config  -  by @soybeanjs [(7029b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7029b499) + - lock deps version  -  by @soybeanjs [(8ff39)](https://github.com/soybeanjs/soybean-admin-antd/commit/8ff398f0) + - lock deps versions  -  by @soybeanjs [(a24f9)](https://github.com/soybeanjs/soybean-admin-antd/commit/a24f9631) + - remove @soybeanjs/cli  -  by @soybeanjs [(02c05)](https://github.com/soybeanjs/soybean-admin-antd/commit/02c05393) + - update pnpm version  -  by @soybeanjs [(ea02b)](https://github.com/soybeanjs/soybean-admin-antd/commit/ea02b237) + - update pnpm version  -  by @soybeanjs [(c6b00)](https://github.com/soybeanjs/soybean-admin-antd/commit/c6b00bb4) + - remove @simonwep/pickr  -  by @soybeanjs [(502a4)](https://github.com/soybeanjs/soybean-admin-antd/commit/502a4d2b) + - remove soybean.svg  -  by @soybeanjs [(4031f)](https://github.com/soybeanjs/soybean-admin-antd/commit/4031fafc) + - update mock api  -  by @soybeanjs [(c0079)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0079357) + - update pnpm version  -  by @soybeanjs [(adec0)](https://github.com/soybeanjs/soybean-admin-antd/commit/adec0d75) + - update deps & fix keep-alive  -  by @soybeanjs [(13001)](https://github.com/soybeanjs/soybean-admin-antd/commit/13001bc8) + - update @elegant-router/vue, fix inject name in windows  -  by @soybeanjs [(0b56e)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b56e44c) + - add dev and build command with service env  -  by @soybeanjs [(ebb15)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebb15484) + - update deps & remove packages docs  -  by @soybeanjs [(57963)](https://github.com/soybeanjs/soybean-admin-antd/commit/579636b0) + - update pnpm-lock.yaml  -  by @soybeanjs [(147f6)](https://github.com/soybeanjs/soybean-admin-antd/commit/147f60d1) + - update repository url  -  by @soybeanjs [(806a1)](https://github.com/soybeanjs/soybean-admin-antd/commit/806a1cba) + - update deps & update pnpm version  -  by @soybeanjs [(9772a)](https://github.com/soybeanjs/soybean-admin-antd/commit/9772aec2) + - add unocss eslint config  -  by @soybeanjs [(40635)](https://github.com/soybeanjs/soybean-admin-antd/commit/4063529a) + - update launch.json  -  by @soybeanjs [(3db82)](https://github.com/soybeanjs/soybean-admin-antd/commit/3db82acb) + - update vscode extensions.json  -  by @soybeanjs [(4e29a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4e29acaa) + - update pnpm version  -  by @soybeanjs [(7065f)](https://github.com/soybeanjs/soybean-admin-antd/commit/7065f6f0) + - update pnpm version  -  by @soybeanjs [(88f26)](https://github.com/soybeanjs/soybean-admin-antd/commit/88f26411) + - update repository url  -  by @soybeanjs [(f46ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/f46ce2a0) + - update vscode config  -  by @soybeanjs [(bfaec)](https://github.com/soybeanjs/soybean-admin-antd/commit/bfaecce0) + - update component.d.ts  -  by @soybeanjs [(1bebf)](https://github.com/soybeanjs/soybean-admin-antd/commit/1bebf8b2) + - add unocss eslint config  -  by @soybeanjs [(6f004)](https://github.com/soybeanjs/soybean-admin-antd/commit/6f004ce6) + - update deps & fix eslint vue rule  -  by @soybeanjs [(8143b)](https://github.com/soybeanjs/soybean-admin-antd/commit/8143b006) + - update pnpm version  -  by @soybeanjs [(6ad51)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ad51e94) + - add .gitattributes  -  by @soybeanjs [(c0009)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0009203) + - update deps  -  by @soybeanjs [(4babb)](https://github.com/soybeanjs/soybean-admin-antd/commit/4babbe19) + - update pnpm version  -  by @soybeanjs [(9125c)](https://github.com/soybeanjs/soybean-admin-antd/commit/9125cc9b) + - disabled unocss eslint rule: order-attributify  -  by @soybeanjs [(1c72d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1c72dc76) + - update .gitattributes  -  by @soybeanjs [(e5235)](https://github.com/soybeanjs/soybean-admin-antd/commit/e5235e06) + - update pnpm version  -  by @soybeanjs [(30c97)](https://github.com/soybeanjs/soybean-admin-antd/commit/30c97290) + - disabled unocss eslint rule: order-attributify  -  by @soybeanjs [(87838)](https://github.com/soybeanjs/soybean-admin-antd/commit/87838042) + - update pnpm-lock.yaml  -  by @soybeanjs [(8f5a6)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f5a6b1f) + - update pnpm version  -  by @soybeanjs [(42e16)](https://github.com/soybeanjs/soybean-admin-antd/commit/42e16a01) + - update deps & update pnpm version & update eslint config  -  by @soybeanjs [(7392b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7392bebf) + - lower vue version to 3.4.23  -  by @soybeanjs [(b5243)](https://github.com/soybeanjs/soybean-admin-antd/commit/b52432a7) + - update pnpm-lock.yaml  -  by @soybeanjs [(516f4)](https://github.com/soybeanjs/soybean-admin-antd/commit/516f46a4) + - update deps & update pnpm version  -  by @soybeanjs [(5260d)](https://github.com/soybeanjs/soybean-admin-antd/commit/5260d67c) + - use `engines` replace `packageManager`  -  by @soybeanjs [(dcd51)](https://github.com/soybeanjs/soybean-admin-antd/commit/dcd51f4c) + - update pnpm version requirement  -  by @soybeanjs [(19e65)](https://github.com/soybeanjs/soybean-admin-antd/commit/19e65c1a) + - update .npmrc  -  by @soybeanjs [(52188)](https://github.com/soybeanjs/soybean-admin-antd/commit/52188d88) + - update vscode settings  -  by @soybeanjs [(c137b)](https://github.com/soybeanjs/soybean-admin-antd/commit/c137b970) + - merge main to v1.1.0  -  by @soybeanjs [(ebe55)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebe55af7) + - update deps & fix TS error  -  by @soybeanjs [(4ea9c)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ea9c857) + - update eslint-config & fix code  -  by @soybeanjs [(68ea9)](https://github.com/soybeanjs/soybean-admin-antd/commit/68ea9746) + - update @elegant-router/vue & add error handle for resolve route. fixed #442  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/442 [(24ff8)](https://github.com/soybeanjs/soybean-admin-antd/commit/24ff8521) + - update vscode launch.json  -  by @soybeanjs [(4c1c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/4c1c7e65) + - close http proxy  -  by @soybeanjs [(d08a3)](https://github.com/soybeanjs/soybean-admin-antd/commit/d08a3817) + - update mock url  -  by @soybeanjs [(e6086)](https://github.com/soybeanjs/soybean-admin-antd/commit/e6086f0f) + - update mock url  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/22 [(32c00)](https://github.com/soybeanjs/soybean-admin-antd/commit/32c006ae) + - update deps & add lock file  -  by @soybeanjs [(e1777)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1777b45) + - update vscode settings  -  by @soybeanjs [(910df)](https://github.com/soybeanjs/soybean-admin-antd/commit/910dfca8) + - synchronize recent changes  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/23 [(d5348)](https://github.com/soybeanjs/soybean-admin-antd/commit/d53487bd) + - update vscode settings: vue official  -  by @soybeanjs [(76649)](https://github.com/soybeanjs/soybean-admin-antd/commit/76649e2a) + - update eslint config  -  by @soybeanjs [(9c450)](https://github.com/soybeanjs/soybean-admin-antd/commit/9c450098) + - update .npmrc  -  by @soybeanjs [(5d15b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d15bdaf) + - update vscode settings  -  by @soybeanjs [(e77bd)](https://github.com/soybeanjs/soybean-admin-antd/commit/e77bda10) + - Fix deprecated configuration config  -  by @paynezhuang in https://github.com/soybeanjs/soybean-admin-antd/issues/524 [(0d20e)](https://github.com/soybeanjs/soybean-admin-antd/commit/0d20e4c9) + - Fix deprecated configuration config  -  by @soybeanjs [(5275b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5275bb47) + - add script `czh`  -  by @soybeanjs [(02069)](https://github.com/soybeanjs/soybean-admin-antd/commit/0206969e) + - update deps & fix vue-router type  -  by @soybeanjs [(96837)](https://github.com/soybeanjs/soybean-admin-antd/commit/968370b1) + - use json5 resolve env `VITE_OTHER_SERVICE_BASE_URL` & fix proxy enable  -  by @soybeanjs [(b16a9)](https://github.com/soybeanjs/soybean-admin-antd/commit/b16a9632) + - add script czh  -  by @soybeanjs [(1e345)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e345aaa) + - rename script czh to `commit:zh`  -  by @soybeanjs [(01d96)](https://github.com/soybeanjs/soybean-admin-antd/commit/01d962ac) + - use json5 resolve env VITE_OTHER_SERVICE_BASE_URL & fix proxy enable  -  by @soybeanjs [(f8b29)](https://github.com/soybeanjs/soybean-admin-antd/commit/f8b29c4b) + - update vscode extensions  -  by @soybeanjs [(24bb6)](https://github.com/soybeanjs/soybean-admin-antd/commit/24bb6d95) + - update deps & fix sass usage  -  by @soybeanjs [(71e63)](https://github.com/soybeanjs/soybean-admin-antd/commit/71e6307d) + - add desc for base url of app  -  by @soybeanjs [(17d7e)](https://github.com/soybeanjs/soybean-admin-antd/commit/17d7e522) + - update deps & fix vite config  -  by @soybeanjs [(3e0eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e0eb720) + - update vscode extensions  -  by @soybeanjs [(39893)](https://github.com/soybeanjs/soybean-admin-antd/commit/39893488) + - update deps & fix vite config  -  by @soybeanjs [(3243d)](https://github.com/soybeanjs/soybean-admin-antd/commit/3243dd9f) + - add desc for base url of app  -  by @soybeanjs [(4966d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4966ddce) +- **release**: + - 0.0.2  -  by **Soybean** [(e44f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/e44f5d72) + - 0.0.3  -  by **Soybean** [(e1dac)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1dacdbc) + - 0.0.4  -  by **Soybean** [(8b27f)](https://github.com/soybeanjs/soybean-admin-antd/commit/8b27fc8b) + - 0.0.5  -  by **Soybean** [(e53e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/e53e7936) + - 0.1.1 精简版发布  -  by **Soybean** [(db3c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/db3c25ea) + - 0.1.2  -  by **Soybean** [(db75c)](https://github.com/soybeanjs/soybean-admin-antd/commit/db75c914) + - 0.1.3  -  by **Soybean** [(32a7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/32a7cc40) + - 0.9.1  -  by **Soybean** [(be374)](https://github.com/soybeanjs/soybean-admin-antd/commit/be374089) + - 0.9.2  -  by **Soybean** [(11407)](https://github.com/soybeanjs/soybean-admin-antd/commit/11407227) + - 0.9.3  -  by **Soybean** [(d0522)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0522ce5) + - 0.9.4  -  by **Soybean** [(97c92)](https://github.com/soybeanjs/soybean-admin-antd/commit/97c92626) + - 0.9.5  -  by **Soybean** [(08d83)](https://github.com/soybeanjs/soybean-admin-antd/commit/08d83ecb) + - 0.9.6  -  by **Soybean** [(65c21)](https://github.com/soybeanjs/soybean-admin-antd/commit/65c21812) + - 0.9.8  -  by **Soybean** [(34ffd)](https://github.com/soybeanjs/soybean-admin-antd/commit/34ffd9c1) + - 0.9.9  -  by **Soybean** [(c0066)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0066b22) +- **types**: + - remove type declaration for document.startViewTransition (TypeScript 5.6 includes it)  -  by @NHZEX in https://github.com/soybeanjs/soybean-admin-antd/issues/633 [(83ba7)](https://github.com/soybeanjs/soybean-admin-antd/commit/83ba7987) + - remove type declaration for document.startViewTransition (TypeScript 5.6 includes it)  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/44 [(e154f)](https://github.com/soybeanjs/soybean-admin-antd/commit/e154fe6c) + +###    🎨 Styles + +- **GlobalBreadcrumb**: + - 代码格式fix  -  by **Eric_Yuan** [(0243b)](https://github.com/soybeanjs/soybean-admin-antd/commit/0243b275) +- **components**: + - 格式规范  -  by **Soybean** [(d8d3c)](https://github.com/soybeanjs/soybean-admin-antd/commit/d8d3cc23) + - 代码优化  -  by **Soybean** [(1e2fd)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e2fdda0) + - Uniform icon size for header  -  by @Azir-11 [(b37c1)](https://github.com/soybeanjs/soybean-admin-antd/commit/b37c1e94) +- **other**: + - modify the Chinese name of the grayscale mode  -  by **Azir** [(53770)](https://github.com/soybeanjs/soybean-admin-antd/commit/53770029) +- **projects**: + - 格式化代码  -  by **Soybean** [(d680e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d680e7d9) + - 代码格式化  -  by **Soybean** [(2bc50)](https://github.com/soybeanjs/soybean-admin-antd/commit/2bc50009) + - 路由相关文件夹简化  -  by **Soybean** [(e5793)](https://github.com/soybeanjs/soybean-admin-antd/commit/e5793e1c) + - update prettier config  -  by **Soybean** [(df56a)](https://github.com/soybeanjs/soybean-admin-antd/commit/df56abe1) + - format yaml  -  by **Soybean** [(fb46d)](https://github.com/soybeanjs/soybean-admin-antd/commit/fb46d7ec) + - per style [完善样式]  -  by **Soybean** [(209ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/209ef3d8) + - unify card border radius, 16px to 8px  -  by **Soybean** [(cbda4)](https://github.com/soybeanjs/soybean-admin-antd/commit/cbda4a38) + - update default theme color  -  by @soybeanjs [(43ac2)](https://github.com/soybeanjs/soybean-admin-antd/commit/43ac23f1) + - prettier format code  -  by @soybeanjs [(24cf1)](https://github.com/soybeanjs/soybean-admin-antd/commit/24cf1d92) + - fix menu style  -  by @soybeanjs [(d8b9b)](https://github.com/soybeanjs/soybean-admin-antd/commit/d8b9b942) + - perf layout card style  -  by @soybeanjs [(fc409)](https://github.com/soybeanjs/soybean-admin-antd/commit/fc409db0) + - format code  -  by @soybeanjs [(a7481)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7481663) + - fix event style  -  by @soybeanjs [(e935f)](https://github.com/soybeanjs/soybean-admin-antd/commit/e935f77e) + - update theme mode segment height  -  by @soybeanjs [(4d846)](https://github.com/soybeanjs/soybean-admin-antd/commit/4d8469e2) + - fix tooltip zIndex of ButtonIcon  -  by @soybeanjs [(db747)](https://github.com/soybeanjs/soybean-admin-antd/commit/db747c4a) + - sort defineProps, defineEmits with TS type  -  by @soybeanjs [(123fd)](https://github.com/soybeanjs/soybean-admin-antd/commit/123fd4f9) + - unify button icon style. close #26  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/26 [(ef60e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ef60e2cb) + - fit table column width of checkbox  -  by @soybeanjs [(ebcfb)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebcfbe1b) + - rename script czh to commit:zh  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/597 [(5094f)](https://github.com/soybeanjs/soybean-admin-antd/commit/5094f0ee) + - reduce ambiguity in theme configuration instructions.  -  by @Azir-11 [(75cbf)](https://github.com/soybeanjs/soybean-admin-antd/commit/75cbfbbf) + - reduce ambiguity in theme configuration instructions.  -  by @Azir-11 [(cf4cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf4ccad9) + +###    🤖 CI + +- add docker build  -  by **徐志强** [(af740)](https://github.com/soybeanjs/soybean-admin-antd/commit/af740461) +- change docker image name  -  by **徐志强** [(6fbde)](https://github.com/soybeanjs/soybean-admin-antd/commit/6fbde1eb) +- **projects**: + - add github actions config  -  by @soybeanjs [(4cb17)](https://github.com/soybeanjs/soybean-admin-antd/commit/4cb17c74) + - update release.yml  -  by @soybeanjs [(7b298)](https://github.com/soybeanjs/soybean-admin-antd/commit/7b298c67) + - add issue template  -  by @soybeanjs [(06e20)](https://github.com/soybeanjs/soybean-admin-antd/commit/06e204a7) + - add github config  -  by @soybeanjs [(fe15a)](https://github.com/soybeanjs/soybean-admin-antd/commit/fe15a9a2) + - add github issues template  -  by @soybeanjs [(b5027)](https://github.com/soybeanjs/soybean-admin-antd/commit/b5027c8f) + - update github issues template  -  by @soybeanjs [(ff1d5)](https://github.com/soybeanjs/soybean-admin-antd/commit/ff1d5046) + - add and update github issues template  -  by @soybeanjs [(a3619)](https://github.com/soybeanjs/soybean-admin-antd/commit/a361927f) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)  [![wzc520pyfm](https://github.com/wzc520pyfm.png?size=48)](https://github.com/wzc520pyfm)  [![JOU-amjs](https://github.com/JOU-amjs.png?size=48)](https://github.com/JOU-amjs)  [![NHZEX](https://github.com/NHZEX.png?size=48)](https://github.com/NHZEX)  [![mufeng889](https://github.com/mufeng889.png?size=48)](https://github.com/mufeng889)  [![yanbowe](https://github.com/yanbowe.png?size=48)](https://github.com/yanbowe)  [![PZ-18664918826](https://github.com/PZ-18664918826.png?size=48)](https://github.com/PZ-18664918826)  [![paynezhuang](https://github.com/paynezhuang.png?size=48)](https://github.com/paynezhuang)  [![mmdapl](https://github.com/mmdapl.png?size=48)](https://github.com/mmdapl)  [![wynn-w](https://github.com/wynn-w.png?size=48)](https://github.com/wynn-w)  [![KickCashew](https://github.com/KickCashew.png?size=48)](https://github.com/KickCashew)  [![sigma-plus](https://github.com/sigma-plus.png?size=48)](https://github.com/sigma-plus)  [![m-xlsea](https://github.com/m-xlsea.png?size=48)](https://github.com/m-xlsea)  [![orangelckc](https://github.com/orangelckc.png?size=48)](https://github.com/orangelckc)  [![zyhnbyyds](https://github.com/zyhnbyyds.png?size=48)](https://github.com/zyhnbyyds)  [![smileluck](https://github.com/smileluck.png?size=48)](https://github.com/smileluck)  [![Particaly](https://github.com/Particaly.png?size=48)](https://github.com/Particaly)  [![linjiangl](https://github.com/linjiangl.png?size=48)](https://github.com/linjiangl)   +[一寸灰](mailto:webzhangfei@163.com), [Redon](mailto:790348264@qq.com), [Azir](mailto:2075125282@qq.com), [dodu2014](mailto:dodu@live.cn), [CHENZL](mailto:zlong5568863@qq.com), [JianJroh](mailto:rhjian@foxmail.com), [alleycharming](mailto:alleycharming@gmail.com), [燕博文](mailto:349952469@qq.com), [~li](mailto:miciili-02@outlook.com), [Kori](mailto:kexin@korix.top), [Ikko Eltociear Ashimine](mailto:eltociear@gmail.com), [lapislazulisch](mailto:108389666+lapislazulisch@users.noreply.github.com), [muzzyh](mailto:1430750200@qq.com), [liwei](mailto:liwei@e-agency-china.com), [Soybean](mailto:honghuangdc@gmail.com), [cc](mailto:cc@qq.com), [xiaojunnuo](mailto:xiaojunnuo@qq.com), [Kirk Lin](mailto:linkirk@163.com), [small_happy](mailto:5304122+small_happy@user.noreply.gitee.com), [guuuuo](mailto:1460412+guuuuo@users.noreply.github.com), [lixin59](mailto:1453287107@qq.com), [alue_mobile](mailto:hi.alue@qq.com), [HuangZheng](mailto:huangzheng@shu.edu.cn), [sunhao1256](mailto:lssh731105702@qq.com), [shabby2333](mailto:1308933842@qq.com), [zuihou](mailto:244387066@qq.com), [Wang Zheng](mailto:wz@sdu.edu.cn), [RockerHX](mailto:rockerhx@gmail.com), [Henry.Huang](mailto:hhglory@outlook.com), [徐志强](mailto:zhiqiang.xu@dolphindb.com), [xiaotao2018](mailto:37537969+xiaotao2018@users.noreply.github.com), [Soybean](mailto:2570172956@qq.com), [tanminglin](mailto:846518677@qq.com), [Grazing Wind](mailto:dxxzst@gmail.com), [Eric_Yuan](mailto:330365043@qq.com), [元家怿](mailto:jiayi.yuan@lkcoffee.com), [相思](mailto:admin@toolv.cn), [元家怿](mailto:jiayi.yuan@luckincoffee.com), [“Southliu”](mailto:1275093225@qq.com), [Soybean](mailto:49704545+honghuangdc@users.noreply.github.com), [毛博文](mailto:maobowen@bonc.com.cn), [pany](mailto:939630029@qq.com), [bundle](mailto:bundle.js@gmail.com), [Lsq128](mailto:924500075@qq.com), [Liushengqun](mailto:18232366809@163.com), [liujunzheng](mailto:liujunzheng@weihaizixun.com), [lingdu](mailto:waong2005@126.com) + +## [v1.3.9](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.10...v1.3.9) (2024-11-17) + +###    🚀 Features + +- **projects**: support show tab when not loggedIn  -  by @soybeanjs [(ba381)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba38119e) + +###    🐞 Bug Fixes + +- **deps**: + - reduced eslint version to 9.14.0  -  by @soybeanjs [(af417)](https://github.com/soybeanjs/soybean-admin-antd/commit/af4177e7) +- **projects**: + - fix route guard hook `onRouteSwitchWhenLoggedIn`. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(ab985)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab9858c7) + - check if init userInfo when initAuthRoute. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(9f4fb)](https://github.com/soybeanjs/soybean-admin-antd/commit/9f4fb8c3) + +###    🛠 Optimizations + +- **projects**: + - optimize router guard  -  by @soybeanjs [(0dfcf)](https://github.com/soybeanjs/soybean-admin-antd/commit/0dfcf18b) + - use `defu` to fill added theme config  -  by @soybeanjs [(101b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/101b6f90) + +###    📖 Documentation + +- **projects**: ✏️ add element-plus version link  -  by **一寸灰** in https://github.com/soybeanjs/soybean-admin-antd/issues/679 [(5c6ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c6ab0b5) + +###    🏡 Chore + +- rename env.d.ts to vite-env.d.ts  -  by @wzc520pyfm in https://github.com/soybeanjs/soybean-admin-antd/issues/675 [(b93c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/b93c2036) +- **projects**: update deps & fix vite config  -  by @soybeanjs [(3e0eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e0eb720) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![wzc520pyfm](https://github.com/wzc520pyfm.png?size=48)](https://github.com/wzc520pyfm)   +[一寸灰](mailto:webzhangfei@163.com),  + +## [v1.3.8](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.10...v1.3.8) (2024-10-25) + +###    🚀 Features + +- **projects**: + - support scheduled detection and update system. close #657  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/669 and https://github.com/soybeanjs/soybean-admin-antd/issues/657 [(d088f)](https://github.com/soybeanjs/soybean-admin-antd/commit/d088f813) + - app version notification plugin support sub deploy path. close #668  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/668 [(a53eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/a53eb10c) + - support show tab when not loggedIn  -  by @soybeanjs [(ba381)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba38119e) + +###    🐞 Bug Fixes + +- **deps**: + - reduced eslint version to 9.14.0  -  by @soybeanjs [(af417)](https://github.com/soybeanjs/soybean-admin-antd/commit/af4177e7) +- **projects**: + - fix route guard hook `onRouteSwitchWhenLoggedIn`. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(ab985)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab9858c7) + - check if init userInfo when initAuthRoute. fixed #680  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/680 [(9f4fb)](https://github.com/soybeanjs/soybean-admin-antd/commit/9f4fb8c3) + +###    🛠 Optimizations + +- **projects**: + - optimize code  -  by @soybeanjs [(9ad5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ad5d717) + - optimize router guard  -  by @soybeanjs [(0dfcf)](https://github.com/soybeanjs/soybean-admin-antd/commit/0dfcf18b) + - use `defu` to fill added theme config  -  by @soybeanjs [(101b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/101b6f90) + +###    💅 Refactors + +- **projects**: refactor router guard. fix #655  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/667 and https://github.com/soybeanjs/soybean-admin-antd/issues/655 [(09144)](https://github.com/soybeanjs/soybean-admin-antd/commit/09144dfe) + +###    📖 Documentation + +- **projects**: + - set the Chinese version of README as default  -  by @soybeanjs [(9d28b)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d28b31c) + - ✏️ add element-plus version link  -  by **一寸灰** in https://github.com/soybeanjs/soybean-admin-antd/issues/679 [(5c6ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c6ab0b5) + +###    🏡 Chore + +- rename env.d.ts to vite-env.d.ts  -  by @wzc520pyfm in https://github.com/soybeanjs/soybean-admin-antd/issues/675 [(b93c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/b93c2036) +- **deps**: + - update deps  -  by @soybeanjs [(91de4)](https://github.com/soybeanjs/soybean-admin-antd/commit/91de4a8e) + - update deps  -  by @soybeanjs [(0c809)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c809de6) +- **projects**: + - add desc for base url of app  -  by @soybeanjs [(17d7e)](https://github.com/soybeanjs/soybean-admin-antd/commit/17d7e522) + - update deps & fix vite config  -  by @soybeanjs [(3e0eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/3e0eb720) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![wzc520pyfm](https://github.com/wzc520pyfm.png?size=48)](https://github.com/wzc520pyfm)  [![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)   +[一寸灰](mailto:webzhangfei@163.com),  + +## [v1.3.7](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.6...v1.3.7) (2024-09-21) + +###    🚨 Breaking Changes + +- **projects**: update scss config  -  by @soybeanjs [(b1cda)](https://github.com/soybeanjs/soybean-admin-antd/commit/b1cda6a) + +###    🐞 Bug Fixes + +- **projects**: fix global-tab click conflict with contextmenu  -  by @soybeanjs [(c0e87)](https://github.com/soybeanjs/soybean-admin-antd/commit/c0e8795) + +###    💅 Refactors + +- **packages**: @sa/materials: remove tab close shortcut by mouse  -  by @soybeanjs [(9fb72)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fb722d) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(3453c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3453c81) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.6](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.5...v1.3.6) (2024-09-20) + +###    🐞 Bug Fixes + +- **projects**: + - fix click global-tab in iPad  -  by @soybeanjs [(740cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/740cf4c) + - when the roles filter submenu is empty, the parent menu is not excluded  -  by @soybeanjs [(6b2fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b2fc0a) + +###    🛠 Optimizations + +- **projects**: remove defineModel setting,enabled by default  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/42 [(05bad)](https://github.com/soybeanjs/soybean-admin-antd/commit/05bad8d) + +###    📖 Documentation + +- **projects**: update QQ group link.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/43 [(589ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/589ecae) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(5e0c2)](https://github.com/soybeanjs/soybean-admin-antd/commit/5e0c288) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)  [![mufeng889](https://github.com/mufeng889.png?size=48)](https://github.com/mufeng889)   + +## [v1.3.5](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.4...v1.3.5) (2024-09-08) + +###    🚀 Features + +- **packages**: + - @sa/scripts: add more commit types according to Apache specifications  -  by @soybeanjs [(5a020)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a020dd) + - @sa/axios: add response to flatRequest when success  -  by @soybeanjs [(aace8)](https://github.com/soybeanjs/soybean-admin-antd/commit/aace819) +- **projects**: + - does the configuration support automatic updates  -  by @soybeanjs [(ffe4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ffe4cef) + - add app error handler  -  by @soybeanjs [(60366)](https://github.com/soybeanjs/soybean-admin-antd/commit/60366c2) + +###    🐞 Bug Fixes + +- **projects**: + - avoid retrieving cached HTML  -  by @soybeanjs [(75df1)](https://github.com/soybeanjs/soybean-admin-antd/commit/75df11c) + - fix breadcrumb when activeMenu is parent menu  -  by @soybeanjs [(49092)](https://github.com/soybeanjs/soybean-admin-antd/commit/4909291) + - fix refresh token when meet multi requests  -  by @soybeanjs [(5ae17)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ae17e6) +- **projects): fix(projects**: + - fix login redirect  -  by @soybeanjs [(5ccdb)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ccdb17) + +###    🛠 Optimizations + +- **projects**: optimize type  -  by @soybeanjs [(4679b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4679b17) + +###    🏡 Chore + +- **projects**: + - rename script czh to `commit:zh`  -  by @soybeanjs [(01d96)](https://github.com/soybeanjs/soybean-admin-antd/commit/01d962a) + - use json5 resolve env VITE_OTHER_SERVICE_BASE_URL & fix proxy enable  -  by @soybeanjs [(f8b29)](https://github.com/soybeanjs/soybean-admin-antd/commit/f8b29c4) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.4](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.3...v1.3.4) (2024-09-08) + +###    🛠 Optimizations + +- **projects**: optimize code  -  by @soybeanjs [(6e8a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/6e8a55d) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.3](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.2...v1.3.3) (2024-09-08) + +###    🐞 Bug Fixes + +- **projects**: fix watermark settings  -  by @soybeanjs [(dbe8e)](https://github.com/soybeanjs/soybean-admin-antd/commit/dbe8ec6) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.2](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.1...v1.3.2) (2024-09-08) + +###    🚀 Features + +- **projects**: + - add color fading mode  -  by @soybeanjs [(719f0)](https://github.com/soybeanjs/soybean-admin-antd/commit/719f02f) + - add full screen watermark  -  by @soybeanjs [(6bb66)](https://github.com/soybeanjs/soybean-admin-antd/commit/6bb66a0) + +###    🛠 Optimizations + +- **projects**: optimize response code comparison  -  by @soybeanjs [(d7025)](https://github.com/soybeanjs/soybean-admin-antd/commit/d702524) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.1](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.3.0...v1.3.1) (2024-09-08) + +###    🐞 Bug Fixes + +- **projects**: fix abnormal width of the sidebar in the top menu mix and reverse mode  -  by @soybeanjs [(0abce)](https://github.com/soybeanjs/soybean-admin-antd/commit/0abce88) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.3.0](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.8...v1.3.0) (2024-09-08) + +###    🚨 Breaking Changes + +- **packages**: modify request retry times to 0  -  by @soybeanjs [(d87e9)](https://github.com/soybeanjs/soybean-admin-antd/commit/d87e9c1) +- **projects**: refactor global menu & support reversed-horizontal-mix-menu  -  by @soybeanjs [(2244f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2244f0c) + +###    🚀 Features + +- **packages**: + - @sa/scripts: command gitCommit support Chinese  -  by @soybeanjs [(8eb1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/8eb1d5e) + - @sa/axios: replace CancelTokenSource by AbortController  -  by @soybeanjs [(91296)](https://github.com/soybeanjs/soybean-admin-antd/commit/9129601) + - @sa/scripts: add ignore pattern list for command gitCommitVerify  -  by @soybeanjs [(5a950)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a95026) + +###    🐞 Bug Fixes + +- **hooks**: prevent program freezing when pagesize returns 0  -  by @soybeanjs [(05912)](https://github.com/soybeanjs/soybean-admin-antd/commit/05912b6) + +###    💅 Refactors + +- **projects**: + - combine theme tokens and theme settings  -  by @soybeanjs [(3f289)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f28911) + - change css vars mount to root  -  by @soybeanjs [(47c46)](https://github.com/soybeanjs/soybean-admin-antd/commit/47c46e3) + +###    🏡 Chore + +- **projects**: add script czh  -  by @soybeanjs [(1e345)](https://github.com/soybeanjs/soybean-admin-antd/commit/1e345aa) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.8](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.7...v1.2.8) (2024-09-08) + +###    🐞 Bug Fixes + +- **packages**: + - @sa/hooks: fix searchParams of useHookTable  -  by @soybeanjs [(cb5bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb5bf07) +- **types**: + - Fixed the reference type error  -  by @soybeanjs [(6b868)](https://github.com/soybeanjs/soybean-admin-antd/commit/6b86861) + - fix data type of useHookTable  -  by @soybeanjs [(3dd78)](https://github.com/soybeanjs/soybean-admin-antd/commit/3dd78d4) + +###    💅 Refactors + +- **projects**: replace `cloneDeep` of `lodash-es` with `klona`  -  by @soybeanjs [(240ab)](https://github.com/soybeanjs/soybean-admin-antd/commit/240ab79) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(7bc1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/7bc1d98) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.7](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.6...v1.2.7) (2024-09-08) + +###    🚀 Features + +- **projects**: supports custom menu icon sizes  -  by **Soybean** [(c8a9e)](https://github.com/soybeanjs/soybean-admin-antd/commit/c8a9e85) + +###    🐞 Bug Fixes + +- **components**: + - fix click `MenuToggler` throw error  -  by **Soybean** [(45588)](https://github.com/soybeanjs/soybean-admin-antd/commit/455880b) + - fix `TableHeaderOperation` style  -  by **Soybean** [(251d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/251d15a) +- **projects**: + - fix manage page edit data. fixed #32  -  by **Soybean** in https://github.com/soybeanjs/soybean-admin-antd/issues/32 [(740d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/740d6f5) + - fix menu style  -  by **Soybean** [(4355b)](https://github.com/soybeanjs/soybean-admin-antd/commit/4355b6e) + +###    🏡 Chore + +- **deps**: update deps  -  by **Soybean** [(5fcf2)](https://github.com/soybeanjs/soybean-admin-antd/commit/5fcf2bd) +- **projects**: Fix deprecated configuration config  -  by **Soybean** [(5275b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5275bb4) + +###    ❤️ Contributors + + +[Soybean](mailto:soybeanjs@outlook.com) + +## [v1.2.6](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.5...v1.2.6) (2024-06-21) + +###    🐞 Bug Fixes + +- **projects**: + - request modal title use i18n  -  by @honghuangdc [(f97e7)](https://github.com/soybeanjs/soybean-admin-antd/commit/f97e74e) + - add `getDataByPage` for `useTable`  -  by @honghuangdc [(cf265)](https://github.com/soybeanjs/soybean-admin-antd/commit/cf2659d) + - fix login redirect to routeHome when routeHome of dynamic route is not same as static route  -  by @honghuangdc [(f6c66)](https://github.com/soybeanjs/soybean-admin-antd/commit/f6c66ec) + +###    📖 Documentation + +- **projects**: update README  -  by @honghuangdc [(a769b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a769b1a) + +###    🏡 Chore + +- **deps**: update deps.  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/30 [(e110d)](https://github.com/soybeanjs/soybean-admin-antd/commit/e110dd0) + +###    🤖 CI + +- **projects**: add and update github issues template  -  by @honghuangdc [(a3619)](https://github.com/soybeanjs/soybean-admin-antd/commit/a361927) + +###    ❤️ Contributors + +[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)  [![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)   + +## [v1.2.5](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.4...v1.2.5) (2024-06-15) + +###    🐞 Bug Fixes + +- **projects**: Fix the issue of abnormal tab caching after logout  -  by @soybeanjs [(e6349)](https://github.com/soybeanjs/soybean-admin-antd/commit/e63490e) + +###    🛠 Optimizations + +- **projects**: Initializing the static routing function does not require asynchronization  -  by @soybeanjs [(02d66)](https://github.com/soybeanjs/soybean-admin-antd/commit/02d66cb) +- **types**: Enhance compatibility of global types  -  by @soybeanjs [(dc359)](https://github.com/soybeanjs/soybean-admin-antd/commit/dc359f5) +- **utils**: Reduce code indentation and improve readability  -  by @soybeanjs [(54ae8)](https://github.com/soybeanjs/soybean-admin-antd/commit/54ae82b) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(423fa)](https://github.com/soybeanjs/soybean-admin-antd/commit/423fafc) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.4](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.3...v1.2.4) (2024-06-14) + +###    🛠 Optimizations + +- **projects**: + - optimize `setupAppVersionNotification`  -  by @soybeanjs [(f061d)](https://github.com/soybeanjs/soybean-admin-antd/commit/f061d8b) + - get buildTime with timezone 'Asia/Shanghai'  -  by @soybeanjs [(b256a)](https://github.com/soybeanjs/soybean-admin-antd/commit/b256a3e) + +###    🤖 CI + +- **projects**: add github config  -  by @soybeanjs [(fe15a)](https://github.com/soybeanjs/soybean-admin-antd/commit/fe15a9a) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.3](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.2...v1.2.3) (2024-06-13) + +###    🐞 Bug Fixes + +- **projects**: + - fix mobile browser theme issue by adding color-scheme meta tag to index.html  -  by @KickCashew in https://github.com/soybeanjs/soybean-admin-antd/issues/27 [(6bf97)](https://github.com/soybeanjs/soybean-admin-antd/commit/6bf972d) + - Fix secondary directory components is empty  -  by @paynezhuang in https://github.com/soybeanjs/soybean-admin-antd/issues/29 [(fb48f)](https://github.com/soybeanjs/soybean-admin-antd/commit/fb48f41) + +###    🛠 Optimizations + +- **projects**: + - optimize table scrollConfig. fixed #25  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/25 [(d0f8e)](https://github.com/soybeanjs/soybean-admin-antd/commit/d0f8e55) + - optimize table rowSelection  -  by @soybeanjs [(49c57)](https://github.com/soybeanjs/soybean-admin-antd/commit/49c572b) + +###    📖 Documentation + +- **projects**: + - Fixed the hyperlink pointing error  -  by **Azir** [(d5602)](https://github.com/soybeanjs/soybean-admin-antd/commit/d5602ed) + - update README  -  by @soybeanjs [(9527e)](https://github.com/soybeanjs/soybean-admin-antd/commit/9527ead) + +###    🏡 Chore + +- **deps**: + - update deps  -  by @soybeanjs [(9954c)](https://github.com/soybeanjs/soybean-admin-antd/commit/9954c8e) + - update deps  -  by @soybeanjs [(d9f9f)](https://github.com/soybeanjs/soybean-admin-antd/commit/d9f9f9f) + +###    🎨 Styles + +- **projects**: + - unify button icon style. close #26  -  by @soybeanjs in https://github.com/soybeanjs/soybean-admin-antd/issues/26 [(ef60e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ef60e2c) + - fit table column width of checkbox  -  by @soybeanjs [(ebcfb)](https://github.com/soybeanjs/soybean-admin-antd/commit/ebcfbe1) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![paynezhuang](https://github.com/paynezhuang.png?size=48)](https://github.com/paynezhuang)  [![KickCashew](https://github.com/KickCashew.png?size=48)](https://github.com/KickCashew)   +[Azir](mailto:2075125282@qq.com) + +## [v1.2.2](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.1...v1.2.2) (2024-06-12) + +###    🚀 Features + +- **projects**: reset scroll position when tab change  -  by @soybeanjs [(804f9)](https://github.com/soybeanjs/soybean-admin-antd/commit/804f9e6) + +###    🐞 Bug Fixes + +- **projects**: + - hide AppVersionNotification in DEV mode  -  by @soybeanjs [(e3d91)](https://github.com/soybeanjs/soybean-admin-antd/commit/e3d91df) + - fix menu-toggler hidden in mobile layout  -  by @soybeanjs [(a73d2)](https://github.com/soybeanjs/soybean-admin-antd/commit/a73d2e1) + +###    📖 Documentation + +- **projects**: update README  -  by @soybeanjs [(bab68)](https://github.com/soybeanjs/soybean-admin-antd/commit/bab6817) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.1](https://github.com/soybeanjs/soybean-admin-antd/compare/v1.2.0...v1.2.1) (2024-06-07) + +###    🐞 Bug Fixes + +- **projects**: + - fix get user info when page reload  -  by @soybeanjs [(0f6b7)](https://github.com/soybeanjs/soybean-admin-antd/commit/0f6b73f) + - fix setupAppVersionNotification render  -  by @soybeanjs [(63d5d)](https://github.com/soybeanjs/soybean-admin-antd/commit/63d5dc5) + +###    🏡 Chore + +- **deps**: update deps  -  by @soybeanjs [(a6c0e)](https://github.com/soybeanjs/soybean-admin-antd/commit/a6c0eae) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)   + +## [v1.2.0](https://github.com/soybeanjs/soybean-admin-antd/compare/undefined...v1.2.0) (2024-06-07) + +###    🚀 Features + +- **hooks**: + - add @sa/hooks  -  by @soybeanjs [(7677a)](https://github.com/soybeanjs/soybean-admin-antd/commit/7677af5) + - add use-echarts  -  by @soybeanjs [(ada3f)](https://github.com/soybeanjs/soybean-admin-antd/commit/ada3f98) + - @sa/hooks: add useTable  -  by @soybeanjs [(348b4)](https://github.com/soybeanjs/soybean-admin-antd/commit/348b4f6) + - add setOptions for useEcharts  -  by @soybeanjs [(40ceb)](https://github.com/soybeanjs/soybean-admin-antd/commit/40cebab) +- **packages**: + - @sa/scripts: add new commit type optimize and commit scope packages  -  by @soybeanjs [(ee111)](https://github.com/soybeanjs/soybean-admin-antd/commit/ee1119e) +- **projects**: + - init  -  by @soybeanjs [(77b6e)](https://github.com/soybeanjs/soybean-admin-antd/commit/77b6e97) + - add switch-lang, add look-forward  -  by @soybeanjs [(0c666)](https://github.com/soybeanjs/soybean-admin-antd/commit/0c66695) + - add logout  -  by @soybeanjs [(486de)](https://github.com/soybeanjs/soybean-admin-antd/commit/486dec4) + - add login module  -  by @soybeanjs [(314e8)](https://github.com/soybeanjs/soybean-admin-antd/commit/314e813) + - add theme palette and colors support unocss color opacity  -  by @soybeanjs [(88e64)](https://github.com/soybeanjs/soybean-admin-antd/commit/88e6438) + - nprogress color feat theme color  -  by @soybeanjs [(d7621)](https://github.com/soybeanjs/soybean-admin-antd/commit/d7621d8) + - perf route meta and route i18n  -  by @soybeanjs [(a2e0f)](https://github.com/soybeanjs/soybean-admin-antd/commit/a2e0f47) + - route store  -  by @soybeanjs [(a7784)](https://github.com/soybeanjs/soybean-admin-antd/commit/a77843c) + - menu in route store  -  by @soybeanjs [(81e59)](https://github.com/soybeanjs/soybean-admin-antd/commit/81e59d3) + - perf menu and add cache in route store  -  by @soybeanjs [(5c60b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5c60b15) + - antd menu  -  by @soybeanjs [(542e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/542e5d3) + - add menu icon  -  by @soybeanjs [(60f29)](https://github.com/soybeanjs/soybean-admin-antd/commit/60f29ed) + - add axios  -  by @soybeanjs [(110fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/110fce6) + - update @elegant-router/vue and fix types  -  by @soybeanjs [(b7632)](https://github.com/soybeanjs/soybean-admin-antd/commit/b76329b) + - service and proxy  -  by @soybeanjs [(ed68c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ed68c8f) + - login, antdv useApp, form  -  by @soybeanjs [(53c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/53c2010) + - router guide  -  by @soybeanjs [(5cf87)](https://github.com/soybeanjs/soybean-admin-antd/commit/5cf87e1) + - add login loading to confirm button  -  by @soybeanjs [(cb6c7)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb6c7d1) + - add page manage and remove page user  -  by @soybeanjs [(73b02)](https://github.com/soybeanjs/soybean-admin-antd/commit/73b023c) + - menu click to switch route  -  by @soybeanjs [(60ef0)](https://github.com/soybeanjs/soybean-admin-antd/commit/60ef0af) + - keep antd menu transition same as system  -  by @soybeanjs [(77c96)](https://github.com/soybeanjs/soybean-admin-antd/commit/77c9623) + - add tab store, PageTab  -  by @soybeanjs [(ecd0d)](https://github.com/soybeanjs/soybean-admin-antd/commit/ecd0df2) + - add LangSwitch to component, fix login page i18n  -  by @soybeanjs [(e435b)](https://github.com/soybeanjs/soybean-admin-antd/commit/e435b18) + - add tab dropdown, FullScreen  -  by @soybeanjs [(dcc4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/dcc4c86) + - add ThemeDrawer  -  by @soybeanjs [(22447)](https://github.com/soybeanjs/soybean-admin-antd/commit/2244788) + - add ReloadButton  -  by @soybeanjs [(66b90)](https://github.com/soybeanjs/soybean-admin-antd/commit/66b9070) + - add ButtonIcon with tooltip  -  by @soybeanjs [(4649d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4649dec) + - support mobile layout  -  by @soybeanjs [(cfcf8)](https://github.com/soybeanjs/soybean-admin-antd/commit/cfcf835) + - add page animate  -  by @soybeanjs [(41c38)](https://github.com/soybeanjs/soybean-admin-antd/commit/41c384f) + - add beadcrumb  -  by @soybeanjs [(d9279)](https://github.com/soybeanjs/soybean-admin-antd/commit/d927989) + - routes cache  -  by @soybeanjs [(073e6)](https://github.com/soybeanjs/soybean-admin-antd/commit/073e615) + - cache tabs  -  by @soybeanjs [(1f439)](https://github.com/soybeanjs/soybean-admin-antd/commit/1f4398d) + - add reset routes  -  by @soybeanjs [(76400)](https://github.com/soybeanjs/soybean-admin-antd/commit/76400a8) + - themeDrawer layout mode  -  by @soybeanjs [(8c36d)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c36db7) + - add horizontal menu  -  by @soybeanjs [(012d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/012d1e8) + - menu style adapter system  -  by @soybeanjs [(32a2d)](https://github.com/soybeanjs/soybean-admin-antd/commit/32a2d98) + - vertical-mix sider  -  by @soybeanjs [(c9329)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9329f9) + - HorizontalMixMenu  -  by @soybeanjs [(2d59d)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d59dd6) + - theme settings theme colors  -  by @soybeanjs [(5d883)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d883f5) + - finish theme settings  -  by @soybeanjs [(92b4c)](https://github.com/soybeanjs/soybean-admin-antd/commit/92b4c18) + - theme settings copy  -  by @soybeanjs [(95e38)](https://github.com/soybeanjs/soybean-admin-antd/commit/95e38c9) + - iconify offline  -  by @soybeanjs [(388e5)](https://github.com/soybeanjs/soybean-admin-antd/commit/388e504) + - antd locale, dayjs locale  -  by @soybeanjs [(3b33c)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b33ce9) + - support Vite5  -  by @soybeanjs [(8e41a)](https://github.com/soybeanjs/soybean-admin-antd/commit/8e41a8f) + - request pkgs  -  by @soybeanjs [(81a31)](https://github.com/soybeanjs/soybean-admin-antd/commit/81a312f) + - update @sa/axios  -  by @soybeanjs [(fd790)](https://github.com/soybeanjs/soybean-admin-antd/commit/fd790fa) + - @sa/axios: createRequest, createFlatRequest, createHookRequest  -  by @soybeanjs [(c5c45)](https://github.com/soybeanjs/soybean-admin-antd/commit/c5c456b) + - add sort routes  -  by @soybeanjs [(637c6)](https://github.com/soybeanjs/soybean-admin-antd/commit/637c64a) + - add app loading  -  by @soybeanjs [(a7ef1)](https://github.com/soybeanjs/soybean-admin-antd/commit/a7ef1a5) + - add vitepress docs  -  by @soybeanjs [(5f72f)](https://github.com/soybeanjs/soybean-admin-antd/commit/5f72fa8) + - add copyright, unocss shortcut: card-wrapper, update package.json  -  by @soybeanjs [(a11b9)](https://github.com/soybeanjs/soybean-admin-antd/commit/a11b955) + - add page: about  -  by @soybeanjs [(a2b6b)](https://github.com/soybeanjs/soybean-admin-antd/commit/a2b6b4e) + - add custom route exception  -  by @soybeanjs [(0bab9)](https://github.com/soybeanjs/soybean-admin-antd/commit/0bab941) + - filter tabs which are not in routes  -  by @soybeanjs [(b047c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b047c2e) + - packages/scripts: add command changelog,release  -  by @soybeanjs [(50926)](https://github.com/soybeanjs/soybean-admin-antd/commit/50926f3) + - add script: gen-route  -  by @soybeanjs [(e9b15)](https://github.com/soybeanjs/soybean-admin-antd/commit/e9b1571) + - @sa/axios: add qs stringify for params  -  by @soybeanjs [(6ee5a)](https://github.com/soybeanjs/soybean-admin-antd/commit/6ee5a21) + - page home & perf useEcharts  -  by @soybeanjs [(37c92)](https://github.com/soybeanjs/soybean-admin-antd/commit/37c928f) + - add page function_tab  -  by @soybeanjs [(bd645)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd64563) + - support directory menu hide all child menus.  -  by @soybeanjs [(cd72e)](https://github.com/soybeanjs/soybean-admin-antd/commit/cd72e7a) + - support route query in menu  -  by @soybeanjs [(063f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/063f563) + - login page: code-login  -  by @soybeanjs [(f4e7c)](https://github.com/soybeanjs/soybean-admin-antd/commit/f4e7c92) + - login page: register  -  by @soybeanjs [(b6420)](https://github.com/soybeanjs/soybean-admin-antd/commit/b642032) + - @sa/axios: support instance state, fix flatRequest error type  -  by @soybeanjs [(3f418)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f41811) + - add request exception  -  by @soybeanjs [(0b1ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b1ece5) + - add function page: request  -  by @soybeanjs [(757d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/757d1d6) + - add function page: hide-child,super-page,toggle-auth  -  by @soybeanjs [(886ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/886ea57) + - manage page: manage_role  -  by @soybeanjs [(658dc)](https://github.com/soybeanjs/soybean-admin-antd/commit/658dc94) + - perf page manage_role  -  by @soybeanjs [(55945)](https://github.com/soybeanjs/soybean-admin-antd/commit/5594558) + - Synchronize role management and menu management  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/13 [(7943c)](https://github.com/soybeanjs/soybean-admin-antd/commit/7943ce2) + - Syncronize user management list page  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/18 [(64be7)](https://github.com/soybeanjs/soybean-admin-antd/commit/64be7d2) + - Synchronous user management  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/19 [(68231)](https://github.com/soybeanjs/soybean-admin-antd/commit/6823194) + - support grayscale  -  by @soybeanjs [(db2a5)](https://github.com/soybeanjs/soybean-admin-antd/commit/db2a5bb) + - add prefix to local storage  -  by @soybeanjs [(0423c)](https://github.com/soybeanjs/soybean-admin-antd/commit/0423cb1) + - support iframe page with diffrent url of custom route  -  by @soybeanjs [(4975d)](https://github.com/soybeanjs/soybean-admin-antd/commit/4975d11) + - add recommend color switch  -  by @soybeanjs [(7fa51)](https://github.com/soybeanjs/soybean-admin-antd/commit/7fa5136) + - support repeated request errors occur once in a short time  -  by @soybeanjs [(6e809)](https://github.com/soybeanjs/soybean-admin-antd/commit/6e80963) + - close tab by mouse wheel button click  -  by @soybeanjs [(31e1d)](https://github.com/soybeanjs/soybean-admin-antd/commit/31e1d4e) + - support system new version update notification  -  by @soybeanjs [(cee03)](https://github.com/soybeanjs/soybean-admin-antd/commit/cee03ed) + - get user info in router guard and remove in localStorage  -  by @soybeanjs [(ccbe3)](https://github.com/soybeanjs/soybean-admin-antd/commit/ccbe39d) + +###    🐞 Bug Fixes + +- **components**: + - 修复主题模式按钮显示与点击的异常  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/21 [(03e09)](https://github.com/soybeanjs/soybean-admin-antd/commit/03e094e) +- **hooks**: + - Fixed abnormal display of table pagers  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/17 [(cc256)](https://github.com/soybeanjs/soybean-admin-antd/commit/cc2562b) +- **projects**: + - fix elegant-router plugin  -  by @soybeanjs [(282b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/282b602) + - keep hsla and rgba consistent with unocss  -  by @soybeanjs [(566cc)](https://github.com/soybeanjs/soybean-admin-antd/commit/566cce2) + - fix menu style  -  by @soybeanjs [(b80a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b80a086) + - update tab label when locale change  -  by @soybeanjs [(50b72)](https://github.com/soybeanjs/soybean-admin-antd/commit/50b722c) + - fix menu style  -  by @soybeanjs [(231fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/231fc8b) + - fix zIndex  -  by @soybeanjs [(eed33)](https://github.com/soybeanjs/soybean-admin-antd/commit/eed33a6) + - fix ThemeButton tooltip trigger  -  by @soybeanjs [(19671)](https://github.com/soybeanjs/soybean-admin-antd/commit/196710d) + - fix menu collapsed  -  by @soybeanjs [(586d6)](https://github.com/soybeanjs/soybean-admin-antd/commit/586d6d7) + - fix siderCollapse  -  by @soybeanjs [(d348b)](https://github.com/soybeanjs/soybean-admin-antd/commit/d348bd8) + - fix tab click when is mobile  -  by @soybeanjs [(ac6c3)](https://github.com/soybeanjs/soybean-admin-antd/commit/ac6c324) + - notification add auto close  -  by @soybeanjs [(2cfcb)](https://github.com/soybeanjs/soybean-admin-antd/commit/2cfcb44) + - hide some content when is mobile layout  -  by @soybeanjs [(b175f)](https://github.com/soybeanjs/soybean-admin-antd/commit/b175fea) + - fix breadcrumb when is not route menu  -  by @soybeanjs [(59d35)](https://github.com/soybeanjs/soybean-admin-antd/commit/59d3511) + - fix button style  -  by @soybeanjs [(93f18)](https://github.com/soybeanjs/soybean-admin-antd/commit/93f1806) + - fix themeVars color  -  by @soybeanjs [(6329c)](https://github.com/soybeanjs/soybean-admin-antd/commit/6329c5d) + - fix cached tabs locale  -  by @soybeanjs [(0973b)](https://github.com/soybeanjs/soybean-admin-antd/commit/0973b08) + - fix inverted menu when is horizontal-mix  -  by @soybeanjs [(1530d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1530dae) + - fix horizontal menu style  -  by @soybeanjs [(b3fce)](https://github.com/soybeanjs/soybean-admin-antd/commit/b3fce71) + - theme setting adapter mobile  -  by @soybeanjs [(8c729)](https://github.com/soybeanjs/soybean-admin-antd/commit/8c72966) + - fix theme colors  -  by @soybeanjs [(ab60e)](https://github.com/soybeanjs/soybean-admin-antd/commit/ab60edc) + - fix customize info color  -  by @soybeanjs [(f0f02)](https://github.com/soybeanjs/soybean-admin-antd/commit/f0f0236) + - fix scrollbar style  -  by @soybeanjs [(cadf2)](https://github.com/soybeanjs/soybean-admin-antd/commit/cadf2e8) + - fix ColorPicker  -  by @soybeanjs [(c735f)](https://github.com/soybeanjs/soybean-admin-antd/commit/c735fd3) + - sider inverted visible  -  by @soybeanjs [(7b46f)](https://github.com/soybeanjs/soybean-admin-antd/commit/7b46f2b) + - fix override theme  -  by @soybeanjs [(76eda)](https://github.com/soybeanjs/soybean-admin-antd/commit/76edab3) + - fix default menu icon  -  by @soybeanjs [(68e0d)](https://github.com/soybeanjs/soybean-admin-antd/commit/68e0d19) + - fix vertical-mix menu when collapse  -  by @soybeanjs [(c4e64)](https://github.com/soybeanjs/soybean-admin-antd/commit/c4e6471) + - fix layout-card  -  by @soybeanjs [(b2b92)](https://github.com/soybeanjs/soybean-admin-antd/commit/b2b9256) + - fix scripts  -  by @soybeanjs [(780eb)](https://github.com/soybeanjs/soybean-admin-antd/commit/780ebf5) + - fix app loading theme color  -  by @soybeanjs [(1ad8d)](https://github.com/soybeanjs/soybean-admin-antd/commit/1ad8dbf) + - fix base-menu style  -  by @soybeanjs [(dcbb3)](https://github.com/soybeanjs/soybean-admin-antd/commit/dcbb302) + - remove space in tab content  -  by @soybeanjs [(16c76)](https://github.com/soybeanjs/soybean-admin-antd/commit/16c765f) + - fix add import $t  -  by @soybeanjs [(2e36f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2e36fbf) + - fix request msg  -  by @soybeanjs [(47b54)](https://github.com/soybeanjs/soybean-admin-antd/commit/47b54b0) + - fix tab error displaying parent localIcon  -  by @soybeanjs [(9d112)](https://github.com/soybeanjs/soybean-admin-antd/commit/9d11258) + - fix build [unocss]: build failed to load icon "close"  -  by @soybeanjs [(6a5aa)](https://github.com/soybeanjs/soybean-admin-antd/commit/6a5aaec) + - fix home when is dynamic mode router  -  by @soybeanjs [(3c229)](https://github.com/soybeanjs/soybean-admin-antd/commit/3c2296e) + - fix homeTab closeRight and disable colseLeft  -  by @soybeanjs [(53f61)](https://github.com/soybeanjs/soybean-admin-antd/commit/53f6166) + - fix GlobalBreadcrumb warning  -  by @soybeanjs [(dd6fc)](https://github.com/soybeanjs/soybean-admin-antd/commit/dd6fce3) + - add maxWidth for GlobalTab to fix bg with gap  -  by @soybeanjs [(423ea)](https://github.com/soybeanjs/soybean-admin-antd/commit/423ea0d) + - fix css var is inserted repeatedly  -  by @soybeanjs [(e58cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/e58cf26) + - fix SvgIcon inheritAttrs warning  -  by @soybeanjs [(f4305)](https://github.com/soybeanjs/soybean-admin-antd/commit/f430584) + - fix event name  -  by @soybeanjs [(642b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/642b6f8) + - fix axios createRequest: add default state  -  by @soybeanjs [(466bc)](https://github.com/soybeanjs/soybean-admin-antd/commit/466bc7a) + - fix type error  -  by @soybeanjs [(77c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/77c2023) + - fix disabled page animate  -  by @soybeanjs [(e6910)](https://github.com/soybeanjs/soybean-admin-antd/commit/e691088) + - fix routes data when role is change  -  by @soybeanjs [(03c80)](https://github.com/soybeanjs/soybean-admin-antd/commit/03c8075) + - fix tabs data when role is change  -  by @soybeanjs [(9fd89)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fd89aa) + - add missing `$t` import  -  by @soybeanjs [(8f9ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f9ee2e) + - add responseType judgment  -  by @soybeanjs [(2246f)](https://github.com/soybeanjs/soybean-admin-antd/commit/2246f78) + - fix mix-menu blank & cache mixMenuFixed  -  by @soybeanjs [(9fdb6)](https://github.com/soybeanjs/soybean-admin-antd/commit/9fdb6c1) + - fix PinToggler label  -  by @soybeanjs [(b1f9c)](https://github.com/soybeanjs/soybean-admin-antd/commit/b1f9c4c) + - recovery the layout config before is mobile  -  by @soybeanjs [(851ae)](https://github.com/soybeanjs/soybean-admin-antd/commit/851ae38) + - fix manage page drawer operate about data reset  -  by @soybeanjs [(91dfa)](https://github.com/soybeanjs/soybean-admin-antd/commit/91dfa57) + - fix menu data when role is changed  -  by @soybeanjs [(7cc5f)](https://github.com/soybeanjs/soybean-admin-antd/commit/7cc5f9c) + - fix useRouter in tab store  -  by @soybeanjs [(962c4)](https://github.com/soybeanjs/soybean-admin-antd/commit/962c403) + - fix header style & fix button highlight when click global-tab  -  by @soybeanjs [(f2983)](https://github.com/soybeanjs/soybean-admin-antd/commit/f298388) + - fix multi tab page only render once  -  by @soybeanjs [(b98b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/b98b075) + - fix login Register component name  -  by @soybeanjs [(a3ba5)](https://github.com/soybeanjs/soybean-admin-antd/commit/a3ba516) +- **styles**: + - fix FirstLevelMenu style  -  by @soybeanjs [(5df82)](https://github.com/soybeanjs/soybean-admin-antd/commit/5df82d1) + - fix PinToggler style  -  by @soybeanjs [(593ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/593ceea) +- **view-manage-role**: + - fix PopConfirm content to title  -  by @zyhnbyyds [(d95bd)](https://github.com/soybeanjs/soybean-admin-antd/commit/d95bd84) + +###    🔥 Performance + +- **projects**: + - remove system logo fill  -  by @soybeanjs [(e02d0)](https://github.com/soybeanjs/soybean-admin-antd/commit/e02d025) + - perf code  -  by @soybeanjs [(c9e34)](https://github.com/soybeanjs/soybean-admin-antd/commit/c9e34f6) + - remove as any  -  by @soybeanjs [(7f61b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f61bdc) + - perf code  -  by @soybeanjs [(3f22e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3f22efa) + - perf code  -  by @soybeanjs [(cb369)](https://github.com/soybeanjs/soybean-admin-antd/commit/cb3694c) + - perf css of base-menu  -  by @soybeanjs [(4046a)](https://github.com/soybeanjs/soybean-admin-antd/commit/4046a8b) + - perf theme store  -  by @soybeanjs [(b0d95)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0d95f1) + - perf code  -  by @soybeanjs [(324cf)](https://github.com/soybeanjs/soybean-admin-antd/commit/324cffd) + - perf code  -  by @soybeanjs [(c2aae)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2aaea9) + - env config  -  by @soybeanjs [(07423)](https://github.com/soybeanjs/soybean-admin-antd/commit/0742326) + - add detailed annotations for route role  -  by @soybeanjs [(2a0ec)](https://github.com/soybeanjs/soybean-admin-antd/commit/2a0ec38) + - remove useless file  -  by @soybeanjs [(da280)](https://github.com/soybeanjs/soybean-admin-antd/commit/da28076) + - perf card style  -  by @soybeanjs [(9895a)](https://github.com/soybeanjs/soybean-admin-antd/commit/9895a37) + - echarts loading style  -  by @soybeanjs [(dca53)](https://github.com/soybeanjs/soybean-admin-antd/commit/dca53b0) + - perf code  -  by @soybeanjs [(8b960)](https://github.com/soybeanjs/soybean-admin-antd/commit/8b9607f) + - remove useless code  -  by @soybeanjs [(3115e)](https://github.com/soybeanjs/soybean-admin-antd/commit/3115ef4) + - perf code  -  by @soybeanjs [(a1220)](https://github.com/soybeanjs/soybean-admin-antd/commit/a122088) + - perf judgement the fixed tab  -  by @soybeanjs [(90c20)](https://github.com/soybeanjs/soybean-admin-antd/commit/90c205d) + +###    🛠 Optimizations + +- **components**: + - ButtonIcon with smarter class merging and tippy  -  by @mufeng889 [(95960)](https://github.com/soybeanjs/soybean-admin-antd/commit/95960b0) + - accuracy draggable area for TableColumnSetting with animation  -  by @soybeanjs [(8a2e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/8a2e0eb) +- **projects**: + - optimize manage_menu  -  by @soybeanjs [(bf406)](https://github.com/soybeanjs/soybean-admin-antd/commit/bf40642) + - remove deprecated code  -  by @soybeanjs [(00361)](https://github.com/soybeanjs/soybean-admin-antd/commit/0036172) + - unocss border shortcut  -  by @soybeanjs [(4ebeb)](https://github.com/soybeanjs/soybean-admin-antd/commit/4ebeb90) + +###    💅 Refactors + +- **hooks**: + - deleting the route export of useRoutePush, use vue-router  -  by @soybeanjs [(b81f7)](https://github.com/soybeanjs/soybean-admin-antd/commit/b81f749) + - refactor @sa/color-palette to @sa/color  -  by @soybeanjs [(fda42)](https://github.com/soybeanjs/soybean-admin-antd/commit/fda42d6) +- **projects**: + - perf code  -  by @soybeanjs [(0b2e0)](https://github.com/soybeanjs/soybean-admin-antd/commit/0b2e046) + - init route store in router guide  -  by @soybeanjs [(bc056)](https://github.com/soybeanjs/soybean-admin-antd/commit/bc056de) + - remove requiresAuth option of route meta  -  by @soybeanjs [(5a137)](https://github.com/soybeanjs/soybean-admin-antd/commit/5a13749) + - fix tooltop of ButtonIcon  -  by @soybeanjs [(a5b16)](https://github.com/soybeanjs/soybean-admin-antd/commit/a5b1666) + - useStore variable name  -  by @soybeanjs [(29291)](https://github.com/soybeanjs/soybean-admin-antd/commit/2929177) + - add createRoutes replace export routes directly  -  by @soybeanjs [(16bca)](https://github.com/soybeanjs/soybean-admin-antd/commit/16bca45) + - refactor ColorPicker  -  by @soybeanjs [(f80c1)](https://github.com/soybeanjs/soybean-admin-antd/commit/f80c1ae) + - themeStore: isCustomizeInfoColor to isInfoFollowPrimary  -  by @soybeanjs [(0867f)](https://github.com/soybeanjs/soybean-admin-antd/commit/0867f4b) + - rename zh-cn locale  -  by @soybeanjs [(ba10c)](https://github.com/soybeanjs/soybean-admin-antd/commit/ba10c3f) + - rename zh-cn locale  -  by @soybeanjs [(26714)](https://github.com/soybeanjs/soybean-admin-antd/commit/26714e9) + - split @sa/request to @sa/axios, @sa/fetch  -  by @soybeanjs [(9ecb5)](https://github.com/soybeanjs/soybean-admin-antd/commit/9ecb516) + - remove @sa/eslint-config  -  by @soybeanjs [(23002)](https://github.com/soybeanjs/soybean-admin-antd/commit/230027c) + - remove docs to soybean-admin-docs  -  by @soybeanjs [(be008)](https://github.com/soybeanjs/soybean-admin-antd/commit/be0087c) + - refactor app-loading  -  by @soybeanjs [(c3c14)](https://github.com/soybeanjs/soybean-admin-antd/commit/c3c143b) + - login components => modules  -  by @soybeanjs [(49237)](https://github.com/soybeanjs/soybean-admin-antd/commit/4923781) + - keep directory "locales/langs" same with version naive-ui  -  by @soybeanjs [(5ecf3)](https://github.com/soybeanjs/soybean-admin-antd/commit/5ecf384) + - refactor service env config  -  by @soybeanjs [(d89ee)](https://github.com/soybeanjs/soybean-admin-antd/commit/d89ee4f) + - refactor unocss shortcuts: wh-full => size-full  -  by @soybeanjs [(835cb)](https://github.com/soybeanjs/soybean-admin-antd/commit/835cb4f) + - use enquirer replace prompts  -  by @soybeanjs [(64b27)](https://github.com/soybeanjs/soybean-admin-antd/commit/64b272c) + - perf code  -  by @soybeanjs [(81f08)](https://github.com/soybeanjs/soybean-admin-antd/commit/81f08f6) + - constant routes, route guard  -  by @soybeanjs [(ddec7)](https://github.com/soybeanjs/soybean-admin-antd/commit/ddec7d8) + - useMixMenuContext replace useMixMenu  -  by @soybeanjs [(e0aa7)](https://github.com/soybeanjs/soybean-admin-antd/commit/e0aa752) + - Soybean Admin to SoybeanAdmin  -  by @soybeanjs [(9427d)](https://github.com/soybeanjs/soybean-admin-antd/commit/9427d07) +- **styles**: + - sort defineProps, defineEmits with TS type  -  by @soybeanjs [(37a64)](https://github.com/soybeanjs/soybean-admin-antd/commit/37a64a5) + +###    📖 Documentation + +- **projects**: + - add README  -  by @soybeanjs [(67fbf)](https://github.com/soybeanjs/soybean-admin-antd/commit/67fbfc7) + - update README.md  -  by @soybeanjs [(3b31b)](https://github.com/soybeanjs/soybean-admin-antd/commit/3b31b19) + - update README.md  -  by @soybeanjs [(43743)](https://github.com/soybeanjs/soybean-admin-antd/commit/43743a0) + - update README.md  -  by @soybeanjs [(d71b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/d71b6ed) + - update README.md  -  by @soybeanjs [(427a0)](https://github.com/soybeanjs/soybean-admin-antd/commit/427a0a5) + - update README  -  by @soybeanjs [(4045e)](https://github.com/soybeanjs/soybean-admin-antd/commit/4045e41) + - add CHANGELOG  -  by @soybeanjs [(01fbb)](https://github.com/soybeanjs/soybean-admin-antd/commit/01fbbac) + +###    🏡 Chore + +- **deps**: + - update deps  -  by @soybeanjs [(4caa4)](https://github.com/soybeanjs/soybean-admin-antd/commit/4caa45d) + - update deps  -  by @soybeanjs [(bd3ef)](https://github.com/soybeanjs/soybean-admin-antd/commit/bd3efe6) + - update deps  -  by @soybeanjs [(56931)](https://github.com/soybeanjs/soybean-admin-antd/commit/56931a2) + - update deps  -  by @soybeanjs [(56e7d)](https://github.com/soybeanjs/soybean-admin-antd/commit/56e7dc3) + - update deps  -  by @soybeanjs [(892e2)](https://github.com/soybeanjs/soybean-admin-antd/commit/892e2d6) + - updtae deps  -  by @soybeanjs [(7088d)](https://github.com/soybeanjs/soybean-admin-antd/commit/7088ddc) + - update deps  -  by @soybeanjs [(b0b48)](https://github.com/soybeanjs/soybean-admin-antd/commit/b0b4830) + - update deps  -  by @soybeanjs [(7f049)](https://github.com/soybeanjs/soybean-admin-antd/commit/7f049ba) + - update deps  -  by @soybeanjs [(854ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/854ce36) + - update deps  -  by @soybeanjs [(82ccf)](https://github.com/soybeanjs/soybean-admin-antd/commit/82ccfbc) + - update deps  -  by @soybeanjs [(b0546)](https://github.com/soybeanjs/soybean-admin-antd/commit/b054661) + - update deps  -  by @soybeanjs [(adc36)](https://github.com/soybeanjs/soybean-admin-antd/commit/adc3656) + - update deps  -  by @soybeanjs [(c655a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c655a24) + - update deps  -  by @soybeanjs [(345b6)](https://github.com/soybeanjs/soybean-admin-antd/commit/345b687) + - update deps  -  by @soybeanjs [(70962)](https://github.com/soybeanjs/soybean-admin-antd/commit/70962f5) + - update deps  -  by @soybeanjs [(2d4d1)](https://github.com/soybeanjs/soybean-admin-antd/commit/2d4d107) + - update deps  -  by @soybeanjs [(9e493)](https://github.com/soybeanjs/soybean-admin-antd/commit/9e493e5) + - update deps  -  by @soybeanjs [(eba20)](https://github.com/soybeanjs/soybean-admin-antd/commit/eba2014) + - update deps  -  by @soybeanjs [(909ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/909ceb8) +- **other**: + - correct spell mistake  -  by @soybeanjs [(308bf)](https://github.com/soybeanjs/soybean-admin-antd/commit/308bff6) +- **projects**: + - rename project  -  by @soybeanjs [(5dfe9)](https://github.com/soybeanjs/soybean-admin-antd/commit/5dfe968) + - update version and perf code  -  by @soybeanjs [(97035)](https://github.com/soybeanjs/soybean-admin-antd/commit/970352c) + - fix pkg version  -  by @soybeanjs [(4b375)](https://github.com/soybeanjs/soybean-admin-antd/commit/4b37577) + - add sourcemap  -  by @soybeanjs [(d25ed)](https://github.com/soybeanjs/soybean-admin-antd/commit/d25ed44) + - add pnpm-lock  -  by @soybeanjs [(0e4cb)](https://github.com/soybeanjs/soybean-admin-antd/commit/0e4cbd9) + - update deps and perf code  -  by @soybeanjs [(19c12)](https://github.com/soybeanjs/soybean-admin-antd/commit/19c1200) + - update gitignore  -  by @soybeanjs [(910fe)](https://github.com/soybeanjs/soybean-admin-antd/commit/910fe4e) + - update pnpm-lock  -  by @soybeanjs [(1d0b0)](https://github.com/soybeanjs/soybean-admin-antd/commit/1d0b061) + - update vscode settings  -  by @soybeanjs [(c2b6a)](https://github.com/soybeanjs/soybean-admin-antd/commit/c2b6aa6) + - use eslint flat config  -  by @soybeanjs [(11adc)](https://github.com/soybeanjs/soybean-admin-antd/commit/11adc8c) + - add config files  -  by @soybeanjs [(87aa0)](https://github.com/soybeanjs/soybean-admin-antd/commit/87aa069) + - update deps & update @sa/scripts config  -  by @soybeanjs [(31f67)](https://github.com/soybeanjs/soybean-admin-antd/commit/31f676a) + - update pnpm version  -  by @soybeanjs [(47819)](https://github.com/soybeanjs/soybean-admin-antd/commit/478194d) + - create LICENSE  -  by @soybeanjs [(853f5)](https://github.com/soybeanjs/soybean-admin-antd/commit/853f5c1) + - update pnpm version  -  by @soybeanjs [(91121)](https://github.com/soybeanjs/soybean-admin-antd/commit/9112193) + - update eslint config  -  by @soybeanjs [(7029b)](https://github.com/soybeanjs/soybean-admin-antd/commit/7029b49) + - lock deps version  -  by @soybeanjs [(8ff39)](https://github.com/soybeanjs/soybean-admin-antd/commit/8ff398f) + - remove @soybeanjs/cli  -  by @soybeanjs [(02c05)](https://github.com/soybeanjs/soybean-admin-antd/commit/02c0539) + - update pnpm version  -  by @soybeanjs [(c6b00)](https://github.com/soybeanjs/soybean-admin-antd/commit/c6b00bb) + - update mock api  -  by @soybeanjs [(c0079)](https://github.com/soybeanjs/soybean-admin-antd/commit/c007935) + - update pnpm version  -  by @soybeanjs [(88f26)](https://github.com/soybeanjs/soybean-admin-antd/commit/88f2641) + - update repository url  -  by @soybeanjs [(f46ce)](https://github.com/soybeanjs/soybean-admin-antd/commit/f46ce2a) + - update vscode config  -  by @soybeanjs [(bfaec)](https://github.com/soybeanjs/soybean-admin-antd/commit/bfaecce) + - update component.d.ts  -  by @soybeanjs [(1bebf)](https://github.com/soybeanjs/soybean-admin-antd/commit/1bebf8b) + - add unocss eslint config  -  by @soybeanjs [(6f004)](https://github.com/soybeanjs/soybean-admin-antd/commit/6f004ce) + - update .gitattributes  -  by @soybeanjs [(e5235)](https://github.com/soybeanjs/soybean-admin-antd/commit/e5235e0) + - update pnpm version  -  by @soybeanjs [(30c97)](https://github.com/soybeanjs/soybean-admin-antd/commit/30c9729) + - disabled unocss eslint rule: order-attributify  -  by @soybeanjs [(87838)](https://github.com/soybeanjs/soybean-admin-antd/commit/8783804) + - update pnpm-lock.yaml  -  by @soybeanjs [(8f5a6)](https://github.com/soybeanjs/soybean-admin-antd/commit/8f5a6b1) + - update deps & update pnpm version  -  by @soybeanjs [(5260d)](https://github.com/soybeanjs/soybean-admin-antd/commit/5260d67) + - update mock url  -  by @Azir-11 in https://github.com/soybeanjs/soybean-admin-antd/issues/22 [(32c00)](https://github.com/soybeanjs/soybean-admin-antd/commit/32c006a) + - update deps & add lock file  -  by @soybeanjs [(e1777)](https://github.com/soybeanjs/soybean-admin-antd/commit/e1777b4) + - synchronize recent changes  -  by @mufeng889 in https://github.com/soybeanjs/soybean-admin-antd/issues/23 [(d5348)](https://github.com/soybeanjs/soybean-admin-antd/commit/d53487b) + - update eslint config  -  by @soybeanjs [(9c450)](https://github.com/soybeanjs/soybean-admin-antd/commit/9c45009) + - update .npmrc  -  by @soybeanjs [(5d15b)](https://github.com/soybeanjs/soybean-admin-antd/commit/5d15bda) + - update vscode settings  -  by @soybeanjs [(e77bd)](https://github.com/soybeanjs/soybean-admin-antd/commit/e77bda1) + +###    🎨 Styles + +- **projects**: + - fix menu style  -  by @soybeanjs [(d8b9b)](https://github.com/soybeanjs/soybean-admin-antd/commit/d8b9b94) + - perf layout card style  -  by @soybeanjs [(fc409)](https://github.com/soybeanjs/soybean-admin-antd/commit/fc409db) + - fix event style  -  by @soybeanjs [(e935f)](https://github.com/soybeanjs/soybean-admin-antd/commit/e935f77) + +###    ❤️ Contributors + +[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)  [![mufeng889](https://github.com/mufeng889.png?size=48)](https://github.com/mufeng889)  [![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)  [![zyhnbyyds](https://github.com/zyhnbyyds.png?size=48)](https://github.com/zyhnbyyds)   + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20547de --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Soybean + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.en_US.md b/README.en_US.md new file mode 100644 index 0000000..b484956 --- /dev/null +++ b/README.en_US.md @@ -0,0 +1,187 @@ +
+ +

SoybeanAdmin AntDesign

+ 中文 | English +
+ +--- + +[![license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) +[![github stars](https://img.shields.io/github/stars/soybeanjs/soybean-admin-antd)](https://github.com/soybeanjs/soybean-admin-antd) +[![github forks](https://img.shields.io/github/forks/soybeanjs/soybean-admin-antd)](https://github.com/soybeanjs/soybean-admin-antd) +[![gitee stars](https://gitee.com/honghuangdc/soybean-admin-antd/badge/star.svg)](https://gitee.com/honghuangdc/soybean-admin-antd) +[![gitcode star](https://gitcode.com/soybeanjs/soybean-admin-antd/star/badge.svg)](https://gitcode.com/soybeanjs/soybean-admin-antd) + +Featured|HelloGitHub + +> [!NOTE] +> If you think `SoybeanAdmin` is helpful to you, or you like our project, please give us a ⭐️ on GitHub. Your support is the driving force for us to continue to improve and add new features! Thank you for your support! + +## Introduction + +[`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) is a clean, elegant, beautiful and powerful admin template, based on the latest front-end technology stack, including Vue3, Vite5, TypeScript, Pinia and UnoCSS. It has built-in rich theme configuration and components, strict code specifications, and an automated file routing system. In addition, it also uses the online mock data solution based on ApiFox. `SoybeanAdmin` provides you with a one-stop admin solution, no additional configuration, and out of the box. It is also a best practice for learning cutting-edge technologies quickly. + + +## Features + +- **Cutting-edge technology application**: using the latest popular technology stack such as Vue3, Vite5, TypeScript, Pinia and UnoCSS. +- **Clear project architecture**: using pnpm monorepo architecture, clear structure, elegant and easy to understand. +- **Strict code specifications**: follow the [SoybeanJS specification](https://docs.soybeanjs.cn/standard), integrate eslint, prettier and simple-git-hooks to ensure the code is standardized. +- **TypeScript**: support strict type checking to improve code maintainability. +- **Rich theme configuration**: built-in a variety of theme configurations, perfectly integrated with UnoCSS. +- **Built-in internationalization solution**: easily realize multi-language support. +- **Automated file routing system**: automatically generate route import, declaration and type. For more details, please refer to [Elegant Router](https://github.com/soybeanjs/elegant-router). +- **Flexible permission routing**: support both front-end static routing and back-end dynamic routing. +- **Rich page components**: built-in a variety of pages and components, including 403, 404, 500 pages, as well as layout components, tag components, theme configuration components, etc. +- **Command line tool**: built-in efficient command line tool, git commit, delete file, release, etc. +- **Mobile adaptation**: perfectly support mobile terminal to realize adaptive layout. + + +## Version + +- **NaiveUI Version:** + - [Preview Link](https://naive.soybeanjs.cn/) + - [Github Repository](https://github.com/soybeanjs/soybean-admin) + - [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin) + +- **AntDesignVue Version:** + - [Preview Link](https://antd.soybeanjs.cn/) + - [Github Repository](https://github.com/soybeanjs/soybean-admin-antd) + - [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin-antd) + +- **ElementPlus Version:** + - [Preview Link](https://elp.soybeanjs.cn/) + - [Github Repository](https://github.com/soybeanjs/soybean-admin-element-plus) + +- **Legacy Version:** + - [Preview Link](https://legacy.soybeanjs.cn/) + - [Github Repository](https://github.com/soybeanjs/soybean-admin/tree/legacy) + + +## Documentation + +- [Link](https://docs.soybeanjs.cn) +- [Legacy Docs](https://legacy-docs.soybeanjs.cn) + +## Example Images + +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-01.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-02.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-03.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-04.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-05.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-06.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-07.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-08.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-09.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png) + + +## Usage + +**Environment Preparation** + +Make sure your environment meets the following requirements: + +- **git**: you need git to clone and manage project versions. +- **NodeJS**: >=18.12.0, recommended 18.19.0 or higher. +- **pnpm**: >= 8.7.0, recommended 8.14.0 or higher. + +**Clone Project** + +```bash +git clone https://github.com/soybeanjs/soybean-admin.git +``` + +**Install Dependencies** + +```bash +pnpm i +``` +> Since this project uses the pnpm monorepo management method, please do not use npm or yarn to install dependencies. + +**Start Project** + +```bash +pnpm dev +``` + +**Build Project** + +```bash +pnpm build +``` + +**Code Synchronization** + +Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) document. + +## Ecosystem + +- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): A Mock Api management system that helps front-end developers quickly implement interface mocks. +- [T-Shell](https://github.com/TheBlindM/T-Shell): A terminal emulator and SSH client with configurable command prompts. +- [pea](https://github.com/haitang1894/pea) : Adopting SpringBoot3.2 + JDK21, MyBatis-Plus, SpringSecurity security framework, etc., suitable for the simple permission system developed by [soybean-admin](https://gitee.com/honghuangdc/soybean-admin). +- [MalusAdmin](https://github.com/pridejoy/MalusAdmin): A backend management framework developed based on Vue3/TypeScript/NaiveUI and NET7 & Sqlsugar. It is implemented in the most original and simplest way, with a fresh and elegant front-end, a clear and elegant backend structure, and powerful functions. +- [PanisAdmin](https://github.com/paynezhuang/panis-admin): Adopting SpringBoot 3, SaToken, MySQL and other frameworks to develop and modify [soybean-admin](https://github.com/soybeanjs/soybean-admin) for the second time, adapting dynamic menu/button-level authorization. Retaining the original flavor, fresh and elegant, high-value back-end management system scaffold. +- [snail-job](https://github.com/aizuda/snail-job): A distributed task retry and task scheduling platform with "high performance, high value and high activity". +- [SuperApi](https://github.com/TmmTop/SuperApi): Quickly turn your idea into an online stable product! Entity-less library and table building, add, delete, change and check entity-less library table, support 15 kinds of condition query, as well as paging, list, unlimited tree list and other functions of the API deployment! With interface documentation, Auth authorisation, interface flow restriction, access to the client's real IP, advanced server caching components, dynamic APIs and other features, we look forward to your experience! +- [FastSoyAdmin](https://github.com/sleep1223/fast-soy-admin): A modern Management Platform based on FastAPI+Vue3+Naive UI. + + +## How to Contribute + +We warmly welcome and appreciate all forms of contributions. If you have any ideas or suggestions, please feel free to share them by submitting [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) or creating GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new). + +## Git Commit Guidelines + +This project has built-in `commit` command, you can execute `pnpm commit` to generate commit information that conforms to [Conventional Commits](https://www.conventionalcommits.org/) specification. When submitting PR, please be sure to use `commit` command to create commit information to ensure the standardization of information. + +## Browser Support + +It is recommended to use the latest version of Chrome in development for a better experience. + +| [IE](http://godban.github.io/browsers-support-badges/) | [ Edge](http://godban.github.io/browsers-support-badges/) | [Firefox](http://godban.github.io/browsers-support-badges/) | [Chrome](http://godban.github.io/browsers-support-badges/) | [Safari](http://godban.github.io/browsers-support-badges/) | +| --- | --- | --- | --- | --- | +| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | + +## OpenSource Author + +[Soybean](https://github.com/honghuangdc) + +## Contributors + +Thanks the following people for their contributions. If you want to contribute to this project, please refer to [How to Contribute](#how-to-contribute). + + + + + +## Communication + +`SoybeanAdmin` is a completely open source and free project, helping developers to develop medium and large-scale management systems more conveniently. It also provides WeChat and QQ communication groups. If you have any questions, please feel free to ask in the group. + +
+

QQ Group

+ +
+ +
+

Add the following WeChat to invite to the WeChat group

+ +
+
+

Add Soybean's WeChat for business consultation, cooperation, project architecture, one-on-one guidance, etc.

+ +
+ +## Star Trend + +[![Star History Chart](https://api.star-history.com/svg?repos=soybeanjs/soybean-admin&type=Date)](https://star-history.com/#soybeanjs/soybean-admin&Date) + +## License + +This project is based on the [MIT © 2021 Soybean](./LICENSE) protocol, for learning purposes only, please retain the author's copyright information for commercial use, the author does not guarantee and is not responsible for the software. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9e9d94a --- /dev/null +++ b/README.md @@ -0,0 +1,185 @@ +
+ +

SoybeanAdmin AntDesign

+ 中文 | English +
+ +--- + +[![license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) +[![github stars](https://img.shields.io/github/stars/soybeanjs/soybean-admin-antd)](https://github.com/soybeanjs/soybean-admin-antd) +[![github forks](https://img.shields.io/github/forks/soybeanjs/soybean-admin-antd)](https://github.com/soybeanjs/soybean-admin-antd) +[![gitee stars](https://gitee.com/honghuangdc/soybean-admin-antd/badge/star.svg)](https://gitee.com/honghuangdc/soybean-admin-antd) +[![gitcode star](https://gitcode.com/soybeanjs/soybean-admin-antd/star/badge.svg)](https://gitcode.com/soybeanjs/soybean-admin-antd) + +Featured|HelloGitHub + +> [!NOTE] +> 如果您觉得 `SoybeanAdmin`对您有所帮助,或者您喜欢我们的项目,请在 GitHub 上给我们一个 ⭐️。您的支持是我们持续改进和增加新功能的动力!感谢您的支持! + +## 简介 + +[`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) 是一个清新优雅、高颜值且功能强大的后台管理模板,基于最新的前端技术栈,包括 Vue3, Vite5, TypeScript, Pinia 和 UnoCSS。它内置了丰富的主题配置和组件,代码规范严谨,实现了自动化的文件路由系统。此外,它还采用了基于 ApiFox 的在线Mock数据方案。`SoybeanAdmin` 为您提供了一站式的后台管理解决方案,无需额外配置,开箱即用。同样是一个快速学习前沿技术的最佳实践。 + +## 特性 + +- **前沿技术应用**:采用 Vue3, Vite5, TypeScript, Pinia 和 UnoCSS 等最新流行的技术栈。 +- **清晰的项目架构**:采用 pnpm monorepo 架构,结构清晰,优雅易懂。 +- **严格的代码规范**:遵循 [SoybeanJS 规范](https://docs.soybeanjs.cn/zh/standard),集成了eslint, prettier 和 simple-git-hooks,保证代码的规范性。 +- **TypeScript**: 支持严格的类型检查,提高代码的可维护性。 +- **丰富的主题配置**:内置多样的主题配置,与 UnoCSS 完美结合。 +- **内置国际化方案**:轻松实现多语言支持。 +- **自动化文件路由系统**:自动生成路由导入、声明和类型。更多细节请查看 [Elegant Router](https://github.com/soybeanjs/elegant-router)。 +- **灵活的权限路由**:同时支持前端静态路由和后端动态路由。 +- **丰富的页面组件**:内置多样页面和组件,包括403、404、500页面,以及布局组件、标签组件、主题配置组件等。 +- **命令行工具**:内置高效的命令行工具,git提交、删除文件、发布等。 +- **移动端适配**:完美支持移动端,实现自适应布局。 + + +## 版本 + +- **NaiveUI 版本:** + - [预览地址](https://naive.soybeanjs.cn/) + - [Github 仓库](https://github.com/soybeanjs/soybean-admin) + - [Gitee 仓库](https://gitee.com/honghuangdc/soybean-admin) +- **AntDesignVue 版本:** + - [预览地址](https://antd.soybeanjs.cn/) + - [Github 仓库](https://github.com/soybeanjs/soybean-admin-antd) + - [Gitee 仓库](https://gitee.com/honghuangdc/soybean-admin-antd) +- **ElementPlus 版本:** + - [预览地址](https://elp.soybeanjs.cn/) + - [Github 仓库](https://github.com/soybeanjs/soybean-admin-element-plus) +- **旧版:** + - [预览地址](https://legacy.soybeanjs.cn/) + - [Github 仓库](https://github.com/soybeanjs/soybean-admin/tree/legacy) + + +## 文档 + +- [地址](https://docs.soybeanjs.cn) +- [旧版文档](https://legacy-docs.soybeanjs.cn) + +## 示例图片 + +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-01.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-02.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-03.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-04.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-05.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-06.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-07.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-08.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-09.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png) +![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png) + + +## 使用 + +**环境准备** + +确保你的环境满足以下要求: + +- **git**: 你需要git来克隆和管理项目版本。 +- **NodeJS**: >=18.12.0,推荐 18.19.0 或更高。 +- **pnpm**: >= 8.7.0,推荐 8.14.0 或更高。 + +**克隆项目** + +```bash +git clone https://github.com/soybeanjs/soybean-admin.git +``` + +**安装依赖** + +```bash +pnpm i +``` +> 由于本项目采用了 pnpm monorepo 的管理方式,因此请不要使用 npm 或 yarn 来安装依赖。 + +**启动项目** + +```bash +pnpm dev +``` + +**构建项目** + +```bash +pnpm build +``` + +**代码同步** + +参考 [代码同步](https://docs.soybeanjs.cn/zh/guide/sync) 文档。 + +## 周边生态 + +- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的 mock。 +- [T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH 客户端。 +- [pea](https://github.com/haitang1894/pea) : 采用SpringBoot3.2 + JDK21、MyBatis-Plus、SpringSecurity安全框架等,适配 [soybean-admin](https://gitee.com/honghuangdc/soybean-admin) 开发的简单权限系统。 +- [MalusAdmin](https://github.com/pridejoy/MalusAdmin): 基于 Vue3/TypeScript/NaiveUI 和 NET7 & Sqlsugar 开发的后台管理框架。采用最原生最简洁的方式来实现, 前端清新优雅高颜值,后端 结构清晰,优雅易懂,功能强大。 +- [PanisAdmin](https://github.com/paynezhuang/panis-admin): 采用SpringBoot3、SaToken、MySQL等框架开发,二次修改 [soybean-admin](https://github.com/soybeanjs/soybean-admin),适配动态菜单/按钮级别的鉴权,保留原汁原味、清新优雅、高颜值的后台管理系统脚手架。 +- [snail-job](https://github.com/aizuda/snail-job): 一款兼具 “高性能、高颜值、高活跃” 的分布式任务重试和分布式任务调度平台。 +- [SuperApi](https://github.com/TmmTop/SuperApi): 快速将你的 idea 变成线上稳定运行的产品! 无实体建库建表,对无实体库表进行增删改查,支持 15 种条件查询,以及分页,列表,无限级树形列表 等功能的 API 部署! 拥有接口文档,Auth 授权,接口限流,获取客户端真实 IP,先进的服务器缓存组件,动态 API 等功能,期待您的体验! +- [FastSoyAdmin](https://github.com/sleep1223/fast-soy-admin): 基于 FastAPI+Vue3+Naive UI 的现代化轻量管理平台. + + +## 如何贡献 + +我们热烈欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) 或创建 GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new) 来分享。 + +## Git 提交规范 + +本项目已内置 `commit` 命令,您可以通过执行 `pnpm commit` 来生成符合 [Conventional Commits]([conventionalcommits](https://www.conventionalcommits.org/)) 规范的提交信息。在提交PR时,请务必使用 `commit` 命令来创建提交信息,以确保信息的规范性。 + + +## 浏览器支持 + +推荐使用最新版的 Chrome 浏览器进行开发,以获得更好的体验。 + +| [IE](http://godban.github.io/browsers-support-badges/) | [ Edge](http://godban.github.io/browsers-support-badges/) | [Firefox](http://godban.github.io/browsers-support-badges/) | [Chrome](http://godban.github.io/browsers-support-badges/) | [Safari](http://godban.github.io/browsers-support-badges/) | +| --- | --- | --- | --- | --- | +| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | + +## 开源作者 + +[Soybean](https://github.com/honghuangdc) + + +## 贡献者 + +感谢以下贡献者的贡献。如果您想为本项目做出贡献,请参考 [如何贡献](#如何贡献)。 + + + + + +## 交流 + +`SoybeanAdmin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。 + +
+

QQ交流群

+ +
+ +
+

添加下面微信邀请进微信群

+ +
+
+

添加 Soybean 的微信,业务咨询、合作、项目架构、一对一指导等

+ +
+ +## Star 趋势 + +[![Star History Chart](https://api.star-history.com/svg?repos=soybeanjs/soybean-admin&type=Date)](https://star-history.com/#soybeanjs/soybean-admin&Date) + +## 开源协议 + +项目基于 [MIT © 2021 Soybean](./LICENSE) 协议,仅供学习参考,商业使用请保留作者版权信息,作者不保证也不承担任何软件的使用风险。 diff --git a/build/config/index.ts b/build/config/index.ts new file mode 100644 index 0000000..8a9621a --- /dev/null +++ b/build/config/index.ts @@ -0,0 +1,2 @@ +export * from './proxy'; +export * from './time'; diff --git a/build/config/proxy.ts b/build/config/proxy.ts new file mode 100644 index 0000000..548ea4e --- /dev/null +++ b/build/config/proxy.ts @@ -0,0 +1,36 @@ +import type { ProxyOptions } from 'vite'; +import { createServiceConfig } from '../../src/utils/service'; + +/** + * Set http proxy + * + * @param env - The current env + * @param enable - If enable http proxy + */ +export function createViteProxy(env: Env.ImportMeta, enable: boolean) { + const isEnableHttpProxy = enable && env.VITE_HTTP_PROXY === 'Y'; + + if (!isEnableHttpProxy) return undefined; + + const { baseURL, proxyPattern, other } = createServiceConfig(env); + + const proxy: Record = createProxyItem({ baseURL, proxyPattern }); + + other.forEach(item => { + Object.assign(proxy, createProxyItem(item)); + }); + + return proxy; +} + +function createProxyItem(item: App.Service.ServiceConfigItem) { + const proxy: Record = {}; + + proxy[item.proxyPattern] = { + target: item.baseURL, + changeOrigin: true, + rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '') + }; + + return proxy; +} diff --git a/build/config/time.ts b/build/config/time.ts new file mode 100644 index 0000000..3b57146 --- /dev/null +++ b/build/config/time.ts @@ -0,0 +1,12 @@ +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; + +export function getBuildTime() { + dayjs.extend(utc); + dayjs.extend(timezone); + + const buildTime = dayjs.tz(Date.now(), 'Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'); + + return buildTime; +} diff --git a/build/plugins/html.ts b/build/plugins/html.ts new file mode 100644 index 0000000..b94d24f --- /dev/null +++ b/build/plugins/html.ts @@ -0,0 +1,13 @@ +import type { Plugin } from 'vite'; + +export function setupHtmlPlugin(buildTime: string) { + const plugin: Plugin = { + name: 'html-plugin', + apply: 'build', + transformIndexHtml(html) { + return html.replace('', `\n `); + } + }; + + return plugin; +} diff --git a/build/plugins/index.ts b/build/plugins/index.ts new file mode 100644 index 0000000..52c7275 --- /dev/null +++ b/build/plugins/index.ts @@ -0,0 +1,24 @@ +import type { PluginOption } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import VueDevtools from 'vite-plugin-vue-devtools'; +import progress from 'vite-plugin-progress'; +import { setupElegantRouter } from './router'; +import { setupUnocss } from './unocss'; +import { setupUnplugin } from './unplugin'; +import { setupHtmlPlugin } from './html'; + +export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) { + const plugins: PluginOption = [ + vue(), + vueJsx(), + VueDevtools(), + setupElegantRouter(), + setupUnocss(viteEnv), + ...setupUnplugin(viteEnv), + progress(), + setupHtmlPlugin(buildTime) + ]; + + return plugins; +} diff --git a/build/plugins/router.ts b/build/plugins/router.ts new file mode 100644 index 0000000..40a5ae5 --- /dev/null +++ b/build/plugins/router.ts @@ -0,0 +1,55 @@ +import type { RouteMeta } from 'vue-router'; +import ElegantVueRouter from '@elegant-router/vue/vite'; +import type { RouteKey } from '@elegant-router/types'; + +export function setupElegantRouter() { + return ElegantVueRouter({ + layouts: { + base: 'src/layouts/base-layout/index.vue', + blank: 'src/layouts/blank-layout/index.vue' + }, + customRoutes: { + names: [ + 'exception_403', + 'exception_404', + 'exception_500', + 'document_project', + 'document_project-link', + 'document_vue', + 'document_vite', + 'document_unocss', + 'document_naive', + 'document_antd' + ] + }, + routePathTransformer(routeName, routePath) { + const key = routeName as RouteKey; + + if (key === 'login') { + const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat']; + + const moduleReg = modules.join('|'); + + return `/login/:module(${moduleReg})?`; + } + + return routePath; + }, + onRouteMetaGen(routeName) { + const key = routeName as RouteKey; + + const constantRoutes: RouteKey[] = ['login', '403', '404', '500']; + + const meta: Partial = { + title: key, + i18nKey: `route.${key}` as App.I18n.I18nKey + }; + + if (constantRoutes.includes(key)) { + meta.constant = true; + } + + return meta; + } + }); +} diff --git a/build/plugins/unocss.ts b/build/plugins/unocss.ts new file mode 100644 index 0000000..06b41d3 --- /dev/null +++ b/build/plugins/unocss.ts @@ -0,0 +1,32 @@ +import process from 'node:process'; +import path from 'node:path'; +import unocss from '@unocss/vite'; +import presetIcons from '@unocss/preset-icons'; +import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'; + +export function setupUnocss(viteEnv: Env.ImportMeta) { + const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv; + + const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon'); + + /** The name of the local icon collection */ + const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, ''); + + return unocss({ + presets: [ + presetIcons({ + prefix: `${VITE_ICON_PREFIX}-`, + scale: 1, + extraProperties: { + display: 'inline-block' + }, + collections: { + [collectionName]: FileSystemIconLoader(localIconPath, svg => + svg.replace(/^ + svg.replace(/^ + + + + + + + %VITE_APP_TITLE% + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ffc64e --- /dev/null +++ b/package.json @@ -0,0 +1,113 @@ +{ + "name": "soybean-admin-antd", + "type": "module", + "version": "1.3.11", + "description": "A fresh and elegant admin template, based on Vue3,Vite3,TypeScript,AntDesign and UnoCSS.", + "author": { + "name": "Soybean", + "email": "soybeanjs@outlook.com", + "url": "https://github.com/soybeanjs" + }, + "license": "MIT", + "homepage": "https://github.com/soybeanjs/soybean-admin-antd", + "repository": { + "url": "https://github.com/soybeanjs/soybean-admin-antd.git" + }, + "bugs": { + "url": "https://github.com/soybeanjs/soybean-admin-antd/issues" + }, + "keywords": [ + "Vue3 admin ", + "vue-admin-template", + "Vite5", + "TypeScript", + "naive-ui", + "naive-ui-admin", + "ant-design-vue v4", + "UnoCSS" + ], + "engines": { + "node": ">=18.12.0", + "pnpm": ">=8.7.0" + }, + "scripts": { + "build": "vite build --mode prod", + "build:test": "vite build --mode test", + "cleanup": "sa cleanup", + "commit": "sa git-commit", + "commit:zh": "sa git-commit -l=zh-cn", + "dev": "vite --mode test", + "dev:prod": "vite --mode prod", + "gen-route": "sa gen-route", + "lint": "eslint . --fix", + "prepare": "simple-git-hooks", + "preview": "vite preview", + "release": "sa release", + "typecheck": "vue-tsc --noEmit --skipLibCheck", + "update-pkg": "sa update-pkg" + }, + "dependencies": { + "@better-scroll/core": "2.5.1", + "@iconify/vue": "4.3.0", + "@sa/axios": "workspace:*", + "@sa/color": "workspace:*", + "@sa/fetch": "workspace:*", + "@sa/hooks": "workspace:*", + "@sa/materials": "workspace:*", + "@sa/utils": "workspace:*", + "@vueuse/core": "12.5.0", + "ant-design-vue": "4.2.6", + "clipboard": "2.0.11", + "dayjs": "1.11.13", + "defu": "6.1.4", + "echarts": "5.6.0", + "json5": "2.2.3", + "nprogress": "0.2.0", + "pinia": "3.0.0", + "tailwind-merge": "3.0.1", + "vue": "3.5.13", + "vue-draggable-plus": "0.6.0", + "vue-i18n": "11.1.1", + "vue-router": "4.5.0" + }, + "devDependencies": { + "@elegant-router/vue": "0.3.8", + "@iconify/json": "2.2.305", + "@sa/scripts": "workspace:*", + "@sa/uno-preset": "workspace:*", + "@soybeanjs/eslint-config": "1.4.4", + "@types/node": "22.13.1", + "@types/nprogress": "0.2.3", + "@unocss/eslint-config": "65.4.3", + "@unocss/preset-icons": "65.4.3", + "@unocss/preset-uno": "65.4.3", + "@unocss/transformer-directives": "65.4.3", + "@unocss/transformer-variant-group": "65.4.3", + "@unocss/vite": "65.4.3", + "@vitejs/plugin-vue": "5.2.1", + "@vitejs/plugin-vue-jsx": "4.1.1", + "eslint": "9.20.0", + "eslint-plugin-vue": "9.32.0", + "lint-staged": "15.4.3", + "sass": "1.84.0", + "simple-git-hooks": "2.11.1", + "tsx": "4.19.2", + "typescript": "5.7.3", + "unplugin-icons": "22.0.0", + "unplugin-vue-components": "28.0.0", + "vite": "6.1.0", + "vite-plugin-progress": "0.0.7", + "vite-plugin-svg-icons": "2.0.1", + "vite-plugin-vue-devtools": "7.7.1", + "vue-eslint-parser": "9.4.3", + "vue-tsc": "2.2.0" + }, + "simple-git-hooks": { + "commit-msg": "pnpm sa git-commit-verify", + "pre-commit": "pnpm typecheck && pnpm lint-staged" + }, + "lint-staged": { + "*": "eslint --fix" + }, + "website": "https://antd.soybeanjs.cn" +} diff --git a/packages/axios/package.json b/packages/axios/package.json new file mode 100644 index 0000000..8278cfd --- /dev/null +++ b/packages/axios/package.json @@ -0,0 +1,21 @@ +{ + "name": "@sa/axios", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "@sa/utils": "workspace:*", + "axios": "1.7.9", + "axios-retry": "4.5.0", + "qs": "6.14.0" + }, + "devDependencies": { + "@types/qs": "6.9.18" + } +} diff --git a/packages/axios/src/constant.ts b/packages/axios/src/constant.ts new file mode 100644 index 0000000..d6c5a33 --- /dev/null +++ b/packages/axios/src/constant.ts @@ -0,0 +1,5 @@ +/** request id key */ +export const REQUEST_ID_KEY = 'X-Request-Id'; + +/** the backend error code key */ +export const BACKEND_ERROR_CODE = 'BACKEND_ERROR'; diff --git a/packages/axios/src/index.ts b/packages/axios/src/index.ts new file mode 100644 index 0000000..c29d9d2 --- /dev/null +++ b/packages/axios/src/index.ts @@ -0,0 +1,183 @@ +import axios, { AxiosError } from 'axios'; +import type { AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios'; +import axiosRetry from 'axios-retry'; +import { nanoid } from '@sa/utils'; +import { createAxiosConfig, createDefaultOptions, createRetryOptions } from './options'; +import { BACKEND_ERROR_CODE, REQUEST_ID_KEY } from './constant'; +import type { + CustomAxiosRequestConfig, + FlatRequestInstance, + MappedType, + RequestInstance, + RequestOption, + ResponseType +} from './type'; + +function createCommonRequest( + axiosConfig?: CreateAxiosDefaults, + options?: Partial> +) { + const opts = createDefaultOptions(options); + + const axiosConf = createAxiosConfig(axiosConfig); + const instance = axios.create(axiosConf); + + const abortControllerMap = new Map(); + + // config axios retry + const retryOptions = createRetryOptions(axiosConf); + axiosRetry(instance, retryOptions); + + instance.interceptors.request.use(conf => { + const config: InternalAxiosRequestConfig = { ...conf }; + + // set request id + const requestId = nanoid(); + config.headers.set(REQUEST_ID_KEY, requestId); + + // config abort controller + if (!config.signal) { + const abortController = new AbortController(); + config.signal = abortController.signal; + abortControllerMap.set(requestId, abortController); + } + + // handle config by hook + const handledConfig = opts.onRequest?.(config) || config; + + return handledConfig; + }); + + instance.interceptors.response.use( + async response => { + const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json'; + + if (responseType !== 'json' || opts.isBackendSuccess(response)) { + return Promise.resolve(response); + } + + const fail = await opts.onBackendFail(response, instance); + if (fail) { + return fail; + } + + const backendError = new AxiosError( + 'the backend request error', + BACKEND_ERROR_CODE, + response.config, + response.request, + response + ); + + await opts.onError(backendError); + + return Promise.reject(backendError); + }, + async (error: AxiosError) => { + await opts.onError(error); + + return Promise.reject(error); + } + ); + + function cancelRequest(requestId: string) { + const abortController = abortControllerMap.get(requestId); + if (abortController) { + abortController.abort(); + abortControllerMap.delete(requestId); + } + } + + function cancelAllRequest() { + abortControllerMap.forEach(abortController => { + abortController.abort(); + }); + abortControllerMap.clear(); + } + + return { + instance, + opts, + cancelRequest, + cancelAllRequest + }; +} + +/** + * create a request instance + * + * @param axiosConfig axios config + * @param options request options + */ +export function createRequest>( + axiosConfig?: CreateAxiosDefaults, + options?: Partial> +) { + const { instance, opts, cancelRequest, cancelAllRequest } = createCommonRequest(axiosConfig, options); + + const request: RequestInstance = async function request( + config: CustomAxiosRequestConfig + ) { + const response: AxiosResponse = await instance(config); + + const responseType = response.config?.responseType || 'json'; + + if (responseType === 'json') { + return opts.transformBackendResponse(response); + } + + return response.data as MappedType; + } as RequestInstance; + + request.cancelRequest = cancelRequest; + request.cancelAllRequest = cancelAllRequest; + request.state = {} as State; + + return request; +} + +/** + * create a flat request instance + * + * The response data is a flat object: { data: any, error: AxiosError } + * + * @param axiosConfig axios config + * @param options request options + */ +export function createFlatRequest>( + axiosConfig?: CreateAxiosDefaults, + options?: Partial> +) { + const { instance, opts, cancelRequest, cancelAllRequest } = createCommonRequest(axiosConfig, options); + + const flatRequest: FlatRequestInstance = async function flatRequest< + T = any, + R extends ResponseType = 'json' + >(config: CustomAxiosRequestConfig) { + try { + const response: AxiosResponse = await instance(config); + + const responseType = response.config?.responseType || 'json'; + + if (responseType === 'json') { + const data = opts.transformBackendResponse(response); + + return { data, error: null, response }; + } + + return { data: response.data as MappedType, error: null }; + } catch (error) { + return { data: null, error, response: (error as AxiosError).response }; + } + } as FlatRequestInstance; + + flatRequest.cancelRequest = cancelRequest; + flatRequest.cancelAllRequest = cancelAllRequest; + flatRequest.state = {} as State; + + return flatRequest; +} + +export { BACKEND_ERROR_CODE, REQUEST_ID_KEY }; +export type * from './type'; +export type { CreateAxiosDefaults, AxiosError }; diff --git a/packages/axios/src/options.ts b/packages/axios/src/options.ts new file mode 100644 index 0000000..8b2b116 --- /dev/null +++ b/packages/axios/src/options.ts @@ -0,0 +1,48 @@ +import type { CreateAxiosDefaults } from 'axios'; +import type { IAxiosRetryConfig } from 'axios-retry'; +import { stringify } from 'qs'; +import { isHttpSuccess } from './shared'; +import type { RequestOption } from './type'; + +export function createDefaultOptions(options?: Partial>) { + const opts: RequestOption = { + onRequest: async config => config, + isBackendSuccess: _response => true, + onBackendFail: async () => {}, + transformBackendResponse: async response => response.data, + onError: async () => {} + }; + + Object.assign(opts, options); + + return opts; +} + +export function createRetryOptions(config?: Partial) { + const retryConfig: IAxiosRetryConfig = { + retries: 0 + }; + + Object.assign(retryConfig, config); + + return retryConfig; +} + +export function createAxiosConfig(config?: Partial) { + const TEN_SECONDS = 10 * 1000; + + const axiosConfig: CreateAxiosDefaults = { + timeout: TEN_SECONDS, + headers: { + 'Content-Type': 'application/json' + }, + validateStatus: isHttpSuccess, + paramsSerializer: params => { + return stringify(params); + } + }; + + Object.assign(axiosConfig, config); + + return axiosConfig; +} diff --git a/packages/axios/src/shared.ts b/packages/axios/src/shared.ts new file mode 100644 index 0000000..7afd32b --- /dev/null +++ b/packages/axios/src/shared.ts @@ -0,0 +1,28 @@ +import type { AxiosHeaderValue, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; + +export function getContentType(config: InternalAxiosRequestConfig) { + const contentType: AxiosHeaderValue = config.headers?.['Content-Type'] || 'application/json'; + + return contentType; +} + +/** + * check if http status is success + * + * @param status + */ +export function isHttpSuccess(status: number) { + const isSuccessCode = status >= 200 && status < 300; + return isSuccessCode || status === 304; +} + +/** + * is response json + * + * @param response axios response + */ +export function isResponseJson(response: AxiosResponse) { + const { responseType } = response.config; + + return responseType === 'json' || responseType === undefined; +} diff --git a/packages/axios/src/type.ts b/packages/axios/src/type.ts new file mode 100644 index 0000000..644847f --- /dev/null +++ b/packages/axios/src/type.ts @@ -0,0 +1,115 @@ +import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; + +export type ContentType = + | 'text/html' + | 'text/plain' + | 'multipart/form-data' + | 'application/json' + | 'application/x-www-form-urlencoded' + | 'application/octet-stream'; + +export interface RequestOption { + /** + * The hook before request + * + * For example: You can add header token in this hook + * + * @param config Axios config + */ + onRequest: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise; + /** + * The hook to check backend response is success or not + * + * @param response Axios response + */ + isBackendSuccess: (response: AxiosResponse) => boolean; + /** + * The hook after backend request fail + * + * For example: You can handle the expired token in this hook + * + * @param response Axios response + * @param instance Axios instance + */ + onBackendFail: ( + response: AxiosResponse, + instance: AxiosInstance + ) => Promise | Promise; + /** + * transform backend response when the responseType is json + * + * @param response Axios response + */ + transformBackendResponse(response: AxiosResponse): any | Promise; + /** + * The hook to handle error + * + * For example: You can show error message in this hook + * + * @param error + */ + onError: (error: AxiosError) => void | Promise; +} + +interface ResponseMap { + blob: Blob; + text: string; + arrayBuffer: ArrayBuffer; + stream: ReadableStream; + document: Document; +} +export type ResponseType = keyof ResponseMap | 'json'; + +export type MappedType = R extends keyof ResponseMap + ? ResponseMap[R] + : JsonType; + +export type CustomAxiosRequestConfig = Omit & { + responseType?: R; +}; + +export interface RequestInstanceCommon { + /** + * cancel the request by request id + * + * if the request provide abort controller sign from config, it will not collect in the abort controller map + * + * @param requestId + */ + cancelRequest: (requestId: string) => void; + /** + * cancel all request + * + * if the request provide abort controller sign from config, it will not collect in the abort controller map + */ + cancelAllRequest: () => void; + /** you can set custom state in the request instance */ + state: T; +} + +/** The request instance */ +export interface RequestInstance> extends RequestInstanceCommon { + (config: CustomAxiosRequestConfig): Promise>; +} + +export type FlatResponseSuccessData = { + data: T; + error: null; + response: AxiosResponse; +}; + +export type FlatResponseFailData = { + data: null; + error: AxiosError; + response: AxiosResponse; +}; + +export type FlatResponseData = + | FlatResponseSuccessData + | FlatResponseFailData; + +export interface FlatRequestInstance, ResponseData = any> extends RequestInstanceCommon { + ( + config: CustomAxiosRequestConfig + ): Promise, ResponseData>>; +} diff --git a/packages/axios/tsconfig.json b/packages/axios/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/axios/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/color/package.json b/packages/color/package.json new file mode 100644 index 0000000..454eb54 --- /dev/null +++ b/packages/color/package.json @@ -0,0 +1,16 @@ +{ + "name": "@sa/color", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "@sa/utils": "workspace:*", + "colord": "2.9.3" + } +} diff --git a/packages/color/src/constant/index.ts b/packages/color/src/constant/index.ts new file mode 100644 index 0000000..cefbcdb --- /dev/null +++ b/packages/color/src/constant/index.ts @@ -0,0 +1,2 @@ +export * from './name'; +export * from './palette'; diff --git a/packages/color/src/constant/name.ts b/packages/color/src/constant/name.ts new file mode 100644 index 0000000..36648c3 --- /dev/null +++ b/packages/color/src/constant/name.ts @@ -0,0 +1,1579 @@ +export const colorNames: [hex: string, name: string][] = [ + ['#000000', 'Black'], + ['#000080', 'Navy Blue'], + ['#0000c8', 'Dark Blue'], + ['#0000ff', 'Blue'], + ['#000741', 'Stratos'], + ['#001b1c', 'Swamp'], + ['#002387', 'Resolution Blue'], + ['#002900', 'Deep Fir'], + ['#002e20', 'Burnham'], + ['#002fa7', 'International Klein Blue'], + ['#003153', 'Prussian Blue'], + ['#003366', 'Midnight Blue'], + ['#003399', 'Smalt'], + ['#003532', 'Deep Teal'], + ['#003e40', 'Cyprus'], + ['#004620', 'Kaitoke Green'], + ['#0047ab', 'Cobalt'], + ['#004816', 'Crusoe'], + ['#004950', 'Sherpa Blue'], + ['#0056a7', 'Endeavour'], + ['#00581a', 'Camarone'], + ['#0066cc', 'Science Blue'], + ['#0066ff', 'Blue Ribbon'], + ['#00755e', 'Tropical Rain Forest'], + ['#0076a3', 'Allports'], + ['#007ba7', 'Deep Cerulean'], + ['#007ec7', 'Lochmara'], + ['#007fff', 'Azure Radiance'], + ['#008080', 'Teal'], + ['#0095b6', 'Bondi Blue'], + ['#009dc4', 'Pacific Blue'], + ['#00a693', 'Persian Green'], + ['#00a86b', 'Jade'], + ['#00cc99', 'Caribbean Green'], + ['#00cccc', "Robin's Egg Blue"], + ['#00ff00', 'Green'], + ['#00ff7f', 'Spring Green'], + ['#00ffff', 'Cyan Aqua'], + ['#010d1a', 'Blue Charcoal'], + ['#011635', 'Midnight'], + ['#011d13', 'Holly'], + ['#012731', 'Daintree'], + ['#01361c', 'Cardin Green'], + ['#01371a', 'County Green'], + ['#013e62', 'Astronaut Blue'], + ['#013f6a', 'Regal Blue'], + ['#014b43', 'Aqua Deep'], + ['#015e85', 'Orient'], + ['#016162', 'Blue Stone'], + ['#016d39', 'Fun Green'], + ['#01796f', 'Pine Green'], + ['#017987', 'Blue Lagoon'], + ['#01826b', 'Deep Sea'], + ['#01a368', 'Green Haze'], + ['#022d15', 'English Holly'], + ['#02402c', 'Sherwood Green'], + ['#02478e', 'Congress Blue'], + ['#024e46', 'Evening Sea'], + ['#026395', 'Bahama Blue'], + ['#02866f', 'Observatory'], + ['#02a4d3', 'Cerulean'], + ['#03163c', 'Tangaroa'], + ['#032b52', 'Green Vogue'], + ['#036a6e', 'Mosque'], + ['#041004', 'Midnight Moss'], + ['#041322', 'Black Pearl'], + ['#042e4c', 'Blue Whale'], + ['#044022', 'Zuccini'], + ['#044259', 'Teal Blue'], + ['#051040', 'Deep Cove'], + ['#051657', 'Gulf Blue'], + ['#055989', 'Venice Blue'], + ['#056f57', 'Watercourse'], + ['#062a78', 'Catalina Blue'], + ['#063537', 'Tiber'], + ['#069b81', 'Gossamer'], + ['#06a189', 'Niagara'], + ['#073a50', 'Tarawera'], + ['#080110', 'Jaguar'], + ['#081910', 'Black Bean'], + ['#082567', 'Deep Sapphire'], + ['#088370', 'Elf Green'], + ['#08e8de', 'Bright Turquoise'], + ['#092256', 'Downriver'], + ['#09230f', 'Palm Green'], + ['#09255d', 'Madison'], + ['#093624', 'Bottle Green'], + ['#095859', 'Deep Sea Green'], + ['#097f4b', 'Salem'], + ['#0a001c', 'Black Russian'], + ['#0a480d', 'Dark Fern'], + ['#0a6906', 'Japanese Laurel'], + ['#0a6f75', 'Atoll'], + ['#0b0b0b', 'Cod Gray'], + ['#0b0f08', 'Marshland'], + ['#0b1107', 'Gordons Green'], + ['#0b1304', 'Black Forest'], + ['#0b6207', 'San Felix'], + ['#0bda51', 'Malachite'], + ['#0c0b1d', 'Ebony'], + ['#0c0d0f', 'Woodsmoke'], + ['#0c1911', 'Racing Green'], + ['#0c7a79', 'Surfie Green'], + ['#0c8990', 'Blue Chill'], + ['#0d0332', 'Black Rock'], + ['#0d1117', 'Bunker'], + ['#0d1c19', 'Aztec'], + ['#0d2e1c', 'Bush'], + ['#0e0e18', 'Cinder'], + ['#0e2a30', 'Firefly'], + ['#0f2d9e', 'Torea Bay'], + ['#10121d', 'Vulcan'], + ['#101405', 'Green Waterloo'], + ['#105852', 'Eden'], + ['#110c6c', 'Arapawa'], + ['#120a8f', 'Ultramarine'], + ['#123447', 'Elephant'], + ['#126b40', 'Jewel'], + ['#130000', 'Diesel'], + ['#130a06', 'Asphalt'], + ['#13264d', 'Blue Zodiac'], + ['#134f19', 'Parsley'], + ['#140600', 'Nero'], + ['#1450aa', 'Tory Blue'], + ['#151f4c', 'Bunting'], + ['#1560bd', 'Denim'], + ['#15736b', 'Genoa'], + ['#161928', 'Mirage'], + ['#161d10', 'Hunter Green'], + ['#162a40', 'Big Stone'], + ['#163222', 'Celtic'], + ['#16322c', 'Timber Green'], + ['#163531', 'Gable Green'], + ['#171f04', 'Pine Tree'], + ['#175579', 'Chathams Blue'], + ['#182d09', 'Deep Forest Green'], + ['#18587a', 'Blumine'], + ['#19330e', 'Palm Leaf'], + ['#193751', 'Nile Blue'], + ['#1959a8', 'Fun Blue'], + ['#1a1a68', 'Lucky Point'], + ['#1ab385', 'Mountain Meadow'], + ['#1b0245', 'Tolopea'], + ['#1b1035', 'Haiti'], + ['#1b127b', 'Deep Koamaru'], + ['#1b1404', 'Acadia'], + ['#1b2f11', 'Seaweed'], + ['#1b3162', 'Biscay'], + ['#1b659d', 'Matisse'], + ['#1c1208', 'Crowshead'], + ['#1c1e13', 'Rangoon Green'], + ['#1c39bb', 'Persian Blue'], + ['#1c402e', 'Everglade'], + ['#1c7c7d', 'Elm'], + ['#1d6142', 'Green Pea'], + ['#1e0f04', 'Creole'], + ['#1e1609', 'Karaka'], + ['#1e1708', 'El Paso'], + ['#1e385b', 'Cello'], + ['#1e433c', 'Te Papa Green'], + ['#1e90ff', 'Dodger Blue'], + ['#1e9ab0', 'Eastern Blue'], + ['#1f120f', 'Night Rider'], + ['#1fc2c2', 'Java'], + ['#20208d', 'Jacksons Purple'], + ['#202e54', 'Cloud Burst'], + ['#204852', 'Blue Dianne'], + ['#211a0e', 'Eternity'], + ['#220878', 'Deep Blue'], + ['#228b22', 'Forest Green'], + ['#233418', 'Mallard'], + ['#240a40', 'Violet'], + ['#240c02', 'Kilamanjaro'], + ['#242a1d', 'Log Cabin'], + ['#242e16', 'Black Olive'], + ['#24500f', 'Green House'], + ['#251607', 'Graphite'], + ['#251706', 'Cannon Black'], + ['#251f4f', 'Port Gore'], + ['#25272c', 'Shark'], + ['#25311c', 'Green Kelp'], + ['#2596d1', 'Curious Blue'], + ['#260368', 'Paua'], + ['#26056a', 'Paris M'], + ['#261105', 'Wood Bark'], + ['#261414', 'Gondola'], + ['#262335', 'Steel Gray'], + ['#26283b', 'Ebony Clay'], + ['#273a81', 'Bay Of Many'], + ['#27504b', 'Plantation'], + ['#278a5b', 'Eucalyptus'], + ['#281e15', 'Oil'], + ['#283a77', 'Astronaut'], + ['#286acd', 'Mariner'], + ['#290c5e', 'Violent Violet'], + ['#292130', 'Bastille'], + ['#292319', 'Zeus'], + ['#292937', 'Charade'], + ['#297b9a', 'Jelly Bean'], + ['#29ab87', 'Jungle Green'], + ['#2a0359', 'Cherry Pie'], + ['#2a140e', 'Coffee Bean'], + ['#2a2630', 'Baltic Sea'], + ['#2a380b', 'Turtle Green'], + ['#2a52be', 'Cerulean Blue'], + ['#2b0202', 'Sepia Black'], + ['#2b194f', 'Valhalla'], + ['#2b3228', 'Heavy Metal'], + ['#2c0e8c', 'Blue Gem'], + ['#2c1632', 'Revolver'], + ['#2c2133', 'Bleached Cedar'], + ['#2c8c84', 'Lochinvar'], + ['#2d2510', 'Mikado'], + ['#2d383a', 'Outer Space'], + ['#2d569b', 'St Tropaz'], + ['#2e0329', 'Jacaranda'], + ['#2e1905', 'Jacko Bean'], + ['#2e3222', 'Rangitoto'], + ['#2e3f62', 'Rhino'], + ['#2e8b57', 'Sea Green'], + ['#2ebfd4', 'Scooter'], + ['#2f270e', 'Onion'], + ['#2f3cb3', 'Governor Bay'], + ['#2f519e', 'Sapphire'], + ['#2f5a57', 'Spectra'], + ['#2f6168', 'Casal'], + ['#300529', 'Melanzane'], + ['#301f1e', 'Cocoa Brown'], + ['#302a0f', 'Woodrush'], + ['#304b6a', 'San Juan'], + ['#30d5c8', 'Turquoise'], + ['#311c17', 'Eclipse'], + ['#314459', 'Pickled Bluewood'], + ['#315ba1', 'Azure'], + ['#31728d', 'Calypso'], + ['#317d82', 'Paradiso'], + ['#32127a', 'Persian Indigo'], + ['#32293a', 'Blackcurrant'], + ['#323232', 'Mine Shaft'], + ['#325d52', 'Stromboli'], + ['#327c14', 'Bilbao'], + ['#327da0', 'Astral'], + ['#33036b', 'Christalle'], + ['#33292f', 'Thunder'], + ['#33cc99', 'Shamrock'], + ['#341515', 'Tamarind'], + ['#350036', 'Mardi Gras'], + ['#350e42', 'Valentino'], + ['#350e57', 'Jagger'], + ['#353542', 'Tuna'], + ['#354e8c', 'Chambray'], + ['#363050', 'Martinique'], + ['#363534', 'Tuatara'], + ['#363c0d', 'Waiouru'], + ['#36747d', 'Ming'], + ['#368716', 'La Palma'], + ['#370202', 'Chocolate'], + ['#371d09', 'Clinker'], + ['#37290e', 'Brown Tumbleweed'], + ['#373021', 'Birch'], + ['#377475', 'Oracle'], + ['#380474', 'Blue Diamond'], + ['#381a51', 'Grape'], + ['#383533', 'Dune'], + ['#384555', 'Oxford Blue'], + ['#384910', 'Clover'], + ['#394851', 'Limed Spruce'], + ['#396413', 'Dell'], + ['#3a0020', 'Toledo'], + ['#3a2010', 'Sambuca'], + ['#3a2a6a', 'Jacarta'], + ['#3a686c', 'William'], + ['#3a6a47', 'Killarney'], + ['#3ab09e', 'Keppel'], + ['#3b000b', 'Temptress'], + ['#3b0910', 'Aubergine'], + ['#3b1f1f', 'Jon'], + ['#3b2820', 'Treehouse'], + ['#3b7a57', 'Amazon'], + ['#3b91b4', 'Boston Blue'], + ['#3c0878', 'Windsor'], + ['#3c1206', 'Rebel'], + ['#3c1f76', 'Meteorite'], + ['#3c2005', 'Dark Ebony'], + ['#3c3910', 'Camouflage'], + ['#3c4151', 'Bright Gray'], + ['#3c4443', 'Cape Cod'], + ['#3c493a', 'Lunar Green'], + ['#3d0c02', 'Bean '], + ['#3d2b1f', 'Bistre'], + ['#3d7d52', 'Goblin'], + ['#3e0480', 'Kingfisher Daisy'], + ['#3e1c14', 'Cedar'], + ['#3e2b23', 'English Walnut'], + ['#3e2c1c', 'Black Marlin'], + ['#3e3a44', 'Ship Gray'], + ['#3eabbf', 'Pelorous'], + ['#3f2109', 'Bronze'], + ['#3f2500', 'Cola'], + ['#3f3002', 'Madras'], + ['#3f307f', 'Minsk'], + ['#3f4c3a', 'Cabbage Pont'], + ['#3f583b', 'Tom Thumb'], + ['#3f5d53', 'Mineral Green'], + ['#3fc1aa', 'Puerto Rico'], + ['#3fff00', 'Harlequin'], + ['#401801', 'Brown Pod'], + ['#40291d', 'Cork'], + ['#403b38', 'Masala'], + ['#403d19', 'Thatch Green'], + ['#405169', 'Fiord'], + ['#40826d', 'Viridian'], + ['#40a860', 'Chateau Green'], + ['#410056', 'Ripe Plum'], + ['#411f10', 'Paco'], + ['#412010', 'Deep Oak'], + ['#413c37', 'Merlin'], + ['#414257', 'Gun Powder'], + ['#414c7d', 'East Bay'], + ['#4169e1', 'Royal Blue'], + ['#41aa78', 'Ocean Green'], + ['#420303', 'Burnt Maroon'], + ['#423921', 'Lisbon Brown'], + ['#427977', 'Faded Jade'], + ['#431560', 'Scarlet Gum'], + ['#433120', 'Iroko'], + ['#433e37', 'Armadillo'], + ['#434c59', 'River Bed'], + ['#436a0d', 'Green Leaf'], + ['#44012d', 'Barossa'], + ['#441d00', 'Morocco Brown'], + ['#444954', 'Mako'], + ['#454936', 'Kelp'], + ['#456cac', 'San Marino'], + ['#45b1e8', 'Picton Blue'], + ['#460b41', 'Loulou'], + ['#462425', 'Crater Brown'], + ['#465945', 'Gray Asparagus'], + ['#4682b4', 'Steel Blue'], + ['#480404', 'Rustic Red'], + ['#480607', 'Bulgarian Rose'], + ['#480656', 'Clairvoyant'], + ['#481c1c', 'Cocoa Bean'], + ['#483131', 'Woody Brown'], + ['#483c32', 'Taupe'], + ['#49170c', 'Van Cleef'], + ['#492615', 'Brown Derby'], + ['#49371b', 'Metallic Bronze'], + ['#495400', 'Verdun Green'], + ['#496679', 'Blue Bayoux'], + ['#497183', 'Bismark'], + ['#4a2a04', 'Bracken'], + ['#4a3004', 'Deep Bronze'], + ['#4a3c30', 'Mondo'], + ['#4a4244', 'Tundora'], + ['#4a444b', 'Gravel'], + ['#4a4e5a', 'Trout'], + ['#4b0082', 'Pigment Indigo'], + ['#4b5d52', 'Nandor'], + ['#4c3024', 'Saddle'], + ['#4c4f56', 'Abbey'], + ['#4d0135', 'Blackberry'], + ['#4d0a18', 'Cab Sav'], + ['#4d1e01', 'Indian Tan'], + ['#4d282d', 'Cowboy'], + ['#4d282e', 'Livid Brown'], + ['#4d3833', 'Rock'], + ['#4d3d14', 'Punga'], + ['#4d400f', 'Bronzetone'], + ['#4d5328', 'Woodland'], + ['#4e0606', 'Mahogany'], + ['#4e2a5a', 'Bossanova'], + ['#4e3b41', 'Matterhorn'], + ['#4e420c', 'Bronze Olive'], + ['#4e4562', 'Mulled Wine'], + ['#4e6649', 'Axolotl'], + ['#4e7f9e', 'Wedgewood'], + ['#4eabd1', 'Shakespeare'], + ['#4f1c70', 'Honey Flower'], + ['#4f2398', 'Daisy Bush'], + ['#4f69c6', 'Indigo'], + ['#4f7942', 'Fern Green'], + ['#4f9d5d', 'Fruit Salad'], + ['#4fa83d', 'Apple'], + ['#504351', 'Mortar'], + ['#507096', 'Kashmir Blue'], + ['#507672', 'Cutty Sark'], + ['#50c878', 'Emerald'], + ['#514649', 'Emperor'], + ['#516e3d', 'Chalet Green'], + ['#517c66', 'Como'], + ['#51808f', 'Smalt Blue'], + ['#52001f', 'Castro'], + ['#520c17', 'Maroon Oak'], + ['#523c94', 'Gigas'], + ['#533455', 'Voodoo'], + ['#534491', 'Victoria'], + ['#53824b', 'Hippie Green'], + ['#541012', 'Heath'], + ['#544333', 'Judge Gray'], + ['#54534d', 'Fuscous Gray'], + ['#549019', 'Vida Loca'], + ['#55280c', 'Cioccolato'], + ['#555b10', 'Saratoga'], + ['#556d56', 'Finlandia'], + ['#5590d9', 'Havelock Blue'], + ['#56b4be', 'Fountain Blue'], + ['#578363', 'Spring Leaves'], + ['#583401', 'Saddle Brown'], + ['#585562', 'Scarpa Flow'], + ['#587156', 'Cactus'], + ['#589aaf', 'Hippie Blue'], + ['#591d35', 'Wine Berry'], + ['#592804', 'Brown Bramble'], + ['#593737', 'Congo Brown'], + ['#594433', 'Millbrook'], + ['#5a6e9c', 'Waikawa Gray'], + ['#5a87a0', 'Horizon'], + ['#5b3013', 'Jambalaya'], + ['#5c0120', 'Bordeaux'], + ['#5c0536', 'Mulberry Wood'], + ['#5c2e01', 'Carnaby Tan'], + ['#5c5d75', 'Comet'], + ['#5d1e0f', 'Redwood'], + ['#5d4c51', 'Don Juan'], + ['#5d5c58', 'Chicago'], + ['#5d5e37', 'Verdigris'], + ['#5d7747', 'Dingley'], + ['#5da19f', 'Breaker Bay'], + ['#5e483e', 'Kabul'], + ['#5e5d3b', 'Hemlock'], + ['#5f3d26', 'Irish Coffee'], + ['#5f5f6e', 'Mid Gray'], + ['#5f6672', 'Shuttle Gray'], + ['#5fa777', 'Aqua Forest'], + ['#5fb3ac', 'Tradewind'], + ['#604913', 'Horses Neck'], + ['#605b73', 'Smoky'], + ['#606e68', 'Corduroy'], + ['#6093d1', 'Danube'], + ['#612718', 'Espresso'], + ['#614051', 'Eggplant'], + ['#615d30', 'Costa Del Sol'], + ['#61845f', 'Glade Green'], + ['#622f30', 'Buccaneer'], + ['#623f2d', 'Quincy'], + ['#624e9a', 'Butterfly Bush'], + ['#625119', 'West Coast'], + ['#626649', 'Finch'], + ['#639a8f', 'Patina'], + ['#63b76c', 'Fern'], + ['#6456b7', 'Blue Violet'], + ['#646077', 'Dolphin'], + ['#646463', 'Storm Dust'], + ['#646a54', 'Siam'], + ['#646e75', 'Nevada'], + ['#6495ed', 'Cornflower Blue'], + ['#64ccdb', 'Viking'], + ['#65000b', 'Rosewood'], + ['#651a14', 'Cherrywood'], + ['#652dc1', 'Purple Heart'], + ['#657220', 'Fern Frond'], + ['#65745d', 'Willow Grove'], + ['#65869f', 'Hoki'], + ['#660045', 'Pompadour'], + ['#660099', 'Purple'], + ['#66023c', 'Tyrian Purple'], + ['#661010', 'Dark Tan'], + ['#66b58f', 'Silver Tree'], + ['#66ff00', 'Bright Green'], + ['#66ff66', 'Screamin Green'], + ['#67032d', 'Black Rose'], + ['#675fa6', 'Scampi'], + ['#676662', 'Ironside Gray'], + ['#678975', 'Viridian Green'], + ['#67a712', 'Christi'], + ['#683600', 'Nutmeg Wood Finish'], + ['#685558', 'Zambezi'], + ['#685e6e', 'Salt Box'], + ['#692545', 'Tawny Port'], + ['#692d54', 'Finn'], + ['#695f62', 'Scorpion'], + ['#697e9a', 'Lynch'], + ['#6a442e', 'Spice'], + ['#6a5d1b', 'Himalaya'], + ['#6a6051', 'Soya Bean'], + ['#6b2a14', 'Hairy Heath'], + ['#6b3fa0', 'Royal Purple'], + ['#6b4e31', 'Shingle Fawn'], + ['#6b5755', 'Dorado'], + ['#6b8ba2', 'Bermuda Gray'], + ['#6b8e23', 'Olive Drab'], + ['#6c3082', 'Eminence'], + ['#6cdae7', 'Turquoise Blue'], + ['#6d0101', 'Lonestar'], + ['#6d5e54', 'Pine Cone'], + ['#6d6c6c', 'Dove Gray'], + ['#6d9292', 'Juniper'], + ['#6d92a1', 'Gothic'], + ['#6e0902', 'Red Oxide'], + ['#6e1d14', 'Moccaccino'], + ['#6e4826', 'Pickled Bean'], + ['#6e4b26', 'Dallas'], + ['#6e6d57', 'Kokoda'], + ['#6e7783', 'Pale Sky'], + ['#6f440c', 'Cafe Royale'], + ['#6f6a61', 'Flint'], + ['#6f8e63', 'Highland'], + ['#6f9d02', 'Limeade'], + ['#6fd0c5', 'Downy'], + ['#701c1c', 'Persian Plum'], + ['#704214', 'Sepia'], + ['#704a07', 'Antique Bronze'], + ['#704f50', 'Ferra'], + ['#706555', 'Coffee'], + ['#708090', 'Slate Gray'], + ['#711a00', 'Cedar Wood Finish'], + ['#71291d', 'Metallic Copper'], + ['#714693', 'Affair'], + ['#714ab2', 'Studio'], + ['#715d47', 'Tobacco Brown'], + ['#716338', 'Yellow Metal'], + ['#716b56', 'Peat'], + ['#716e10', 'Olivetone'], + ['#717486', 'Storm Gray'], + ['#718080', 'Sirocco'], + ['#71d9e2', 'Aquamarine Blue'], + ['#72010f', 'Venetian Red'], + ['#724a2f', 'Old Copper'], + ['#726d4e', 'Go Ben'], + ['#727b89', 'Raven'], + ['#731e8f', 'Seance'], + ['#734a12', 'Raw Umber'], + ['#736c9f', 'Kimberly'], + ['#736d58', 'Crocodile'], + ['#737829', 'Crete'], + ['#738678', 'Xanadu'], + ['#74640d', 'Spicy Mustard'], + ['#747d63', 'Limed Ash'], + ['#747d83', 'Rolling Stone'], + ['#748881', 'Blue Smoke'], + ['#749378', 'Laurel'], + ['#74c365', 'Mantis'], + ['#755a57', 'Russett'], + ['#7563a8', 'Deluge'], + ['#76395d', 'Cosmic'], + ['#7666c6', 'Blue Marguerite'], + ['#76bd17', 'Lima'], + ['#76d7ea', 'Sky Blue'], + ['#770f05', 'Dark Burgundy'], + ['#771f1f', 'Crown Of Thorns'], + ['#773f1a', 'Walnut'], + ['#776f61', 'Pablo'], + ['#778120', 'Pacifika'], + ['#779e86', 'Oxley'], + ['#77dd77', 'Pastel Green'], + ['#780109', 'Japanese Maple'], + ['#782d19', 'Mocha'], + ['#782f16', 'Peanut'], + ['#78866b', 'Camouflage Green'], + ['#788a25', 'Wasabi'], + ['#788bba', 'Ship Cove'], + ['#78a39c', 'Sea Nymph'], + ['#795d4c', 'Roman Coffee'], + ['#796878', 'Old Lavender'], + ['#796989', 'Rum'], + ['#796a78', 'Fedora'], + ['#796d62', 'Sandstone'], + ['#79deec', 'Spray'], + ['#7a013a', 'Siren'], + ['#7a58c1', 'Fuchsia Blue'], + ['#7a7a7a', 'Boulder'], + ['#7a89b8', 'Wild Blue Yonder'], + ['#7ac488', 'De York'], + ['#7b3801', 'Red Beech'], + ['#7b3f00', 'Cinnamon'], + ['#7b6608', 'Yukon Gold'], + ['#7b7874', 'Tapa'], + ['#7b7c94', 'Waterloo '], + ['#7b8265', 'Flax Smoke'], + ['#7b9f80', 'Amulet'], + ['#7ba05b', 'Asparagus'], + ['#7c1c05', 'Kenyan Copper'], + ['#7c7631', 'Pesto'], + ['#7c778a', 'Topaz'], + ['#7c7b7a', 'Concord'], + ['#7c7b82', 'Jumbo'], + ['#7c881a', 'Trendy Green'], + ['#7ca1a6', 'Gumbo'], + ['#7cb0a1', 'Acapulco'], + ['#7cb7bb', 'Neptune'], + ['#7d2c14', 'Pueblo'], + ['#7da98d', 'Bay Leaf'], + ['#7dc8f7', 'Malibu'], + ['#7dd8c6', 'Bermuda'], + ['#7e3a15', 'Copper Canyon'], + ['#7f1734', 'Claret'], + ['#7f3a02', 'Peru Tan'], + ['#7f626d', 'Falcon'], + ['#7f7589', 'Mobster'], + ['#7f76d3', 'Moody Blue'], + ['#7fff00', 'Chartreuse'], + ['#7fffd4', 'Aquamarine'], + ['#800000', 'Maroon'], + ['#800b47', 'Rose Bud Cherry'], + ['#801818', 'Falu Red'], + ['#80341f', 'Red Robin'], + ['#803790', 'Vivid Violet'], + ['#80461b', 'Russet'], + ['#807e79', 'Friar Gray'], + ['#808000', 'Olive'], + ['#808080', 'Gray'], + ['#80b3ae', 'Gulf Stream'], + ['#80b3c4', 'Glacier'], + ['#80ccea', 'Seagull'], + ['#81422c', 'Nutmeg'], + ['#816e71', 'Spicy Pink'], + ['#817377', 'Empress'], + ['#819885', 'Spanish Green'], + ['#826f65', 'Sand Dune'], + ['#828685', 'Gunsmoke'], + ['#828f72', 'Battleship Gray'], + ['#831923', 'Merlot'], + ['#837050', 'Shadow'], + ['#83aa5d', 'Chelsea Cucumber'], + ['#83d0c6', 'Monte Carlo'], + ['#843179', 'Plum'], + ['#84a0a0', 'Granny Smith'], + ['#8581d9', 'Chetwode Blue'], + ['#858470', 'Bandicoot'], + ['#859faf', 'Bali Hai'], + ['#85c4cc', 'Half Baked'], + ['#860111', 'Red Devil'], + ['#863c3c', 'Lotus'], + ['#86483c', 'Ironstone'], + ['#864d1e', 'Bull Shot'], + ['#86560a', 'Rusty Nail'], + ['#868974', 'Bitter'], + ['#86949f', 'Regent Gray'], + ['#871550', 'Disco'], + ['#87756e', 'Americano'], + ['#877c7b', 'Hurricane'], + ['#878d91', 'Oslo Gray'], + ['#87ab39', 'Sushi'], + ['#885342', 'Spicy Mix'], + ['#886221', 'Kumera'], + ['#888387', 'Suva Gray'], + ['#888d65', 'Avocado'], + ['#893456', 'Camelot'], + ['#893843', 'Solid Pink'], + ['#894367', 'Cannon Pink'], + ['#897d6d', 'Makara'], + ['#8a3324', 'Burnt Umber'], + ['#8a73d6', 'True V'], + ['#8a8360', 'Clay Creek'], + ['#8a8389', 'Monsoon'], + ['#8a8f8a', 'Stack'], + ['#8ab9f1', 'Jordy Blue'], + ['#8b00ff', 'Electric Violet'], + ['#8b0723', 'Monarch'], + ['#8b6b0b', 'Corn Harvest'], + ['#8b8470', 'Olive Haze'], + ['#8b847e', 'Schooner'], + ['#8b8680', 'Natural Gray'], + ['#8b9c90', 'Mantle'], + ['#8b9fee', 'Portage'], + ['#8ba690', 'Envy'], + ['#8ba9a5', 'Cascade'], + ['#8be6d8', 'Riptide'], + ['#8c055e', 'Cardinal Pink'], + ['#8c472f', 'Mule Fawn'], + ['#8c5738', 'Potters Clay'], + ['#8c6495', 'Trendy Pink'], + ['#8d0226', 'Paprika'], + ['#8d3d38', 'Sanguine Brown'], + ['#8d3f3f', 'Tosca'], + ['#8d7662', 'Cement'], + ['#8d8974', 'Granite Green'], + ['#8d90a1', 'Manatee'], + ['#8da8cc', 'Polo Blue'], + ['#8e0000', 'Red Berry'], + ['#8e4d1e', 'Rope'], + ['#8e6f70', 'Opium'], + ['#8e775e', 'Domino'], + ['#8e8190', 'Mamba'], + ['#8eabc1', 'Nepal'], + ['#8f021c', 'Pohutukawa'], + ['#8f3e33', 'El Salva'], + ['#8f4b0e', 'Korma'], + ['#8f8176', 'Squirrel'], + ['#8fd6b4', 'Vista Blue'], + ['#900020', 'Burgundy'], + ['#901e1e', 'Old Brick'], + ['#907874', 'Hemp'], + ['#907b71', 'Almond Frost'], + ['#908d39', 'Sycamore'], + ['#92000a', 'Sangria'], + ['#924321', 'Cumin'], + ['#926f5b', 'Beaver'], + ['#928573', 'Stonewall'], + ['#928590', 'Venus'], + ['#9370db', 'Medium Purple'], + ['#93ccea', 'Cornflower'], + ['#93dfb8', 'Algae Green'], + ['#944747', 'Copper Rust'], + ['#948771', 'Arrowtown'], + ['#950015', 'Scarlett'], + ['#956387', 'Strikemaster'], + ['#959396', 'Mountain Mist'], + ['#960018', 'Carmine'], + ['#964b00', 'Brown'], + ['#967059', 'Leather'], + ['#9678b6', "Purple Mountain's Majesty"], + ['#967bb6', 'Lavender Purple'], + ['#96a8a1', 'Pewter'], + ['#96bbab', 'Summer Green'], + ['#97605d', 'Au Chico'], + ['#9771b5', 'Wisteria'], + ['#97cd2d', 'Atlantis'], + ['#983d61', 'Vin Rouge'], + ['#9874d3', 'Lilac Bush'], + ['#98777b', 'Bazaar'], + ['#98811b', 'Hacienda'], + ['#988d77', 'Pale Oyster'], + ['#98ff98', 'Mint Green'], + ['#990066', 'Fresh Eggplant'], + ['#991199', 'Violet Eggplant'], + ['#991613', 'Tamarillo'], + ['#991b07', 'Totem Pole'], + ['#996666', 'Copper Rose'], + ['#9966cc', 'Amethyst'], + ['#997a8d', 'Mountbatten Pink'], + ['#9999cc', 'Blue Bell'], + ['#9a3820', 'Prairie Sand'], + ['#9a6e61', 'Toast'], + ['#9a9577', 'Gurkha'], + ['#9ab973', 'Olivine'], + ['#9ac2b8', 'Shadow Green'], + ['#9b4703', 'Oregon'], + ['#9b9e8f', 'Lemon Grass'], + ['#9c3336', 'Stiletto'], + ['#9d5616', 'Hawaiian Tan'], + ['#9dacb7', 'Gull Gray'], + ['#9dc209', 'Pistachio'], + ['#9de093', 'Granny Smith Apple'], + ['#9de5ff', 'Anakiwa'], + ['#9e5302', 'Chelsea Gem'], + ['#9e5b40', 'Sepia Skin'], + ['#9ea587', 'Sage'], + ['#9ea91f', 'Citron'], + ['#9eb1cd', 'Rock Blue'], + ['#9edee0', 'Morning Glory'], + ['#9f381d', 'Cognac'], + ['#9f821c', 'Reef Gold'], + ['#9f9f9c', 'Star Dust'], + ['#9fa0b1', 'Santas Gray'], + ['#9fd7d3', 'Sinbad'], + ['#9fdd8c', 'Feijoa'], + ['#a02712', 'Tabasco'], + ['#a1750d', 'Buttered Rum'], + ['#a1adb5', 'Hit Gray'], + ['#a1c50a', 'Citrus'], + ['#a1dad7', 'Aqua Island'], + ['#a1e9de', 'Water Leaf'], + ['#a2006d', 'Flirt'], + ['#a23b6c', 'Rouge'], + ['#a26645', 'Cape Palliser'], + ['#a2aab3', 'Gray Chateau'], + ['#a2aeab', 'Edward'], + ['#a3807b', 'Pharlap'], + ['#a397b4', 'Amethyst Smoke'], + ['#a3e3ed', 'Blizzard Blue'], + ['#a4a49d', 'Delta'], + ['#a4a6d3', 'Wistful'], + ['#a4af6e', 'Green Smoke'], + ['#a50b5e', 'Jazzberry Jam'], + ['#a59b91', 'Zorba'], + ['#a5cb0c', 'Bahia'], + ['#a62f20', 'Roof Terracotta'], + ['#a65529', 'Paarl'], + ['#a68b5b', 'Barley Corn'], + ['#a69279', 'Donkey Brown'], + ['#a6a29a', 'Dawn'], + ['#a72525', 'Mexican Red'], + ['#a7882c', 'Luxor Gold'], + ['#a85307', 'Rich Gold'], + ['#a86515', 'Reno Sand'], + ['#a86b6b', 'Coral Tree'], + ['#a8989b', 'Dusty Gray'], + ['#a899e6', 'Dull Lavender'], + ['#a8a589', 'Tallow'], + ['#a8ae9c', 'Bud'], + ['#a8af8e', 'Locust'], + ['#a8bd9f', 'Norway'], + ['#a8e3bd', 'Chinook'], + ['#a9a491', 'Gray Olive'], + ['#a9acb6', 'Aluminium'], + ['#a9b2c3', 'Cadet Blue'], + ['#a9b497', 'Schist'], + ['#a9bdbf', 'Tower Gray'], + ['#a9bef2', 'Perano'], + ['#a9c6c2', 'Opal'], + ['#aa375a', 'Night Shadz'], + ['#aa4203', 'Fire'], + ['#aa8b5b', 'Muesli'], + ['#aa8d6f', 'Sandal'], + ['#aaa5a9', 'Shady Lady'], + ['#aaa9cd', 'Logan'], + ['#aaabb7', 'Spun Pearl'], + ['#aad6e6', 'Regent St Blue'], + ['#aaf0d1', 'Magic Mint'], + ['#ab0563', 'Lipstick'], + ['#ab3472', 'Royal Heath'], + ['#ab917a', 'Sandrift'], + ['#aba0d9', 'Cold Purple'], + ['#aba196', 'Bronco'], + ['#ac8a56', 'Limed Oak'], + ['#ac91ce', 'East Side'], + ['#ac9e22', 'Lemon Ginger'], + ['#aca494', 'Napa'], + ['#aca586', 'Hillary'], + ['#aca59f', 'Cloudy'], + ['#acacac', 'Silver Chalice'], + ['#acb78e', 'Swamp Green'], + ['#accbb1', 'Spring Rain'], + ['#acdd4d', 'Conifer'], + ['#ace1af', 'Celadon'], + ['#ad781b', 'Mandalay'], + ['#adbed1', 'Casper'], + ['#addfad', 'Moss Green'], + ['#ade6c4', 'Padua'], + ['#adff2f', 'Green Yellow'], + ['#ae4560', 'Hippie Pink'], + ['#ae6020', 'Desert'], + ['#ae809e', 'Bouquet'], + ['#af4035', 'Medium Carmine'], + ['#af4d43', 'Apple Blossom'], + ['#af593e', 'Brown Rust'], + ['#af8751', 'Driftwood'], + ['#af8f2c', 'Alpine'], + ['#af9f1c', 'Lucky'], + ['#afa09e', 'Martini'], + ['#afb1b8', 'Bombay'], + ['#afbdd9', 'Pigeon Post'], + ['#b04c6a', 'Cadillac'], + ['#b05d54', 'Matrix'], + ['#b05e81', 'Tapestry'], + ['#b06608', 'Mai Tai'], + ['#b09a95', 'Del Rio'], + ['#b0e0e6', 'Powder Blue'], + ['#b0e313', 'Inch Worm'], + ['#b10000', 'Bright Red'], + ['#b14a0b', 'Vesuvius'], + ['#b1610b', 'Pumpkin Skin'], + ['#b16d52', 'Santa Fe'], + ['#b19461', 'Teak'], + ['#b1e2c1', 'Fringy Flower'], + ['#b1f4e7', 'Ice Cold'], + ['#b20931', 'Shiraz'], + ['#b2a1ea', 'Biloba Flower'], + ['#b32d29', 'Tall Poppy'], + ['#b35213', 'Fiery Orange'], + ['#b38007', 'Hot Toddy'], + ['#b3af95', 'Taupe Gray'], + ['#b3c110', 'La Rioja'], + ['#b43332', 'Well Read'], + ['#b44668', 'Blush'], + ['#b4cfd3', 'Jungle Mist'], + ['#b57281', 'Turkish Rose'], + ['#b57edc', 'Lavender'], + ['#b5a27f', 'Mongoose'], + ['#b5b35c', 'Olive Green'], + ['#b5d2ce', 'Jet Stream'], + ['#b5ecdf', 'Cruise'], + ['#b6316c', 'Hibiscus'], + ['#b69d98', 'Thatch'], + ['#b6b095', 'Heathered Gray'], + ['#b6baa4', 'Eagle'], + ['#b6d1ea', 'Spindle'], + ['#b6d3bf', 'Gum Leaf'], + ['#b7410e', 'Rust'], + ['#b78e5c', 'Muddy Waters'], + ['#b7a214', 'Sahara'], + ['#b7a458', 'Husk'], + ['#b7b1b1', 'Nobel'], + ['#b7c3d0', 'Heather'], + ['#b7f0be', 'Madang'], + ['#b81104', 'Milano Red'], + ['#b87333', 'Copper'], + ['#b8b56a', 'Gimblet'], + ['#b8c1b1', 'Green Spring'], + ['#b8c25d', 'Celery'], + ['#b8e0f9', 'Sail'], + ['#b94e48', 'Chestnut'], + ['#b95140', 'Crail'], + ['#b98d28', 'Marigold'], + ['#b9c46a', 'Wild Willow'], + ['#b9c8ac', 'Rainee'], + ['#ba0101', 'Guardsman Red'], + ['#ba450c', 'Rock Spray'], + ['#ba6f1e', 'Bourbon'], + ['#ba7f03', 'Pirate Gold'], + ['#bab1a2', 'Nomad'], + ['#bac7c9', 'Submarine'], + ['#baeef9', 'Charlotte'], + ['#bb3385', 'Medium Red Violet'], + ['#bb8983', 'Brandy Rose'], + ['#bbd009', 'Rio Grande'], + ['#bbd7c1', 'Surf'], + ['#bcc9c2', 'Powder Ash'], + ['#bd5e2e', 'Tuscany'], + ['#bd978e', 'Quicksand'], + ['#bdb1a8', 'Silk'], + ['#bdb2a1', 'Malta'], + ['#bdb3c7', 'Chatelle'], + ['#bdbbd7', 'Lavender Gray'], + ['#bdbdc6', 'French Gray'], + ['#bdc8b3', 'Clay Ash'], + ['#bdc9ce', 'Loblolly'], + ['#bdedfd', 'French Pass'], + ['#bea6c3', 'London Hue'], + ['#beb5b7', 'Pink Swan'], + ['#bede0d', 'Fuego'], + ['#bf5500', 'Rose Of Sharon'], + ['#bfb8b0', 'Tide'], + ['#bfbed8', 'Blue Haze'], + ['#bfc1c2', 'Silver Sand'], + ['#bfc921', 'Key Lime Pie'], + ['#bfdbe2', 'Ziggurat'], + ['#bfff00', 'Lime'], + ['#c02b18', 'Thunderbird'], + ['#c04737', 'Mojo'], + ['#c08081', 'Old Rose'], + ['#c0c0c0', 'Silver'], + ['#c0d3b9', 'Pale Leaf'], + ['#c0d8b6', 'Pixie Green'], + ['#c1440e', 'Tia Maria'], + ['#c154c1', 'Fuchsia Pink'], + ['#c1a004', 'Buddha Gold'], + ['#c1b7a4', 'Bison Hide'], + ['#c1bab0', 'Tea'], + ['#c1becd', 'Gray Suit'], + ['#c1d7b0', 'Sprout'], + ['#c1f07c', 'Sulu'], + ['#c26b03', 'Indochine'], + ['#c2955d', 'Twine'], + ['#c2bdb6', 'Cotton Seed'], + ['#c2cac4', 'Pumice'], + ['#c2e8e5', 'Jagged Ice'], + ['#c32148', 'Maroon Flush'], + ['#c3b091', 'Indian Khaki'], + ['#c3bfc1', 'Pale Slate'], + ['#c3c3bd', 'Gray Nickel'], + ['#c3cde6', 'Periwinkle Gray'], + ['#c3d1d1', 'Tiara'], + ['#c3ddf9', 'Tropical Blue'], + ['#c41e3a', 'Cardinal'], + ['#c45655', 'Fuzzy Wuzzy Brown'], + ['#c45719', 'Orange Roughy'], + ['#c4c4bc', 'Mist Gray'], + ['#c4d0b0', 'Coriander'], + ['#c4f4eb', 'Mint Tulip'], + ['#c54b8c', 'Mulberry'], + ['#c59922', 'Nugget'], + ['#c5994b', 'Tussock'], + ['#c5dbca', 'Sea Mist'], + ['#c5e17a', 'Yellow Green'], + ['#c62d42', 'Brick Red'], + ['#c6726b', 'Contessa'], + ['#c69191', 'Oriental Pink'], + ['#c6a84b', 'Roti'], + ['#c6c3b5', 'Ash'], + ['#c6c8bd', 'Kangaroo'], + ['#c6e610', 'Las Palmas'], + ['#c7031e', 'Monza'], + ['#c71585', 'Red Violet'], + ['#c7bca2', 'Coral Reef'], + ['#c7c1ff', 'Melrose'], + ['#c7c4bf', 'Cloud'], + ['#c7c9d5', 'Ghost'], + ['#c7cd90', 'Pine Glade'], + ['#c7dde5', 'Botticelli'], + ['#c88a65', 'Antique Brass'], + ['#c8a2c8', 'Lilac'], + ['#c8a528', 'Hokey Pokey'], + ['#c8aabf', 'Lily'], + ['#c8b568', 'Laser'], + ['#c8e3d7', 'Edgewater'], + ['#c96323', 'Piper'], + ['#c99415', 'Pizza'], + ['#c9a0dc', 'Light Wisteria'], + ['#c9b29b', 'Rodeo Dust'], + ['#c9b35b', 'Sundance'], + ['#c9b93b', 'Earls Green'], + ['#c9c0bb', 'Silver Rust'], + ['#c9d9d2', 'Conch'], + ['#c9ffa2', 'Reef'], + ['#c9ffe5', 'Aero Blue'], + ['#ca3435', 'Flush Mahogany'], + ['#cabb48', 'Turmeric'], + ['#cadcd4', 'Paris White'], + ['#cae00d', 'Bitter Lemon'], + ['#cae6da', 'Skeptic'], + ['#cb8fa9', 'Viola'], + ['#cbcab6', 'Foggy Gray'], + ['#cbd3b0', 'Green Mist'], + ['#cbdbd6', 'Nebula'], + ['#cc3333', 'Persian Red'], + ['#cc5500', 'Burnt Orange'], + ['#cc7722', 'Ochre'], + ['#cc8899', 'Puce'], + ['#cccaa8', 'Thistle Green'], + ['#ccccff', 'Periwinkle'], + ['#ccff00', 'Electric Lime'], + ['#cd5700', 'Tenn'], + ['#cd5c5c', 'Chestnut Rose'], + ['#cd8429', 'Brandy Punch'], + ['#cdf4ff', 'Onahau'], + ['#ceb98f', 'Sorrell Brown'], + ['#cebaba', 'Cold Turkey'], + ['#cec291', 'Yuma'], + ['#cec7a7', 'Chino'], + ['#cfa39d', 'Eunry'], + ['#cfb53b', 'Old Gold'], + ['#cfdccf', 'Tasman'], + ['#cfe5d2', 'Surf Crest'], + ['#cff9f3', 'Humming Bird'], + ['#cffaf4', 'Scandal'], + ['#d05f04', 'Red Stage'], + ['#d06da1', 'Hopbush'], + ['#d07d12', 'Meteor'], + ['#d0bef8', 'Perfume'], + ['#d0c0e5', 'Prelude'], + ['#d0f0c0', 'Tea Green'], + ['#d18f1b', 'Geebung'], + ['#d1bea8', 'Vanilla'], + ['#d1c6b4', 'Soft Amber'], + ['#d1d2ca', 'Celeste'], + ['#d1d2dd', 'Mischka'], + ['#d1e231', 'Pear'], + ['#d2691e', 'Hot Cinnamon'], + ['#d27d46', 'Raw Sienna'], + ['#d29eaa', 'Careys Pink'], + ['#d2b48c', 'Tan'], + ['#d2da97', 'Deco'], + ['#d2f6de', 'Blue Romance'], + ['#d2f8b0', 'Gossip'], + ['#d3cbba', 'Sisal'], + ['#d3cdc5', 'Swirl'], + ['#d47494', 'Charm'], + ['#d4b6af', 'Clam Shell'], + ['#d4bf8d', 'Straw'], + ['#d4c4a8', 'Akaroa'], + ['#d4cd16', 'Bird Flower'], + ['#d4d7d9', 'Iron'], + ['#d4dfe2', 'Geyser'], + ['#d4e2fc', 'Hawkes Blue'], + ['#d54600', 'Grenadier'], + ['#d591a4', 'Can Can'], + ['#d59a6f', 'Whiskey'], + ['#d5d195', 'Winter Hazel'], + ['#d5f6e3', 'Granny Apple'], + ['#d69188', 'My Pink'], + ['#d6c562', 'Tacha'], + ['#d6cef6', 'Moon Raker'], + ['#d6d6d1', 'Quill Gray'], + ['#d6ffdb', 'Snowy Mint'], + ['#d7837f', 'New York Pink'], + ['#d7c498', 'Pavlova'], + ['#d7d0ff', 'Fog'], + ['#d84437', 'Valencia'], + ['#d87c63', 'Japonica'], + ['#d8bfd8', 'Thistle'], + ['#d8c2d5', 'Maverick'], + ['#d8fcfa', 'Foam'], + ['#d94972', 'Cabaret'], + ['#d99376', 'Burning Sand'], + ['#d9b99b', 'Cameo'], + ['#d9d6cf', 'Timberwolf'], + ['#d9dcc1', 'Tana'], + ['#d9e4f5', 'Link Water'], + ['#d9f7ff', 'Mabel'], + ['#da3287', 'Cerise'], + ['#da5b38', 'Flame Pea'], + ['#da6304', 'Bamboo'], + ['#da6a41', 'Red Damask'], + ['#da70d6', 'Orchid'], + ['#da8a67', 'Copperfield'], + ['#daa520', 'Golden Grass'], + ['#daecd6', 'Zanah'], + ['#daf4f0', 'Iceberg'], + ['#dafaff', 'Oyster Bay'], + ['#db5079', 'Cranberry'], + ['#db9690', 'Petite Orchid'], + ['#db995e', 'Di Serria'], + ['#dbdbdb', 'Alto'], + ['#dbfff8', 'Frosted Mint'], + ['#dc143c', 'Crimson'], + ['#dc4333', 'Punch'], + ['#dcb20c', 'Galliano'], + ['#dcb4bc', 'Blossom'], + ['#dcd747', 'Wattle'], + ['#dcd9d2', 'Westar'], + ['#dcddcc', 'Moon Mist'], + ['#dcedb4', 'Caper'], + ['#dcf0ea', 'Swans Down'], + ['#ddd6d5', 'Swiss Coffee'], + ['#ddf9f1', 'White Ice'], + ['#de3163', 'Cerise Red'], + ['#de6360', 'Roman'], + ['#dea681', 'Tumbleweed'], + ['#deba13', 'Gold Tips'], + ['#dec196', 'Brandy'], + ['#decbc6', 'Wafer'], + ['#ded4a4', 'Sapling'], + ['#ded717', 'Barberry'], + ['#dee5c0', 'Beryl Green'], + ['#def5ff', 'Pattens Blue'], + ['#df73ff', 'Heliotrope'], + ['#dfbe6f', 'Apache'], + ['#dfcd6f', 'Chenin'], + ['#dfcfdb', 'Lola'], + ['#dfecda', 'Willow Brook'], + ['#dfff00', 'Chartreuse Yellow'], + ['#e0b0ff', 'Mauve'], + ['#e0b646', 'Anzac'], + ['#e0b974', 'Harvest Gold'], + ['#e0c095', 'Calico'], + ['#e0ffff', 'Baby Blue'], + ['#e16865', 'Sunglo'], + ['#e1bc64', 'Equator'], + ['#e1c0c8', 'Pink Flare'], + ['#e1e6d6', 'Periglacial Blue'], + ['#e1ead4', 'Kidnapper'], + ['#e1f6e8', 'Tara'], + ['#e25465', 'Mandy'], + ['#e2725b', 'Terracotta'], + ['#e28913', 'Golden Bell'], + ['#e292c0', 'Shocking'], + ['#e29418', 'Dixie'], + ['#e29cd2', 'Light Orchid'], + ['#e2d8ed', 'Snuff'], + ['#e2ebed', 'Mystic'], + ['#e2f3ec', 'Apple Green'], + ['#e30b5c', 'Razzmatazz'], + ['#e32636', 'Alizarin Crimson'], + ['#e34234', 'Cinnabar'], + ['#e3bebe', 'Cavern Pink'], + ['#e3f5e1', 'Peppermint'], + ['#e3f988', 'Mindaro'], + ['#e47698', 'Deep Blush'], + ['#e49b0f', 'Gamboge'], + ['#e4c2d5', 'Melanie'], + ['#e4cfde', 'Twilight'], + ['#e4d1c0', 'Bone'], + ['#e4d422', 'Sunflower'], + ['#e4d5b7', 'Grain Brown'], + ['#e4d69b', 'Zombie'], + ['#e4f6e7', 'Frostee'], + ['#e4ffd1', 'Snow Flurry'], + ['#e52b50', 'Amaranth'], + ['#e5841b', 'Zest'], + ['#e5ccc9', 'Dust Storm'], + ['#e5d7bd', 'Stark White'], + ['#e5d8af', 'Hampton'], + ['#e5e0e1', 'Bon Jour'], + ['#e5e5e5', 'Mercury'], + ['#e5f9f6', 'Polar'], + ['#e64e03', 'Trinidad'], + ['#e6be8a', 'Gold Sand'], + ['#e6bea5', 'Cashmere'], + ['#e6d7b9', 'Double Spanish White'], + ['#e6e4d4', 'Satin Linen'], + ['#e6f2ea', 'Harp'], + ['#e6f8f3', 'Off Green'], + ['#e6ffe9', 'Hint Of Green'], + ['#e6ffff', 'Tranquil'], + ['#e77200', 'Mango Tango'], + ['#e7730a', 'Christine'], + ['#e79f8c', 'Tonys Pink'], + ['#e79fc4', 'Kobi'], + ['#e7bcb4', 'Rose Fog'], + ['#e7bf05', 'Corn'], + ['#e7cd8c', 'Putty'], + ['#e7ece6', 'Gray Nurse'], + ['#e7f8ff', 'Lily White'], + ['#e7feff', 'Bubbles'], + ['#e89928', 'Fire Bush'], + ['#e8b9b3', 'Shilo'], + ['#e8e0d5', 'Pearl Bush'], + ['#e8ebe0', 'Green White'], + ['#e8f1d4', 'Chrome White'], + ['#e8f2eb', 'Gin'], + ['#e8f5f2', 'Aqua Squeeze'], + ['#e96e00', 'Clementine'], + ['#e97451', 'Burnt Sienna'], + ['#e97c07', 'Tahiti Gold'], + ['#e9cecd', 'Oyster Pink'], + ['#e9d75a', 'Confetti'], + ['#e9e3e3', 'Ebb'], + ['#e9f8ed', 'Ottoman'], + ['#e9fffd', 'Clear Day'], + ['#ea88a8', 'Carissma'], + ['#eaae69', 'Porsche'], + ['#eab33b', 'Tulip Tree'], + ['#eac674', 'Rob Roy'], + ['#eadab8', 'Raffia'], + ['#eae8d4', 'White Rock'], + ['#eaf6ee', 'Panache'], + ['#eaf6ff', 'Solitude'], + ['#eaf9f5', 'Aqua Spring'], + ['#eafffe', 'Dew'], + ['#eb9373', 'Apricot'], + ['#ebc2af', 'Zinnwaldite'], + ['#eca927', 'Fuel Yellow'], + ['#ecc54e', 'Ronchi'], + ['#ecc7ee', 'French Lilac'], + ['#eccdb9', 'Just Right'], + ['#ece090', 'Wild Rice'], + ['#ecebbd', 'Fall Green'], + ['#ecebce', 'Aths Special'], + ['#ecf245', 'Starship'], + ['#ed0a3f', 'Red Ribbon'], + ['#ed7a1c', 'Tango'], + ['#ed9121', 'Carrot Orange'], + ['#ed989e', 'Sea Pink'], + ['#edb381', 'Tacao'], + ['#edc9af', 'Desert Sand'], + ['#edcdab', 'Pancho'], + ['#eddcb1', 'Chamois'], + ['#edea99', 'Primrose'], + ['#edf5dd', 'Frost'], + ['#edf5f5', 'Aqua Haze'], + ['#edf6ff', 'Zumthor'], + ['#edf9f1', 'Narvik'], + ['#edfc84', 'Honeysuckle'], + ['#ee82ee', 'Lavender Magenta'], + ['#eec1be', 'Beauty Bush'], + ['#eed794', 'Chalky'], + ['#eed9c4', 'Almond'], + ['#eedc82', 'Flax'], + ['#eededa', 'Bizarre'], + ['#eee3ad', 'Double Colonial White'], + ['#eeeee8', 'Cararra'], + ['#eeef78', 'Manz'], + ['#eef0c8', 'Tahuna Sands'], + ['#eef0f3', 'Athens Gray'], + ['#eef3c3', 'Tusk'], + ['#eef4de', 'Loafer'], + ['#eef6f7', 'Catskill White'], + ['#eefdff', 'Twilight Blue'], + ['#eeff9a', 'Jonquil'], + ['#eeffe2', 'Rice Flower'], + ['#ef863f', 'Jaffa'], + ['#efefef', 'Gallery'], + ['#eff2f3', 'Porcelain'], + ['#f091a9', 'Mauvelous'], + ['#f0d52d', 'Golden Dream'], + ['#f0db7d', 'Golden Sand'], + ['#f0dc82', 'Buff'], + ['#f0e2ec', 'Prim'], + ['#f0e68c', 'Khaki'], + ['#f0eefd', 'Selago'], + ['#f0eeff', 'Titan White'], + ['#f0f8ff', 'Alice Blue'], + ['#f0fcea', 'Feta'], + ['#f18200', 'Gold Drop'], + ['#f19bab', 'Wewak'], + ['#f1e788', 'Sahara Sand'], + ['#f1e9d2', 'Parchment'], + ['#f1e9ff', 'Blue Chalk'], + ['#f1eec1', 'Mint Julep'], + ['#f1f1f1', 'Seashell'], + ['#f1f7f2', 'Saltpan'], + ['#f1ffad', 'Tidal'], + ['#f1ffc8', 'Chiffon'], + ['#f2552a', 'Flamingo'], + ['#f28500', 'Tangerine'], + ['#f2c3b2', 'Mandys Pink'], + ['#f2f2f2', 'Concrete'], + ['#f2fafa', 'Black Squeeze'], + ['#f34723', 'Pomegranate'], + ['#f3ad16', 'Buttercup'], + ['#f3d69d', 'New Orleans'], + ['#f3d9df', 'Vanilla Ice'], + ['#f3e7bb', 'Sidecar'], + ['#f3e9e5', 'Dawn Pink'], + ['#f3edcf', 'Wheatfield'], + ['#f3fb62', 'Canary'], + ['#f3fbd4', 'Orinoco'], + ['#f3ffd8', 'Carla'], + ['#f400a1', 'Hollywood Cerise'], + ['#f4a460', 'Sandy brown'], + ['#f4c430', 'Saffron'], + ['#f4d81c', 'Ripe Lemon'], + ['#f4ebd3', 'Janna'], + ['#f4f2ee', 'Pampas'], + ['#f4f4f4', 'Wild Sand'], + ['#f4f8ff', 'Zircon'], + ['#f57584', 'Froly'], + ['#f5c85c', 'Cream Can'], + ['#f5c999', 'Manhattan'], + ['#f5d5a0', 'Maize'], + ['#f5deb3', 'Wheat'], + ['#f5e7a2', 'Sandwisp'], + ['#f5e7e2', 'Pot Pourri'], + ['#f5e9d3', 'Albescent White'], + ['#f5edef', 'Soft Peach'], + ['#f5f3e5', 'Ecru White'], + ['#f5f5dc', 'Beige'], + ['#f5fb3d', 'Golden Fizz'], + ['#f5ffbe', 'Australian Mint'], + ['#f64a8a', 'French Rose'], + ['#f653a6', 'Brilliant Rose'], + ['#f6a4c9', 'Illusion'], + ['#f6f0e6', 'Merino'], + ['#f6f7f7', 'Black Haze'], + ['#f6ffdc', 'Spring Sun'], + ['#f7468a', 'Violet Red'], + ['#f77703', 'Chilean Fire'], + ['#f77fbe', 'Persian Pink'], + ['#f7b668', 'Rajah'], + ['#f7c8da', 'Azalea'], + ['#f7dbe6', 'We Peep'], + ['#f7f2e1', 'Quarter Spanish White'], + ['#f7f5fa', 'Whisper'], + ['#f7faf7', 'Snow Drift'], + ['#f8b853', 'Casablanca'], + ['#f8c3df', 'Chantilly'], + ['#f8d9e9', 'Cherub'], + ['#f8db9d', 'Marzipan'], + ['#f8dd5c', 'Energy Yellow'], + ['#f8e4bf', 'Givry'], + ['#f8f0e8', 'White Linen'], + ['#f8f4ff', 'Magnolia'], + ['#f8f6f1', 'Spring Wood'], + ['#f8f7dc', 'Coconut Cream'], + ['#f8f7fc', 'White Lilac'], + ['#f8f8f7', 'Desert Storm'], + ['#f8f99c', 'Texas'], + ['#f8facd', 'Corn Field'], + ['#f8fdd3', 'Mimosa'], + ['#f95a61', 'Carnation'], + ['#f9bf58', 'Saffron Mango'], + ['#f9e0ed', 'Carousel Pink'], + ['#f9e4bc', 'Dairy Cream'], + ['#f9e663', 'Portica'], + ['#f9eaf3', 'Amour'], + ['#f9f8e4', 'Rum Swizzle'], + ['#f9ff8b', 'Dolly'], + ['#f9fff6', 'Sugar Cane'], + ['#fa7814', 'Ecstasy'], + ['#fa9d5a', 'Tan Hide'], + ['#fad3a2', 'Corvette'], + ['#fadfad', 'Peach Yellow'], + ['#fae600', 'Turbo'], + ['#faeab9', 'Astra'], + ['#faeccc', 'Champagne'], + ['#faf0e6', 'Linen'], + ['#faf3f0', 'Fantasy'], + ['#faf7d6', 'Citrine White'], + ['#fafafa', 'Alabaster'], + ['#fafde4', 'Hint Of Yellow'], + ['#faffa4', 'Milan'], + ['#fb607f', 'Brink Pink'], + ['#fb8989', 'Geraldine'], + ['#fba0e3', 'Lavender Rose'], + ['#fba129', 'Sea Buckthorn'], + ['#fbac13', 'Sun'], + ['#fbaed2', 'Lavender Pink'], + ['#fbb2a3', 'Rose Bud'], + ['#fbbeda', 'Cupid'], + ['#fbcce7', 'Classic Rose'], + ['#fbceb1', 'Apricot Peach'], + ['#fbe7b2', 'Banana Mania'], + ['#fbe870', 'Marigold Yellow'], + ['#fbe96c', 'Festival'], + ['#fbea8c', 'Sweet Corn'], + ['#fbec5d', 'Candy Corn'], + ['#fbf9f9', 'Hint Of Red'], + ['#fbffba', 'Shalimar'], + ['#fc0fc0', 'Shocking Pink'], + ['#fc80a5', 'Tickle Me Pink'], + ['#fc9c1d', 'Tree Poppy'], + ['#fcc01e', 'Lightning Yellow'], + ['#fcd667', 'Goldenrod'], + ['#fcd917', 'Candlelight'], + ['#fcda98', 'Cherokee'], + ['#fcf4d0', 'Double Pearl Lusta'], + ['#fcf4dc', 'Pearl Lusta'], + ['#fcf8f7', 'Vista White'], + ['#fcfbf3', 'Bianca'], + ['#fcfeda', 'Moon Glow'], + ['#fcffe7', 'China Ivory'], + ['#fcfff9', 'Ceramic'], + ['#fd0e35', 'Torch Red'], + ['#fd5b78', 'Wild Watermelon'], + ['#fd7b33', 'Crusta'], + ['#fd7c07', 'Sorbus'], + ['#fd9fa2', 'Sweet Pink'], + ['#fdd5b1', 'Light Apricot'], + ['#fdd7e4', 'Pig Pink'], + ['#fde1dc', 'Cinderella'], + ['#fde295', 'Golden Glow'], + ['#fde910', 'Lemon'], + ['#fdf5e6', 'Old Lace'], + ['#fdf6d3', 'Half Colonial White'], + ['#fdf7ad', 'Drover'], + ['#fdfeb8', 'Pale Prim'], + ['#fdffd5', 'Cumulus'], + ['#fe28a2', 'Persian Rose'], + ['#fe4c40', 'Sunset Orange'], + ['#fe6f5e', 'Bittersweet'], + ['#fe9d04', 'California'], + ['#fea904', 'Yellow Sea'], + ['#febaad', 'Melon'], + ['#fed33c', 'Bright Sun'], + ['#fed85d', 'Dandelion'], + ['#fedb8d', 'Salomie'], + ['#fee5ac', 'Cape Honey'], + ['#feebf3', 'Remy'], + ['#feefce', 'Oasis'], + ['#fef0ec', 'Bridesmaid'], + ['#fef2c7', 'Beeswax'], + ['#fef3d8', 'Bleach White'], + ['#fef4cc', 'Pipi'], + ['#fef4db', 'Half Spanish White'], + ['#fef4f8', 'Wisp Pink'], + ['#fef5f1', 'Provincial Pink'], + ['#fef7de', 'Half Dutch White'], + ['#fef8e2', 'Solitaire'], + ['#fef8ff', 'White Pointer'], + ['#fef9e3', 'Off Yellow'], + ['#fefced', 'Orange White'], + ['#ff0000', 'Red'], + ['#ff007f', 'Rose'], + ['#ff00cc', 'Purple Pizzazz'], + ['#ff00ff', 'Magenta Fuchsia'], + ['#ff2400', 'Scarlet'], + ['#ff3399', 'Wild Strawberry'], + ['#ff33cc', 'Razzle Dazzle Rose'], + ['#ff355e', 'Radical Red'], + ['#ff3f34', 'Red Orange'], + ['#ff4040', 'Coral Red'], + ['#ff4d00', 'Vermilion'], + ['#ff4f00', 'International Orange'], + ['#ff6037', 'Outrageous Orange'], + ['#ff6600', 'Blaze Orange'], + ['#ff66ff', 'Pink Flamingo'], + ['#ff681f', 'Orange'], + ['#ff69b4', 'Hot Pink'], + ['#ff6b53', 'Persimmon'], + ['#ff6fff', 'Blush Pink'], + ['#ff7034', 'Burning Orange'], + ['#ff7518', 'Pumpkin'], + ['#ff7d07', 'Flamenco'], + ['#ff7f00', 'Flush Orange'], + ['#ff7f50', 'Coral'], + ['#ff8c69', 'Salmon'], + ['#ff9000', 'Pizazz'], + ['#ff910f', 'West Side'], + ['#ff91a4', 'Pink Salmon'], + ['#ff9933', 'Neon Carrot'], + ['#ff9966', 'Atomic Tangerine'], + ['#ff9980', 'Vivid Tangerine'], + ['#ff9e2c', 'Sunshade'], + ['#ffa000', 'Orange Peel'], + ['#ffa194', 'Mona Lisa'], + ['#ffa500', 'Web Orange'], + ['#ffa6c9', 'Carnation Pink'], + ['#ffab81', 'Hit Pink'], + ['#ffae42', 'Yellow Orange'], + ['#ffb0ac', 'Cornflower Lilac'], + ['#ffb1b3', 'Sundown'], + ['#ffb31f', 'My Sin'], + ['#ffb555', 'Texas Rose'], + ['#ffb7d5', 'Cotton Candy'], + ['#ffb97b', 'Macaroni And Cheese'], + ['#ffba00', 'Selective Yellow'], + ['#ffbd5f', 'Koromiko'], + ['#ffbf00', 'Amber'], + ['#ffc0a8', 'Wax Flower'], + ['#ffc0cb', 'Pink'], + ['#ffc3c0', 'Your Pink'], + ['#ffc901', 'Supernova'], + ['#ffcba4', 'Flesh'], + ['#ffcc33', 'Sunglow'], + ['#ffcc5c', 'Golden Tainoi'], + ['#ffcc99', 'Peach Orange'], + ['#ffcd8c', 'Chardonnay'], + ['#ffd1dc', 'Pastel Pink'], + ['#ffd2b7', 'Romantic'], + ['#ffd38c', 'Grandis'], + ['#ffd700', 'Gold'], + ['#ffd800', 'School Bus Yellow'], + ['#ffd8d9', 'Cosmos'], + ['#ffdb58', 'Mustard'], + ['#ffdcd6', 'Peach Schnapps'], + ['#ffddaf', 'Caramel'], + ['#ffddcd', 'Tuft Bush'], + ['#ffddcf', 'Watusi'], + ['#ffddf4', 'Pink Lace'], + ['#ffdead', 'Navajo White'], + ['#ffdeb3', 'Frangipani'], + ['#ffe1df', 'Pippin'], + ['#ffe1f2', 'Pale Rose'], + ['#ffe2c5', 'Negroni'], + ['#ffe5a0', 'Cream Brulee'], + ['#ffe5b4', 'Peach'], + ['#ffe6c7', 'Tequila'], + ['#ffe772', 'Kournikova'], + ['#ffeac8', 'Sandy Beach'], + ['#ffead4', 'Karry'], + ['#ffec13', 'Broom'], + ['#ffedbc', 'Colonial White'], + ['#ffeed8', 'Derby'], + ['#ffefa1', 'Vis Vis'], + ['#ffefc1', 'Egg White'], + ['#ffefd5', 'Papaya Whip'], + ['#ffefec', 'Fair Pink'], + ['#fff0db', 'Peach Cream'], + ['#fff0f5', 'Lavender Blush'], + ['#fff14f', 'Gorse'], + ['#fff1b5', 'Buttermilk'], + ['#fff1d8', 'Pink Lady'], + ['#fff1ee', 'Forget Me Not'], + ['#fff1f9', 'Tutu'], + ['#fff39d', 'Picasso'], + ['#fff3f1', 'Chardon'], + ['#fff46e', 'Paris Daisy'], + ['#fff4ce', 'Barley White'], + ['#fff4dd', 'Egg Sour'], + ['#fff4e0', 'Sazerac'], + ['#fff4e8', 'Serenade'], + ['#fff4f3', 'Chablis'], + ['#fff5ee', 'Seashell Peach'], + ['#fff5f3', 'Sauvignon'], + ['#fff6d4', 'Milk Punch'], + ['#fff6df', 'Varden'], + ['#fff6f5', 'Rose White'], + ['#fff8d1', 'Baja White'], + ['#fff9e2', 'Gin Fizz'], + ['#fff9e6', 'Early Dawn'], + ['#fffacd', 'Lemon Chiffon'], + ['#fffaf4', 'Bridal Heath'], + ['#fffbdc', 'Scotch Mist'], + ['#fffbf9', 'Soapstone'], + ['#fffc99', 'Witch Haze'], + ['#fffcea', 'Buttery White'], + ['#fffcee', 'Island Spice'], + ['#fffdd0', 'Cream'], + ['#fffde6', 'Chilean Heath'], + ['#fffde8', 'Travertine'], + ['#fffdf3', 'Orchid White'], + ['#fffdf4', 'Quarter Pearl Lusta'], + ['#fffee1', 'Half And Half'], + ['#fffeec', 'Apricot White'], + ['#fffef0', 'Rice Cake'], + ['#fffef6', 'Black White'], + ['#fffefd', 'Romance'], + ['#ffff00', 'Yellow'], + ['#ffff66', 'Laser Lemon'], + ['#ffff99', 'Pale Canary'], + ['#ffffb4', 'Portafino'], + ['#fffff0', 'Ivory'], + ['#ffffff', 'White'] +]; + +/** + * Map Of hex color values to color names + * + * - key: hex value + * - value: color name + */ +export const colorNameMap = colorNames.reduce>((acc, [hex, name]) => { + acc[hex] = name; + return acc; +}, {}); diff --git a/packages/color/src/constant/palette.ts b/packages/color/src/constant/palette.ts new file mode 100644 index 0000000..9f62664 --- /dev/null +++ b/packages/color/src/constant/palette.ts @@ -0,0 +1,356 @@ +import type { ColorPaletteFamily } from '../types'; + +export const colorPalettes: ColorPaletteFamily[] = [ + { + name: 'Slate', + palettes: [ + { hex: '#f8fafc', number: 50 }, + { hex: '#f1f5f9', number: 100 }, + { hex: '#e2e8f0', number: 200 }, + { hex: '#cbd5e1', number: 300 }, + { hex: '#94a3b8', number: 400 }, + { hex: '#64748b', number: 500 }, + { hex: '#475569', number: 600 }, + { hex: '#334155', number: 700 }, + { hex: '#1e293b', number: 800 }, + { hex: '#0f172a', number: 900 }, + { hex: '#020617', number: 950 } + ] + }, + { + name: 'Gray', + palettes: [ + { hex: '#f9fafb', number: 50 }, + { hex: '#f3f4f6', number: 100 }, + { hex: '#e5e7eb', number: 200 }, + { hex: '#d1d5db', number: 300 }, + { hex: '#9ca3af', number: 400 }, + { hex: '#6b7280', number: 500 }, + { hex: '#4b5563', number: 600 }, + { hex: '#374151', number: 700 }, + { hex: '#1f2937', number: 800 }, + { hex: '#111827', number: 900 }, + { hex: '#030712', number: 950 } + ] + }, + { + name: 'Zinc', + palettes: [ + { hex: '#fafafa', number: 50 }, + { hex: '#f4f4f5', number: 100 }, + { hex: '#e4e4e7', number: 200 }, + { hex: '#d4d4d8', number: 300 }, + { hex: '#a1a1aa', number: 400 }, + { hex: '#71717a', number: 500 }, + { hex: '#52525b', number: 600 }, + { hex: '#3f3f46', number: 700 }, + { hex: '#27272a', number: 800 }, + { hex: '#18181b', number: 900 }, + { hex: '#09090b', number: 950 } + ] + }, + { + name: 'Neutral', + palettes: [ + { hex: '#fafafa', number: 50 }, + { hex: '#f5f5f5', number: 100 }, + { hex: '#e5e5e5', number: 200 }, + { hex: '#d4d4d4', number: 300 }, + { hex: '#a3a3a3', number: 400 }, + { hex: '#737373', number: 500 }, + { hex: '#525252', number: 600 }, + { hex: '#404040', number: 700 }, + { hex: '#262626', number: 800 }, + { hex: '#171717', number: 900 }, + { hex: '#0a0a0a', number: 950 } + ] + }, + { + name: 'Stone', + palettes: [ + { hex: '#fafaf9', number: 50 }, + { hex: '#f5f5f4', number: 100 }, + { hex: '#e7e5e4', number: 200 }, + { hex: '#d6d3d1', number: 300 }, + { hex: '#a8a29e', number: 400 }, + { hex: '#78716c', number: 500 }, + { hex: '#57534e', number: 600 }, + { hex: '#44403c', number: 700 }, + { hex: '#292524', number: 800 }, + { hex: '#1c1917', number: 900 }, + { hex: '#0c0a09', number: 950 } + ] + }, + { + name: 'Red', + palettes: [ + { hex: '#fef2f2', number: 50 }, + { hex: '#fee2e2', number: 100 }, + { hex: '#fecaca', number: 200 }, + { hex: '#fca5a5', number: 300 }, + { hex: '#f87171', number: 400 }, + { hex: '#ef4444', number: 500 }, + { hex: '#dc2626', number: 600 }, + { hex: '#b91c1c', number: 700 }, + { hex: '#991b1b', number: 800 }, + { hex: '#7f1d1d', number: 900 }, + { hex: '#450a0a', number: 950 } + ] + }, + { + name: 'Orange', + palettes: [ + { hex: '#fff7ed', number: 50 }, + { hex: '#ffedd5', number: 100 }, + { hex: '#fed7aa', number: 200 }, + { hex: '#fdba74', number: 300 }, + { hex: '#fb923c', number: 400 }, + { hex: '#f97316', number: 500 }, + { hex: '#ea580c', number: 600 }, + { hex: '#c2410c', number: 700 }, + { hex: '#9a3412', number: 800 }, + { hex: '#7c2d12', number: 900 }, + { hex: '#431407', number: 950 } + ] + }, + { + name: 'Amber', + palettes: [ + { hex: '#fffbeb', number: 50 }, + { hex: '#fef3c7', number: 100 }, + { hex: '#fde68a', number: 200 }, + { hex: '#fcd34d', number: 300 }, + { hex: '#fbbf24', number: 400 }, + { hex: '#f59e0b', number: 500 }, + { hex: '#d97706', number: 600 }, + { hex: '#b45309', number: 700 }, + { hex: '#92400e', number: 800 }, + { hex: '#78350f', number: 900 }, + { hex: '#451a03', number: 950 } + ] + }, + { + name: 'Yellow', + palettes: [ + { hex: '#fefce8', number: 50 }, + { hex: '#fef9c3', number: 100 }, + { hex: '#fef08a', number: 200 }, + { hex: '#fde047', number: 300 }, + { hex: '#facc15', number: 400 }, + { hex: '#eab308', number: 500 }, + { hex: '#ca8a04', number: 600 }, + { hex: '#a16207', number: 700 }, + { hex: '#854d0e', number: 800 }, + { hex: '#713f12', number: 900 }, + { hex: '#422006', number: 950 } + ] + }, + { + name: 'Lime', + palettes: [ + { hex: '#f7fee7', number: 50 }, + { hex: '#ecfccb', number: 100 }, + { hex: '#d9f99d', number: 200 }, + { hex: '#bef264', number: 300 }, + { hex: '#a3e635', number: 400 }, + { hex: '#84cc16', number: 500 }, + { hex: '#65a30d', number: 600 }, + { hex: '#4d7c0f', number: 700 }, + { hex: '#3f6212', number: 800 }, + { hex: '#365314', number: 900 }, + { hex: '#1a2e05', number: 950 } + ] + }, + { + name: 'Green', + palettes: [ + { hex: '#f0fdf4', number: 50 }, + { hex: '#dcfce7', number: 100 }, + { hex: '#bbf7d0', number: 200 }, + { hex: '#86efac', number: 300 }, + { hex: '#4ade80', number: 400 }, + { hex: '#22c55e', number: 500 }, + { hex: '#16a34a', number: 600 }, + { hex: '#15803d', number: 700 }, + { hex: '#166534', number: 800 }, + { hex: '#14532d', number: 900 }, + { hex: '#052e16', number: 950 } + ] + }, + { + name: 'Emerald', + palettes: [ + { hex: '#ecfdf5', number: 50 }, + { hex: '#d1fae5', number: 100 }, + { hex: '#a7f3d0', number: 200 }, + { hex: '#6ee7b7', number: 300 }, + { hex: '#34d399', number: 400 }, + { hex: '#10b981', number: 500 }, + { hex: '#059669', number: 600 }, + { hex: '#047857', number: 700 }, + { hex: '#065f46', number: 800 }, + { hex: '#064e3b', number: 900 }, + { hex: '#022c22', number: 950 } + ] + }, + { + name: 'Teal', + palettes: [ + { hex: '#f0fdfa', number: 50 }, + { hex: '#ccfbf1', number: 100 }, + { hex: '#99f6e4', number: 200 }, + { hex: '#5eead4', number: 300 }, + { hex: '#2dd4bf', number: 400 }, + { hex: '#14b8a6', number: 500 }, + { hex: '#0d9488', number: 600 }, + { hex: '#0f766e', number: 700 }, + { hex: '#115e59', number: 800 }, + { hex: '#134e4a', number: 900 }, + { hex: '#042f2e', number: 950 } + ] + }, + { + name: 'Cyan', + palettes: [ + { hex: '#ecfeff', number: 50 }, + { hex: '#cffafe', number: 100 }, + { hex: '#a5f3fc', number: 200 }, + { hex: '#67e8f9', number: 300 }, + { hex: '#22d3ee', number: 400 }, + { hex: '#06b6d4', number: 500 }, + { hex: '#0891b2', number: 600 }, + { hex: '#0e7490', number: 700 }, + { hex: '#155e75', number: 800 }, + { hex: '#164e63', number: 900 }, + { hex: '#083344', number: 950 } + ] + }, + { + name: 'Sky', + palettes: [ + { hex: '#f0f9ff', number: 50 }, + { hex: '#e0f2fe', number: 100 }, + { hex: '#bae6fd', number: 200 }, + { hex: '#7dd3fc', number: 300 }, + { hex: '#38bdf8', number: 400 }, + { hex: '#0ea5e9', number: 500 }, + { hex: '#0284c7', number: 600 }, + { hex: '#0369a1', number: 700 }, + { hex: '#075985', number: 800 }, + { hex: '#0c4a6e', number: 900 }, + { hex: '#082f49', number: 950 } + ] + }, + { + name: 'Blue', + palettes: [ + { hex: '#eff6ff', number: 50 }, + { hex: '#dbeafe', number: 100 }, + { hex: '#bfdbfe', number: 200 }, + { hex: '#93c5fd', number: 300 }, + { hex: '#60a5fa', number: 400 }, + { hex: '#3b82f6', number: 500 }, + { hex: '#2563eb', number: 600 }, + { hex: '#1d4ed8', number: 700 }, + { hex: '#1e40af', number: 800 }, + { hex: '#1e3a8a', number: 900 }, + { hex: '#172554', number: 950 } + ] + }, + { + name: 'Indigo', + palettes: [ + { hex: '#eef2ff', number: 50 }, + { hex: '#e0e7ff', number: 100 }, + { hex: '#c7d2fe', number: 200 }, + { hex: '#a5b4fc', number: 300 }, + { hex: '#818cf8', number: 400 }, + { hex: '#6366f1', number: 500 }, + { hex: '#4f46e5', number: 600 }, + { hex: '#4338ca', number: 700 }, + { hex: '#3730a3', number: 800 }, + { hex: '#312e81', number: 900 }, + { hex: '#1e1b4b', number: 950 } + ] + }, + { + name: 'Violet', + palettes: [ + { hex: '#f5f3ff', number: 50 }, + { hex: '#ede9fe', number: 100 }, + { hex: '#ddd6fe', number: 200 }, + { hex: '#c4b5fd', number: 300 }, + { hex: '#a78bfa', number: 400 }, + { hex: '#8b5cf6', number: 500 }, + { hex: '#7c3aed', number: 600 }, + { hex: '#6d28d9', number: 700 }, + { hex: '#5b21b6', number: 800 }, + { hex: '#4c1d95', number: 900 }, + { hex: '#2e1065', number: 950 } + ] + }, + { + name: 'Purple', + palettes: [ + { hex: '#faf5ff', number: 50 }, + { hex: '#f3e8ff', number: 100 }, + { hex: '#e9d5ff', number: 200 }, + { hex: '#d8b4fe', number: 300 }, + { hex: '#c084fc', number: 400 }, + { hex: '#a855f7', number: 500 }, + { hex: '#9333ea', number: 600 }, + { hex: '#7e22ce', number: 700 }, + { hex: '#6b21a8', number: 800 }, + { hex: '#581c87', number: 900 }, + { hex: '#3b0764', number: 950 } + ] + }, + { + name: 'Fuchsia', + palettes: [ + { hex: '#fdf4ff', number: 50 }, + { hex: '#fae8ff', number: 100 }, + { hex: '#f5d0fe', number: 200 }, + { hex: '#f0abfc', number: 300 }, + { hex: '#e879f9', number: 400 }, + { hex: '#d946ef', number: 500 }, + { hex: '#c026d3', number: 600 }, + { hex: '#a21caf', number: 700 }, + { hex: '#86198f', number: 800 }, + { hex: '#701a75', number: 900 }, + { hex: '#4a044e', number: 950 } + ] + }, + { + name: 'Pink', + palettes: [ + { hex: '#fdf2f8', number: 50 }, + { hex: '#fce7f3', number: 100 }, + { hex: '#fbcfe8', number: 200 }, + { hex: '#f9a8d4', number: 300 }, + { hex: '#f472b6', number: 400 }, + { hex: '#ec4899', number: 500 }, + { hex: '#db2777', number: 600 }, + { hex: '#be185d', number: 700 }, + { hex: '#9d174d', number: 800 }, + { hex: '#831843', number: 900 }, + { hex: '#500724', number: 950 } + ] + }, + { + name: 'Rose', + palettes: [ + { hex: '#fff1f2', number: 50 }, + { hex: '#ffe4e6', number: 100 }, + { hex: '#fecdd3', number: 200 }, + { hex: '#fda4af', number: 300 }, + { hex: '#fb7185', number: 400 }, + { hex: '#f43f5e', number: 500 }, + { hex: '#e11d48', number: 600 }, + { hex: '#be123c', number: 700 }, + { hex: '#9f1239', number: 800 }, + { hex: '#881337', number: 900 }, + { hex: '#4c0519', number: 950 } + ] + } +]; diff --git a/packages/color/src/index.ts b/packages/color/src/index.ts new file mode 100644 index 0000000..42a4d54 --- /dev/null +++ b/packages/color/src/index.ts @@ -0,0 +1,7 @@ +import { colorPalettes } from './constant'; + +export * from './palette'; +export * from './shared'; +export { colorPalettes }; + +export * from './types'; diff --git a/packages/color/src/palette/antd.ts b/packages/color/src/palette/antd.ts new file mode 100644 index 0000000..c3d5b48 --- /dev/null +++ b/packages/color/src/palette/antd.ts @@ -0,0 +1,176 @@ +import type { AnyColor, HsvColor } from 'colord'; +import { getHex, getHsv, isValidColor, mixColor } from '../shared'; +import type { ColorIndex } from '../types'; + +/** Hue step */ +const hueStep = 2; +/** Saturation step, light color part */ +const saturationStep = 16; +/** Saturation step, dark color part */ +const saturationStep2 = 5; +/** Brightness step, light color part */ +const brightnessStep1 = 5; +/** Brightness step, dark color part */ +const brightnessStep2 = 15; +/** Light color count, main color up */ +const lightColorCount = 5; +/** Dark color count, main color down */ +const darkColorCount = 4; + +/** + * Get AntD palette color by index + * + * @param color - Color + * @param index - The color index of color palette (the main color index is 6) + * @returns Hex color + */ +export function getAntDPaletteColorByIndex(color: AnyColor, index: ColorIndex): string { + if (!isValidColor(color)) { + throw new Error('invalid input color value'); + } + + if (index === 6) { + return getHex(color); + } + + const isLight = index < 6; + const hsv = getHsv(color); + const i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1; + + const newHsv: HsvColor = { + h: getHue(hsv, i, isLight), + s: getSaturation(hsv, i, isLight), + v: getValue(hsv, i, isLight) + }; + + return getHex(newHsv); +} + +/** Map of dark color index and opacity */ +const darkColorMap = [ + { index: 7, opacity: 0.15 }, + { index: 6, opacity: 0.25 }, + { index: 5, opacity: 0.3 }, + { index: 5, opacity: 0.45 }, + { index: 5, opacity: 0.65 }, + { index: 5, opacity: 0.85 }, + { index: 5, opacity: 0.9 }, + { index: 4, opacity: 0.93 }, + { index: 3, opacity: 0.95 }, + { index: 2, opacity: 0.97 }, + { index: 1, opacity: 0.98 } +]; + +/** + * Get AntD color palette + * + * @param color - Color + * @param darkTheme - Dark theme + * @param darkThemeMixColor - Dark theme mix color (default: #141414) + */ +export function getAntDColorPalette(color: AnyColor, darkTheme = false, darkThemeMixColor = '#141414'): string[] { + const indexes: ColorIndex[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + + const patterns = indexes.map(index => getAntDPaletteColorByIndex(color, index)); + + if (darkTheme) { + const darkPatterns = darkColorMap.map(({ index, opacity }) => { + const darkColor = mixColor(darkThemeMixColor, patterns[index], opacity); + + return darkColor; + }); + + return darkPatterns.map(item => getHex(item)); + } + + return patterns; +} + +/** + * Get hue + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getHue(hsv: HsvColor, i: number, isLight: boolean) { + let hue: number; + + const hsvH = Math.round(hsv.h); + + if (hsvH >= 60 && hsvH <= 240) { + hue = isLight ? hsvH - hueStep * i : hsvH + hueStep * i; + } else { + hue = isLight ? hsvH + hueStep * i : hsvH - hueStep * i; + } + + if (hue < 0) { + hue += 360; + } + + if (hue >= 360) { + hue -= 360; + } + + return hue; +} + +/** + * Get saturation + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getSaturation(hsv: HsvColor, i: number, isLight: boolean) { + if (hsv.h === 0 && hsv.s === 0) { + return hsv.s; + } + + let saturation: number; + + if (isLight) { + saturation = hsv.s - saturationStep * i; + } else if (i === darkColorCount) { + saturation = hsv.s + saturationStep; + } else { + saturation = hsv.s + saturationStep2 * i; + } + + if (saturation > 100) { + saturation = 100; + } + + if (isLight && i === lightColorCount && saturation > 10) { + saturation = 10; + } + + if (saturation < 6) { + saturation = 6; + } + + return saturation; +} + +/** + * Get value of hsv + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getValue(hsv: HsvColor, i: number, isLight: boolean) { + let value: number; + + if (isLight) { + value = hsv.v + brightnessStep1 * i; + } else { + value = hsv.v - brightnessStep2 * i; + } + + if (value > 100) { + value = 100; + } + + return value; +} diff --git a/packages/color/src/palette/index.ts b/packages/color/src/palette/index.ts new file mode 100644 index 0000000..ba3b853 --- /dev/null +++ b/packages/color/src/palette/index.ts @@ -0,0 +1,45 @@ +import type { AnyColor } from 'colord'; +import { getHex } from '../shared'; +import type { ColorPaletteNumber } from '../types'; +import { getRecommendedColorPalette } from './recommend'; +import { getAntDColorPalette } from './antd'; + +/** + * get color palette by provided color + * + * @param color + * @param recommended whether to get recommended color palette (the provided color may not be the main color) + */ +export function getColorPalette(color: AnyColor, recommended = false) { + const colorMap = new Map(); + + if (recommended) { + const colorPalette = getRecommendedColorPalette(getHex(color)); + colorPalette.palettes.forEach(palette => { + colorMap.set(palette.number, palette.hex); + }); + } else { + const colors = getAntDColorPalette(color); + + const colorNumbers: ColorPaletteNumber[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]; + + colorNumbers.forEach((number, index) => { + colorMap.set(number, colors[index]); + }); + } + + return colorMap; +} + +/** + * get color palette color by number + * + * @param color the provided color + * @param number the color palette number + * @param recommended whether to get recommended color palette (the provided color may not be the main color) + */ +export function getPaletteColorByNumber(color: AnyColor, number: ColorPaletteNumber, recommended = false) { + const colorMap = getColorPalette(color, recommended); + + return colorMap.get(number as ColorPaletteNumber)!; +} diff --git a/packages/color/src/palette/recommend.ts b/packages/color/src/palette/recommend.ts new file mode 100644 index 0000000..904cae2 --- /dev/null +++ b/packages/color/src/palette/recommend.ts @@ -0,0 +1,152 @@ +import { getColorName, getDeltaE, getHsl, isValidColor, transformHslToHex } from '../shared'; +import { colorPalettes } from '../constant'; +import type { + ColorPalette, + ColorPaletteFamily, + ColorPaletteFamilyWithNearestPalette, + ColorPaletteMatch, + ColorPaletteNumber +} from '../types'; + +/** + * get recommended color palette by provided color + * + * @param color the provided color + */ +export function getRecommendedColorPalette(color: string) { + const colorPaletteFamily = getRecommendedColorPaletteFamily(color); + + const colorMap = new Map(); + + colorPaletteFamily.palettes.forEach(palette => { + colorMap.set(palette.number, palette); + }); + + const mainColor = colorMap.get(500)!; + const matchColor = colorPaletteFamily.palettes.find(palette => palette.hex === color)!; + + const colorPalette: ColorPaletteMatch = { + ...colorPaletteFamily, + colorMap, + main: mainColor, + match: matchColor + }; + + return colorPalette; +} + +/** + * get recommended palette color by provided color + * + * @param color the provided color + * @param number the color palette number + */ +export function getRecommendedPaletteColorByNumber(color: string, number: ColorPaletteNumber) { + const colorPalette = getRecommendedColorPalette(color); + + const { hex } = colorPalette.colorMap.get(number)!; + + return hex; +} + +/** + * get color palette family by provided color and color name + * + * @param color the provided color + */ +export function getRecommendedColorPaletteFamily(color: string) { + if (!isValidColor(color)) { + throw new Error('Invalid color, please check color value!'); + } + + let colorName = getColorName(color); + + colorName = colorName.toLowerCase().replace(/\s/g, '-'); + + const { h: h1, s: s1 } = getHsl(color); + + const { nearestLightnessPalette, palettes } = getNearestColorPaletteFamily(color, colorPalettes); + + const { number, hex } = nearestLightnessPalette; + + const { h: h2, s: s2 } = getHsl(hex); + + const deltaH = h1 - h2; + + const sRatio = s1 / s2; + + const colorPaletteFamily: ColorPaletteFamily = { + name: colorName, + palettes: palettes.map(palette => { + let hexValue = color; + + const isSame = number === palette.number; + + if (!isSame) { + const { h: h3, s: s3, l } = getHsl(palette.hex); + + const newH = deltaH < 0 ? h3 + deltaH : h3 - deltaH; + const newS = s3 * sRatio; + + hexValue = transformHslToHex({ + h: newH, + s: newS, + l + }); + } + + return { + hex: hexValue, + number: palette.number + }; + }) + }; + + return colorPaletteFamily; +} + +/** + * get nearest color palette family + * + * @param color color + * @param families color palette families + */ +function getNearestColorPaletteFamily(color: string, families: ColorPaletteFamily[]) { + const familyWithConfig = families.map(family => { + const palettes = family.palettes.map(palette => { + return { + ...palette, + delta: getDeltaE(color, palette.hex) + }; + }); + + const nearestPalette = palettes.reduce((prev, curr) => (prev.delta < curr.delta ? prev : curr)); + + return { + ...family, + palettes, + nearestPalette + }; + }); + + const nearestPaletteFamily = familyWithConfig.reduce((prev, curr) => + prev.nearestPalette.delta < curr.nearestPalette.delta ? prev : curr + ); + + const { l } = getHsl(color); + + const paletteFamily: ColorPaletteFamilyWithNearestPalette = { + ...nearestPaletteFamily, + nearestLightnessPalette: nearestPaletteFamily.palettes.reduce((prev, curr) => { + const { l: prevLightness } = getHsl(prev.hex); + const { l: currLightness } = getHsl(curr.hex); + + const deltaPrev = Math.abs(prevLightness - l); + const deltaCurr = Math.abs(currLightness - l); + + return deltaPrev < deltaCurr ? prev : curr; + }) + }; + + return paletteFamily; +} diff --git a/packages/color/src/shared/colord.ts b/packages/color/src/shared/colord.ts new file mode 100644 index 0000000..4c52330 --- /dev/null +++ b/packages/color/src/shared/colord.ts @@ -0,0 +1,93 @@ +import { colord, extend } from 'colord'; +import namesPlugin from 'colord/plugins/names'; +import mixPlugin from 'colord/plugins/mix'; +import labPlugin from 'colord/plugins/lab'; +import type { AnyColor, HslColor, RgbColor } from 'colord'; + +extend([namesPlugin, mixPlugin, labPlugin]); + +export function isValidColor(color: AnyColor) { + return colord(color).isValid(); +} + +export function getHex(color: AnyColor) { + return colord(color).toHex(); +} + +export function getRgb(color: AnyColor) { + return colord(color).toRgb(); +} + +export function getHsl(color: AnyColor) { + return colord(color).toHsl(); +} + +export function getHsv(color: AnyColor) { + return colord(color).toHsv(); +} + +export function getDeltaE(color1: AnyColor, color2: AnyColor) { + return colord(color1).delta(color2); +} + +export function transformHslToHex(color: HslColor) { + return colord(color).toHex(); +} + +/** + * Add color alpha + * + * @param color - Color + * @param alpha - Alpha (0 - 1) + */ +export function addColorAlpha(color: AnyColor, alpha: number) { + return colord(color).alpha(alpha).toHex(); +} + +/** + * Mix color + * + * @param firstColor - First color + * @param secondColor - Second color + * @param ratio - The ratio of the second color (0 - 1) + */ +export function mixColor(firstColor: AnyColor, secondColor: AnyColor, ratio: number) { + return colord(firstColor).mix(secondColor, ratio).toHex(); +} + +/** + * Transform color with opacity to similar color without opacity + * + * @param color - Color + * @param alpha - Alpha (0 - 1) + * @param bgColor Background color (usually white or black) + */ +export function transformColorWithOpacity(color: AnyColor, alpha: number, bgColor = '#ffffff') { + const originColor = addColorAlpha(color, alpha); + const { r: oR, g: oG, b: oB } = colord(originColor).toRgb(); + + const { r: bgR, g: bgG, b: bgB } = colord(bgColor).toRgb(); + + function calRgb(or: number, bg: number, al: number) { + return bg + (or - bg) * al; + } + + const resultRgb: RgbColor = { + r: calRgb(oR, bgR, alpha), + g: calRgb(oG, bgG, alpha), + b: calRgb(oB, bgB, alpha) + }; + + return colord(resultRgb).toHex(); +} + +/** + * Is white color + * + * @param color - Color + */ +export function isWhiteColor(color: AnyColor) { + return colord(color).isEqual('#ffffff'); +} + +export { colord }; diff --git a/packages/color/src/shared/index.ts b/packages/color/src/shared/index.ts new file mode 100644 index 0000000..ae293ce --- /dev/null +++ b/packages/color/src/shared/index.ts @@ -0,0 +1,2 @@ +export * from './colord'; +export * from './name'; diff --git a/packages/color/src/shared/name.ts b/packages/color/src/shared/name.ts new file mode 100644 index 0000000..866bd33 --- /dev/null +++ b/packages/color/src/shared/name.ts @@ -0,0 +1,49 @@ +import { colorNames } from '../constant'; +import { getHex, getHsl, getRgb } from './colord'; + +/** + * Get color name + * + * @param color + */ +export function getColorName(color: string) { + const hex = getHex(color); + const rgb = getRgb(color); + const hsl = getHsl(color); + + let ndf = 0; + let ndf1 = 0; + let ndf2 = 0; + let cl = -1; + let df = -1; + + let name = ''; + + colorNames.some((item, index) => { + const [hexValue, colorName] = item; + + const match = hex === hexValue; + + if (match) { + name = colorName; + } else { + const { r, g, b } = getRgb(hexValue); + const { h, s, l } = getHsl(hexValue); + + ndf1 = (rgb.r - r) ** 2 + (rgb.g - g) ** 2 + (rgb.b - b) ** 2; + ndf2 = (hsl.h - h) ** 2 + (hsl.s - s) ** 2 + (hsl.l - l) ** 2; + + ndf = ndf1 + ndf2 * 2; + if (df < 0 || df > ndf) { + df = ndf; + cl = index; + } + } + + return match; + }); + + name = colorNames[cl][1]; + + return name; +} diff --git a/packages/color/src/types/index.ts b/packages/color/src/types/index.ts new file mode 100644 index 0000000..3a63bc8 --- /dev/null +++ b/packages/color/src/types/index.ts @@ -0,0 +1,58 @@ +/** + * the color palette number + * + * the main color number is 500 + */ +export type ColorPaletteNumber = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950; + +/** the color palette */ +export type ColorPalette = { + /** the color hex value */ + hex: string; + /** + * the color number + * + * - 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 + */ + number: ColorPaletteNumber; +}; + +/** the color palette family */ +export type ColorPaletteFamily = { + /** the color palette family name */ + name: string; + /** the color palettes */ + palettes: ColorPalette[]; +}; + +/** the color palette with delta */ +export type ColorPaletteWithDelta = ColorPalette & { + delta: number; +}; + +/** the color palette family with nearest palette */ +export type ColorPaletteFamilyWithNearestPalette = ColorPaletteFamily & { + nearestPalette: ColorPaletteWithDelta; + nearestLightnessPalette: ColorPaletteWithDelta; +}; + +/** the color palette match */ +export type ColorPaletteMatch = ColorPaletteFamily & { + /** the color map of the palette */ + colorMap: Map; + /** + * the main color of the palette + * + * which number is 500 + */ + main: ColorPalette; + /** the match color of the palette */ + match: ColorPalette; +}; + +/** + * The color index of color palette + * + * From left to right, the color is from light to dark, 6 is main color + */ +export type ColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11; diff --git a/packages/color/tsconfig.json b/packages/color/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/color/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/hooks/package.json b/packages/hooks/package.json new file mode 100644 index 0000000..808f995 --- /dev/null +++ b/packages/hooks/package.json @@ -0,0 +1,16 @@ +{ + "name": "@sa/hooks", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "@sa/axios": "workspace:*", + "@sa/utils": "workspace:^" + } +} diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts new file mode 100644 index 0000000..a36c843 --- /dev/null +++ b/packages/hooks/src/index.ts @@ -0,0 +1,10 @@ +import useBoolean from './use-boolean'; +import useLoading from './use-loading'; +import useCountDown from './use-count-down'; +import useContext from './use-context'; +import useSvgIconRender from './use-svg-icon-render'; +import useHookTable from './use-table'; + +export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable }; + +export * from './use-table'; diff --git a/packages/hooks/src/use-boolean.ts b/packages/hooks/src/use-boolean.ts new file mode 100644 index 0000000..a60d45a --- /dev/null +++ b/packages/hooks/src/use-boolean.ts @@ -0,0 +1,31 @@ +import { ref } from 'vue'; + +/** + * Boolean + * + * @param initValue Init value + */ +export default function useBoolean(initValue = false) { + const bool = ref(initValue); + + function setBool(value: boolean) { + bool.value = value; + } + function setTrue() { + setBool(true); + } + function setFalse() { + setBool(false); + } + function toggle() { + setBool(!bool.value); + } + + return { + bool, + setBool, + setTrue, + setFalse, + toggle + }; +} diff --git a/packages/hooks/src/use-context.ts b/packages/hooks/src/use-context.ts new file mode 100644 index 0000000..001d8aa --- /dev/null +++ b/packages/hooks/src/use-context.ts @@ -0,0 +1,96 @@ +import { inject, provide } from 'vue'; +import type { InjectionKey } from 'vue'; + +/** + * Use context + * + * @example + * ```ts + * // there are three vue files: A.vue, B.vue, C.vue, and A.vue is the parent component of B.vue and C.vue + * + * // context.ts + * import { ref } from 'vue'; + * import { useContext } from '@sa/hooks'; + * + * export const { setupStore, useStore } = useContext('demo', () => { + * const count = ref(0); + * + * function increment() { + * count.value++; + * } + * + * function decrement() { + * count.value--; + * } + * + * return { + * count, + * increment, + * decrement + * }; + * }) + * ``` // A.vue + * ```vue + * + * + * ``` // B.vue + * ```vue + * + * + * ```; + * + * // C.vue is same as B.vue + * + * @param contextName Context name + * @param fn Context function + */ +export default function useContext any>(contextName: string, fn: T) { + type Context = ReturnType; + + const { useProvide, useInject: useStore } = createContext(contextName); + + function setupStore(...args: Parameters) { + const context: Context = fn(...args); + return useProvide(context); + } + + return { + /** Setup store in the parent component */ + setupStore, + /** Use store in the child component */ + useStore + }; +} + +/** Create context */ +function createContext(contextName: string) { + const injectKey: InjectionKey = Symbol(contextName); + + function useProvide(context: T) { + provide(injectKey, context); + + return context; + } + + function useInject() { + return inject(injectKey) as T; + } + + return { + useProvide, + useInject + }; +} diff --git a/packages/hooks/src/use-count-down.ts b/packages/hooks/src/use-count-down.ts new file mode 100644 index 0000000..bfad064 --- /dev/null +++ b/packages/hooks/src/use-count-down.ts @@ -0,0 +1,49 @@ +import { computed, onScopeDispose, ref } from 'vue'; +import { useRafFn } from '@vueuse/core'; + +/** + * count down + * + * @param seconds - count down seconds + */ +export default function useCountDown(seconds: number) { + const FPS_PER_SECOND = 60; + + const fps = ref(0); + + const count = computed(() => Math.ceil(fps.value / FPS_PER_SECOND)); + + const isCounting = computed(() => fps.value > 0); + + const { pause, resume } = useRafFn( + () => { + if (fps.value > 0) { + fps.value -= 1; + } else { + pause(); + } + }, + { immediate: false } + ); + + function start(updateSeconds: number = seconds) { + fps.value = FPS_PER_SECOND * updateSeconds; + resume(); + } + + function stop() { + fps.value = 0; + pause(); + } + + onScopeDispose(() => { + pause(); + }); + + return { + count, + isCounting, + start, + stop + }; +} diff --git a/packages/hooks/src/use-loading.ts b/packages/hooks/src/use-loading.ts new file mode 100644 index 0000000..b8f89ad --- /dev/null +++ b/packages/hooks/src/use-loading.ts @@ -0,0 +1,16 @@ +import useBoolean from './use-boolean'; + +/** + * Loading + * + * @param initValue Init value + */ +export default function useLoading(initValue = false) { + const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue); + + return { + loading, + startLoading, + endLoading + }; +} diff --git a/packages/hooks/src/use-request.ts b/packages/hooks/src/use-request.ts new file mode 100644 index 0000000..a0a40e6 --- /dev/null +++ b/packages/hooks/src/use-request.ts @@ -0,0 +1,79 @@ +import { ref } from 'vue'; +import type { Ref } from 'vue'; +import { createFlatRequest } from '@sa/axios'; +import type { + AxiosError, + CreateAxiosDefaults, + CustomAxiosRequestConfig, + MappedType, + RequestOption, + ResponseType +} from '@sa/axios'; +import useLoading from './use-loading'; + +export type HookRequestInstanceResponseSuccessData = { + data: Ref; + error: Ref; +}; + +export type HookRequestInstanceResponseFailData = { + data: Ref; + error: Ref>; +}; + +export type HookRequestInstanceResponseData = { + loading: Ref; +} & (HookRequestInstanceResponseSuccessData | HookRequestInstanceResponseFailData); + +export interface HookRequestInstance { + ( + config: CustomAxiosRequestConfig + ): HookRequestInstanceResponseData, ResponseData>; + cancelRequest: (requestId: string) => void; + cancelAllRequest: () => void; +} + +/** + * create a hook request instance + * + * @param axiosConfig + * @param options + */ +export default function createHookRequest( + axiosConfig?: CreateAxiosDefaults, + options?: Partial> +) { + const request = createFlatRequest(axiosConfig, options); + + const hookRequest: HookRequestInstance = function hookRequest( + config: CustomAxiosRequestConfig + ) { + const { loading, startLoading, endLoading } = useLoading(); + + const data = ref | null>(null) as Ref>; + const error = ref | null>(null) as Ref | null>; + + startLoading(); + + request(config).then(res => { + if (res.data) { + data.value = res.data; + } else { + error.value = res.error; + } + + endLoading(); + }); + + return { + loading, + data, + error + }; + } as HookRequestInstance; + + hookRequest.cancelRequest = request.cancelRequest; + hookRequest.cancelAllRequest = request.cancelAllRequest; + + return hookRequest; +} diff --git a/packages/hooks/src/use-svg-icon-render.ts b/packages/hooks/src/use-svg-icon-render.ts new file mode 100644 index 0000000..62c2206 --- /dev/null +++ b/packages/hooks/src/use-svg-icon-render.ts @@ -0,0 +1,50 @@ +import { h } from 'vue'; +import type { Component } from 'vue'; + +/** + * Svg icon render hook + * + * @param SvgIcon Svg icon component + */ +export default function useSvgIconRender(SvgIcon: Component) { + interface IconConfig { + /** Iconify icon name */ + icon?: string; + /** Local icon name */ + localIcon?: string; + /** Icon color */ + color?: string; + /** Icon size */ + fontSize?: number; + } + + type IconStyle = Partial>; + + /** + * Svg icon VNode + * + * @param config + */ + const SvgIconVNode = (config: IconConfig) => { + const { color, fontSize, icon, localIcon } = config; + + const style: IconStyle = {}; + + if (color) { + style.color = color; + } + if (fontSize) { + style.fontSize = `${fontSize}px`; + } + + if (!icon && !localIcon) { + return undefined; + } + + return () => h(SvgIcon, { icon, localIcon, style }); + }; + + return { + SvgIconVNode + }; +} diff --git a/packages/hooks/src/use-table.ts b/packages/hooks/src/use-table.ts new file mode 100644 index 0000000..c4d0602 --- /dev/null +++ b/packages/hooks/src/use-table.ts @@ -0,0 +1,152 @@ +import { computed, reactive, ref } from 'vue'; +import type { Ref } from 'vue'; +import { jsonClone } from '@sa/utils'; +import useBoolean from './use-boolean'; +import useLoading from './use-loading'; + +export type MaybePromise = T | Promise; + +export type ApiFn = (args: any) => Promise; + +export type TableColumnCheck = { + key: string; + title: string; + checked: boolean; +}; + +export type TableDataWithIndex = T & { index: number }; + +export type TransformedData = { + data: TableDataWithIndex[]; + pageNum: number; + pageSize: number; + total: number; +}; + +export type Transformer = (response: Response) => TransformedData; + +export type TableConfig = { + /** api function to get table data */ + apiFn: A; + /** api params */ + apiParams?: Parameters[0]; + /** transform api response to table data */ + transformer: Transformer>>; + /** columns factory */ + columns: () => C[]; + /** + * get column checks + * + * @param columns + */ + getColumnChecks: (columns: C[]) => TableColumnCheck[]; + /** + * get columns + * + * @param columns + */ + getColumns: (columns: C[], checks: TableColumnCheck[]) => C[]; + /** + * callback when response fetched + * + * @param transformed transformed data + */ + onFetched?: (transformed: TransformedData) => MaybePromise; + /** + * whether to get data immediately + * + * @default true + */ + immediate?: boolean; +}; + +export default function useHookTable(config: TableConfig) { + const { loading, startLoading, endLoading } = useLoading(); + const { bool: empty, setBool: setEmpty } = useBoolean(); + + const { apiFn, apiParams, transformer, immediate = true, getColumnChecks, getColumns } = config; + + const searchParams: NonNullable[0]> = reactive({ ...apiParams }); + + const allColumns = ref(config.columns()) as Ref; + + const data: Ref[]> = ref([]); + + const columnChecks: Ref = ref(getColumnChecks(config.columns())); + + const columns = computed(() => getColumns(allColumns.value, columnChecks.value)); + + function reloadColumns() { + allColumns.value = config.columns(); + + const checkMap = new Map(columnChecks.value.map(col => [col.key, col.checked])); + + const defaultChecks = getColumnChecks(allColumns.value); + + columnChecks.value = defaultChecks.map(col => ({ + ...col, + checked: checkMap.get(col.key) ?? col.checked + })); + } + + async function getData() { + startLoading(); + + const formattedParams = formatSearchParams(searchParams); + + const response = await apiFn(formattedParams); + + const transformed = transformer(response as Awaited>); + + data.value = transformed.data; + + setEmpty(transformed.data.length === 0); + + await config.onFetched?.(transformed); + + endLoading(); + } + + function formatSearchParams(params: Record) { + const formattedParams: Record = {}; + + Object.entries(params).forEach(([key, value]) => { + if (value !== null && value !== undefined) { + formattedParams[key] = value; + } + }); + + return formattedParams; + } + + /** + * update search params + * + * @param params + */ + function updateSearchParams(params: Partial[0]>) { + Object.assign(searchParams, params); + } + + /** reset search params */ + function resetSearchParams() { + Object.assign(searchParams, jsonClone(apiParams)); + } + + if (immediate) { + getData(); + } + + return { + loading, + empty, + data, + columns, + columnChecks, + reloadColumns, + getData, + searchParams, + updateSearchParams, + resetSearchParams + }; +} diff --git a/packages/hooks/tsconfig.json b/packages/hooks/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/hooks/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/materials/package.json b/packages/materials/package.json new file mode 100644 index 0000000..1ca68ab --- /dev/null +++ b/packages/materials/package.json @@ -0,0 +1,20 @@ +{ + "name": "@sa/materials", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "@sa/utils": "workspace:*", + "@simonwep/pickr": "1.9.1", + "simplebar-vue": "2.4.0" + }, + "devDependencies": { + "typed-css-modules": "0.9.1" + } +} diff --git a/packages/materials/src/index.ts b/packages/materials/src/index.ts new file mode 100644 index 0000000..99694d1 --- /dev/null +++ b/packages/materials/src/index.ts @@ -0,0 +1,7 @@ +import AdminLayout, { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './libs/admin-layout'; +import PageTab from './libs/page-tab'; +import SimpleScrollbar from './libs/simple-scrollbar'; +import ColorPicker from './libs/color-picker'; + +export { AdminLayout, LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX, PageTab, SimpleScrollbar, ColorPicker }; +export * from './types'; diff --git a/packages/materials/src/libs/admin-layout/index.module.css b/packages/materials/src/libs/admin-layout/index.module.css new file mode 100644 index 0000000..e5c8ac8 --- /dev/null +++ b/packages/materials/src/libs/admin-layout/index.module.css @@ -0,0 +1,63 @@ +/* @type */ + +.layout-header, +.layout-header-placement { + height: var(--soy-header-height); +} + +.layout-header { + z-index: var(--soy-header-z-index); +} + +.layout-tab { + top: var(--soy-header-height); + height: var(--soy-tab-height); + z-index: var(--soy-tab-z-index); +} + +.layout-tab-placement { + height: var(--soy-tab-height); +} + +.layout-sider { + width: var(--soy-sider-width); + z-index: var(--soy-sider-z-index); +} + +.layout-mobile-sider { + z-index: var(--soy-sider-z-index); +} + +.layout-mobile-sider-mask { + z-index: var(--soy-mobile-sider-z-index); +} + +.layout-sider_collapsed { + width: var(--soy-sider-collapsed-width); + z-index: var(--soy-sider-z-index); +} + +.layout-footer, +.layout-footer-placement { + height: var(--soy-footer-height); +} + +.layout-footer { + z-index: var(--soy-footer-z-index); +} + +.left-gap { + padding-left: var(--soy-sider-width); +} + +.left-gap_collapsed { + padding-left: var(--soy-sider-collapsed-width); +} + +.sider-padding-top { + padding-top: var(--soy-header-height); +} + +.sider-padding-bottom { + padding-bottom: var(--soy-footer-height); +} diff --git a/packages/materials/src/libs/admin-layout/index.module.css.d.ts b/packages/materials/src/libs/admin-layout/index.module.css.d.ts new file mode 100644 index 0000000..e6d10d1 --- /dev/null +++ b/packages/materials/src/libs/admin-layout/index.module.css.d.ts @@ -0,0 +1,17 @@ +declare const styles: { + readonly 'layout-header': string; + readonly 'layout-header-placement': string; + readonly 'layout-tab': string; + readonly 'layout-tab-placement': string; + readonly 'layout-sider': string; + readonly 'layout-mobile-sider': string; + readonly 'layout-mobile-sider-mask': string; + readonly 'layout-sider_collapsed': string; + readonly 'layout-footer': string; + readonly 'layout-footer-placement': string; + readonly 'left-gap': string; + readonly 'left-gap_collapsed': string; + readonly 'sider-padding-top': string; + readonly 'sider-padding-bottom': string; +}; +export default styles; diff --git a/packages/materials/src/libs/admin-layout/index.ts b/packages/materials/src/libs/admin-layout/index.ts new file mode 100644 index 0000000..0687362 --- /dev/null +++ b/packages/materials/src/libs/admin-layout/index.ts @@ -0,0 +1,5 @@ +import AdminLayout from './index.vue'; +import { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './shared'; + +export default AdminLayout; +export { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX }; diff --git a/packages/materials/src/libs/admin-layout/index.vue b/packages/materials/src/libs/admin-layout/index.vue new file mode 100644 index 0000000..543f7dc --- /dev/null +++ b/packages/materials/src/libs/admin-layout/index.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/packages/materials/src/libs/admin-layout/shared.ts b/packages/materials/src/libs/admin-layout/shared.ts new file mode 100644 index 0000000..940451e --- /dev/null +++ b/packages/materials/src/libs/admin-layout/shared.ts @@ -0,0 +1,68 @@ +import type { AdminLayoutProps, LayoutCssVars, LayoutCssVarsProps } from '../../types'; + +/** The id of the scroll element of the layout */ +export const LAYOUT_SCROLL_EL_ID = '__SCROLL_EL_ID__'; + +/** The max z-index of the layout */ +export const LAYOUT_MAX_Z_INDEX = 100; + +/** + * Create layout css vars by css vars props + * + * @param props Css vars props + */ +function createLayoutCssVarsByCssVarsProps(props: LayoutCssVarsProps) { + const cssVars: LayoutCssVars = { + '--soy-header-height': `${props.headerHeight}px`, + '--soy-header-z-index': props.headerZIndex, + '--soy-tab-height': `${props.tabHeight}px`, + '--soy-tab-z-index': props.tabZIndex, + '--soy-sider-width': `${props.siderWidth}px`, + '--soy-sider-collapsed-width': `${props.siderCollapsedWidth}px`, + '--soy-sider-z-index': props.siderZIndex, + '--soy-mobile-sider-z-index': props.mobileSiderZIndex, + '--soy-footer-height': `${props.footerHeight}px`, + '--soy-footer-z-index': props.footerZIndex + }; + + return cssVars; +} + +/** + * Create layout css vars + * + * @param props + */ +export function createLayoutCssVars(props: AdminLayoutProps) { + const { + mode, + isMobile, + maxZIndex = LAYOUT_MAX_Z_INDEX, + headerHeight, + tabHeight, + siderWidth, + siderCollapsedWidth, + footerHeight + } = props; + + const headerZIndex = maxZIndex - 3; + const tabZIndex = maxZIndex - 5; + const siderZIndex = mode === 'vertical' || isMobile ? maxZIndex - 1 : maxZIndex - 4; + const mobileSiderZIndex = isMobile ? maxZIndex - 2 : 0; + const footerZIndex = maxZIndex - 5; + + const cssProps: LayoutCssVarsProps = { + headerHeight, + headerZIndex, + tabHeight, + tabZIndex, + siderWidth, + siderZIndex, + mobileSiderZIndex, + siderCollapsedWidth, + footerHeight, + footerZIndex + }; + + return createLayoutCssVarsByCssVarsProps(cssProps); +} diff --git a/packages/materials/src/libs/color-picker/index.ts b/packages/materials/src/libs/color-picker/index.ts new file mode 100644 index 0000000..131b1d1 --- /dev/null +++ b/packages/materials/src/libs/color-picker/index.ts @@ -0,0 +1,3 @@ +import ColorPicker from './index.vue'; + +export default ColorPicker; diff --git a/packages/materials/src/libs/color-picker/index.vue b/packages/materials/src/libs/color-picker/index.vue new file mode 100644 index 0000000..1267886 --- /dev/null +++ b/packages/materials/src/libs/color-picker/index.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/packages/materials/src/libs/page-tab/button-tab.vue b/packages/materials/src/libs/page-tab/button-tab.vue new file mode 100644 index 0000000..0826e71 --- /dev/null +++ b/packages/materials/src/libs/page-tab/button-tab.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/packages/materials/src/libs/page-tab/chrome-tab-bg.vue b/packages/materials/src/libs/page-tab/chrome-tab-bg.vue new file mode 100644 index 0000000..151e03a --- /dev/null +++ b/packages/materials/src/libs/page-tab/chrome-tab-bg.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/packages/materials/src/libs/page-tab/chrome-tab.vue b/packages/materials/src/libs/page-tab/chrome-tab.vue new file mode 100644 index 0000000..e4509b0 --- /dev/null +++ b/packages/materials/src/libs/page-tab/chrome-tab.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/packages/materials/src/libs/page-tab/index.module.css b/packages/materials/src/libs/page-tab/index.module.css new file mode 100644 index 0000000..abf56a5 --- /dev/null +++ b/packages/materials/src/libs/page-tab/index.module.css @@ -0,0 +1,97 @@ +/* @type */ + +.button-tab { + border-color: #e5e7eb; +} + +.button-tab_dark { + border-color: #ffffff3d; +} + +.button-tab:hover { + color: var(--soy-primary-color); + border-color: var(--soy-primary-color-opacity3); +} + +.button-tab_active { + color: var(--soy-primary-color); + border-color: var(--soy-primary-color-opacity3); + background-color: var(--soy-primary-color-opacity1); +} + +.button-tab_active_dark { + background-color: var(--soy-primary-color-opacity2); +} + +.button-tab .svg-close:hover { + font-size: 12px; + color: #ffffff; + background-color: var(--soy-primary-color); +} + +.button-tab_dark .svg-close:hover { + color: #000000; +} + +.chrome-tab:hover { + z-index: 9; +} + +.chrome-tab_active { + z-index: 10; + color: var(--soy-primary-color); +} + +.chrome-tab__bg { + color: transparent; +} + +.chrome-tab_active .chrome-tab__bg { + color: var(--soy-primary-color1); +} + +.chrome-tab_active_dark .chrome-tab__bg { + color: var(--soy-primary-color2); +} + +.chrome-tab:hover .chrome-tab__bg { + color: #dee1e6; +} + +.chrome-tab_active:hover .chrome-tab__bg { + color: var(--soy-primary-color1); +} + +.chrome-tab_dark:hover .chrome-tab__bg { + color: #333333; +} + +.chrome-tab_active_dark:hover .chrome-tab__bg { + color: var(--soy-primary-color2); +} + +.chrome-tab .svg-close:hover { + font-size: 12px; + color: #ffffff; + background-color: #9ca3af; +} + +.chrome-tab_active .svg-close:hover { + background-color: var(--soy-primary-color); +} + +.chrome-tab_dark .svg-close:hover { + color: #000000; +} + +.chrome-tab_active .chrome-tab-divider { + opacity: 0; +} + +.chrome-tab:hover .chrome-tab-divider { + opacity: 0; +} + +.chrome-tab_dark .chrome-tab-divider { + background-color: rgba(255, 255, 255, 0.9); +} diff --git a/packages/materials/src/libs/page-tab/index.module.css.d.ts b/packages/materials/src/libs/page-tab/index.module.css.d.ts new file mode 100644 index 0000000..f04f933 --- /dev/null +++ b/packages/materials/src/libs/page-tab/index.module.css.d.ts @@ -0,0 +1,14 @@ +declare const styles: { + readonly 'button-tab': string; + readonly 'button-tab_dark': string; + readonly 'button-tab_active': string; + readonly 'button-tab_active_dark': string; + readonly 'chrome-tab': string; + readonly 'chrome-tab_active': string; + readonly 'chrome-tab__bg': string; + readonly 'chrome-tab_active_dark': string; + readonly 'chrome-tab_dark': string; + readonly 'chrome-tab-divider': string; + readonly 'svg-close': string; +}; +export default styles; diff --git a/packages/materials/src/libs/page-tab/index.ts b/packages/materials/src/libs/page-tab/index.ts new file mode 100644 index 0000000..b402adf --- /dev/null +++ b/packages/materials/src/libs/page-tab/index.ts @@ -0,0 +1,3 @@ +import PageTab from './index.vue'; + +export default PageTab; diff --git a/packages/materials/src/libs/page-tab/index.vue b/packages/materials/src/libs/page-tab/index.vue new file mode 100644 index 0000000..6f93115 --- /dev/null +++ b/packages/materials/src/libs/page-tab/index.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/packages/materials/src/libs/page-tab/shared.ts b/packages/materials/src/libs/page-tab/shared.ts new file mode 100644 index 0000000..c6ff0c3 --- /dev/null +++ b/packages/materials/src/libs/page-tab/shared.ts @@ -0,0 +1,31 @@ +import { addColorAlpha, transformColorWithOpacity } from '@sa/utils'; +import type { PageTabCssVars, PageTabCssVarsProps } from '../../types'; + +/** The active color of the tab */ +export const ACTIVE_COLOR = '#1890ff'; + +function createCssVars(props: PageTabCssVarsProps) { + const cssVars: PageTabCssVars = { + '--soy-primary-color': props.primaryColor, + '--soy-primary-color1': props.primaryColor1, + '--soy-primary-color2': props.primaryColor2, + '--soy-primary-color-opacity1': props.primaryColorOpacity1, + '--soy-primary-color-opacity2': props.primaryColorOpacity2, + '--soy-primary-color-opacity3': props.primaryColorOpacity3 + }; + + return cssVars; +} + +export function createTabCssVars(primaryColor: string) { + const cssProps: PageTabCssVarsProps = { + primaryColor, + primaryColor1: transformColorWithOpacity(primaryColor, 0.1, '#ffffff'), + primaryColor2: transformColorWithOpacity(primaryColor, 0.3, '#000000'), + primaryColorOpacity1: addColorAlpha(primaryColor, 0.1), + primaryColorOpacity2: addColorAlpha(primaryColor, 0.15), + primaryColorOpacity3: addColorAlpha(primaryColor, 0.3) + }; + + return createCssVars(cssProps); +} diff --git a/packages/materials/src/libs/page-tab/svg-close.vue b/packages/materials/src/libs/page-tab/svg-close.vue new file mode 100644 index 0000000..1e51fcd --- /dev/null +++ b/packages/materials/src/libs/page-tab/svg-close.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/packages/materials/src/libs/simple-scrollbar/index.ts b/packages/materials/src/libs/simple-scrollbar/index.ts new file mode 100644 index 0000000..1453a06 --- /dev/null +++ b/packages/materials/src/libs/simple-scrollbar/index.ts @@ -0,0 +1,3 @@ +import SimpleScrollbar from './index.vue'; + +export default SimpleScrollbar; diff --git a/packages/materials/src/libs/simple-scrollbar/index.vue b/packages/materials/src/libs/simple-scrollbar/index.vue new file mode 100644 index 0000000..1e8076b --- /dev/null +++ b/packages/materials/src/libs/simple-scrollbar/index.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/packages/materials/src/types/index.ts b/packages/materials/src/types/index.ts new file mode 100644 index 0000000..bbcfb9d --- /dev/null +++ b/packages/materials/src/types/index.ts @@ -0,0 +1,294 @@ +/** Header config */ +interface AdminLayoutHeaderConfig { + /** + * Whether header is visible + * + * @default true + */ + headerVisible?: boolean; + /** + * Header class + * + * @default '' + */ + headerClass?: string; + /** + * Header height + * + * @default 56px + */ + headerHeight?: number; +} + +/** Tab config */ +interface AdminLayoutTabConfig { + /** + * Whether tab is visible + * + * @default true + */ + tabVisible?: boolean; + /** + * Tab class + * + * @default '' + */ + tabClass?: string; + /** + * Tab height + * + * @default 48px + */ + tabHeight?: number; +} + +/** Sider config */ +interface AdminLayoutSiderConfig { + /** + * Whether sider is visible + * + * @default true + */ + siderVisible?: boolean; + /** + * Sider class + * + * @default '' + */ + siderClass?: string; + /** + * Mobile sider class + * + * @default '' + */ + mobileSiderClass?: string; + /** + * Sider collapse status + * + * @default false + */ + siderCollapse?: boolean; + /** + * Sider width when collapse is false + * + * @default '220px' + */ + siderWidth?: number; + /** + * Sider width when collapse is true + * + * @default '64px' + */ + siderCollapsedWidth?: number; +} + +/** Content config */ +export interface AdminLayoutContentConfig { + /** + * Content class + * + * @default '' + */ + contentClass?: string; + /** + * Whether content is full the page + * + * If true, other elements will be hidden by `display: none` + */ + fullContent?: boolean; +} + +/** Footer config */ +export interface AdminLayoutFooterConfig { + /** + * Whether footer is visible + * + * @default true + */ + footerVisible?: boolean; + /** + * Whether footer is fixed + * + * @default true + */ + fixedFooter?: boolean; + /** + * Footer class + * + * @default '' + */ + footerClass?: string; + /** + * Footer height + * + * @default 48px + */ + footerHeight?: number; + /** + * Whether footer is on the right side + * + * When the layout is vertical, the footer is on the right side + */ + rightFooter?: boolean; +} + +/** + * Layout mode + * + * - Horizontal + * - Vertical + */ +export type LayoutMode = 'horizontal' | 'vertical'; + +/** + * The scroll mode when content overflow + * + * - Wrapper: the layout component's wrapper element has a scrollbar + * - Content: the layout component's content element has a scrollbar + * + * @default 'wrapper' + */ +export type LayoutScrollMode = 'wrapper' | 'content'; + +/** Admin layout props */ +export interface AdminLayoutProps + extends AdminLayoutHeaderConfig, + AdminLayoutTabConfig, + AdminLayoutSiderConfig, + AdminLayoutContentConfig, + AdminLayoutFooterConfig { + /** + * Layout mode + * + * - {@link LayoutMode} + */ + mode?: LayoutMode; + /** Is mobile layout */ + isMobile?: boolean; + /** + * Scroll mode + * + * - {@link ScrollMode} + */ + scrollMode?: LayoutScrollMode; + /** + * The id of the scroll element of the layout + * + * It can be used to get the corresponding Dom and scroll it + * + * @example + * use the default id by import + * ```ts + * import { adminLayoutScrollElId } from '@sa/vue-materials'; + * ``` + * + * @default + * ```ts + * const adminLayoutScrollElId = '__ADMIN_LAYOUT_SCROLL_EL_ID__' + * ``` + */ + scrollElId?: string; + /** The class of the scroll element */ + scrollElClass?: string; + /** The class of the scroll wrapper element */ + scrollWrapperClass?: string; + /** + * The common class of the layout + * + * Is can be used to configure the transition animation + * + * @default 'transition-all-300' + */ + commonClass?: string; + /** + * Whether fix the header and tab + * + * @default true + */ + fixedTop?: boolean; + /** + * The max z-index of the layout + * + * The z-index of Header,Tab,Sider and Footer will not exceed this value + */ + maxZIndex?: number; +} + +type Kebab = S extends Uncapitalize ? S : `-${Uncapitalize}`; + +type KebabCase = S extends `${infer Start}${infer End}` + ? `${Uncapitalize}${KebabCase>}` + : S; + +type Prefix = '--soy-'; + +export type LayoutCssVarsProps = Pick< + AdminLayoutProps, + 'headerHeight' | 'tabHeight' | 'siderWidth' | 'siderCollapsedWidth' | 'footerHeight' +> & { + headerZIndex?: number; + tabZIndex?: number; + siderZIndex?: number; + mobileSiderZIndex?: number; + footerZIndex?: number; +}; + +export type LayoutCssVars = { + [K in keyof LayoutCssVarsProps as `${Prefix}${KebabCase}`]: string | number; +}; + +/** + * The mode of the tab + * + * - Button: button style + * - Chrome: chrome style + * + * @default chrome + */ +export type PageTabMode = 'button' | 'chrome'; + +export interface PageTabProps { + /** Whether is dark mode */ + darkMode?: boolean; + /** + * The mode of the tab + * + * - {@link TabMode} + */ + mode?: PageTabMode; + /** + * The common class of the layout + * + * Is can be used to configure the transition animation + * + * @default 'transition-all-300' + */ + commonClass?: string; + /** The class of the button tab */ + buttonClass?: string; + /** The class of the chrome tab */ + chromeClass?: string; + /** Whether the tab is active */ + active?: boolean; + /** The color of the active tab */ + activeColor?: string; + /** + * Whether the tab is closable + * + * Show the close icon when true + */ + closable?: boolean; +} + +export type PageTabCssVarsProps = { + primaryColor: string; + primaryColor1: string; + primaryColor2: string; + primaryColorOpacity1: string; + primaryColorOpacity2: string; + primaryColorOpacity3: string; +}; + +export type PageTabCssVars = { + [K in keyof PageTabCssVarsProps as `${Prefix}${KebabCase}`]: string | number; +}; diff --git a/packages/materials/tsconfig.json b/packages/materials/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/materials/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/ofetch/package.json b/packages/ofetch/package.json new file mode 100644 index 0000000..74aff4f --- /dev/null +++ b/packages/ofetch/package.json @@ -0,0 +1,15 @@ +{ + "name": "@sa/fetch", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "ofetch": "1.4.1" + } +} diff --git a/packages/ofetch/src/index.ts b/packages/ofetch/src/index.ts new file mode 100644 index 0000000..dce1ed4 --- /dev/null +++ b/packages/ofetch/src/index.ts @@ -0,0 +1,10 @@ +import { ofetch } from 'ofetch'; +import type { FetchOptions } from 'ofetch'; + +export function createRequest(options: FetchOptions) { + const request = ofetch.create(options); + + return request; +} + +export default createRequest; diff --git a/packages/ofetch/tsconfig.json b/packages/ofetch/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/ofetch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/scripts/bin.ts b/packages/scripts/bin.ts new file mode 100644 index 0000000..1a1817b --- /dev/null +++ b/packages/scripts/bin.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env tsx + +import './src/index.ts'; diff --git a/packages/scripts/package.json b/packages/scripts/package.json new file mode 100644 index 0000000..fe669aa --- /dev/null +++ b/packages/scripts/package.json @@ -0,0 +1,27 @@ +{ + "name": "@sa/scripts", + "version": "1.3.11", + "bin": { + "sa": "./bin.ts" + }, + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "devDependencies": { + "@soybeanjs/changelog": "0.3.24", + "bumpp": "10.0.3", + "c12": "2.0.2", + "cac": "6.7.14", + "consola": "3.4.0", + "enquirer": "2.4.1", + "execa": "9.5.2", + "kolorist": "1.8.0", + "npm-check-updates": "17.1.14", + "rimraf": "6.0.1" + } +} diff --git a/packages/scripts/src/commands/changelog.ts b/packages/scripts/src/commands/changelog.ts new file mode 100644 index 0000000..e01ce40 --- /dev/null +++ b/packages/scripts/src/commands/changelog.ts @@ -0,0 +1,10 @@ +import { generateChangelog, generateTotalChangelog } from '@soybeanjs/changelog'; +import type { ChangelogOption } from '@soybeanjs/changelog'; + +export async function genChangelog(options?: Partial, total = false) { + if (total) { + await generateTotalChangelog(options); + } else { + await generateChangelog(options); + } +} diff --git a/packages/scripts/src/commands/cleanup.ts b/packages/scripts/src/commands/cleanup.ts new file mode 100644 index 0000000..a9d3990 --- /dev/null +++ b/packages/scripts/src/commands/cleanup.ts @@ -0,0 +1,5 @@ +import { rimraf } from 'rimraf'; + +export async function cleanup(paths: string[]) { + await rimraf(paths, { glob: true }); +} diff --git a/packages/scripts/src/commands/git-commit.ts b/packages/scripts/src/commands/git-commit.ts new file mode 100644 index 0000000..35c0df5 --- /dev/null +++ b/packages/scripts/src/commands/git-commit.ts @@ -0,0 +1,84 @@ +import path from 'node:path'; +import { readFileSync } from 'node:fs'; +import { prompt } from 'enquirer'; +import { execCommand } from '../shared'; +import { locales } from '../locales'; +import type { Lang } from '../locales'; + +interface PromptObject { + types: string; + scopes: string; + description: string; +} + +/** + * Git commit with Conventional Commits standard + * + * @param lang + */ +export async function gitCommit(lang: Lang = 'en-us') { + const { gitCommitMessages, gitCommitTypes, gitCommitScopes } = locales[lang]; + + const typesChoices = gitCommitTypes.map(([value, msg]) => { + const nameWithSuffix = `${value}:`; + + const message = `${nameWithSuffix.padEnd(12)}${msg}`; + + return { + name: value, + message + }; + }); + + const scopesChoices = gitCommitScopes.map(([value, msg]) => ({ + name: value, + message: `${value.padEnd(30)} (${msg})` + })); + + const result = await prompt([ + { + name: 'types', + type: 'select', + message: gitCommitMessages.types, + choices: typesChoices + }, + { + name: 'scopes', + type: 'select', + message: gitCommitMessages.scopes, + choices: scopesChoices + }, + { + name: 'description', + type: 'text', + message: gitCommitMessages.description + } + ]); + + const breaking = result.description.startsWith('!') ? '!' : ''; + + const description = result.description.replace(/^!/, '').trim(); + + const commitMsg = `${result.types}(${result.scopes})${breaking}: ${description}`; + + await execCommand('git', ['commit', '-m', commitMsg], { stdio: 'inherit' }); +} + +/** Git commit message verify */ +export async function gitCommitVerify(lang: Lang = 'en-us', ignores: RegExp[] = []) { + const gitPath = await execCommand('git', ['rev-parse', '--show-toplevel']); + + const gitMsgPath = path.join(gitPath, '.git', 'COMMIT_EDITMSG'); + + const commitMsg = readFileSync(gitMsgPath, 'utf8').trim(); + + if (ignores.some(regExp => regExp.test(commitMsg))) return; + + const REG_EXP = /(?[a-z]+)(?:\((?.+)\))?(?!)?: (?.+)/i; + + if (!REG_EXP.test(commitMsg)) { + const errorMsg = locales[lang].gitCommitVerify; + + throw new Error(errorMsg); + } +} diff --git a/packages/scripts/src/commands/index.ts b/packages/scripts/src/commands/index.ts new file mode 100644 index 0000000..db4fc15 --- /dev/null +++ b/packages/scripts/src/commands/index.ts @@ -0,0 +1,6 @@ +export * from './git-commit'; +export * from './cleanup'; +export * from './update-pkg'; +export * from './changelog'; +export * from './release'; +export * from './router'; diff --git a/packages/scripts/src/commands/release.ts b/packages/scripts/src/commands/release.ts new file mode 100644 index 0000000..1cf3bc3 --- /dev/null +++ b/packages/scripts/src/commands/release.ts @@ -0,0 +1,12 @@ +import { versionBump } from 'bumpp'; + +export async function release(execute = 'pnpm sa changelog', push = true) { + await versionBump({ + files: ['**/package.json', '!**/node_modules'], + execute, + all: true, + tag: true, + commit: 'chore(projects): release v%s', + push + }); +} diff --git a/packages/scripts/src/commands/router.ts b/packages/scripts/src/commands/router.ts new file mode 100644 index 0000000..f407589 --- /dev/null +++ b/packages/scripts/src/commands/router.ts @@ -0,0 +1,90 @@ +import process from 'node:process'; +import path from 'node:path'; +import { writeFile } from 'node:fs/promises'; +import { existsSync, mkdirSync } from 'node:fs'; +import { prompt } from 'enquirer'; +import { green, red } from 'kolorist'; + +interface PromptObject { + routeName: string; + addRouteParams: boolean; + routeParams: string; +} + +/** generate route */ +export async function generateRoute() { + const result = await prompt([ + { + name: 'routeName', + type: 'text', + message: 'please enter route name', + initial: 'demo-route_child' + }, + { + name: 'addRouteParams', + type: 'confirm', + message: 'add route params?', + initial: false + } + ]); + + if (result.addRouteParams) { + const answers = await prompt({ + name: 'routeParams', + type: 'text', + message: 'please enter route params', + initial: 'id' + }); + + Object.assign(result, answers); + } + + const PAGE_DIR_NAME_PATTERN = /^[\w-]+[0-9a-zA-Z]+$/; + + if (!PAGE_DIR_NAME_PATTERN.test(result.routeName)) { + throw new Error(`${red('route name is invalid, it only allow letters, numbers, "-" or "_"')}. +For example: +(1) one level route: ${green('demo-route')} +(2) two level route: ${green('demo-route_child')} +(3) multi level route: ${green('demo-route_child_child')} +(4) group route: ${green('_ignore_demo-route')}' +`); + } + + const PARAM_REG = /^\w+$/g; + + if (result.routeParams && !PARAM_REG.test(result.routeParams)) { + throw new Error(red('route params is invalid, it only allow letters, numbers or "_".')); + } + + const cwd = process.cwd(); + + const [dir, ...rest] = result.routeName.split('_') as string[]; + + let routeDir = path.join(cwd, 'src', 'views', dir); + + if (rest.length) { + routeDir = path.join(routeDir, rest.join('_')); + } + + if (!existsSync(routeDir)) { + mkdirSync(routeDir, { recursive: true }); + } else { + throw new Error(red('route already exists')); + } + + const fileName = result.routeParams ? `[${result.routeParams}].vue` : 'index.vue'; + + const vueTemplate = ` + + + + +`; + + const filePath = path.join(routeDir, fileName); + + await writeFile(filePath, vueTemplate); +} diff --git a/packages/scripts/src/commands/update-pkg.ts b/packages/scripts/src/commands/update-pkg.ts new file mode 100644 index 0000000..54d1132 --- /dev/null +++ b/packages/scripts/src/commands/update-pkg.ts @@ -0,0 +1,5 @@ +import { execCommand } from '../shared'; + +export async function updatePkg(args: string[] = ['--deep', '-u']) { + execCommand('npx', ['ncu', ...args], { stdio: 'inherit' }); +} diff --git a/packages/scripts/src/config/index.ts b/packages/scripts/src/config/index.ts new file mode 100644 index 0000000..0fd9fbe --- /dev/null +++ b/packages/scripts/src/config/index.ts @@ -0,0 +1,39 @@ +import process from 'node:process'; +import { loadConfig } from 'c12'; +import type { CliOption } from '../types'; + +const defaultOptions: CliOption = { + cwd: process.cwd(), + cleanupDirs: [ + '**/dist', + '**/package-lock.json', + '**/yarn.lock', + '**/pnpm-lock.yaml', + '**/node_modules', + '!node_modules/**' + ], + ncuCommandArgs: ['--deep', '-u'], + changelogOptions: {}, + gitCommitVerifyIgnores: [ + /^((Merge pull request)|(Merge (.*?) into (.*?)|(Merge branch (.*?)))(?:\r?\n)*$)/m, + /^(Merge tag (.*?))(?:\r?\n)*$/m, + /^(R|r)evert (.*)/, + /^(amend|fixup|squash)!/, + /^(Merged (.*?)(in|into) (.*)|Merged PR (.*): (.*))/, + /^Merge remote-tracking branch(\s*)(.*)/, + /^Automatic merge(.*)/, + /^Auto-merged (.*?) into (.*)/ + ] +}; + +export async function loadCliOptions(overrides?: Partial, cwd = process.cwd()) { + const { config } = await loadConfig>({ + name: 'soybean', + defaults: defaultOptions, + overrides, + cwd, + packageJson: true + }); + + return config as CliOption; +} diff --git a/packages/scripts/src/index.ts b/packages/scripts/src/index.ts new file mode 100644 index 0000000..34367d7 --- /dev/null +++ b/packages/scripts/src/index.ts @@ -0,0 +1,109 @@ +import cac from 'cac'; +import { blue, lightGreen } from 'kolorist'; +import { version } from '../package.json'; +import { cleanup, genChangelog, generateRoute, gitCommit, gitCommitVerify, release, updatePkg } from './commands'; +import { loadCliOptions } from './config'; +import type { Lang } from './locales'; + +type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify' | 'changelog' | 'release' | 'gen-route'; + +type CommandAction = (args?: A) => Promise | void; + +type CommandWithAction = Record }>; + +interface CommandArg { + /** Execute additional command after bumping and before git commit. Defaults to 'pnpm sa changelog' */ + execute?: string; + /** Indicates whether to push the git commit and tag. Defaults to true */ + push?: boolean; + /** Generate changelog by total tags */ + total?: boolean; + /** + * The glob pattern of dirs to clean up + * + * If not set, it will use the default value + * + * Multiple values use "," to separate them + */ + cleanupDir?: string; + /** + * display lang of cli + * + * @default 'en-us' + */ + lang?: Lang; +} + +export async function setupCli() { + const cliOptions = await loadCliOptions(); + + const cli = cac(blue('soybean-admin')); + + cli + .version(lightGreen(version)) + .option( + '-e, --execute [command]', + "Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog'" + ) + .option('-p, --push', 'Indicates whether to push the git commit and tag') + .option('-t, --total', 'Generate changelog by total tags') + .option( + '-c, --cleanupDir ', + 'The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use "," to separate them' + ) + .option('-l, --lang ', 'display lang of cli', { default: 'en-us', type: [String] }) + .help(); + + const commands: CommandWithAction = { + cleanup: { + desc: 'delete dirs: node_modules, dist, etc.', + action: async () => { + await cleanup(cliOptions.cleanupDirs); + } + }, + 'update-pkg': { + desc: 'update package.json dependencies versions', + action: async () => { + await updatePkg(cliOptions.ncuCommandArgs); + } + }, + 'git-commit': { + desc: 'git commit, generate commit message which match Conventional Commits standard', + action: async args => { + await gitCommit(args?.lang); + } + }, + 'git-commit-verify': { + desc: 'verify git commit message, make sure it match Conventional Commits standard', + action: async args => { + await gitCommitVerify(args?.lang, cliOptions.gitCommitVerifyIgnores); + } + }, + changelog: { + desc: 'generate changelog', + action: async args => { + await genChangelog(cliOptions.changelogOptions, args?.total); + } + }, + release: { + desc: 'release: update version, generate changelog, commit code', + action: async args => { + await release(args?.execute, args?.push); + } + }, + 'gen-route': { + desc: 'generate route', + action: async () => { + await generateRoute(); + } + } + }; + + for (const [command, { desc, action }] of Object.entries(commands)) { + cli.command(command, lightGreen(desc)).action(action); + } + + cli.parse(); +} + +setupCli(); diff --git a/packages/scripts/src/locales/index.ts b/packages/scripts/src/locales/index.ts new file mode 100644 index 0000000..74321d0 --- /dev/null +++ b/packages/scripts/src/locales/index.ts @@ -0,0 +1,82 @@ +import { bgRed, green, red, yellow } from 'kolorist'; + +export type Lang = 'zh-cn' | 'en-us'; + +export const locales = { + 'zh-cn': { + gitCommitMessages: { + types: '请选择提交类型', + scopes: '请选择提交范围', + description: `请输入描述信息(${yellow('!')}开头表示破坏性改动` + }, + gitCommitTypes: [ + ['feat', '新功能'], + ['feat-wip', '开发中的功能,比如某功能的部分代码'], + ['fix', '修复Bug'], + ['docs', '只涉及文档更新'], + ['typo', '代码或文档勘误,比如错误拼写'], + ['style', '修改代码风格,不影响代码含义的变更'], + ['refactor', '代码重构,既不修复 bug 也不添加功能的代码变更'], + ['perf', '可提高性能的代码更改'], + ['optimize', '优化代码质量的代码更改'], + ['test', '添加缺失的测试或更正现有测试'], + ['build', '影响构建系统或外部依赖项的更改'], + ['ci', '对 CI 配置文件和脚本的更改'], + ['chore', '没有修改src或测试文件的其他变更'], + ['revert', '还原先前的提交'] + ] as [string, string][], + gitCommitScopes: [ + ['projects', '项目'], + ['packages', '包'], + ['components', '组件'], + ['hooks', '钩子函数'], + ['utils', '工具函数'], + ['types', 'TS类型声明'], + ['styles', '代码风格'], + ['deps', '项目依赖'], + ['release', '发布项目新版本'], + ['other', '其他的变更'] + ] as [string, string][], + gitCommitVerify: `${bgRed(' 错误 ')} ${red('git 提交信息必须符合 Conventional Commits 标准!')}\n\n${green( + '推荐使用命令 `pnpm commit` 生成符合 Conventional Commits 标准的提交信息。\n获取有关 Conventional Commits 的更多信息,请访问此链接: https://conventionalcommits.org' + )}` + }, + 'en-us': { + gitCommitMessages: { + types: 'Please select a type', + scopes: 'Please select a scope', + description: `Please enter a description (add prefix ${yellow('!')} to indicate breaking change)` + }, + gitCommitTypes: [ + ['feat', 'A new feature'], + ['feat-wip', 'Features in development, such as partial code for a certain feature'], + ['fix', 'A bug fix'], + ['docs', 'Documentation only changes'], + ['typo', 'Code or document corrections, such as spelling errors'], + ['style', 'Changes that do not affect the meaning of the code'], + ['refactor', 'A code change that neither fixes a bug nor adds a feature'], + ['perf', 'A code change that improves performance'], + ['optimize', 'A code change that optimizes code quality'], + ['test', 'Adding missing tests or correcting existing tests'], + ['build', 'Changes that affect the build system or external dependencies'], + ['ci', 'Changes to our CI configuration files and scripts'], + ['chore', "Other changes that don't modify src or test files"], + ['revert', 'Reverts a previous commit'] + ] as [string, string][], + gitCommitScopes: [ + ['projects', 'project'], + ['packages', 'packages'], + ['components', 'components'], + ['hooks', 'hook functions'], + ['utils', 'utils functions'], + ['types', 'TS declaration'], + ['styles', 'style'], + ['deps', 'project dependencies'], + ['release', 'release project'], + ['other', 'other changes'] + ] as [string, string][], + gitCommitVerify: `${bgRed(' ERROR ')} ${red('git commit message must match the Conventional Commits standard!')}\n\n${green( + 'Recommended to use the command `pnpm commit` to generate Conventional Commits compliant commit information.\nGet more info about Conventional Commits, follow this link: https://conventionalcommits.org' + )}` + } +} satisfies Record>; diff --git a/packages/scripts/src/shared/index.ts b/packages/scripts/src/shared/index.ts new file mode 100644 index 0000000..9b1763f --- /dev/null +++ b/packages/scripts/src/shared/index.ts @@ -0,0 +1,7 @@ +import type { Options } from 'execa'; + +export async function execCommand(cmd: string, args: string[], options?: Options) { + const { execa } = await import('execa'); + const res = await execa(cmd, args, options); + return (res?.stdout as string)?.trim() || ''; +} diff --git a/packages/scripts/src/types/index.ts b/packages/scripts/src/types/index.ts new file mode 100644 index 0000000..32bc091 --- /dev/null +++ b/packages/scripts/src/types/index.ts @@ -0,0 +1,31 @@ +import type { ChangelogOption } from '@soybeanjs/changelog'; + +export interface CliOption { + /** The project root directory */ + cwd: string; + /** + * Cleanup dirs + * + * Glob pattern syntax {@link https://github.com/isaacs/minimatch} + * + * @default + * ```json + * ["** /dist", "** /pnpm-lock.yaml", "** /node_modules", "!node_modules/**"] + * ``` + */ + cleanupDirs: string[]; + /** + * Npm-check-updates command args + * + * @default ['--deep', '-u'] + */ + ncuCommandArgs: string[]; + /** + * Options of generate changelog + * + * @link https://github.com/soybeanjs/changelog + */ + changelogOptions: Partial; + /** The ignore pattern list of git commit verify */ + gitCommitVerifyIgnores: RegExp[]; +} diff --git a/packages/scripts/tsconfig.json b/packages/scripts/tsconfig.json new file mode 100644 index 0000000..67ab8a4 --- /dev/null +++ b/packages/scripts/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*", "typings/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/uno-preset/package.json b/packages/uno-preset/package.json new file mode 100644 index 0000000..b6d20a1 --- /dev/null +++ b/packages/uno-preset/package.json @@ -0,0 +1,12 @@ +{ + "name": "@sa/uno-preset", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + } +} diff --git a/packages/uno-preset/src/index.ts b/packages/uno-preset/src/index.ts new file mode 100644 index 0000000..f0b13e1 --- /dev/null +++ b/packages/uno-preset/src/index.ts @@ -0,0 +1,54 @@ +// @unocss-include + +import type { Preset } from '@unocss/core'; +import type { Theme } from '@unocss/preset-uno'; + +export function presetSoybeanAdmin(): Preset { + const preset: Preset = { + name: 'preset-soybean-admin', + shortcuts: [ + { + 'flex-center': 'flex justify-center items-center', + 'flex-x-center': 'flex justify-center', + 'flex-y-center': 'flex items-center', + 'flex-col': 'flex flex-col', + 'flex-col-center': 'flex-center flex-col', + 'flex-col-stretch': 'flex-col items-stretch', + 'i-flex-center': 'inline-flex justify-center items-center', + 'i-flex-x-center': 'inline-flex justify-center', + 'i-flex-y-center': 'inline-flex items-center', + 'i-flex-col': 'flex-col inline-flex', + 'i-flex-col-stretch': 'i-flex-col items-stretch', + 'flex-1-hidden': 'flex-1 overflow-hidden' + }, + { + 'absolute-lt': 'absolute left-0 top-0', + 'absolute-lb': 'absolute left-0 bottom-0', + 'absolute-rt': 'absolute right-0 top-0', + 'absolute-rb': 'absolute right-0 bottom-0', + 'absolute-tl': 'absolute-lt', + 'absolute-tr': 'absolute-rt', + 'absolute-bl': 'absolute-lb', + 'absolute-br': 'absolute-rb', + 'absolute-center': 'absolute-lt flex-center size-full', + 'fixed-lt': 'fixed left-0 top-0', + 'fixed-lb': 'fixed left-0 bottom-0', + 'fixed-rt': 'fixed right-0 top-0', + 'fixed-rb': 'fixed right-0 bottom-0', + 'fixed-tl': 'fixed-lt', + 'fixed-tr': 'fixed-rt', + 'fixed-bl': 'fixed-lb', + 'fixed-br': 'fixed-rb', + 'fixed-center': 'fixed-lt flex-center size-full' + }, + { + 'nowrap-hidden': 'overflow-hidden whitespace-nowrap', + 'ellipsis-text': 'nowrap-hidden text-ellipsis' + } + ] + }; + + return preset; +} + +export default presetSoybeanAdmin; diff --git a/packages/uno-preset/tsconfig.json b/packages/uno-preset/tsconfig.json new file mode 100644 index 0000000..5823ed5 --- /dev/null +++ b/packages/uno-preset/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..f2e3c12 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,22 @@ +{ + "name": "@sa/utils", + "version": "1.3.11", + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "colord": "2.9.3", + "crypto-js": "4.2.0", + "klona": "^2.0.6", + "localforage": "1.10.0", + "nanoid": "5.0.9" + }, + "devDependencies": { + "@types/crypto-js": "4.2.2" + } +} diff --git a/packages/utils/src/color.ts b/packages/utils/src/color.ts new file mode 100644 index 0000000..88c3595 --- /dev/null +++ b/packages/utils/src/color.ts @@ -0,0 +1,252 @@ +import { colord, extend } from 'colord'; +import namesPlugin from 'colord/plugins/names'; +import mixPlugin from 'colord/plugins/mix'; +import type { AnyColor, HsvColor, RgbColor } from 'colord'; + +extend([namesPlugin, mixPlugin]); + +/** + * Add color alpha + * + * @param color - Color + * @param alpha - Alpha (0 - 1) + */ +export function addColorAlpha(color: string, alpha: number) { + return colord(color).alpha(alpha).toHex(); +} + +/** + * Mix color + * + * @param firstColor - First color + * @param secondColor - Second color + * @param ratio - The ratio of the second color (0 - 1) + */ +export function mixColor(firstColor: string, secondColor: string, ratio: number) { + return colord(firstColor).mix(secondColor, ratio).toHex(); +} + +/** + * Transform color with opacity to similar color without opacity + * + * @param color - Color + * @param alpha - Alpha (0 - 1) + * @param bgColor Background color (usually white or black) + */ +export function transformColorWithOpacity(color: string, alpha: number, bgColor = '#ffffff') { + const originColor = addColorAlpha(color, alpha); + const { r: oR, g: oG, b: oB } = colord(originColor).toRgb(); + + const { r: bgR, g: bgG, b: bgB } = colord(bgColor).toRgb(); + + function calRgb(or: number, bg: number, al: number) { + return bg + (or - bg) * al; + } + + const resultRgb: RgbColor = { + r: calRgb(oR, bgR, alpha), + g: calRgb(oG, bgG, alpha), + b: calRgb(oB, bgB, alpha) + }; + + return colord(resultRgb).toHex(); +} + +/** + * Is white color + * + * @param color - Color + */ +export function isWhiteColor(color: string) { + return colord(color).isEqual('#ffffff'); +} + +/** + * Get rgb of color + * + * @param color Color + */ +export function getRgbOfColor(color: string) { + return colord(color).toRgb(); +} + +/** Hue step */ +const hueStep = 2; +/** Saturation step, light color part */ +const saturationStep = 16; +/** Saturation step, dark color part */ +const saturationStep2 = 5; +/** Brightness step, light color part */ +const brightnessStep1 = 5; +/** Brightness step, dark color part */ +const brightnessStep2 = 15; +/** Light color count, main color up */ +const lightColorCount = 5; +/** Dark color count, main color down */ +const darkColorCount = 4; + +/** + * The color index of color palette + * + * From left to right, the color is from light to dark, 6 is main color + */ +type ColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; + +/** + * Get color palette (from left to right, the color is from light to dark, 6 is main color) + * + * @param color - Color + * @param index - The color index of color palette (the main color index is 6) + * @returns Hex color + */ +export function getColorPalette(color: AnyColor, index: ColorIndex): string { + const transformColor = colord(color); + + if (!transformColor.isValid()) { + throw new Error('invalid input color value'); + } + + if (index === 6) { + return colord(transformColor).toHex(); + } + + const isLight = index < 6; + const hsv = transformColor.toHsv(); + const i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1; + + const newHsv: HsvColor = { + h: getHue(hsv, i, isLight), + s: getSaturation(hsv, i, isLight), + v: getValue(hsv, i, isLight) + }; + + return colord(newHsv).toHex(); +} + +/** Map of dark color index and opacity */ +const darkColorMap = [ + { index: 7, opacity: 0.15 }, + { index: 6, opacity: 0.25 }, + { index: 5, opacity: 0.3 }, + { index: 5, opacity: 0.45 }, + { index: 5, opacity: 0.65 }, + { index: 5, opacity: 0.85 }, + { index: 4, opacity: 0.9 }, + { index: 3, opacity: 0.95 }, + { index: 2, opacity: 0.97 }, + { index: 1, opacity: 0.98 } +]; + +/** + * Get color palettes + * + * @param color - Color + * @param darkTheme - Dark theme + * @param darkThemeMixColor - Dark theme mix color (default: #141414) + */ +export function getColorPalettes(color: AnyColor, darkTheme = false, darkThemeMixColor = '#141414'): string[] { + const indexes: ColorIndex[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + const patterns = indexes.map(index => getColorPalette(color, index)); + + if (darkTheme) { + const darkPatterns = darkColorMap.map(({ index, opacity }) => { + const darkColor = colord(darkThemeMixColor).mix(patterns[index], opacity); + + return darkColor; + }); + + return darkPatterns.map(item => colord(item).toHex()); + } + + return patterns; +} + +/** + * Get hue + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getHue(hsv: HsvColor, i: number, isLight: boolean) { + let hue: number; + + const hsvH = Math.round(hsv.h); + + if (hsvH >= 60 && hsvH <= 240) { + hue = isLight ? hsvH - hueStep * i : hsvH + hueStep * i; + } else { + hue = isLight ? hsvH + hueStep * i : hsvH - hueStep * i; + } + + if (hue < 0) { + hue += 360; + } + + if (hue >= 360) { + hue -= 360; + } + + return hue; +} + +/** + * Get saturation + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getSaturation(hsv: HsvColor, i: number, isLight: boolean) { + if (hsv.h === 0 && hsv.s === 0) { + return hsv.s; + } + + let saturation: number; + + if (isLight) { + saturation = hsv.s - saturationStep * i; + } else if (i === darkColorCount) { + saturation = hsv.s + saturationStep; + } else { + saturation = hsv.s + saturationStep2 * i; + } + + if (saturation > 100) { + saturation = 100; + } + + if (isLight && i === lightColorCount && saturation > 10) { + saturation = 10; + } + + if (saturation < 6) { + saturation = 6; + } + + return saturation; +} + +/** + * Get value of hsv + * + * @param hsv - Hsv format color + * @param i - The relative distance from 6 + * @param isLight - Is light color + */ +function getValue(hsv: HsvColor, i: number, isLight: boolean) { + let value: number; + + if (isLight) { + value = hsv.v + brightnessStep1 * i; + } else { + value = hsv.v - brightnessStep2 * i; + } + + if (value > 100) { + value = 100; + } + + return value; +} diff --git a/packages/utils/src/crypto.ts b/packages/utils/src/crypto.ts new file mode 100644 index 0000000..dc173c8 --- /dev/null +++ b/packages/utils/src/crypto.ts @@ -0,0 +1,27 @@ +import CryptoJS from 'crypto-js'; + +export class Crypto { + /** Secret */ + secret: string; + + constructor(secret: string) { + this.secret = secret; + } + + encrypt(data: T): string { + const dataString = JSON.stringify(data); + const encrypted = CryptoJS.AES.encrypt(dataString, this.secret); + return encrypted.toString(); + } + + decrypt(encrypted: string) { + const decrypted = CryptoJS.AES.decrypt(encrypted, this.secret); + const dataString = decrypted.toString(CryptoJS.enc.Utf8); + try { + return JSON.parse(dataString) as T; + } catch { + // avoid parse error + return null; + } + } +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 0000000..79018bd --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,5 @@ +export * from './color'; +export * from './crypto'; +export * from './storage'; +export * from './nanoid'; +export * from './klona'; diff --git a/packages/utils/src/klona.ts b/packages/utils/src/klona.ts new file mode 100644 index 0000000..2fe5927 --- /dev/null +++ b/packages/utils/src/klona.ts @@ -0,0 +1,3 @@ +import { klona as jsonClone } from 'klona/json'; + +export { jsonClone }; diff --git a/packages/utils/src/nanoid.ts b/packages/utils/src/nanoid.ts new file mode 100644 index 0000000..5cc1d2e --- /dev/null +++ b/packages/utils/src/nanoid.ts @@ -0,0 +1,3 @@ +import { nanoid } from 'nanoid'; + +export { nanoid }; diff --git a/packages/utils/src/storage.ts b/packages/utils/src/storage.ts new file mode 100644 index 0000000..850562a --- /dev/null +++ b/packages/utils/src/storage.ts @@ -0,0 +1,76 @@ +import localforage from 'localforage'; + +/** The storage type */ +export type StorageType = 'local' | 'session'; + +export function createStorage(type: StorageType, storagePrefix: string) { + const stg = type === 'session' ? window.sessionStorage : window.localStorage; + + const storage = { + /** + * Set session + * + * @param key Session key + * @param value Session value + */ + set(key: K, value: T[K]) { + const json = JSON.stringify(value); + + stg.setItem(`${storagePrefix}${key as string}`, json); + }, + /** + * Get session + * + * @param key Session key + */ + get(key: K): T[K] | null { + const json = stg.getItem(`${storagePrefix}${key as string}`); + if (json) { + let storageData: T[K] | null = null; + + try { + storageData = JSON.parse(json); + } catch {} + + if (storageData) { + return storageData as T[K]; + } + } + + stg.removeItem(`${storagePrefix}${key as string}`); + + return null; + }, + remove(key: keyof T) { + stg.removeItem(`${storagePrefix}${key as string}`); + }, + clear() { + stg.clear(); + } + }; + return storage; +} + +type LocalForage = Omit & { + getItem(key: K, callback?: (err: any, value: T[K] | null) => void): Promise; + + setItem(key: K, value: T[K], callback?: (err: any, value: T[K]) => void): Promise; + + removeItem(key: keyof T, callback?: (err: any) => void): Promise; +}; + +type LocalforageDriver = 'local' | 'indexedDB' | 'webSQL'; + +export function createLocalforage(driver: LocalforageDriver) { + const driverMap: Record = { + local: localforage.LOCALSTORAGE, + indexedDB: localforage.INDEXEDDB, + webSQL: localforage.WEBSQL + }; + + localforage.config({ + driver: driverMap[driver] + }); + + return localforage as LocalForage; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9410d13 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,8977 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@better-scroll/core': + specifier: 2.5.1 + version: 2.5.1 + '@iconify/vue': + specifier: 4.3.0 + version: 4.3.0(vue@3.5.13(typescript@5.7.3)) + '@sa/axios': + specifier: workspace:* + version: link:packages/axios + '@sa/color': + specifier: workspace:* + version: link:packages/color + '@sa/fetch': + specifier: workspace:* + version: link:packages/ofetch + '@sa/hooks': + specifier: workspace:* + version: link:packages/hooks + '@sa/materials': + specifier: workspace:* + version: link:packages/materials + '@sa/utils': + specifier: workspace:* + version: link:packages/utils + '@vueuse/core': + specifier: 12.5.0 + version: 12.5.0(typescript@5.7.3) + ant-design-vue: + specifier: 4.2.6 + version: 4.2.6(vue@3.5.13(typescript@5.7.3)) + clipboard: + specifier: 2.0.11 + version: 2.0.11 + dayjs: + specifier: 1.11.13 + version: 1.11.13 + defu: + specifier: 6.1.4 + version: 6.1.4 + echarts: + specifier: 5.6.0 + version: 5.6.0 + json5: + specifier: 2.2.3 + version: 2.2.3 + nprogress: + specifier: 0.2.0 + version: 0.2.0 + pinia: + specifier: 3.0.0 + version: 3.0.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3)) + tailwind-merge: + specifier: 3.0.1 + version: 3.0.1 + vue: + specifier: 3.5.13 + version: 3.5.13(typescript@5.7.3) + vue-draggable-plus: + specifier: 0.6.0 + version: 0.6.0(@types/sortablejs@1.15.8) + vue-i18n: + specifier: 11.1.1 + version: 11.1.1(vue@3.5.13(typescript@5.7.3)) + vue-router: + specifier: 4.5.0 + version: 4.5.0(vue@3.5.13(typescript@5.7.3)) + devDependencies: + '@elegant-router/vue': + specifier: 0.3.8 + version: 0.3.8 + '@iconify/json': + specifier: 2.2.305 + version: 2.2.305 + '@sa/scripts': + specifier: workspace:* + version: link:packages/scripts + '@sa/uno-preset': + specifier: workspace:* + version: link:packages/uno-preset + '@soybeanjs/eslint-config': + specifier: 1.4.4 + version: 1.4.4(@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)(vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2))) + '@types/node': + specifier: 22.13.1 + version: 22.13.1 + '@types/nprogress': + specifier: 0.2.3 + version: 0.2.3 + '@unocss/eslint-config': + specifier: 65.4.3 + version: 65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@unocss/preset-icons': + specifier: 65.4.3 + version: 65.4.3 + '@unocss/preset-uno': + specifier: 65.4.3 + version: 65.4.3 + '@unocss/transformer-directives': + specifier: 65.4.3 + version: 65.4.3 + '@unocss/transformer-variant-group': + specifier: 65.4.3 + version: 65.4.3 + '@unocss/vite': + specifier: 65.4.3 + version: 65.4.3(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + '@vitejs/plugin-vue': + specifier: 5.2.1 + version: 5.2.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + '@vitejs/plugin-vue-jsx': + specifier: 4.1.1 + version: 4.1.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + eslint: + specifier: 9.20.0 + version: 9.20.0(jiti@2.4.2) + eslint-plugin-vue: + specifier: 9.32.0 + version: 9.32.0(eslint@9.20.0(jiti@2.4.2)) + lint-staged: + specifier: 15.4.3 + version: 15.4.3 + sass: + specifier: 1.84.0 + version: 1.84.0 + simple-git-hooks: + specifier: 2.11.1 + version: 2.11.1 + tsx: + specifier: 4.19.2 + version: 4.19.2 + typescript: + specifier: 5.7.3 + version: 5.7.3 + unplugin-icons: + specifier: 22.0.0 + version: 22.0.0(@vue/compiler-sfc@3.5.13) + unplugin-vue-components: + specifier: 28.0.0 + version: 28.0.0(@babel/parser@7.26.8)(rollup@4.34.6)(vue@3.5.13(typescript@5.7.3)) + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + vite-plugin-progress: + specifier: 0.0.7 + version: 0.0.7(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)) + vite-plugin-svg-icons: + specifier: 2.0.1 + version: 2.0.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)) + vite-plugin-vue-devtools: + specifier: 7.7.1 + version: 7.7.1(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + vue-eslint-parser: + specifier: 9.4.3 + version: 9.4.3(eslint@9.20.0(jiti@2.4.2)) + vue-tsc: + specifier: 2.2.0 + version: 2.2.0(typescript@5.7.3) + + packages/axios: + dependencies: + '@sa/utils': + specifier: workspace:* + version: link:../utils + axios: + specifier: 1.7.9 + version: 1.7.9 + axios-retry: + specifier: 4.5.0 + version: 4.5.0(axios@1.7.9) + qs: + specifier: 6.14.0 + version: 6.14.0 + devDependencies: + '@types/qs': + specifier: 6.9.18 + version: 6.9.18 + + packages/color: + dependencies: + '@sa/utils': + specifier: workspace:* + version: link:../utils + colord: + specifier: 2.9.3 + version: 2.9.3 + + packages/hooks: + dependencies: + '@sa/axios': + specifier: workspace:* + version: link:../axios + '@sa/utils': + specifier: workspace:^ + version: link:../utils + + packages/materials: + dependencies: + '@sa/utils': + specifier: workspace:* + version: link:../utils + '@simonwep/pickr': + specifier: 1.9.1 + version: 1.9.1 + simplebar-vue: + specifier: 2.4.0 + version: 2.4.0(vue@3.5.13(typescript@5.7.3)) + devDependencies: + typed-css-modules: + specifier: 0.9.1 + version: 0.9.1 + + packages/ofetch: + dependencies: + ofetch: + specifier: 1.4.1 + version: 1.4.1 + + packages/scripts: + devDependencies: + '@soybeanjs/changelog': + specifier: 0.3.24 + version: 0.3.24(@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)(vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2))) + bumpp: + specifier: 10.0.3 + version: 10.0.3 + c12: + specifier: 2.0.2 + version: 2.0.2 + cac: + specifier: 6.7.14 + version: 6.7.14 + consola: + specifier: 3.4.0 + version: 3.4.0 + enquirer: + specifier: 2.4.1 + version: 2.4.1 + execa: + specifier: 9.5.2 + version: 9.5.2 + kolorist: + specifier: 1.8.0 + version: 1.8.0 + npm-check-updates: + specifier: 17.1.14 + version: 17.1.14 + rimraf: + specifier: 6.0.1 + version: 6.0.1 + + packages/uno-preset: {} + + packages/utils: + dependencies: + colord: + specifier: 2.9.3 + version: 2.9.3 + crypto-js: + specifier: 4.2.0 + version: 4.2.0 + klona: + specifier: ^2.0.6 + version: 2.0.6 + localforage: + specifier: 1.10.0 + version: 1.10.0 + nanoid: + specifier: 5.0.9 + version: 5.0.9 + devDependencies: + '@types/crypto-js': + specifier: 4.2.2 + version: 4.2.2 + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@ant-design/colors@6.0.0': + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + + '@ant-design/icons-svg@4.4.2': + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + + '@ant-design/icons-vue@7.0.1': + resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==} + peerDependencies: + vue: '>=3.0.3' + + '@antfu/eslint-define-config@1.23.0-2': + resolution: {integrity: sha512-LvxY21+ZhpuBf/aHeBUtGQhSEfad4PkNKXKvDOSvukaM3XVTfBhwmHX2EKwAsdq5DlfjbT3qqYyMiueBIO5iDQ==} + engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'} + + '@antfu/install-pkg@0.5.0': + resolution: {integrity: sha512-dKnk2xlAyC7rvTkpkHmu+Qy/2Zc3Vm/l8PtNyIOGDBtXPY3kThfU4ORNEp3V7SXw5XSOb+tOJaUYpfquPzL/Tg==} + + '@antfu/install-pkg@1.0.0': + resolution: {integrity: sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==} + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + + '@antfu/utils@8.1.0': + resolution: {integrity: sha512-XPR7Jfwp0FFl/dFYPX8ZjpmU4/1mIXTjnZ1ba48BLMyKOV62/tiRjdsFcPs2hsYcSud4tzk7w3a3LjX8Fu3huA==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.8': + resolution: {integrity: sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.8': + resolution: {integrity: sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.25.9': + resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.7': + resolution: {integrity: sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.8': + resolution: {integrity: sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.25.9': + resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.25.9': + resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.26.8': + resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.26.7': + resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.26.8': + resolution: {integrity: sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.26.8': + resolution: {integrity: sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.8': + resolution: {integrity: sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==} + engines: {node: '>=6.9.0'} + + '@better-scroll/core@2.5.1': + resolution: {integrity: sha512-koKOuYA55dQ04FJRIVUpMGDr1hbCfWmfX0MGp1hKagkQSWSRpwblqACiwtggVauoj9aaJRJZ9hDsTM4weaavlg==} + + '@better-scroll/shared-utils@2.5.1': + resolution: {integrity: sha512-AplkfSjXVYP9LZiD6JsKgmgQJ/mG4uuLmBuwLz8W5OsYc7AYTfN8kw6GqZ5OwCGoXkVhBGyd8NeC4xwYItp0aw==} + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@elegant-router/core@0.3.8': + resolution: {integrity: sha512-q8CihD9la9V2H+/OYIzMLftXSBkbT234UMwhMxDL1Gq7BGKU3kEIEJvifRM7htbiRD77bkQhwMGBY3WZacqw8A==} + + '@elegant-router/vue@0.3.8': + resolution: {integrity: sha512-K9x2275vw9kQB25WnZ7ROTLsT3o8bxu8acvwF09Do8hexIKG2i6elV0+pWxaufNZ4XCuBxT+lKHfHeyBbRhtYQ==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/compat@1.2.6': + resolution: {integrity: sha512-k7HNCqApoDHM6XzT30zGoETj+D+uUcZUb+IVAJmar3u6bvHf7hhHJcWx09QHj4/a2qrKZMWU0E16tvkiAdv06Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/config-array@0.19.2': + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.10.0': + resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.11.0': + resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.16.0': + resolution: {integrity: sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.20.0': + resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.5': + resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + engines: {node: '>=18.18'} + + '@iconify/json@2.2.305': + resolution: {integrity: sha512-hUBioJfu3xiCIRS/+RN1jV4eobOnROWnGCtGxc1f+m1xzhJoxQqso6zqhe0xcWygbgVzwiNggC2W6Hew0m8jXg==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.3.0': + resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} + + '@iconify/vue@4.3.0': + resolution: {integrity: sha512-Xq0h6zMrHBbrW8jXJ9fISi+x8oDQllg5hTDkDuxnWiskJ63rpJu9CvJshj8VniHVTbsxCg9fVoPAaNp3RQI5OQ==} + peerDependencies: + vue: '>=3' + + '@intlify/core-base@11.1.1': + resolution: {integrity: sha512-bb8gZvoeKExCI2r/NVCK9E4YyOkvYGaSCPxVZe8T0jz8aX+dHEOZWxK06Z/Y9mWRkJfBiCH4aOhDF1yr1t5J8Q==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@11.1.1': + resolution: {integrity: sha512-4iEsUZ3aF7jXY19CJFN5VP+pPyLITD9FVsjB13z9TU1UxaZLlFsmNhvRxlPDSOfHAP5RpNF2QKKdZ3DHVf4Yzw==} + engines: {node: '>= 16'} + + '@intlify/shared@11.1.1': + resolution: {integrity: sha512-2kGiWoXaeV8HZlhU/Nml12oTbhv7j2ufsJ5vQaa0VTjzUmZVdd/nmKFRAOJ/FtjO90Qba5AnZDwsrY7ZND5udA==} + engines: {node: '>= 16'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.28': + resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.34.6': + resolution: {integrity: sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.34.6': + resolution: {integrity: sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.34.6': + resolution: {integrity: sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.34.6': + resolution: {integrity: sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.34.6': + resolution: {integrity: sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.6': + resolution: {integrity: sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.6': + resolution: {integrity: sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.34.6': + resolution: {integrity: sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.34.6': + resolution: {integrity: sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.34.6': + resolution: {integrity: sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loongarch64-gnu@4.34.6': + resolution: {integrity: sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.6': + resolution: {integrity: sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.34.6': + resolution: {integrity: sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-s390x-gnu@4.34.6': + resolution: {integrity: sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.34.6': + resolution: {integrity: sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.34.6': + resolution: {integrity: sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-win32-arm64-msvc@4.34.6': + resolution: {integrity: sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.34.6': + resolution: {integrity: sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.34.6': + resolution: {integrity: sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==} + cpu: [x64] + os: [win32] + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@simonwep/pickr@1.8.2': + resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==} + + '@simonwep/pickr@1.9.1': + resolution: {integrity: sha512-fR3qmfAcPf/HSFS7GEnTmZLM3+xERv1+jyMBbzT63ilRRM8veYjI7ELvkHHKk0/du3lHp7uh/FqatjM3646X1g==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@soybeanjs/changelog@0.3.24': + resolution: {integrity: sha512-QQVDFOsAdrYkyE5eEXuwtEi3poIOptkZhA0NxV2dfZoU3ChfFo0pkkuDplgpXaZvx09Omu2i04fdNKxFftAC3w==} + engines: {node: '>=16', pnpm: '>=9'} + + '@soybeanjs/eslint-config@1.4.4': + resolution: {integrity: sha512-URstICwbRggp2LK8DP1aGghUeloQ5UjqrsbttX37CrcSjQ1Af+VZkwpgPzuHyw5HSilcyxfwzgcQUV7haqlnag==} + peerDependencies: + '@toml-tools/parser': '*' + '@unocss/eslint-config': '>=0.58.0' + eslint: '>=8.40.0' + eslint-plugin-astro: '>=0.30.0' + eslint-plugin-react: '>=7.0.0' + eslint-plugin-react-hooks: '>=4.0.0' + eslint-plugin-react-native: '>=4.0.0' + eslint-plugin-react-refresh: '>=0.4.0' + eslint-plugin-solid: '>=0.10.0' + eslint-plugin-svelte: '>=2.0.0' + eslint-plugin-vue: '>=9.19.0' + prettier-plugin-astro: '>=0.12.0' + prettier-plugin-svelte: '>=3.0.0' + prettier-plugin-toml: '>=2.0.0' + typescript: '>=5.0.0' + vue-eslint-parser: '>=9.3.2' + peerDependenciesMeta: + '@toml-tools/parser': + optional: true + '@unocss/eslint-config': + optional: true + eslint-plugin-astro: + optional: true + eslint-plugin-react: + optional: true + eslint-plugin-react-hooks: + optional: true + eslint-plugin-react-native: + optional: true + eslint-plugin-react-refresh: + optional: true + eslint-plugin-solid: + optional: true + eslint-plugin-svelte: + optional: true + eslint-plugin-vue: + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-svelte: + optional: true + prettier-plugin-toml: + optional: true + vue-eslint-parser: + optional: true + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/gensync@1.0.4': + resolution: {integrity: sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@10.17.60': + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + + '@types/node@22.13.1': + resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/nprogress@0.2.3': + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + + '@types/sortablejs@1.15.8': + resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} + + '@types/svgo@2.6.4': + resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/web-bluetooth@0.0.20': + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + '@typescript-eslint/eslint-plugin@8.18.0': + resolution: {integrity: sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/parser@8.18.0': + resolution: {integrity: sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/scope-manager@8.18.0': + resolution: {integrity: sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.24.0': + resolution: {integrity: sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.18.0': + resolution: {integrity: sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/types@8.18.0': + resolution: {integrity: sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@8.24.0': + resolution: {integrity: sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.18.0': + resolution: {integrity: sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/typescript-estree@8.24.0': + resolution: {integrity: sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/utils@8.18.0': + resolution: {integrity: sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/utils@8.24.0': + resolution: {integrity: sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/visitor-keys@8.18.0': + resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.24.0': + resolution: {integrity: sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@unocss/config@65.4.3': + resolution: {integrity: sha512-Z3tnQ10UjM09Y1yVqfCYfZEh2pXFQlUQ1g188mMWxjXWEIXeei3f9dIApRBgC+xcPE6prqdu3fDC5emU+sqyxw==} + engines: {node: '>=14'} + + '@unocss/core@65.4.3': + resolution: {integrity: sha512-luFgdcchSlNrYSaDvU2176T2PPQZdxqfREVbxEXNXlFEgyEFrx5hOSUXoJtJSZjRhAcE6zkWyLDf/JkQJ5Eeyw==} + + '@unocss/eslint-config@65.4.3': + resolution: {integrity: sha512-EfOPGRZlLWIMpWseeocGkQqDBitOOqmDV59WLkhrzocRCV5XTbadSdC4yR8iipUWnNHWxPBboemc24lNQlmMOA==} + engines: {node: '>=14'} + + '@unocss/eslint-plugin@65.4.3': + resolution: {integrity: sha512-uK6WpZPy/zJxunw4lh51KjIO370SRAIFlvg/Knh4Kl5214xiJDezKp7F7NATVBx+JqSf7iHYn2qUdB8Z8I7sXg==} + engines: {node: '>=14'} + + '@unocss/extractor-arbitrary-variants@65.4.3': + resolution: {integrity: sha512-RhSOOzOxkNjJl9zeglaBe0U+o39jleCCNPWJ87DDJA3ckbyylIIf21ZwY1Xu76rmdar5DT9ob7ucuPfEpJLN9A==} + + '@unocss/inspector@65.4.3': + resolution: {integrity: sha512-mj3K0WtnP0DuonQPzxkXhLMBU5qi13dpxaJcEOSv+EBMPlJbww0bj7K7uaFqXv8LPufs/hkQzI9yjOrEzR5WBQ==} + + '@unocss/preset-icons@65.4.3': + resolution: {integrity: sha512-g1WNamvYOIdD8YAOvZ5h4g3peel3rLTtKvB0wX4pVL5exsYsoyc0tmiGm57k+ZmnIucqSzxoUZ/vjHDLAViahw==} + + '@unocss/preset-mini@65.4.3': + resolution: {integrity: sha512-JajAF18DKJRXgd9usrAYTcHUtZy606mD396ZswDgw/mUSu529tuiT6LOD43aJMYHgPEw7wKYjiGFHkeBTHijuQ==} + + '@unocss/preset-uno@65.4.3': + resolution: {integrity: sha512-gxELOQwR3YbMLR+WjYz3m/Zb6VXa8O0Xln0rfS2TI7OXXoQ1twak5zwYPrOI5fJF8lJ5yyKUiXiOR8UEPBpoCQ==} + + '@unocss/preset-wind@65.4.3': + resolution: {integrity: sha512-KM13xIARNeZ/ZKJr33fZ89l79wgI+1Oo8VPJzmckLjbH9IGOhcH2GON7wVIxQqqqM9IM3vALEqw2KNdM6ontWw==} + + '@unocss/rule-utils@65.4.3': + resolution: {integrity: sha512-bzRRdb9mb82IvgOt3KiRyUh/njRfJC3hoV84lMyUPryT8YTEP/hl6kt2KQ2l1K3WDz7ZPQXVi2eqUbqc+AUpwg==} + engines: {node: '>=14'} + + '@unocss/transformer-directives@65.4.3': + resolution: {integrity: sha512-e3zZYjXqHSWb6YrC09/FnCsndhZdRzmYhPubTzOjnvb5K0ihIiLvHx9c2TRPWvMspXs0wHKQsLW5fAs8oyimeQ==} + + '@unocss/transformer-variant-group@65.4.3': + resolution: {integrity: sha512-nZNgKLclhIjfuqCaZTmJwhWSByL7vnhb3l/ChRX4qtWOweRLro79r6MvfcqQNrweK5nCw4yibsXCrFUWq7Jj5w==} + + '@unocss/vite@65.4.3': + resolution: {integrity: sha512-YajF8Z2J/KvXdnC5BsGJjt3fm4D14vmYaHdlTyzi92Rkh/67JtaCz2OhElDoF6k4S4fm9B8uLRP10p+smRe9Fw==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 + + '@vitejs/plugin-vue-jsx@4.1.1': + resolution: {integrity: sha512-uMJqv/7u1zz/9NbWAD3XdjaY20tKTf17XVfQ9zq4wY1BjsB/PjpJPMe2xiG39QpP4ZdhYNhm4Hvo66uJrykNLA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@5.2.1': + resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.11': + resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} + + '@volar/source-map@2.4.11': + resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==} + + '@volar/typescript@2.4.11': + resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==} + + '@vue/babel-helper-vue-transform-on@1.2.5': + resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==} + + '@vue/babel-plugin-jsx@1.2.5': + resolution: {integrity: sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.2.5': + resolution: {integrity: sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + + '@vue/compiler-sfc@3.5.13': + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + + '@vue/compiler-ssr@3.5.13': + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-api@7.7.1': + resolution: {integrity: sha512-Cexc8GimowoDkJ6eNelOPdYIzsu2mgNyp0scOQ3tiaYSb9iok6LOESSsJvHaI+ib3joRfqRJNLkHFjhNuWA5dg==} + + '@vue/devtools-core@7.7.1': + resolution: {integrity: sha512-W4CRrSZJodNIfrPO7/dXF6ZS0QyOY6PCYVhpSoTSx9+nh2wpZxcS1482lAdKM0FTlaoApHV6jXT95Me90hSaBA==} + peerDependencies: + vue: ^3.0.0 + + '@vue/devtools-kit@7.7.1': + resolution: {integrity: sha512-yhZ4NPnK/tmxGtLNQxmll90jIIXdb2jAhPF76anvn5M/UkZCiLJy28bYgPIACKZ7FCosyKoaope89/RsFJll1w==} + + '@vue/devtools-shared@7.7.1': + resolution: {integrity: sha512-BtgF7kHq4BHG23Lezc/3W2UhK2ga7a8ohAIAGJMBr4BkxUFzhqntQtCiuL1ijo2ztWnmusymkirgqUrXoQKumA==} + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.13': + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + + '@vue/runtime-core@3.5.13': + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + + '@vue/runtime-dom@3.5.13': + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + + '@vue/server-renderer@3.5.13': + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} + peerDependencies: + vue: 3.5.13 + + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + + '@vueuse/core@12.5.0': + resolution: {integrity: sha512-GVyH1iYqNANwcahAx8JBm6awaNgvR/SwZ1fjr10b8l1HIgDp82ngNbfzJUgOgWEoxjL+URAggnlilAEXwCOZtg==} + + '@vueuse/metadata@12.5.0': + resolution: {integrity: sha512-Ui7Lo2a7AxrMAXRF+fAp9QsXuwTeeZ8fIB9wsLHqzq9MQk+2gMYE2IGJW48VMJ8ecvCB3z3GsGLKLbSasQ5Qlg==} + + '@vueuse/shared@12.5.0': + resolution: {integrity: sha512-vMpcL1lStUU6O+kdj6YdHDixh0odjPAUM15uJ9f7MY781jcYkIwFA4iv2EfoIPO6vBmvutI1HxxAwmf0cx5ISQ==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ant-design-vue@4.2.6: + resolution: {integrity: sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==} + engines: {node: '>=12.22.0'} + peerDependencies: + vue: '>=3.2.0' + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + args-tokenizer@0.3.0: + resolution: {integrity: sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q==} + + arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + + arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + + arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + + array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios-retry@4.5.0: + resolution: {integrity: sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==} + peerDependencies: + axios: 0.x || 1.x + + axios@1.7.9: + resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + binary-searching@2.0.5: + resolution: {integrity: sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==} + + birpc@0.2.19: + resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + bumpp@10.0.3: + resolution: {integrity: sha512-5ONBZenNf9yfTIl2vFvDEfeeioidt0fG10SzjHQw50BRxOmXzsdY+lab1+SDMfiW6UyJ1xQqzFymcy5wa8YhTA==} + engines: {node: '>=18'} + hasBin: true + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + c12@2.0.2: + resolution: {integrity: sha512-NkvlL5CHZt9kPswJYDCUYtTaMt7JOfcpsnNncfj7sWsc13x6Wz+GiTpBtqZOojFlzyTHui8+OAfR6praV6PYaQ==} + peerDependencies: + magicast: ^0.3.5 + peerDependenciesMeta: + magicast: + optional: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001699: + resolution: {integrity: sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + ci-info@4.1.0: + resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} + engines: {node: '>=8'} + + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + + class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-progress@3.12.0: + resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} + engines: {node: '>=4'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + clipboard@2.0.11: + resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + + collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + engines: {node: ^14.18.0 || >=16.10.0} + + convert-gitmoji@0.1.5: + resolution: {integrity: sha512-4wqOafJdk2tqZC++cjcbGcaJ13BZ3kwldf06PTiAQRAB76Z1KJwZNL1SaRZMi2w1FM9RYTgZ6QErS8NUl/GBmQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + + core-js-compat@3.40.0: + resolution: {integrity: sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==} + + core-js@3.37.0: + resolution: {integrity: sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug==} + + core-js@3.40.0: + resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + dayjs@1.11.11: + resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + + define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + + define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegate@3.2.0: + resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + + dom-scroll-into-view@2.0.1: + resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} + + dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + echarts@5.6.0: + resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} + + electron-to-chromium@1.5.97: + resolution: {integrity: sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + error-stack-parser-es@0.1.5: + resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==} + + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-flat-gitignore@0.3.0: + resolution: {integrity: sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==} + peerDependencies: + eslint: ^9.5.0 + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-parser-plain@0.1.0: + resolution: {integrity: sha512-oOeA6FWU0UJT/Rxc3XF5Cq0nbIZbylm7j8+plqq0CZoE6m4u32OXJrR+9iy4srGMmF6v6pmgvP1zPxSRIGh3sg==} + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import-x@4.5.0: + resolution: {integrity: sha512-l0OTfnPF8RwmSXfjT75N8d6ZYLVrVYWpaGlgvVkVqFERCI5SyBfDP7QEMr3kt0zWi2sOa9EQ47clbdFsHkF83Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + eslint-plugin-n@17.15.0: + resolution: {integrity: sha512-xF3zJkOfLlFOm5TvmqmsnA9/fO+/z2pYs0dkuKXKN/ymS6UB1yEcaoIkqxLKQ9Dw/WmLX/Tdh6/5ZS5azVixFQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.23.0' + + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-plugin-unicorn@56.0.1: + resolution: {integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==} + engines: {node: '>=18.18'} + peerDependencies: + eslint: '>=8.56.0' + + eslint-plugin-vue@9.32.0: + resolution: {integrity: sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.20.0: + resolution: {integrity: sha512-aL4F8167Hg4IvsW89ejnpTwx+B/UQRzJPGgbIOl+4XqffWsahVVsLEWoZvnrVuwpWmnRd7XeXmQI1zlKcFDteA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + execa@9.1.0: + resolution: {integrity: sha512-lSgHc4Elo2m6bUDhc3Hl/VxvUDJdQWI40RZ4KMY9bKRc+hgMOT7II/JjbNDhI8VnMtrCb7U/fhpJIkLORZozWw==} + engines: {node: '>=18'} + + execa@9.5.2: + resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} + engines: {node: ^18.19.0 || >=20.5.0} + + expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + + extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.0: + resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} + + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + + fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.2.7: + resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + + get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + + giget@1.2.4: + resolution: {integrity: sha512-Wv+daGyispVoA31TrWAVR+aAdP7roubTPEM/8JzRnqXhLbdJH0T9eQyXVFF8fjk3WKTsctII6QcyxILYgNp2DA==} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} + engines: {node: 20 || >=22} + hasBin: true + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.13.0: + resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} + engines: {node: '>=18'} + + globals@15.14.0: + resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + good-listener@1.2.2: + resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + + has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + + has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + + has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + human-signals@7.0.0: + resolution: {integrity: sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==} + engines: {node: '>=18.18.0'} + + human-signals@8.0.0: + resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} + engines: {node: '>=18.18.0'} + + icss-replace-symbols@1.1.0: + resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + immutable@5.0.3: + resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + importx@0.5.1: + resolution: {integrity: sha512-YrRaigAec1sC2CdIJjf/hCH1Wp9Ii8Cq5ROw4k5nJ19FVl2FcJUHZ5gGIb1vs8+JNYIyOJpc2fcufS2330bxDw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + + is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-plain-object@3.0.1: + resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} + engines: {node: '>=0.10.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-retry-allowed@2.2.0: + resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} + engines: {node: '>=10'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-there@4.5.1: + resolution: {integrity: sha512-vIZ7HTXAoRoIwYSsTnxb0sg9L6rth+JOulNcavsbskQkCIWoSM2cjFOWZs4wGziGZER+Xgs/HXiCQZgiL8ppxQ==} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + + kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + + kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.4.3: + resolution: {integrity: sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + + local-pkg@1.0.0: + resolution: {integrity: sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==} + engines: {node: '>=14'} + + localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magicast@0.3.4: + resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + + merge-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-core-commonmark@2.0.2: + resolution: {integrity: sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.0.4: + resolution: {integrity: sha512-N6hXjrin2GTJDe3MVjf5FuXpm12PGm80BrUAeub9XFXca8JZbP+oIwY4LJSVwFUCL1IPm/WwSVUN7goFHmSGGQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.1: + resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==} + + micromark@4.0.1: + resolution: {integrity: sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==} + + micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.0.9: + resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} + engines: {node: ^18 || >=20} + hasBin: true + + nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + + nanopop@2.4.2: + resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-fetch-native@1.6.6: + resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-check-updates@17.1.14: + resolution: {integrity: sha512-dr4bXIxETubLI1tFGeock5hN8yVjahvaVpx+lPO4/O2md3zJuxB7FgH3MIoTvQSCgsgkIRpe0skti01IEAA5tA==} + engines: {node: ^18.18.0 || >=20.0.0, npm: '>=8.12.1'} + hasBin: true + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nypm@0.5.2: + resolution: {integrity: sha512-AHzvnyUJYSrrphPhRWWZNcoZfArGNp3Vrc4pm/ZurO74tYNTgAPrEyBQEKy+qioqmWlPXwvMZCG2wOaHlPG0Pw==} + engines: {node: ^14.16.0 || >=16.10.0} + hasBin: true + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + ofetch@1.3.4: + resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} + + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + + ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.9: + resolution: {integrity: sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.2: + resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pinia@3.0.0: + resolution: {integrity: sha512-Go23UsqaeABb4OYNmpDkE9VwDnqmbbjGzWpQhi3xfNkSPO6ZP+Ttt0EMo2J4DHXW+T0l3EqRneeXdyV/oJg/Mg==} + peerDependencies: + typescript: '>=4.4.4' + vue: ^2.7.0 || ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-prefix-selector@1.16.1: + resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==} + peerDependencies: + postcss: '>4 <9' + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + + postcss@8.5.2: + resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==} + engines: {node: ^10 || ^12 || >=14} + + posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + + posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + + posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + + posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + + posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-jsdoc@1.3.0: + resolution: {integrity: sha512-cQm8xIa0fN9ieJFMXACQd6JPycl+8ouOijAqUqu44EF/s4fXL3Wi9sKXuEaodsEWgCN42Xby/bNhqgM1iWx4uw==} + engines: {node: '>=14.13.1 || >=16.0.0'} + peerDependencies: + prettier: ^3.0.0 + + prettier-plugin-json-sort@0.0.2: + resolution: {integrity: sha512-xd5VVfneeUBdWhTm5uh0rAto3qnkkosbte6poO5WVTZEAiQdndMQMRPv1SROXx968zfyAlS+Z+C6rkr4jbVOgg==} + peerDependencies: + prettier: '>=2.0.0' + + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} + hasBin: true + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + + rd@2.0.1: + resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.1: + resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==} + engines: {node: '>= 14.18.0'} + + recast@0.23.9: + resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} + engines: {node: '>= 4'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + + repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + rollup@4.34.6: + resolution: {integrity: sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + + sass@1.84.0: + resolution: {integrity: sha512-XDAbhEPJRxi7H0SxrnOpiXFQoUJHwkR2u3Zc4el+fK/Tt5Hpzw5kkQ59qVDfvdaUq6gCrEZIbySFBM2T9DNKHg==} + engines: {node: '>=14.0.0'} + hasBin: true + + scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + + select@1.1.2: + resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + + shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-git-hooks@2.11.1: + resolution: {integrity: sha512-tgqwPUMDcNDhuf1Xf6KTUsyeqGdgKMhzaH4PAZZuzguOgTl5uuyeYe/8mWgAr6IBxB5V06uqEf6Dy37gIWDtDg==} + hasBin: true + + simplebar-core@1.3.0: + resolution: {integrity: sha512-LpWl3w0caz0bl322E68qsrRPpIn+rWBGAaEJ0lUJA7Xpr2sw92AkIhg6VWj988IefLXYh50ILatfAnbNoCFrlA==} + + simplebar-vue@2.4.0: + resolution: {integrity: sha512-XUFGqoTCjzTKRWLHmS0/gy03GF7Id9FZhczrAqC3tbFO5OZ9vRCdzMZ7F2MuCI5+fp6Plpvug9GUgyBDJLTc5A==} + peerDependencies: + vue: '>=2.5.17' + + sirv@3.0.0: + resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} + engines: {node: '>=18'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + + snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + + snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + + strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + + superjson@2.2.2: + resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} + engines: {node: '>=16'} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tailwind-merge@3.0.1: + resolution: {integrity: sha512-AvzE8FmSoXC7nC+oU5GlQJbip2UO7tmOhOfQyOmPhrStOGXHU08j8mZEHZ4BmCqY5dWTCo4ClWkNyRNx1wpT0g==} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} + engines: {node: '>=12.22'} + + tiny-emitter@2.1.0: + resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.10: + resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} + engines: {node: '>=12.0.0'} + + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + + to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + traverse@0.6.11: + resolution: {integrity: sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==} + engines: {node: '>= 0.4'} + + ts-api-utils@1.4.3: + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.19.2: + resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typed-css-modules@0.9.1: + resolution: {integrity: sha512-W2HWKncdKd+bLWsnuWB2EyuQBzZ7KJ9Byr/67KLiiyGegcN52rOveun9JR8yAvuL5IXunRMxt0eORMtAUj5bmA==} + engines: {node: '>=18.0.0'} + hasBin: true + + typedarray.prototype.slice@1.0.5: + resolution: {integrity: sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==} + engines: {node: '>= 0.4'} + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + unconfig@0.6.1: + resolution: {integrity: sha512-cVU+/sPloZqOyJEAfNwnQSFCzFrZm85vcVkryH7lnlB/PiTycUkAjt5Ds79cfIshGOZ+M5v3PBDnKgpmlE5DtA==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin-icons@22.0.0: + resolution: {integrity: sha512-+1jIt2wynxL+GISehNok8MIb9RaCufIZCHJs0HKbxOljJL9m4NtOhva+dZhNtSKtfQ62Hwd/RRbniSVuuD4Xow==} + peerDependencies: + '@svgr/core': '>=7.0.0' + '@svgx/core': ^1.0.1 + '@vue/compiler-sfc': ^3.0.2 || ^2.7.0 + svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 + vue-template-compiler: ^2.6.12 + vue-template-es2015-compiler: ^1.9.0 + peerDependenciesMeta: + '@svgr/core': + optional: true + '@svgx/core': + optional: true + '@vue/compiler-sfc': + optional: true + svelte: + optional: true + vue-template-compiler: + optional: true + vue-template-es2015-compiler: + optional: true + + unplugin-vue-components@28.0.0: + resolution: {integrity: sha512-vYe0wSyqTVhyNFIad1iiGyQGhG++tDOMgohqenMDOAooMJP9vvzCdXTqCVx20A0rCQXFNjgoRbSeDAioLPH36Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/parser': ^7.15.8 + '@nuxt/kit': ^3.2.2 + vue: 2 || 3 + peerDependenciesMeta: + '@babel/parser': + optional: true + '@nuxt/kit': + optional: true + + unplugin@1.12.0: + resolution: {integrity: sha512-KeczzHl2sATPQUx1gzo+EnUkmN4VmGBYRRVOZSGvGITE9rGHRDGqft6ONceP3vgXcyJ2XjX5axG5jMWUwNCYLw==} + engines: {node: '>=14.0.0'} + + unplugin@2.2.0: + resolution: {integrity: sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw==} + engines: {node: '>=18.12.0'} + + unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + + update-browserslist-db@1.1.2: + resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + + use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite-hot-client@0.2.4: + resolution: {integrity: sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==} + peerDependencies: + vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 + + vite-plugin-inspect@0.8.9: + resolution: {integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + vite-plugin-progress@0.0.7: + resolution: {integrity: sha512-zyvKdcc/X+6hnw3J1HVV1TKrlFKC4Rh8GnDnWG/2qhRXjqytTcM++xZ+SAPnoDsSyWl8O93ymK0wZRgHAoglEQ==} + engines: {node: '>=14', pnpm: '>=7.0.0'} + peerDependencies: + vite: '>2.0.0-0' + + vite-plugin-svg-icons@2.0.1: + resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-vue-devtools@7.7.1: + resolution: {integrity: sha512-f1Fnda4CJYH7t7K1WaTEjFTLdF4oUkmlZTVwBGG5UhJ+Oa5KPX0Ue32c+YWRMOpCtFbCDl1iXGgQVzg8Ew5JnQ==} + engines: {node: '>=v14.21.3'} + peerDependencies: + vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 + + vite-plugin-vue-inspector@5.3.1: + resolution: {integrity: sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A==} + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 + + vite@6.1.0: + resolution: {integrity: sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.13.11: + resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-draggable-plus@0.6.0: + resolution: {integrity: sha512-G5TSfHrt9tX9EjdG49InoFJbt2NYk0h3kgjgKxkFWr3ulIUays0oFObr5KZ8qzD4+QnhtALiRwIqY6qul4egqw==} + peerDependencies: + '@types/sortablejs': ^1.15.0 + '@vue/composition-api': '*' + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-eslint-parser@9.4.3: + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + vue-flow-layout@0.1.1: + resolution: {integrity: sha512-JdgRRUVrN0Y2GosA0M68DEbKlXMqJ7FQgsK8CjQD2vxvNSqAU6PZEpi4cfcTVtfM2GVOMjHo7GKKLbXxOBqDqA==} + peerDependencies: + vue: ^3.4.37 + + vue-i18n@11.1.1: + resolution: {integrity: sha512-0P6DkKy96R4Wh2sIZJEHw8ivnlD1pnB6Ib/eldoF1SUpQutfKZv6aMqZwICS1gW0rwq24ZSXw7y3jW+PRVYqWA==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + + vue-router@4.5.0: + resolution: {integrity: sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==} + peerDependencies: + vue: ^3.2.0 + + vue-tsc@2.2.0: + resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue-types@3.0.2: + resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==} + engines: {node: '>=10.15.0'} + peerDependencies: + vue: ^3.0.0 + + vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + + webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.18: + resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zrender@5.6.1: + resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@ant-design/colors@6.0.0': + dependencies: + '@ctrl/tinycolor': 3.6.1 + + '@ant-design/icons-svg@4.4.2': {} + + '@ant-design/icons-vue@7.0.1(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.4.2 + vue: 3.5.13(typescript@5.7.3) + + '@antfu/eslint-define-config@1.23.0-2': {} + + '@antfu/install-pkg@0.5.0': + dependencies: + package-manager-detector: 0.2.9 + tinyexec: 0.3.2 + + '@antfu/install-pkg@1.0.0': + dependencies: + package-manager-detector: 0.2.9 + tinyexec: 0.3.2 + + '@antfu/utils@0.7.10': {} + + '@antfu/utils@8.1.0': {} + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.8': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.8 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.8) + '@babel/helpers': 7.26.7 + '@babel/parser': 7.26.8 + '@babel/template': 7.26.8 + '@babel/traverse': 7.26.8 + '@babel/types': 7.26.8 + '@types/gensync': 1.0.4 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.8': + dependencies: + '@babel/parser': 7.26.8 + '@babel/types': 7.26.8 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.26.8 + + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.8) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.26.8 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.9': + dependencies: + '@babel/traverse': 7.26.8 + '@babel/types': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.8 + '@babel/types': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.9': + dependencies: + '@babel/types': 7.26.8 + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + dependencies: + '@babel/traverse': 7.26.8 + '@babel/types': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.7': + dependencies: + '@babel/template': 7.26.8 + '@babel/types': 7.26.8 + + '@babel/parser@7.26.8': + dependencies: + '@babel/types': 7.26.8 + + '@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.8) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.8)': + dependencies: + '@babel/core': 7.26.8 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.8) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.8) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.26.7': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.26.8': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.8 + '@babel/types': 7.26.8 + + '@babel/traverse@7.26.8': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.8 + '@babel/parser': 7.26.8 + '@babel/template': 7.26.8 + '@babel/types': 7.26.8 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.8': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@better-scroll/core@2.5.1': + dependencies: + '@better-scroll/shared-utils': 2.5.1 + + '@better-scroll/shared-utils@2.5.1': {} + + '@ctrl/tinycolor@3.6.1': {} + + '@elegant-router/core@0.3.8': + dependencies: + chokidar: 3.6.0 + consola: 3.2.3 + fast-glob: 3.3.2 + kolorist: 1.8.0 + micromatch: 4.0.7 + + '@elegant-router/vue@0.3.8': + dependencies: + '@elegant-router/core': 0.3.8 + consola: 3.2.3 + kolorist: 1.8.0 + magic-string: 0.30.11 + magicast: 0.3.4 + prettier: 3.3.3 + recast: 0.23.9 + unplugin: 1.12.0 + + '@emotion/hash@0.9.2': {} + + '@emotion/unitless@0.8.1': {} + + '@esbuild/aix-ppc64@0.23.1': + optional: true + + '@esbuild/aix-ppc64@0.24.2': + optional: true + + '@esbuild/android-arm64@0.23.1': + optional: true + + '@esbuild/android-arm64@0.24.2': + optional: true + + '@esbuild/android-arm@0.23.1': + optional: true + + '@esbuild/android-arm@0.24.2': + optional: true + + '@esbuild/android-x64@0.23.1': + optional: true + + '@esbuild/android-x64@0.24.2': + optional: true + + '@esbuild/darwin-arm64@0.23.1': + optional: true + + '@esbuild/darwin-arm64@0.24.2': + optional: true + + '@esbuild/darwin-x64@0.23.1': + optional: true + + '@esbuild/darwin-x64@0.24.2': + optional: true + + '@esbuild/freebsd-arm64@0.23.1': + optional: true + + '@esbuild/freebsd-arm64@0.24.2': + optional: true + + '@esbuild/freebsd-x64@0.23.1': + optional: true + + '@esbuild/freebsd-x64@0.24.2': + optional: true + + '@esbuild/linux-arm64@0.23.1': + optional: true + + '@esbuild/linux-arm64@0.24.2': + optional: true + + '@esbuild/linux-arm@0.23.1': + optional: true + + '@esbuild/linux-arm@0.24.2': + optional: true + + '@esbuild/linux-ia32@0.23.1': + optional: true + + '@esbuild/linux-ia32@0.24.2': + optional: true + + '@esbuild/linux-loong64@0.23.1': + optional: true + + '@esbuild/linux-loong64@0.24.2': + optional: true + + '@esbuild/linux-mips64el@0.23.1': + optional: true + + '@esbuild/linux-mips64el@0.24.2': + optional: true + + '@esbuild/linux-ppc64@0.23.1': + optional: true + + '@esbuild/linux-ppc64@0.24.2': + optional: true + + '@esbuild/linux-riscv64@0.23.1': + optional: true + + '@esbuild/linux-riscv64@0.24.2': + optional: true + + '@esbuild/linux-s390x@0.23.1': + optional: true + + '@esbuild/linux-s390x@0.24.2': + optional: true + + '@esbuild/linux-x64@0.23.1': + optional: true + + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/netbsd-x64@0.24.2': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.24.2': + optional: true + + '@esbuild/openbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-x64@0.24.2': + optional: true + + '@esbuild/sunos-x64@0.23.1': + optional: true + + '@esbuild/sunos-x64@0.24.2': + optional: true + + '@esbuild/win32-arm64@0.23.1': + optional: true + + '@esbuild/win32-arm64@0.24.2': + optional: true + + '@esbuild/win32-ia32@0.23.1': + optional: true + + '@esbuild/win32-ia32@0.24.2': + optional: true + + '@esbuild/win32-x64@0.23.1': + optional: true + + '@esbuild/win32-x64@0.24.2': + optional: true + + '@eslint-community/eslint-utils@4.4.1(eslint@9.20.0(jiti@2.4.2))': + dependencies: + eslint: 9.20.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/compat@1.2.6(eslint@9.20.0(jiti@2.4.2))': + optionalDependencies: + eslint: 9.20.0(jiti@2.4.2) + + '@eslint/config-array@0.19.2': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/core@0.10.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/core@0.11.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.2.0': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.16.0': {} + + '@eslint/js@9.20.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.5': + dependencies: + '@eslint/core': 0.10.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.1': {} + + '@iconify/json@2.2.305': + dependencies: + '@iconify/types': 2.0.0 + pathe: 1.1.2 + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.3.0': + dependencies: + '@antfu/install-pkg': 1.0.0 + '@antfu/utils': 8.1.0 + '@iconify/types': 2.0.0 + debug: 4.4.0 + globals: 15.14.0 + kolorist: 1.8.0 + local-pkg: 1.0.0 + mlly: 1.7.4 + transitivePeerDependencies: + - supports-color + + '@iconify/vue@4.3.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@iconify/types': 2.0.0 + vue: 3.5.13(typescript@5.7.3) + + '@intlify/core-base@11.1.1': + dependencies: + '@intlify/message-compiler': 11.1.1 + '@intlify/shared': 11.1.1 + + '@intlify/message-compiler@11.1.1': + dependencies: + '@intlify/shared': 11.1.1 + source-map-js: 1.2.1 + + '@intlify/shared@11.1.1': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.0 + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@polka/url@1.0.0-next.28': {} + + '@rollup/pluginutils@5.1.4(rollup@4.34.6)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.34.6 + + '@rollup/rollup-android-arm-eabi@4.34.6': + optional: true + + '@rollup/rollup-android-arm64@4.34.6': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.6': + optional: true + + '@rollup/rollup-darwin-x64@4.34.6': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.6': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.6': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.6': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.6': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.6': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.6': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.6': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.6': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.6': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.6': + optional: true + + '@sec-ant/readable-stream@0.4.1': {} + + '@simonwep/pickr@1.8.2': + dependencies: + core-js: 3.40.0 + nanopop: 2.4.2 + + '@simonwep/pickr@1.9.1': + dependencies: + core-js: 3.37.0 + nanopop: 2.4.2 + + '@sindresorhus/merge-streams@4.0.0': {} + + '@soybeanjs/changelog@0.3.24(@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)(vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2)))': + dependencies: + '@soybeanjs/eslint-config': 1.4.4(@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)(vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2))) + cli-progress: 3.12.0 + convert-gitmoji: 0.1.5 + dayjs: 1.11.11 + execa: 9.1.0 + ofetch: 1.3.4 + semver: 7.6.2 + transitivePeerDependencies: + - '@toml-tools/parser' + - '@types/eslint' + - '@unocss/eslint-config' + - eslint + - eslint-plugin-astro + - eslint-plugin-react + - eslint-plugin-react-hooks + - eslint-plugin-react-native + - eslint-plugin-react-refresh + - eslint-plugin-solid + - eslint-plugin-svelte + - eslint-plugin-vue + - prettier-plugin-astro + - prettier-plugin-svelte + - prettier-plugin-toml + - supports-color + - typescript + - vue-eslint-parser + + '@soybeanjs/eslint-config@1.4.4(@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)(vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2)))': + dependencies: + '@antfu/eslint-define-config': 1.23.0-2 + '@antfu/install-pkg': 0.5.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.16.0 + '@typescript-eslint/eslint-plugin': 8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.20.0(jiti@2.4.2) + eslint-config-flat-gitignore: 0.3.0(eslint@9.20.0(jiti@2.4.2)) + eslint-config-prettier: 9.1.0(eslint@9.20.0(jiti@2.4.2)) + eslint-parser-plain: 0.1.0 + eslint-plugin-import-x: 4.5.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + eslint-plugin-n: 17.15.0(eslint@9.20.0(jiti@2.4.2)) + eslint-plugin-prettier: 5.2.1(eslint-config-prettier@9.1.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(prettier@3.4.2) + eslint-plugin-unicorn: 56.0.1(eslint@9.20.0(jiti@2.4.2)) + globals: 15.13.0 + local-pkg: 0.5.1 + prettier: 3.4.2 + prettier-plugin-jsdoc: 1.3.0(prettier@3.4.2) + prettier-plugin-json-sort: 0.0.2(prettier@3.4.2) + prompts: 2.4.2 + typescript: 5.7.3 + optionalDependencies: + '@unocss/eslint-config': 65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + eslint-plugin-vue: 9.32.0(eslint@9.20.0(jiti@2.4.2)) + vue-eslint-parser: 9.4.3(eslint@9.20.0(jiti@2.4.2)) + transitivePeerDependencies: + - '@types/eslint' + - supports-color + + '@trysound/sax@0.2.0': {} + + '@types/crypto-js@4.2.2': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree@1.0.6': {} + + '@types/gensync@1.0.4': {} + + '@types/json-schema@7.0.15': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@2.1.0': {} + + '@types/node@10.17.60': {} + + '@types/node@22.13.1': + dependencies: + undici-types: 6.20.0 + + '@types/normalize-package-data@2.4.4': {} + + '@types/nprogress@0.2.3': {} + + '@types/qs@6.9.18': {} + + '@types/sortablejs@1.15.8': {} + + '@types/svgo@2.6.4': + dependencies: + '@types/node': 22.13.1 + + '@types/unist@3.0.3': {} + + '@types/web-bluetooth@0.0.20': {} + + '@typescript-eslint/eslint-plugin@8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/type-utils': 8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.18.0 + eslint: 9.20.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.18.0 + debug: 4.4.0 + eslint: 9.20.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.18.0': + dependencies: + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/visitor-keys': 8.18.0 + + '@typescript-eslint/scope-manager@8.24.0': + dependencies: + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/visitor-keys': 8.24.0 + + '@typescript-eslint/type-utils@8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.0 + eslint: 9.20.0(jiti@2.4.2) + ts-api-utils: 1.4.3(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.18.0': {} + + '@typescript-eslint/types@8.24.0': {} + + '@typescript-eslint/typescript-estree@8.18.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/visitor-keys': 8.18.0 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 1.4.3(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.24.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/visitor-keys': 8.24.0 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.18.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.3) + eslint: 9.20.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.24.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.24.0 + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) + eslint: 9.20.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.18.0': + dependencies: + '@typescript-eslint/types': 8.18.0 + eslint-visitor-keys: 4.2.0 + + '@typescript-eslint/visitor-keys@8.24.0': + dependencies: + '@typescript-eslint/types': 8.24.0 + eslint-visitor-keys: 4.2.0 + + '@unocss/config@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + unconfig: 0.6.1 + transitivePeerDependencies: + - supports-color + + '@unocss/core@65.4.3': {} + + '@unocss/eslint-config@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@unocss/eslint-plugin': 65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@unocss/eslint-plugin@65.4.3(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/utils': 8.24.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + '@unocss/config': 65.4.3 + '@unocss/core': 65.4.3 + '@unocss/rule-utils': 65.4.3 + magic-string: 0.30.17 + synckit: 0.9.2 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@unocss/extractor-arbitrary-variants@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + + '@unocss/inspector@65.4.3(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@unocss/core': 65.4.3 + '@unocss/rule-utils': 65.4.3 + colorette: 2.0.20 + gzip-size: 6.0.0 + sirv: 3.0.0 + vue-flow-layout: 0.1.1(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - vue + + '@unocss/preset-icons@65.4.3': + dependencies: + '@iconify/utils': 2.3.0 + '@unocss/core': 65.4.3 + ofetch: 1.4.1 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-mini@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + '@unocss/extractor-arbitrary-variants': 65.4.3 + '@unocss/rule-utils': 65.4.3 + + '@unocss/preset-uno@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + '@unocss/preset-mini': 65.4.3 + '@unocss/preset-wind': 65.4.3 + '@unocss/rule-utils': 65.4.3 + + '@unocss/preset-wind@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + '@unocss/preset-mini': 65.4.3 + '@unocss/rule-utils': 65.4.3 + + '@unocss/rule-utils@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + magic-string: 0.30.17 + + '@unocss/transformer-directives@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + '@unocss/rule-utils': 65.4.3 + css-tree: 3.1.0 + + '@unocss/transformer-variant-group@65.4.3': + dependencies: + '@unocss/core': 65.4.3 + + '@unocss/vite@65.4.3(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.4(rollup@4.34.6) + '@unocss/config': 65.4.3 + '@unocss/core': 65.4.3 + '@unocss/inspector': 65.4.3(vue@3.5.13(typescript@5.7.3)) + chokidar: 3.6.0 + magic-string: 0.30.17 + tinyglobby: 0.2.10 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - rollup + - supports-color + - vue + + '@vitejs/plugin-vue-jsx@4.1.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@babel/core': 7.26.8 + '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.8) + '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.8) + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.2.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + vue: 3.5.13(typescript@5.7.3) + + '@volar/language-core@2.4.11': + dependencies: + '@volar/source-map': 2.4.11 + + '@volar/source-map@2.4.11': {} + + '@volar/typescript@2.4.11': + dependencies: + '@volar/language-core': 2.4.11 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/babel-helper-vue-transform-on@1.2.5': {} + + '@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.8)': + dependencies: + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.8) + '@babel/template': 7.26.8 + '@babel/traverse': 7.26.8 + '@babel/types': 7.26.8 + '@vue/babel-helper-vue-transform-on': 1.2.5 + '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.26.8) + html-tags: 3.3.1 + svg-tags: 1.0.0 + optionalDependencies: + '@babel/core': 7.26.8 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.26.8)': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/core': 7.26.8 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/parser': 7.26.8 + '@vue/compiler-sfc': 3.5.13 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.26.8 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-sfc@3.5.13': + dependencies: + '@babel/parser': 7.26.8 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.2 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.13': + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-api@7.7.1': + dependencies: + '@vue/devtools-kit': 7.7.1 + + '@vue/devtools-core@7.7.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@vue/devtools-kit': 7.7.1 + '@vue/devtools-shared': 7.7.1 + mitt: 3.0.1 + nanoid: 5.0.9 + pathe: 2.0.2 + vite-hot-client: 0.2.4(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - vite + + '@vue/devtools-kit@7.7.1': + dependencies: + '@vue/devtools-shared': 7.7.1 + birpc: 0.2.19 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 + + '@vue/devtools-shared@7.7.1': + dependencies: + rfdc: 1.4.1 + + '@vue/language-core@2.2.0(typescript@5.7.3)': + dependencies: + '@volar/language-core': 2.4.11 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.13 + alien-signals: 0.4.14 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.7.3 + + '@vue/reactivity@3.5.13': + dependencies: + '@vue/shared': 3.5.13 + + '@vue/runtime-core@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/runtime-dom@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13(typescript@5.7.3) + + '@vue/shared@3.5.13': {} + + '@vueuse/core@12.5.0(typescript@5.7.3)': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 12.5.0 + '@vueuse/shared': 12.5.0(typescript@5.7.3) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - typescript + + '@vueuse/metadata@12.5.0': {} + + '@vueuse/shared@12.5.0(typescript@5.7.3)': + dependencies: + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - typescript + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn@8.14.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + alien-signals@0.4.14: {} + + ansi-colors@4.1.3: {} + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + + ansi-regex@2.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@2.2.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + ant-design-vue@4.2.6(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-vue': 7.0.1(vue@3.5.13(typescript@5.7.3)) + '@babel/runtime': 7.26.7 + '@ctrl/tinycolor': 3.6.1 + '@emotion/hash': 0.9.2 + '@emotion/unitless': 0.8.1 + '@simonwep/pickr': 1.8.2 + array-tree-filter: 2.1.0 + async-validator: 4.2.5 + csstype: 3.1.3 + dayjs: 1.11.13 + dom-align: 1.12.4 + dom-scroll-into-view: 2.0.1 + lodash: 4.17.21 + lodash-es: 4.17.21 + resize-observer-polyfill: 1.5.1 + scroll-into-view-if-needed: 2.2.31 + shallow-equal: 1.2.1 + stylis: 4.3.6 + throttle-debounce: 5.0.2 + vue: 3.5.13(typescript@5.7.3) + vue-types: 3.0.2(vue@3.5.13(typescript@5.7.3)) + warning: 4.0.3 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + args-tokenizer@0.3.0: {} + + arr-diff@4.0.0: {} + + arr-flatten@1.1.0: {} + + arr-union@3.1.0: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + is-array-buffer: 3.0.5 + + array-tree-filter@2.1.0: {} + + array-unique@0.3.2: {} + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + is-array-buffer: 3.0.5 + + assign-symbols@1.0.0: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + async-function@1.0.0: {} + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + atob@2.1.2: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axios-retry@4.5.0(axios@1.7.9): + dependencies: + axios: 1.7.9 + is-retry-allowed: 2.2.0 + + axios@1.7.9: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.1 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + base@0.11.2: + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + + big.js@5.2.2: {} + + binary-extensions@2.3.0: {} + + binary-searching@2.0.5: {} + + birpc@0.2.19: {} + + bluebird@3.7.2: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@2.3.2: + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001699 + electron-to-chromium: 1.5.97 + node-releases: 2.0.19 + update-browserslist-db: 1.1.2(browserslist@4.24.4) + + builtin-modules@3.3.0: {} + + bumpp@10.0.3: + dependencies: + args-tokenizer: 0.3.0 + c12: 2.0.2 + cac: 6.7.14 + escalade: 3.2.0 + js-yaml: 4.1.0 + jsonc-parser: 3.3.1 + package-manager-detector: 0.2.9 + prompts: 2.4.2 + semver: 7.7.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.10 + transitivePeerDependencies: + - magicast + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + bundle-require@5.1.0(esbuild@0.24.2): + dependencies: + esbuild: 0.24.2 + load-tsconfig: 0.2.5 + + c12@2.0.2: + dependencies: + chokidar: 4.0.3 + confbox: 0.1.8 + defu: 6.1.4 + dotenv: 16.4.7 + giget: 1.2.4 + jiti: 2.4.2 + mlly: 1.7.4 + ohash: 1.1.4 + pathe: 2.0.2 + perfect-debounce: 1.0.0 + pkg-types: 1.3.1 + rc9: 2.1.2 + + cac@6.7.14: {} + + cache-base@1.0.1: + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + + call-bind-apply-helpers@1.0.1: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + get-intrinsic: 1.2.7 + set-function-length: 1.2.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.1 + get-intrinsic: 1.2.7 + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001699: {} + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.4.1: {} + + character-entities@2.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.1 + + chownr@2.0.0: {} + + ci-info@4.1.0: {} + + citty@0.1.6: + dependencies: + consola: 3.4.0 + + class-utils@0.3.6: + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-progress@3.12.0: + dependencies: + string-width: 4.2.3 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + clipboard@2.0.11: + dependencies: + good-listener: 1.2.2 + select: 1.1.2 + tiny-emitter: 2.1.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@2.1.2: {} + + collection-visit@1.0.0: + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@13.1.0: {} + + commander@7.2.0: {} + + comment-parser@1.4.1: {} + + component-emitter@1.3.1: {} + + compute-scroll-into-view@1.0.20: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + consola@3.2.3: {} + + consola@3.4.0: {} + + convert-gitmoji@0.1.5: {} + + convert-source-map@2.0.0: {} + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + copy-descriptor@0.1.1: {} + + core-js-compat@3.40.0: + dependencies: + browserslist: 4.24.4 + + core-js@3.37.0: {} + + core-js@3.40.0: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-js@4.2.0: {} + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + css-what@6.1.0: {} + + cssesc@3.0.0: {} + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + csstype@3.1.3: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dayjs@1.11.11: {} + + dayjs@1.11.13: {} + + de-indent@1.0.2: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + + decode-uri-component@0.2.2: {} + + deep-is@0.1.4: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + define-property@0.2.5: + dependencies: + is-descriptor: 0.1.7 + + define-property@1.0.0: + dependencies: + is-descriptor: 1.0.3 + + define-property@2.0.2: + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + delegate@3.2.0: {} + + dequal@2.0.3: {} + + destr@2.0.3: {} + + detect-libc@1.0.3: + optional: true + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-align@1.12.4: {} + + dom-scroll-into-view@2.0.1: {} + + dom-serializer@0.2.2: + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@1.3.1: {} + + domelementtype@2.3.0: {} + + domhandler@2.4.2: + dependencies: + domelementtype: 1.3.1 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domutils@1.7.0: + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dotenv@16.4.7: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + echarts@5.6.0: + dependencies: + tslib: 2.3.0 + zrender: 5.6.1 + + electron-to-chromium@1.5.97: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@1.1.2: {} + + entities@2.2.0: {} + + entities@4.5.0: {} + + environment@1.1.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser-es@0.1.5: {} + + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.2.7 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.18 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-compat-utils@0.5.1(eslint@9.20.0(jiti@2.4.2)): + dependencies: + eslint: 9.20.0(jiti@2.4.2) + semver: 7.7.1 + + eslint-config-flat-gitignore@0.3.0(eslint@9.20.0(jiti@2.4.2)): + dependencies: + '@eslint/compat': 1.2.6(eslint@9.20.0(jiti@2.4.2)) + eslint: 9.20.0(jiti@2.4.2) + find-up-simple: 1.0.0 + + eslint-config-prettier@9.1.0(eslint@9.20.0(jiti@2.4.2)): + dependencies: + eslint: 9.20.0(jiti@2.4.2) + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-parser-plain@0.1.0: {} + + eslint-plugin-es-x@7.8.0(eslint@9.20.0(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + eslint: 9.20.0(jiti@2.4.2) + eslint-compat-utils: 0.5.1(eslint@9.20.0(jiti@2.4.2)) + + eslint-plugin-import-x@4.5.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@typescript-eslint/scope-manager': 8.24.0 + '@typescript-eslint/utils': 8.24.0(eslint@9.20.0(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.0 + doctrine: 3.0.0 + eslint: 9.20.0(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + get-tsconfig: 4.10.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + stable-hash: 0.0.4 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-n@17.15.0(eslint@9.20.0(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + enhanced-resolve: 5.18.1 + eslint: 9.20.0(jiti@2.4.2) + eslint-plugin-es-x: 7.8.0(eslint@9.20.0(jiti@2.4.2)) + get-tsconfig: 4.10.0 + globals: 15.13.0 + ignore: 5.3.2 + minimatch: 9.0.5 + semver: 7.7.1 + + eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@9.20.0(jiti@2.4.2)))(eslint@9.20.0(jiti@2.4.2))(prettier@3.4.2): + dependencies: + eslint: 9.20.0(jiti@2.4.2) + prettier: 3.4.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.9.2 + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@9.20.0(jiti@2.4.2)) + + eslint-plugin-unicorn@56.0.1(eslint@9.20.0(jiti@2.4.2)): + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + ci-info: 4.1.0 + clean-regexp: 1.0.0 + core-js-compat: 3.40.0 + eslint: 9.20.0(jiti@2.4.2) + esquery: 1.6.0 + globals: 15.13.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.1.0 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.7.1 + strip-indent: 3.0.0 + + eslint-plugin-vue@9.32.0(eslint@9.20.0(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + eslint: 9.20.0(jiti@2.4.2) + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.7.1 + vue-eslint-parser: 9.4.3(eslint@9.20.0(jiti@2.4.2)) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.2.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.20.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.2 + '@eslint/core': 0.11.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.20.0 + '@eslint/plugin-kit': 0.2.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + + espree@9.6.1: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@5.0.1: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + execa@9.1.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 7.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 5.3.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + execa@9.5.2: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + expand-brackets@2.1.4: + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend-shallow@3.0.2: + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + extglob@2.0.4: + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.0: + dependencies: + reusify: 1.0.4 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@4.0.0: + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up-simple@1.0.0: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + + flatted@3.3.2: {} + + follow-redirects@1.15.9: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + for-in@1.0.2: {} + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + fragment-cache@0.2.1: + dependencies: + map-cache: 0.2.2 + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.2.7: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@8.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-value@2.0.6: {} + + giget@1.2.4: + dependencies: + citty: 0.1.6 + consola: 3.4.0 + defu: 6.1.4 + node-fetch-native: 1.6.6 + nypm: 0.5.2 + ohash: 1.1.4 + pathe: 2.0.2 + tar: 6.2.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.0.1: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + globals@11.12.0: {} + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + globals@15.13.0: {} + + globals@15.14.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + good-listener@1.2.2: + dependencies: + delegate: 3.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@1.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-value@0.3.1: + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + has-value@1.0.0: + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + has-values@0.1.4: {} + + has-values@1.0.0: + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + hookable@5.5.3: {} + + hosted-git-info@2.8.9: {} + + html-tags@3.3.1: {} + + htmlparser2@3.10.1: + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + + human-signals@5.0.0: {} + + human-signals@7.0.0: {} + + human-signals@8.0.0: {} + + icss-replace-symbols@1.1.0: {} + + icss-utils@5.1.0(postcss@8.5.2): + dependencies: + postcss: 8.5.2 + + ignore@5.3.2: {} + + image-size@0.5.5: {} + + immediate@3.0.6: {} + + immutable@5.0.3: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + importx@0.5.1: + dependencies: + bundle-require: 5.1.0(esbuild@0.24.2) + debug: 4.4.0 + esbuild: 0.24.2 + jiti: 2.4.2 + pathe: 1.1.2 + tsx: 4.19.2 + transitivePeerDependencies: + - supports-color + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-accessor-descriptor@1.0.1: + dependencies: + hasown: 2.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-buffer@1.1.6: {} + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-descriptor@1.0.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-descriptor@0.1.7: + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + is-descriptor@1.0.3: + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + is-docker@3.0.0: {} + + is-extendable@0.1.1: {} + + is-extendable@1.0.1: + dependencies: + is-plain-object: 2.0.4 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.3 + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-map@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-number@3.0.0: + dependencies: + kind-of: 3.2.2 + + is-number@7.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-plain-object@3.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-retry-allowed@2.2.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.3 + + is-stream@3.0.0: {} + + is-stream@4.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.3 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-there@4.5.1: {} + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.18 + + is-unicode-supported@2.1.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.3 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + + is-what@4.1.16: {} + + is-windows@1.0.2: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isobject@2.1.0: + dependencies: + isarray: 1.0.0 + + isobject@3.0.1: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.0.2: + dependencies: + '@isaacs/cliui': 8.0.2 + + jiti@2.4.2: {} + + js-base64@2.6.4: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@0.5.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonc-parser@3.3.1: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@3.2.2: + dependencies: + is-buffer: 1.1.6 + + kind-of@4.0.0: + dependencies: + is-buffer: 1.1.6 + + kind-of@5.1.0: {} + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + klona@2.0.6: {} + + kolorist@1.8.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lie@3.1.1: + dependencies: + immediate: 3.0.6 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.4.3: + dependencies: + chalk: 5.4.1 + commander: 13.1.0 + debug: 4.4.0 + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.2.5 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.7.0 + transitivePeerDependencies: + - supports-color + + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + load-tsconfig@0.2.5: {} + + loader-utils@1.4.2: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + local-pkg@0.5.1: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + + local-pkg@1.0.0: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + + localforage@1.10.0: + dependencies: + lie: 3.1.1 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} + + lru-cache@11.0.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.11: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.4: + dependencies: + '@babel/parser': 7.26.8 + '@babel/types': 7.26.8 + source-map-js: 1.2.1 + + map-cache@0.2.2: {} + + map-visit@1.0.0: + dependencies: + object-visit: 1.0.1 + + math-intrinsics@1.1.0: {} + + mdast-util-from-markdown@2.0.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdn-data@2.0.14: {} + + mdn-data@2.12.2: {} + + merge-options@1.0.1: + dependencies: + is-plain-obj: 1.1.0 + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromark-core-commonmark@2.0.2: + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.0.4 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.1 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.1 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.0.4: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.1: {} + + micromark@4.0.1: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.0 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.2 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.0.4 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + transitivePeerDependencies: + - supports-color + + micromatch@3.1.0: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + min-indent@1.0.1: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minipass@7.1.2: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mitt@3.0.1: {} + + mixin-deep@1.3.2: + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + mkdirp@1.0.4: {} + + mkdirp@3.0.1: {} + + mlly@1.7.4: + dependencies: + acorn: 8.14.0 + pathe: 2.0.2 + pkg-types: 1.3.1 + ufo: 1.5.4 + + mrmime@2.0.0: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.8: {} + + nanoid@5.0.9: {} + + nanomatch@1.2.13: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + nanopop@2.4.2: {} + + natural-compare@1.4.0: {} + + node-addon-api@7.1.1: + optional: true + + node-fetch-native@1.6.6: {} + + node-releases@2.0.19: {} + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.10 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + npm-check-updates@17.1.14: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + nprogress@0.2.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nypm@0.5.2: + dependencies: + citty: 0.1.6 + consola: 3.4.0 + pathe: 2.0.2 + pkg-types: 1.3.1 + tinyexec: 0.3.2 + ufo: 1.5.4 + + object-assign@4.1.1: {} + + object-copy@0.1.0: + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object-visit@1.0.1: + dependencies: + isobject: 3.0.1 + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + ofetch@1.3.4: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.6 + ufo: 1.5.4 + + ofetch@1.4.1: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.6 + ufo: 1.5.4 + + ohash@1.1.4: {} + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@10.1.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.2.7 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.9: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-ms@4.0.0: {} + + pascalcase@0.1.1: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + + pathe@0.2.0: {} + + pathe@1.1.2: {} + + pathe@2.0.2: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pidtree@0.6.0: {} + + pinia@3.0.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@vue/devtools-api': 7.7.1 + vue: 3.5.13(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.2 + + pluralize@8.0.0: {} + + posix-character-classes@0.1.1: {} + + possible-typed-array-names@1.1.0: {} + + postcss-modules-extract-imports@3.1.0(postcss@8.5.2): + dependencies: + postcss: 8.5.2 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.2): + dependencies: + icss-utils: 5.1.0(postcss@8.5.2) + postcss: 8.5.2 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.2): + dependencies: + postcss: 8.5.2 + postcss-selector-parser: 7.1.0 + + postcss-modules-values@4.0.0(postcss@8.5.2): + dependencies: + icss-utils: 5.1.0(postcss@8.5.2) + postcss: 8.5.2 + + postcss-prefix-selector@1.16.1(postcss@5.2.18): + dependencies: + postcss: 5.2.18 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@5.2.18: + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + + postcss@8.5.2: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + posthtml-parser@0.2.1: + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + + posthtml-rename-id@1.0.12: + dependencies: + escape-string-regexp: 1.0.5 + + posthtml-render@1.4.0: {} + + posthtml-svg-mode@1.0.3: + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + posthtml@0.9.2: + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier-plugin-jsdoc@1.3.0(prettier@3.4.2): + dependencies: + binary-searching: 2.0.5 + comment-parser: 1.4.1 + mdast-util-from-markdown: 2.0.2 + prettier: 3.4.2 + transitivePeerDependencies: + - supports-color + + prettier-plugin-json-sort@0.0.2(prettier@3.4.2): + dependencies: + prettier: 3.4.2 + + prettier@3.3.3: {} + + prettier@3.4.2: {} + + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + + progress@2.0.3: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + query-string@4.3.4: + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + + queue-microtask@1.2.3: {} + + rc9@2.1.2: + dependencies: + defu: 6.1.4 + destr: 2.0.3 + + rd@2.0.1: + dependencies: + '@types/node': 10.17.60 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.1: {} + + recast@0.23.9: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.2.7 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerator-runtime@0.14.1: {} + + regex-not@1.0.2: + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regjsparser@0.10.0: + dependencies: + jsesc: 0.5.0 + + repeat-element@1.1.4: {} + + repeat-string@1.6.1: {} + + require-directory@2.1.1: {} + + resize-observer-polyfill@1.5.1: {} + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve-url@0.2.1: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + ret@0.1.15: {} + + reusify@1.0.4: {} + + rfdc@1.4.1: {} + + rimraf@6.0.1: + dependencies: + glob: 11.0.1 + package-json-from-dist: 1.0.1 + + rollup@4.34.6: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.6 + '@rollup/rollup-android-arm64': 4.34.6 + '@rollup/rollup-darwin-arm64': 4.34.6 + '@rollup/rollup-darwin-x64': 4.34.6 + '@rollup/rollup-freebsd-arm64': 4.34.6 + '@rollup/rollup-freebsd-x64': 4.34.6 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.6 + '@rollup/rollup-linux-arm-musleabihf': 4.34.6 + '@rollup/rollup-linux-arm64-gnu': 4.34.6 + '@rollup/rollup-linux-arm64-musl': 4.34.6 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.6 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.6 + '@rollup/rollup-linux-riscv64-gnu': 4.34.6 + '@rollup/rollup-linux-s390x-gnu': 4.34.6 + '@rollup/rollup-linux-x64-gnu': 4.34.6 + '@rollup/rollup-linux-x64-musl': 4.34.6 + '@rollup/rollup-win32-arm64-msvc': 4.34.6 + '@rollup/rollup-win32-ia32-msvc': 4.34.6 + '@rollup/rollup-win32-x64-msvc': 4.34.6 + fsevents: 2.3.3 + + run-applescript@7.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex@1.1.0: + dependencies: + ret: 0.1.15 + + sass@1.84.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.0.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + select@1.1.2: {} + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.2: {} + + semver@7.7.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.7 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + set-value@2.0.1: + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + + shallow-equal@1.2.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@4.1.0: {} + + simple-git-hooks@2.11.1: {} + + simplebar-core@1.3.0: + dependencies: + lodash: 4.17.21 + + simplebar-vue@2.4.0(vue@3.5.13(typescript@5.7.3)): + dependencies: + simplebar-core: 1.3.0 + vue: 3.5.13(typescript@5.7.3) + vue-demi: 0.13.11(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - '@vue/composition-api' + + sirv@3.0.0: + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.0 + totalist: 3.0.1 + + sisteransi@1.0.5: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + snapdragon-node@2.1.1: + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + snapdragon-util@3.0.1: + dependencies: + kind-of: 3.2.2 + + snapdragon@0.8.2: + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + + source-map-js@1.2.1: {} + + source-map-resolve@0.5.3: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + + source-map-url@0.4.1: {} + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-license-ids@3.0.21: {} + + speakingurl@14.0.1: {} + + split-string@3.1.0: + dependencies: + extend-shallow: 3.0.2 + + stable-hash@0.0.4: {} + + stable@0.1.8: {} + + static-extend@0.1.2: + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + strict-uri-encode@1.1.0: {} + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-final-newline@3.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + stylis@4.3.6: {} + + superjson@2.2.2: + dependencies: + copy-anything: 3.0.5 + + supports-color@2.0.0: {} + + supports-color@3.2.3: + dependencies: + has-flag: 1.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-baker@1.7.0: + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.1(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.11 + transitivePeerDependencies: + - supports-color + + svg-tags@1.0.0: {} + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + stable: 0.1.8 + + synckit@0.9.2: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.1 + + tailwind-merge@3.0.1: {} + + tapable@2.2.1: {} + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + throttle-debounce@5.0.2: {} + + tiny-emitter@2.1.0: {} + + tiny-invariant@1.3.3: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.10: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + to-object-path@0.3.0: + dependencies: + kind-of: 3.2.2 + + to-regex-range@2.1.1: + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-regex@3.0.2: + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + + totalist@3.0.1: {} + + traverse@0.6.11: + dependencies: + gopd: 1.2.0 + typedarray.prototype.slice: 1.0.5 + which-typed-array: 1.1.18 + + ts-api-utils@1.4.3(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-api-utils@2.0.1(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + tslib@2.3.0: {} + + tslib@2.8.1: {} + + tsx@4.19.2: + dependencies: + esbuild: 0.23.1 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typed-css-modules@0.9.1: + dependencies: + camelcase: 6.3.0 + chalk: 4.1.2 + chokidar: 3.6.0 + glob: 10.4.5 + icss-replace-symbols: 1.1.0 + is-there: 4.5.1 + mkdirp: 3.0.1 + postcss: 8.5.2 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.2) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.2) + postcss-modules-scope: 3.2.1(postcss@8.5.2) + postcss-modules-values: 4.0.0(postcss@8.5.2) + yargs: 17.7.2 + + typedarray.prototype.slice@1.0.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-proto: 1.0.1 + math-intrinsics: 1.1.0 + typed-array-buffer: 1.0.3 + typed-array-byte-offset: 1.0.4 + + typescript@5.7.3: {} + + ufo@1.5.4: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.3 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + unconfig@0.6.1: + dependencies: + '@antfu/utils': 8.1.0 + defu: 6.1.4 + importx: 0.5.1 + transitivePeerDependencies: + - supports-color + + undici-types@6.20.0: {} + + unicorn-magic@0.3.0: {} + + union-value@1.0.1: + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + universalify@2.0.1: {} + + unplugin-icons@22.0.0(@vue/compiler-sfc@3.5.13): + dependencies: + '@antfu/install-pkg': 0.5.0 + '@antfu/utils': 0.7.10 + '@iconify/utils': 2.3.0 + debug: 4.4.0 + kolorist: 1.8.0 + local-pkg: 0.5.1 + unplugin: 2.2.0 + optionalDependencies: + '@vue/compiler-sfc': 3.5.13 + transitivePeerDependencies: + - supports-color + + unplugin-vue-components@28.0.0(@babel/parser@7.26.8)(rollup@4.34.6)(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.4(rollup@4.34.6) + chokidar: 3.6.0 + debug: 4.4.0 + fast-glob: 3.3.3 + local-pkg: 0.5.1 + magic-string: 0.30.17 + minimatch: 9.0.5 + mlly: 1.7.4 + unplugin: 2.2.0 + vue: 3.5.13(typescript@5.7.3) + optionalDependencies: + '@babel/parser': 7.26.8 + transitivePeerDependencies: + - rollup + - supports-color + + unplugin@1.12.0: + dependencies: + acorn: 8.14.0 + chokidar: 3.6.0 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.6.2 + + unplugin@2.2.0: + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + + unset-value@1.0.0: + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + update-browserslist-db@1.1.2(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + urix@0.1.0: {} + + use@3.1.1: {} + + util-deprecate@1.0.2: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + vary@1.1.2: {} + + vite-hot-client@0.2.4(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + + vite-plugin-inspect@0.8.9(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.4(rollup@4.34.6) + debug: 4.4.0 + error-stack-parser-es: 0.1.5 + fs-extra: 11.3.0 + open: 10.1.0 + perfect-debounce: 1.0.0 + picocolors: 1.1.1 + sirv: 3.0.0 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - rollup + - supports-color + + vite-plugin-progress@0.0.7(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + picocolors: 1.1.1 + progress: 2.0.3 + rd: 2.0.1 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + + vite-plugin-svg-icons@2.0.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + '@types/svgo': 2.6.4 + cors: 2.8.5 + debug: 4.4.0 + etag: 1.8.1 + fs-extra: 10.1.0 + pathe: 0.2.0 + svg-baker: 1.7.0 + svgo: 2.8.0 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + vite-plugin-vue-devtools@7.7.1(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@vue/devtools-core': 7.7.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + '@vue/devtools-kit': 7.7.1 + '@vue/devtools-shared': 7.7.1 + execa: 9.5.2 + sirv: 3.0.0 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + vite-plugin-inspect: 0.8.9(rollup@4.34.6)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)) + vite-plugin-vue-inspector: 5.3.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)) + transitivePeerDependencies: + - '@nuxt/kit' + - rollup + - supports-color + - vue + + vite-plugin-vue-inspector@5.3.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + '@babel/core': 7.26.8 + '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.8) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.8) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.8) + '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.8) + '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.8) + '@vue/compiler-dom': 3.5.13 + kolorist: 1.8.0 + magic-string: 0.30.17 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(sass@1.84.0)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + esbuild: 0.24.2 + postcss: 8.5.2 + rollup: 4.34.6 + optionalDependencies: + '@types/node': 22.13.1 + fsevents: 2.3.3 + jiti: 2.4.2 + sass: 1.84.0 + tsx: 4.19.2 + yaml: 2.7.0 + + vscode-uri@3.1.0: {} + + vue-demi@0.13.11(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + + vue-draggable-plus@0.6.0(@types/sortablejs@1.15.8): + dependencies: + '@types/sortablejs': 1.15.8 + + vue-eslint-parser@9.4.3(eslint@9.20.0(jiti@2.4.2)): + dependencies: + debug: 4.4.0 + eslint: 9.20.0(jiti@2.4.2) + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + lodash: 4.17.21 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + vue-flow-layout@0.1.1(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + + vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@intlify/core-base': 11.1.1 + '@intlify/shared': 11.1.1 + '@vue/devtools-api': 6.6.4 + vue: 3.5.13(typescript@5.7.3) + + vue-router@4.5.0(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.13(typescript@5.7.3) + + vue-tsc@2.2.0(typescript@5.7.3): + dependencies: + '@volar/typescript': 2.4.11 + '@vue/language-core': 2.2.0(typescript@5.7.3) + typescript: 5.7.3 + + vue-types@3.0.2(vue@3.5.13(typescript@5.7.3)): + dependencies: + is-plain-object: 3.0.1 + vue: 3.5.13(typescript@5.7.3) + + vue@3.5.13(typescript@5.7.3): + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.7.3)) + '@vue/shared': 3.5.13 + optionalDependencies: + typescript: 5.7.3 + + warning@4.0.3: + dependencies: + loose-envify: 1.4.0 + + webpack-sources@3.2.3: {} + + webpack-virtual-modules@0.6.2: {} + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.3 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.18: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + for-each: 0.3.5 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + xml-name-validator@4.0.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yaml@2.7.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yoctocolors@2.1.1: {} + + zrender@5.6.1: + dependencies: + tslib: 2.3.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..169b2ab --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f332f042f84334a6de6a69baa69166dc059adb74 GIT binary patch literal 23414 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 de~VYw6WU1j- +import { computed } from 'vue'; +import { ConfigProvider } from 'ant-design-vue'; +import type { WatermarkProps } from 'ant-design-vue'; +import { useAppStore } from './store/modules/app'; +import { useThemeStore } from './store/modules/theme'; +import { antdLocales } from './locales/antd'; + +defineOptions({ + name: 'App' +}); + +const appStore = useAppStore(); +const themeStore = useThemeStore(); + +const antdLocale = computed(() => { + return antdLocales[appStore.locale]; +}); + +const watermarkProps = computed(() => { + const props: WatermarkProps = { + content: themeStore.watermark.text, + width: 120, + height: 120, + font: { + fontSize: 16 + }, + offset: [12, 60], + rotate: -15, + zIndex: 9999 + }; + + return props; +}); + + + + + diff --git a/src/assets/imgs/soybean.jpg b/src/assets/imgs/soybean.jpg new file mode 100644 index 0000000000000000000000000000000000000000..75457d5015acebac780047ca61b0f8dbd8525ddf GIT binary patch literal 114241 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

>@yuk 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 z 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 literal 0 HcmV?d00001 diff --git a/src/assets/svg-icon/activity.svg b/src/assets/svg-icon/activity.svg new file mode 100644 index 0000000..abe892f --- /dev/null +++ b/src/assets/svg-icon/activity.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/at-sign.svg b/src/assets/svg-icon/at-sign.svg new file mode 100644 index 0000000..625214d --- /dev/null +++ b/src/assets/svg-icon/at-sign.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/avatar.svg b/src/assets/svg-icon/avatar.svg new file mode 100644 index 0000000..66fe6f2 --- /dev/null +++ b/src/assets/svg-icon/avatar.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/banner.svg b/src/assets/svg-icon/banner.svg new file mode 100644 index 0000000..192b637 --- /dev/null +++ b/src/assets/svg-icon/banner.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/cast.svg b/src/assets/svg-icon/cast.svg new file mode 100644 index 0000000..4f008d3 --- /dev/null +++ b/src/assets/svg-icon/cast.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/chrome.svg b/src/assets/svg-icon/chrome.svg new file mode 100644 index 0000000..6314173 --- /dev/null +++ b/src/assets/svg-icon/chrome.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/copy.svg b/src/assets/svg-icon/copy.svg new file mode 100644 index 0000000..ab25601 --- /dev/null +++ b/src/assets/svg-icon/copy.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/custom-icon.svg b/src/assets/svg-icon/custom-icon.svg new file mode 100644 index 0000000..b33a43f --- /dev/null +++ b/src/assets/svg-icon/custom-icon.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/empty-data.svg b/src/assets/svg-icon/empty-data.svg new file mode 100644 index 0000000..293486c --- /dev/null +++ b/src/assets/svg-icon/empty-data.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/expectation.svg b/src/assets/svg-icon/expectation.svg new file mode 100644 index 0000000..1d87d5e --- /dev/null +++ b/src/assets/svg-icon/expectation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg-icon/heart.svg b/src/assets/svg-icon/heart.svg new file mode 100644 index 0000000..56e59b4 --- /dev/null +++ b/src/assets/svg-icon/heart.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/logo.svg b/src/assets/svg-icon/logo.svg new file mode 100644 index 0000000..341675d --- /dev/null +++ b/src/assets/svg-icon/logo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/network-error.svg b/src/assets/svg-icon/network-error.svg new file mode 100644 index 0000000..52f97ab --- /dev/null +++ b/src/assets/svg-icon/network-error.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/no-icon.svg b/src/assets/svg-icon/no-icon.svg new file mode 100644 index 0000000..f6dcdd0 --- /dev/null +++ b/src/assets/svg-icon/no-icon.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/no-permission.svg b/src/assets/svg-icon/no-permission.svg new file mode 100644 index 0000000..4c408ca --- /dev/null +++ b/src/assets/svg-icon/no-permission.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/not-found.svg b/src/assets/svg-icon/not-found.svg new file mode 100644 index 0000000..a513656 --- /dev/null +++ b/src/assets/svg-icon/not-found.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/service-error.svg b/src/assets/svg-icon/service-error.svg new file mode 100644 index 0000000..0120f1e --- /dev/null +++ b/src/assets/svg-icon/service-error.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg-icon/wind.svg b/src/assets/svg-icon/wind.svg new file mode 100644 index 0000000..7c90590 --- /dev/null +++ b/src/assets/svg-icon/wind.svg @@ -0,0 +1 @@ + diff --git a/src/components/advanced/table-column-setting.vue b/src/components/advanced/table-column-setting.vue new file mode 100644 index 0000000..02e004c --- /dev/null +++ b/src/components/advanced/table-column-setting.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/src/components/advanced/table-header-operation.vue b/src/components/advanced/table-header-operation.vue new file mode 100644 index 0000000..a26b165 --- /dev/null +++ b/src/components/advanced/table-header-operation.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/components/common/app-provider.vue b/src/components/common/app-provider.vue new file mode 100644 index 0000000..32714e6 --- /dev/null +++ b/src/components/common/app-provider.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/common/dark-mode-container.vue b/src/components/common/dark-mode-container.vue new file mode 100644 index 0000000..71f2733 --- /dev/null +++ b/src/components/common/dark-mode-container.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/common/exception-base.vue b/src/components/common/exception-base.vue new file mode 100644 index 0000000..801bd26 --- /dev/null +++ b/src/components/common/exception-base.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/components/common/full-screen.vue b/src/components/common/full-screen.vue new file mode 100644 index 0000000..41c1c56 --- /dev/null +++ b/src/components/common/full-screen.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/common/lang-switch.vue b/src/components/common/lang-switch.vue new file mode 100644 index 0000000..3ee65fc --- /dev/null +++ b/src/components/common/lang-switch.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/src/components/common/menu-toggler.vue b/src/components/common/menu-toggler.vue new file mode 100644 index 0000000..30a9e64 --- /dev/null +++ b/src/components/common/menu-toggler.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/common/pin-toggler.vue b/src/components/common/pin-toggler.vue new file mode 100644 index 0000000..e6c62df --- /dev/null +++ b/src/components/common/pin-toggler.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/common/reload-button.vue b/src/components/common/reload-button.vue new file mode 100644 index 0000000..2881d03 --- /dev/null +++ b/src/components/common/reload-button.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/components/common/system-logo.vue b/src/components/common/system-logo.vue new file mode 100644 index 0000000..7f23cc1 --- /dev/null +++ b/src/components/common/system-logo.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/src/components/common/theme-schema-switch.vue b/src/components/common/theme-schema-switch.vue new file mode 100644 index 0000000..9aa6d2a --- /dev/null +++ b/src/components/common/theme-schema-switch.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/custom/better-scroll.vue b/src/components/custom/better-scroll.vue new file mode 100644 index 0000000..7d2559c --- /dev/null +++ b/src/components/custom/better-scroll.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/components/custom/button-icon.vue b/src/components/custom/button-icon.vue new file mode 100644 index 0000000..c9bf9db --- /dev/null +++ b/src/components/custom/button-icon.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/src/components/custom/count-to.vue b/src/components/custom/count-to.vue new file mode 100644 index 0000000..910b4cc --- /dev/null +++ b/src/components/custom/count-to.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/custom/look-forward.vue b/src/components/custom/look-forward.vue new file mode 100644 index 0000000..d0494f9 --- /dev/null +++ b/src/components/custom/look-forward.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/src/components/custom/soybean-avatar.vue b/src/components/custom/soybean-avatar.vue new file mode 100644 index 0000000..8d3278a --- /dev/null +++ b/src/components/custom/soybean-avatar.vue @@ -0,0 +1,13 @@ + + + + + diff --git a/src/components/custom/svg-icon.vue b/src/components/custom/svg-icon.vue new file mode 100644 index 0000000..504763e --- /dev/null +++ b/src/components/custom/svg-icon.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/src/components/custom/wave-bg.vue b/src/components/custom/wave-bg.vue new file mode 100644 index 0000000..534bb37 --- /dev/null +++ b/src/components/custom/wave-bg.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/constants/app.ts b/src/constants/app.ts new file mode 100644 index 0000000..3757a4e --- /dev/null +++ b/src/constants/app.ts @@ -0,0 +1,63 @@ +import { transformRecordToOption } from '@/utils/common'; + +export const GLOBAL_HEADER_MENU_ID = '__GLOBAL_HEADER_MENU__'; + +export const GLOBAL_SIDER_MENU_ID = '__GLOBAL_SIDER_MENU__'; + +export const themeSchemaRecord: Record = { + light: 'theme.themeSchema.light', + dark: 'theme.themeSchema.dark', + auto: 'theme.themeSchema.auto' +}; + +export const themeSchemaOptions = transformRecordToOption(themeSchemaRecord); + +export const loginModuleRecord: Record = { + 'pwd-login': 'page.login.pwdLogin.title', + 'code-login': 'page.login.codeLogin.title', + register: 'page.login.register.title', + 'reset-pwd': 'page.login.resetPwd.title', + 'bind-wechat': 'page.login.bindWeChat.title' +}; + +export const themeLayoutModeRecord: Record = { + vertical: 'theme.layoutMode.vertical', + 'vertical-mix': 'theme.layoutMode.vertical-mix', + horizontal: 'theme.layoutMode.horizontal', + 'horizontal-mix': 'theme.layoutMode.horizontal-mix' +}; + +export const themeLayoutModeOptions = transformRecordToOption(themeLayoutModeRecord); + +export const themeScrollModeRecord: Record = { + wrapper: 'theme.scrollMode.wrapper', + content: 'theme.scrollMode.content' +}; + +export const themeScrollModeOptions = transformRecordToOption(themeScrollModeRecord); + +export const themeTabModeRecord: Record = { + chrome: 'theme.tab.mode.chrome', + button: 'theme.tab.mode.button' +}; + +export const themeTabModeOptions = transformRecordToOption(themeTabModeRecord); + +export const themePageAnimationModeRecord: Record = { + 'fade-slide': 'theme.page.mode.fade-slide', + fade: 'theme.page.mode.fade', + 'fade-bottom': 'theme.page.mode.fade-bottom', + 'fade-scale': 'theme.page.mode.fade-scale', + 'zoom-fade': 'theme.page.mode.zoom-fade', + 'zoom-out': 'theme.page.mode.zoom-out', + none: 'theme.page.mode.none' +}; + +export const themePageAnimationModeOptions = transformRecordToOption(themePageAnimationModeRecord); + +export const resetCacheStrategyRecord: Record = { + close: 'theme.resetCacheStrategy.close', + refresh: 'theme.resetCacheStrategy.refresh' +}; + +export const resetCacheStrategyOptions = transformRecordToOption(resetCacheStrategyRecord); diff --git a/src/constants/business.ts b/src/constants/business.ts new file mode 100644 index 0000000..a84d742 --- /dev/null +++ b/src/constants/business.ts @@ -0,0 +1,29 @@ +import { transformRecordToOption } from '@/utils/common'; + +export const enableStatusRecord: Record = { + '1': 'page.manage.common.status.enable', + '2': 'page.manage.common.status.disable' +}; + +export const enableStatusOptions = transformRecordToOption(enableStatusRecord); + +export const userGenderRecord: Record = { + '1': 'page.manage.user.gender.male', + '2': 'page.manage.user.gender.female' +}; + +export const userGenderOptions = transformRecordToOption(userGenderRecord); + +export const menuTypeRecord: Record = { + '1': 'page.manage.menu.type.directory', + '2': 'page.manage.menu.type.menu' +}; + +export const menuTypeOptions = transformRecordToOption(menuTypeRecord); + +export const menuIconTypeRecord: Record = { + '1': 'page.manage.menu.iconType.iconify', + '2': 'page.manage.menu.iconType.local' +}; + +export const menuIconTypeOptions = transformRecordToOption(menuIconTypeRecord); diff --git a/src/constants/common.ts b/src/constants/common.ts new file mode 100644 index 0000000..2d5e05e --- /dev/null +++ b/src/constants/common.ts @@ -0,0 +1,8 @@ +import { transformRecordToOption } from '@/utils/common'; + +export const yesOrNoRecord: Record = { + Y: 'common.yesOrNo.yes', + N: 'common.yesOrNo.no' +}; + +export const yesOrNoOptions = transformRecordToOption(yesOrNoRecord); diff --git a/src/constants/reg.ts b/src/constants/reg.ts new file mode 100644 index 0000000..8805ca8 --- /dev/null +++ b/src/constants/reg.ts @@ -0,0 +1,25 @@ +export const REG_USER_NAME = /^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/; + +/** Phone reg */ +export const REG_PHONE = + /^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/; + +/** + * Password reg + * + * 6-18 characters, including letters, numbers, and underscores + */ +export const REG_PWD = /^\w{6,18}$/; + +/** Email reg */ +export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; + +/** Six digit code reg */ +export const REG_CODE_SIX = /^\d{6}$/; + +/** Four digit code reg */ +export const REG_CODE_FOUR = /^\d{4}$/; + +/** Url reg */ +export const REG_URL = + /(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/; diff --git a/src/enum/index.ts b/src/enum/index.ts new file mode 100644 index 0000000..2739b3a --- /dev/null +++ b/src/enum/index.ts @@ -0,0 +1,7 @@ +export enum SetupStoreId { + App = 'app-store', + Theme = 'theme-store', + Auth = 'auth-store', + Route = 'route-store', + Tab = 'tab-store' +} diff --git a/src/hooks/business/auth.ts b/src/hooks/business/auth.ts new file mode 100644 index 0000000..f8fc749 --- /dev/null +++ b/src/hooks/business/auth.ts @@ -0,0 +1,21 @@ +import { useAuthStore } from '@/store/modules/auth'; + +export function useAuth() { + const authStore = useAuthStore(); + + function hasAuth(codes: string | string[]) { + if (!authStore.isLogin) { + return false; + } + + if (typeof codes === 'string') { + return authStore.userInfo.buttons.includes(codes); + } + + return codes.some(code => authStore.userInfo.buttons.includes(code)); + } + + return { + hasAuth + }; +} diff --git a/src/hooks/business/captcha.ts b/src/hooks/business/captcha.ts new file mode 100644 index 0000000..c2303d3 --- /dev/null +++ b/src/hooks/business/captcha.ts @@ -0,0 +1,71 @@ +import { computed } from 'vue'; +import { useCountDown, useLoading } from '@sa/hooks'; +import { $t } from '@/locales'; +import { REG_PHONE } from '@/constants/reg'; + +export function useCaptcha() { + const { loading, startLoading, endLoading } = useLoading(); + const { count, start, stop, isCounting } = useCountDown(10); + + const label = computed(() => { + let text = $t('page.login.codeLogin.getCode'); + + const countingLabel = $t('page.login.codeLogin.reGetCode', { time: count.value }); + + if (loading.value) { + text = ''; + } + + if (isCounting.value) { + text = countingLabel; + } + + return text; + }); + + function isPhoneValid(phone: string) { + if (phone.trim() === '') { + window.$message?.error?.($t('form.phone.required')); + + return false; + } + + if (!REG_PHONE.test(phone)) { + window.$message?.error?.($t('form.phone.invalid')); + + return false; + } + + return true; + } + + async function getCaptcha(phone: string) { + const valid = isPhoneValid(phone); + + if (!valid || loading.value) { + return; + } + + startLoading(); + + // request + await new Promise(resolve => { + setTimeout(resolve, 500); + }); + + window.$message?.success?.($t('page.login.codeLogin.sendCodeSuccess')); + + start(); + + endLoading(); + } + + return { + label, + start, + stop, + isCounting, + loading, + getCaptcha + }; +} diff --git a/src/hooks/common/echarts.ts b/src/hooks/common/echarts.ts new file mode 100644 index 0000000..db27312 --- /dev/null +++ b/src/hooks/common/echarts.ts @@ -0,0 +1,235 @@ +import { computed, effectScope, nextTick, onScopeDispose, ref, watch } from 'vue'; +import * as echarts from 'echarts/core'; +import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts'; +import type { + BarSeriesOption, + GaugeSeriesOption, + LineSeriesOption, + PictorialBarSeriesOption, + PieSeriesOption, + RadarSeriesOption, + ScatterSeriesOption +} from 'echarts/charts'; +import { + DatasetComponent, + GridComponent, + LegendComponent, + TitleComponent, + ToolboxComponent, + TooltipComponent, + TransformComponent +} from 'echarts/components'; +import type { + DatasetComponentOption, + GridComponentOption, + LegendComponentOption, + TitleComponentOption, + ToolboxComponentOption, + TooltipComponentOption +} from 'echarts/components'; +import { LabelLayout, UniversalTransition } from 'echarts/features'; +import { CanvasRenderer } from 'echarts/renderers'; +import { useElementSize } from '@vueuse/core'; +import { useThemeStore } from '@/store/modules/theme'; + +export type ECOption = echarts.ComposeOption< + | BarSeriesOption + | LineSeriesOption + | PieSeriesOption + | ScatterSeriesOption + | PictorialBarSeriesOption + | RadarSeriesOption + | GaugeSeriesOption + | TitleComponentOption + | LegendComponentOption + | TooltipComponentOption + | GridComponentOption + | ToolboxComponentOption + | DatasetComponentOption +>; + +echarts.use([ + TitleComponent, + LegendComponent, + TooltipComponent, + GridComponent, + DatasetComponent, + TransformComponent, + ToolboxComponent, + BarChart, + LineChart, + PieChart, + ScatterChart, + PictorialBarChart, + RadarChart, + GaugeChart, + LabelLayout, + UniversalTransition, + CanvasRenderer +]); + +interface ChartHooks { + onRender?: (chart: echarts.ECharts) => void | Promise; + onUpdated?: (chart: echarts.ECharts) => void | Promise; + onDestroy?: (chart: echarts.ECharts) => void | Promise; +} + +/** + * use echarts + * + * @param optionsFactory echarts options factory function + * @param darkMode dark mode + */ +export function useEcharts(optionsFactory: () => T, hooks: ChartHooks = {}) { + const scope = effectScope(); + + const themeStore = useThemeStore(); + const darkMode = computed(() => themeStore.darkMode); + + const domRef = ref(null); + const initialSize = { width: 0, height: 0 }; + const { width, height } = useElementSize(domRef, initialSize); + + let chart: echarts.ECharts | null = null; + const chartOptions: T = optionsFactory(); + + const { + onRender = instance => { + const textColor = darkMode.value ? 'rgb(224, 224, 224)' : 'rgb(31, 31, 31)'; + const maskColor = darkMode.value ? 'rgba(0, 0, 0, 0.4)' : 'rgba(255, 255, 255, 0.8)'; + + instance.showLoading({ + color: themeStore.themeColor, + textColor, + fontSize: 14, + maskColor + }); + }, + onUpdated = instance => { + instance.hideLoading(); + }, + onDestroy + } = hooks; + + /** + * whether can render chart + * + * when domRef is ready and initialSize is valid + */ + function canRender() { + return domRef.value && initialSize.width > 0 && initialSize.height > 0; + } + + /** is chart rendered */ + function isRendered() { + return Boolean(domRef.value && chart); + } + + /** + * update chart options + * + * @param callback callback function + */ + async function updateOptions(callback: (opts: T, optsFactory: () => T) => ECOption = () => chartOptions) { + if (!isRendered()) return; + + const updatedOpts = callback(chartOptions, optionsFactory); + + Object.assign(chartOptions, updatedOpts); + + if (isRendered()) { + chart?.clear(); + } + + chart?.setOption({ ...updatedOpts, backgroundColor: 'transparent' }); + + await onUpdated?.(chart!); + } + + function setOptions(options: T) { + chart?.setOption(options); + } + + /** render chart */ + async function render() { + if (!isRendered()) { + const chartTheme = darkMode.value ? 'dark' : 'light'; + + await nextTick(); + + chart = echarts.init(domRef.value, chartTheme); + + chart.setOption({ ...chartOptions, backgroundColor: 'transparent' }); + + await onRender?.(chart); + } + } + + /** resize chart */ + function resize() { + chart?.resize(); + } + + /** destroy chart */ + async function destroy() { + if (!chart) return; + + await onDestroy?.(chart); + chart?.dispose(); + chart = null; + } + + /** change chart theme */ + async function changeTheme() { + await destroy(); + await render(); + await onUpdated?.(chart!); + } + + /** + * render chart by size + * + * @param w width + * @param h height + */ + async function renderChartBySize(w: number, h: number) { + initialSize.width = w; + initialSize.height = h; + + // size is abnormal, destroy chart + if (!canRender()) { + await destroy(); + + return; + } + + // resize chart + if (isRendered()) { + resize(); + } + + // render chart + await render(); + } + + scope.run(() => { + watch([width, height], ([newWidth, newHeight]) => { + renderChartBySize(newWidth, newHeight); + }); + + watch(darkMode, () => { + changeTheme(); + }); + }); + + onScopeDispose(() => { + destroy(); + scope.stop(); + }); + + return { + domRef, + updateOptions, + setOptions + }; +} diff --git a/src/hooks/common/form.ts b/src/hooks/common/form.ts new file mode 100644 index 0000000..e5c9af8 --- /dev/null +++ b/src/hooks/common/form.ts @@ -0,0 +1,97 @@ +import { ref, toValue } from 'vue'; +import type { ComputedRef, Ref } from 'vue'; +import type { FormInstance } from 'ant-design-vue'; +import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg'; +import { $t } from '@/locales'; + +export function useFormRules() { + const patternRules = { + userName: { + pattern: REG_USER_NAME, + message: $t('form.userName.invalid'), + trigger: 'change' + }, + phone: { + pattern: REG_PHONE, + message: $t('form.phone.invalid'), + trigger: 'change' + }, + pwd: { + pattern: REG_PWD, + message: $t('form.pwd.invalid'), + trigger: 'change' + }, + code: { + pattern: REG_CODE_SIX, + message: $t('form.code.invalid'), + trigger: 'change' + }, + email: { + pattern: REG_EMAIL, + message: $t('form.email.invalid'), + trigger: 'change' + } + } satisfies Record; + + const formRules = { + userName: [createRequiredRule($t('form.userName.required')), patternRules.userName], + phone: [createRequiredRule($t('form.phone.required')), patternRules.phone], + pwd: [createRequiredRule($t('form.pwd.required')), patternRules.pwd], + code: [createRequiredRule($t('form.code.required')), patternRules.code], + email: [createRequiredRule($t('form.email.required')), patternRules.email] + } satisfies Record; + + /** the default required rule */ + const defaultRequiredRule = createRequiredRule($t('form.required')); + + function createRequiredRule(message: string) { + return { + required: true, + message + }; + } + + /** create a rule for confirming the password */ + function createConfirmPwdRule(pwd: string | Ref | ComputedRef) { + const confirmPwdRule: App.Global.FormRule[] = [ + { required: true, message: $t('form.confirmPwd.required') }, + { + validator: (rule, value) => { + if (value.trim() !== '' && value !== toValue(pwd)) { + return Promise.reject(rule.message); + } + return Promise.resolve(); + }, + message: $t('form.confirmPwd.invalid'), + trigger: 'change' + } + ]; + return confirmPwdRule; + } + + return { + patternRules, + formRules, + defaultRequiredRule, + createRequiredRule, + createConfirmPwdRule + }; +} + +export function useAntdForm() { + const formRef = ref(null); + + async function validate() { + await formRef.value?.validate(); + } + + function resetFields() { + formRef.value?.resetFields(); + } + + return { + formRef, + validate, + resetFields + }; +} diff --git a/src/hooks/common/icon.ts b/src/hooks/common/icon.ts new file mode 100644 index 0000000..8998f60 --- /dev/null +++ b/src/hooks/common/icon.ts @@ -0,0 +1,10 @@ +import { useSvgIconRender } from '@sa/hooks'; +import SvgIcon from '@/components/custom/svg-icon.vue'; + +export function useSvgIcon() { + const { SvgIconVNode } = useSvgIconRender(SvgIcon); + + return { + SvgIconVNode + }; +} diff --git a/src/hooks/common/router.ts b/src/hooks/common/router.ts new file mode 100644 index 0000000..4ab21ea --- /dev/null +++ b/src/hooks/common/router.ts @@ -0,0 +1,120 @@ +import { useRouter } from 'vue-router'; +import type { RouteLocationRaw } from 'vue-router'; +import type { RouteKey } from '@elegant-router/types'; +import { router as globalRouter } from '@/router'; + +/** + * Router push + * + * Jump to the specified route, it can replace function router.push + * + * @param inSetup Whether is in vue script setup + */ +export function useRouterPush(inSetup = true) { + const router = inSetup ? useRouter() : globalRouter; + const route = globalRouter.currentRoute; + + const routerPush = router.push; + + const routerBack = router.back; + + interface RouterPushOptions { + query?: Record; + params?: Record; + } + + async function routerPushByKey(key: RouteKey, options?: RouterPushOptions) { + const { query, params } = options || {}; + + const routeLocation: RouteLocationRaw = { + name: key + }; + + if (Object.keys(query || {}).length) { + routeLocation.query = query; + } + + if (Object.keys(params || {}).length) { + routeLocation.params = params; + } + + return routerPush(routeLocation); + } + + function routerPushByKeyWithMetaQuery(key: RouteKey) { + const allRoutes = router.getRoutes(); + const meta = allRoutes.find(item => item.name === key)?.meta || null; + + const query: Record = {}; + + meta?.query?.forEach(item => { + query[item.key] = item.value; + }); + + return routerPushByKey(key, { query }); + } + + async function toHome() { + return routerPushByKey('root'); + } + + /** + * Navigate to login page + * + * @param loginModule The login module + * @param redirectUrl The redirect url, if not specified, it will be the current route fullPath + */ + async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) { + const module = loginModule || 'pwd-login'; + + const options: RouterPushOptions = { + params: { + module + } + }; + + const redirect = redirectUrl || route.value.fullPath; + + options.query = { + redirect + }; + + return routerPushByKey('login', options); + } + + /** + * Toggle login module + * + * @param module + */ + async function toggleLoginModule(module: UnionKey.LoginModule) { + const query = route.value.query as Record; + + return routerPushByKey('login', { query, params: { module } }); + } + + /** + * Redirect from login + * + * @param [needRedirect=true] Whether to redirect after login. Default is `true` + */ + async function redirectFromLogin(needRedirect = true) { + const redirect = route.value.query?.redirect as string; + + if (needRedirect && redirect) { + await routerPush(redirect); + } else { + await toHome(); + } + } + + return { + routerPush, + routerBack, + routerPushByKey, + routerPushByKeyWithMetaQuery, + toLogin, + toggleLoginModule, + redirectFromLogin + }; +} diff --git a/src/hooks/common/table.ts b/src/hooks/common/table.ts new file mode 100644 index 0000000..e2c8285 --- /dev/null +++ b/src/hooks/common/table.ts @@ -0,0 +1,263 @@ +import { computed, effectScope, onScopeDispose, reactive, ref, shallowRef, toValue, watch } from 'vue'; +import type { MaybeRef, Ref } from 'vue'; +import type { TablePaginationConfig } from 'ant-design-vue'; +import type { TableRowSelection } from 'ant-design-vue/es/table/interface'; +import { useElementSize } from '@vueuse/core'; +import { useBoolean, useHookTable } from '@sa/hooks'; +import { jsonClone } from '@sa/utils'; +import { useAppStore } from '@/store/modules/app'; +import { $t } from '@/locales'; + +type TableData = AntDesign.TableData; +type GetTableData = AntDesign.GetTableData; +type TableColumn = AntDesign.TableColumn; + +export function useTable(config: AntDesign.AntDesignTableConfig) { + const scope = effectScope(); + const appStore = useAppStore(); + + const { apiFn, apiParams, immediate } = config; + + const { + loading, + empty, + data, + columns, + columnChecks, + reloadColumns, + getData, + searchParams, + updateSearchParams, + resetSearchParams + } = useHookTable, TableColumn>>>({ + apiFn, + apiParams, + columns: config.columns, + transformer: res => { + const { records = [], current = 1, size = 10, total = 0 } = res.data || {}; + + // Ensure that the size is greater than 0, If it is less than 0, it will cause paging calculation errors. + const pageSize = size <= 0 ? 10 : size; + + const recordsWithIndex = records.map((item, index) => { + return { + ...item, + index: (current - 1) * pageSize + index + 1 + }; + }); + + return { + data: recordsWithIndex, + pageNum: current, + pageSize, + total + }; + }, + getColumnChecks: cols => { + const checks: AntDesign.TableColumnCheck[] = []; + + cols.forEach(column => { + if (column.key) { + checks.push({ + key: column.key as string, + title: column.title as string, + checked: true + }); + } + }); + + return checks; + }, + getColumns: (cols, checks) => { + const columnMap = new Map>>(); + + cols.forEach(column => { + if (column.key) { + columnMap.set(column.key as string, column); + } + }); + + const filteredColumns = checks + .filter(item => item.checked) + .map(check => columnMap.get(check.key) as TableColumn>); + + return filteredColumns; + }, + onFetched: async transformed => { + const { pageNum, pageSize, total } = transformed; + + updatePagination({ + current: pageNum, + pageSize, + total + }); + }, + immediate + }); + + const pagination: TablePaginationConfig = reactive({ + current: 1, + pageSize: 10, + showSizeChanger: true, + pageSizeOptions: ['10', '15', '20', '25', '30'], + total: 0, + onChange: async (current: number, size: number) => { + pagination.current = current; + + updateSearchParams({ + current, + size + }); + + getData(); + } + }); + + // this is for mobile, if the system does not support mobile, you can use `pagination` directly + const mobilePagination = computed(() => { + const p: TablePaginationConfig = { + ...pagination, + simple: appStore.isMobile + }; + + return p; + }); + + function updatePagination(update: Partial) { + Object.assign(pagination, update); + } + + /** + * get data by page number + * + * @param pageNum the page number. default is 1 + */ + async function getDataByPage(pageNum: number = 1) { + updatePagination({ + current: pageNum + }); + + updateSearchParams({ + current: pageNum, + size: pagination.pageSize! + }); + + await getData(); + } + + scope.run(() => { + watch( + () => appStore.locale, + () => { + reloadColumns(); + } + ); + }); + + onScopeDispose(() => { + scope.stop(); + }); + + return { + loading, + empty, + data, + columns, + columnChecks, + reloadColumns, + pagination, + mobilePagination, + updatePagination, + getData, + getDataByPage, + searchParams, + updateSearchParams, + resetSearchParams + }; +} + +export function useTableOperate(data: Ref, getData: () => Promise) { + const { bool: drawerVisible, setTrue: openDrawer, setFalse: closeDrawer } = useBoolean(); + + const operateType = ref('add'); + + function handleAdd() { + operateType.value = 'add'; + openDrawer(); + } + + /** the editing row data */ + const editingData: Ref = ref(null); + + function handleEdit(id: T['id']) { + operateType.value = 'edit'; + const findItem = data.value.find(item => item.id === id) || null; + editingData.value = jsonClone(findItem); + + openDrawer(); + } + + /** the checked row keys of table */ + const checkedRowKeys: Ref = ref([]); + + function onSelectChange(keys: (string | number)[]) { + checkedRowKeys.value = keys as T['id'][]; + } + + const rowSelection = computed>(() => { + return { + columnWidth: 48, + type: 'checkbox', + selectedRowKeys: checkedRowKeys.value, + onChange: onSelectChange + }; + }); + + /** the hook after the batch delete operation is completed */ + async function onBatchDeleted() { + window.$message?.success($t('common.deleteSuccess')); + + checkedRowKeys.value = []; + + await getData(); + } + + /** the hook after the delete operation is completed */ + async function onDeleted() { + window.$message?.success($t('common.deleteSuccess')); + + await getData(); + } + + return { + drawerVisible, + openDrawer, + closeDrawer, + operateType, + handleAdd, + editingData, + handleEdit, + checkedRowKeys, + onSelectChange, + rowSelection, + onBatchDeleted, + onDeleted + }; +} + +export function useTableScroll(scrollX: MaybeRef = 702) { + const tableWrapperRef = shallowRef(null); + const { height: wrapperElHeight } = useElementSize(tableWrapperRef); + + const scrollConfig = computed(() => { + return { + y: wrapperElHeight.value - 72, + x: toValue(scrollX) + }; + }); + + return { + tableWrapperRef, + scrollConfig + }; +} diff --git a/src/layouts/base-layout/index.vue b/src/layouts/base-layout/index.vue new file mode 100644 index 0000000..7debe5d --- /dev/null +++ b/src/layouts/base-layout/index.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/layouts/blank-layout/index.vue b/src/layouts/blank-layout/index.vue new file mode 100644 index 0000000..2e393f0 --- /dev/null +++ b/src/layouts/blank-layout/index.vue @@ -0,0 +1,13 @@ + + + + + diff --git a/src/layouts/context/index.ts b/src/layouts/context/index.ts new file mode 100644 index 0000000..8b54264 --- /dev/null +++ b/src/layouts/context/index.ts @@ -0,0 +1,83 @@ +import { computed, ref, watch } from 'vue'; +import { useRoute } from 'vue-router'; +import { useContext } from '@sa/hooks'; +import { useRouteStore } from '@/store/modules/route'; + +export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu); + +function useMixMenu() { + const route = useRoute(); + const routeStore = useRouteStore(); + const { selectedKey } = useMenu(); + + const activeFirstLevelMenuKey = ref(''); + + function setActiveFirstLevelMenuKey(key: string) { + activeFirstLevelMenuKey.value = key; + } + + function getActiveFirstLevelMenuKey() { + const [firstLevelRouteName] = selectedKey.value.split('_'); + + setActiveFirstLevelMenuKey(firstLevelRouteName); + } + + const allMenus = computed(() => routeStore.menus); + + const firstLevelMenus = computed(() => + routeStore.menus.map(menu => { + const { children: _, ...rest } = menu; + + return rest; + }) + ); + + const childLevelMenus = computed( + () => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || [] + ); + + const isActiveFirstLevelMenuHasChildren = computed(() => { + if (!activeFirstLevelMenuKey.value) { + return false; + } + + const findItem = allMenus.value.find(item => item.key === activeFirstLevelMenuKey.value); + + return Boolean(findItem?.children?.length); + }); + + watch( + () => route.name, + () => { + getActiveFirstLevelMenuKey(); + }, + { immediate: true } + ); + + return { + allMenus, + firstLevelMenus, + childLevelMenus, + isActiveFirstLevelMenuHasChildren, + activeFirstLevelMenuKey, + setActiveFirstLevelMenuKey, + getActiveFirstLevelMenuKey + }; +} + +export function useMenu() { + const route = useRoute(); + + const selectedKey = computed(() => { + const { hideInMenu, activeMenu } = route.meta; + const name = route.name as string; + + const routeName = (hideInMenu ? activeMenu : name) || name; + + return routeName; + }); + + return { + selectedKey + }; +} diff --git a/src/layouts/modules/global-breadcrumb/index.vue b/src/layouts/modules/global-breadcrumb/index.vue new file mode 100644 index 0000000..c9b9190 --- /dev/null +++ b/src/layouts/modules/global-breadcrumb/index.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/layouts/modules/global-content/index.vue b/src/layouts/modules/global-content/index.vue new file mode 100644 index 0000000..989b6d4 --- /dev/null +++ b/src/layouts/modules/global-content/index.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/layouts/modules/global-footer/index.vue b/src/layouts/modules/global-footer/index.vue new file mode 100644 index 0000000..26273b5 --- /dev/null +++ b/src/layouts/modules/global-footer/index.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/layouts/modules/global-header/components/theme-button.vue b/src/layouts/modules/global-header/components/theme-button.vue new file mode 100644 index 0000000..732c1b0 --- /dev/null +++ b/src/layouts/modules/global-header/components/theme-button.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/layouts/modules/global-header/components/user-avatar.vue b/src/layouts/modules/global-header/components/user-avatar.vue new file mode 100644 index 0000000..a6f81e6 --- /dev/null +++ b/src/layouts/modules/global-header/components/user-avatar.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/layouts/modules/global-header/index.vue b/src/layouts/modules/global-header/index.vue new file mode 100644 index 0000000..67e22ba --- /dev/null +++ b/src/layouts/modules/global-header/index.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/layouts/modules/global-logo/index.vue b/src/layouts/modules/global-logo/index.vue new file mode 100644 index 0000000..40ec52b --- /dev/null +++ b/src/layouts/modules/global-logo/index.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/src/layouts/modules/global-menu/components/first-level-menu.vue b/src/layouts/modules/global-menu/components/first-level-menu.vue new file mode 100644 index 0000000..b9c895a --- /dev/null +++ b/src/layouts/modules/global-menu/components/first-level-menu.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/layouts/modules/global-menu/index.scss b/src/layouts/modules/global-menu/index.scss new file mode 100644 index 0000000..ed3a313 --- /dev/null +++ b/src/layouts/modules/global-menu/index.scss @@ -0,0 +1,49 @@ +.menu-wrapper { + :deep(.ant-menu-inline) { + .ant-menu-item { + width: calc(100% - 16px); + margin-inline: 8px; + } + } + + :deep(.ant-menu-submenu-title) { + width: calc(100% - 16px); + margin-inline: 8px; + } + + :deep(.ant-menu-inline-collapsed) { + > .ant-menu-item { + padding-inline: calc(50% - 14px); + } + + .ant-menu-item-icon { + vertical-align: -0.25em; + } + + .ant-menu-submenu-title { + padding-inline: calc(50% - 18px); + } + } +} + +.select-menu { + :deep(.ant-menu-inline) { + .ant-menu-item-selected { + background-color: var(--selected-bg-color); + } + } +} + +.horizontal-menu { + :deep(.ant-menu-horizontal) { + .ant-menu-item { + display: flex; + align-items: center; + } + + .ant-menu-submenu-title { + display: flex; + align-items: center; + } + } +} diff --git a/src/layouts/modules/global-menu/index.vue b/src/layouts/modules/global-menu/index.vue new file mode 100644 index 0000000..00d3a32 --- /dev/null +++ b/src/layouts/modules/global-menu/index.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/layouts/modules/global-menu/modules/horizontal-menu.vue b/src/layouts/modules/global-menu/modules/horizontal-menu.vue new file mode 100644 index 0000000..362c353 --- /dev/null +++ b/src/layouts/modules/global-menu/modules/horizontal-menu.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/layouts/modules/global-menu/modules/horizontal-mix-menu.vue b/src/layouts/modules/global-menu/modules/horizontal-mix-menu.vue new file mode 100644 index 0000000..9cd7aeb --- /dev/null +++ b/src/layouts/modules/global-menu/modules/horizontal-mix-menu.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/layouts/modules/global-menu/modules/reversed-horizontal-mix-menu.vue b/src/layouts/modules/global-menu/modules/reversed-horizontal-mix-menu.vue new file mode 100644 index 0000000..465bd36 --- /dev/null +++ b/src/layouts/modules/global-menu/modules/reversed-horizontal-mix-menu.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/layouts/modules/global-menu/modules/vertical-menu.vue b/src/layouts/modules/global-menu/modules/vertical-menu.vue new file mode 100644 index 0000000..8409751 --- /dev/null +++ b/src/layouts/modules/global-menu/modules/vertical-menu.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/layouts/modules/global-menu/modules/vertical-mix-menu.vue b/src/layouts/modules/global-menu/modules/vertical-mix-menu.vue new file mode 100644 index 0000000..52ee392 --- /dev/null +++ b/src/layouts/modules/global-menu/modules/vertical-mix-menu.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/src/layouts/modules/global-sider/index.vue b/src/layouts/modules/global-sider/index.vue new file mode 100644 index 0000000..2a5b8fe --- /dev/null +++ b/src/layouts/modules/global-sider/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/layouts/modules/global-tab/context-menu.vue b/src/layouts/modules/global-tab/context-menu.vue new file mode 100644 index 0000000..84c4091 --- /dev/null +++ b/src/layouts/modules/global-tab/context-menu.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/layouts/modules/global-tab/index.vue b/src/layouts/modules/global-tab/index.vue new file mode 100644 index 0000000..2543c6c --- /dev/null +++ b/src/layouts/modules/global-tab/index.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/components/layout-mode-card.vue b/src/layouts/modules/theme-drawer/components/layout-mode-card.vue new file mode 100644 index 0000000..cc7ba16 --- /dev/null +++ b/src/layouts/modules/theme-drawer/components/layout-mode-card.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/components/setting-item.vue b/src/layouts/modules/theme-drawer/components/setting-item.vue new file mode 100644 index 0000000..ccd29bd --- /dev/null +++ b/src/layouts/modules/theme-drawer/components/setting-item.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/index.vue b/src/layouts/modules/theme-drawer/index.vue new file mode 100644 index 0000000..2118714 --- /dev/null +++ b/src/layouts/modules/theme-drawer/index.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/modules/config-operation.vue b/src/layouts/modules/theme-drawer/modules/config-operation.vue new file mode 100644 index 0000000..f57b6f1 --- /dev/null +++ b/src/layouts/modules/theme-drawer/modules/config-operation.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/modules/dark-mode.vue b/src/layouts/modules/theme-drawer/modules/dark-mode.vue new file mode 100644 index 0000000..7b25ee0 --- /dev/null +++ b/src/layouts/modules/theme-drawer/modules/dark-mode.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/modules/layout-mode.vue b/src/layouts/modules/theme-drawer/modules/layout-mode.vue new file mode 100644 index 0000000..39ffc82 --- /dev/null +++ b/src/layouts/modules/theme-drawer/modules/layout-mode.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/modules/page-fun.vue b/src/layouts/modules/theme-drawer/modules/page-fun.vue new file mode 100644 index 0000000..834477b --- /dev/null +++ b/src/layouts/modules/theme-drawer/modules/page-fun.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/src/layouts/modules/theme-drawer/modules/theme-color.vue b/src/layouts/modules/theme-drawer/modules/theme-color.vue new file mode 100644 index 0000000..76d182f --- /dev/null +++ b/src/layouts/modules/theme-drawer/modules/theme-color.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/locales/antd.ts b/src/locales/antd.ts new file mode 100644 index 0000000..5726ce3 --- /dev/null +++ b/src/locales/antd.ts @@ -0,0 +1,8 @@ +import type { Locale } from 'ant-design-vue/es/locale'; +import zhCN from 'ant-design-vue/es/locale/zh_CN'; +import enUS from 'ant-design-vue/es/locale/en_US'; + +export const antdLocales: Record = { + 'zh-CN': zhCN, + 'en-US': enUS +}; diff --git a/src/locales/dayjs.ts b/src/locales/dayjs.ts new file mode 100644 index 0000000..7dc8f8b --- /dev/null +++ b/src/locales/dayjs.ts @@ -0,0 +1,20 @@ +import { locale } from 'dayjs'; +import 'dayjs/locale/zh-cn'; +import 'dayjs/locale/en'; +import { localStg } from '@/utils/storage'; + +/** + * Set dayjs locale + * + * @param lang + */ +export function setDayjsLocale(lang: App.I18n.LangType = 'zh-CN') { + const localMap = { + 'zh-CN': 'zh-cn', + 'en-US': 'en' + } satisfies Record; + + const l = lang || localStg.get('lang') || 'zh-CN'; + + locale(localMap[l]); +} diff --git a/src/locales/index.ts b/src/locales/index.ts new file mode 100644 index 0000000..40af8a9 --- /dev/null +++ b/src/locales/index.ts @@ -0,0 +1,26 @@ +import type { App } from 'vue'; +import { createI18n } from 'vue-i18n'; +import { localStg } from '@/utils/storage'; +import messages from './locale'; + +const i18n = createI18n({ + locale: localStg.get('lang') || 'zh-CN', + fallbackLocale: 'en', + messages, + legacy: false +}); + +/** + * Setup plugin i18n + * + * @param app + */ +export function setupI18n(app: App) { + app.use(i18n); +} + +export const $t = i18n.global.t as App.I18n.$T; + +export function setLocale(locale: App.I18n.LangType) { + i18n.global.locale.value = locale; +} diff --git a/src/locales/langs/en-us.ts b/src/locales/langs/en-us.ts new file mode 100644 index 0000000..c315fd9 --- /dev/null +++ b/src/locales/langs/en-us.ts @@ -0,0 +1,490 @@ +const local: App.I18n.Schema = { + system: { + title: 'SoybeanAdmin', + updateTitle: 'System Version Update Notification', + updateContent: 'A new version of the system has been detected. Do you want to refresh the page immediately?', + updateConfirm: 'Refresh immediately', + updateCancel: 'Later' + }, + common: { + action: 'Action', + add: 'Add', + addSuccess: 'Add Success', + backToHome: 'Back to home', + batchDelete: 'Batch Delete', + cancel: 'Cancel', + close: 'Close', + check: 'Check', + columnSetting: 'Column Setting', + config: 'Config', + confirm: 'Confirm', + delete: 'Delete', + deleteSuccess: 'Delete Success', + confirmDelete: 'Are you sure you want to delete?', + edit: 'Edit', + error: 'Error', + index: 'Index', + keywordSearch: 'Please enter keyword', + logout: 'Logout', + logoutConfirm: 'Are you sure you want to log out?', + lookForward: 'Coming soon', + modify: 'Modify', + modifySuccess: 'Modify Success', + noData: 'No Data', + operate: 'Operate', + pleaseCheckValue: 'Please check whether the value is valid', + refresh: 'Refresh', + reset: 'Reset', + search: 'Search', + switch: 'Switch', + tip: 'Tip', + trigger: 'Trigger', + update: 'Update', + updateSuccess: 'Update Success', + userCenter: 'User Center', + yesOrNo: { + yes: 'Yes', + no: 'No' + } + }, + request: { + logout: 'Logout user after request failed', + logoutMsg: 'User status is invalid, please log in again', + logoutWithModal: 'Pop up modal after request failed and then log out user', + logoutWithModalMsg: 'User status is invalid, please log in again', + refreshToken: 'The requested token has expired, refresh the token', + tokenExpired: 'The requested token has expired' + }, + theme: { + themeSchema: { + title: 'Theme Schema', + light: 'Light', + dark: 'Dark', + auto: 'Follow System' + }, + grayscale: 'Grayscale', + colourWeakness: 'Colour Weakness', + layoutMode: { + title: 'Layout Mode', + vertical: 'Vertical Menu Mode', + horizontal: 'Horizontal Menu Mode', + 'vertical-mix': 'Vertical Mix Menu Mode', + 'horizontal-mix': 'Horizontal Mix menu Mode', + reverseHorizontalMix: 'Reverse first level menus and child level menus position' + }, + recommendColor: 'Apply Recommended Color Algorithm', + recommendColorDesc: 'The recommended color algorithm refers to', + themeColor: { + title: 'Theme Color', + primary: 'Primary', + info: 'Info', + success: 'Success', + warning: 'Warning', + error: 'Error', + followPrimary: 'Follow Primary' + }, + scrollMode: { + title: 'Scroll Mode', + wrapper: 'Wrapper', + content: 'Content' + }, + page: { + animate: 'Page Animate', + mode: { + title: 'Page Animate Mode', + fade: 'Fade', + 'fade-slide': 'Slide', + 'fade-bottom': 'Fade Zoom', + 'fade-scale': 'Fade Scale', + 'zoom-fade': 'Zoom Fade', + 'zoom-out': 'Zoom Out', + none: 'None' + } + }, + fixedHeaderAndTab: 'Fixed Header And Tab', + header: { + height: 'Header Height', + breadcrumb: { + visible: 'Breadcrumb Visible', + showIcon: 'Breadcrumb Icon Visible' + } + }, + tab: { + visible: 'Tab Visible', + cache: 'Tag Bar Info Cache', + height: 'Tab Height', + mode: { + title: 'Tab Mode', + chrome: 'Chrome', + button: 'Button' + } + }, + sider: { + inverted: 'Dark Sider', + width: 'Sider Width', + collapsedWidth: 'Sider Collapsed Width', + mixWidth: 'Mix Sider Width', + mixCollapsedWidth: 'Mix Sider Collapse Width', + mixChildMenuWidth: 'Mix Child Menu Width' + }, + footer: { + visible: 'Footer Visible', + fixed: 'Fixed Footer', + height: 'Footer Height', + right: 'Right Footer' + }, + watermark: { + visible: 'Watermark Full Screen Visible', + text: 'Watermark Text' + }, + themeDrawerTitle: 'Theme Configuration', + pageFunTitle: 'Page Function', + resetCacheStrategy: { + title: 'Reset Cache Strategy', + close: 'Close Page', + refresh: 'Refresh Page' + }, + configOperation: { + copyConfig: 'Copy Config', + copySuccessMsg: 'Copy Success, Please replace the variable "themeSettings" in "src/theme/settings.ts"', + resetConfig: 'Reset Config', + resetSuccessMsg: 'Reset Success' + } + }, + route: { + login: 'Login', + 403: 'No Permission', + 404: 'Page Not Found', + 500: 'Server Error', + 'iframe-page': 'Iframe', + home: 'Home', + document: 'Document', + document_project: 'Project Document', + 'document_project-link': 'Project Document(External Link)', + document_vue: 'Vue Document', + document_vite: 'Vite Document', + document_unocss: 'UnoCSS Document', + document_naive: 'Naive UI Document', + document_antd: 'Ant Design Vue Document', + 'user-center': 'User Center', + about: 'About', + function: 'System Function', + function_tab: 'Tab', + 'function_multi-tab': 'Multi Tab', + 'function_hide-child': 'Hide Child', + 'function_hide-child_one': 'Hide Child', + 'function_hide-child_two': 'Two', + 'function_hide-child_three': 'Three', + function_request: 'Request', + 'function_toggle-auth': 'Toggle Auth', + 'function_super-page': 'Super Admin Visible', + manage: 'System Manage', + manage_user: 'User Manage', + 'manage_user-detail': 'User Detail', + manage_role: 'Role Manage', + manage_menu: 'Menu Manage', + 'multi-menu': 'Multi Menu', + 'multi-menu_first': 'Menu One', + 'multi-menu_first_child': 'Menu One Child', + 'multi-menu_second': 'Menu Two', + 'multi-menu_second_child': 'Menu Two Child', + 'multi-menu_second_child_home': 'Menu Two Child Home', + exception: 'Exception', + exception_403: '403', + exception_404: '404', + exception_500: '500' + }, + page: { + login: { + common: { + loginOrRegister: 'Login / Register', + userNamePlaceholder: 'Please enter user name', + phonePlaceholder: 'Please enter phone number', + codePlaceholder: 'Please enter verification code', + passwordPlaceholder: 'Please enter password', + confirmPasswordPlaceholder: 'Please enter password again', + codeLogin: 'Verification code login', + confirm: 'Confirm', + back: 'Back', + validateSuccess: 'Verification passed', + loginSuccess: 'Login successfully', + welcomeBack: 'Welcome back, {userName} !' + }, + pwdLogin: { + title: 'Password Login', + rememberMe: 'Remember me', + forgetPassword: 'Forget password?', + register: 'Register', + otherAccountLogin: 'Other Account Login', + otherLoginMode: 'Other Login Mode', + superAdmin: 'Super Admin', + admin: 'Admin', + user: 'User' + }, + codeLogin: { + title: 'Verification Code Login', + getCode: 'Get verification code', + reGetCode: 'Reacquire after {time}s', + sendCodeSuccess: 'Verification code sent successfully', + imageCodePlaceholder: 'Please enter image verification code' + }, + register: { + title: 'Register', + agreement: 'I have read and agree to', + protocol: '《User Agreement》', + policy: '《Privacy Policy》' + }, + resetPwd: { + title: 'Reset Password' + }, + bindWeChat: { + title: 'Bind WeChat' + } + }, + about: { + title: 'About', + introduction: `SoybeanAdmin is an elegant and powerful admin template, based on the latest front-end technology stack, including Vue3, Vite5, TypeScript, Pinia and UnoCSS. It has built-in rich theme configuration and components, strict code specifications, and an automated file routing system. In addition, it also uses the online mock data solution based on ApiFox. SoybeanAdmin provides you with a one-stop admin solution, no additional configuration, and out of the box. It is also a best practice for learning cutting-edge technologies quickly.`, + projectInfo: { + title: 'Project Info', + version: 'Version', + latestBuildTime: 'Latest Build Time', + githubLink: 'Github Link', + previewLink: 'Preview Link' + }, + prdDep: 'Production Dependency', + devDep: 'Development Dependency' + }, + home: { + greeting: 'Good morning, {userName}, today is another day full of vitality!', + weatherDesc: 'Today is cloudy to clear, 20℃ - 25℃!', + projectCount: 'Project Count', + todo: 'Todo', + message: 'Message', + downloadCount: 'Download Count', + registerCount: 'Register Count', + schedule: 'Work and rest Schedule', + study: 'Study', + work: 'Work', + rest: 'Rest', + entertainment: 'Entertainment', + visitCount: 'Visit Count', + turnover: 'Turnover', + dealCount: 'Deal Count', + projectNews: { + title: 'Project News', + moreNews: 'More News', + desc1: 'Soybean created the open source project soybean-admin on May 28, 2021!', + desc2: 'Yanbowe submitted a bug to soybean-admin, the multi-tab bar will not adapt.', + desc3: 'Soybean is ready to do sufficient preparation for the release of soybean-admin!', + desc4: 'Soybean is busy writing project documentation for soybean-admin!', + desc5: 'Soybean just wrote some of the workbench pages casually, and it was enough to see!' + }, + creativity: 'Creativity' + }, + function: { + tab: { + tabOperate: { + title: 'Tab Operation', + addTab: 'Add Tab', + addTabDesc: 'To about page', + closeTab: 'Close Tab', + closeCurrentTab: 'Close Current Tab', + closeAboutTab: 'Close "About" Tab', + addMultiTab: 'Add Multi Tab', + addMultiTabDesc1: 'To MultiTab page', + addMultiTabDesc2: 'To MultiTab page(with query params)' + }, + tabTitle: { + title: 'Tab Title', + changeTitle: 'Change Title', + change: 'Change', + resetTitle: 'Reset Title', + reset: 'Reset' + } + }, + multiTab: { + routeParam: 'Route Param', + backTab: 'Back function_tab' + }, + toggleAuth: { + toggleAccount: 'Toggle Account', + authHook: 'Auth Hook Function `hasAuth`', + superAdminVisible: 'Super Admin Visible', + adminVisible: 'Admin Visible', + adminOrUserVisible: 'Admin and User Visible' + }, + request: { + repeatedErrorOccurOnce: 'Repeated Request Error Occurs Once', + repeatedError: 'Repeated Request Error', + repeatedErrorMsg1: 'Custom Request Error 1', + repeatedErrorMsg2: 'Custom Request Error 2' + } + }, + manage: { + common: { + status: { + enable: 'Enable', + disable: 'Disable' + } + }, + role: { + title: 'Role List', + roleName: 'Role Name', + roleCode: 'Role Code', + roleStatus: 'Role Status', + roleDesc: 'Role Description', + menuAuth: 'Menu Auth', + buttonAuth: 'Button Auth', + form: { + roleName: 'Please enter role name', + roleCode: 'Please enter role code', + roleStatus: 'Please select role status', + roleDesc: 'Please enter role description' + }, + addRole: 'Add Role', + editRole: 'Edit Role' + }, + user: { + title: 'User List', + userName: 'User Name', + userGender: 'Gender', + nickName: 'Nick Name', + userPhone: 'Phone Number', + userEmail: 'Email', + userStatus: 'User Status', + userRole: 'User Role', + form: { + userName: 'Please enter user name', + userGender: 'Please select gender', + nickName: 'Please enter nick name', + userPhone: 'Please enter phone number', + userEmail: 'Please enter email', + userStatus: 'Please select user status', + userRole: 'Please select user role' + }, + addUser: 'Add User', + editUser: 'Edit User', + gender: { + male: 'Male', + female: 'Female' + } + }, + menu: { + home: 'Home', + title: 'Menu List', + id: 'ID', + parentId: 'Parent ID', + menuType: 'Menu Type', + menuName: 'Menu Name', + query: 'Query Params', + routeName: 'Route Name', + routePath: 'Route Path', + layout: 'Layout Component', + page: 'Page Component', + i18nKey: 'I18n Key', + icon: 'Icon', + localIcon: 'Local Icon', + constant: 'Constant', + iconTypeTitle: 'Icon Type', + order: 'Order', + keepAlive: 'Keep Alive', + pathParam: 'Path Param', + href: 'Href', + hideInMenu: 'Hide In Menu', + activeMenu: 'Active Menu', + multiTab: 'Multi Tab', + fixedIndexInTab: 'Fixed Index In Tab', + button: 'Button', + buttonCode: 'Button Code', + buttonDesc: 'Button Desc', + menuStatus: 'Menu Status', + form: { + home: 'Please select home', + menuType: 'Please select menu type', + menuName: 'Please enter menu name', + routeName: 'Please enter route name', + routePath: 'Please enter route path', + pathParam: 'Please enter path param', + page: 'Please select page component', + layout: 'Please select layout component', + i18nKey: 'Please enter i18n key', + icon: 'Please enter iconify name', + localIcon: 'Please enter local icon name', + order: 'Please enter order', + keepAlive: 'Please select whether to cache route', + href: 'Please enter href', + hideInMenu: 'Please select whether to hide menu', + activeMenu: 'Please enter the route name of the highlighted menu', + multiTab: 'Please select whether to support multiple tabs', + queryKey: 'Please enter route parameter Key', + queryValue: 'Please enter route parameter Value', + fixedInTab: 'Please select whether to fix in the tab', + fixedIndexInTab: 'Please enter the index fixed in the tab', + button: 'Please select whether it is a button', + buttonCode: 'Please enter button code', + buttonDesc: 'Please enter button description', + menuStatus: 'Please select menu status' + }, + addMenu: 'Add Menu', + editMenu: 'Edit Menu', + addChildMenu: 'Add Child Menu', + type: { + directory: 'Directory', + menu: 'Menu' + }, + iconType: { + iconify: 'Iconify Icon', + local: 'Local Icon' + } + } + } + }, + form: { + required: 'Cannot be empty', + userName: { + required: 'Please enter user name', + invalid: 'User name format is incorrect' + }, + phone: { + required: 'Please enter phone number', + invalid: 'Phone number format is incorrect' + }, + pwd: { + required: 'Please enter password', + invalid: '6-18 characters, including letters, numbers, and underscores' + }, + confirmPwd: { + required: 'Please enter password again', + invalid: 'The two passwords are inconsistent' + }, + code: { + required: 'Please enter verification code', + invalid: 'Verification code format is incorrect' + }, + email: { + required: 'Please enter email', + invalid: 'Email format is incorrect' + } + }, + dropdown: { + closeCurrent: 'Close Current', + closeOther: 'Close Other', + closeLeft: 'Close Left', + closeRight: 'Close Right', + closeAll: 'Close All' + }, + icon: { + themeConfig: 'Theme Configuration', + themeSchema: 'Theme Schema', + lang: 'Switch Language', + fullscreen: 'Fullscreen', + fullscreenExit: 'Exit Fullscreen', + reload: 'Reload Page', + collapse: 'Collapse Menu', + expand: 'Expand Menu', + pin: 'Pin', + unpin: 'Unpin' + } +}; + +export default local; diff --git a/src/locales/langs/zh-cn.ts b/src/locales/langs/zh-cn.ts new file mode 100644 index 0000000..0f6338e --- /dev/null +++ b/src/locales/langs/zh-cn.ts @@ -0,0 +1,490 @@ +const local: App.I18n.Schema = { + system: { + title: 'Soybean 管理系统', + updateTitle: '系统版本更新通知', + updateContent: '检测到系统有新版本发布,是否立即刷新页面?', + updateConfirm: '立即刷新', + updateCancel: '稍后再说' + }, + common: { + action: '操作', + add: '新增', + addSuccess: '添加成功', + backToHome: '返回首页', + batchDelete: '批量删除', + cancel: '取消', + close: '关闭', + check: '勾选', + columnSetting: '列设置', + config: '配置', + confirm: '确认', + delete: '删除', + deleteSuccess: '删除成功', + confirmDelete: '确认删除吗?', + edit: '编辑', + error: '错误', + index: '序号', + keywordSearch: '请输入关键词搜索', + logout: '退出登录', + logoutConfirm: '确认退出登录吗?', + lookForward: '敬请期待', + modify: '修改', + modifySuccess: '修改成功', + noData: '无数据', + operate: '操作', + pleaseCheckValue: '请检查输入的值是否合法', + refresh: '刷新', + reset: '重置', + search: '搜索', + switch: '切换', + tip: '提示', + trigger: '触发', + update: '更新', + updateSuccess: '更新成功', + userCenter: '个人中心', + yesOrNo: { + yes: '是', + no: '否' + } + }, + request: { + logout: '请求失败后登出用户', + logoutMsg: '用户状态失效,请重新登录', + logoutWithModal: '请求失败后弹出模态框再登出用户', + logoutWithModalMsg: '用户状态失效,请重新登录', + refreshToken: '请求的token已过期,刷新token', + tokenExpired: 'token已过期' + }, + theme: { + themeSchema: { + title: '主题模式', + light: '亮色模式', + dark: '暗黑模式', + auto: '跟随系统' + }, + grayscale: '灰色模式', + colourWeakness: '色弱模式', + layoutMode: { + title: '布局模式', + vertical: '左侧菜单模式', + 'vertical-mix': '左侧菜单混合模式', + horizontal: '顶部菜单模式', + 'horizontal-mix': '顶部菜单混合模式', + reverseHorizontalMix: '一级菜单与子级菜单位置反转' + }, + recommendColor: '应用推荐算法的颜色', + recommendColorDesc: '推荐颜色的算法参照', + themeColor: { + title: '主题颜色', + primary: '主色', + info: '信息色', + success: '成功色', + warning: '警告色', + error: '错误色', + followPrimary: '跟随主色' + }, + scrollMode: { + title: '滚动模式', + wrapper: '外层滚动', + content: '主体滚动' + }, + page: { + animate: '页面切换动画', + mode: { + title: '页面切换动画类型', + 'fade-slide': '滑动', + fade: '淡入淡出', + 'fade-bottom': '底部消退', + 'fade-scale': '缩放消退', + 'zoom-fade': '渐变', + 'zoom-out': '闪现', + none: '无' + } + }, + fixedHeaderAndTab: '固定头部和标签栏', + header: { + height: '头部高度', + breadcrumb: { + visible: '显示面包屑', + showIcon: '显示面包屑图标' + } + }, + tab: { + visible: '显示标签栏', + cache: '标签栏信息缓存', + height: '标签栏高度', + mode: { + title: '标签栏风格', + chrome: '谷歌风格', + button: '按钮风格' + } + }, + sider: { + inverted: '深色侧边栏', + width: '侧边栏宽度', + collapsedWidth: '侧边栏折叠宽度', + mixWidth: '混合布局侧边栏宽度', + mixCollapsedWidth: '混合布局侧边栏折叠宽度', + mixChildMenuWidth: '混合布局子菜单宽度' + }, + footer: { + visible: '显示底部', + fixed: '固定底部', + height: '底部高度', + right: '底部局右' + }, + watermark: { + visible: '显示全屏水印', + text: '水印文本' + }, + themeDrawerTitle: '主题配置', + pageFunTitle: '页面功能', + resetCacheStrategy: { + title: '重置缓存策略', + close: '关闭页面', + refresh: '刷新页面' + }, + configOperation: { + copyConfig: '复制配置', + copySuccessMsg: '复制成功,请替换 src/theme/settings.ts 中的变量 themeSettings', + resetConfig: '重置配置', + resetSuccessMsg: '重置成功' + } + }, + route: { + login: '登录', + 403: '无权限', + 404: '页面不存在', + 500: '服务器错误', + 'iframe-page': '外链页面', + home: '首页', + document: '文档', + document_project: '项目文档', + 'document_project-link': '项目文档(外链)', + document_vue: 'Vue文档', + document_vite: 'Vite文档', + document_unocss: 'UnoCSS文档', + document_naive: 'Naive UI文档', + document_antd: 'Ant Design Vue文档', + 'user-center': '个人中心', + about: '关于', + function: '系统功能', + function_tab: '标签页', + 'function_multi-tab': '多标签页', + 'function_hide-child': '隐藏子菜单', + 'function_hide-child_one': '隐藏子菜单', + 'function_hide-child_two': '菜单二', + 'function_hide-child_three': '菜单三', + function_request: '请求', + 'function_toggle-auth': '切换权限', + 'function_super-page': '超级管理员可见', + manage: '系统管理', + manage_user: '用户管理', + 'manage_user-detail': '用户详情', + manage_role: '角色管理', + manage_menu: '菜单管理', + 'multi-menu': '多级菜单', + 'multi-menu_first': '菜单一', + 'multi-menu_first_child': '菜单一子菜单', + 'multi-menu_second': '菜单二', + 'multi-menu_second_child': '菜单二子菜单', + 'multi-menu_second_child_home': '菜单二子菜单首页', + exception: '异常页', + exception_403: '403', + exception_404: '404', + exception_500: '500' + }, + page: { + login: { + common: { + loginOrRegister: '登录 / 注册', + userNamePlaceholder: '请输入用户名', + phonePlaceholder: '请输入手机号', + codePlaceholder: '请输入验证码', + passwordPlaceholder: '请输入密码', + confirmPasswordPlaceholder: '请再次输入密码', + codeLogin: '验证码登录', + confirm: '确定', + back: '返回', + validateSuccess: '验证成功', + loginSuccess: '登录成功', + welcomeBack: '欢迎回来,{userName} !' + }, + pwdLogin: { + title: '密码登录', + rememberMe: '记住我', + forgetPassword: '忘记密码?', + register: '注册账号', + otherAccountLogin: '其他账号登录', + otherLoginMode: '其他登录方式', + superAdmin: '超级管理员', + admin: '管理员', + user: '普通用户' + }, + codeLogin: { + title: '验证码登录', + getCode: '获取验证码', + reGetCode: '{time}秒后重新获取', + sendCodeSuccess: '验证码发送成功', + imageCodePlaceholder: '请输入图片验证码' + }, + register: { + title: '注册账号', + agreement: '我已经仔细阅读并接受', + protocol: '《用户协议》', + policy: '《隐私权政策》' + }, + resetPwd: { + title: '重置密码' + }, + bindWeChat: { + title: '绑定微信' + } + }, + about: { + title: '关于', + introduction: `SoybeanAdmin 是一个优雅且功能强大的后台管理模板,基于最新的前端技术栈,包括 Vue3, Vite5, TypeScript, Pinia 和 UnoCSS。它内置了丰富的主题配置和组件,代码规范严谨,实现了自动化的文件路由系统。此外,它还采用了基于 ApiFox 的在线Mock数据方案。SoybeanAdmin 为您提供了一站式的后台管理解决方案,无需额外配置,开箱即用。同样是一个快速学习前沿技术的最佳实践。`, + projectInfo: { + title: '项目信息', + version: '版本', + latestBuildTime: '最新构建时间', + githubLink: 'Github 地址', + previewLink: '预览地址' + }, + prdDep: '生产依赖', + devDep: '开发依赖' + }, + home: { + greeting: '早安,{userName}, 今天又是充满活力的一天!', + weatherDesc: '今日多云转晴,20℃ - 25℃!', + projectCount: '项目数', + todo: '待办', + message: '消息', + downloadCount: '下载量', + registerCount: '注册量', + schedule: '作息安排', + study: '学习', + work: '工作', + rest: '休息', + entertainment: '娱乐', + visitCount: '访问量', + turnover: '成交额', + dealCount: '成交量', + projectNews: { + title: '项目动态', + moreNews: '更多动态', + desc1: 'Soybean 在2021年5月28日创建了开源项目 soybean-admin!', + desc2: 'Yanbowe 向 soybean-admin 提交了一个bug,多标签栏不会自适应。', + desc3: 'Soybean 准备为 soybean-admin 的发布做充分的准备工作!', + desc4: 'Soybean 正在忙于为soybean-admin写项目说明文档!', + desc5: 'Soybean 刚才把工作台页面随便写了一些,凑合能看了!' + }, + creativity: '创意' + }, + function: { + tab: { + tabOperate: { + title: '标签页操作', + addTab: '添加标签页', + addTabDesc: '跳转到关于页面', + closeTab: '关闭标签页', + closeCurrentTab: '关闭当前标签页', + closeAboutTab: '关闭"关于"标签页', + addMultiTab: '添加多标签页', + addMultiTabDesc1: '跳转到多标签页页面', + addMultiTabDesc2: '跳转到多标签页页面(带有查询参数)' + }, + tabTitle: { + title: '标签页标题', + changeTitle: '修改标题', + change: '修改', + resetTitle: '重置标题', + reset: '重置' + } + }, + multiTab: { + routeParam: '路由参数', + backTab: '返回 function_tab' + }, + toggleAuth: { + toggleAccount: '切换账号', + authHook: '权限钩子函数 `hasAuth`', + superAdminVisible: '超级管理员可见', + adminVisible: '管理员可见', + adminOrUserVisible: '管理员和用户可见' + }, + request: { + repeatedErrorOccurOnce: '重复请求错误只出现一次', + repeatedError: '重复请求错误', + repeatedErrorMsg1: '自定义请求错误 1', + repeatedErrorMsg2: '自定义请求错误 2' + } + }, + manage: { + common: { + status: { + enable: '启用', + disable: '禁用' + } + }, + role: { + title: '角色列表', + roleName: '角色名称', + roleCode: '角色编码', + roleStatus: '角色状态', + roleDesc: '角色描述', + menuAuth: '菜单权限', + buttonAuth: '按钮权限', + form: { + roleName: '请输入角色名称', + roleCode: '请输入角色编码', + roleStatus: '请选择角色状态', + roleDesc: '请输入角色描述' + }, + addRole: '新增角色', + editRole: '编辑角色' + }, + user: { + title: '用户列表', + userName: '用户名', + userGender: '性别', + nickName: '昵称', + userPhone: '手机号', + userEmail: '邮箱', + userStatus: '用户状态', + userRole: '用户角色', + form: { + userName: '请输入用户名', + userGender: '请选择性别', + nickName: '请输入昵称', + userPhone: '请输入手机号', + userEmail: '请输入邮箱', + userStatus: '请选择用户状态', + userRole: '请选择用户角色' + }, + addUser: '新增用户', + editUser: '编辑用户', + gender: { + male: '男', + female: '女' + } + }, + menu: { + home: '首页', + title: '菜单列表', + id: 'ID', + parentId: '父级菜单ID', + menuType: '菜单类型', + menuName: '菜单名称', + routeName: '路由名称', + query: '路由参数', + routePath: '路由路径', + pathParam: '路径参数', + layout: '布局', + page: '页面组件', + i18nKey: '国际化key', + icon: '图标', + localIcon: '本地图标', + iconTypeTitle: '图标类型', + order: '排序', + keepAlive: '缓存路由', + href: '外链', + hideInMenu: '隐藏菜单', + activeMenu: '高亮的菜单', + multiTab: '支持多页签', + fixedIndexInTab: '固定在页签中的序号', + button: '按钮', + buttonCode: '按钮编码', + buttonDesc: '按钮描述', + menuStatus: '菜单状态', + constant: '常量路由', + form: { + home: '请选择首页', + menuType: '请选择菜单类型', + menuName: '请输入菜单名称', + routeName: '请输入路由名称', + routePath: '请输入路由路径', + pathParam: '请输入路径参数', + page: '请选择页面组件', + layout: '请选择布局组件', + i18nKey: '请输入国际化key', + icon: '请输入图标', + queryKey: '请输入路由参数Key', + queryValue: '请输入路由参数Value', + localIcon: '请选择本地图标', + order: '请输入排序', + keepAlive: '请选择是否缓存路由', + href: '请输入外链', + hideInMenu: '请选择是否隐藏菜单', + activeMenu: '请输入高亮的菜单的路由名称', + multiTab: '请选择是否支持多标签', + fixedInTab: '请选择是否固定在页签中', + fixedIndexInTab: '请输入固定在页签中的序号', + button: '请选择是否按钮', + buttonCode: '请输入按钮编码', + buttonDesc: '请输入按钮描述', + menuStatus: '请选择菜单状态' + }, + addMenu: '新增菜单', + editMenu: '编辑菜单', + addChildMenu: '新增子菜单', + type: { + directory: '目录', + menu: '菜单' + }, + iconType: { + iconify: 'iconify图标', + local: '本地图标' + } + } + } + }, + form: { + required: '不能为空', + userName: { + required: '请输入用户名', + invalid: '用户名格式不正确' + }, + phone: { + required: '请输入手机号', + invalid: '手机号格式不正确' + }, + pwd: { + required: '请输入密码', + invalid: '密码格式不正确,6-18位字符,包含字母、数字、下划线' + }, + confirmPwd: { + required: '请输入确认密码', + invalid: '两次输入密码不一致' + }, + code: { + required: '请输入验证码', + invalid: '验证码格式不正确' + }, + email: { + required: '请输入邮箱', + invalid: '邮箱格式不正确' + } + }, + dropdown: { + closeCurrent: '关闭', + closeOther: '关闭其它', + closeLeft: '关闭左侧', + closeRight: '关闭右侧', + closeAll: '关闭所有' + }, + icon: { + themeConfig: '主题配置', + themeSchema: '主题模式', + lang: '切换语言', + fullscreen: '全屏', + fullscreenExit: '退出全屏', + reload: '刷新页面', + collapse: '折叠菜单', + expand: '展开菜单', + pin: '固定', + unpin: '取消固定' + } +}; + +export default local; diff --git a/src/locales/locale.ts b/src/locales/locale.ts new file mode 100644 index 0000000..dc38010 --- /dev/null +++ b/src/locales/locale.ts @@ -0,0 +1,9 @@ +import zhCN from './langs/zh-cn'; +import enUS from './langs/en-us'; + +const locales: Record = { + 'zh-CN': zhCN, + 'en-US': enUS +}; + +export default locales; diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..b97a0d9 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,31 @@ +import { createApp } from 'vue'; +import './plugins/assets'; +import { setupAppVersionNotification, setupDayjs, setupIconifyOffline, setupLoading, setupNProgress } from './plugins'; +import { setupStore } from './store'; +import { setupRouter } from './router'; +import { setupI18n } from './locales'; +import App from './App.vue'; + +async function setupApp() { + setupLoading(); + + setupNProgress(); + + setupIconifyOffline(); + + setupDayjs(); + + const app = createApp(App); + + setupStore(app); + + await setupRouter(app); + + setupI18n(app); + + setupAppVersionNotification(); + + app.mount('#app'); +} + +setupApp(); diff --git a/src/plugins/app.ts b/src/plugins/app.ts new file mode 100644 index 0000000..d247588 --- /dev/null +++ b/src/plugins/app.ts @@ -0,0 +1,105 @@ +import { h } from 'vue'; +import type { App } from 'vue'; +import { Button } from 'ant-design-vue'; +import { $t } from '@/locales'; + +export function setupAppErrorHandle(app: App) { + app.config.errorHandler = (err, vm, info) => { + // eslint-disable-next-line no-console + console.error(err, vm, info); + }; +} + +export function setupAppVersionNotification() { + // Update check interval in milliseconds + const UPDATE_CHECK_INTERVAL = 3 * 60 * 1000; + + const canAutoUpdateApp = import.meta.env.VITE_AUTOMATICALLY_DETECT_UPDATE === 'Y' && import.meta.env.PROD; + if (!canAutoUpdateApp) return; + + let isShow = false; + let updateInterval: ReturnType | undefined; + + const checkForUpdates = async () => { + if (isShow) return; + + const buildTime = await getHtmlBuildTime(); + + // If build time hasn't changed, no update is needed + if (buildTime === BUILD_TIME) { + return; + } + + isShow = true; + + const key = `open${Date.now()}`; + + window.$notification?.open({ + key, + message: $t('system.updateTitle'), + description: $t('system.updateContent'), + btn() { + return h('div', { style: { display: 'flex', justifyContent: 'end', gap: '12px', width: '325px' } }, [ + h( + Button, + { + onClick() { + window.$notification?.destroy(key); + isShow = false; + } + }, + () => $t('system.updateCancel') + ), + h( + Button, + { + type: 'primary', + onClick() { + location.reload(); + } + }, + () => $t('system.updateConfirm') + ) + ]); + }, + onClose() { + isShow = false; + } + }); + }; + + const startUpdateInterval = () => { + if (updateInterval) { + clearInterval(updateInterval); + } + updateInterval = setInterval(checkForUpdates, UPDATE_CHECK_INTERVAL); + }; + + // If updates should be checked, set up the visibility change listener and start the update interval + if (!isShow && document.visibilityState === 'visible') { + // Check for updates when the document is visible + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + checkForUpdates(); + startUpdateInterval(); + } + }); + + // Start the update interval + startUpdateInterval(); + } +} + +async function getHtmlBuildTime() { + const baseUrl = import.meta.env.VITE_BASE_URL || '/'; + + const res = await fetch(`${baseUrl}index.html?time=${Date.now()}`); + + const html = await res.text(); + + const match = html.match(//); + + const buildTime = match?.[1] || ''; + + return buildTime; +} diff --git a/src/plugins/assets.ts b/src/plugins/assets.ts new file mode 100644 index 0000000..904aa6a --- /dev/null +++ b/src/plugins/assets.ts @@ -0,0 +1,3 @@ +import 'virtual:svg-icons-register'; +import 'uno.css'; +import '../styles/css/global.css'; diff --git a/src/plugins/dayjs.ts b/src/plugins/dayjs.ts new file mode 100644 index 0000000..d3f96ee --- /dev/null +++ b/src/plugins/dayjs.ts @@ -0,0 +1,9 @@ +import { extend } from 'dayjs'; +import localeData from 'dayjs/plugin/localeData'; +import { setDayjsLocale } from '../locales/dayjs'; + +export function setupDayjs() { + extend(localeData); + + setDayjsLocale(); +} diff --git a/src/plugins/iconify.ts b/src/plugins/iconify.ts new file mode 100644 index 0000000..f58d669 --- /dev/null +++ b/src/plugins/iconify.ts @@ -0,0 +1,12 @@ +import { addAPIProvider, disableCache } from '@iconify/vue'; + +/** Setup the iconify offline */ +export function setupIconifyOffline() { + const { VITE_ICONIFY_URL } = import.meta.env; + + if (VITE_ICONIFY_URL) { + addAPIProvider('', { resources: [VITE_ICONIFY_URL] }); + + disableCache('all'); + } +} diff --git a/src/plugins/index.ts b/src/plugins/index.ts new file mode 100644 index 0000000..b2c9f9b --- /dev/null +++ b/src/plugins/index.ts @@ -0,0 +1,5 @@ +export * from './loading'; +export * from './nprogress'; +export * from './iconify'; +export * from './dayjs'; +export * from './app'; diff --git a/src/plugins/loading.ts b/src/plugins/loading.ts new file mode 100644 index 0000000..d61bc58 --- /dev/null +++ b/src/plugins/loading.ts @@ -0,0 +1,45 @@ +// @unocss-include +import { getRgbOfColor } from '@sa/utils'; +import { $t } from '@/locales'; +import { localStg } from '@/utils/storage'; +import systemLogo from '@/assets/svg-icon/logo.svg?raw'; + +export function setupLoading() { + const themeColor = localStg.get('themeColor') || '#646cff'; + + const { r, g, b } = getRgbOfColor(themeColor); + + const primaryColor = `--primary-color: ${r} ${g} ${b}`; + + const loadingClasses = [ + 'left-0 top-0', + 'left-0 bottom-0 animate-delay-500', + 'right-0 top-0 animate-delay-1000', + 'right-0 bottom-0 animate-delay-1500' + ]; + + const logoWithClass = systemLogo.replace(' { + return `

`; + }) + .join('\n'); + + const loading = ` +
+ ${logoWithClass} +
+
+ ${dot} +
+
+

${$t('system.title')}

+
`; + + const app = document.getElementById('app'); + + if (app) { + app.innerHTML = loading; + } +} diff --git a/src/plugins/nprogress.ts b/src/plugins/nprogress.ts new file mode 100644 index 0000000..841ae1e --- /dev/null +++ b/src/plugins/nprogress.ts @@ -0,0 +1,9 @@ +import NProgress from 'nprogress'; + +/** Setup plugin NProgress */ +export function setupNProgress() { + NProgress.configure({ easing: 'ease', speed: 500 }); + + // mount on window + window.NProgress = NProgress; +} diff --git a/src/router/elegant/imports.ts b/src/router/elegant/imports.ts new file mode 100644 index 0000000..5c9ebee --- /dev/null +++ b/src/router/elegant/imports.ts @@ -0,0 +1,40 @@ +/* eslint-disable */ +/* prettier-ignore */ +// Generated by elegant-router +// Read more: https://github.com/soybeanjs/elegant-router + +import type { RouteComponent } from "vue-router"; +import type { LastLevelRouteKey, RouteLayout } from "@elegant-router/types"; + +import BaseLayout from "@/layouts/base-layout/index.vue"; +import BlankLayout from "@/layouts/blank-layout/index.vue"; + +export const layouts: Record Promise)> = { + base: BaseLayout, + blank: BlankLayout, +}; + +export const views: Record Promise)> = { + 403: () => import("@/views/_builtin/403/index.vue"), + 404: () => import("@/views/_builtin/404/index.vue"), + 500: () => import("@/views/_builtin/500/index.vue"), + "iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"), + login: () => import("@/views/_builtin/login/index.vue"), + about: () => import("@/views/about/index.vue"), + "function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"), + "function_hide-child_three": () => import("@/views/function/hide-child/three/index.vue"), + "function_hide-child_two": () => import("@/views/function/hide-child/two/index.vue"), + "function_multi-tab": () => import("@/views/function/multi-tab/index.vue"), + function_request: () => import("@/views/function/request/index.vue"), + "function_super-page": () => import("@/views/function/super-page/index.vue"), + function_tab: () => import("@/views/function/tab/index.vue"), + "function_toggle-auth": () => import("@/views/function/toggle-auth/index.vue"), + home: () => import("@/views/home/index.vue"), + manage_menu: () => import("@/views/manage/menu/index.vue"), + manage_role: () => import("@/views/manage/role/index.vue"), + "manage_user-detail": () => import("@/views/manage/user-detail/[id].vue"), + manage_user: () => import("@/views/manage/user/index.vue"), + "multi-menu_first_child": () => import("@/views/multi-menu/first_child/index.vue"), + "multi-menu_second_child_home": () => import("@/views/multi-menu/second_child_home/index.vue"), + "user-center": () => import("@/views/user-center/index.vue"), +}; diff --git a/src/router/elegant/routes.ts b/src/router/elegant/routes.ts new file mode 100644 index 0000000..822c0be --- /dev/null +++ b/src/router/elegant/routes.ts @@ -0,0 +1,343 @@ +/* eslint-disable */ +/* prettier-ignore */ +// Generated by elegant-router +// Read more: https://github.com/soybeanjs/elegant-router + +import type { GeneratedRoute } from '@elegant-router/types'; + +export const generatedRoutes: GeneratedRoute[] = [ + { + name: '403', + path: '/403', + component: 'layout.blank$view.403', + meta: { + title: '403', + i18nKey: 'route.403', + constant: true, + hideInMenu: true + } + }, + { + name: '404', + path: '/404', + component: 'layout.blank$view.404', + meta: { + title: '404', + i18nKey: 'route.404', + constant: true, + hideInMenu: true + } + }, + { + name: '500', + path: '/500', + component: 'layout.blank$view.500', + meta: { + title: '500', + i18nKey: 'route.500', + constant: true, + hideInMenu: true + } + }, + { + name: 'about', + path: '/about', + component: 'layout.base$view.about', + meta: { + title: 'about', + i18nKey: 'route.about', + icon: 'fluent:book-information-24-regular', + order: 10 + } + }, + { + name: 'function', + path: '/function', + component: 'layout.base', + meta: { + title: 'function', + i18nKey: 'route.function', + icon: 'icon-park-outline:all-application', + order: 6 + }, + children: [ + { + name: 'function_hide-child', + path: '/function/hide-child', + meta: { + title: 'function_hide-child', + i18nKey: 'route.function_hide-child', + icon: 'material-symbols:filter-list-off', + order: 2 + }, + redirect: '/function/hide-child/one', + children: [ + { + name: 'function_hide-child_one', + path: '/function/hide-child/one', + component: 'view.function_hide-child_one', + meta: { + title: 'function_hide-child_one', + i18nKey: 'route.function_hide-child_one', + icon: 'material-symbols:filter-list-off', + hideInMenu: true, + activeMenu: 'function_hide-child' + } + }, + { + name: 'function_hide-child_three', + path: '/function/hide-child/three', + component: 'view.function_hide-child_three', + meta: { + title: 'function_hide-child_three', + i18nKey: 'route.function_hide-child_three', + hideInMenu: true, + activeMenu: 'function_hide-child' + } + }, + { + name: 'function_hide-child_two', + path: '/function/hide-child/two', + component: 'view.function_hide-child_two', + meta: { + title: 'function_hide-child_two', + i18nKey: 'route.function_hide-child_two', + hideInMenu: true, + activeMenu: 'function_hide-child' + } + } + ] + }, + { + name: 'function_multi-tab', + path: '/function/multi-tab', + component: 'view.function_multi-tab', + meta: { + title: 'function_multi-tab', + i18nKey: 'route.function_multi-tab', + icon: 'ic:round-tab', + multiTab: true, + hideInMenu: true, + activeMenu: 'function_tab' + } + }, + { + name: 'function_request', + path: '/function/request', + component: 'view.function_request', + meta: { + title: 'function_request', + i18nKey: 'route.function_request', + icon: 'carbon:network-overlay', + order: 3 + } + }, + { + name: 'function_super-page', + path: '/function/super-page', + component: 'view.function_super-page', + meta: { + title: 'function_super-page', + i18nKey: 'route.function_super-page', + icon: 'ic:round-supervisor-account', + order: 5, + roles: ['R_SUPER'] + } + }, + { + name: 'function_tab', + path: '/function/tab', + component: 'view.function_tab', + meta: { + title: 'function_tab', + i18nKey: 'route.function_tab', + icon: 'ic:round-tab', + order: 1 + } + }, + { + name: 'function_toggle-auth', + path: '/function/toggle-auth', + component: 'view.function_toggle-auth', + meta: { + title: 'function_toggle-auth', + i18nKey: 'route.function_toggle-auth', + icon: 'ic:round-construction', + order: 4 + } + } + ] + }, + { + name: 'home', + path: '/home', + component: 'layout.base$view.home', + meta: { + title: 'home', + i18nKey: 'route.home', + icon: 'mdi:monitor-dashboard', + order: 1 + } + }, + { + name: 'iframe-page', + path: '/iframe-page/:url', + component: 'layout.base$view.iframe-page', + props: true, + meta: { + title: 'iframe-page', + i18nKey: 'route.iframe-page', + constant: true, + hideInMenu: true, + keepAlive: true + } + }, + { + name: 'login', + path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?', + component: 'layout.blank$view.login', + props: true, + meta: { + title: 'login', + i18nKey: 'route.login', + constant: true, + hideInMenu: true + } + }, + { + name: 'manage', + path: '/manage', + component: 'layout.base', + meta: { + title: 'manage', + i18nKey: 'route.manage', + icon: 'carbon:cloud-service-management', + order: 9, + roles: ['R_ADMIN'] + }, + children: [ + { + name: 'manage_menu', + path: '/manage/menu', + component: 'view.manage_menu', + meta: { + title: 'manage_menu', + i18nKey: 'route.manage_menu', + icon: 'material-symbols:route', + order: 3, + roles: ['R_ADMIN'], + keepAlive: true + } + }, + { + name: 'manage_role', + path: '/manage/role', + component: 'view.manage_role', + meta: { + title: 'manage_role', + i18nKey: 'route.manage_role', + icon: 'carbon:user-role', + order: 2, + roles: ['R_SUPER'] + } + }, + { + name: 'manage_user', + path: '/manage/user', + component: 'view.manage_user', + meta: { + title: 'manage_user', + i18nKey: 'route.manage_user', + icon: 'ic:round-manage-accounts', + order: 1, + roles: ['R_ADMIN'] + } + }, + { + name: 'manage_user-detail', + path: '/manage/user-detail/:id', + component: 'view.manage_user-detail', + props: true, + meta: { + title: 'manage_user-detail', + i18nKey: 'route.manage_user-detail', + hideInMenu: true, + roles: ['R_ADMIN'], + activeMenu: 'manage_user' + } + } + ] + }, + { + name: 'multi-menu', + path: '/multi-menu', + component: 'layout.base', + meta: { + title: 'multi-menu', + i18nKey: 'route.multi-menu', + order: 8 + }, + children: [ + { + name: 'multi-menu_first', + path: '/multi-menu/first', + meta: { + title: 'multi-menu_first', + i18nKey: 'route.multi-menu_first', + order: 1 + }, + children: [ + { + name: 'multi-menu_first_child', + path: '/multi-menu/first/child', + component: 'view.multi-menu_first_child', + meta: { + title: 'multi-menu_first_child', + i18nKey: 'route.multi-menu_first_child' + } + } + ] + }, + { + name: 'multi-menu_second', + path: '/multi-menu/second', + meta: { + title: 'multi-menu_second', + i18nKey: 'route.multi-menu_second', + order: 2 + }, + children: [ + { + name: 'multi-menu_second_child', + path: '/multi-menu/second/child', + meta: { + title: 'multi-menu_second_child', + i18nKey: 'route.multi-menu_second_child' + }, + children: [ + { + name: 'multi-menu_second_child_home', + path: '/multi-menu/second/child/home', + component: 'view.multi-menu_second_child_home', + meta: { + title: 'multi-menu_second_child_home', + i18nKey: 'route.multi-menu_second_child_home' + } + } + ] + } + ] + } + ] + }, + { + name: 'user-center', + path: '/user-center', + component: 'layout.base$view.user-center', + meta: { + title: 'user-center', + i18nKey: 'route.user-center', + hideInMenu: true + } + } +]; diff --git a/src/router/elegant/transform.ts b/src/router/elegant/transform.ts new file mode 100644 index 0000000..203239b --- /dev/null +++ b/src/router/elegant/transform.ts @@ -0,0 +1,227 @@ +/* eslint-disable */ +/* prettier-ignore */ +// Generated by elegant-router +// Read more: https://github.com/soybeanjs/elegant-router + +import type { RouteRecordRaw, RouteComponent } from 'vue-router'; +import type { ElegantConstRoute } from '@elegant-router/vue'; +import type { RouteMap, RouteKey, RoutePath } from '@elegant-router/types'; + +/** + * transform elegant const routes to vue routes + * @param routes elegant const routes + * @param layouts layout components + * @param views view components + */ +export function transformElegantRoutesToVueRoutes( + routes: ElegantConstRoute[], + layouts: Record Promise)>, + views: Record Promise)> +) { + return routes.flatMap(route => transformElegantRouteToVueRoute(route, layouts, views)); +} + +/** + * transform elegant route to vue route + * @param route elegant const route + * @param layouts layout components + * @param views view components + */ +function transformElegantRouteToVueRoute( + route: ElegantConstRoute, + layouts: Record Promise)>, + views: Record Promise)> +) { + const LAYOUT_PREFIX = 'layout.'; + const VIEW_PREFIX = 'view.'; + const ROUTE_DEGREE_SPLITTER = '_'; + const FIRST_LEVEL_ROUTE_COMPONENT_SPLIT = '$'; + + function isLayout(component: string) { + return component.startsWith(LAYOUT_PREFIX); + } + + function getLayoutName(component: string) { + const layout = component.replace(LAYOUT_PREFIX, ''); + + if(!layouts[layout]) { + throw new Error(`Layout component "${layout}" not found`); + } + + return layout; + } + + function isView(component: string) { + return component.startsWith(VIEW_PREFIX); + } + + function getViewName(component: string) { + const view = component.replace(VIEW_PREFIX, ''); + + if(!views[view]) { + throw new Error(`View component "${view}" not found`); + } + + return view; + } + + function isFirstLevelRoute(item: ElegantConstRoute) { + return !item.name.includes(ROUTE_DEGREE_SPLITTER); + } + + function isSingleLevelRoute(item: ElegantConstRoute) { + return isFirstLevelRoute(item) && !item.children?.length; + } + + function getSingleLevelRouteComponent(component: string) { + const [layout, view] = component.split(FIRST_LEVEL_ROUTE_COMPONENT_SPLIT); + + return { + layout: getLayoutName(layout), + view: getViewName(view) + }; + } + + const vueRoutes: RouteRecordRaw[] = []; + + // add props: true to route + if (route.path.includes(':') && !route.props) { + route.props = true; + } + + const { name, path, component, children, ...rest } = route; + + const vueRoute = { name, path, ...rest } as RouteRecordRaw; + + try { + if (component) { + if (isSingleLevelRoute(route)) { + const { layout, view } = getSingleLevelRouteComponent(component); + + const singleLevelRoute: RouteRecordRaw = { + path, + component: layouts[layout], + meta: { + title: route.meta?.title || '' + }, + children: [ + { + name, + path: '', + component: views[view], + ...rest + } as RouteRecordRaw + ] + }; + + return [singleLevelRoute]; + } + + if (isLayout(component)) { + const layoutName = getLayoutName(component); + + vueRoute.component = layouts[layoutName]; + } + + if (isView(component)) { + const viewName = getViewName(component); + + vueRoute.component = views[viewName]; + } + + } + } catch (error: any) { + console.error(`Error transforming route "${route.name}": ${error.toString()}`); + return []; + } + + // add redirect to child + if (children?.length && !vueRoute.redirect) { + vueRoute.redirect = { + name: children[0].name + }; + } + + if (children?.length) { + const childRoutes = children.flatMap(child => transformElegantRouteToVueRoute(child, layouts, views)); + + if(isFirstLevelRoute(route)) { + vueRoute.children = childRoutes; + } else { + vueRoutes.push(...childRoutes); + } + } + + vueRoutes.unshift(vueRoute); + + return vueRoutes; +} + +/** + * map of route name and route path + */ +const routeMap: RouteMap = { + "root": "/", + "not-found": "/:pathMatch(.*)*", + "exception": "/exception", + "exception_403": "/exception/403", + "exception_404": "/exception/404", + "exception_500": "/exception/500", + "document": "/document", + "document_project": "/document/project", + "document_project-link": "/document/project-link", + "document_vue": "/document/vue", + "document_vite": "/document/vite", + "document_unocss": "/document/unocss", + "document_naive": "/document/naive", + "document_antd": "/document/antd", + "403": "/403", + "404": "/404", + "500": "/500", + "about": "/about", + "function": "/function", + "function_hide-child": "/function/hide-child", + "function_hide-child_one": "/function/hide-child/one", + "function_hide-child_three": "/function/hide-child/three", + "function_hide-child_two": "/function/hide-child/two", + "function_multi-tab": "/function/multi-tab", + "function_request": "/function/request", + "function_super-page": "/function/super-page", + "function_tab": "/function/tab", + "function_toggle-auth": "/function/toggle-auth", + "home": "/home", + "iframe-page": "/iframe-page/:url", + "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?", + "manage": "/manage", + "manage_menu": "/manage/menu", + "manage_role": "/manage/role", + "manage_user": "/manage/user", + "manage_user-detail": "/manage/user-detail/:id", + "multi-menu": "/multi-menu", + "multi-menu_first": "/multi-menu/first", + "multi-menu_first_child": "/multi-menu/first/child", + "multi-menu_second": "/multi-menu/second", + "multi-menu_second_child": "/multi-menu/second/child", + "multi-menu_second_child_home": "/multi-menu/second/child/home", + "user-center": "/user-center" +}; + +/** + * get route path by route name + * @param name route name + */ +export function getRoutePath(name: T) { + return routeMap[name]; +} + +/** + * get route name by route path + * @param path route path + */ +export function getRouteName(path: RoutePath) { + const routeEntries = Object.entries(routeMap) as [RouteKey, RoutePath][]; + + const routeName: RouteKey | null = routeEntries.find(([, routePath]) => routePath === path)?.[0] || null; + + return routeName; +} diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts new file mode 100644 index 0000000..9f91c9b --- /dev/null +++ b/src/router/guard/index.ts @@ -0,0 +1,15 @@ +import type { Router } from 'vue-router'; +import { createRouteGuard } from './route'; +import { createProgressGuard } from './progress'; +import { createDocumentTitleGuard } from './title'; + +/** + * Router guard + * + * @param router - Router instance + */ +export function createRouterGuard(router: Router) { + createProgressGuard(router); + createRouteGuard(router); + createDocumentTitleGuard(router); +} diff --git a/src/router/guard/progress.ts b/src/router/guard/progress.ts new file mode 100644 index 0000000..a1d4aee --- /dev/null +++ b/src/router/guard/progress.ts @@ -0,0 +1,11 @@ +import type { Router } from 'vue-router'; + +export function createProgressGuard(router: Router) { + router.beforeEach((_to, _from, next) => { + window.NProgress?.start?.(); + next(); + }); + router.afterEach(_to => { + window.NProgress?.done?.(); + }); +} diff --git a/src/router/guard/route.ts b/src/router/guard/route.ts new file mode 100644 index 0000000..64250c8 --- /dev/null +++ b/src/router/guard/route.ts @@ -0,0 +1,192 @@ +import type { + LocationQueryRaw, + NavigationGuardNext, + RouteLocationNormalized, + RouteLocationRaw, + Router +} from 'vue-router'; +import type { RouteKey, RoutePath } from '@elegant-router/types'; +import { getRouteName } from '@/router/elegant/transform'; +import { useAuthStore } from '@/store/modules/auth'; +import { useRouteStore } from '@/store/modules/route'; +import { localStg } from '@/utils/storage'; + +/** + * create route guard + * + * @param router router instance + */ +export function createRouteGuard(router: Router) { + router.beforeEach(async (to, from, next) => { + const location = await initRoute(to); + + if (location) { + next(location); + return; + } + + const authStore = useAuthStore(); + + const rootRoute: RouteKey = 'root'; + const loginRoute: RouteKey = 'login'; + const noAuthorizationRoute: RouteKey = '403'; + + const isLogin = Boolean(localStg.get('token')); + const needLogin = !to.meta.constant; + const routeRoles = to.meta.roles || []; + + const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role)); + const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole; + + // if it is login route when logged in, then switch to the root page + if (to.name === loginRoute && isLogin) { + next({ name: rootRoute }); + return; + } + + // if the route does not need login, then it is allowed to access directly + if (!needLogin) { + handleRouteSwitch(to, from, next); + return; + } + + // the route need login but the user is not logged in, then switch to the login page + if (!isLogin) { + next({ name: loginRoute, query: { redirect: to.fullPath } }); + return; + } + + // if the user is logged in but does not have authorization, then switch to the 403 page + if (!hasAuth) { + next({ name: noAuthorizationRoute }); + return; + } + + // switch route normally + handleRouteSwitch(to, from, next); + }); +} + +/** + * initialize route + * + * @param to to route + */ +async function initRoute(to: RouteLocationNormalized): Promise { + const routeStore = useRouteStore(); + + const notFoundRoute: RouteKey = 'not-found'; + const isNotFoundRoute = to.name === notFoundRoute; + + // if the constant route is not initialized, then initialize the constant route + if (!routeStore.isInitConstantRoute) { + await routeStore.initConstantRoute(); + + // the route is captured by the "not-found" route because the constant route is not initialized + // after the constant route is initialized, redirect to the original route + const path = to.fullPath; + const location: RouteLocationRaw = { + path, + replace: true, + query: to.query, + hash: to.hash + }; + + return location; + } + + const isLogin = Boolean(localStg.get('token')); + + if (!isLogin) { + // if the user is not logged in and the route is a constant route but not the "not-found" route, then it is allowed to access. + if (to.meta.constant && !isNotFoundRoute) { + routeStore.onRouteSwitchWhenNotLoggedIn(); + + return null; + } + + // if the user is not logged in, then switch to the login page + const loginRoute: RouteKey = 'login'; + const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome); + + const location: RouteLocationRaw = { + name: loginRoute, + query + }; + + return location; + } + + if (!routeStore.isInitAuthRoute) { + // initialize the auth route + await routeStore.initAuthRoute(); + + // the route is captured by the "not-found" route because the auth route is not initialized + // after the auth route is initialized, redirect to the original route + if (isNotFoundRoute) { + const rootRoute: RouteKey = 'root'; + const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath; + + const location: RouteLocationRaw = { + path, + replace: true, + query: to.query, + hash: to.hash + }; + + return location; + } + } + + routeStore.onRouteSwitchWhenLoggedIn(); + + // the auth route is initialized + // it is not the "not-found" route, then it is allowed to access + if (!isNotFoundRoute) { + return null; + } + + // it is captured by the "not-found" route, then check whether the route exists + const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath); + const noPermissionRoute: RouteKey = '403'; + + if (exist) { + const location: RouteLocationRaw = { + name: noPermissionRoute + }; + + return location; + } + + return null; +} + +function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) { + // route with href + if (to.meta.href) { + window.open(to.meta.href, '_blank'); + + next({ path: from.fullPath, replace: true, query: from.query, hash: to.hash }); + + return; + } + + next(); +} + +function getRouteQueryOfLoginRoute(to: RouteLocationNormalized, routeHome: RouteKey) { + const loginRoute: RouteKey = 'login'; + const redirect = to.fullPath; + const [redirectPath, redirectQuery] = redirect.split('?'); + const redirectName = getRouteName(redirectPath as RoutePath); + + const isRedirectHome = routeHome === redirectName; + + const query: LocationQueryRaw = to.name !== loginRoute && !isRedirectHome ? { redirect } : {}; + + if (isRedirectHome && redirectQuery) { + query.redirect = `/?${redirectQuery}`; + } + + return query; +} diff --git a/src/router/guard/title.ts b/src/router/guard/title.ts new file mode 100644 index 0000000..5b60368 --- /dev/null +++ b/src/router/guard/title.ts @@ -0,0 +1,13 @@ +import { useTitle } from '@vueuse/core'; +import type { Router } from 'vue-router'; +import { $t } from '@/locales'; + +export function createDocumentTitleGuard(router: Router) { + router.afterEach(to => { + const { i18nKey, title } = to.meta; + + const documentTitle = i18nKey ? $t(i18nKey) : title; + + useTitle(documentTitle); + }); +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..ec1b925 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,30 @@ +import type { App } from 'vue'; +import { + type RouterHistory, + createMemoryHistory, + createRouter, + createWebHashHistory, + createWebHistory +} from 'vue-router'; +import { createBuiltinVueRoutes } from './routes/builtin'; +import { createRouterGuard } from './guard'; + +const { VITE_ROUTER_HISTORY_MODE = 'history', VITE_BASE_URL } = import.meta.env; + +const historyCreatorMap: Record RouterHistory> = { + hash: createWebHashHistory, + history: createWebHistory, + memory: createMemoryHistory +}; + +export const router = createRouter({ + history: historyCreatorMap[VITE_ROUTER_HISTORY_MODE](VITE_BASE_URL), + routes: createBuiltinVueRoutes() +}); + +/** Setup Vue Router */ +export async function setupRouter(app: App) { + app.use(router); + createRouterGuard(router); + await router.isReady(); +} diff --git a/src/router/routes/builtin.ts b/src/router/routes/builtin.ts new file mode 100644 index 0000000..0a13e78 --- /dev/null +++ b/src/router/routes/builtin.ts @@ -0,0 +1,31 @@ +import type { CustomRoute } from '@elegant-router/types'; +import { layouts, views } from '../elegant/imports'; +import { getRoutePath, transformElegantRoutesToVueRoutes } from '../elegant/transform'; + +export const ROOT_ROUTE: CustomRoute = { + name: 'root', + path: '/', + redirect: getRoutePath(import.meta.env.VITE_ROUTE_HOME) || '/home', + meta: { + title: 'root', + constant: true + } +}; + +const NOT_FOUND_ROUTE: CustomRoute = { + name: 'not-found', + path: '/:pathMatch(.*)*', + component: 'layout.blank$view.404', + meta: { + title: 'not-found', + constant: true + } +}; + +/** builtin routes, it must be constant and setup in vue-router */ +const builtinRoutes: CustomRoute[] = [ROOT_ROUTE, NOT_FOUND_ROUTE]; + +/** create builtin vue routes */ +export function createBuiltinVueRoutes() { + return transformElegantRoutesToVueRoutes(builtinRoutes, layouts, views); +} diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts new file mode 100644 index 0000000..96322a9 --- /dev/null +++ b/src/router/routes/index.ts @@ -0,0 +1,193 @@ +import type { CustomRoute, ElegantConstRoute, ElegantRoute } from '@elegant-router/types'; +import { generatedRoutes } from '../elegant/routes'; +import { layouts, views } from '../elegant/imports'; +import { transformElegantRoutesToVueRoutes } from '../elegant/transform'; + +/** + * custom routes + * + * @link https://github.com/soybeanjs/elegant-router?tab=readme-ov-file#custom-route + */ +const customRoutes: CustomRoute[] = [ + { + name: 'exception', + path: '/exception', + component: 'layout.base', + meta: { + title: 'exception', + i18nKey: 'route.exception', + icon: 'ant-design:exception-outlined', + order: 7 + }, + children: [ + { + name: 'exception_403', + path: '/exception/403', + component: 'view.403', + meta: { + title: 'exception_403', + i18nKey: 'route.exception_403', + icon: 'ic:baseline-block' + } + }, + { + name: 'exception_404', + path: '/exception/404', + component: 'view.404', + meta: { + title: 'exception_404', + i18nKey: 'route.exception_404', + icon: 'ic:baseline-web-asset-off' + } + }, + { + name: 'exception_500', + path: '/exception/500', + component: 'view.500', + meta: { + title: 'exception_500', + i18nKey: 'route.exception_500', + icon: 'ic:baseline-wifi-off' + } + } + ] + }, + { + name: 'document', + path: '/document', + component: 'layout.base', + meta: { + title: 'document', + i18nKey: 'route.document', + order: 2, + icon: 'mdi:file-document-multiple-outline' + }, + children: [ + { + name: 'document_antd', + path: '/document/antd', + component: 'view.iframe-page', + props: { + url: 'https://antdv.com/components/overview-cn' + }, + meta: { + title: 'document_antd', + i18nKey: 'route.document_antd', + order: 7, + icon: 'logos:ant-design' + } + }, + { + name: 'document_naive', + path: '/document/naive', + component: 'view.iframe-page', + props: { + url: 'https://www.naiveui.com/zh-CN/os-theme/docs/introduction' + }, + meta: { + title: 'document_naive', + i18nKey: 'route.document_naive', + order: 6, + icon: 'logos:naiveui' + } + }, + { + name: 'document_project', + path: '/document/project', + component: 'view.iframe-page', + props: { + url: 'https://docs.soybeanjs.cn/zh' + }, + meta: { + title: 'document_project', + i18nKey: 'route.document_project', + order: 1, + localIcon: 'logo' + } + }, + { + name: 'document_project-link', + path: '/document/project-link', + component: 'view.iframe-page', + meta: { + title: 'document_project-link', + i18nKey: 'route.document_project-link', + order: 2, + localIcon: 'logo', + href: 'https://docs.soybeanjs.cn/zh' + } + }, + { + name: 'document_unocss', + path: '/document/unocss', + component: 'view.iframe-page', + props: { + url: 'https://unocss.dev/' + }, + meta: { + title: 'document_unocss', + i18nKey: 'route.document_unocss', + order: 5, + icon: 'logos:unocss' + } + }, + { + name: 'document_vite', + path: '/document/vite', + component: 'view.iframe-page', + props: { + url: 'https://cn.vitejs.dev/' + }, + meta: { + title: 'document_vite', + i18nKey: 'route.document_vite', + order: 4, + icon: 'logos:vitejs' + } + }, + { + name: 'document_vue', + path: '/document/vue', + component: 'view.iframe-page', + props: { + url: 'https://cn.vuejs.org/' + }, + meta: { + title: 'document_vue', + i18nKey: 'route.document_vue', + order: 3, + icon: 'logos:vue' + } + } + ] + } +]; + +/** create routes when the auth route mode is static */ +export function createStaticRoutes() { + const constantRoutes: ElegantRoute[] = []; + + const authRoutes: ElegantRoute[] = []; + + [...customRoutes, ...generatedRoutes].forEach(item => { + if (item.meta?.constant) { + constantRoutes.push(item); + } else { + authRoutes.push(item); + } + }); + + return { + constantRoutes, + authRoutes + }; +} + +/** + * Get auth vue routes + * + * @param routes Elegant routes + */ +export function getAuthVueRoutes(routes: ElegantConstRoute[]) { + return transformElegantRoutesToVueRoutes(routes, layouts, views); +} diff --git a/src/service/api/auth.ts b/src/service/api/auth.ts new file mode 100644 index 0000000..1ffcf2b --- /dev/null +++ b/src/service/api/auth.ts @@ -0,0 +1,48 @@ +import { request } from '../request'; + +/** + * Login + * + * @param userName User name + * @param password Password + */ +export function fetchLogin(userName: string, password: string) { + return request({ + url: '/auth/login', + method: 'post', + data: { + userName, + password + } + }); +} + +/** Get user info */ +export function fetchGetUserInfo() { + return request({ url: '/auth/getUserInfo' }); +} + +/** + * Refresh token + * + * @param refreshToken Refresh token + */ +export function fetchRefreshToken(refreshToken: string) { + return request({ + url: '/auth/refreshToken', + method: 'post', + data: { + refreshToken + } + }); +} + +/** + * return custom backend error + * + * @param code error code + * @param msg error message + */ +export function fetchCustomBackendError(code: string, msg: string) { + return request({ url: '/auth/error', params: { code, msg } }); +} diff --git a/src/service/api/index.ts b/src/service/api/index.ts new file mode 100644 index 0000000..c9d31d1 --- /dev/null +++ b/src/service/api/index.ts @@ -0,0 +1,3 @@ +export * from './auth'; +export * from './route'; +export * from './system-manage'; diff --git a/src/service/api/route.ts b/src/service/api/route.ts new file mode 100644 index 0000000..0956a7a --- /dev/null +++ b/src/service/api/route.ts @@ -0,0 +1,20 @@ +import { request } from '../request'; + +/** get constant routes */ +export function fetchGetConstantRoutes() { + return request({ url: '/route/getConstantRoutes' }); +} + +/** get user routes */ +export function fetchGetUserRoutes() { + return request({ url: '/route/getUserRoutes' }); +} + +/** + * whether the route is exist + * + * @param routeName route name + */ +export function fetchIsRouteExist(routeName: string) { + return request({ url: '/route/isRouteExist', params: { routeName } }); +} diff --git a/src/service/api/system-manage.ts b/src/service/api/system-manage.ts new file mode 100644 index 0000000..cb975b2 --- /dev/null +++ b/src/service/api/system-manage.ts @@ -0,0 +1,55 @@ +import { request } from '../request'; + +/** get role list */ +export function fetchGetRoleList(params?: Api.SystemManage.RoleSearchParams) { + return request({ + url: '/systemManage/getRoleList', + method: 'get', + params + }); +} + +/** + * get all roles + * + * these roles are all enabled + */ +export function fetchGetAllRoles() { + return request({ + url: '/systemManage/getAllRoles', + method: 'get' + }); +} + +/** get user list */ +export function fetchGetUserList(params?: Api.SystemManage.UserSearchParams) { + return request({ + url: '/systemManage/getUserList', + method: 'get', + params + }); +} + +/** get menu list */ +export function fetchGetMenuList() { + return request({ + url: '/systemManage/getMenuList/v2', + method: 'get' + }); +} + +/** get all pages */ +export function fetchGetAllPages() { + return request({ + url: '/systemManage/getAllPages', + method: 'get' + }); +} + +/** get menu tree */ +export function fetchGetMenuTree() { + return request({ + url: '/systemManage/getMenuTree', + method: 'get' + }); +} diff --git a/src/service/request/index.ts b/src/service/request/index.ts new file mode 100644 index 0000000..2ba34f7 --- /dev/null +++ b/src/service/request/index.ts @@ -0,0 +1,165 @@ +import type { AxiosResponse } from 'axios'; +import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios'; +import { useAuthStore } from '@/store/modules/auth'; +import { localStg } from '@/utils/storage'; +import { getServiceBaseURL } from '@/utils/service'; +import { $t } from '@/locales'; +import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared'; +import type { RequestInstanceState } from './type'; + +const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y'; +const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy); + +export const request = createFlatRequest( + { + baseURL, + headers: { + apifoxToken: 'XL299LiMEDZ0H5h3A29PxwQXdMJqWyY2' + } + }, + { + async onRequest(config) { + const Authorization = getAuthorization(); + Object.assign(config.headers, { Authorization }); + + return config; + }, + isBackendSuccess(response) { + // when the backend response code is "0000"(default), it means the request is success + // to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file + return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE; + }, + async onBackendFail(response, instance) { + const authStore = useAuthStore(); + const responseCode = String(response.data.code); + + function handleLogout() { + authStore.resetStore(); + } + + function logoutAndCleanup() { + handleLogout(); + window.removeEventListener('beforeunload', handleLogout); + + request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg); + } + + // when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page + const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || []; + if (logoutCodes.includes(responseCode)) { + handleLogout(); + return null; + } + + // when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal + const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || []; + if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(responseCode)) { + request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg]; + + // prevent the user from refreshing the page + window.addEventListener('beforeunload', handleLogout); + + window.$modal?.error({ + title: $t('common.error'), + content: response.data.msg, + okText: $t('common.confirm'), + maskClosable: false, + onOk() { + logoutAndCleanup(); + }, + onCancel() { + logoutAndCleanup(); + } + }); + + return null; + } + + // when the backend response code is in `expiredTokenCodes`, it means the token is expired, and refresh token + // the api `refreshToken` can not return error code in `expiredTokenCodes`, otherwise it will be a dead loop, should return `logoutCodes` or `modalLogoutCodes` + const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || []; + if (expiredTokenCodes.includes(responseCode)) { + const success = await handleExpiredRequest(request.state); + if (success) { + const Authorization = getAuthorization(); + Object.assign(response.config.headers, { Authorization }); + + return instance.request(response.config) as Promise; + } + } + + return null; + }, + transformBackendResponse(response) { + return response.data.data; + }, + onError(error) { + // when the request is fail, you can show error message + + let message = error.message; + let backendErrorCode = ''; + + // get backend error message and code + if (error.code === BACKEND_ERROR_CODE) { + message = error.response?.data?.msg || message; + backendErrorCode = String(error.response?.data?.code) || ''; + } + + // the error message is displayed in the modal + const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || []; + if (modalLogoutCodes.includes(backendErrorCode)) { + return; + } + + // when the token is expired, refresh token and retry request, so no need to show error message + const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || []; + if (expiredTokenCodes.includes(backendErrorCode)) { + return; + } + + showErrorMsg(request.state, message); + } + } +); + +export const demoRequest = createRequest( + { + baseURL: otherBaseURL.demo + }, + { + async onRequest(config) { + const { headers } = config; + + // set token + const token = localStg.get('token'); + const Authorization = token ? `Bearer ${token}` : null; + Object.assign(headers, { Authorization }); + + return config; + }, + isBackendSuccess(response) { + // when the backend response code is "200", it means the request is success + // you can change this logic by yourself + return response.data.status === '200'; + }, + async onBackendFail(_response) { + // when the backend response code is not "200", it means the request is fail + // for example: the token is expired, refresh token and retry request + }, + transformBackendResponse(response) { + return response.data.result; + }, + onError(error) { + // when the request is fail, you can show error message + + let message = error.message; + + // show backend error message + if (error.code === BACKEND_ERROR_CODE) { + message = error.response?.data?.message || message; + } + + window.$message?.error(message); + } + } +); diff --git a/src/service/request/shared.ts b/src/service/request/shared.ts new file mode 100644 index 0000000..409625c --- /dev/null +++ b/src/service/request/shared.ts @@ -0,0 +1,62 @@ +import { useAuthStore } from '@/store/modules/auth'; +import { localStg } from '@/utils/storage'; +import { fetchRefreshToken } from '../api'; +import type { RequestInstanceState } from './type'; + +export function getAuthorization() { + const token = localStg.get('token'); + const Authorization = token ? `Bearer ${token}` : null; + + return Authorization; +} + +/** refresh token */ +async function handleRefreshToken() { + const { resetStore } = useAuthStore(); + + const rToken = localStg.get('refreshToken') || ''; + const { error, data } = await fetchRefreshToken(rToken); + if (!error) { + localStg.set('token', data.token); + localStg.set('refreshToken', data.refreshToken); + return true; + } + + resetStore(); + + return false; +} + +export async function handleExpiredRequest(state: RequestInstanceState) { + if (!state.refreshTokenFn) { + state.refreshTokenFn = handleRefreshToken(); + } + + const success = await state.refreshTokenFn; + + setTimeout(() => { + state.refreshTokenFn = null; + }, 1000); + + return success; +} + +export function showErrorMsg(state: RequestInstanceState, message: string) { + if (!state.errMsgStack?.length) { + state.errMsgStack = []; + } + + const isExist = state.errMsgStack.includes(message); + + if (!isExist) { + state.errMsgStack.push(message); + + window.$message?.error(message, 1.5, () => { + state.errMsgStack = state.errMsgStack.filter(msg => msg !== message); + + setTimeout(() => { + state.errMsgStack = []; + }, 5000); + }); + } +} diff --git a/src/service/request/type.ts b/src/service/request/type.ts new file mode 100644 index 0000000..4e4a2f7 --- /dev/null +++ b/src/service/request/type.ts @@ -0,0 +1,6 @@ +export interface RequestInstanceState { + /** whether the request is refreshing token */ + refreshTokenFn: Promise | null; + /** the request error message stack */ + errMsgStack: string[]; +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..df57302 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,12 @@ +import type { App } from 'vue'; +import { createPinia } from 'pinia'; +import { resetSetupStore } from './plugins'; + +/** Setup Vue store plugin pinia */ +export function setupStore(app: App) { + const store = createPinia(); + + store.use(resetSetupStore); + + app.use(store); +} diff --git a/src/store/modules/app/index.ts b/src/store/modules/app/index.ts new file mode 100644 index 0000000..d3c3af6 --- /dev/null +++ b/src/store/modules/app/index.ts @@ -0,0 +1,169 @@ +import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue'; +import { defineStore } from 'pinia'; +import { breakpointsTailwind, useBreakpoints, useEventListener, useTitle } from '@vueuse/core'; +import { useBoolean } from '@sa/hooks'; +import { SetupStoreId } from '@/enum'; +import { router } from '@/router'; +import { $t, setLocale } from '@/locales'; +import { setDayjsLocale } from '@/locales/dayjs'; +import { localStg } from '@/utils/storage'; +import { useRouteStore } from '../route'; +import { useTabStore } from '../tab'; +import { useThemeStore } from '../theme'; + +export const useAppStore = defineStore(SetupStoreId.App, () => { + const themeStore = useThemeStore(); + const routeStore = useRouteStore(); + const tabStore = useTabStore(); + const scope = effectScope(); + const breakpoints = useBreakpoints(breakpointsTailwind); + const { bool: themeDrawerVisible, setTrue: openThemeDrawer, setFalse: closeThemeDrawer } = useBoolean(); + const { bool: reloadFlag, setBool: setReloadFlag } = useBoolean(true); + const { bool: fullContent, toggle: toggleFullContent } = useBoolean(); + const { bool: contentXScrollable, setBool: setContentXScrollable } = useBoolean(); + const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean(); + const { + bool: mixSiderFixed, + setBool: setMixSiderFixed, + toggle: toggleMixSiderFixed + } = useBoolean(localStg.get('mixSiderFixed') === 'Y'); + + /** Is mobile layout */ + const isMobile = breakpoints.smaller('sm'); + + /** + * Reload page + * + * @param duration Duration time + */ + async function reloadPage(duration = 300) { + setReloadFlag(false); + + const d = themeStore.page.animate ? duration : 40; + + await new Promise(resolve => { + setTimeout(resolve, d); + }); + + setReloadFlag(true); + + if (themeStore.resetCacheStrategy === 'refresh') { + routeStore.resetRouteCache(); + } + } + + const locale = ref(localStg.get('lang') || 'zh-CN'); + + const localeOptions: App.I18n.LangOption[] = [ + { + label: '中文', + key: 'zh-CN' + }, + { + label: 'English', + key: 'en-US' + } + ]; + + function changeLocale(lang: App.I18n.LangType) { + locale.value = lang; + setLocale(lang); + localStg.set('lang', lang); + } + + /** Update document title by locale */ + function updateDocumentTitleByLocale() { + const { i18nKey, title } = router.currentRoute.value.meta; + + const documentTitle = i18nKey ? $t(i18nKey) : title; + + useTitle(documentTitle); + } + + function init() { + setDayjsLocale(locale.value); + } + + // watch store + scope.run(() => { + // watch isMobile, if is mobile, collapse sider + watch( + isMobile, + newValue => { + if (newValue) { + // backup theme setting before is mobile + localStg.set('backupThemeSettingBeforeIsMobile', { + layout: themeStore.layout.mode, + siderCollapse: siderCollapse.value + }); + + themeStore.setThemeLayout('vertical'); + setSiderCollapse(true); + } else { + // when is not mobile, recover the backup theme setting + const backup = localStg.get('backupThemeSettingBeforeIsMobile'); + + if (backup) { + nextTick(() => { + themeStore.setThemeLayout(backup.layout); + setSiderCollapse(backup.siderCollapse); + + localStg.remove('backupThemeSettingBeforeIsMobile'); + }); + } + } + }, + { immediate: true } + ); + + // watch locale + watch(locale, () => { + // update document title by locale + updateDocumentTitleByLocale(); + + // update global menus by locale + routeStore.updateGlobalMenusByLocale(); + + // update tabs by locale + tabStore.updateTabsByLocale(); + + // set dayjs locale + setDayjsLocale(locale.value); + }); + }); + + // cache mixSiderFixed + useEventListener(window, 'beforeunload', () => { + localStg.set('mixSiderFixed', mixSiderFixed.value ? 'Y' : 'N'); + }); + + /** On scope dispose */ + onScopeDispose(() => { + scope.stop(); + }); + + // init + init(); + + return { + isMobile, + reloadFlag, + reloadPage, + fullContent, + locale, + localeOptions, + changeLocale, + themeDrawerVisible, + openThemeDrawer, + closeThemeDrawer, + toggleFullContent, + contentXScrollable, + setContentXScrollable, + siderCollapse, + setSiderCollapse, + toggleSiderCollapse, + mixSiderFixed, + setMixSiderFixed, + toggleMixSiderFixed + }; +}); diff --git a/src/store/modules/auth/index.ts b/src/store/modules/auth/index.ts new file mode 100644 index 0000000..0aed10b --- /dev/null +++ b/src/store/modules/auth/index.ts @@ -0,0 +1,138 @@ +import { computed, reactive, ref } from 'vue'; +import { useRoute } from 'vue-router'; +import { defineStore } from 'pinia'; +import { useLoading } from '@sa/hooks'; +import { SetupStoreId } from '@/enum'; +import { useRouterPush } from '@/hooks/common/router'; +import { fetchGetUserInfo, fetchLogin } from '@/service/api'; +import { localStg } from '@/utils/storage'; +import { $t } from '@/locales'; +import { useRouteStore } from '../route'; +import { useTabStore } from '../tab'; +import { clearAuthStorage, getToken } from './shared'; + +export const useAuthStore = defineStore(SetupStoreId.Auth, () => { + const route = useRoute(); + const routeStore = useRouteStore(); + const tabStore = useTabStore(); + const { toLogin, redirectFromLogin } = useRouterPush(false); + const { loading: loginLoading, startLoading, endLoading } = useLoading(); + + const token = ref(getToken()); + + const userInfo: Api.Auth.UserInfo = reactive({ + userId: '', + userName: '', + roles: [], + buttons: [] + }); + + /** is super role in static route */ + const isStaticSuper = computed(() => { + const { VITE_AUTH_ROUTE_MODE, VITE_STATIC_SUPER_ROLE } = import.meta.env; + + return VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.includes(VITE_STATIC_SUPER_ROLE); + }); + + /** Is login */ + const isLogin = computed(() => Boolean(token.value)); + + /** Reset auth store */ + async function resetStore() { + const authStore = useAuthStore(); + + clearAuthStorage(); + + authStore.$reset(); + + if (!route.meta.constant) { + await toLogin(); + } + + tabStore.cacheTabs(); + routeStore.resetStore(); + } + + /** + * Login + * + * @param userName User name + * @param password Password + * @param [redirect=true] Whether to redirect after login. Default is `true` + */ + async function login(userName: string, password: string, redirect = true) { + startLoading(); + + const { data: loginToken, error } = await fetchLogin(userName, password); + + if (!error) { + const pass = await loginByToken(loginToken); + + if (pass) { + await redirectFromLogin(redirect); + + window.$notification?.success({ + message: $t('page.login.common.loginSuccess'), + description: $t('page.login.common.welcomeBack', { userName: userInfo.userName }) + }); + } + } else { + resetStore(); + } + + endLoading(); + } + + async function loginByToken(loginToken: Api.Auth.LoginToken) { + // 1. stored in the localStorage, the later requests need it in headers + localStg.set('token', loginToken.token); + localStg.set('refreshToken', loginToken.refreshToken); + + // 2. get user info + const pass = await getUserInfo(); + + if (pass) { + token.value = loginToken.token; + + return true; + } + + return false; + } + + async function getUserInfo() { + const { data: info, error } = await fetchGetUserInfo(); + + if (!error) { + // update store + Object.assign(userInfo, info); + + return true; + } + + return false; + } + + async function initUserInfo() { + const hasToken = getToken(); + + if (hasToken) { + const pass = await getUserInfo(); + + if (!pass) { + resetStore(); + } + } + } + + return { + token, + userInfo, + isStaticSuper, + isLogin, + loginLoading, + resetStore, + login, + initUserInfo + }; +}); diff --git a/src/store/modules/auth/shared.ts b/src/store/modules/auth/shared.ts new file mode 100644 index 0000000..5cf8852 --- /dev/null +++ b/src/store/modules/auth/shared.ts @@ -0,0 +1,12 @@ +import { localStg } from '@/utils/storage'; + +/** Get token */ +export function getToken() { + return localStg.get('token') || ''; +} + +/** Clear auth storage */ +export function clearAuthStorage() { + localStg.remove('token'); + localStg.remove('refreshToken'); +} diff --git a/src/store/modules/route/index.ts b/src/store/modules/route/index.ts new file mode 100644 index 0000000..beb7443 --- /dev/null +++ b/src/store/modules/route/index.ts @@ -0,0 +1,348 @@ +import { computed, nextTick, ref, shallowRef } from 'vue'; +import type { RouteRecordRaw } from 'vue-router'; +import { defineStore } from 'pinia'; +import { useBoolean } from '@sa/hooks'; +import type { CustomRoute, ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types'; +import { SetupStoreId } from '@/enum'; +import { router } from '@/router'; +import { createStaticRoutes, getAuthVueRoutes } from '@/router/routes'; +import { ROOT_ROUTE } from '@/router/routes/builtin'; +import { getRouteName, getRoutePath } from '@/router/elegant/transform'; +import { fetchGetConstantRoutes, fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api'; +import { useAuthStore } from '../auth'; +import { useTabStore } from '../tab'; +import { + filterAuthRoutesByRoles, + getBreadcrumbsByRoute, + getCacheRouteNames, + getGlobalMenusByAuthRoutes, + getSelectedMenuKeyPathByKey, + isRouteExistByRouteName, + sortRoutesByOrder, + transformMenuToSearchMenus, + updateLocaleOfGlobalMenus +} from './shared'; + +export const useRouteStore = defineStore(SetupStoreId.Route, () => { + const authStore = useAuthStore(); + const tabStore = useTabStore(); + const { bool: isInitConstantRoute, setBool: setIsInitConstantRoute } = useBoolean(); + const { bool: isInitAuthRoute, setBool: setIsInitAuthRoute } = useBoolean(); + + /** + * Auth route mode + * + * It recommends to use static mode in the development environment, and use dynamic mode in the production + * environment, if use static mode in development environment, the auth routes will be auto generated by plugin + * "@elegant-router/vue" + */ + const authRouteMode = ref(import.meta.env.VITE_AUTH_ROUTE_MODE); + + /** Home route key */ + const routeHome = ref(import.meta.env.VITE_ROUTE_HOME); + + /** + * Set route home + * + * @param routeKey Route key + */ + function setRouteHome(routeKey: LastLevelRouteKey) { + routeHome.value = routeKey; + } + + /** constant routes */ + const constantRoutes = shallowRef([]); + + function addConstantRoutes(routes: ElegantConstRoute[]) { + const constantRoutesMap = new Map([]); + + routes.forEach(route => { + constantRoutesMap.set(route.name, route); + }); + + constantRoutes.value = Array.from(constantRoutesMap.values()); + } + + /** auth routes */ + const authRoutes = shallowRef([]); + + function addAuthRoutes(routes: ElegantConstRoute[]) { + const authRoutesMap = new Map([]); + + routes.forEach(route => { + authRoutesMap.set(route.name, route); + }); + + authRoutes.value = Array.from(authRoutesMap.values()); + } + + const removeRouteFns: (() => void)[] = []; + + /** Global menus */ + const menus = ref([]); + const searchMenus = computed(() => transformMenuToSearchMenus(menus.value)); + + /** Get global menus */ + function getGlobalMenus(routes: ElegantConstRoute[]) { + menus.value = getGlobalMenusByAuthRoutes(routes); + } + + /** Update global menus by locale */ + function updateGlobalMenusByLocale() { + menus.value = updateLocaleOfGlobalMenus(menus.value); + } + + /** Cache routes */ + const cacheRoutes = ref([]); + + /** + * Exclude cache routes + * + * for reset route cache + */ + const excludeCacheRoutes = ref([]); + + /** + * Get cache routes + * + * @param routes Vue routes + */ + function getCacheRoutes(routes: RouteRecordRaw[]) { + cacheRoutes.value = getCacheRouteNames(routes); + } + + /** + * Reset route cache + * + * @default router.currentRoute.value.name current route name + * @param routeKey + */ + async function resetRouteCache(routeKey?: RouteKey) { + const routeName = routeKey || (router.currentRoute.value.name as RouteKey); + + excludeCacheRoutes.value.push(routeName); + + await nextTick(); + + excludeCacheRoutes.value = []; + } + + /** Global breadcrumbs */ + const breadcrumbs = computed(() => getBreadcrumbsByRoute(router.currentRoute.value, menus.value)); + + /** Reset store */ + async function resetStore() { + const routeStore = useRouteStore(); + + routeStore.$reset(); + + resetVueRoutes(); + + // after reset store, need to re-init constant route + await initConstantRoute(); + } + + /** Reset vue routes */ + function resetVueRoutes() { + removeRouteFns.forEach(fn => fn()); + removeRouteFns.length = 0; + } + + /** init constant route */ + async function initConstantRoute() { + if (isInitConstantRoute.value) return; + + const staticRoute = createStaticRoutes(); + + if (authRouteMode.value === 'static') { + addConstantRoutes(staticRoute.constantRoutes); + } else { + const { data, error } = await fetchGetConstantRoutes(); + + if (!error) { + addConstantRoutes(data); + } else { + // if fetch constant routes failed, use static constant routes + addConstantRoutes(staticRoute.constantRoutes); + } + } + + handleConstantAndAuthRoutes(); + + setIsInitConstantRoute(true); + + tabStore.initHomeTab(); + } + + /** Init auth route */ + async function initAuthRoute() { + // check if user info is initialized + if (!authStore.userInfo.userId) { + await authStore.initUserInfo(); + } + + if (authRouteMode.value === 'static') { + initStaticAuthRoute(); + } else { + await initDynamicAuthRoute(); + } + + tabStore.initHomeTab(); + } + + /** Init static auth route */ + function initStaticAuthRoute() { + const { authRoutes: staticAuthRoutes } = createStaticRoutes(); + + if (authStore.isStaticSuper) { + addAuthRoutes(staticAuthRoutes); + } else { + const filteredAuthRoutes = filterAuthRoutesByRoles(staticAuthRoutes, authStore.userInfo.roles); + + addAuthRoutes(filteredAuthRoutes); + } + + handleConstantAndAuthRoutes(); + + setIsInitAuthRoute(true); + } + + /** Init dynamic auth route */ + async function initDynamicAuthRoute() { + const { data, error } = await fetchGetUserRoutes(); + + if (!error) { + const { routes, home } = data; + + addAuthRoutes(routes); + + handleConstantAndAuthRoutes(); + + setRouteHome(home); + + handleUpdateRootRouteRedirect(home); + + setIsInitAuthRoute(true); + } else { + // if fetch user routes failed, reset store + authStore.resetStore(); + } + } + + /** handle constant and auth routes */ + function handleConstantAndAuthRoutes() { + const allRoutes = [...constantRoutes.value, ...authRoutes.value]; + + const sortRoutes = sortRoutesByOrder(allRoutes); + + const vueRoutes = getAuthVueRoutes(sortRoutes); + + resetVueRoutes(); + + addRoutesToVueRouter(vueRoutes); + + getGlobalMenus(sortRoutes); + + getCacheRoutes(vueRoutes); + } + + /** + * Add routes to vue router + * + * @param routes Vue routes + */ + function addRoutesToVueRouter(routes: RouteRecordRaw[]) { + routes.forEach(route => { + const removeFn = router.addRoute(route); + addRemoveRouteFn(removeFn); + }); + } + + /** + * Add remove route fn + * + * @param fn + */ + function addRemoveRouteFn(fn: () => void) { + removeRouteFns.push(fn); + } + + /** + * Update root route redirect when auth route mode is dynamic + * + * @param redirectKey Redirect route key + */ + function handleUpdateRootRouteRedirect(redirectKey: LastLevelRouteKey) { + const redirect = getRoutePath(redirectKey); + + if (redirect) { + const rootRoute: CustomRoute = { ...ROOT_ROUTE, redirect }; + + router.removeRoute(rootRoute.name); + + const [rootVueRoute] = getAuthVueRoutes([rootRoute]); + + router.addRoute(rootVueRoute); + } + } + + /** + * Get is auth route exist + * + * @param routePath Route path + */ + async function getIsAuthRouteExist(routePath: RouteMap[RouteKey]) { + const routeName = getRouteName(routePath); + + if (!routeName) { + return false; + } + + if (authRouteMode.value === 'static') { + const { authRoutes: staticAuthRoutes } = createStaticRoutes(); + return isRouteExistByRouteName(routeName, staticAuthRoutes); + } + + const { data } = await fetchIsRouteExist(routeName); + + return data; + } + + /** + * Get selected menu key path + * + * @param selectedKey Selected menu key + */ + function getSelectedMenuKeyPath(selectedKey: string) { + return getSelectedMenuKeyPathByKey(selectedKey, menus.value); + } + + async function onRouteSwitchWhenLoggedIn() { + await authStore.initUserInfo(); + } + + async function onRouteSwitchWhenNotLoggedIn() { + // some global init logic if it does not need to be logged in + } + + return { + resetStore, + routeHome, + menus, + searchMenus, + updateGlobalMenusByLocale, + cacheRoutes, + excludeCacheRoutes, + resetRouteCache, + breadcrumbs, + initConstantRoute, + isInitConstantRoute, + initAuthRoute, + isInitAuthRoute, + setIsInitAuthRoute, + getIsAuthRouteExist, + getSelectedMenuKeyPath, + onRouteSwitchWhenLoggedIn, + onRouteSwitchWhenNotLoggedIn + }; +}); diff --git a/src/store/modules/route/shared.ts b/src/store/modules/route/shared.ts new file mode 100644 index 0000000..81e7719 --- /dev/null +++ b/src/store/modules/route/shared.ts @@ -0,0 +1,321 @@ +import type { RouteLocationNormalizedLoaded, RouteRecordRaw, _RouteRecordBase } from 'vue-router'; +import type { ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types'; +import { $t } from '@/locales'; +import { useSvgIcon } from '@/hooks/common/icon'; + +/** + * Filter auth routes by roles + * + * @param routes Auth routes + * @param roles Roles + */ +export function filterAuthRoutesByRoles(routes: ElegantConstRoute[], roles: string[]) { + return routes.flatMap(route => filterAuthRouteByRoles(route, roles)); +} + +/** + * Filter auth route by roles + * + * @param route Auth route + * @param roles Roles + */ +function filterAuthRouteByRoles(route: ElegantConstRoute, roles: string[]): ElegantConstRoute[] { + const routeRoles = (route.meta && route.meta.roles) || []; + + // if the route's "roles" is empty, then it is allowed to access + const isEmptyRoles = !routeRoles.length; + + // if the user's role is included in the route's "roles", then it is allowed to access + const hasPermission = routeRoles.some(role => roles.includes(role)); + + const filterRoute = { ...route }; + + if (filterRoute.children?.length) { + filterRoute.children = filterRoute.children.flatMap(item => filterAuthRouteByRoles(item, roles)); + } + + // Exclude the route if it has no children after filtering + if (filterRoute.children?.length === 0) { + return []; + } + + return hasPermission || isEmptyRoles ? [filterRoute] : []; +} + +/** + * sort route by order + * + * @param route route + */ +function sortRouteByOrder(route: ElegantConstRoute) { + if (route.children?.length) { + route.children.sort((next, prev) => (Number(next.meta?.order) || 0) - (Number(prev.meta?.order) || 0)); + route.children.forEach(sortRouteByOrder); + } + + return route; +} + +/** + * sort routes by order + * + * @param routes routes + */ +export function sortRoutesByOrder(routes: ElegantConstRoute[]) { + routes.sort((next, prev) => (Number(next.meta?.order) || 0) - (Number(prev.meta?.order) || 0)); + routes.forEach(sortRouteByOrder); + + return routes; +} + +/** + * Get global menus by auth routes + * + * @param routes Auth routes + */ +export function getGlobalMenusByAuthRoutes(routes: ElegantConstRoute[]) { + const menus: App.Global.Menu[] = []; + + routes.forEach(route => { + if (!route.meta?.hideInMenu) { + const menu = getGlobalMenuByBaseRoute(route); + + if (route.children?.some(child => !child.meta?.hideInMenu)) { + menu.children = getGlobalMenusByAuthRoutes(route.children); + } + + menus.push(menu); + } + }); + + return menus; +} + +/** + * Update locale of global menus + * + * @param menus + */ +export function updateLocaleOfGlobalMenus(menus: App.Global.Menu[]) { + const result: App.Global.Menu[] = []; + + menus.forEach(menu => { + const { i18nKey, label, children } = menu; + + const newLabel = i18nKey ? $t(i18nKey) : label; + + const newMenu: App.Global.Menu = { + ...menu, + label: newLabel, + title: newLabel + }; + + if (children?.length) { + newMenu.children = updateLocaleOfGlobalMenus(children); + } + + result.push(newMenu); + }); + + return result; +} + +/** + * Get global menu by route + * + * @param route + */ +function getGlobalMenuByBaseRoute(route: RouteLocationNormalizedLoaded | ElegantConstRoute) { + const { SvgIconVNode } = useSvgIcon(); + + const { name, path } = route; + const { title, i18nKey, icon = import.meta.env.VITE_MENU_ICON, localIcon, iconFontSize } = route.meta ?? {}; + + const label = i18nKey ? $t(i18nKey) : title!; + + const menu: App.Global.Menu = { + key: name as string, + label, + i18nKey, + routeKey: name as RouteKey, + routePath: path as RouteMap[RouteKey], + icon: SvgIconVNode({ icon, localIcon, fontSize: iconFontSize || 20 }), + title: label + }; + + return menu; +} + +/** + * Get cache route names + * + * @param routes Vue routes (two levels) + */ +export function getCacheRouteNames(routes: RouteRecordRaw[]) { + const cacheNames: LastLevelRouteKey[] = []; + + routes.forEach(route => { + // only get last two level route, which has component + route.children?.forEach(child => { + if (child.component && child.meta?.keepAlive) { + cacheNames.push(child.name as LastLevelRouteKey); + } + }); + }); + + return cacheNames; +} + +/** + * Is route exist by route name + * + * @param routeName + * @param routes + */ +export function isRouteExistByRouteName(routeName: RouteKey, routes: ElegantConstRoute[]) { + return routes.some(route => recursiveGetIsRouteExistByRouteName(route, routeName)); +} + +/** + * Recursive get is route exist by route name + * + * @param route + * @param routeName + */ +function recursiveGetIsRouteExistByRouteName(route: ElegantConstRoute, routeName: RouteKey) { + let isExist = route.name === routeName; + + if (isExist) { + return true; + } + + if (route.children && route.children.length) { + isExist = route.children.some(item => recursiveGetIsRouteExistByRouteName(item, routeName)); + } + + return isExist; +} + +/** + * Get selected menu key path + * + * @param selectedKey + * @param menus + */ +export function getSelectedMenuKeyPathByKey(selectedKey: string, menus: App.Global.Menu[]) { + const keyPath: string[] = []; + + menus.some(menu => { + const path = findMenuPath(selectedKey, menu); + + const find = Boolean(path?.length); + + if (find) { + keyPath.push(...path!); + } + + return find; + }); + + return keyPath; +} + +/** + * Find menu path + * + * @param targetKey Target menu key + * @param menu Menu + */ +function findMenuPath(targetKey: string, menu: App.Global.Menu): string[] | null { + const path: string[] = []; + + function dfs(item: App.Global.Menu): boolean { + path.push(item.key); + + if (item.key === targetKey) { + return true; + } + + if (item.children) { + for (const child of item.children) { + if (dfs(child)) { + return true; + } + } + } + + path.pop(); + + return false; + } + + if (dfs(menu)) { + return path; + } + + return null; +} + +/** + * Get breadcrumbs by route + * + * @param route + * @param menus + */ +export function getBreadcrumbsByRoute( + route: RouteLocationNormalizedLoaded, + menus: App.Global.Menu[] +): App.Global.Menu[] { + const key = route.name as string; + const activeKey = route.meta?.activeMenu; + + const menuKey = activeKey || key; + + for (const menu of menus) { + if (menu.key === menuKey) { + return [menu]; + } + + if (menu.key === activeKey) { + const ROUTE_DEGREE_SPLITTER = '_'; + + const parentKey = key.split(ROUTE_DEGREE_SPLITTER).slice(0, -1).join(ROUTE_DEGREE_SPLITTER); + + const breadcrumbMenu = getGlobalMenuByBaseRoute(route); + + if (parentKey !== activeKey) { + return [breadcrumbMenu]; + } + + return [menu, breadcrumbMenu]; + } + + if (menu.children?.length) { + const result = getBreadcrumbsByRoute(route, menu.children); + if (result.length > 0) { + return [menu, ...result]; + } + } + } + + return []; +} + +/** + * Transform menu to searchMenus + * + * @param menus - menus + * @param treeMap + */ +export function transformMenuToSearchMenus(menus: App.Global.Menu[], treeMap: App.Global.Menu[] = []) { + if (menus && menus.length === 0) return []; + return menus.reduce((acc, cur) => { + if (!cur.children) { + acc.push(cur); + } + if (cur.children && cur.children.length > 0) { + transformMenuToSearchMenus(cur.children, treeMap); + } + return acc; + }, treeMap); +} diff --git a/src/store/modules/tab/index.ts b/src/store/modules/tab/index.ts new file mode 100644 index 0000000..85add10 --- /dev/null +++ b/src/store/modules/tab/index.ts @@ -0,0 +1,296 @@ +import { computed, ref } from 'vue'; +import { defineStore } from 'pinia'; +import { useEventListener } from '@vueuse/core'; +import type { RouteKey } from '@elegant-router/types'; +import { router } from '@/router'; +import { SetupStoreId } from '@/enum'; +import { useRouterPush } from '@/hooks/common/router'; +import { localStg } from '@/utils/storage'; +import { useRouteStore } from '@/store/modules/route'; +import { useThemeStore } from '../theme'; +import { + extractTabsByAllRoutes, + filterTabsById, + filterTabsByIds, + findTabByRouteName, + getAllTabs, + getDefaultHomeTab, + getFixedTabIds, + getTabByRoute, + getTabIdByRoute, + isTabInTabs, + updateTabByI18nKey, + updateTabsByI18nKey +} from './shared'; + +export const useTabStore = defineStore(SetupStoreId.Tab, () => { + const routeStore = useRouteStore(); + const themeStore = useThemeStore(); + const { routerPush } = useRouterPush(false); + + /** Tabs */ + const tabs = ref([]); + + /** Get active tab */ + const homeTab = ref(); + + /** Init home tab */ + function initHomeTab() { + homeTab.value = getDefaultHomeTab(router, routeStore.routeHome); + } + + /** Get all tabs */ + const allTabs = computed(() => getAllTabs(tabs.value, homeTab.value)); + + /** Active tab id */ + const activeTabId = ref(''); + + /** + * Set active tab id + * + * @param id Tab id + */ + function setActiveTabId(id: string) { + activeTabId.value = id; + } + + /** + * Init tab store + * + * @param currentRoute Current route + */ + function initTabStore(currentRoute: App.Global.TabRoute) { + const storageTabs = localStg.get('globalTabs'); + + if (themeStore.tab.cache && storageTabs) { + const extractedTabs = extractTabsByAllRoutes(router, storageTabs); + tabs.value = updateTabsByI18nKey(extractedTabs); + } + + addTab(currentRoute); + } + + /** + * Add tab + * + * @param route Tab route + * @param active Whether to activate the added tab + */ + function addTab(route: App.Global.TabRoute, active = true) { + const tab = getTabByRoute(route); + + const isHomeTab = tab.id === homeTab.value?.id; + + if (!isHomeTab && !isTabInTabs(tab.id, tabs.value)) { + tabs.value.push(tab); + } + + if (active) { + setActiveTabId(tab.id); + } + } + + /** + * Remove tab + * + * @param tabId Tab id + */ + async function removeTab(tabId: string) { + const isRemoveActiveTab = activeTabId.value === tabId; + const updatedTabs = filterTabsById(tabId, tabs.value); + + function update() { + tabs.value = updatedTabs; + } + + if (!isRemoveActiveTab) { + update(); + return; + } + + const activeTab = updatedTabs.at(-1) || homeTab.value; + + if (activeTab) { + await switchRouteByTab(activeTab); + update(); + } + } + + /** remove active tab */ + async function removeActiveTab() { + await removeTab(activeTabId.value); + } + + /** + * remove tab by route name + * + * @param routeName route name + */ + async function removeTabByRouteName(routeName: RouteKey) { + const tab = findTabByRouteName(routeName, tabs.value); + if (!tab) return; + + await removeTab(tab.id); + } + + /** + * Clear tabs + * + * @param excludes Exclude tab ids + */ + async function clearTabs(excludes: string[] = []) { + const remainTabIds = [...getFixedTabIds(tabs.value), ...excludes]; + const removedTabsIds = tabs.value.map(tab => tab.id).filter(id => !remainTabIds.includes(id)); + + const isRemoveActiveTab = removedTabsIds.includes(activeTabId.value); + const updatedTabs = filterTabsByIds(removedTabsIds, tabs.value); + + function update() { + tabs.value = updatedTabs; + } + + if (!isRemoveActiveTab) { + update(); + return; + } + + const activeTab = updatedTabs[updatedTabs.length - 1] || homeTab.value; + + await switchRouteByTab(activeTab); + update(); + } + + /** + * Switch route by tab + * + * @param tab + */ + async function switchRouteByTab(tab: App.Global.Tab) { + const fail = await routerPush(tab.fullPath); + if (!fail) { + setActiveTabId(tab.id); + } + } + + /** + * Clear left tabs + * + * @param tabId + */ + async function clearLeftTabs(tabId: string) { + const tabIds = tabs.value.map(tab => tab.id); + const index = tabIds.indexOf(tabId); + if (index === -1) return; + + const excludes = tabIds.slice(index); + await clearTabs(excludes); + } + + /** + * Clear right tabs + * + * @param tabId + */ + async function clearRightTabs(tabId: string) { + const isHomeTab = tabId === homeTab.value?.id; + if (isHomeTab) { + clearTabs(); + return; + } + + const tabIds = tabs.value.map(tab => tab.id); + const index = tabIds.indexOf(tabId); + if (index === -1) return; + + const excludes = tabIds.slice(0, index + 1); + await clearTabs(excludes); + } + + /** + * Set new label of tab + * + * @default activeTabId + * @param label New tab label + * @param tabId Tab id + */ + function setTabLabel(label: string, tabId?: string) { + const id = tabId || activeTabId.value; + + const tab = tabs.value.find(item => item.id === id); + if (!tab) return; + + tab.oldLabel = tab.label; + tab.newLabel = label; + } + + /** + * Reset tab label + * + * @default activeTabId + * @param tabId Tab id + */ + function resetTabLabel(tabId?: string) { + const id = tabId || activeTabId.value; + + const tab = tabs.value.find(item => item.id === id); + if (!tab) return; + + tab.newLabel = undefined; + } + + /** + * Is tab retain + * + * @param tabId + */ + function isTabRetain(tabId: string) { + if (tabId === homeTab.value?.id) return true; + + const fixedTabIds = getFixedTabIds(tabs.value); + + return fixedTabIds.includes(tabId); + } + + /** Update tabs by locale */ + function updateTabsByLocale() { + tabs.value = updateTabsByI18nKey(tabs.value); + + if (homeTab.value) { + homeTab.value = updateTabByI18nKey(homeTab.value); + } + } + + /** Cache tabs */ + function cacheTabs() { + if (!themeStore.tab.cache) return; + + localStg.set('globalTabs', tabs.value); + } + + // cache tabs when page is closed or refreshed + useEventListener(window, 'beforeunload', () => { + cacheTabs(); + }); + + return { + /** All tabs */ + tabs: allTabs, + activeTabId, + initHomeTab, + initTabStore, + addTab, + removeTab, + removeActiveTab, + removeTabByRouteName, + clearTabs, + clearLeftTabs, + clearRightTabs, + switchRouteByTab, + setTabLabel, + resetTabLabel, + isTabRetain, + updateTabsByLocale, + getTabIdByRoute, + cacheTabs + }; +}); diff --git a/src/store/modules/tab/shared.ts b/src/store/modules/tab/shared.ts new file mode 100644 index 0000000..935c520 --- /dev/null +++ b/src/store/modules/tab/shared.ts @@ -0,0 +1,250 @@ +import type { Router } from 'vue-router'; +import type { LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types'; +import { $t } from '@/locales'; +import { getRoutePath } from '@/router/elegant/transform'; + +/** + * Get all tabs + * + * @param tabs Tabs + * @param homeTab Home tab + */ +export function getAllTabs(tabs: App.Global.Tab[], homeTab?: App.Global.Tab) { + if (!homeTab) { + return []; + } + + const filterHomeTabs = tabs.filter(tab => tab.id !== homeTab.id); + + const fixedTabs = filterHomeTabs.filter(isFixedTab).sort((a, b) => a.fixedIndex! - b.fixedIndex!); + + const remainTabs = filterHomeTabs.filter(tab => !isFixedTab(tab)); + + const allTabs = [homeTab, ...fixedTabs, ...remainTabs]; + + return updateTabsLabel(allTabs); +} + +/** + * Is fixed tab + * + * @param tab + */ +function isFixedTab(tab: App.Global.Tab) { + return tab.fixedIndex !== undefined && tab.fixedIndex !== null; +} + +/** + * Get tab id by route + * + * @param route + */ +export function getTabIdByRoute(route: App.Global.TabRoute) { + const { path, query = {}, meta } = route; + + let id = path; + + if (meta.multiTab) { + const queryKeys = Object.keys(query).sort(); + const qs = queryKeys.map(key => `${key}=${query[key]}`).join('&'); + + id = `${path}?${qs}`; + } + + return id; +} + +/** + * Get tab by route + * + * @param route + */ +export function getTabByRoute(route: App.Global.TabRoute) { + const { name, path, fullPath = path, meta } = route; + const { title, i18nKey, fixedIndexInTab } = meta; + + // Get icon and localIcon from getRouteIcons function + const { icon, localIcon } = getRouteIcons(route); + + const label = i18nKey ? $t(i18nKey) : title; + + const tab: App.Global.Tab = { + id: getTabIdByRoute(route), + label, + routeKey: name as LastLevelRouteKey, + routePath: path as RouteMap[LastLevelRouteKey], + fullPath, + fixedIndex: fixedIndexInTab, + icon, + localIcon, + i18nKey + }; + + return tab; +} + +/** + * The vue router will automatically merge the meta of all matched items, and the icons here may be affected by other + * matching items, so they need to be processed separately + * + * @param route + */ +export function getRouteIcons(route: App.Global.TabRoute) { + // Set default value for icon at the beginning + let icon: string = route?.meta?.icon || import.meta.env.VITE_MENU_ICON; + let localIcon: string | undefined = route?.meta?.localIcon; + + // Route.matched only appears when there are multiple matches,so check if route.matched exists + if (route.matched) { + // Find the meta of the current route from matched + const currentRoute = route.matched.find(r => r.name === route.name); + // If icon exists in currentRoute.meta, it will overwrite the default value + icon = currentRoute?.meta?.icon || icon; + localIcon = currentRoute?.meta?.localIcon; + } + + return { icon, localIcon }; +} + +/** + * Get default home tab + * + * @param router + * @param homeRouteName routeHome in useRouteStore + */ +export function getDefaultHomeTab(router: Router, homeRouteName: LastLevelRouteKey) { + const homeRoutePath = getRoutePath(homeRouteName); + const i18nLabel = $t(`route.${homeRouteName}`); + + let homeTab: App.Global.Tab = { + id: getRoutePath(homeRouteName), + label: i18nLabel || homeRouteName, + routeKey: homeRouteName, + routePath: homeRoutePath, + fullPath: homeRoutePath + }; + + const routes = router.getRoutes(); + const homeRoute = routes.find(route => route.name === homeRouteName); + if (homeRoute) { + homeTab = getTabByRoute(homeRoute); + } + + return homeTab; +} + +/** + * Is tab in tabs + * + * @param tab + * @param tabs + */ +export function isTabInTabs(tabId: string, tabs: App.Global.Tab[]) { + return tabs.some(tab => tab.id === tabId); +} + +/** + * Filter tabs by id + * + * @param tabId + * @param tabs + */ +export function filterTabsById(tabId: string, tabs: App.Global.Tab[]) { + return tabs.filter(tab => tab.id !== tabId); +} + +/** + * Filter tabs by ids + * + * @param tabIds + * @param tabs + */ +export function filterTabsByIds(tabIds: string[], tabs: App.Global.Tab[]) { + return tabs.filter(tab => !tabIds.includes(tab.id)); +} + +/** + * extract tabs by all routes + * + * @param router + * @param tabs + */ +export function extractTabsByAllRoutes(router: Router, tabs: App.Global.Tab[]) { + const routes = router.getRoutes(); + + const routeNames = routes.map(route => route.name); + + return tabs.filter(tab => routeNames.includes(tab.routeKey)); +} + +/** + * Get fixed tabs + * + * @param tabs + */ +export function getFixedTabs(tabs: App.Global.Tab[]) { + return tabs.filter(tab => tab.fixedIndex !== undefined); +} + +/** + * Get fixed tab ids + * + * @param tabs + */ +export function getFixedTabIds(tabs: App.Global.Tab[]) { + const fixedTabs = getFixedTabs(tabs); + + return fixedTabs.map(tab => tab.id); +} + +/** + * Update tabs label + * + * @param tabs + */ +function updateTabsLabel(tabs: App.Global.Tab[]) { + const updated = tabs.map(tab => ({ + ...tab, + label: tab.newLabel || tab.oldLabel || tab.label + })); + + return updated; +} + +/** + * Update tab by i18n key + * + * @param tab + */ +export function updateTabByI18nKey(tab: App.Global.Tab) { + const { i18nKey, label } = tab; + + return { + ...tab, + label: i18nKey ? $t(i18nKey) : label + }; +} + +/** + * Update tabs by i18n key + * + * @param tabs + */ +export function updateTabsByI18nKey(tabs: App.Global.Tab[]) { + return tabs.map(tab => updateTabByI18nKey(tab)); +} + +/** + * find tab by route name + * + * @param name + * @param tabs + */ +export function findTabByRouteName(name: RouteKey, tabs: App.Global.Tab[]) { + const routePath = getRoutePath(name); + + const tabId = routePath; + const multiTabId = `${routePath}?`; + + return tabs.find(tab => tab.id === tabId || tab.id.startsWith(multiTabId)); +} diff --git a/src/store/modules/theme/index.ts b/src/store/modules/theme/index.ts new file mode 100644 index 0000000..4fc837c --- /dev/null +++ b/src/store/modules/theme/index.ts @@ -0,0 +1,221 @@ +import { computed, effectScope, onScopeDispose, ref, toRefs, watch } from 'vue'; +import type { Ref } from 'vue'; +import { defineStore } from 'pinia'; +import { useEventListener, usePreferredColorScheme } from '@vueuse/core'; +import { getPaletteColorByNumber } from '@sa/color'; +import { SetupStoreId } from '@/enum'; +import { localStg } from '@/utils/storage'; +import { + addThemeVarsToGlobal, + createThemeToken, + getAntdTheme, + initThemeSettings, + toggleAuxiliaryColorModes, + toggleCssDarkMode +} from './shared'; + +/** Theme store */ +export const useThemeStore = defineStore(SetupStoreId.Theme, () => { + const scope = effectScope(); + const osTheme = usePreferredColorScheme(); + + /** Theme settings */ + const settings: Ref = ref(initThemeSettings()); + + /** Reset store */ + function resetStore() { + const themeStore = useThemeStore(); + + themeStore.$reset(); + } + + /** Theme colors */ + const themeColors = computed(() => { + const { themeColor, otherColor, isInfoFollowPrimary } = settings.value; + const colors: App.Theme.ThemeColor = { + primary: themeColor, + ...otherColor, + info: isInfoFollowPrimary ? themeColor : otherColor.info + }; + return colors; + }); + + /** Dark mode */ + const darkMode = computed(() => { + if (settings.value.themeScheme === 'auto') { + return osTheme.value === 'dark'; + } + return settings.value.themeScheme === 'dark'; + }); + + /** grayscale mode */ + const grayscaleMode = computed(() => settings.value.grayscale); + + /** colourWeakness mode */ + const colourWeaknessMode = computed(() => settings.value.colourWeakness); + + /** Antd theme */ + const antdTheme = computed(() => getAntdTheme(themeColors.value, darkMode.value)); + + /** + * Settings json + * + * It is for copy settings + */ + const settingsJson = computed(() => JSON.stringify(settings.value)); + + /** + * Set theme scheme + * + * @param themeScheme + */ + function setThemeScheme(themeScheme: UnionKey.ThemeScheme) { + settings.value.themeScheme = themeScheme; + } + + /** + * Set grayscale value + * + * @param isGrayscale + */ + function setGrayscale(isGrayscale: boolean) { + settings.value.grayscale = isGrayscale; + } + + /** + * Set colourWeakness value + * + * @param isColourWeakness + */ + function setColourWeakness(isColourWeakness: boolean) { + settings.value.colourWeakness = isColourWeakness; + } + + /** Toggle theme scheme */ + function toggleThemeScheme() { + const themeSchemes: UnionKey.ThemeScheme[] = ['light', 'dark', 'auto']; + + const index = themeSchemes.findIndex(item => item === settings.value.themeScheme); + + const nextIndex = index === themeSchemes.length - 1 ? 0 : index + 1; + + const nextThemeScheme = themeSchemes[nextIndex]; + + setThemeScheme(nextThemeScheme); + } + + /** + * Set theme layout + * + * @param mode Theme layout mode + */ + function setThemeLayout(mode: UnionKey.ThemeLayoutMode) { + settings.value.layout.mode = mode; + } + + /** + * Update theme colors + * + * @param key Theme color key + * @param color Theme color + */ + function updateThemeColors(key: App.Theme.ThemeColorKey, color: string) { + let colorValue = color; + + if (settings.value.recommendColor) { + // get a color palette by provided color and color name, and use the suitable color + + colorValue = getPaletteColorByNumber(color, 500, true); + } + + if (key === 'primary') { + settings.value.themeColor = colorValue; + } else { + settings.value.otherColor[key] = colorValue; + } + } + + /** Setup theme vars to global */ + function setupThemeVarsToGlobal() { + const { themeTokens, darkThemeTokens } = createThemeToken( + themeColors.value, + settings.value.tokens, + settings.value.recommendColor + ); + addThemeVarsToGlobal(themeTokens, darkThemeTokens); + } + + /** + * Set layout reverse horizontal mix + * + * @param reverse Reverse horizontal mix + */ + function setLayoutReverseHorizontalMix(reverse: boolean) { + settings.value.layout.reverseHorizontalMix = reverse; + } + + /** Cache theme settings */ + function cacheThemeSettings() { + const isProd = import.meta.env.PROD; + + if (!isProd) return; + + localStg.set('themeSettings', settings.value); + } + + // cache theme settings when page is closed or refreshed + useEventListener(window, 'beforeunload', () => { + cacheThemeSettings(); + }); + + // watch store + scope.run(() => { + // watch dark mode + watch( + darkMode, + val => { + toggleCssDarkMode(val); + }, + { immediate: true } + ); + + watch( + [grayscaleMode, colourWeaknessMode], + val => { + toggleAuxiliaryColorModes(val[0], val[1]); + }, + { immediate: true } + ); + + // themeColors change, update css vars and storage theme color + watch( + themeColors, + val => { + setupThemeVarsToGlobal(); + localStg.set('themeColor', val.primary); + }, + { immediate: true } + ); + }); + + /** On scope dispose */ + onScopeDispose(() => { + scope.stop(); + }); + + return { + ...toRefs(settings.value), + darkMode, + themeColors, + antdTheme, + settingsJson, + setGrayscale, + setColourWeakness, + resetStore, + toggleThemeScheme, + setThemeScheme, + updateThemeColors, + setThemeLayout, + setLayoutReverseHorizontalMix + }; +}); diff --git a/src/store/modules/theme/shared.ts b/src/store/modules/theme/shared.ts new file mode 100644 index 0000000..4d4eb4a --- /dev/null +++ b/src/store/modules/theme/shared.ts @@ -0,0 +1,232 @@ +import { theme as antdTheme } from 'ant-design-vue'; +import type { ConfigProviderProps } from 'ant-design-vue'; +import { getColorPalette } from '@sa/color'; +import { getRgbOfColor } from '@sa/utils'; +import { defu } from 'defu'; +import { overrideThemeSettings, themeSettings } from '@/theme/settings'; +import { themeVars } from '@/theme/vars'; +import { toggleHtmlClass } from '@/utils/common'; +import { localStg } from '@/utils/storage'; + +const DARK_CLASS = 'dark'; + +/** Init theme settings */ +export function initThemeSettings() { + const isProd = import.meta.env.PROD; + + // if it is development mode, the theme settings will not be cached, by update `themeSettings` in `src/theme/settings.ts` to update theme settings + if (!isProd) return themeSettings; + + // if it is production mode, the theme settings will be cached in localStorage + // if want to update theme settings when publish new version, please update `overrideThemeSettings` in `src/theme/settings.ts` + + const localSettings = localStg.get('themeSettings'); + + let settings = defu(localSettings, themeSettings); + + const isOverride = localStg.get('overrideThemeFlag') === BUILD_TIME; + + if (!isOverride) { + settings = defu(overrideThemeSettings, settings); + + localStg.set('overrideThemeFlag', BUILD_TIME); + } + + return settings; +} + +/** + * create theme token css vars value by theme settings + * + * @param colors Theme colors + * @param tokens Theme setting tokens + * @param [recommended=false] Use recommended color. Default is `false` + */ +export function createThemeToken( + colors: App.Theme.ThemeColor, + tokens?: App.Theme.ThemeSetting['tokens'], + recommended = false +) { + const paletteColors = createThemePaletteColors(colors, recommended); + + const { light, dark } = tokens || themeSettings.tokens; + + const themeTokens: App.Theme.ThemeTokenCSSVars = { + colors: { + ...paletteColors, + nprogress: paletteColors.primary, + ...light.colors + }, + boxShadow: { + ...light.boxShadow + } + }; + + const darkThemeTokens: App.Theme.ThemeTokenCSSVars = { + colors: { + ...themeTokens.colors, + ...dark?.colors + }, + boxShadow: { + ...themeTokens.boxShadow, + ...dark?.boxShadow + } + }; + + return { + themeTokens, + darkThemeTokens + }; +} + +/** + * Create theme palette colors + * + * @param colors Theme colors + * @param [recommended=false] Use recommended color. Default is `false` + */ +function createThemePaletteColors(colors: App.Theme.ThemeColor, recommended = false) { + const colorKeys = Object.keys(colors) as App.Theme.ThemeColorKey[]; + const colorPaletteVar = {} as App.Theme.ThemePaletteColor; + + colorKeys.forEach(key => { + const colorMap = getColorPalette(colors[key], recommended); + + colorPaletteVar[key] = colorMap.get(500)!; + + colorMap.forEach((hex, number) => { + colorPaletteVar[`${key}-${number}`] = hex; + }); + }); + + return colorPaletteVar; +} + +/** + * Get css var by tokens + * + * @param tokens Theme base tokens + */ +function getCssVarByTokens(tokens: App.Theme.BaseToken) { + const styles: string[] = []; + + function removeVarPrefix(value: string) { + return value.replace('var(', '').replace(')', ''); + } + + function removeRgbPrefix(value: string) { + return value.replace('rgb(', '').replace(')', ''); + } + + for (const [key, tokenValues] of Object.entries(themeVars)) { + for (const [tokenKey, tokenValue] of Object.entries(tokenValues)) { + let cssVarsKey = removeVarPrefix(tokenValue); + let cssValue = tokens[key][tokenKey]; + + if (key === 'colors') { + cssVarsKey = removeRgbPrefix(cssVarsKey); + const { r, g, b } = getRgbOfColor(cssValue); + cssValue = `${r} ${g} ${b}`; + } + + styles.push(`${cssVarsKey}: ${cssValue}`); + } + } + + const styleStr = styles.join(';'); + + return styleStr; +} + +/** + * Add theme vars to global + * + * @param tokens + */ +export function addThemeVarsToGlobal(tokens: App.Theme.BaseToken, darkTokens: App.Theme.BaseToken) { + const cssVarStr = getCssVarByTokens(tokens); + const darkCssVarStr = getCssVarByTokens(darkTokens); + + const css = ` + :root { + ${cssVarStr} + } + `; + + const darkCss = ` + html.${DARK_CLASS} { + ${darkCssVarStr} + } + `; + + const styleId = 'theme-vars'; + + const style = document.querySelector(`#${styleId}`) || document.createElement('style'); + + style.id = styleId; + + style.textContent = css + darkCss; + + document.head.appendChild(style); +} + +/** + * Toggle css dark mode + * + * @param darkMode Is dark mode + */ +export function toggleCssDarkMode(darkMode = false) { + const { add, remove } = toggleHtmlClass(DARK_CLASS); + + if (darkMode) { + add(); + } else { + remove(); + } +} + +/** + * Toggle auxiliary color modes + * + * @param grayscaleMode + * @param colourWeakness + */ +export function toggleAuxiliaryColorModes(grayscaleMode = false, colourWeakness = false) { + const htmlElement = document.documentElement; + htmlElement.style.filter = [grayscaleMode ? 'grayscale(100%)' : '', colourWeakness ? 'invert(80%)' : ''] + .filter(Boolean) + .join(' '); +} + +/** + * Get antd theme + * + * @param colors Theme colors + * @param darkMode Is dark mode + */ +export function getAntdTheme(colors: App.Theme.ThemeColor, darkMode: boolean) { + const { defaultAlgorithm, darkAlgorithm } = antdTheme; + + const { primary, info, success, warning, error } = colors; + + const theme: ConfigProviderProps['theme'] = { + token: { + colorPrimary: primary, + colorInfo: info, + colorSuccess: success, + colorWarning: warning, + colorError: error + }, + algorithm: [darkMode ? darkAlgorithm : defaultAlgorithm], + components: { + Button: { + controlHeightSM: 28 + }, + Menu: { + colorSubItemBg: 'transparent' + } + } + }; + + return theme; +} diff --git a/src/store/plugins/index.ts b/src/store/plugins/index.ts new file mode 100644 index 0000000..dd929d4 --- /dev/null +++ b/src/store/plugins/index.ts @@ -0,0 +1,22 @@ +import type { PiniaPluginContext } from 'pinia'; +import { jsonClone } from '@sa/utils'; +import { SetupStoreId } from '@/enum'; + +/** + * The plugin reset the state of the store which is written by setup syntax + * + * @param context + */ +export function resetSetupStore(context: PiniaPluginContext) { + const setupSyntaxIds = Object.values(SetupStoreId) as string[]; + + if (setupSyntaxIds.includes(context.store.$id)) { + const { $state } = context.store; + + const defaultStore = jsonClone($state); + + context.store.$reset = () => { + context.store.$patch(defaultStore); + }; + } +} diff --git a/src/styles/css/global.css b/src/styles/css/global.css new file mode 100644 index 0000000..3121a31 --- /dev/null +++ b/src/styles/css/global.css @@ -0,0 +1,13 @@ +@import './reset.css'; +@import './nprogress.css'; +@import './transition.css'; + +html, +body, +#app { + height: 100%; +} + +html { + overflow-x: hidden; +} diff --git a/src/styles/css/nprogress.css b/src/styles/css/nprogress.css new file mode 100644 index 0000000..3e631b5 --- /dev/null +++ b/src/styles/css/nprogress.css @@ -0,0 +1,83 @@ +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: rgb(var(--nprogress-color)); + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: + 0 0 10px rgb(var(--nprogress-color)), + 0 0 5px rgb(var(--nprogress-color)); + opacity: 1; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + display: block; + position: fixed; + z-index: 1031; + top: 15px; + right: 15px; +} + +#nprogress .spinner-icon { + width: 18px; + height: 18px; + box-sizing: border-box; + + border: solid 2px transparent; + border-top-color: rgb(var(--nprogress-color)); + border-left-color: rgb(var(--nprogress-color)); + border-radius: 50%; + + -webkit-animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + overflow: hidden; + position: relative; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + position: absolute; +} + +@-webkit-keyframes nprogress-spinner { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + } +} +@keyframes nprogress-spinner { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/src/styles/css/reset.css b/src/styles/css/reset.css new file mode 100644 index 0000000..5714b35 --- /dev/null +++ b/src/styles/css/reset.css @@ -0,0 +1,377 @@ +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +2. [UnoCSS]: allow to override the default border color with css var `--un-default-border-color` +*/ + +*, +::before, +::after { + box-sizing: border-box; /* 1 */ + border-width: 0; /* 2 */ + border-style: solid; /* 2 */ + border-color: var(--un-default-border-color, #e5e7eb); /* 2 */ +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +*/ + +html { + line-height: 1.5; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -moz-tab-size: 4; /* 3 */ + tab-size: 4; /* 3 */ + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + 'Helvetica Neue', + Arial, + 'Noto Sans', + sans-serif, + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + 'Noto Color Emoji'; /* 4 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; /* 1 */ + line-height: inherit; /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; /* 1 */ + color: inherit; /* 2 */ + border-top-width: 1px; /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; /* 1 */ + border-color: inherit; /* 2 */ + border-collapse: collapse; /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-feature-settings: inherit; /* 1 */ + font-variation-settings: inherit; /* 1 */ + font-size: 100%; /* 1 */ + font-weight: inherit; /* 1 */ + line-height: inherit; /* 1 */ + color: inherit; /* 1 */ + margin: 0; /* 2 */ + padding: 0; /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; /* 1 */ + /* background-color: transparent; */ + background-image: none; /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::placeholder, +textarea::placeholder { + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role='button'] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; /* 1 */ + vertical-align: middle; /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ +[hidden] { + display: none; +} diff --git a/src/styles/css/transition.css b/src/styles/css/transition.css new file mode 100644 index 0000000..9e2a50b --- /dev/null +++ b/src/styles/css/transition.css @@ -0,0 +1,82 @@ +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.3s ease-in-out; +} +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +/* fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} +.fade-slide-enter-from { + opacity: 0; + transform: translateX(-30px); +} +.fade-slide-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* fade-bottom */ +.fade-bottom-enter-active, +.fade-bottom-leave-active { + transition: + opacity 0.25s, + transform 0.3s; +} +.fade-bottom-enter-from { + opacity: 0; + transform: translateY(-10%); +} +.fade-bottom-leave-to { + opacity: 0; + transform: translateY(10%); +} + +/* fade-scale */ +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} +.fade-scale-enter-from { + opacity: 0; + transform: scale(1.2); +} +.fade-scale-leave-to { + opacity: 0; + transform: scale(0.8); +} + +/* zoom-fade */ +.zoom-fade-enter-active, +.zoom-fade-leave-active { + transition: + transform 0.2s, + opacity 0.3s ease-out; +} +.zoom-fade-enter-from { + opacity: 0; + transform: scale(0.92); +} +.zoom-fade-leave-to { + opacity: 0; + transform: scale(1.06); +} + +/* zoom-out */ +.zoom-out-enter-active, +.zoom-out-leave-active { + transition: + opacity 0.1s ease-in-out, + transform 0.15s ease-out; +} +.zoom-out-enter-from, +.zoom-out-leave-to { + opacity: 0; + transform: scale(0); +} diff --git a/src/styles/scss/global.scss b/src/styles/scss/global.scss new file mode 100644 index 0000000..3a13435 --- /dev/null +++ b/src/styles/scss/global.scss @@ -0,0 +1 @@ +@forward './scrollbar.scss'; diff --git a/src/styles/scss/scrollbar.scss b/src/styles/scss/scrollbar.scss new file mode 100644 index 0000000..2e5ec45 --- /dev/null +++ b/src/styles/scss/scrollbar.scss @@ -0,0 +1,21 @@ +@mixin scrollbar($size: 7px, $color: rgba(0, 0, 0, 0.5)) { + scrollbar-width: thin; + scrollbar-color: $color transparent; + + &::-webkit-scrollbar-thumb { + background-color: $color; + border-radius: $size; + } + &::-webkit-scrollbar-thumb:hover { + background-color: $color; + border-radius: $size; + } + &::-webkit-scrollbar { + width: $size; + height: $size; + } + &::-webkit-scrollbar-track-piece { + background-color: rgba(0, 0, 0, 0); + border-radius: 0; + } +} diff --git a/src/theme/settings.ts b/src/theme/settings.ts new file mode 100644 index 0000000..cf092b3 --- /dev/null +++ b/src/theme/settings.ts @@ -0,0 +1,86 @@ +/** Default theme settings */ +export const themeSettings: App.Theme.ThemeSetting = { + themeScheme: 'light', + grayscale: false, + colourWeakness: false, + recommendColor: false, + themeColor: '#646cff', + otherColor: { + info: '#2080f0', + success: '#52c41a', + warning: '#faad14', + error: '#f5222d' + }, + isInfoFollowPrimary: true, + resetCacheStrategy: 'close', + layout: { + mode: 'vertical', + scrollMode: 'content', + reverseHorizontalMix: false + }, + page: { + animate: true, + animateMode: 'fade-slide' + }, + header: { + height: 56, + breadcrumb: { + visible: true, + showIcon: true + } + }, + tab: { + visible: true, + cache: true, + height: 44, + mode: 'chrome' + }, + fixedHeaderAndTab: true, + sider: { + inverted: false, + width: 220, + collapsedWidth: 64, + mixWidth: 90, + mixCollapsedWidth: 64, + mixChildMenuWidth: 200 + }, + footer: { + visible: true, + fixed: false, + height: 48, + right: true + }, + watermark: { + visible: false, + text: 'SoybeanAdmin' + }, + tokens: { + light: { + colors: { + container: 'rgb(255, 255, 255)', + layout: 'rgb(247, 250, 252)', + inverted: 'rgb(0, 20, 40)', + 'base-text': 'rgb(31, 31, 31)' + }, + boxShadow: { + header: '0 1px 2px rgb(0, 21, 41, 0.08)', + sider: '2px 0 8px 0 rgb(29, 35, 41, 0.05)', + tab: '0 1px 2px rgb(0, 21, 41, 0.08)' + } + }, + dark: { + colors: { + container: 'rgb(28, 28, 28)', + layout: 'rgb(18, 18, 18)', + 'base-text': 'rgb(224, 224, 224)' + } + } + } +}; + +/** + * Override theme settings + * + * If publish new version, use `overrideThemeSettings` to override certain theme settings + */ +export const overrideThemeSettings: Partial = {}; diff --git a/src/theme/vars.ts b/src/theme/vars.ts new file mode 100644 index 0000000..3e7946a --- /dev/null +++ b/src/theme/vars.ts @@ -0,0 +1,35 @@ +/** Create color palette vars */ +function createColorPaletteVars() { + const colors: App.Theme.ThemeColorKey[] = ['primary', 'info', 'success', 'warning', 'error']; + const colorPaletteNumbers: App.Theme.ColorPaletteNumber[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]; + + const colorPaletteVar = {} as App.Theme.ThemePaletteColor; + + colors.forEach(color => { + colorPaletteVar[color] = `rgb(var(--${color}-color))`; + colorPaletteNumbers.forEach(number => { + colorPaletteVar[`${color}-${number}`] = `rgb(var(--${color}-${number}-color))`; + }); + }); + + return colorPaletteVar; +} + +const colorPaletteVars = createColorPaletteVars(); + +/** Theme vars */ +export const themeVars: App.Theme.ThemeTokenCSSVars = { + colors: { + ...colorPaletteVars, + nprogress: 'rgb(var(--nprogress-color))', + container: 'rgb(var(--container-bg-color))', + layout: 'rgb(var(--layout-bg-color))', + inverted: 'rgb(var(--inverted-bg-color))', + 'base-text': 'rgb(var(--base-text-color))' + }, + boxShadow: { + header: 'var(--header-box-shadow)', + sider: 'var(--sider-box-shadow)', + tab: 'var(--tab-box-shadow)' + } +}; diff --git a/src/typings/antd.d.ts b/src/typings/antd.d.ts new file mode 100644 index 0000000..26a0bdf --- /dev/null +++ b/src/typings/antd.d.ts @@ -0,0 +1,40 @@ +declare namespace AntDesign { + type TableColumnType = import('ant-design-vue').TableColumnType; + type TableColumnGroupType = import('ant-design-vue').TableColumnGroupType; + type TablePaginationConfig = import('ant-design-vue').TablePaginationConfig; + type TableColumnCheck = import('@sa/hooks').TableColumnCheck; + type TableDataWithIndex = import('@sa/hooks').TableDataWithIndex; + type FlatResponseData = import('@sa/axios').FlatResponseData; + + type TableData = Api.Common.CommonRecord; + + /** + * the custom column key + * + * if you want to add a custom column, you should add a key to this type + */ + type CustomColumnKey = 'operate'; + + type SetTableColumnKey = Omit & { key?: keyof T | CustomColumnKey }; + + type TableColumn = SetTableColumnKey, T> | SetTableColumnKey, T>; + + type TableApiFn = ( + params: R + ) => Promise>>; + + /** + * the type of table operation + * + * - add: add table item + * - edit: edit table item + */ + type TableOperateType = 'add' | 'edit'; + + type GetTableData = A extends TableApiFn ? T : never; + + type AntDesignTableConfig = Pick< + import('@sa/hooks').TableConfig, TableColumn>>>, + 'apiFn' | 'apiParams' | 'columns' | 'immediate' + >; +} diff --git a/src/typings/api.d.ts b/src/typings/api.d.ts new file mode 100644 index 0000000..eff30a7 --- /dev/null +++ b/src/typings/api.d.ts @@ -0,0 +1,223 @@ +/** + * Namespace Api + * + * All backend api type + */ +declare namespace Api { + namespace Common { + /** common params of paginating */ + interface PaginatingCommonParams { + /** current page number */ + current: number; + /** page size */ + size: number; + /** total count */ + total: number; + } + + /** common params of paginating query list data */ + interface PaginatingQueryRecord extends PaginatingCommonParams { + records: T[]; + } + + /** common search params of table */ + type CommonSearchParams = Pick; + + /** + * enable status + * + * - "1": enabled + * - "2": disabled + */ + type EnableStatus = '1' | '2'; + + /** common record */ + type CommonRecord = { + /** record id */ + id: number; + /** record creator */ + createBy: string; + /** record create time */ + createTime: string; + /** record updater */ + updateBy: string; + /** record update time */ + updateTime: string; + /** record status */ + status: EnableStatus; + } & T; + } + + /** + * Namespace Auth + * + * Backend api module: "auth" + */ + namespace Auth { + interface LoginToken { + token: string; + refreshToken: string; + } + + interface UserInfo { + userId: string; + userName: string; + roles: string[]; + buttons: string[]; + } + } + + /** + * Namespace Route + * + * Backend api module: "route" + */ + namespace Route { + type ElegantConstRoute = import('@elegant-router/types').ElegantConstRoute; + + interface MenuRoute extends ElegantConstRoute { + id: string; + } + + interface UserRoute { + routes: MenuRoute[]; + home: import('@elegant-router/types').LastLevelRouteKey; + } + } + + /** + * namespace SystemManage + * + * backend api module: "systemManage" + */ + namespace SystemManage { + /** role */ + type Role = Common.CommonRecord<{ + /** role name */ + roleName: string; + /** role code */ + roleCode: string; + /** role description */ + roleDesc: string; + }>; + + /** role search params */ + type RoleSearchParams = Partial< + Pick & Common.CommonSearchParams + >; + + /** role list */ + type RoleList = Common.PaginatingQueryRecord; + + /** all role */ + type AllRole = Pick; + + /** + * user gender + * + * - "1": "male" + * - "2": "female" + */ + type UserGender = '1' | '2'; + + /** user */ + type User = Common.CommonRecord<{ + /** user name */ + userName: string; + /** user gender */ + userGender: UserGender; + /** user nick name */ + nickName: string; + /** user phone */ + userPhone: string; + /** user email */ + userEmail: string; + /** user role code collection */ + userRoles: string[]; + }>; + + /** user search params */ + type UserSearchParams = Partial< + Pick & + Common.CommonSearchParams + >; + + /** user list */ + type UserList = Common.PaginatingQueryRecord; + + /** + * menu type + * + * - "1": directory + * - "2": menu + */ + type MenuType = '1' | '2'; + + type MenuButton = { + /** + * button code + * + * it can be used to control the button permission + */ + code: string; + /** button description */ + desc: string; + }; + + /** + * icon type + * + * - "1": iconify icon + * - "2": local icon + */ + type IconType = '1' | '2'; + + type MenuPropsOfRoute = Pick< + import('vue-router').RouteMeta, + | 'i18nKey' + | 'keepAlive' + | 'constant' + | 'order' + | 'href' + | 'hideInMenu' + | 'activeMenu' + | 'multiTab' + | 'fixedIndexInTab' + | 'query' + >; + + type Menu = Common.CommonRecord<{ + /** parent menu id */ + parentId: number; + /** menu type */ + menuType: MenuType; + /** menu name */ + menuName: string; + /** route name */ + routeName: string; + /** route path */ + routePath: string; + /** component */ + component?: string; + /** iconify icon name or local icon name */ + icon: string; + /** icon type */ + iconType: IconType; + /** buttons */ + buttons?: MenuButton[] | null; + /** children menu */ + children?: Menu[]; + }> & + MenuPropsOfRoute; + + /** menu list */ + type MenuList = Common.PaginatingQueryRecord; + + type MenuTree = { + id: number; + label: string; + pId: number; + children?: MenuTree[]; + }; + } +} diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts new file mode 100644 index 0000000..4cb5d71 --- /dev/null +++ b/src/typings/app.d.ts @@ -0,0 +1,736 @@ +/** The global namespace for the app */ +declare namespace App { + /** Theme namespace */ + namespace Theme { + type ColorPaletteNumber = import('@sa/color').ColorPaletteNumber; + + /** Theme setting */ + interface ThemeSetting { + /** Theme scheme */ + themeScheme: UnionKey.ThemeScheme; + /** grayscale mode */ + grayscale: boolean; + /** colour weakness mode */ + colourWeakness: boolean; + /** Whether to recommend color */ + recommendColor: boolean; + /** Theme color */ + themeColor: string; + /** Other color */ + otherColor: OtherColor; + /** Whether info color is followed by the primary color */ + isInfoFollowPrimary: boolean; + /** Reset cache strategy */ + resetCacheStrategy: UnionKey.ResetCacheStrategy; + /** Layout */ + layout: { + /** Layout mode */ + mode: UnionKey.ThemeLayoutMode; + /** Scroll mode */ + scrollMode: UnionKey.ThemeScrollMode; + /** + * Whether to reverse the horizontal mix + * + * if true, the vertical child level menus in left and horizontal first level menus in top + */ + reverseHorizontalMix: boolean; + }; + /** Page */ + page: { + /** Whether to show the page transition */ + animate: boolean; + /** Page animate mode */ + animateMode: UnionKey.ThemePageAnimateMode; + }; + /** Header */ + header: { + /** Header height */ + height: number; + /** Header breadcrumb */ + breadcrumb: { + /** Whether to show the breadcrumb */ + visible: boolean; + /** Whether to show the breadcrumb icon */ + showIcon: boolean; + }; + }; + /** Tab */ + tab: { + /** Whether to show the tab */ + visible: boolean; + /** + * Whether to cache the tab + * + * If cache, the tabs will get from the local storage when the page is refreshed + */ + cache: boolean; + /** Tab height */ + height: number; + /** Tab mode */ + mode: UnionKey.ThemeTabMode; + }; + /** Fixed header and tab */ + fixedHeaderAndTab: boolean; + /** Sider */ + sider: { + /** Inverted sider */ + inverted: boolean; + /** Sider width */ + width: number; + /** Collapsed sider width */ + collapsedWidth: number; + /** Sider width when the layout is 'vertical-mix' or 'horizontal-mix' */ + mixWidth: number; + /** Collapsed sider width when the layout is 'vertical-mix' or 'horizontal-mix' */ + mixCollapsedWidth: number; + /** Child menu width when the layout is 'vertical-mix' or 'horizontal-mix' */ + mixChildMenuWidth: number; + }; + /** Footer */ + footer: { + /** Whether to show the footer */ + visible: boolean; + /** Whether fixed the footer */ + fixed: boolean; + /** Footer height */ + height: number; + /** Whether float the footer to the right when the layout is 'horizontal-mix' */ + right: boolean; + }; + /** Watermark */ + watermark: { + /** Whether to show the watermark */ + visible: boolean; + /** Watermark text */ + text: string; + }; + /** define some theme settings tokens, will transform to css variables */ + tokens: { + light: ThemeSettingToken; + dark?: { + [K in keyof ThemeSettingToken]?: Partial; + }; + }; + } + + interface OtherColor { + info: string; + success: string; + warning: string; + error: string; + } + + interface ThemeColor extends OtherColor { + primary: string; + } + + type ThemeColorKey = keyof ThemeColor; + + type ThemePaletteColor = { + [key in ThemeColorKey | `${ThemeColorKey}-${ColorPaletteNumber}`]: string; + }; + + type BaseToken = Record>; + + interface ThemeSettingTokenColor { + /** the progress bar color, if not set, will use the primary color */ + nprogress?: string; + container: string; + layout: string; + inverted: string; + 'base-text': string; + } + + interface ThemeSettingTokenBoxShadow { + header: string; + sider: string; + tab: string; + } + + interface ThemeSettingToken { + colors: ThemeSettingTokenColor; + boxShadow: ThemeSettingTokenBoxShadow; + } + + type ThemeTokenColor = ThemePaletteColor & ThemeSettingTokenColor; + + /** Theme token CSS variables */ + type ThemeTokenCSSVars = { + colors: ThemeTokenColor & { [key: string]: string }; + boxShadow: ThemeSettingTokenBoxShadow & { [key: string]: string }; + }; + } + + /** Global namespace */ + namespace Global { + type VNode = import('vue').VNode; + type RouteLocationNormalizedLoaded = import('vue-router').RouteLocationNormalizedLoaded; + type RouteKey = import('@elegant-router/types').RouteKey; + type RouteMap = import('@elegant-router/types').RouteMap; + type RoutePath = import('@elegant-router/types').RoutePath; + type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey; + + /** The global header props */ + interface HeaderProps { + /** Whether to show the logo */ + showLogo?: boolean; + /** Whether to show the menu toggler */ + showMenuToggler?: boolean; + /** Whether to show the menu */ + showMenu?: boolean; + } + + /** The global menu */ + type Menu = { + /** + * The menu key + * + * Equal to the route key + */ + key: string; + /** The menu label */ + label: string; + /** The menu i18n key */ + i18nKey?: I18n.I18nKey | null; + /** The route key */ + routeKey: RouteKey; + /** The route path */ + routePath: RoutePath; + /** The menu icon */ + icon?: () => VNode; + /** The tooltip title */ + title?: string; + /** The menu children */ + children?: Menu[]; + }; + + /** Tab route */ + type TabRoute = Pick & + Partial>; + + /** The global tab */ + type Tab = { + /** The tab id */ + id: string; + /** The tab label */ + label: string; + /** + * The new tab label + * + * If set, the tab label will be replaced by this value + */ + newLabel?: string; + /** + * The old tab label + * + * when reset the tab label, the tab label will be replaced by this value + */ + oldLabel?: string; + /** The tab route key */ + routeKey: LastLevelRouteKey; + /** The tab route path */ + routePath: RouteMap[LastLevelRouteKey]; + /** The tab route full path */ + fullPath: string; + /** The tab fixed index */ + fixedIndex?: number | null; + /** + * Tab icon + * + * Iconify icon + */ + icon?: string; + /** + * Tab local icon + * + * Local icon + */ + localIcon?: string; + /** I18n key */ + i18nKey?: I18n.I18nKey | null; + }; + + /** Form rule */ + type FormRule = import('ant-design-vue/es/form/interface.d.ts').Rule; + + /** The global dropdown key */ + type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll'; + } + + /** + * I18n namespace + * + * Locales type + */ + namespace I18n { + type RouteKey = import('@elegant-router/types').RouteKey; + + type LangType = 'en-US' | 'zh-CN'; + + type LangOption = { + label: string; + key: LangType; + }; + + type I18nRouteKey = Exclude; + + type FormMsg = { + required: string; + invalid: string; + }; + + type Schema = { + system: { + title: string; + updateTitle: string; + updateContent: string; + updateConfirm: string; + updateCancel: string; + }; + common: { + action: string; + add: string; + addSuccess: string; + backToHome: string; + batchDelete: string; + cancel: string; + close: string; + check: string; + columnSetting: string; + config: string; + confirm: string; + delete: string; + deleteSuccess: string; + confirmDelete: string; + edit: string; + error: string; + index: string; + keywordSearch: string; + logout: string; + logoutConfirm: string; + lookForward: string; + modify: string; + modifySuccess: string; + noData: string; + operate: string; + pleaseCheckValue: string; + refresh: string; + reset: string; + search: string; + switch: string; + tip: string; + trigger: string; + update: string; + updateSuccess: string; + userCenter: string; + yesOrNo: { + yes: string; + no: string; + }; + }; + request: { + logout: string; + logoutMsg: string; + logoutWithModal: string; + logoutWithModalMsg: string; + refreshToken: string; + tokenExpired: string; + }; + theme: { + themeSchema: { title: string } & Record; + grayscale: string; + colourWeakness: string; + layoutMode: { title: string; reverseHorizontalMix: string } & Record; + recommendColor: string; + recommendColorDesc: string; + themeColor: { + title: string; + followPrimary: string; + } & Theme.ThemeColor; + scrollMode: { title: string } & Record; + page: { + animate: string; + mode: { title: string } & Record; + }; + fixedHeaderAndTab: string; + header: { + height: string; + breadcrumb: { + visible: string; + showIcon: string; + }; + }; + tab: { + visible: string; + cache: string; + height: string; + mode: { title: string } & Record; + }; + sider: { + inverted: string; + width: string; + collapsedWidth: string; + mixWidth: string; + mixCollapsedWidth: string; + mixChildMenuWidth: string; + }; + footer: { + visible: string; + fixed: string; + height: string; + right: string; + }; + watermark: { + visible: string; + text: string; + }; + themeDrawerTitle: string; + pageFunTitle: string; + resetCacheStrategy: { title: string } & Record; + configOperation: { + copyConfig: string; + copySuccessMsg: string; + resetConfig: string; + resetSuccessMsg: string; + }; + }; + route: Record; + page: { + login: { + common: { + loginOrRegister: string; + userNamePlaceholder: string; + phonePlaceholder: string; + codePlaceholder: string; + passwordPlaceholder: string; + confirmPasswordPlaceholder: string; + codeLogin: string; + confirm: string; + back: string; + validateSuccess: string; + loginSuccess: string; + welcomeBack: string; + }; + pwdLogin: { + title: string; + rememberMe: string; + forgetPassword: string; + register: string; + otherAccountLogin: string; + otherLoginMode: string; + superAdmin: string; + admin: string; + user: string; + }; + codeLogin: { + title: string; + getCode: string; + reGetCode: string; + sendCodeSuccess: string; + imageCodePlaceholder: string; + }; + register: { + title: string; + agreement: string; + protocol: string; + policy: string; + }; + resetPwd: { + title: string; + }; + bindWeChat: { + title: string; + }; + }; + about: { + title: string; + introduction: string; + projectInfo: { + title: string; + version: string; + latestBuildTime: string; + githubLink: string; + previewLink: string; + }; + prdDep: string; + devDep: string; + }; + home: { + greeting: string; + weatherDesc: string; + projectCount: string; + todo: string; + message: string; + downloadCount: string; + registerCount: string; + schedule: string; + study: string; + work: string; + rest: string; + entertainment: string; + visitCount: string; + turnover: string; + dealCount: string; + projectNews: { + title: string; + moreNews: string; + desc1: string; + desc2: string; + desc3: string; + desc4: string; + desc5: string; + }; + creativity: string; + }; + function: { + tab: { + tabOperate: { + title: string; + addTab: string; + addTabDesc: string; + closeTab: string; + closeCurrentTab: string; + closeAboutTab: string; + addMultiTab: string; + addMultiTabDesc1: string; + addMultiTabDesc2: string; + }; + tabTitle: { + title: string; + changeTitle: string; + change: string; + resetTitle: string; + reset: string; + }; + }; + multiTab: { + routeParam: string; + backTab: string; + }; + toggleAuth: { + toggleAccount: string; + authHook: string; + superAdminVisible: string; + adminVisible: string; + adminOrUserVisible: string; + }; + request: { + repeatedErrorOccurOnce: string; + repeatedError: string; + repeatedErrorMsg1: string; + repeatedErrorMsg2: string; + }; + }; + manage: { + common: { + status: { + enable: string; + disable: string; + }; + }; + role: { + title: string; + roleName: string; + roleCode: string; + roleStatus: string; + roleDesc: string; + form: { + roleName: string; + roleCode: string; + roleStatus: string; + roleDesc: string; + }; + addRole: string; + editRole: string; + menuAuth: string; + buttonAuth: string; + }; + user: { + title: string; + userName: string; + userGender: string; + nickName: string; + userPhone: string; + userEmail: string; + userStatus: string; + userRole: string; + form: { + userName: string; + userGender: string; + nickName: string; + userPhone: string; + userEmail: string; + userStatus: string; + userRole: string; + }; + addUser: string; + editUser: string; + gender: { + male: string; + female: string; + }; + }; + menu: { + home: string; + title: string; + id: string; + parentId: string; + menuType: string; + menuName: string; + constant: string; + routeName: string; + routePath: string; + pathParam: string; + layout: string; + page: string; + i18nKey: string; + icon: string; + localIcon: string; + iconTypeTitle: string; + order: string; + keepAlive: string; + href: string; + hideInMenu: string; + activeMenu: string; + multiTab: string; + fixedIndexInTab: string; + query: string; + button: string; + buttonCode: string; + buttonDesc: string; + menuStatus: string; + form: { + home: string; + menuType: string; + menuName: string; + routeName: string; + routePath: string; + pathParam: string; + layout: string; + queryKey: string; + page: string; + i18nKey: string; + icon: string; + localIcon: string; + queryValue: string; + order: string; + keepAlive: string; + href: string; + hideInMenu: string; + activeMenu: string; + multiTab: string; + fixedInTab: string; + fixedIndexInTab: string; + button: string; + buttonCode: string; + buttonDesc: string; + menuStatus: string; + }; + addMenu: string; + editMenu: string; + addChildMenu: string; + type: { + directory: string; + menu: string; + }; + iconType: { + iconify: string; + local: string; + }; + }; + }; + }; + form: { + required: string; + userName: FormMsg; + phone: FormMsg; + pwd: FormMsg; + confirmPwd: FormMsg; + code: FormMsg; + email: FormMsg; + }; + dropdown: Record; + icon: { + themeConfig: string; + themeSchema: string; + lang: string; + fullscreen: string; + fullscreenExit: string; + reload: string; + collapse: string; + expand: string; + pin: string; + unpin: string; + }; + }; + + type GetI18nKey, K extends keyof T = keyof T> = K extends string + ? T[K] extends Record + ? `${K}.${GetI18nKey}` + : K + : never; + + type I18nKey = GetI18nKey; + + type TranslateOptions = import('vue-i18n').TranslateOptions; + + interface $T { + (key: I18nKey): string; + (key: I18nKey, plural: number, options?: TranslateOptions): string; + (key: I18nKey, defaultMsg: string, options?: TranslateOptions): string; + (key: I18nKey, list: unknown[], options?: TranslateOptions): string; + (key: I18nKey, list: unknown[], plural: number): string; + (key: I18nKey, list: unknown[], defaultMsg: string): string; + (key: I18nKey, named: Record, options?: TranslateOptions): string; + (key: I18nKey, named: Record, plural: number): string; + (key: I18nKey, named: Record, defaultMsg: string): string; + } + } + + /** Service namespace */ + namespace Service { + /** Other baseURL key */ + type OtherBaseURLKey = 'demo'; + + interface ServiceConfigItem { + /** The backend service base url */ + baseURL: string; + /** The proxy pattern of the backend service base url */ + proxyPattern: string; + } + + interface OtherServiceConfigItem extends ServiceConfigItem { + key: OtherBaseURLKey; + } + + /** The backend service config */ + interface ServiceConfig extends ServiceConfigItem { + /** Other backend service config */ + other: OtherServiceConfigItem[]; + } + + interface SimpleServiceConfig extends Pick { + other: Record; + } + + /** The backend service response data */ + type Response = { + /** The backend service response code */ + code: string; + /** The backend service response message */ + msg: string; + /** The backend service response data */ + data: T; + }; + + /** The demo backend service response data */ + type DemoResponse = { + /** The backend service response code */ + status: string; + /** The backend service response message */ + message: string; + /** The backend service response data */ + result: T; + }; + } +} diff --git a/src/typings/common.d.ts b/src/typings/common.d.ts new file mode 100644 index 0000000..06b526c --- /dev/null +++ b/src/typings/common.d.ts @@ -0,0 +1,25 @@ +/** The common type namespace */ +declare namespace CommonType { + /** The strategic pattern */ + interface StrategicPattern { + /** The condition */ + condition: boolean; + /** If the condition is true, then call the action function */ + callback: () => void; + } + + /** + * The option type + * + * @property value: The option value + * @property label: The option label + */ + type Option = { value: K; label: string }; + + type YesOrNo = 'Y' | 'N'; + + /** add null to all properties */ + type RecordNullable = { + [K in keyof T]?: T[K] | null; + }; +} diff --git a/src/typings/components.d.ts b/src/typings/components.d.ts new file mode 100644 index 0000000..b3e8227 --- /dev/null +++ b/src/typings/components.d.ts @@ -0,0 +1,87 @@ +/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb'] + ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem'] + AButton: typeof import('ant-design-vue/es')['Button'] + ACard: typeof import('ant-design-vue/es')['Card'] + ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] + ACol: typeof import('ant-design-vue/es')['Col'] + ADescriptions: typeof import('ant-design-vue/es')['Descriptions'] + ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem'] + ADivider: typeof import('ant-design-vue/es')['Divider'] + ADrawer: typeof import('ant-design-vue/es')['Drawer'] + ADropdown: typeof import('ant-design-vue/es')['Dropdown'] + AForm: typeof import('ant-design-vue/es')['Form'] + AFormItem: typeof import('ant-design-vue/es')['FormItem'] + AInput: typeof import('ant-design-vue/es')['Input'] + AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] + AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] + AInputSearch: typeof import('ant-design-vue/es')['InputSearch'] + AList: typeof import('ant-design-vue/es')['List'] + AListItem: typeof import('ant-design-vue/es')['ListItem'] + AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta'] + AMenu: typeof import('ant-design-vue/es')['Menu'] + AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider'] + AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] + AModal: typeof import('ant-design-vue/es')['Modal'] + APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] + APopover: typeof import('ant-design-vue/es')['Popover'] + AppProvider: typeof import('./../components/common/app-provider.vue')['default'] + ARadio: typeof import('ant-design-vue/es')['Radio'] + ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] + ARow: typeof import('ant-design-vue/es')['Row'] + ASegmented: typeof import('ant-design-vue/es')['Segmented'] + ASelect: typeof import('ant-design-vue/es')['Select'] + ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] + ASpace: typeof import('ant-design-vue/es')['Space'] + AStatistic: typeof import('ant-design-vue/es')['Statistic'] + ASwitch: typeof import('ant-design-vue/es')['Switch'] + ATable: typeof import('ant-design-vue/es')['Table'] + ATag: typeof import('ant-design-vue/es')['Tag'] + ATooltip: typeof import('ant-design-vue/es')['Tooltip'] + ATree: typeof import('ant-design-vue/es')['Tree'] + AWatermark: typeof import('ant-design-vue/es')['Watermark'] + BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default'] + ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default'] + CountTo: typeof import('./../components/custom/count-to.vue')['default'] + DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default'] + ExceptionBase: typeof import('./../components/common/exception-base.vue')['default'] + FullScreen: typeof import('./../components/common/full-screen.vue')['default'] + IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default'] + IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default'] + IconCarbonAdd: typeof import('~icons/carbon/add')['default'] + IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default'] + IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default'] + 'IconIc:roundPlus': typeof import('~icons/ic/round-plus')['default'] + IconIcRoundDelete: typeof import('~icons/ic/round-delete')['default'] + IconIcRoundPlus: typeof import('~icons/ic/round-plus')['default'] + IconIcRoundRefresh: typeof import('~icons/ic/round-refresh')['default'] + IconIcRoundRemove: typeof import('~icons/ic/round-remove')['default'] + IconIcRoundSearch: typeof import('~icons/ic/round-search')['default'] + IconLocalBanner: typeof import('~icons/local/banner')['default'] + IconLocalLogo: typeof import('~icons/local/logo')['default'] + IconMdiDrag: typeof import('~icons/mdi/drag')['default'] + IconMdiRefresh: typeof import('~icons/mdi/refresh')['default'] + LangSwitch: typeof import('./../components/common/lang-switch.vue')['default'] + LookForward: typeof import('./../components/custom/look-forward.vue')['default'] + MenuToggler: typeof import('./../components/common/menu-toggler.vue')['default'] + PinToggler: typeof import('./../components/common/pin-toggler.vue')['default'] + ReloadButton: typeof import('./../components/common/reload-button.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + SoybeanAvatar: typeof import('./../components/custom/soybean-avatar.vue')['default'] + SvgIcon: typeof import('./../components/custom/svg-icon.vue')['default'] + SystemLogo: typeof import('./../components/common/system-logo.vue')['default'] + TableColumnSetting: typeof import('./../components/advanced/table-column-setting.vue')['default'] + TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default'] + ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default'] + WaveBg: typeof import('./../components/custom/wave-bg.vue')['default'] + } +} diff --git a/src/typings/elegant-router.d.ts b/src/typings/elegant-router.d.ts new file mode 100644 index 0000000..267270b --- /dev/null +++ b/src/typings/elegant-router.d.ts @@ -0,0 +1,320 @@ +/* eslint-disable */ +/* prettier-ignore */ +// Generated by elegant-router +// Read more: https://github.com/soybeanjs/elegant-router + +declare module "@elegant-router/types" { + type ElegantConstRoute = import('@elegant-router/vue').ElegantConstRoute; + + /** + * route layout + */ + export type RouteLayout = "base" | "blank"; + + /** + * route map + */ + export type RouteMap = { + "root": "/"; + "not-found": "/:pathMatch(.*)*"; + "exception": "/exception"; + "exception_403": "/exception/403"; + "exception_404": "/exception/404"; + "exception_500": "/exception/500"; + "document": "/document"; + "document_project": "/document/project"; + "document_project-link": "/document/project-link"; + "document_vue": "/document/vue"; + "document_vite": "/document/vite"; + "document_unocss": "/document/unocss"; + "document_naive": "/document/naive"; + "document_antd": "/document/antd"; + "403": "/403"; + "404": "/404"; + "500": "/500"; + "about": "/about"; + "function": "/function"; + "function_hide-child": "/function/hide-child"; + "function_hide-child_one": "/function/hide-child/one"; + "function_hide-child_three": "/function/hide-child/three"; + "function_hide-child_two": "/function/hide-child/two"; + "function_multi-tab": "/function/multi-tab"; + "function_request": "/function/request"; + "function_super-page": "/function/super-page"; + "function_tab": "/function/tab"; + "function_toggle-auth": "/function/toggle-auth"; + "home": "/home"; + "iframe-page": "/iframe-page/:url"; + "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?"; + "manage": "/manage"; + "manage_menu": "/manage/menu"; + "manage_role": "/manage/role"; + "manage_user": "/manage/user"; + "manage_user-detail": "/manage/user-detail/:id"; + "multi-menu": "/multi-menu"; + "multi-menu_first": "/multi-menu/first"; + "multi-menu_first_child": "/multi-menu/first/child"; + "multi-menu_second": "/multi-menu/second"; + "multi-menu_second_child": "/multi-menu/second/child"; + "multi-menu_second_child_home": "/multi-menu/second/child/home"; + "user-center": "/user-center"; + }; + + /** + * route key + */ + export type RouteKey = keyof RouteMap; + + /** + * route path + */ + export type RoutePath = RouteMap[RouteKey]; + + /** + * custom route key + */ + export type CustomRouteKey = Extract< + RouteKey, + | "root" + | "not-found" + | "exception" + | "exception_403" + | "exception_404" + | "exception_500" + | "document" + | "document_project" + | "document_project-link" + | "document_vue" + | "document_vite" + | "document_unocss" + | "document_naive" + | "document_antd" + >; + + /** + * the generated route key + */ + export type GeneratedRouteKey = Exclude; + + /** + * the first level route key, which contain the layout of the route + */ + export type FirstLevelRouteKey = Extract< + RouteKey, + | "403" + | "404" + | "500" + | "about" + | "function" + | "home" + | "iframe-page" + | "login" + | "manage" + | "multi-menu" + | "user-center" + >; + + /** + * the custom first level route key + */ + export type CustomFirstLevelRouteKey = Extract< + CustomRouteKey, + | "root" + | "not-found" + | "exception" + | "document" + >; + + /** + * the last level route key, which has the page file + */ + export type LastLevelRouteKey = Extract< + RouteKey, + | "403" + | "404" + | "500" + | "iframe-page" + | "login" + | "about" + | "function_hide-child_one" + | "function_hide-child_three" + | "function_hide-child_two" + | "function_multi-tab" + | "function_request" + | "function_super-page" + | "function_tab" + | "function_toggle-auth" + | "home" + | "manage_menu" + | "manage_role" + | "manage_user-detail" + | "manage_user" + | "multi-menu_first_child" + | "multi-menu_second_child_home" + | "user-center" + >; + + /** + * the custom last level route key + */ + export type CustomLastLevelRouteKey = Extract< + CustomRouteKey, + | "root" + | "not-found" + | "exception_403" + | "exception_404" + | "exception_500" + | "document_project" + | "document_project-link" + | "document_vue" + | "document_vite" + | "document_unocss" + | "document_naive" + | "document_antd" + >; + + /** + * the single level route key + */ + export type SingleLevelRouteKey = FirstLevelRouteKey & LastLevelRouteKey; + + /** + * the custom single level route key + */ + export type CustomSingleLevelRouteKey = CustomFirstLevelRouteKey & CustomLastLevelRouteKey; + + /** + * the first level route key, but not the single level + */ + export type FirstLevelRouteNotSingleKey = Exclude; + + /** + * the custom first level route key, but not the single level + */ + export type CustomFirstLevelRouteNotSingleKey = Exclude; + + /** + * the center level route key + */ + export type CenterLevelRouteKey = Exclude; + + /** + * the custom center level route key + */ + export type CustomCenterLevelRouteKey = Exclude; + + /** + * the center level route key + */ + type GetChildRouteKey = T extends `${K}_${infer R}` + ? R extends `${string}_${string}` + ? never + : T + : never; + + /** + * the single level route + */ + type SingleLevelRoute = K extends string + ? Omit & { + name: K; + path: RouteMap[K]; + component: `layout.${RouteLayout}$view.${K}`; + } + : never; + + /** + * the last level route + */ + type LastLevelRoute = K extends LastLevelRouteKey + ? Omit & { + name: K; + path: RouteMap[K]; + component: `view.${K}`; + } + : never; + + /** + * the center level route + */ + type CenterLevelRoute = K extends CenterLevelRouteKey + ? Omit & { + name: K; + path: RouteMap[K]; + children: (CenterLevelRoute> | LastLevelRoute>)[]; + } + : never; + + /** + * the multi level route + */ + type MultiLevelRoute = K extends string + ? ElegantConstRoute & { + name: K; + path: RouteMap[K]; + component: `layout.${RouteLayout}`; + children: (CenterLevelRoute> | LastLevelRoute>)[]; + } + : never; + + /** + * the custom first level route + */ + type CustomSingleLevelRoute = K extends string + ? Omit & { + name: K; + path: RouteMap[K]; + component?: `layout.${RouteLayout}$view.${LastLevelRouteKey}`; + } + : never; + + /** + * the custom last level route + */ + type CustomLastLevelRoute = K extends CustomLastLevelRouteKey + ? Omit & { + name: K; + path: RouteMap[K]; + component?: `view.${LastLevelRouteKey}`; + } + : never; + + /** + * the custom center level route + */ + type CustomCenterLevelRoute = K extends CustomCenterLevelRouteKey + ? Omit & { + name: K; + path: RouteMap[K]; + children: (CustomCenterLevelRoute> | CustomLastLevelRoute>)[]; + } + : never; + + /** + * the custom multi level route + */ + type CustomMultiLevelRoute = + K extends string + ? ElegantConstRoute & { + name: K; + path: RouteMap[K]; + component: `layout.${RouteLayout}`; + children: (CustomCenterLevelRoute> | CustomLastLevelRoute>)[]; + } + : never; + + /** + * the custom route + */ + type CustomRoute = CustomSingleLevelRoute | CustomMultiLevelRoute; + + /** + * the generated route + */ + type GeneratedRoute = SingleLevelRoute | MultiLevelRoute; + + /** + * the elegant route + */ + type ElegantRoute = GeneratedRoute | CustomRoute; +} diff --git a/src/typings/global.d.ts b/src/typings/global.d.ts new file mode 100644 index 0000000..e9f3dc4 --- /dev/null +++ b/src/typings/global.d.ts @@ -0,0 +1,17 @@ +export {}; + +declare global { + export interface Window { + /** NProgress instance */ + NProgress?: import('nprogress').NProgress; + /** Ant-design-vue message instance */ + $message?: import('ant-design-vue/es/message/interface').MessageInstance; + /** Ant-design-vue modal instance */ + $modal?: Omit; + /** Ant-design-vue notification instance */ + $notification?: import('ant-design-vue/es/notification/interface').NotificationInstance; + } + + /** Build time of the project */ + export const BUILD_TIME: string; +} diff --git a/src/typings/router.d.ts b/src/typings/router.d.ts new file mode 100644 index 0000000..256e646 --- /dev/null +++ b/src/typings/router.d.ts @@ -0,0 +1,72 @@ +import 'vue-router'; + +declare module 'vue-router' { + interface RouteMeta { + /** + * Title of the route + * + * It can be used in document title + */ + title: string; + /** + * I18n key of the route + * + * It's used in i18n, if it is set, the title will be ignored + */ + i18nKey?: App.I18n.I18nKey | null; + /** + * Roles of the route + * + * Route can be accessed if the current user has at least one of the roles + * + * It only works when the route mode is "static", if the route mode is "dynamic", it will be ignored + */ + roles?: string[]; + /** Whether to cache the route */ + keepAlive?: boolean | null; + /** + * Is constant route + * + * when it is set to true, there will be no login verification and no permission verification to access the route + */ + constant?: boolean | null; + /** + * Iconify icon + * + * It can be used in the menu or breadcrumb + */ + icon?: string; + /** + * Local icon + * + * In "src/assets/svg-icon", if it is set, the icon will be ignored + */ + localIcon?: string; + /** Icon size. width and height are the same. */ + iconFontSize?: number; + /** Router order */ + order?: number | null; + /** The outer link of the route */ + href?: string | null; + /** Whether to hide the route in the menu */ + hideInMenu?: boolean | null; + /** + * The menu key will be activated when entering the route + * + * The route is not in the menu + * + * @example + * the route is "user_detail", if it is set to "user_list", the menu "user_list" will be activated + */ + activeMenu?: import('@elegant-router/types').RouteKey | null; + /** + * By default, the same route path will use one tab, even with different query, if set true, the route with + * different query will use different tabs + */ + multiTab?: boolean | null; + /** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */ + fixedIndexInTab?: number | null; + /** if set query parameters, it will be automatically carried when entering the route */ + query?: { key: string; value: string }[] | null; + } +} diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts new file mode 100644 index 0000000..0d52f33 --- /dev/null +++ b/src/typings/storage.d.ts @@ -0,0 +1,39 @@ +/** The storage namespace */ +declare namespace StorageType { + interface Session { + /** The theme color */ + themeColor: string; + // /** + // * the theme settings + // */ + // themeSettings: App.Theme.ThemeSetting; + } + + interface Local { + /** The i18n language */ + lang: App.I18n.LangType; + /** The token */ + token: string; + /** Fixed sider with mix-menu */ + mixSiderFixed: CommonType.YesOrNo; + /** The refresh token */ + refreshToken: string; + /** The theme color */ + themeColor: string; + /** The theme settings */ + themeSettings: App.Theme.ThemeSetting; + /** + * The override theme flags + * + * The value is the build time of the project + */ + overrideThemeFlag: string; + /** The global tabs */ + globalTabs: App.Global.Tab[]; + /** The backup theme setting before is mobile */ + backupThemeSettingBeforeIsMobile: { + layout: UnionKey.ThemeLayoutMode; + siderCollapse: boolean; + }; + } +} diff --git a/src/typings/union-key.d.ts b/src/typings/union-key.d.ts new file mode 100644 index 0000000..a783294 --- /dev/null +++ b/src/typings/union-key.d.ts @@ -0,0 +1,157 @@ +/** The union key namespace */ +declare namespace UnionKey { + /** + * The login module + * + * - pwd-login: password login + * - code-login: phone code login + * - register: register + * - reset-pwd: reset password + * - bind-wechat: bind wechat + */ + type LoginModule = 'pwd-login' | 'code-login' | 'register' | 'reset-pwd' | 'bind-wechat'; + + /** Theme scheme */ + type ThemeScheme = 'light' | 'dark' | 'auto'; + + /** + * Reset cache strategy + * + * - close: re-cache when close page + * - refresh: re-cache when refresh page + */ + type ResetCacheStrategy = 'close' | 'refresh'; + + /** + * The layout mode + * + * - vertical: the vertical menu in left + * - horizontal: the horizontal menu in top + * - vertical-mix: two vertical mixed menus in left + * - horizontal-mix: the vertical first level menus in left and horizontal child level menus in top + */ + type ThemeLayoutMode = 'vertical' | 'horizontal' | 'vertical-mix' | 'horizontal-mix'; + + /** + * The scroll mode when content overflow + * + * - wrapper: the wrapper component's root element overflow + * - content: the content component overflow + */ + type ThemeScrollMode = import('@sa/materials').LayoutScrollMode; + + /** Page animate mode */ + type ThemePageAnimateMode = 'fade' | 'fade-slide' | 'fade-bottom' | 'fade-scale' | 'zoom-fade' | 'zoom-out' | 'none'; + + /** + * Tab mode + * + * - chrome: chrome style + * - button: button style + */ + type ThemeTabMode = import('@sa/materials').PageTabMode; + + /** Unocss animate key */ + type UnoCssAnimateKey = + | 'pulse' + | 'bounce' + | 'spin' + | 'ping' + | 'bounce-alt' + | 'flash' + | 'pulse-alt' + | 'rubber-band' + | 'shake-x' + | 'shake-y' + | 'head-shake' + | 'swing' + | 'tada' + | 'wobble' + | 'jello' + | 'heart-beat' + | 'hinge' + | 'jack-in-the-box' + | 'light-speed-in-left' + | 'light-speed-in-right' + | 'light-speed-out-left' + | 'light-speed-out-right' + | 'flip' + | 'flip-in-x' + | 'flip-in-y' + | 'flip-out-x' + | 'flip-out-y' + | 'rotate-in' + | 'rotate-in-down-left' + | 'rotate-in-down-right' + | 'rotate-in-up-left' + | 'rotate-in-up-right' + | 'rotate-out' + | 'rotate-out-down-left' + | 'rotate-out-down-right' + | 'rotate-out-up-left' + | 'rotate-out-up-right' + | 'roll-in' + | 'roll-out' + | 'zoom-in' + | 'zoom-in-down' + | 'zoom-in-left' + | 'zoom-in-right' + | 'zoom-in-up' + | 'zoom-out' + | 'zoom-out-down' + | 'zoom-out-left' + | 'zoom-out-right' + | 'zoom-out-up' + | 'bounce-in' + | 'bounce-in-down' + | 'bounce-in-left' + | 'bounce-in-right' + | 'bounce-in-up' + | 'bounce-out' + | 'bounce-out-down' + | 'bounce-out-left' + | 'bounce-out-right' + | 'bounce-out-up' + | 'slide-in-down' + | 'slide-in-left' + | 'slide-in-right' + | 'slide-in-up' + | 'slide-out-down' + | 'slide-out-left' + | 'slide-out-right' + | 'slide-out-up' + | 'fade-in' + | 'fade-in-down' + | 'fade-in-down-big' + | 'fade-in-left' + | 'fade-in-left-big' + | 'fade-in-right' + | 'fade-in-right-big' + | 'fade-in-up' + | 'fade-in-up-big' + | 'fade-in-top-left' + | 'fade-in-top-right' + | 'fade-in-bottom-left' + | 'fade-in-bottom-right' + | 'fade-out' + | 'fade-out-down' + | 'fade-out-down-big' + | 'fade-out-left' + | 'fade-out-left-big' + | 'fade-out-right' + | 'fade-out-right-big' + | 'fade-out-up' + | 'fade-out-up-big' + | 'fade-out-top-left' + | 'fade-out-top-right' + | 'fade-out-bottom-left' + | 'fade-out-bottom-right' + | 'back-in-up' + | 'back-in-down' + | 'back-in-right' + | 'back-in-left' + | 'back-out-up' + | 'back-out-down' + | 'back-out-right' + | 'back-out-left'; +} diff --git a/src/typings/vite-env.d.ts b/src/typings/vite-env.d.ts new file mode 100644 index 0000000..90c9fae --- /dev/null +++ b/src/typings/vite-env.d.ts @@ -0,0 +1,113 @@ +/** + * Namespace Env + * + * It is used to declare the type of the import.meta object + */ +declare namespace Env { + /** The router history mode */ + type RouterHistoryMode = 'hash' | 'history' | 'memory'; + + /** Interface for import.meta */ + interface ImportMeta extends ImportMetaEnv { + /** The base url of the application */ + readonly VITE_BASE_URL: string; + /** The title of the application */ + readonly VITE_APP_TITLE: string; + /** The description of the application */ + readonly VITE_APP_DESC: string; + /** The router history mode */ + readonly VITE_ROUTER_HISTORY_MODE?: RouterHistoryMode; + /** The prefix of the iconify icon */ + readonly VITE_ICON_PREFIX: 'icon'; + /** + * The prefix of the local icon + * + * This prefix is start with the icon prefix + */ + readonly VITE_ICON_LOCAL_PREFIX: 'local-icon'; + /** backend service base url */ + readonly VITE_SERVICE_BASE_URL: string; + /** + * success code of backend service + * + * when the code is received, the request is successful + */ + readonly VITE_SERVICE_SUCCESS_CODE: string; + /** + * logout codes of backend service + * + * when the code is received, the user will be logged out and redirected to login page + * + * use "," to separate multiple codes + */ + readonly VITE_SERVICE_LOGOUT_CODES: string; + /** + * modal logout codes of backend service + * + * when the code is received, the user will be logged out by displaying a modal + * + * use "," to separate multiple codes + */ + readonly VITE_SERVICE_MODAL_LOGOUT_CODES: string; + /** + * token expired codes of backend service + * + * when the code is received, it will refresh the token and resend the request + * + * use "," to separate multiple codes + */ + readonly VITE_SERVICE_EXPIRED_TOKEN_CODES: string; + /** when the route mode is static, the defined super role */ + readonly VITE_STATIC_SUPER_ROLE: string; + /** + * other backend service base url + * + * the value is a json + */ + readonly VITE_OTHER_SERVICE_BASE_URL: string; + /** + * Whether to enable the http proxy + * + * Only valid in the development environment + */ + readonly VITE_HTTP_PROXY?: CommonType.YesOrNo; + /** + * The auth route mode + * + * - Static: the auth routes is generated in front-end + * - Dynamic: the auth routes is generated in back-end + */ + readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic'; + /** + * The home route key + * + * It only has effect when the auth route mode is static, if the route mode is dynamic, the home route key is + * defined in the back-end + */ + readonly VITE_ROUTE_HOME: import('@elegant-router/types').LastLevelRouteKey; + /** + * Default menu icon if menu icon is not set + * + * Iconify icon name + */ + readonly VITE_MENU_ICON: string; + /** Whether to build with sourcemap */ + readonly VITE_SOURCE_MAP?: CommonType.YesOrNo; + /** + * Iconify api provider url + * + * If the project is deployed in intranet, you can set the api provider url to the local iconify server + * + * @link https://docs.iconify.design/api/providers.html + */ + readonly VITE_ICONIFY_URL?: string; + /** Used to differentiate storage across different domains */ + readonly VITE_STORAGE_PREFIX?: string; + /** Whether to automatically detect updates after configuring application packaging */ + readonly VITE_AUTOMATICALLY_DETECT_UPDATE?: CommonType.YesOrNo; + } +} + +interface ImportMeta { + readonly env: Env.ImportMeta; +} diff --git a/src/utils/agent.ts b/src/utils/agent.ts new file mode 100644 index 0000000..a8416b2 --- /dev/null +++ b/src/utils/agent.ts @@ -0,0 +1,7 @@ +export function isPC() { + const agents = ['Android', 'iPhone', 'webOS', 'BlackBerry', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']; + + const isMobile = agents.some(agent => window.navigator.userAgent.includes(agent)); + + return !isMobile; +} diff --git a/src/utils/common.ts b/src/utils/common.ts new file mode 100644 index 0000000..dc9a368 --- /dev/null +++ b/src/utils/common.ts @@ -0,0 +1,58 @@ +import { $t } from '@/locales'; + +/** + * Transform record to option + * + * @example + * ```ts + * const record = { + * key1: 'label1', + * key2: 'label2' + * }; + * const options = transformRecordToOption(record); + * // [ + * // { value: 'key1', label: 'label1' }, + * // { value: 'key2', label: 'label2' } + * // ] + * ```; + * + * @param record + */ +export function transformRecordToOption>(record: T) { + return Object.entries(record).map(([value, label]) => ({ + value, + label + })) as CommonType.Option[]; +} + +/** + * Translate options + * + * @param options + */ +export function translateOptions(options: CommonType.Option[]) { + return options.map(option => ({ + ...option, + label: $t(option.label as App.I18n.I18nKey) + })); +} + +/** + * Toggle html class + * + * @param className + */ +export function toggleHtmlClass(className: string) { + function add() { + document.documentElement.classList.add(className); + } + + function remove() { + document.documentElement.classList.remove(className); + } + + return { + add, + remove + }; +} diff --git a/src/utils/icon.ts b/src/utils/icon.ts new file mode 100644 index 0000000..2e18729 --- /dev/null +++ b/src/utils/icon.ts @@ -0,0 +1,9 @@ +export function getLocalIcons() { + const svgIcons = import.meta.glob('/src/assets/svg-icon/*.svg'); + + const keys = Object.keys(svgIcons) + .map(item => item.split('/').at(-1)?.replace('.svg', '') || '') + .filter(Boolean); + + return keys; +} diff --git a/src/utils/service.ts b/src/utils/service.ts new file mode 100644 index 0000000..a275b39 --- /dev/null +++ b/src/utils/service.ts @@ -0,0 +1,75 @@ +import json5 from 'json5'; + +/** + * Create service config by current env + * + * @param env The current env + */ +export function createServiceConfig(env: Env.ImportMeta) { + const { VITE_SERVICE_BASE_URL, VITE_OTHER_SERVICE_BASE_URL } = env; + + let other = {} as Record; + try { + other = json5.parse(VITE_OTHER_SERVICE_BASE_URL); + } catch { + // eslint-disable-next-line no-console + console.error('VITE_OTHER_SERVICE_BASE_URL is not a valid json5 string'); + } + + const httpConfig: App.Service.SimpleServiceConfig = { + baseURL: VITE_SERVICE_BASE_URL, + other + }; + + const otherHttpKeys = Object.keys(httpConfig.other) as App.Service.OtherBaseURLKey[]; + + const otherConfig: App.Service.OtherServiceConfigItem[] = otherHttpKeys.map(key => { + return { + key, + baseURL: httpConfig.other[key], + proxyPattern: createProxyPattern(key) + }; + }); + + const config: App.Service.ServiceConfig = { + baseURL: httpConfig.baseURL, + proxyPattern: createProxyPattern(), + other: otherConfig + }; + + return config; +} + +/** + * get backend service base url + * + * @param env - the current env + * @param isProxy - if use proxy + */ +export function getServiceBaseURL(env: Env.ImportMeta, isProxy: boolean) { + const { baseURL, other } = createServiceConfig(env); + + const otherBaseURL = {} as Record; + + other.forEach(item => { + otherBaseURL[item.key] = isProxy ? item.proxyPattern : item.baseURL; + }); + + return { + baseURL: isProxy ? createProxyPattern() : baseURL, + otherBaseURL + }; +} + +/** + * Get proxy pattern of backend service base url + * + * @param key If not set, will use the default key + */ +function createProxyPattern(key?: App.Service.OtherBaseURLKey) { + if (!key) { + return '/proxy-default'; + } + + return `/proxy-${key}`; +} diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..2ab44c2 --- /dev/null +++ b/src/utils/storage.ts @@ -0,0 +1,9 @@ +import { createLocalforage, createStorage } from '@sa/utils'; + +const storagePrefix = import.meta.env.VITE_STORAGE_PREFIX || ''; + +export const localStg = createStorage('local', storagePrefix); + +export const sessionStg = createStorage('session', storagePrefix); + +export const localforage = createLocalforage('local'); diff --git a/src/views/_builtin/403/index.vue b/src/views/_builtin/403/index.vue new file mode 100644 index 0000000..3c59ddf --- /dev/null +++ b/src/views/_builtin/403/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/_builtin/404/index.vue b/src/views/_builtin/404/index.vue new file mode 100644 index 0000000..4b4bf5b --- /dev/null +++ b/src/views/_builtin/404/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/_builtin/500/index.vue b/src/views/_builtin/500/index.vue new file mode 100644 index 0000000..0028cf2 --- /dev/null +++ b/src/views/_builtin/500/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/_builtin/iframe-page/[url].vue b/src/views/_builtin/iframe-page/[url].vue new file mode 100644 index 0000000..b28c952 --- /dev/null +++ b/src/views/_builtin/iframe-page/[url].vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/views/_builtin/login/index.vue b/src/views/_builtin/login/index.vue new file mode 100644 index 0000000..ac70bf8 --- /dev/null +++ b/src/views/_builtin/login/index.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/views/_builtin/login/modules/bind-wechat.vue b/src/views/_builtin/login/modules/bind-wechat.vue new file mode 100644 index 0000000..cb417bf --- /dev/null +++ b/src/views/_builtin/login/modules/bind-wechat.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/src/views/_builtin/login/modules/code-login.vue b/src/views/_builtin/login/modules/code-login.vue new file mode 100644 index 0000000..e6a6f0b --- /dev/null +++ b/src/views/_builtin/login/modules/code-login.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/views/_builtin/login/modules/pwd-login.vue b/src/views/_builtin/login/modules/pwd-login.vue new file mode 100644 index 0000000..6a8bada --- /dev/null +++ b/src/views/_builtin/login/modules/pwd-login.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/views/_builtin/login/modules/register.vue b/src/views/_builtin/login/modules/register.vue new file mode 100644 index 0000000..db9db76 --- /dev/null +++ b/src/views/_builtin/login/modules/register.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/views/_builtin/login/modules/reset-pwd.vue b/src/views/_builtin/login/modules/reset-pwd.vue new file mode 100644 index 0000000..6cbca57 --- /dev/null +++ b/src/views/_builtin/login/modules/reset-pwd.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/views/about/index.vue b/src/views/about/index.vue new file mode 100644 index 0000000..1160b9d --- /dev/null +++ b/src/views/about/index.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/views/function/hide-child/one/index.vue b/src/views/function/hide-child/one/index.vue new file mode 100644 index 0000000..2a654c5 --- /dev/null +++ b/src/views/function/hide-child/one/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/function/hide-child/three/index.vue b/src/views/function/hide-child/three/index.vue new file mode 100644 index 0000000..f9b42b4 --- /dev/null +++ b/src/views/function/hide-child/three/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/function/hide-child/two/index.vue b/src/views/function/hide-child/two/index.vue new file mode 100644 index 0000000..2fa26a8 --- /dev/null +++ b/src/views/function/hide-child/two/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/function/multi-tab/index.vue b/src/views/function/multi-tab/index.vue new file mode 100644 index 0000000..d26d727 --- /dev/null +++ b/src/views/function/multi-tab/index.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/src/views/function/request/index.vue b/src/views/function/request/index.vue new file mode 100644 index 0000000..e129ac8 --- /dev/null +++ b/src/views/function/request/index.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/views/function/super-page/index.vue b/src/views/function/super-page/index.vue new file mode 100644 index 0000000..2a654c5 --- /dev/null +++ b/src/views/function/super-page/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/function/tab/index.vue b/src/views/function/tab/index.vue new file mode 100644 index 0000000..0ffb2d4 --- /dev/null +++ b/src/views/function/tab/index.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/views/function/toggle-auth/index.vue b/src/views/function/toggle-auth/index.vue new file mode 100644 index 0000000..5eff1a0 --- /dev/null +++ b/src/views/function/toggle-auth/index.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/views/home/index.vue b/src/views/home/index.vue new file mode 100644 index 0000000..0c7da6b --- /dev/null +++ b/src/views/home/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/views/home/modules/card-data.vue b/src/views/home/modules/card-data.vue new file mode 100644 index 0000000..ba6a15a --- /dev/null +++ b/src/views/home/modules/card-data.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/src/views/home/modules/creativity-banner.vue b/src/views/home/modules/creativity-banner.vue new file mode 100644 index 0000000..36c0d62 --- /dev/null +++ b/src/views/home/modules/creativity-banner.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/src/views/home/modules/header-banner.vue b/src/views/home/modules/header-banner.vue new file mode 100644 index 0000000..8bab91c --- /dev/null +++ b/src/views/home/modules/header-banner.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/views/home/modules/line-chart.vue b/src/views/home/modules/line-chart.vue new file mode 100644 index 0000000..7cae56f --- /dev/null +++ b/src/views/home/modules/line-chart.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/src/views/home/modules/pie-chart.vue b/src/views/home/modules/pie-chart.vue new file mode 100644 index 0000000..6714f8a --- /dev/null +++ b/src/views/home/modules/pie-chart.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/src/views/home/modules/project-news.vue b/src/views/home/modules/project-news.vue new file mode 100644 index 0000000..212e3a0 --- /dev/null +++ b/src/views/home/modules/project-news.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/views/manage/menu/index.vue b/src/views/manage/menu/index.vue new file mode 100644 index 0000000..9e26850 --- /dev/null +++ b/src/views/manage/menu/index.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/src/views/manage/menu/modules/menu-operate-modal.vue b/src/views/manage/menu/modules/menu-operate-modal.vue new file mode 100644 index 0000000..65a54d5 --- /dev/null +++ b/src/views/manage/menu/modules/menu-operate-modal.vue @@ -0,0 +1,571 @@ + + + + + diff --git a/src/views/manage/menu/modules/shared.ts b/src/views/manage/menu/modules/shared.ts new file mode 100644 index 0000000..a8da693 --- /dev/null +++ b/src/views/manage/menu/modules/shared.ts @@ -0,0 +1,79 @@ +const LAYOUT_PREFIX = 'layout.'; +const VIEW_PREFIX = 'view.'; +const FIRST_LEVEL_ROUTE_COMPONENT_SPLIT = '$'; + +export function getLayoutAndPage(component?: string | null) { + let layout = ''; + let page = ''; + + const [layoutOrPage = '', pageItem = ''] = component?.split(FIRST_LEVEL_ROUTE_COMPONENT_SPLIT) || []; + + layout = getLayout(layoutOrPage); + page = getPage(pageItem || layoutOrPage); + + return { layout, page }; +} + +function getLayout(layout: string) { + return layout.startsWith(LAYOUT_PREFIX) ? layout.replace(LAYOUT_PREFIX, '') : ''; +} + +function getPage(page: string) { + return page.startsWith(VIEW_PREFIX) ? page.replace(VIEW_PREFIX, '') : ''; +} + +export function transformLayoutAndPageToComponent(layout: string, page: string) { + const hasLayout = Boolean(layout); + const hasPage = Boolean(page); + + if (hasLayout && hasPage) { + return `${LAYOUT_PREFIX}${layout}${FIRST_LEVEL_ROUTE_COMPONENT_SPLIT}${VIEW_PREFIX}${page}`; + } + + if (hasLayout) { + return `${LAYOUT_PREFIX}${layout}`; + } + + if (hasPage) { + return `${VIEW_PREFIX}${page}`; + } + + return ''; +} + +/** + * Get route name by route path + * + * @param routeName + */ +export function getRoutePathByRouteName(routeName: string) { + return `/${routeName.replace(/_/g, '/')}`; +} + +/** + * Get path param from route path + * + * @param routePath route path + */ +export function getPathParamFromRoutePath(routePath: string) { + const [path, param = ''] = routePath.split('/:'); + + return { + path, + param + }; +} + +/** + * Get route path with param + * + * @param routePath route path + * @param param path param + */ +export function getRoutePathWithParam(routePath: string, param: string) { + if (param.trim()) { + return `${routePath}/:${param}`; + } + + return routePath; +} diff --git a/src/views/manage/role/index.vue b/src/views/manage/role/index.vue new file mode 100644 index 0000000..2061a9b --- /dev/null +++ b/src/views/manage/role/index.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/src/views/manage/role/modules/button-auth-modal.vue b/src/views/manage/role/modules/button-auth-modal.vue new file mode 100644 index 0000000..8cf6551 --- /dev/null +++ b/src/views/manage/role/modules/button-auth-modal.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/views/manage/role/modules/menu-auth-modal.vue b/src/views/manage/role/modules/menu-auth-modal.vue new file mode 100644 index 0000000..36cb811 --- /dev/null +++ b/src/views/manage/role/modules/menu-auth-modal.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/src/views/manage/role/modules/role-operate-drawer.vue b/src/views/manage/role/modules/role-operate-drawer.vue new file mode 100644 index 0000000..3b02422 --- /dev/null +++ b/src/views/manage/role/modules/role-operate-drawer.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/src/views/manage/role/modules/role-search.vue b/src/views/manage/role/modules/role-search.vue new file mode 100644 index 0000000..369b631 --- /dev/null +++ b/src/views/manage/role/modules/role-search.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/views/manage/user-detail/[id].vue b/src/views/manage/user-detail/[id].vue new file mode 100644 index 0000000..c7f6751 --- /dev/null +++ b/src/views/manage/user-detail/[id].vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/manage/user/index.vue b/src/views/manage/user/index.vue new file mode 100644 index 0000000..7d25717 --- /dev/null +++ b/src/views/manage/user/index.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/src/views/manage/user/modules/user-operate-drawer.vue b/src/views/manage/user/modules/user-operate-drawer.vue new file mode 100644 index 0000000..b64be8d --- /dev/null +++ b/src/views/manage/user/modules/user-operate-drawer.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/src/views/manage/user/modules/user-search.vue b/src/views/manage/user/modules/user-search.vue new file mode 100644 index 0000000..fb70aec --- /dev/null +++ b/src/views/manage/user/modules/user-search.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/views/multi-menu/first_child/index.vue b/src/views/multi-menu/first_child/index.vue new file mode 100644 index 0000000..2a654c5 --- /dev/null +++ b/src/views/multi-menu/first_child/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/multi-menu/second_child_home/index.vue b/src/views/multi-menu/second_child_home/index.vue new file mode 100644 index 0000000..2a654c5 --- /dev/null +++ b/src/views/multi-menu/second_child_home/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/user-center/index.vue b/src/views/user-center/index.vue new file mode 100644 index 0000000..2a654c5 --- /dev/null +++ b/src/views/user-center/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..362dbb8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ESNext", + "jsx": "preserve", + "jsxImportSource": "vue", + "lib": ["DOM", "ESNext"], + "baseUrl": ".", + "module": "ESNext", + "moduleResolution": "node", + "paths": { + "@/*": ["./src/*"], + "~/*": ["./*"] + }, + "resolveJsonModule": true, + "types": ["vite/client", "node", "unplugin-icons/types/vue", "ant-design-vue/typings/global.d.ts"], + "strict": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true + }, + "include": ["./**/*.ts", "./**/*.tsx", "./**/*.vue"], + "exclude": ["node_modules", "dist"] +} diff --git a/uno.config.ts b/uno.config.ts new file mode 100644 index 0000000..2f86f99 --- /dev/null +++ b/uno.config.ts @@ -0,0 +1,30 @@ +import { defineConfig } from '@unocss/vite'; +import transformerDirectives from '@unocss/transformer-directives'; +import transformerVariantGroup from '@unocss/transformer-variant-group'; +import presetUno from '@unocss/preset-uno'; +import type { Theme } from '@unocss/preset-uno'; +import { presetSoybeanAdmin } from '@sa/uno-preset'; +import { themeVars } from './src/theme/vars'; + +export default defineConfig({ + content: { + pipeline: { + exclude: ['node_modules', 'dist'] + } + }, + theme: { + ...themeVars, + fontSize: { + 'icon-xs': '0.875rem', + 'icon-small': '1rem', + icon: '1.125rem', + 'icon-large': '1.5rem', + 'icon-xl': '2rem' + } + }, + shortcuts: { + 'card-wrapper': 'rd-8px shadow-sm' + }, + transformers: [transformerDirectives(), transformerVariantGroup()], + presets: [presetUno({ dark: 'class' }), presetSoybeanAdmin()] +}); diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..45c2f97 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,51 @@ +import process from 'node:process'; +import { URL, fileURLToPath } from 'node:url'; +import { defineConfig, loadEnv } from 'vite'; +import { setupVitePlugins } from './build/plugins'; +import { createViteProxy, getBuildTime } from './build/config'; + +export default defineConfig(configEnv => { + const viteEnv = loadEnv(configEnv.mode, process.cwd()) as unknown as Env.ImportMeta; + + const buildTime = getBuildTime(); + + const enableProxy = configEnv.command === 'serve' && !configEnv.isPreview; + + return { + base: viteEnv.VITE_BASE_URL, + resolve: { + alias: { + '~': fileURLToPath(new URL('./', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + css: { + preprocessorOptions: { + scss: { + api: 'modern-compiler', + additionalData: `@use "@/styles/scss/global.scss" as *;` + } + } + }, + plugins: setupVitePlugins(viteEnv, buildTime), + define: { + BUILD_TIME: JSON.stringify(buildTime) + }, + server: { + host: '0.0.0.0', + port: 9527, + open: true, + proxy: createViteProxy(viteEnv, enableProxy) + }, + preview: { + port: 9725 + }, + build: { + reportCompressedSize: false, + sourcemap: viteEnv.VITE_SOURCE_MAP === 'Y', + commonjsOptions: { + ignoreTryCatch: false + } + } + }; +});