├── .eslintignore ├── src ├── styles │ ├── scss │ │ ├── global.scss │ │ └── scrollbar.scss │ └── css │ │ ├── global.css │ │ ├── scrollbar.css │ │ ├── transition.css │ │ └── reset.css ├── plugins │ ├── index.ts │ └── assets.ts ├── views │ ├── HomeView.vue │ └── AboutView.vue ├── stores │ ├── index.ts │ └── counter.ts ├── assets │ ├── logo.svg │ └── base.css ├── components │ ├── icons │ │ ├── IconSupport.vue │ │ ├── IconTooling.vue │ │ ├── IconCommunity.vue │ │ ├── IconDocumentation.vue │ │ └── IconEcosystem.vue │ ├── HelloWorld.vue │ ├── WelcomeItem.vue │ └── TheWelcome.vue ├── main.ts ├── router │ └── index.ts ├── App.vue └── typings │ └── components.d.ts ├── commitlint.config.js ├── public └── favicon.ico ├── .husky ├── commit-msg └── pre-commit ├── .npmrc ├── .editorconfig ├── README.md ├── .gitattributes ├── index.html ├── .gitignore ├── tsconfig.json ├── .vscode ├── extensions.json └── settings.json ├── vite.config.ts ├── package.json ├── .cz-config.js ├── uno.config.ts └── .eslintrc.js /.eslintignore: -------------------------------------------------------------------------------- 1 | components.d.ts 2 | -------------------------------------------------------------------------------- /src/styles/scss/global.scss: -------------------------------------------------------------------------------- 1 | @import './scrollbar.scss'; 2 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /src/plugins/index.ts: -------------------------------------------------------------------------------- 1 | import setupAssets from './assets'; 2 | 3 | export { setupAssets }; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soybeanjs/vite-vue3-ts-starter/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run lint && npm run typecheck 5 | -------------------------------------------------------------------------------- /src/styles/css/global.css: -------------------------------------------------------------------------------- 1 | @import './transition.css'; 2 | @import './reset.css'; 3 | 4 | html, body, #app { 5 | height: 100%; 6 | } 7 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmmirror.com/ 2 | shamefully-hoist=true 3 | strict-peer-dependencies=false 4 | auto-install-peers=true 5 | -------------------------------------------------------------------------------- /src/plugins/assets.ts: -------------------------------------------------------------------------------- 1 | import 'uno.css'; 2 | 3 | /** import assets, such as js, css files. */ 4 | export default function setupAssets() { 5 | // 6 | } 7 | -------------------------------------------------------------------------------- /src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /src/stores/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue'; 2 | import { createPinia } from 'pinia'; 3 | 4 | export function setupStore(app: App) { 5 | const store = createPinia(); 6 | app.use(store); 7 | } 8 | 9 | export * from './counter'; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = tab 8 | indent_size = 2 9 | end_of_line = lf 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-vue3-ts-starter 2 | 3 | This template is based on the template created by create-vue, which add eslint、prettier、husky、commitlint to format code. 4 | 5 | on branch unit-test, which has unit test tool vitest. 6 | 7 | on branch unocss, which has atomic css tool. 8 | -------------------------------------------------------------------------------- /src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export const useCounterStore = defineStore({ 4 | id: 'counter', 5 | state: () => ({ 6 | counter: 0 7 | }), 8 | getters: { 9 | doubleCount: state => state.counter * 2 10 | }, 11 | actions: { 12 | increment() { 13 | this.counter += 1; 14 | } 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | "*.vue" eol=lf 2 | "*.js" eol=lf 3 | "*.ts" eol=lf 4 | "*.jsx" eol=lf 5 | "*.tsx" eol=lf 6 | "*.cjs" eol=lf 7 | "*.cts" eol=lf 8 | "*.mjs" eol=lf 9 | "*.mts" eol=lf 10 | "*.json" eol=lf 11 | "*.html" eol=lf 12 | "*.css" eol=lf 13 | "*.less" eol=lf 14 | "*.scss" eol=lf 15 | "*.sass" eol=lf 16 | "*.styl" eol=lf 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | vite-vue3-ts-starter 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | !.vscode/settings.json 24 | .idea 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | -------------------------------------------------------------------------------- /src/styles/scss/scrollbar.scss: -------------------------------------------------------------------------------- 1 | @mixin scrollbar($size:8px, $color:#d9d9d9) { 2 | &::-webkit-scrollbar-thumb { 3 | background-color: $color; 4 | border-radius: $size; 5 | } 6 | &::-webkit-scrollbar-thumb:hover { 7 | background-color: $color; 8 | border-radius: $size; 9 | } 10 | &::-webkit-scrollbar { 11 | width: $size; 12 | height: $size; 13 | } 14 | &::-webkit-scrollbar-track-piece { 15 | background-color: rgba(0, 0, 0, 0); 16 | border-radius: 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import { setupAssets } from './plugins'; 3 | import { setupStore } from './stores'; 4 | import { setupRouter } from './router'; 5 | import App from './App.vue'; 6 | 7 | async function setupApp() { 8 | // import assets: js、css 9 | setupAssets(); 10 | 11 | // create app instance 12 | const app = createApp(App); 13 | 14 | // install store plugin: pinia 15 | setupStore(app); 16 | 17 | // vue router 18 | await setupRouter(app); 19 | 20 | // mount app on the dom 21 | app.mount('#app'); 22 | } 23 | 24 | setupApp(); 25 | -------------------------------------------------------------------------------- /src/styles/css/scrollbar.css: -------------------------------------------------------------------------------- 1 | /*---滚动条默认显示样式--*/ 2 | ::-webkit-scrollbar-thumb { 3 | background-color: #e6e6e6; 4 | border-radius: 6px; 5 | } 6 | /*---鼠标点击滚动条显示样式--*/ 7 | ::-webkit-scrollbar-thumb:hover { 8 | background-color: #e6e6e6; 9 | border-radius: 6px; 10 | } 11 | /*---滚动条大小--*/ 12 | ::-webkit-scrollbar { 13 | width: 6px; 14 | height: 6px; 15 | } 16 | 17 | /*---滚动框背景样式--*/ 18 | ::-webkit-scrollbar-track-piece { 19 | background-color: rgba(0, 0, 0, 0); 20 | border-radius: 0; 21 | } 22 | 23 | html { 24 | scrollbar-width: thin; 25 | scrollbar-color: e6e6e6 transparent; 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "ESNext", 5 | "target": "ESNext", 6 | "lib": ["DOM", "ESNext"], 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "jsx": "preserve", 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "noUnusedLocals": true, 14 | "strictNullChecks": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "paths": { 17 | "~/*": ["./*"], 18 | "@/*": ["./src/*"] 19 | }, 20 | "types": ["node", "vite/client"] 21 | }, 22 | "exclude": ["node_modules", "dist"] 23 | } 24 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue'; 2 | import { createRouter, createWebHistory } from 'vue-router'; 3 | import HomeView from '../views/HomeView.vue'; 4 | 5 | const router = createRouter({ 6 | history: createWebHistory(import.meta.env.BASE_URL), 7 | routes: [ 8 | { 9 | path: '/', 10 | name: 'home', 11 | component: HomeView 12 | }, 13 | { 14 | path: '/about', 15 | name: 'about', 16 | component: () => import('../views/AboutView.vue') 17 | } 18 | ] 19 | }); 20 | 21 | export async function setupRouter(app: App) { 22 | app.use(router); 23 | // 路由守卫createRouterGuard(router); 24 | await router.isReady(); 25 | } 26 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "afzalsayed96.icones", 4 | "antfu.iconify", 5 | "antfu.unocss", 6 | "christian-kohler.path-intellisense", 7 | "dbaeumer.vscode-eslint", 8 | "eamodio.gitlens", 9 | "editorconfig.editorconfig", 10 | "esbenp.prettier-vscode", 11 | "formulahendry.auto-complete-tag", 12 | "formulahendry.auto-close-tag", 13 | "formulahendry.auto-rename-tag", 14 | "kisstkondoros.vscode-gutter-preview", 15 | "lokalise.i18n-ally", 16 | "mhutchie.git-graph", 17 | "mikestead.dotenv", 18 | "naumovs.color-highlight", 19 | "pkief.material-icon-theme", 20 | "steoates.autoimport", 21 | "vue.volar", 22 | "whtouche.vscode-js-console-utils", 23 | "zhuangtongfa.material-theme" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 11 | 19 | 42 | -------------------------------------------------------------------------------- /src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/typings/components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/core/pull/3399 4 | import '@vue/runtime-core' 5 | 6 | export {} 7 | 8 | declare module '@vue/runtime-core' { 9 | export interface GlobalComponents { 10 | HelloWorld: typeof import('./../components/HelloWorld.vue')['default'] 11 | IconCommunity: typeof import('./../components/icons/IconCommunity.vue')['default'] 12 | IconDocumentation: typeof import('./../components/icons/IconDocumentation.vue')['default'] 13 | IconEcosystem: typeof import('./../components/icons/IconEcosystem.vue')['default'] 14 | IconSupport: typeof import('./../components/icons/IconSupport.vue')['default'] 15 | IconTooling: typeof import('./../components/icons/IconTooling.vue')['default'] 16 | RouterLink: typeof import('vue-router')['RouterLink'] 17 | RouterView: typeof import('vue-router')['RouterView'] 18 | TheWelcome: typeof import('./../components/TheWelcome.vue')['default'] 19 | WelcomeItem: typeof import('./../components/WelcomeItem.vue')['default'] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { defineConfig } from 'vite'; 3 | import vue from '@vitejs/plugin-vue'; 4 | import vueJsx from '@vitejs/plugin-vue-jsx'; 5 | import Components from 'unplugin-vue-components/vite'; 6 | import unocss from 'unocss/vite'; 7 | 8 | export default defineConfig(() => { 9 | const rootPath = path.resolve(process.cwd()); 10 | const srcPath = `${rootPath}/src`; 11 | 12 | return { 13 | resolve: { 14 | alias: { 15 | '~': rootPath, 16 | '@': srcPath 17 | } 18 | }, 19 | css: { 20 | preprocessorOptions: { 21 | scss: { 22 | additionalData: `@use "./src/styles/scss/global.scss" as *;` 23 | } 24 | } 25 | }, 26 | plugins: [ 27 | vue(), 28 | vueJsx(), 29 | Components({ 30 | dts: 'src/typings/components.d.ts', 31 | types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }] 32 | }), 33 | unocss() 34 | ], 35 | server: { 36 | host: '0.0.0.0', 37 | open: true 38 | }, 39 | build: { 40 | brotliSize: false, 41 | sourcemap: false, 42 | commonjsOptions: { 43 | ignoreTryCatch: false 44 | } 45 | } 46 | }; 47 | }); 48 | -------------------------------------------------------------------------------- /src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue3-ts-starter", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "npm run typecheck && vite build", 7 | "preview": "vite preview", 8 | "typecheck": "vue-tsc --noEmit --skipLibCheck", 9 | "lint": "eslint . --fix", 10 | "commit": "pnpm cz", 11 | "prepare": "husky install" 12 | }, 13 | "dependencies": { 14 | "pinia": "^2.0.23", 15 | "vue": "^3.2.41", 16 | "vue-router": "^4.1.6" 17 | }, 18 | "devDependencies": { 19 | "@commitlint/cli": "^17.1.2", 20 | "@commitlint/config-conventional": "^17.1.0", 21 | "@types/node": "18.8.0", 22 | "@vitejs/plugin-vue": "^3.1.2", 23 | "@vitejs/plugin-vue-jsx": "^2.0.1", 24 | "commitizen": "^4.2.5", 25 | "cz-conventional-changelog": "^3.3.0", 26 | "cz-customizable": "^7.0.0", 27 | "eslint": "^8.26.0", 28 | "eslint-config-soybeanjs-vue": "^0.1.1", 29 | "husky": "^8.0.1", 30 | "lint-staged": "^13.0.3", 31 | "sass": "^1.55.0", 32 | "typescript": "^4.8.4", 33 | "unocss": "^0.45.30", 34 | "unplugin-vue-components": "^0.22.9", 35 | "vite": "^3.1.8", 36 | "vue-tsc": "^1.0.9" 37 | }, 38 | "lint-staged": { 39 | "*.{vue,js,jsx,ts,tsx,json}": "eslint --fix" 40 | }, 41 | "config": { 42 | "commitizen": { 43 | "path": "./node_modules/cz-customizable" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.cz-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | types: [ 3 | { value: 'init', name: 'init: 项目初始化' }, 4 | { value: 'feat', name: 'feat: 添加新特性' }, 5 | { value: 'fix', name: 'fix: 修复bug' }, 6 | { value: 'docs', name: 'docs: 仅仅修改文档' }, 7 | { value: 'style', name: 'style: 仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑' }, 8 | { value: 'refactor', name: 'refactor: 代码重构,没有加新功能或者修复bug' }, 9 | { value: 'perf', name: 'perf: 优化相关,比如提升性能、体验' }, 10 | { value: 'test', name: 'test: 添加测试用例' }, 11 | { value: 'build', name: 'build: 依赖相关的内容' }, 12 | { value: 'ci', name: 'ci: CI配置相关,例如对k8s,docker的配置文件的修改' }, 13 | { value: 'chore', name: 'chore: 改变构建流程、或者增加依赖库、工具等' }, 14 | { value: 'revert', name: 'revert: 回滚到上一个版本' } 15 | ], 16 | scopes: [ 17 | ['projects', '项目搭建'], 18 | ['components', '组件相关'], 19 | ['hooks', 'hook 相关'], 20 | ['utils', 'utils 相关'], 21 | ['types', 'ts类型相关'], 22 | ['styles', '样式相关'], 23 | ['deps', '项目依赖'], 24 | ['auth', '对 auth 修改'], 25 | ['other', '其他修改'], 26 | ['custom', '以上都不是?我要自定义'] 27 | ].map(([value, description]) => { 28 | return { 29 | value, 30 | name: `${value.padEnd(30)} (${description})` 31 | } 32 | }), 33 | messages: { 34 | type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型:', 35 | scope: '\n选择一个 scope(可选):', 36 | customScope: '请输入自定义的 scope:', 37 | subject: '填写简短精炼的变更描述:\n', 38 | body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n', 39 | breaking: '列举非兼容性重大的变更(可选):\n', 40 | footer: '列举出所有变更的 ISSUES CLOSED(可选)。 例如: #31, #34:\n', 41 | confirmCommit: '确认提交?' 42 | }, 43 | allowBreakingChanges: ['feat', 'fix'], 44 | subjectLimit: 100, 45 | breaklineChar: '|' 46 | } 47 | -------------------------------------------------------------------------------- /src/styles/css/transition.css: -------------------------------------------------------------------------------- 1 | /* fade */ 2 | .fade-enter-active, 3 | .fade-leave-active { 4 | transition: opacity 0.3s ease-in-out; 5 | } 6 | .fade-enter-from, 7 | .fade-leave-to { 8 | opacity: 0; 9 | } 10 | 11 | /* fade-slide */ 12 | .fade-slide-leave-active, 13 | .fade-slide-enter-active { 14 | transition: all 0.3s; 15 | } 16 | .fade-slide-enter-from { 17 | opacity: 0; 18 | transform: translateX(-30px); 19 | } 20 | .fade-slide-leave-to { 21 | opacity: 0; 22 | transform: translateX(30px); 23 | } 24 | 25 | /* fade-bottom */ 26 | .fade-bottom-enter-active, 27 | .fade-bottom-leave-active { 28 | transition: opacity 0.25s, transform 0.3s; 29 | } 30 | .fade-bottom-enter-from { 31 | opacity: 0; 32 | transform: translateY(-10%); 33 | } 34 | .fade-bottom-leave-to { 35 | opacity: 0; 36 | transform: translateY(10%); 37 | } 38 | 39 | /* fade-scale */ 40 | .fade-scale-leave-active, 41 | .fade-scale-enter-active { 42 | transition: all 0.28s; 43 | } 44 | .fade-scale-enter-from { 45 | opacity: 0; 46 | transform: scale(1.2); 47 | } 48 | .fade-scale-leave-to { 49 | opacity: 0; 50 | transform: scale(0.8); 51 | } 52 | 53 | /* zoom-fade */ 54 | .zoom-fade-enter-active, 55 | .zoom-fade-leave-active { 56 | transition: transform 0.2s, opacity 0.3s ease-out; 57 | } 58 | .zoom-fade-enter-from { 59 | opacity: 0; 60 | transform: scale(0.92); 61 | } 62 | .zoom-fade-leave-to { 63 | opacity: 0; 64 | transform: scale(1.06); 65 | } 66 | 67 | /* zoom-out */ 68 | .zoom-out-enter-active, 69 | .zoom-out-leave-active { 70 | transition: opacity 0.1s ease-in-out, transform 0.15s ease-out; 71 | } 72 | .zoom-out-enter-from, 73 | .zoom-out-leave-to { 74 | opacity: 0; 75 | transform: scale(0); 76 | } 77 | -------------------------------------------------------------------------------- /src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 86 | -------------------------------------------------------------------------------- /uno.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, presetUno } from 'unocss'; 2 | 3 | export default defineConfig({ 4 | exclude: ['node_modules', '.git', '.husky', '.vscode', 'dist', 'public', 'build', 'mock', './stats.html'], 5 | presets: [presetUno({ dark: 'class' })], 6 | shortcuts: { 7 | 'wh-full': 'w-full h-full', 8 | 'flex-center': 'flex justify-center items-center', 9 | 'flex-col-center': 'flex-center flex-col', 10 | 'flex-x-center': 'flex justify-center', 11 | 'flex-y-center': 'flex items-center', 12 | 'i-flex-center': 'inline-flex justify-center items-center', 13 | 'i-flex-x-center': 'inline-flex justify-center', 14 | 'i-flex-y-center': 'inline-flex items-center', 15 | 'flex-col': 'flex flex-col', 16 | 'flex-col-stretch': 'flex-col items-stretch', 17 | 'i-flex-col': 'inline-flex flex-col', 18 | 'i-flex-col-stretch': 'i-flex-col items-stretch', 19 | 'flex-1-hidden': 'flex-1 overflow-hidden', 20 | 'absolute-lt': 'absolute left-0 top-0', 21 | 'absolute-lb': 'absolute left-0 bottom-0', 22 | 'absolute-rt': 'absolute right-0 top-0', 23 | 'absolute-rb': 'absolute right-0 bottom-0', 24 | 'absolute-tl': 'absolute-lt', 25 | 'absolute-tr': 'absolute-rt', 26 | 'absolute-bl': 'absolute-lb', 27 | 'absolute-br': 'absolute-rb', 28 | 'absolute-center': 'absolute-lt flex-center wh-full', 29 | 'fixed-lt': 'fixed left-0 top-0', 30 | 'fixed-lb': 'fixed left-0 bottom-0', 31 | 'fixed-rt': 'fixed right-0 top-0', 32 | 'fixed-rb': 'fixed right-0 bottom-0', 33 | 'fixed-tl': 'fixed-lt', 34 | 'fixed-tr': 'fixed-rt', 35 | 'fixed-bl': 'fixed-lb', 36 | 'fixed-br': 'fixed-rb', 37 | 'fixed-center': 'fixed-lt flex-center wh-full', 38 | 'nowrap-hidden': 'whitespace-nowrap overflow-hidden', 39 | 'ellipsis-text': 'nowrap-hidden overflow-ellipsis', 40 | 'transition-base': 'transition-all duration-300 ease-in-out' 41 | } 42 | }); 43 | -------------------------------------------------------------------------------- /src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | position: relative; 59 | font-weight: normal; 60 | } 61 | 62 | body { 63 | min-height: 100vh; 64 | color: var(--color-text); 65 | background: var(--color-background); 66 | transition: color 0.5s, background-color 0.5s; 67 | line-height: 1.6; 68 | font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 69 | Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 70 | font-size: 15px; 71 | text-rendering: optimizeLegibility; 72 | -webkit-font-smoothing: antialiased; 73 | -moz-osx-font-smoothing: grayscale; 74 | } 75 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | }, 5 | "editor.fontLigatures": true, 6 | "editor.formatOnSave": false, 7 | "editor.guides.bracketPairs": "active", 8 | "editor.quickSuggestions": { 9 | "strings": true 10 | }, 11 | "editor.tabSize": 2, 12 | "eslint.alwaysShowStatus": true, 13 | "eslint.validate": [ 14 | "javascript", 15 | "javascriptreact", 16 | "typescript", 17 | "typescriptreact", 18 | "vue", 19 | "html", 20 | "json", 21 | "jsonc", 22 | "json5", 23 | "yaml", 24 | "yml", 25 | "markdown" 26 | ], 27 | "files.associations": { 28 | "*.env.*": "dotenv" 29 | }, 30 | "files.eol": "\n", 31 | "git.enableSmartCommit": true, 32 | "gutterpreview.paths": { 33 | "@": "/src", 34 | "~@": "/src" 35 | }, 36 | "material-icon-theme.activeIconPack": "angular", 37 | "material-icon-theme.files.associations": {}, 38 | "material-icon-theme.folders.associations": { 39 | "src-tauri": "src", 40 | "enum": "typescript", 41 | "enums": "typescript", 42 | "store": "context", 43 | "stores": "context", 44 | "composable": "hook", 45 | "composables": "hook", 46 | "directive": "tools", 47 | "directives": "tools", 48 | "business": "core", 49 | "request": "api", 50 | "adapter": "middleware" 51 | }, 52 | "path-intellisense.mappings": { 53 | "@": "${workspaceFolder}/src", 54 | "~@": "${workspaceFolder}/src" 55 | }, 56 | "terminal.integrated.cursorStyle": "line", 57 | "terminal.integrated.fontSize": 14, 58 | "terminal.integrated.fontWeight": 500, 59 | "terminal.integrated.tabs.enabled": true, 60 | "workbench.iconTheme": "material-icon-theme", 61 | "workbench.colorTheme": "One Dark Pro", 62 | "[html]": { 63 | "editor.defaultFormatter": "esbenp.prettier-vscode" 64 | }, 65 | "[json]": { 66 | "editor.defaultFormatter": "esbenp.prettier-vscode" 67 | }, 68 | "[jsonc]": { 69 | "editor.defaultFormatter": "esbenp.prettier-vscode" 70 | }, 71 | "[javascript]": { 72 | "editor.defaultFormatter": "esbenp.prettier-vscode" 73 | }, 74 | "[javascriptreact]": { 75 | "editor.defaultFormatter": "esbenp.prettier-vscode" 76 | }, 77 | "[markdown]": { 78 | "editor.defaultFormatter": "yzhang.markdown-all-in-one" 79 | }, 80 | "[typescript]": { 81 | "editor.defaultFormatter": "esbenp.prettier-vscode" 82 | }, 83 | "[typescriptreact]": { 84 | "editor.defaultFormatter": "esbenp.prettier-vscode" 85 | }, 86 | "[vue]": { 87 | "editor.defaultFormatter": "Vue.volar" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/components/TheWelcome.vue: -------------------------------------------------------------------------------- 1 | 72 | 80 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['soybeanjs-vue'], 3 | settings: { 4 | 'import/core-modules': ['uno.css', '~icons/*', 'virtual:svg-icons-register'] 5 | }, 6 | rules: { 7 | 'import/order': [ 8 | 'error', 9 | { 10 | 'newlines-between': 'never', 11 | groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], 12 | pathGroups: [ 13 | { 14 | pattern: 'vue', 15 | group: 'external', 16 | position: 'before' 17 | }, 18 | { 19 | pattern: 'vue-router', 20 | group: 'external', 21 | position: 'before' 22 | }, 23 | { 24 | pattern: 'pinia', 25 | group: 'external', 26 | position: 'before' 27 | }, 28 | { 29 | pattern: 'naive-ui', 30 | group: 'external', 31 | position: 'before' 32 | }, 33 | { 34 | pattern: '@/config', 35 | group: 'internal', 36 | position: 'before' 37 | }, 38 | { 39 | pattern: '@/settings', 40 | group: 'internal', 41 | position: 'before' 42 | }, 43 | { 44 | pattern: '@/enum', 45 | group: 'internal', 46 | position: 'before' 47 | }, 48 | { 49 | pattern: '@/plugins', 50 | group: 'internal', 51 | position: 'before' 52 | }, 53 | { 54 | pattern: '@/layouts', 55 | group: 'internal', 56 | position: 'before' 57 | }, 58 | { 59 | pattern: '@/views', 60 | group: 'internal', 61 | position: 'before' 62 | }, 63 | { 64 | pattern: '@/components', 65 | group: 'internal', 66 | position: 'before' 67 | }, 68 | { 69 | pattern: '@/router', 70 | group: 'internal', 71 | position: 'before' 72 | }, 73 | { 74 | pattern: '@/service', 75 | group: 'internal', 76 | position: 'before' 77 | }, 78 | { 79 | pattern: '@/store', 80 | group: 'internal', 81 | position: 'before' 82 | }, 83 | { 84 | pattern: '@/context', 85 | group: 'internal', 86 | position: 'before' 87 | }, 88 | { 89 | pattern: '@/composables', 90 | group: 'internal', 91 | position: 'before' 92 | }, 93 | { 94 | pattern: '@/hooks', 95 | group: 'internal', 96 | position: 'before' 97 | }, 98 | { 99 | pattern: '@/utils', 100 | group: 'internal', 101 | position: 'before' 102 | }, 103 | { 104 | pattern: '@/assets', 105 | group: 'internal', 106 | position: 'before' 107 | }, 108 | { 109 | pattern: '@/**', 110 | group: 'internal', 111 | position: 'before' 112 | } 113 | ], 114 | pathGroupsExcludedImportTypes: ['vue', 'vue-router', 'pinia', 'naive-ui'] 115 | } 116 | ] 117 | } 118 | }; 119 | -------------------------------------------------------------------------------- /src/styles/css/reset.css: -------------------------------------------------------------------------------- 1 | /* 2 | 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) 3 | 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) 4 | */ 5 | 6 | *, 7 | ::before, 8 | ::after { 9 | box-sizing: border-box; /* 1 */ 10 | border-width: 0; /* 2 */ 11 | border-style: solid; /* 2 */ 12 | border-color: currentColor; /* 2 */ 13 | } 14 | 15 | /* 16 | 1. Use a consistent sensible line-height in all browsers. 17 | 2. Prevent adjustments of font size after orientation changes in iOS. 18 | 3. Use a more readable tab size. 19 | 4. Use the user's configured `sans` font-family by default. 20 | */ 21 | 22 | html { 23 | line-height: 1.5; /* 1 */ 24 | -webkit-text-size-adjust: 100%; /* 2 */ 25 | -moz-tab-size: 4; /* 3 */ 26 | tab-size: 4; /* 3 */ 27 | 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 */ 28 | } 29 | 30 | /* 31 | 1. Remove the margin in all browsers. 32 | 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. 33 | */ 34 | 35 | body { 36 | margin: 0; /* 1 */ 37 | line-height: inherit; /* 2 */ 38 | } 39 | 40 | /* 41 | 1. Add the correct height in Firefox. 42 | 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) 43 | 3. Ensure horizontal rules are visible by default. 44 | */ 45 | 46 | hr { 47 | height: 0; /* 1 */ 48 | color: inherit; /* 2 */ 49 | border-top-width: 1px; /* 3 */ 50 | } 51 | 52 | /* 53 | Add the correct text decoration in Chrome, Edge, and Safari. 54 | */ 55 | 56 | abbr:where([title]) { 57 | text-decoration: underline dotted; 58 | } 59 | 60 | /* 61 | Remove the default font size and weight for headings. 62 | */ 63 | 64 | h1, 65 | h2, 66 | h3, 67 | h4, 68 | h5, 69 | h6 { 70 | font-size: inherit; 71 | font-weight: inherit; 72 | } 73 | 74 | /* 75 | Reset links to optimize for opt-in styling instead of opt-out. 76 | */ 77 | 78 | a { 79 | color: inherit; 80 | text-decoration: inherit; 81 | } 82 | 83 | /* 84 | Add the correct font weight in Edge and Safari. 85 | */ 86 | 87 | b, 88 | strong { 89 | font-weight: bolder; 90 | } 91 | 92 | /* 93 | 1. Use the user's configured `mono` font family by default. 94 | 2. Correct the odd `em` font sizing in all browsers. 95 | */ 96 | 97 | code, 98 | kbd, 99 | samp, 100 | pre { 101 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ 102 | font-size: 1em; /* 2 */ 103 | } 104 | 105 | /* 106 | Add the correct font size in all browsers. 107 | */ 108 | 109 | small { 110 | font-size: 80%; 111 | } 112 | 113 | /* 114 | Prevent `sub` and `sup` elements from affecting the line height in all browsers. 115 | */ 116 | 117 | sub, 118 | sup { 119 | font-size: 75%; 120 | line-height: 0; 121 | position: relative; 122 | vertical-align: baseline; 123 | } 124 | 125 | sub { 126 | bottom: -0.25em; 127 | } 128 | 129 | sup { 130 | top: -0.5em; 131 | } 132 | 133 | /* 134 | 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) 135 | 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) 136 | 3. Remove gaps between table borders by default. 137 | */ 138 | 139 | table { 140 | text-indent: 0; /* 1 */ 141 | border-color: inherit; /* 2 */ 142 | border-collapse: collapse; /* 3 */ 143 | } 144 | 145 | /* 146 | 1. Change the font styles in all browsers. 147 | 2. Remove the margin in Firefox and Safari. 148 | 3. Remove default padding in all browsers. 149 | */ 150 | 151 | button, 152 | input, 153 | optgroup, 154 | select, 155 | textarea { 156 | font-family: inherit; /* 1 */ 157 | font-size: 100%; /* 1 */ 158 | line-height: inherit; /* 1 */ 159 | color: inherit; /* 1 */ 160 | margin: 0; /* 2 */ 161 | padding: 0; /* 3 */ 162 | } 163 | 164 | /* 165 | Remove the inheritance of text transform in Edge and Firefox. 166 | */ 167 | 168 | button, 169 | select { 170 | text-transform: none; 171 | } 172 | 173 | /* 174 | 1. Correct the inability to style clickable types in iOS and Safari. 175 | 2. Remove default button styles. 176 | */ 177 | 178 | button, 179 | [type='button'], 180 | [type='reset'], 181 | [type='submit'] { 182 | -webkit-appearance: button; /* 1 */ 183 | /* background-color: transparent; 2 */ 184 | background-image: none; /* 2 */ 185 | } 186 | 187 | /* 188 | Use the modern Firefox focus style for all focusable elements. 189 | */ 190 | 191 | :-moz-focusring { 192 | outline: auto; 193 | } 194 | 195 | /* 196 | Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) 197 | */ 198 | 199 | :-moz-ui-invalid { 200 | box-shadow: none; 201 | } 202 | 203 | /* 204 | Add the correct vertical alignment in Chrome and Firefox. 205 | */ 206 | 207 | progress { 208 | vertical-align: baseline; 209 | } 210 | 211 | /* 212 | Correct the cursor style of increment and decrement buttons in Safari. 213 | */ 214 | 215 | ::-webkit-inner-spin-button, 216 | ::-webkit-outer-spin-button { 217 | height: auto; 218 | } 219 | 220 | /* 221 | 1. Correct the odd appearance in Chrome and Safari. 222 | 2. Correct the outline style in Safari. 223 | */ 224 | 225 | [type='search'] { 226 | -webkit-appearance: textfield; /* 1 */ 227 | outline-offset: -2px; /* 2 */ 228 | } 229 | 230 | /* 231 | Remove the inner padding in Chrome and Safari on macOS. 232 | */ 233 | 234 | ::-webkit-search-decoration { 235 | -webkit-appearance: none; 236 | } 237 | 238 | /* 239 | 1. Correct the inability to style clickable types in iOS and Safari. 240 | 2. Change font properties to `inherit` in Safari. 241 | */ 242 | 243 | ::-webkit-file-upload-button { 244 | -webkit-appearance: button; /* 1 */ 245 | font: inherit; /* 2 */ 246 | } 247 | 248 | /* 249 | Add the correct display in Chrome and Safari. 250 | */ 251 | 252 | summary { 253 | display: list-item; 254 | } 255 | 256 | /* 257 | Removes the default spacing and border for appropriate elements. 258 | */ 259 | 260 | blockquote, 261 | dl, 262 | dd, 263 | h1, 264 | h2, 265 | h3, 266 | h4, 267 | h5, 268 | h6, 269 | hr, 270 | figure, 271 | p, 272 | pre { 273 | margin: 0; 274 | } 275 | 276 | fieldset { 277 | margin: 0; 278 | padding: 0; 279 | } 280 | 281 | legend { 282 | padding: 0; 283 | } 284 | 285 | ol, 286 | ul, 287 | menu { 288 | list-style: none; 289 | margin: 0; 290 | padding: 0; 291 | } 292 | 293 | /* 294 | Prevent resizing textareas horizontally by default. 295 | */ 296 | 297 | textarea { 298 | resize: vertical; 299 | } 300 | 301 | /* 302 | 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) 303 | 2. Set the default placeholder color to the user's configured gray 400 color. 304 | */ 305 | 306 | input::placeholder, 307 | textarea::placeholder { 308 | opacity: 1; /* 1 */ 309 | color: #9ca3af; /* 2 */ 310 | } 311 | 312 | /* 313 | Set the default cursor for buttons. 314 | */ 315 | 316 | button, 317 | [role="button"] { 318 | cursor: pointer; 319 | } 320 | 321 | /* 322 | Make sure disabled buttons don't get the pointer cursor. 323 | */ 324 | :disabled { 325 | cursor: default; 326 | } 327 | 328 | /* 329 | 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) 330 | 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) 331 | This can trigger a poorly considered lint error in some tools but is included by design. 332 | */ 333 | 334 | img, 335 | svg, 336 | video, 337 | canvas, 338 | audio, 339 | iframe, 340 | embed, 341 | object { 342 | display: block; /* 1 */ 343 | vertical-align: middle; /* 2 */ 344 | } 345 | 346 | /* 347 | Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) 348 | */ 349 | 350 | img, 351 | video { 352 | max-width: 100%; 353 | height: auto; 354 | } 355 | 356 | /* 357 | Ensure the default browser behavior of the `hidden` attribute. 358 | */ 359 | 360 | [hidden] { 361 | display: none; 362 | } 363 | 364 | .dark { 365 | color-scheme: dark; 366 | } 367 | --------------------------------------------------------------------------------