├── .commitlintrc.cjs ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── FUNDING.yml └── workflows │ ├── CI.yml │ ├── algolia.yml │ └── release.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── README.md ├── alias.ts ├── docs ├── docs │ ├── .vitepress │ │ ├── config.ts │ │ ├── locales │ │ │ ├── en-US.ts │ │ │ ├── index.ts │ │ │ └── zh-CN.ts │ │ └── theme │ │ │ ├── index.ts │ │ │ └── style │ │ │ └── var.css │ ├── components │ │ ├── backtop.md │ │ ├── button.md │ │ ├── checkbox.md │ │ ├── drawer.md │ │ ├── icon.md │ │ ├── message.md │ │ ├── table.md │ │ ├── tooltip.md │ │ ├── tree.md │ │ └── upload.md │ ├── examples │ │ ├── backtop │ │ │ ├── basic.vue │ │ │ └── custom.vue │ │ ├── button │ │ │ ├── basic.vue │ │ │ ├── disabled.vue │ │ │ ├── shape.vue │ │ │ └── size.vue │ │ ├── checkbox │ │ │ └── basic.vue │ │ ├── drawer │ │ │ └── basic.vue │ │ ├── icon │ │ │ └── basic.vue │ │ ├── message │ │ │ ├── Basic.vue │ │ │ ├── Duration.vue │ │ │ └── Offset.vue │ │ ├── tooltip │ │ │ └── basic.vue │ │ ├── tree │ │ │ └── basic.vue │ │ └── upload │ │ │ └── basic.vue │ ├── guide │ │ ├── develop.md │ │ ├── install.md │ │ ├── problem.md │ │ ├── start.md │ │ └── translate.md │ ├── index.md │ ├── public │ │ ├── icon.ico │ │ ├── icon.png │ │ └── logo.png │ ├── type.d.ts │ └── zh-CN │ │ ├── components │ │ ├── backtop.md │ │ ├── button.md │ │ ├── checkbox.md │ │ ├── drawer.md │ │ ├── icon.md │ │ ├── message.md │ │ ├── table.md │ │ ├── tooltip.md │ │ ├── tree.md │ │ └── upload.md │ │ ├── guide │ │ ├── develop.md │ │ ├── install.md │ │ ├── problem.md │ │ ├── start.md │ │ └── translate.md │ │ └── index.md ├── hooks │ └── useIsEnglish.ts ├── package.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── package.json ├── packages ├── common │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── types.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ └── install.ts │ └── tsup.config.ts ├── components │ ├── auto-imports.d.ts │ ├── env.d.ts │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── backtop │ │ │ ├── __tests__ │ │ │ │ └── backtop.test.tsx │ │ │ ├── backtop.vue │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ └── style.scss │ │ ├── button │ │ │ ├── __tests__ │ │ │ │ └── button.test.tsx │ │ │ ├── button.vue │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ └── style.scss │ │ ├── checkbox │ │ │ ├── __tests__ │ │ │ │ └── checkbox.test.tsx │ │ │ ├── checkbox.vue │ │ │ ├── index.ts │ │ │ └── props.ts │ │ ├── container │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ ├── src │ │ │ │ ├── aside.vue │ │ │ │ ├── container.vue │ │ │ │ ├── footer.vue │ │ │ │ ├── header.vue │ │ │ │ └── main.vue │ │ │ └── style │ │ │ │ ├── aside.scss │ │ │ │ ├── common │ │ │ │ └── var.scss │ │ │ │ ├── container.scss │ │ │ │ ├── footer.scss │ │ │ │ ├── header.scss │ │ │ │ ├── index.ts │ │ │ │ ├── main.scss │ │ │ │ └── mixins │ │ │ │ ├── _var.scss │ │ │ │ ├── config.scss │ │ │ │ ├── function.scss │ │ │ │ └── mixins.scss │ │ ├── drawer │ │ │ ├── __tests__ │ │ │ │ └── drawer.test.tsx │ │ │ ├── drawer.vue │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ └── style.scss │ │ ├── icon │ │ │ ├── __tests__ │ │ │ │ └── icon.tsx │ │ │ ├── icon.vue │ │ │ ├── iconList.ts │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ └── style.scss │ │ ├── message │ │ │ ├── index.ts │ │ │ ├── manager.ts │ │ │ ├── message.vue │ │ │ ├── props.ts │ │ │ ├── style.scss │ │ │ └── types.ts │ │ ├── table │ │ │ ├── __tests__ │ │ │ │ └── table.test.tsx │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ ├── style.scss │ │ │ └── table.vue │ │ ├── tooltip │ │ │ ├── content.vue │ │ │ ├── helper.ts │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ ├── style.scss │ │ │ ├── tooltip.vue │ │ │ ├── trigger.vue │ │ │ └── types.ts │ │ ├── tree │ │ │ ├── __tests__ │ │ │ │ └── tree.test.tsx │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ ├── style.scss │ │ │ └── tree.vue │ │ └── upload │ │ │ ├── __test__ │ │ │ └── upload.test.tsx │ │ │ ├── ajax.ts │ │ │ ├── index.ts │ │ │ ├── props.ts │ │ │ ├── style.scss │ │ │ ├── types.ts │ │ │ └── upload.vue │ ├── tsconfig.json │ ├── unocss.config.ts │ └── vite.config.ts ├── lucky-design │ ├── package.json │ ├── src │ │ ├── components.ts │ │ └── index.ts │ ├── tsconfig.json │ └── vite.config.ts └── preset │ ├── index.ts │ ├── package.json │ ├── src │ ├── colors.ts │ ├── preflights.ts │ ├── preset.ts │ ├── rules.ts │ ├── shortcuts │ │ ├── button.ts │ │ └── index.ts │ └── theme.ts │ └── tsup.config.ts ├── playground ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ └── Header.vue │ ├── main.ts │ ├── router │ │ ├── dynamicRoutes.ts │ │ ├── index.ts │ │ └── routes.ts │ ├── style.css │ ├── views │ │ ├── Backtop.vue │ │ ├── Button.vue │ │ ├── Checkbox.vue │ │ ├── Drawer.vue │ │ ├── Icon.vue │ │ ├── LTooltip.vue │ │ ├── Message.vue │ │ ├── Table.vue │ │ ├── Tree.vue │ │ ├── Upload.vue │ │ └── index.vue │ └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── add-component.sh ├── build.ts ├── dev-packages.ts ├── dev.ts └── utils.ts ├── tsconfig.json └── vitest.config.ts /.commitlintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | quote_type = single 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | pnpm-lock.yaml 4 | CHANGELOG.en-US.md 5 | docs/components.d.ts 6 | coverage 7 | play 8 | ssr-testing/cases/* 9 | docs/.vitepress/i18n/* 10 | docs/.vitepress/crowdin/* 11 | !docs/.vitepress/crowdin/en-US 12 | !.* 13 | cache 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@antfu"], 3 | "rules": { 4 | "react/display-name": "off", 5 | "react-hooks/rules-of-hooks": "off", 6 | "no-sequences": "off", 7 | "no-alert": "off", 8 | "no-console": ["error", { "allow": ["error"] }] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [lucky-design] 2 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | lint: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Install pnpm 21 | uses: pnpm/action-setup@v2 22 | 23 | - name: Set node 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: 16.x 27 | cache: pnpm 28 | 29 | - name: Setup 30 | run: npm i -g @antfu/ni 31 | 32 | - name: Install 33 | run: nci 34 | 35 | - name: Lint 36 | run: nr lint 37 | 38 | - name: Type Check 39 | run: nr typecheck 40 | 41 | test: 42 | runs-on: ${{ matrix.os }} 43 | 44 | strategy: 45 | matrix: 46 | node: [16.x] 47 | os: [ubuntu-latest, windows-latest, macos-latest] 48 | fail-fast: false 49 | 50 | steps: 51 | - uses: actions/checkout@v3 52 | with: 53 | fetch-depth: 0 54 | 55 | - name: Install pnpm 56 | uses: pnpm/action-setup@v2 57 | 58 | - name: Set node ${{ matrix.node }} 59 | uses: actions/setup-node@v3 60 | with: 61 | node-version: ${{ matrix.node }} 62 | cache: pnpm 63 | 64 | - name: Setup 65 | run: npm i -g @antfu/ni 66 | 67 | - name: Install 68 | run: nci 69 | 70 | - name: Test 71 | run: nr test 72 | -------------------------------------------------------------------------------- /.github/workflows/algolia.yml: -------------------------------------------------------------------------------- 1 | name: algolia 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | algolia: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Get the content of algolia.json as config 14 | id: algolia_config 15 | run: echo "config=$(cat docs/crawler.config.json | jq -r tostring)" >> $GITHUB_OUTPUT 16 | - name: Push indices to Algolia 17 | uses: signcl/docsearch-scraper-action@master 18 | env: 19 | APPLICATION_ID: ${{ secrets.ALGOLIA_APP_ID }} 20 | API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }} 21 | CONFIG: ${{ steps.algolia_config.outputs.config }} 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | tags: 8 | - 'v*' 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Install pnpm 19 | uses: pnpm/action-setup@v2 20 | 21 | - name: Set node 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: 18 25 | cache: pnpm 26 | registry-url: 'https://registry.npmjs.org' 27 | 28 | - run: npx changelogithub 29 | continue-on-error: true 30 | env: 31 | GITHUB_TOKEN: ${{secrets.PERMANENT_GITHUB_TOKEN}} 32 | 33 | - name: Install Dependencies 34 | run: pnpm i 35 | 36 | - name: PNPM build 37 | run: pnpm run build 38 | 39 | - name: Publish to NPM 40 | run: pnpm -r publish --access public --no-git-checks 41 | env: 42 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 43 | -------------------------------------------------------------------------------- /.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 | packages/lucky-design/src/style.css 11 | 12 | node_modules 13 | dist 14 | dist-ssr 15 | *.local 16 | 17 | cache 18 | 19 | # Editor directories and files 20 | .vscode/* 21 | !.vscode/extensions.json 22 | .idea 23 | .DS_Store 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # # 获取当前的分支名称 4 | # branch="$(git rev-parse --abbrev-ref HEAD)" 5 | # # 判断当前分支是否为禁止提交的分支名, 如果是则给出相关提示,并终止commit 6 | # if [ "$branch" = "master" ]; then 7 | # echo "master分支不支持提交操作, You can't commit to master branch" 8 | # exit 1 9 | # fi 10 | 11 | . "$(dirname -- "$0")/_/husky.sh" 12 | 13 | pnpm run lint 14 | pnpm run typecheck 15 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | coverage 4 | CHANGELOG.en-US.md 5 | pnpm-lock.yaml 6 | docs/components.d.ts 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "overrides": [ 5 | { 6 | "files": ".prettierrc", 7 | "options": { 8 | "parser": "json" 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lucky-design 2 | 3 |

4 | 5 |

Lucky Design

6 |

7 | 8 |

9 | Lucky Design 可在 vue3 应用程序中快速构建交互界面,简洁, 强大, 美观, 高效 10 |

11 | 12 | ## ✨ 特性 13 | 14 | - 🪐 n+ 常用组件 15 | - 💪 使用 Vue.js 最新特性开发 16 | - 🐆 全面基于 Vite,速度够快 17 | - 🤟 极致的开发体验 18 | - 🥇 超详细的 JSDoc 注释 19 | - ✂️ 完善的代码提示 20 | - 🏆 支持完整引入和按需引入 21 | - ✅ 使用 TypeScript + Template 编写 22 | - 🖍️ 严格的 TypeScript 类型 23 | - ✔️ 配置简单,上手容易 24 | - 🚩 单元测试 25 | - 👍 社区团队维护 26 | - ❤️ 根据实际需求开发 27 | - 📃 优质详细的文档 28 | - ☝️ 提出需求,不断完善 29 | - 🛠 更多特性开发中 30 | 31 | ## 使用 32 | 33 | 安装lucky-design 34 | ```cmd 35 | # 选择一个你喜欢的包管理器 36 | 37 | # NPM 38 | $ npm install lucky-design --save 39 | 40 | # Yarn 41 | $ yarn add lucky-design --save 42 | 43 | # pnpm 44 | $ pnpm add lucky-design --save 45 | ``` 46 | 47 | 在项目中引入 48 | 49 | ```ts 50 | // main.ts 51 | import { createApp } from 'vue' 52 | import LuckyDesign from 'lucky-design' 53 | import 'lucky-design/dist/style.css' 54 | import App from './App.vue' 55 | 56 | const app = createApp(App) 57 | 58 | app.use(LuckyDesign) 59 | app.mount('#app') 60 | ``` 61 | 62 | ## 开发文档 63 | 64 | ### 目录说明 65 | - .github 工作流 66 | - .husky git hook 67 | - docs 组件库文档 68 | - packages 69 | - common 工具方法和常量 70 | - components 开发组件的位置 71 | - preset 预设 72 | - playground 调试操场 73 | - scripts 脚本 74 | ### 安装依赖 75 | 76 | ```cmd 77 | pnpm install 78 | pnpm dev 79 | ``` 80 | 81 | ### 开发新组件 82 | 83 | 运行命令 84 | 85 | ```cmd 86 | pnpm gen 87 | 88 | 例: pnpm gen button 89 | ``` 90 | 91 | 会自动在`packages/components/src`和`playground/src/views`下创建基础文件配置 92 | 93 | 运行命令,在playground中开发调试组件 94 | 95 | ```cmd 96 | pnpm dev:playground 97 | ``` 98 | 99 | ### 文档 100 | 组件开发完成后,在`docs`中更新组件文档 101 | 102 | ```cmd 103 | pnpm dev:docs 104 | ``` 105 | 106 | `docs/docs/components`中添加对应的md文件介绍组件,在`zh-CN`下同步更新中文文档 107 | 108 | 编写完成后在`.vitepress/locales`中对应的文件中的添加到`sidebar`上 109 | -------------------------------------------------------------------------------- /alias.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path' 2 | 3 | export const r = (p: string) => resolve(__dirname, p) 4 | 5 | export const alias: Record = { 6 | '@lucky-design/components': r('./packages/components/'), 7 | '@lucky-design/common': r('./packages/common/'), 8 | '@lucky-design/preset': r('./packages/preset'), 9 | } 10 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | import { 3 | componentPreview, 4 | containerPreview, 5 | } from '@vitepress-demo-preview/plugin' 6 | 7 | import locales from './locales' 8 | 9 | export default defineConfig({ 10 | title: 'lucky-design', 11 | head: [['link', { rel: 'icon', href: '/icon.ico' }]], 12 | 13 | // 默认主题 14 | appearance: 'dark', 15 | 16 | // i18n 17 | locales: { 18 | 'root': locales.en, 19 | 'zh-CN': locales.zh, 20 | }, 21 | 22 | // 从URL中删除尾随的.html 23 | cleanUrls: true, 24 | 25 | // 显示更新时间 26 | lastUpdated: true, 27 | 28 | markdown: { 29 | theme: { 30 | light: 'min-dark', 31 | dark: 'one-dark-pro', 32 | }, 33 | lineNumbers: true, 34 | config: (md) => { 35 | // eslint-disable-next-line @typescript-eslint/no-var-requires 36 | md.use(require('markdown-it-task-lists')) 37 | md.use(componentPreview) 38 | md.use(containerPreview) 39 | }, 40 | }, 41 | 42 | themeConfig: { 43 | logo: '/icon.png', 44 | 45 | // 网站header部分标题 46 | siteTitle: 'lucky-design', 47 | 48 | // 社交账号链接 49 | socialLinks: [ 50 | { 51 | icon: 'github', 52 | link: 'https://github.com/lucky-design-org/lucky-design', 53 | }, 54 | ], 55 | 56 | // footer 57 | footer: { 58 | message: 'Released under the MIT License.', 59 | copyright: 'Copyright © 2023-present Lucky-Design', 60 | }, 61 | 62 | search: { 63 | provider: 'local', 64 | }, 65 | }, 66 | }) 67 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | label: 'English', 3 | lang: 'en-US', 4 | description: 'lightweight component library', 5 | themeConfig: { 6 | lastUpdatedText: 'Last updated', 7 | outlineTitle: 'On this page', 8 | editLink: { 9 | pattern: 10 | 'https://github.com/lucky-design-org/lucky-design/edit/master/docs/docs/:path', 11 | text: 'Edit this page on GitHub', 12 | }, 13 | docFooter: { 14 | prev: 'Previous page', 15 | next: 'Next page', 16 | }, 17 | nav: [ 18 | { text: 'Guide', link: '/guide/install', activeMatch: '/guide' }, 19 | { 20 | text: 'Components', 21 | link: '/components/button', 22 | activeMatch: '/components', 23 | }, 24 | ], 25 | sidebar: { 26 | '/guide': [ 27 | { 28 | text: 'Guide', 29 | collapsed: false, 30 | items: [ 31 | { text: 'install', link: '/guide/install' }, 32 | { text: 'start', link: '/guide/start' }, 33 | ], 34 | }, 35 | { 36 | text: 'development', 37 | collapsed: false, 38 | items: [ 39 | { text: 'develop guide', link: '/guide/develop' }, 40 | { text: 'develop problem', link: '/guide/problem' }, 41 | ], 42 | }, 43 | { 44 | text: 'other', 45 | collapsed: false, 46 | items: [{ text: 'translate', link: '/guide/translate' }], 47 | }, 48 | ], 49 | '/components': [ 50 | { 51 | text: 'Basic', 52 | collapsed: false, 53 | items: [ 54 | { text: 'Button', link: '/components/button' }, 55 | { text: 'Icon', link: '/components/icon' }, 56 | ], 57 | }, 58 | { 59 | text: 'Form', 60 | collapsed: false, 61 | items: [ 62 | { text: 'Checkbox', link: '/components/checkbox' }, 63 | { text: 'Upload', link: '/components/upload' }, 64 | ], 65 | }, 66 | { 67 | text: 'Data', 68 | collapsed: false, 69 | items: [ 70 | { text: 'Table', link: '/components/table' }, 71 | { text: 'Tree', link: '/components/tree' }, 72 | ], 73 | }, 74 | { 75 | text: 'Navigation', 76 | collapsed: false, 77 | items: [{ text: 'Backtop', link: '/components/backtop' }], 78 | }, 79 | { 80 | text: 'Feedback', 81 | collapsed: false, 82 | items: [ 83 | { text: 'Drawer', link: '/components/drawer' }, 84 | { text: 'Message', link: '/components/message' }, 85 | { text: 'Tooltip', link: '/components/tooltip' }, 86 | ], 87 | }, 88 | ], 89 | }, 90 | }, 91 | } 92 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/locales/index.ts: -------------------------------------------------------------------------------- 1 | import en from './en-US.js' 2 | import zh from './zh-CN.js' 3 | 4 | export default { 5 | en, 6 | zh, 7 | } 8 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | label: '简体中文', 3 | lang: 'zh-CN', 4 | link: '/zh-CN/', 5 | description: '基于Vue3的高效美观的组件库', 6 | themeConfig: { 7 | lastUpdatedText: '上次更新', 8 | outlineTitle: '当前页面', 9 | editLink: { 10 | pattern: 'https://github.com/lucky-design-org/lucky-design/edit/master/docs/docs/:path', 11 | text: '在github上编辑此页面', 12 | }, 13 | docFooter: { 14 | prev: '上一页', 15 | next: '下一页', 16 | }, 17 | nav: [ 18 | { text: '指南', link: '/zh-CN/guide/install', activeMatch: '/zh-CN/guide' }, 19 | { 20 | text: '组件', 21 | link: '/zh-CN/components/button', 22 | activeMatch: '/zh-CN/components', 23 | }, 24 | ], 25 | sidebar: { 26 | '/zh-CN/guide': [ 27 | { 28 | text: '导航', 29 | collapsed: false, 30 | items: [ 31 | { text: '安装', link: '/zh-CN/guide/install' }, 32 | { text: '快速开始', link: '/zh-CN/guide/start' }, 33 | ], 34 | }, 35 | { 36 | text: '开发', 37 | collapsed: false, 38 | items: [ 39 | { text: '开发指南', link: '/zh-CN/guide/develop' }, 40 | { text: '开发问题', link: '/zh-CN/guide/problem' }, 41 | ], 42 | }, 43 | { 44 | text: '其他', 45 | collapsed: false, 46 | items: [ 47 | { text: '翻译', link: '/zh-CN/guide/translate' }, 48 | ], 49 | }, 50 | ], 51 | '/zh-CN/components': [ 52 | { 53 | text: 'Basic 基础组件', 54 | collapsed: false, 55 | items: [ 56 | { text: 'Button 按钮', link: '/zh-CN/components/button' }, 57 | { text: 'Icon 图标', link: '/zh-CN/components/icon' }, 58 | ], 59 | }, 60 | { 61 | text: 'Form 表单组件', 62 | collapsed: false, 63 | items: [ 64 | { text: 'Checkbox 多选框', link: '/zh-CN/components/checkbox' }, 65 | { text: 'Upload 上传', link: '/zh-CN/components/upload' }, 66 | ], 67 | }, 68 | { 69 | text: 'Data 数据展示', 70 | collapsed: false, 71 | items: [ 72 | { text: 'Table 表格', link: '/zh-CN/components/table' }, 73 | { text: 'Tree 树形控件', link: '/zh-CN/components/tree' }, 74 | ], 75 | }, 76 | { 77 | text: 'Navigation 导航', 78 | collapsed: false, 79 | items: [ 80 | { text: 'Backtop 回到顶部', link: '/zh-CN/components/backtop' }, 81 | ], 82 | }, 83 | { 84 | text: 'Feedback 反馈组件', 85 | collapsed: false, 86 | items: [ 87 | { text: 'Drawer 抽屉', link: '/zh-CN/components/drawer' }, 88 | { text: 'Message 消息提示', link: '/zh-CN/components/message' }, 89 | { text: 'Tooltip 文字提示', link: '/zh-CN/components/tooltip' }, 90 | ], 91 | }, 92 | ], 93 | }, 94 | }, 95 | } 96 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import Theme from 'vitepress/theme' 2 | import './style/var.css' 3 | import 'lucky-design/dist/style.css' 4 | 5 | import { ElementPlusContainer } from '@vitepress-demo-preview/component' 6 | import '@vitepress-demo-preview/component/dist/style.css' 7 | 8 | export default { 9 | ...Theme, 10 | enhanceApp({ app }) { 11 | app.component('DemoPreview', ElementPlusContainer) 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /docs/docs/.vitepress/theme/style/var.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 标题 */ 3 | --vp-home-hero-name-color: #7d4ac9; 4 | --vp-home-hero-name-background: linear-gradient(#7d4ac9 100%); 5 | 6 | /* 图标背景 */ 7 | --vp-home-hero-image-background-image: linear-gradient( 135deg, #7d4ac9 50%, #5019a2 50%); 8 | --vp-home-hero-image-filter: blur(56px); 9 | 10 | /* brand按钮 */ 11 | --vp-button-brand-border: #7d4ac9; 12 | --vp-button-brand-text: #fff; 13 | --vp-button-brand-bg: #7d4ac9; 14 | 15 | --vp-button-brand-hover-border: #4a119e; 16 | --vp-button-brand-hover-text: rgb(216, 216, 216); 17 | --vp-button-brand-hover-bg: #4a119e; 18 | 19 | --vp-button-brand-active-border: #fff; 20 | 21 | /* 主题基色 */ 22 | --vp-c-brand: #7d4ac9; 23 | --vp-c-brand-light: #7d4ac9; 24 | --vp-c-brand-dark: #7d4ac9; 25 | 26 | /* 代码块背景色 */ 27 | --vp-code-block-bg: rgba(40,44,52); 28 | 29 | /* tip边框 */ 30 | --vp-custom-block-tip-border: #7d4ac9; 31 | --vp-custom-block-tip-text: #7d4ac9; 32 | --vp-custom-block-tip-bg: #7d4ac92e; 33 | } 34 | 35 | /* vitepress-demo-preview */ 36 | .vitepress-demo-preview__element-plus__container .vitepress-demo-preview-description .vitepress-demo-preview-description__handle-btn { 37 | justify-content: center !important; 38 | } 39 | -------------------------------------------------------------------------------- /docs/docs/components/backtop.md: -------------------------------------------------------------------------------- 1 | # Backtop 2 | 3 | Back to the action button at the top of the page 4 | 5 | ## Basic usage 6 | 7 | 8 | 9 | ## Customizations 10 | 11 | 12 | 13 | ## API 14 | 15 | | Name | Description | Type | Default | 16 | | ---------------- | ----------------- | ------ | ------------ | 17 | | right | right distance | number | 50 | 18 | | bottom | bottom distance | number | 50 | 19 | | visibilityHeight | visibility height | number | client hight | 20 | -------------------------------------------------------------------------------- /docs/docs/components/button.md: -------------------------------------------------------------------------------- 1 | # Button 2 | 3 | Commonly used button 4 | 5 | ## Basic usage 6 | 7 | 8 | 9 | ## Button size 10 | 11 | 12 | 13 | ## Button shape 14 | 15 | 16 | 17 | ## Disabled Button 18 | 19 | 20 | 21 | ## API 22 | 23 | | Name | Description | Type | Default | 24 | | -------- | ------------------ | ------- | ------- | 25 | | type | button type | string | primary | 26 | | plain | plain button | boolean | false | 27 | | size | button size | string | md | 28 | | shape | button shape | string | square | 29 | | disabled | disable the button | boolean | false | 30 | -------------------------------------------------------------------------------- /docs/docs/components/checkbox.md: -------------------------------------------------------------------------------- 1 | # Checkbox 2 | 3 | Commonly used Checkbox 4 | 5 | ## Basic usage 6 | 7 | 8 | 9 | ## API 10 | 11 | | Name | Description | Type | Default | 12 | | ----------- | -------------------- | -------- | ------- | 13 | | value | checkbox value | boolean | false | 14 | | true-value | checkbox true-value | boolean | true | 15 | | false-value | checkbox false-value | boolean | false | 16 | | disabled | checkbox disabled | boolean | false | 17 | | input | input event | function | null | 18 | -------------------------------------------------------------------------------- /docs/docs/components/drawer.md: -------------------------------------------------------------------------------- 1 | # Drawer 2 | 3 | A temporary sidebar that can appear in multiple directions 4 | 5 | # Basic usage 6 | 7 | 8 | 9 | ## API 10 | 11 | | Name | Description | Type | Default | 12 | | --------- | ----------------------- | -------- | ------- | 13 | | title | sidebar title | string | - | 14 | | visible | show | boolean | false | 15 | | direction | direction of occurrence | string | right | 16 | | close | close sidebar | function | - | 17 | | bg-color | background color | string | white | 18 | -------------------------------------------------------------------------------- /docs/docs/components/icon.md: -------------------------------------------------------------------------------- 1 | # icon 2 | 3 | ## Basic usage 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/docs/components/message.md: -------------------------------------------------------------------------------- 1 | # Message 2 | 3 | used for feedback prompt after active operation 4 | 5 | ## Basic usage 6 | 7 | 8 | 9 | ## Delay close 10 | 11 | 12 | 13 | ## Offset 14 | 15 | 16 | 17 | ## API 18 | 19 | | Name | Description | Type | Default | 20 | | -------- | --------------- | ------- | ------- | 21 | | type | message type | string | info | 22 | | message | message content | string | - | 23 | | timeout | close time | number | 3000 | 24 | | closeBtn | close button | boolean | false | 25 | | offset | offset | number | 20 | 26 | -------------------------------------------------------------------------------- /docs/docs/components/table.md: -------------------------------------------------------------------------------- 1 | # Table 2 | -------------------------------------------------------------------------------- /docs/docs/components/tooltip.md: -------------------------------------------------------------------------------- 1 | # Tooltip 2 | 3 | ## Basic usage 4 | 5 | 6 | 7 | ## API 8 | 9 | | Name | Description | Type | Default | 10 | | - | - | - | -| 11 | | append-to | Indicates to which web element will the content of the Tooltip be attached | CSS 选择器 | - | 12 | | content | To display content, can also use the Content slot | string | - | 13 | | placement | Position of appearance | string | bottom | 14 | -------------------------------------------------------------------------------- /docs/docs/components/tree.md: -------------------------------------------------------------------------------- 1 | # Tree 2 | 3 | Commonly used Tree 4 | 5 | ## Basic usage 6 | 7 | 8 | 9 | ## API 10 | 11 | | Name | Description | Type | Default | 12 | | - | - | - | - | 13 | | data | data source | Array | [] | 14 | | show | isShow | boolean | true | 15 | -------------------------------------------------------------------------------- /docs/docs/components/upload.md: -------------------------------------------------------------------------------- 1 | # Upload 2 | 3 | ## Basic usage 4 | 5 | 6 | 7 | ## API 8 | 9 | | Name | Description | Type | Default | 10 | | ----------- | ------------------------------------- | -------- | ------- | 11 | | action | request URL | string | - | 12 | | multiple | Whether multiple upload is supported | boolean | false | 13 | | name | Field name of the file to be uploaded | string | file | 14 | | auto-upload | Whether to upload automatically | boolean | true | 15 | | on-error | File upload failure callback | Function | 16 | | on-success | File upload success callback | Function | 17 | | on-progress | File upload callback | Function | 18 | -------------------------------------------------------------------------------- /docs/docs/examples/backtop/basic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /docs/docs/examples/backtop/custom.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /docs/docs/examples/button/basic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | 22 | 31 | -------------------------------------------------------------------------------- /docs/docs/examples/button/disabled.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /docs/docs/examples/button/shape.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /docs/docs/examples/button/size.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | 23 | -------------------------------------------------------------------------------- /docs/docs/examples/checkbox/basic.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | 25 | 34 | -------------------------------------------------------------------------------- /docs/docs/examples/drawer/basic.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 50 | 51 | 61 | -------------------------------------------------------------------------------- /docs/docs/examples/icon/basic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /docs/docs/examples/message/Basic.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 32 | 33 | 39 | -------------------------------------------------------------------------------- /docs/docs/examples/message/Duration.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 39 | 40 | 46 | -------------------------------------------------------------------------------- /docs/docs/examples/message/Offset.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | 28 | 34 | -------------------------------------------------------------------------------- /docs/docs/examples/tooltip/basic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /docs/docs/examples/tree/basic.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 73 | -------------------------------------------------------------------------------- /docs/docs/examples/upload/basic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | 21 | 30 | -------------------------------------------------------------------------------- /docs/docs/guide/develop.md: -------------------------------------------------------------------------------- 1 | # Develop Guide 2 | 3 | ### install dependency and running 4 | 5 | ```cmd 6 | pnpm install 7 | pnpm dev 8 | ``` 9 | 10 | ### develop new component 11 | 12 | run command 13 | 14 | ```cmd 15 | pnpm gen 16 | 17 | example: pnpm gen button 18 | ``` 19 | 20 | Will automatically create basic file configuration in `packages/components/src`和`playground/src/views` 21 | 22 | run command,develop and debug components in playground 23 | 24 | ```cmd 25 | pnpm dev:playground 26 | ``` 27 | 28 | ### 文档 29 | 30 | After component development,update component documentation in `docs` 31 | 32 | ```cmd 33 | pnpm dev:docs 34 | ``` 35 | 36 | Add the corresponding md file to introduce the component in `docs/docs/components`,synchronize update of Chinese documents in `zh-CN` 37 | 38 | After finish add url to `sidebar` in `.vitepress/locales` 39 | -------------------------------------------------------------------------------- /docs/docs/guide/install.md: -------------------------------------------------------------------------------- 1 | # Environment 2 | 3 | :::tip 4 | Since Vue3 no longer supports IE11, lucky-design does not support IE browser either 5 | ::: 6 | 7 | ## version 8 | 9 | - Lucky-Design is still in rapid development iteration 10 | 11 | ## install 12 | 13 | ```cmd 14 | # Choose a package manager of your liking 15 | 16 | # NPM 17 | $ npm install lucky-design --save 18 | 19 | # Yarn 20 | $ yarn add lucky-design --save 21 | 22 | # pnpm 23 | $ pnpm add lucky-design --save 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/docs/guide/problem.md: -------------------------------------------------------------------------------- 1 | # Problems encountered in development 2 | 3 | - [x] Running in Mac environment 4 | 5 | - [x] use algolia search 6 | 7 | - [x] i18n configure 8 | 9 | - [x] release 10 | -------------------------------------------------------------------------------- /docs/docs/guide/start.md: -------------------------------------------------------------------------------- 1 | # Start 2 | 3 | Import in the project 4 | 5 | ```ts 6 | // main.ts 7 | import { createApp } from 'vue' 8 | import LuckyDesign from 'lucky-design' 9 | import 'lucky-design/dist/style.css' 10 | import App from './App.vue' 11 | 12 | const app = createApp(App) 13 | 14 | app.use(LuckyDesign) 15 | app.mount('#app') 16 | ``` 17 | 18 | Now you can start the project 19 | 20 | -------------------------------------------------------------------------------- /docs/docs/guide/translate.md: -------------------------------------------------------------------------------- 1 | # Translate 2 | 3 | Welcome to correct the problems (typos, translation errors, etc.) in the document, and also welcome to mention [pull request](https://github.com/lucky-design-org/lucky-design/pulls) or [issue](https://github.com/lucky-design-org/lucky-design/issues) 4 | -------------------------------------------------------------------------------- /docs/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | title: Lucky-Design 5 | editLink: true 6 | lastUpdated: true 7 | hero: 8 | name: Lucky-Design 9 | text: lightweight component library 10 | tagline: Simple, powerful, pretty, and performant 11 | image: 12 | src: /icon.png 13 | alt: lucky-design 14 | actions: 15 | - theme: brand 16 | text: Get Starred 17 | link: /guide/install 18 | - theme: alt 19 | text: View on Github 20 | link: https://github.com/lucky-design-org/lucky-design 21 | features: 22 | - icon: 🔨 23 | title: Simple and intuitive 24 | details: Design simple and intuitive operation process to reduce user's memory burden 25 | - icon: 🧩 26 | title: Clear and definite 27 | details: The language is clear and the meaning is clear, so that users can quickly understand and make decisions 28 | - icon: ✈️ 29 | title: Control feedback 30 | details: Users can clearly perceive their own operations through interface style and interactive dynamic effect 31 | --- 32 | -------------------------------------------------------------------------------- /docs/docs/public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucky-design-org/lucky-design/d99317a1abbf1f4a0901481529338a86f128599c/docs/docs/public/icon.ico -------------------------------------------------------------------------------- /docs/docs/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucky-design-org/lucky-design/d99317a1abbf1f4a0901481529338a86f128599c/docs/docs/public/icon.png -------------------------------------------------------------------------------- /docs/docs/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucky-design-org/lucky-design/d99317a1abbf1f4a0901481529338a86f128599c/docs/docs/public/logo.png -------------------------------------------------------------------------------- /docs/docs/type.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'lucky-design' { 2 | import { 3 | LButton, 4 | LCheckbox, 5 | LDrawer, 6 | LMessage, 7 | LTree, 8 | LBacktop, 9 | LUpload, 10 | LIcon, 11 | LToolTip, 12 | } from 'lucky-design' 13 | export { 14 | LButton, 15 | LCheckbox, 16 | LDrawer, 17 | LMessage, 18 | LTree, 19 | LBacktop, 20 | LUpload, 21 | LIcon, 22 | LToolTip, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/backtop.md: -------------------------------------------------------------------------------- 1 | # Backtop 2 | 3 | 返回页面顶部的操作按钮 4 | 5 | 9 | 10 | ## 基础使用 11 | 12 | 13 | 14 | :::info 15 | 16 | 向下滚动查看右下角的按钮 17 | 18 | ::: 19 | 20 | ::: details code 21 | 22 | ```vue 23 | 26 | 27 | 30 | ``` 31 | 32 | ::: 33 | 34 | ## 自定义 35 | 36 | 37 | 38 | :::info 39 | 40 | 你可以自定义组件的偏移量以及隐藏高度 41 | 42 | ::: 43 | 44 | ::: details code 45 | 46 | ```vue 47 | 50 | 51 | 58 | ``` 59 | 60 | ::: 61 | 62 | ## API 63 | 64 | | Name | Description | Type | Default | 65 | | ---------------- | ----------- | ------ | ------------ | 66 | | right | 右侧偏移量 | number | 50 | 67 | | bottom | 底部偏移量 | number | 50 | 68 | | visibilityHeight | 显示的高度 | number | 当前窗口高度 | 69 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/button.md: -------------------------------------------------------------------------------- 1 | # Button 2 | 3 | 9 | 10 | 常用的按钮操作 11 | 12 | ## 基础用法 13 | 14 | :::info 15 | 16 | 17 | 18 | ::: 19 | 20 | ::: details code 21 | 22 | ```vue 23 | 26 | 27 | 43 | ``` 44 | 45 | ::: 46 | 47 | ## 按钮大小 48 | 49 | :::info 50 | 51 | 52 | 53 | ::: 54 | 55 | ::: details code 56 | 57 | ```vue 58 | 61 | 62 | 70 | ``` 71 | 72 | ::: 73 | 74 | ## 按钮形状 75 | 76 | :::info 77 | 78 | 79 | 80 | ::: 81 | 82 | ::: details code 83 | 84 | ```vue 85 | 88 | 89 | 96 | ``` 97 | 98 | ::: 99 | 100 | ## 禁用状态 101 | 102 | :::info 103 | 104 | 105 | 106 | ::: 107 | 108 | ::: details code 109 | 110 | ```vue 111 | 114 | 115 | 124 | ``` 125 | 126 | ::: 127 | 128 | ## API 129 | 130 | | 名称 | 描述 | 类型 | 默认值 | 131 | | -------- | -------------- | ------- | ------- | 132 | | type | 按钮的类型 | string | primary | 133 | | plain | 是否为朴素按钮 | boolean | false | 134 | | size | 按钮的大小 | string | md | 135 | | shape | 按钮的形状 | string | square | 136 | | disabled | 禁用按钮 | boolean | false | 137 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/checkbox.md: -------------------------------------------------------------------------------- 1 | # Checkbox 2 | 3 | 8 | 9 | 常用的 Checkbox 操作 10 | 11 | ## 基本使用 12 | 13 | :::info 14 | 15 | 16 | 17 | ::: 18 | 19 | ::: details code 20 | 21 | ```vue 22 |
23 | 北京 24 | 上海 25 | 广州 26 | 杭州 27 |
28 | ``` 29 | 30 | ::: 31 | 32 | ## API 33 | 34 | | Name | Description | Type | Default | 35 | | ----------- | -------------------- | -------- | ------- | 36 | | value | checkbox value | boolean | false | 37 | | true-value | checkbox true-value | boolean | true | 38 | | false-value | checkbox false-value | boolean | false | 39 | | disabled | checkbox disabled | boolean | false | 40 | | input | input event | function | null | 41 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/drawer.md: -------------------------------------------------------------------------------- 1 | # Drawer 抽屉 2 | 3 | 一个临时的侧边栏, 可以从多个方向出现 4 | 5 | 8 | 9 | :::info 10 | 11 | 12 | 13 | ::: 14 | 15 | ::: details code 16 | 17 | ```vue 18 | 33 | 34 | 51 | ``` 52 | 53 | ::: 54 | 55 | ## API 56 | 57 | | 名称 | 描述 | 类型 | 默认值 | 58 | | --------- | -------------- | -------- | ------ | 59 | | title | 侧边栏的 title | string | - | 60 | | visible | 是否显示 | boolean | false | 61 | | direction | 出现的方向 | string | right | 62 | | close | 关闭侧边栏 | function | - | 63 | | bg-color | 背景颜色 | string | white | 64 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/icon.md: -------------------------------------------------------------------------------- 1 | # 图标 2 | 3 | 6 | 7 | ## 基本使用 8 | 9 | :::info 10 | 11 | 12 | 13 | ::: 14 | 15 | ::: details code 16 | 17 | ```vue 18 | 21 | 22 | 30 | ``` 31 | 32 | ::: 33 | 34 | 你可以通过 iconfont 来扩展图标 35 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/message.md: -------------------------------------------------------------------------------- 1 | # Message 2 | 3 | 8 | 9 | 常用于主动操作后的反馈提示 10 | 11 | ## 基础用法 12 | 13 | :::info 14 | 15 | 16 | 17 | ::: 18 | 19 | ::: details code 20 | 21 | ```vue 22 | 25 | 26 | 50 | ``` 51 | 52 | ::: 53 | 54 | ## 延时关闭 55 | 56 | :::info 57 | 58 | 59 | 60 | ::: 61 | 62 | ::: details code 63 | 64 | ```vue 65 | 68 | 69 | 100 | ``` 101 | 102 | ::: 103 | 104 | ## 偏移量 105 | 106 | :::info 107 | 108 | 109 | 110 | ::: 111 | 112 | ::: details code 113 | 114 | ```vue 115 | 118 | 119 | 138 | ``` 139 | 140 | ::: 141 | 142 | ## API 143 | 144 | | 名称 | 描述 | 类型 | 默认值 | 145 | | -------- | ---------- | ------- | ------ | 146 | | type | 消息的类型 | string | info | 147 | | message | 消息内容 | string | - | 148 | | timeout | 关闭时间 | number | 3000 | 149 | | closeBtn | 关闭按钮 | boolean | false | 150 | | offset | 偏移量 | number | 20 | 151 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/table.md: -------------------------------------------------------------------------------- 1 | # Table 2 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/tooltip.md: -------------------------------------------------------------------------------- 1 | # Tooltip 2 | 3 | 6 | 7 | ## 基本使用 8 | 9 | :::info 10 | 11 | 12 | 13 | ::: 14 | 15 | ::: details code 16 | 17 | ```vue 18 | 21 | 22 | 32 | ``` 33 | 34 | ::: 35 | 36 | ## API 37 | 38 | | 名称 | 描述 | 类型 | 默认值 | 39 | | --------- | ------------------------------------------- | ---------- | -------- | 40 | | append-to | 指示 Tooltip 的内容将附加在哪一个网页元素上 | CSS 选择器 | - | 41 | | content | 显示的内容,也可使用 content 插槽 | string | - | 42 | | placement | 出现的位置 | string | 'bottom' | 43 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/tree.md: -------------------------------------------------------------------------------- 1 | # Tree 2 | 3 | 6 | 7 | ## 基本使用 8 | 9 | :::info 10 | 11 | 12 | 13 | ::: 14 | 15 | ::: details code 16 | 17 | ```vue 18 | 81 | 82 | 87 | ``` 88 | 89 | ::: 90 | 91 | ## API 92 | 93 | | Name | Description | Type | Default | 94 | | ---- | -------------- | ------- | ------- | 95 | | data | 数据源 | Array | [] | 96 | | show | 是否显示某一项 | boolean | true | 97 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/components/upload.md: -------------------------------------------------------------------------------- 1 | # Upload 2 | 3 | 6 | 7 | ## 基本使用 8 | 9 | :::info 10 | 11 | 12 | 13 | ::: 14 | 15 | ::: details code 16 | 17 | ```vue 18 | 21 | 22 | 37 | ``` 38 | 39 | ::: 40 | 41 | ## API 42 | 43 | | 名称 | 描述 | 类型 | 默认值 | 44 | | ----------- | ---------------- | -------- | ------ | 45 | | action | 请求 URL | string | - | 46 | | multiple | 是否支持多选上传 | boolean | false | 47 | | name | 上传的文件字段名 | string | 'file' | 48 | | auto-upload | 是否自动上传 | boolean | true | 49 | | on-error | 文件上传失败回调 | Function | 50 | | on-success | 文件上传成功回调 | Function | 51 | | on-progress | 文件上传时回调 | Function | 52 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/guide/develop.md: -------------------------------------------------------------------------------- 1 | # 开发指南 2 | 3 | ### 安装依赖 4 | 5 | ```cmd 6 | pnpm install 7 | pnpm dev 8 | ``` 9 | 10 | ### 开发新组件 11 | 12 | 运行命令 13 | 14 | ```cmd 15 | pnpm gen 16 | 17 | 例: pnpm gen button 18 | ``` 19 | 20 | 会自动在`packages/components/src`和`playground/src/views`下创建基础文件配置 21 | 22 | 运行命令,在playground中开发调试组件 23 | 24 | ```cmd 25 | pnpm dev:playground 26 | ``` 27 | 28 | ### 文档 29 | 组件开发完成后,在`docs`中更新组件文档 30 | 31 | ```cmd 32 | pnpm dev:docs 33 | ``` 34 | 35 | `docs/docs/components`中添加对应的md文件介绍组件,在`zh-CN`下同步更新中文文档 36 | 37 | 编写完成后在`.vitepress/locales`对应的文件中的添加url到`sidebar`上 38 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/guide/install.md: -------------------------------------------------------------------------------- 1 | # 环境 2 | 3 | :::tip 4 | 由于 Vue3 不再支持 IE11,lucky-design 也不支持 IE 浏览器 5 | ::: 6 | 7 | ## 版本 8 | 9 | - Lucky-Design 目前还处于快速开发迭代中 10 | 11 | # 安装 12 | 13 | ```cmd 14 | # 选择一个你喜欢的包管理器 15 | 16 | # NPM 17 | $ npm install lucky-design --save 18 | 19 | # Yarn 20 | $ yarn add lucky-design --save 21 | 22 | # pnpm 23 | $ pnpm add lucky-design --save 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/guide/problem.md: -------------------------------------------------------------------------------- 1 | # 开发遇到的问题 2 | 3 | - [x] Mac环境下运行问题 4 | 5 | - [x] algolia搜索问题 6 | 7 | - [x] i18n配置问题 8 | 9 | - [x] 发包问题 10 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/guide/start.md: -------------------------------------------------------------------------------- 1 | # 快速开始 2 | 3 | 在项目引入 4 | 5 | ```ts 6 | // main.ts 7 | import { createApp } from 'vue' 8 | import LuckyDesign from 'lucky-design' 9 | import 'lucky-design/dist/style.css' 10 | import App from './App.vue' 11 | 12 | const app = createApp(App) 13 | 14 | app.use(LuckyDesign) 15 | app.mount('#app') 16 | ``` 17 | 18 | 现在你可以启动项目了 19 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/guide/translate.md: -------------------------------------------------------------------------------- 1 | # 翻译 2 | 3 | 欢迎对文档中出现的问题(错别字、翻译出错等)进行指正,也欢迎提[pull request](https://github.com/lucky-design-org/lucky-design/pulls) 或者 [issue](https://github.com/lucky-design-org/lucky-design/issues) 4 | -------------------------------------------------------------------------------- /docs/docs/zh-CN/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | title: Lucky-Design 5 | editLink: true 6 | lastUpdated: true 7 | hero: 8 | name: Lucky-Design 9 | text: 一款基于Vue3的轻量级组件库 10 | tagline: 简洁, 强大, 美观, 高效的 11 | image: 12 | src: /icon.png 13 | alt: lucky-design 14 | actions: 15 | - theme: brand 16 | text: 快速开始 17 | link: /zh-CN/guide/install 18 | - theme: alt 19 | text: 访问 Github 20 | link: https://github.com/lucky-design-org/lucky-design 21 | features: 22 | - icon: 🔨 23 | title: 简洁直观 24 | details: 设计简洁直观的操作流程,减少用户记忆负担 25 | - icon: 🧩 26 | title: 清晰明确 27 | details: 语言表达清晰且表意明确,让用户快速理解进而作出决策 28 | - icon: ✈️ 29 | title: 控制反馈 30 | details: 通过界面样式和交互动效让用户可以清晰的感知自己的操作 31 | --- 32 | -------------------------------------------------------------------------------- /docs/hooks/useIsEnglish.ts: -------------------------------------------------------------------------------- 1 | const useIsEnglish = () => { 2 | return !window.location.pathname.includes('/zh-CN') 3 | } 4 | 5 | export default useIsEnglish 6 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lucky-design/docs", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vitepress dev docs", 6 | "build": "vitepress build docs" 7 | }, 8 | "dependencies": { 9 | "lucky-design": "workspace:*", 10 | "vue": "^3.2.45" 11 | }, 12 | "devDependencies": { 13 | "@vitepress-demo-preview/component": "^2.3.0", 14 | "@vitepress-demo-preview/plugin": "^1.1.12", 15 | "markdown-it-task-lists": "^2.1.1", 16 | "vite": "^4.0.0", 17 | "vitepress": "1.0.0-beta.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /docs/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [vue()], 6 | }) 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.7", 3 | "type": "module", 4 | "packageManager": "pnpm@7.5.2", 5 | "description": "", 6 | "private": true, 7 | "scripts": { 8 | "gen": "bash ./scripts/add-component.sh", 9 | "dev": "esno scripts/dev-packages.ts", 10 | "build": "esno scripts/build.ts", 11 | "dev:docs": "cd docs && pnpm run dev", 12 | "dev:playground": "cd playground && pnpm run dev", 13 | "prepare": "husky install", 14 | "lint": "eslint --fix --ext .js,.ts,.tsx,.vue .", 15 | "test": "vitest run", 16 | "test:cover": "vitest run --coverage", 17 | "test:dev": "vitest dev", 18 | "typecheck": "tsc --noEmit && vue-tsc --noEmit", 19 | "release": "bumpp package.json packages/**/package.json" 20 | }, 21 | "lint-staged": { 22 | "packages/**": [ 23 | "prettier --config .prettierrc --write", 24 | "eslint --fix" 25 | ] 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/ByteDanceYouthTrainCamp/lucky-design.git" 30 | }, 31 | "keywords": [ 32 | "components" 33 | ], 34 | "author": "", 35 | "license": "ISC", 36 | "bugs": { 37 | "url": "https://github.com/ByteDanceYouthTrainCamp/lucky-design/issues" 38 | }, 39 | "homepage": "https://github.com/ByteDanceYouthTrainCamp/lucky-design#readme", 40 | "dependencies": { 41 | "lucky-design": "workspace:*", 42 | "vue": "^3.2.45" 43 | }, 44 | "devDependencies": { 45 | "@antfu/eslint-config": "^0.34.1", 46 | "@commitlint/config-conventional": "^17.4.2", 47 | "@types/node": "^18.11.18", 48 | "@typescript-eslint/eslint-plugin": "^5.48.2", 49 | "@typescript-eslint/parser": "^5.48.2", 50 | "@vitejs/plugin-vue": "^4.0.0", 51 | "@vitejs/plugin-vue-jsx": "^3.0.0", 52 | "bumpp": "^8.2.1", 53 | "chokidar": "^3.5.3", 54 | "commitlint": "^17.4.2", 55 | "eslint": "8.31.0", 56 | "esno": "^0.16.3", 57 | "execa": "^6.1.0", 58 | "fs-extra": "^11.1.0", 59 | "husky": "^8.0.0", 60 | "jsdom": "^21.0.0", 61 | "lint-staged": "^13.1.0", 62 | "perfect-debounce": "^0.1.3", 63 | "picocolors": "^1.0.0", 64 | "prettier": "^2.8.3", 65 | "sass": "^1.57.1", 66 | "tsup": "^6.5.0", 67 | "typescript": "^4.9.3", 68 | "unocss": "^0.49.0", 69 | "vite": "^4.0.0", 70 | "vite-plugin-dts": "^1.7.1", 71 | "vitest": "^0.27.2", 72 | "vue-tsc": "^1.0.11" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/utils' 2 | export * from './src/types' 3 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lucky-design/common", 3 | "version": "0.0.7", 4 | "description": "lucky-design common library", 5 | "license": "MIT", 6 | "sideEffects": false, 7 | "exports": { 8 | ".": { 9 | "types": "./dist/index.d.ts", 10 | "require": "./dist/index.js", 11 | "import": "./dist/index.mjs" 12 | } 13 | }, 14 | "main": "dist/index.js", 15 | "module": "dist/index.mjs", 16 | "types": "dist/index.d.ts", 17 | "files": [ 18 | "dist" 19 | ], 20 | "scripts": { 21 | "build": "tsup", 22 | "dev": "tsup --watch" 23 | }, 24 | "peerDependencies": { 25 | "vue": "^3.2.0" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/common/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { AppContext, Plugin } from 'vue' 2 | 3 | export type SFCWithInstall = T & Plugin 4 | 5 | export type SFCInstallWithContext = SFCWithInstall & { 6 | _context: AppContext | null 7 | } 8 | 9 | export type SizeType = 'xs' | 'sm' | 'md' | 'lg' 10 | export type DirectionType = 'top' | 'right' | 'bottom' | 'left' 11 | export type StatusType = 'primary' | 'success' | 'warning' | 'error' | 'info' 12 | -------------------------------------------------------------------------------- /packages/common/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './install' 2 | -------------------------------------------------------------------------------- /packages/common/src/utils/install.ts: -------------------------------------------------------------------------------- 1 | import type { App, Component } from 'vue' 2 | 3 | import type { SFCInstallWithContext, SFCWithInstall } from '../types' 4 | 5 | export const withInstall = ( 6 | component: T, 7 | name?: string, 8 | ) => { 9 | (component as SFCWithInstall).install = (app): void => { 10 | if (!name) 11 | app.component(`L${component.name}`, component) 12 | else app.component(name, component) 13 | } 14 | 15 | return component as SFCWithInstall 16 | } 17 | 18 | export const withInstallFunction = (fn: T, name: string) => { 19 | (fn as SFCWithInstall).install = (app: App) => { 20 | (fn as SFCInstallWithContext)._context = app._context 21 | app.config.globalProperties[name] = fn 22 | } 23 | 24 | return fn as SFCInstallWithContext 25 | } 26 | export const withInstallObj = >( 27 | main: T, 28 | extra?: E, 29 | ) => { 30 | (main as SFCWithInstall).install = (app): void => { 31 | for (const comp of [main, ...Object.values(extra ?? {})]) 32 | app.component(comp.name, comp) 33 | } 34 | 35 | if (extra) { 36 | for (const [key, comp] of Object.entries(extra)) 37 | (main as any)[key] = comp 38 | } 39 | return main as SFCWithInstall & E 40 | } 41 | 42 | declare const NOOP: () => void 43 | export const withNoopInstall = (component: T) => { 44 | (component as SFCWithInstall).install = NOOP 45 | 46 | return component as SFCWithInstall 47 | } 48 | -------------------------------------------------------------------------------- /packages/common/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['./index.ts'], 5 | clean: true, 6 | format: ['cjs', 'esm'], 7 | external: ['vue'], 8 | dts: true, 9 | minify: true, 10 | }) 11 | -------------------------------------------------------------------------------- /packages/components/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | export {} 3 | declare global { 4 | const EffectScope: typeof import('vue')['EffectScope'] 5 | const computed: typeof import('vue')['computed'] 6 | const createApp: typeof import('vue')['createApp'] 7 | const customRef: typeof import('vue')['customRef'] 8 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 9 | const defineComponent: typeof import('vue')['defineComponent'] 10 | const effectScope: typeof import('vue')['effectScope'] 11 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 12 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 13 | const h: typeof import('vue')['h'] 14 | const inject: typeof import('vue')['inject'] 15 | const isProxy: typeof import('vue')['isProxy'] 16 | const isReactive: typeof import('vue')['isReactive'] 17 | const isReadonly: typeof import('vue')['isReadonly'] 18 | const isRef: typeof import('vue')['isRef'] 19 | const markRaw: typeof import('vue')['markRaw'] 20 | const nextTick: typeof import('vue')['nextTick'] 21 | const onActivated: typeof import('vue')['onActivated'] 22 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 23 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 24 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 25 | const onDeactivated: typeof import('vue')['onDeactivated'] 26 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 27 | const onMounted: typeof import('vue')['onMounted'] 28 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 29 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 30 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 31 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 32 | const onUnmounted: typeof import('vue')['onUnmounted'] 33 | const onUpdated: typeof import('vue')['onUpdated'] 34 | const provide: typeof import('vue')['provide'] 35 | const reactive: typeof import('vue')['reactive'] 36 | const readonly: typeof import('vue')['readonly'] 37 | const ref: typeof import('vue')['ref'] 38 | const resolveComponent: typeof import('vue')['resolveComponent'] 39 | const resolveDirective: typeof import('vue')['resolveDirective'] 40 | const shallowReactive: typeof import('vue')['shallowReactive'] 41 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 42 | const shallowRef: typeof import('vue')['shallowRef'] 43 | const toRaw: typeof import('vue')['toRaw'] 44 | const toRef: typeof import('vue')['toRef'] 45 | const toRefs: typeof import('vue')['toRefs'] 46 | const triggerRef: typeof import('vue')['triggerRef'] 47 | const unref: typeof import('vue')['unref'] 48 | const useAttrs: typeof import('vue')['useAttrs'] 49 | const useCssModule: typeof import('vue')['useCssModule'] 50 | const useCssVars: typeof import('vue')['useCssVars'] 51 | const useSlots: typeof import('vue')['useSlots'] 52 | const watch: typeof import('vue')['watch'] 53 | const watchEffect: typeof import('vue')['watchEffect'] 54 | const watchPostEffect: typeof import('vue')['watchPostEffect'] 55 | const watchSyncEffect: typeof import('vue')['watchSyncEffect'] 56 | } 57 | -------------------------------------------------------------------------------- /packages/components/env.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue' 3 | const component: DefineComponent<{}, {}, any> 4 | export default component 5 | } 6 | -------------------------------------------------------------------------------- /packages/components/index.ts: -------------------------------------------------------------------------------- 1 | import 'uno.css' 2 | 3 | export * from './src/button' 4 | export * from './src/tree' 5 | export * from './src/message' 6 | export * from './src/drawer' 7 | export * from './src/checkbox' 8 | export * from './src/backtop' 9 | export * from './src/icon' 10 | export * from './src/upload' 11 | export * from './src/tooltip' 12 | export * from './src/table' 13 | -------------------------------------------------------------------------------- /packages/components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lucky-design/components", 3 | "version": "0.0.7", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "publishConfig": { 8 | "registry": "https://registry.npmjs.org/", 9 | "access": "public" 10 | }, 11 | "scripts": { 12 | "build": "vite build && vue-tsc --declaration --emitDeclarationOnly --skipLibCheck", 13 | "dev": "esno ../../scripts/dev.ts" 14 | }, 15 | "exports": { 16 | ".": { 17 | "types": "./dist/components/index.d.ts", 18 | "require": "./dist/components.umd.cjs", 19 | "import": "./dist/components.js" 20 | }, 21 | "./dist/style.css": "./dist/style.css" 22 | }, 23 | "files": [ 24 | "dist" 25 | ], 26 | "keywords": [], 27 | "author": "", 28 | "license": "MIT", 29 | "dependencies": { 30 | "@lucky-design/common": "workspace:*", 31 | "@lucky-design/preset": "workspace:*", 32 | "@vueuse/core": "^9.12.0", 33 | "lodash-es": "^4.17.21" 34 | }, 35 | "devDependencies": { 36 | "@iconify-json/mdi": "^1.1.45", 37 | "@unocss/preset-icons": "^0.49.2", 38 | "unplugin-auto-import": "^0.12.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/components/src/backtop/__tests__/backtop.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Backtop.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/backtop/backtop.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | -------------------------------------------------------------------------------- /packages/components/src/backtop/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Backtop from './backtop.vue' 3 | import './style.scss' 4 | 5 | export const LBacktop = withInstall(Backtop, 'LBacktop') 6 | 7 | export default LBacktop 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/backtop/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const BacktopProps = { 4 | bottom: { 5 | type: Number, 6 | default: 50, 7 | }, 8 | right: { 9 | type: Number, 10 | default: 50, 11 | }, 12 | visibilityHeight: { 13 | type: Number, 14 | default: 400, 15 | }, 16 | } 17 | 18 | export type LBacktopProps = ExtractPropTypes 19 | -------------------------------------------------------------------------------- /packages/components/src/backtop/style.scss: -------------------------------------------------------------------------------- 1 | .ld-backtop { 2 | border: 1px solid; 3 | @apply ld-primary fixed right-[50px] bottom-[50px] border-context rounded cursor-pointer p-2 transition-all duration-700 ease-in-out 4 | } 5 | -------------------------------------------------------------------------------- /packages/components/src/button/__tests__/button.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('button.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/button/button.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /packages/components/src/button/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Button from './button.vue' 3 | import './style.scss' 4 | 5 | export const LButton = withInstall(Button, 'LButton') 6 | 7 | export default LButton 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/button/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { SizeType, StatusType } from '@lucky-design/common' 3 | 4 | export const buttonProps = { 5 | /** 6 | * @description: Button type 7 | */ 8 | type: { 9 | type: String as PropType, 10 | default: 'primary', 11 | }, 12 | plain: { 13 | type: Boolean as PropType, 14 | default: false, 15 | }, 16 | /** 17 | * @description: Button text 18 | */ 19 | text: String, 20 | 21 | /** 22 | * @description: Button shape 23 | */ 24 | shape: { 25 | type: String as PropType<'round' | 'circle' | 'square'>, 26 | default: 'square', 27 | }, 28 | 29 | /** 30 | * @description: Button disabled 31 | */ 32 | disabled: { 33 | type: Boolean as PropType, 34 | default: false, 35 | }, 36 | 37 | /** 38 | * @description: Button size 39 | */ 40 | size: { 41 | type: String as PropType, 42 | default: 'md', 43 | }, 44 | } 45 | 46 | export type LButtonProps = ExtractPropTypes 47 | -------------------------------------------------------------------------------- /packages/components/src/button/style.scss: -------------------------------------------------------------------------------- 1 | .ld-button { 2 | @apply ld-primary bg-context text-white p2 cursor-pointer rounded w-fit px-3 hover:opacity-80 border-none; 3 | } 4 | 5 | .plain { 6 | @apply text-context hover:border-context hover:bg-context hover:opacity-100 hover:text-white transition-colors duration-400 ease-in-out; 7 | background-color: rgba(var(--ld-c-context), 0.2); 8 | border: 1px solid; 9 | } 10 | 11 | .xs { 12 | @apply p1 px-2; 13 | font-size: 10px 14 | } 15 | 16 | .sm { 17 | @apply p1.5 px-2.5; 18 | font-size: 12px 19 | } 20 | 21 | .lg { 22 | @apply p3 px-4; 23 | font-size: 16px 24 | } 25 | 26 | .circle { 27 | @apply rounded-full; 28 | } 29 | 30 | .round { 31 | @apply rounded-lg; 32 | } 33 | 34 | .disabled { 35 | @apply cursor-not-allowed opacity-50 hover:opacity-50; 36 | } 37 | 38 | .success { 39 | @apply ld-success; 40 | } 41 | 42 | .warning { 43 | @apply ld-warning; 44 | } 45 | 46 | .error { 47 | @apply ld-error; 48 | } 49 | 50 | .info { 51 | @apply ld-info; 52 | } 53 | -------------------------------------------------------------------------------- /packages/components/src/checkbox/__tests__/checkbox.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('checkbox.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/checkbox/checkbox.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 32 | 33 | 39 | -------------------------------------------------------------------------------- /packages/components/src/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Checkbox from './checkbox.vue' 3 | 4 | export const LCheckbox = withInstall(Checkbox, 'LTree') 5 | 6 | export default LCheckbox 7 | 8 | export * from './props' 9 | -------------------------------------------------------------------------------- /packages/components/src/checkbox/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const checkboxProps = { 4 | value: { 5 | type: Boolean, 6 | default: false, 7 | }, 8 | label: { 9 | type: String, 10 | }, 11 | disabled: { 12 | type: Boolean, 13 | default: false, 14 | }, 15 | trueValue: { 16 | type: [String, Number, Boolean], 17 | default: true, 18 | }, 19 | falseValue: { 20 | type: [String, Number, Boolean], 21 | default: false, 22 | }, 23 | } 24 | 25 | export type CheckboxProps = ExtractPropTypes 26 | -------------------------------------------------------------------------------- /packages/components/src/container/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstallObj, withNoopInstall } from '@lucky-design/common' 2 | import Container from './src/container.vue' 3 | import Aside from './src/aside.vue' 4 | import Footer from './src/footer.vue' 5 | import Header from './src/header.vue' 6 | import Main from './src/main.vue' 7 | 8 | import './style/container.scss' 9 | import './style/aside.scss' 10 | import './style/footer.scss' 11 | import './style/header.scss' 12 | import './style/main.scss' 13 | 14 | export const LContainer = withInstallObj(Container, { 15 | Aside, 16 | Footer, 17 | Header, 18 | Main, 19 | }) 20 | 21 | export default LContainer 22 | 23 | export const LAside = withNoopInstall(Aside) 24 | export const LFooter = withNoopInstall(Footer) 25 | export const LHeader = withNoopInstall(Header) 26 | export const LMain = withNoopInstall(Main) 27 | 28 | export type ContainerInstance = InstanceType 29 | export type AsideInstance = InstanceType 30 | export type FooterInstance = InstanceType 31 | export type HeaderInstance = InstanceType 32 | export type MainInstance = InstanceType 33 | -------------------------------------------------------------------------------- /packages/components/src/container/props.ts: -------------------------------------------------------------------------------- 1 | export const asideProps = defineProps({ 2 | width: { 3 | type: String, 4 | default: null, 5 | }, 6 | }) 7 | 8 | export const containerProps = defineProps({ 9 | direction: { 10 | type: String, 11 | }, 12 | }) 13 | 14 | export const footerProps = defineProps({ 15 | height: { 16 | type: String, 17 | default: null, 18 | }, 19 | }) 20 | export const headerProps = defineProps({ 21 | height: { 22 | type: String, 23 | default: null, 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /packages/components/src/container/src/aside.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /packages/components/src/container/src/container.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 43 | -------------------------------------------------------------------------------- /packages/components/src/container/src/footer.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /packages/components/src/container/src/header.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /packages/components/src/container/src/main.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /packages/components/src/container/style/aside.scss: -------------------------------------------------------------------------------- 1 | @use 'mixins/mixins' as *; 2 | 3 | @include b(aside) { 4 | overflow: auto; 5 | box-sizing: border-box; 6 | flex-shrink: 0; 7 | width: var(#{getCssVarName('aside', 'width')}, 300px); 8 | } 9 | -------------------------------------------------------------------------------- /packages/components/src/container/style/common/var.scss: -------------------------------------------------------------------------------- 1 | /* Element Chalk Variables */ 2 | @use 'sass:math'; 3 | @use 'sass:map'; 4 | 5 | @use '../mixins/function.scss' as *; 6 | 7 | 8 | // header 9 | $header: () !default; 10 | $header: map.merge( 11 | ( 12 | 'padding': 0 20px, 13 | 'height': 60px, 14 | ), 15 | $header 16 | ); 17 | // main 18 | $main: () !default; 19 | $main: map.merge( 20 | ( 21 | 'padding': 20px, 22 | ), 23 | $main 24 | ); 25 | // footer 26 | $footer: () !default; 27 | $footer: map.merge( 28 | ( 29 | 'padding': 0 20px, 30 | 'height': 60px, 31 | ), 32 | $footer 33 | ); 34 | -------------------------------------------------------------------------------- /packages/components/src/container/style/container.scss: -------------------------------------------------------------------------------- 1 | @use 'mixins/mixins' as *; 2 | 3 | @include b(container) { 4 | display: flex; 5 | flex-direction: row; 6 | flex: 1; 7 | flex-basis: auto; 8 | box-sizing: border-box; 9 | min-width: 0; 10 | 11 | @include when(vertical) { 12 | flex-direction: column; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/components/src/container/style/footer.scss: -------------------------------------------------------------------------------- 1 | @use 'mixins/mixins' as *; 2 | @use 'mixins/var' as *; 3 | @use 'common/var' as *; 4 | 5 | @include b(footer) { 6 | @include set-component-css-var('footer', $footer); 7 | 8 | padding: getCssVar('footer-padding'); 9 | box-sizing: border-box; 10 | flex-shrink: 0; 11 | height: getCssVar('footer-height'); 12 | } 13 | -------------------------------------------------------------------------------- /packages/components/src/container/style/header.scss: -------------------------------------------------------------------------------- 1 | @use 'mixins/mixins' as *; 2 | @use 'mixins/var' as *; 3 | @use 'common/var' as *; 4 | 5 | @include b(header) { 6 | @include set-component-css-var('header', $header); 7 | 8 | padding: getCssVar('header-padding'); 9 | box-sizing: border-box; 10 | flex-shrink: 0; 11 | height: getCssVar('header-height'); 12 | } 13 | -------------------------------------------------------------------------------- /packages/components/src/container/style/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucky-design-org/lucky-design/d99317a1abbf1f4a0901481529338a86f128599c/packages/components/src/container/style/index.ts -------------------------------------------------------------------------------- /packages/components/src/container/style/main.scss: -------------------------------------------------------------------------------- 1 | @use 'mixins/mixins' as *; 2 | @use 'mixins/var' as *; 3 | @use 'common/var' as *; 4 | 5 | @include b(main) { 6 | @include set-component-css-var('main', $main); 7 | 8 | display: block; 9 | flex: 1; 10 | flex-basis: auto; 11 | overflow: auto; 12 | box-sizing: border-box; 13 | padding: getCssVar('main-padding'); 14 | } 15 | -------------------------------------------------------------------------------- /packages/components/src/container/style/mixins/_var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | @use 'config'; 4 | @use 'function' as *; 5 | 6 | 7 | // set all css var for component by map 8 | @mixin set-component-css-var($name, $variables) { 9 | @each $attribute, $value in $variables { 10 | @if $attribute == 'default' { 11 | #{getCssVarName($name)}: #{$value}; 12 | } @else { 13 | #{getCssVarName($name, $attribute)}: #{$value}; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/components/src/container/style/mixins/config.scss: -------------------------------------------------------------------------------- 1 | $namespace: 'ld' !default; 2 | $common-separator: '-' !default; 3 | $element-separator: '__' !default; 4 | $modifier-separator: '--' !default; 5 | $state-prefix: 'is-' !default; 6 | -------------------------------------------------------------------------------- /packages/components/src/container/style/mixins/function.scss: -------------------------------------------------------------------------------- 1 | @use 'config'; 2 | // join var name 3 | // joinVarName(('button', 'text-color')) => '--el-button-text-color' 4 | @function joinVarName($list) { 5 | $name: '--' + config.$namespace; 6 | @each $item in $list { 7 | @if $item != '' { 8 | $name: $name + '-' + $item; 9 | } 10 | } 11 | @return $name; 12 | } 13 | 14 | // getCssVarName('button', 'text-color') => '--el-button-text-color' 15 | @function getCssVarName($args...) { 16 | @return joinVarName($args); 17 | } 18 | 19 | // getCssVar('button', 'text-color') => var(--el-button-text-color) 20 | @function getCssVar($args...) { 21 | @return var(#{joinVarName($args)}); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /packages/components/src/container/style/mixins/mixins.scss: -------------------------------------------------------------------------------- 1 | @use 'function' as *; 2 | @forward 'config'; 3 | @forward 'function'; 4 | @forward '_var'; 5 | @use 'config' as *; 6 | 7 | // BEM 8 | @mixin b($block) { 9 | $B: $namespace + '-' + $block !global; 10 | 11 | .#{$B} { 12 | @content; 13 | } 14 | } 15 | @mixin when($state) { 16 | @at-root { 17 | &.#{$state-prefix + $state} { 18 | @content; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/components/src/drawer/__tests__/drawer.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('drawer.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/drawer/drawer.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | -------------------------------------------------------------------------------- /packages/components/src/drawer/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Drawer from './drawer.vue' 3 | import './style.scss' 4 | 5 | export const LDrawer = withInstall(Drawer, 'LDrawer') 6 | 7 | export default LDrawer 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/drawer/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { DirectionType } from '@lucky-design/common' 3 | 4 | export const drawerProps = { 5 | /** 6 | * @description: drawer title 7 | */ 8 | title: String, 9 | /** 10 | * @description: drawer appearance direction 11 | */ 12 | direction: { 13 | type: String as PropType, 14 | default: 'right', 15 | }, 16 | /** 17 | * @description: Whether to show the mask 18 | */ 19 | visible: { 20 | type: Boolean, 21 | default: false, 22 | }, 23 | /** 24 | * @description: close the drawer 25 | */ 26 | close: { 27 | type: Function as PropType<() => void>, 28 | default: () => {}, 29 | }, 30 | /** 31 | * @description: drawer background color 32 | * @default: white 33 | */ 34 | bgColor: { 35 | type: String, 36 | default: 'white', 37 | }, 38 | } 39 | 40 | export type LDrawerProps = ExtractPropTypes 41 | -------------------------------------------------------------------------------- /packages/components/src/drawer/style.scss: -------------------------------------------------------------------------------- 1 | .ld-drawer { 2 | @apply fixed w-[30vw] min-w-[300px] h-full z-50 shadow-lg py-4 px-8 3 | } 4 | 5 | .header { 6 | @apply flex items-center justify-between mb-8 7 | } 8 | 9 | .close { 10 | @apply cursor-pointer p2 text-2xl 11 | } 12 | 13 | .mask { 14 | @apply fixed top-0 left-0 w-screen h-screen bg-black opacity-50 transition-all duration-300 ease-in-out z-20 15 | } 16 | 17 | .right { 18 | @apply right-0 top-0 border-l-1 border-gray 19 | } 20 | 21 | .left { 22 | @apply top-0 left-0 border-r-1 border-gray 23 | } 24 | 25 | .top { 26 | @apply top-0 left-0 right-0 border-b-1 border-gray h-[30vh] min-h-[300px] w-full 27 | } 28 | 29 | .bottom { 30 | @apply bottom-0 left-0 right-0 border-t-1 border-gray h-[30vh] min-h-[300px] w-full 31 | } 32 | -------------------------------------------------------------------------------- /packages/components/src/icon/__tests__/icon.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('icon.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/icon/icon.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /packages/components/src/icon/iconList.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { className: 'icon-arrow-up-filling' }, 3 | { className: 'icon-arrow-down-filling' }, 4 | { className: 'icon-arrow-left-filling' }, 5 | { className: 'icon-arrow-right-filling' }, 6 | ] 7 | -------------------------------------------------------------------------------- /packages/components/src/icon/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Icon from './icon.vue' 3 | import './style.scss' 4 | 5 | export const LIcon = withInstall(Icon, 'LIcon') 6 | 7 | export default LIcon 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/icon/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | // enum IconClassNames {} 4 | 5 | export const iconProps = { 6 | className: { 7 | type: String, 8 | required: true, 9 | }, 10 | } 11 | 12 | export type LIconProps = ExtractPropTypes 13 | -------------------------------------------------------------------------------- /packages/components/src/icon/style.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucky-design-org/lucky-design/d99317a1abbf1f4a0901481529338a86f128599c/packages/components/src/icon/style.scss -------------------------------------------------------------------------------- /packages/components/src/message/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstallFunction } from '@lucky-design/common' 2 | import { closeAll, createMessage, createSubHandler } from './manager' 3 | import type { Message } from './types' 4 | import { messageTypes } from './types' 5 | import './style.scss' 6 | 7 | const message = createMessage as Message 8 | 9 | for (const type of messageTypes) 10 | message[type] = createSubHandler(type) 11 | 12 | message.closeAll = closeAll 13 | const LMessage = withInstallFunction(message, '$message') 14 | 15 | export * from './props' 16 | export default LMessage 17 | export { LMessage } 18 | -------------------------------------------------------------------------------- /packages/components/src/message/manager.ts: -------------------------------------------------------------------------------- 1 | import { h, render, shallowReactive } from 'vue' 2 | import type { MessageInstance, MessageType } from './types' 3 | import Message from './message.vue' 4 | import type { LMessageProps } from './props' 5 | 6 | const instances: MessageInstance[] = shallowReactive([]) 7 | let currId = 1 8 | 9 | export function createMessage(props: LMessageProps) { 10 | const el = document.createElement('div') 11 | const id = `lucky-message-${currId}` 12 | 13 | const vnode = h( 14 | Message, 15 | { 16 | ...props, 17 | id, 18 | onDestroy: () => { 19 | // 移除DOM 20 | removeMessageById(id) 21 | render(null, el) 22 | }, 23 | }, 24 | () => props.message, 25 | ) 26 | render(vnode, el) 27 | document.body.appendChild(el.firstElementChild!) 28 | 29 | const instance: MessageInstance = { 30 | id, 31 | vnode, 32 | component: vnode.component!, 33 | props, 34 | close: () => { 35 | vnode.component!.exposed!.visible.value = false 36 | }, 37 | } 38 | instances.push(instance) 39 | currId++ 40 | 41 | return instance 42 | } 43 | 44 | export function removeMessage(instance: MessageInstance) { 45 | const index = instances.indexOf(instance) 46 | if (index === -1) 47 | return 48 | instances.splice(index, 1) 49 | instance.close() 50 | } 51 | 52 | export function removeMessageById(id: string) { 53 | const index = instances.findIndex(item => item.id === id) 54 | if (index === -1) 55 | return 56 | instances[index].close() 57 | instances.splice(index, 1) 58 | } 59 | 60 | export const getLastOffset = (id: string): number => { 61 | const index = instances.findIndex(item => item.id === id) 62 | const target = instances[index - 1] 63 | 64 | if (!target) 65 | return 0 66 | return target.component.exposed!.bottom.value 67 | } 68 | 69 | export function createSubHandler(type: MessageType) { 70 | return function (message: any, options: LMessageProps) { 71 | return createMessage({ 72 | ...options, 73 | type, 74 | message, 75 | }) 76 | } 77 | } 78 | 79 | export function closeAll() { 80 | for (const instance of instances) instance.close() 81 | 82 | instances.splice(0, instances.length) 83 | } 84 | -------------------------------------------------------------------------------- /packages/components/src/message/message.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 74 | -------------------------------------------------------------------------------- /packages/components/src/message/props.ts: -------------------------------------------------------------------------------- 1 | import type { MessageType } from './types' 2 | 3 | export interface LMessageProps { 4 | type?: MessageType 5 | message: string 6 | timeout?: number 7 | offset?: number 8 | closeBtn?: boolean 9 | } 10 | -------------------------------------------------------------------------------- /packages/components/src/message/style.scss: -------------------------------------------------------------------------------- 1 | $colorTypes: ( 2 | "info": "text-blue", 3 | "warning": "text-orange", 4 | "success": "text-green", 5 | "error": "text-red", 6 | ); 7 | 8 | $iconTypes: ( 9 | "info": "i-mdi-information", 10 | "warning": "i-mdi-alert-circle", 11 | "success": "i-mdi-check-circle", 12 | "error": "i-mdi-close-circle", 13 | ); 14 | 15 | .ld-message { 16 | box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); 17 | transform: translate(-50%, 0); 18 | max-width: 50%; 19 | z-index: 30; 20 | @apply bg-white top-20px left-50% px-3 py-2 rd-1 text-gray-5 flex items-center transition-all-300 fixed; 21 | 22 | .message-content { 23 | overflow-wrap: anywhere; 24 | } 25 | 26 | .close-btn { 27 | @apply text-sm text-gray hover:text-dark ml-2 cursor-pointer transition-all-300 flex-shrink-0; 28 | } 29 | 30 | .message-icon { 31 | @apply text-lg mr-2 flex-shrink-0; 32 | } 33 | 34 | @each $type, $color in $iconTypes { 35 | &.is-#{$type} .message-icon { 36 | @apply #{$color}; 37 | } 38 | } 39 | @each $type, $color in $colorTypes { 40 | &.is-#{$type} .message-icon { 41 | @apply #{$color}; 42 | } 43 | } 44 | } 45 | 46 | .ld-message-fade-enter-from, 47 | .ld-message-fade-leave-to { 48 | transform: translate(-50%, -100%); 49 | @apply opacity-0; 50 | } 51 | -------------------------------------------------------------------------------- /packages/components/src/message/types.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentInternalInstance, VNode } from 'vue' 2 | import type { closeAll, createMessage, createSubHandler } from './manager' 3 | 4 | export interface MessageInstance { 5 | id: string 6 | vnode: VNode 7 | component: ComponentInternalInstance 8 | props: any 9 | close: Function 10 | } 11 | 12 | export const messageTypes = ['info', 'success', 'warning', 'error'] as const 13 | 14 | export type MessageType = (typeof messageTypes)[number] 15 | 16 | export type Message = typeof createMessage & Record> & { closeAll: typeof closeAll } 17 | -------------------------------------------------------------------------------- /packages/components/src/table/__tests__/table.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('table.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/table/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Table from './table.vue' 3 | import './style.scss' 4 | 5 | export const LTable = withInstall(Table, 'LTable') 6 | 7 | export default LTable 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/table/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | // import type { DirectionType } from '@lucky-design/common'common 4 | 5 | interface TableColumn { 6 | label: string 7 | prop: string 8 | } 9 | interface TableRow { 10 | id: number 11 | [key: string]: string | number 12 | } 13 | interface Sort { 14 | column: String 15 | order: 'asc' | 'desc' 16 | } 17 | export type { 18 | TableColumn, 19 | TableRow, 20 | Sort, 21 | } 22 | export const tableProps = { 23 | /** 24 | * @description: table columns 25 | */ 26 | columns: { 27 | type: Array as () => TableColumn[], 28 | required: true, 29 | }, 30 | /** 31 | * @description: table rows 32 | */ 33 | rows: { 34 | type: Array as () => TableRow[], 35 | required: true, 36 | }, 37 | /** 38 | * @description: sort orders about table cells' content 39 | */ 40 | striped: { 41 | type: Boolean, 42 | default: false, 43 | }, 44 | defaultSort: { 45 | // type: Object as PropType<() => Sort | null>, 46 | // default: { column: 'id', order: 'asc' }, 47 | type: String, 48 | default: 'asc', 49 | }, 50 | tableClass: { 51 | type: String, 52 | default: '', 53 | }, 54 | 55 | /** 56 | * @description: Whether to visible the browser windows 57 | */ 58 | visible: { 59 | type: Boolean, 60 | default: true, 61 | }, 62 | } 63 | // export const data = {TableColumn, TableRow} 64 | export type LTableProps = ExtractPropTypes 65 | -------------------------------------------------------------------------------- /packages/components/src/table/style.scss: -------------------------------------------------------------------------------- 1 | .ld-table { 2 | @apply fixed w-[30vw] min-w-[300px] h-full z-50 bg-white shadow-lg p-8 3 | } 4 | 5 | .header { 6 | @apply flex items-center justify-between mb-8 7 | } 8 | 9 | .close { 10 | @apply cursor-pointer p2 11 | } 12 | 13 | .mask { 14 | @apply fixed top-0 left-0 w-screen h-screen bg-black opacity-50 transition-all duration-300 ease-in-out 15 | } 16 | 17 | .right { 18 | @apply right-0 top-0 border-l-1 border-gray 19 | } 20 | th { 21 | cursor: pointer; 22 | } 23 | 24 | th, td { 25 | min-width: 120px; 26 | padding: 10px; 27 | text-align: left; 28 | } 29 | 30 | thead { 31 | background-color: #eee; 32 | } 33 | 34 | tbody { 35 | overflow-y: scroll; 36 | height: 300px; 37 | } 38 | 39 | table { 40 | width: 100%; 41 | } 42 | -------------------------------------------------------------------------------- /packages/components/src/table/table.vue: -------------------------------------------------------------------------------- 1 | 184 | 185 | 208 | 209 | 278 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/content.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 87 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/helper.ts: -------------------------------------------------------------------------------- 1 | import { Fragment, Text, h } from 'vue' 2 | import type { VNode } from 'vue' 3 | 4 | export const findFirstLegitChild = (node: VNode[]) => { 5 | for (const child of node) { 6 | switch (child.type) { 7 | case Comment: 8 | continue 9 | 10 | case Text: 11 | case 'svg': 12 | return h('span', null, child) 13 | 14 | case Fragment: 15 | return findFirstLegitChild(child.children as VNode[]) 16 | 17 | default: 18 | return child 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | 3 | import ToolTip from './tooltip.vue' 4 | import './style.scss' 5 | 6 | export const LToolTip = withInstall(ToolTip) 7 | 8 | export default LToolTip 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { Placement } from './types' 3 | 4 | export const toolTipProps = { 5 | placement: { 6 | type: String as PropType, 7 | default: 'bottom', 8 | }, 9 | content: String, 10 | appendTo: String, 11 | visible: Boolean, 12 | } 13 | 14 | export type LToolTipProps = ExtractPropTypes 15 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/style.scss: -------------------------------------------------------------------------------- 1 | .ld-tooltip { 2 | @apply absolute c-white b-rd-5px left-0 top-0; 3 | background-color: rgb(51, 51, 51); 4 | padding: 5px 10px; 5 | font-size: 12px; 6 | .ld-tooltip__arrow { 7 | @apply absolute; 8 | &::before { 9 | @apply w-10px h-10px absolute content-empty rotate-45 left-0 top-0; 10 | background-color: rgb(51, 51, 51); 11 | } 12 | &[placement='top'] { 13 | bottom: 5px; 14 | left: 0px; 15 | } 16 | &[placement='right'] { 17 | left: -5px; 18 | top: 0px; 19 | } 20 | &[placement='left'] { 21 | right: 5px; 22 | top: 0px; 23 | } 24 | &[placement='bottom'] { 25 | top: -5px; 26 | left: 0px; 27 | } 28 | } 29 | } 30 | 31 | .ld-tooltip-content-enter-from, 32 | .ld-tooltip-content-leave-to { 33 | @apply opacity-0; 34 | } 35 | 36 | .ld-tooltip-content-enter-active { 37 | transition: opacity 0.25s; 38 | } 39 | .ld-tooltip-content-leave-active { 40 | transition: opacity 0.25s; 41 | } 42 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/tooltip.vue: -------------------------------------------------------------------------------- 1 | 72 | 73 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/trigger.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /packages/components/src/tooltip/types.ts: -------------------------------------------------------------------------------- 1 | export type Placement = 'bottom' | 'left' | 'right' | 'top' 2 | -------------------------------------------------------------------------------- /packages/components/src/tree/__tests__/tree.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Tree.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/tree/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Tree from './tree.vue' 3 | import './style.scss' 4 | 5 | export const LTree = withInstall(Tree, 'LTree') 6 | 7 | export default LTree 8 | 9 | export * from './props' 10 | -------------------------------------------------------------------------------- /packages/components/src/tree/props.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const treeNodeProps = {} 4 | 5 | export const treeItemProps = { 6 | items: { 7 | type: Object as PropType, 8 | default: () => {}, 9 | }, 10 | dataKey: Object as PropType, 11 | index: Number, 12 | icon: { 13 | type: String, 14 | default: 'icon-arrow-right-filling', 15 | }, 16 | defaultOpenNodes: { 17 | type: Array, 18 | default: () => [], 19 | }, 20 | options: { 21 | type: Object, 22 | default: () => { 23 | return {} 24 | }, 25 | }, 26 | tabIndexs: Object as PropType, 27 | multiple: Boolean, 28 | defaultSelectNodes: { 29 | type: Array, 30 | default: () => [], 31 | }, 32 | children: { 33 | type: Array as PropType, 34 | }, 35 | } 36 | export type TreeNodeProps = ExtractPropTypes 37 | export type TreeItemProps = ExtractPropTypes 38 | -------------------------------------------------------------------------------- /packages/components/src/tree/style.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | margin-left: 20px; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/tree/tree.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 33 | 34 | 39 | -------------------------------------------------------------------------------- /packages/components/src/upload/__test__/upload.test.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Upload.vue', () => { 4 | it('hello world', () => { 5 | expect(1).toBe(1) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/components/src/upload/ajax.ts: -------------------------------------------------------------------------------- 1 | type XMLHttpFN = (ev: ProgressEvent) => void 2 | 3 | export interface UploadRequestOptions { 4 | action: string 5 | method: string 6 | file: File 7 | data?: { [k: string]: string | Blob } 8 | filename: string 9 | withCredentials: boolean 10 | onProgress?: XMLHttpFN 11 | onSuccess: (res: any) => void 12 | onError?: ( 13 | actions: string, 14 | options: UploadRequestOptions, 15 | xhr: XMLHttpRequest 16 | ) => void 17 | } 18 | 19 | const getResponce = (xhr: XMLHttpRequest) => { 20 | const text = xhr.responseText || xhr.response 21 | 22 | try { 23 | return JSON.parse(text) 24 | } 25 | catch (error) { 26 | return text 27 | } 28 | } 29 | 30 | export const httpRequest = (options: UploadRequestOptions): XMLHttpRequest => { 31 | if (typeof XMLHttpRequest === 'undefined') 32 | throw new Error('XMLHttpRequest is undefined') 33 | const { 34 | action, 35 | method, 36 | file, 37 | data, 38 | filename, 39 | withCredentials, 40 | onProgress, 41 | onSuccess, 42 | onError, 43 | } = options 44 | 45 | const xhr = new XMLHttpRequest() 46 | 47 | const formData = new FormData() 48 | 49 | if (data) { 50 | for (const key in data) 51 | formData.append(key, data[key]) 52 | } 53 | 54 | xhr.open(method, action, true) 55 | 56 | xhr.addEventListener('progress', (ev) => { 57 | onProgress && onProgress(ev) 58 | }) 59 | 60 | xhr.addEventListener('error', () => { 61 | onError && onError(action, options, xhr) 62 | }) 63 | 64 | xhr.addEventListener('load', () => { 65 | onSuccess && onSuccess(getResponce(xhr)) 66 | }) 67 | 68 | xhr.withCredentials = withCredentials 69 | 70 | formData.append(filename, file, file.name) 71 | 72 | xhr.send(formData) 73 | return xhr 74 | } 75 | -------------------------------------------------------------------------------- /packages/components/src/upload/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@lucky-design/common' 2 | import Upload from './upload.vue' 3 | import './style.scss' 4 | 5 | export const LUpload = withInstall(Upload) 6 | 7 | export * from './props' 8 | export default LUpload 9 | -------------------------------------------------------------------------------- /packages/components/src/upload/props.ts: -------------------------------------------------------------------------------- 1 | import type { MethodType } from './types' 2 | import type { UploadRequestOptions } from './ajax' 3 | 4 | export interface IUploadProps { 5 | action: string 6 | data?: { [k: string]: string | Blob } 7 | method?: MethodType 8 | name?: string 9 | multiple?: boolean 10 | withCredentials?: boolean 11 | disabled?: boolean 12 | beforeUpload?: (file: File) => Promise 13 | onProgress?: (et: ProgressEvent) => void 14 | onSuccess?: (res: any) => void 15 | onError?: ( 16 | actions: string, 17 | options: UploadRequestOptions, 18 | xhr: XMLHttpRequest 19 | ) => void 20 | } 21 | -------------------------------------------------------------------------------- /packages/components/src/upload/style.scss: -------------------------------------------------------------------------------- 1 | .ld-upload { 2 | @apply cursor-pointer flex-inline justify-center items-center; 3 | .ld-upload_input { 4 | @apply hidden; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/components/src/upload/types.ts: -------------------------------------------------------------------------------- 1 | export type MethodType = 2 | | 'post' 3 | | 'get' 4 | | 'delete' 5 | | 'head' 6 | | 'option' 7 | | 'patch' 8 | | 'put' 9 | -------------------------------------------------------------------------------- /packages/components/src/upload/upload.vue: -------------------------------------------------------------------------------- 1 | 114 | 115 | 130 | -------------------------------------------------------------------------------- /packages/components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "exclude": [ 4 | "**/dist/**", 5 | "unocss.config.ts" 6 | ], 7 | "include": [ 8 | "**/*.ts", 9 | "**/*.d.ts", 10 | "**/*.vue", 11 | "**/*.tsx", 12 | ], 13 | "compilerOptions": { 14 | "declaration": false, 15 | "composite": false, 16 | "outDir": "./dist" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/components/unocss.config.ts: -------------------------------------------------------------------------------- 1 | import type { Preset } from 'unocss' 2 | import { presetAttributify, presetUno, transformerDirectives } from 'unocss' 3 | import { defineConfig } from 'unocss/vite' 4 | import { presetLuckyDesign } from '@lucky-design/preset' 5 | import presetIcons from '@unocss/preset-icons' 6 | export default defineConfig({ 7 | presets: [ 8 | presetIcons() as unknown as Preset, 9 | presetAttributify(), 10 | presetLuckyDesign() as unknown as Preset, 11 | presetUno(), 12 | ], 13 | transformers: [transformerDirectives()], 14 | }) 15 | -------------------------------------------------------------------------------- /packages/components/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { resolve } from 'path' 3 | import fs from 'fs' 4 | import AutoImport from 'unplugin-auto-import/vite' 5 | import { defineConfig } from 'vite' 6 | import Vue from '@vitejs/plugin-vue' 7 | import VueJSX from '@vitejs/plugin-vue-jsx' 8 | import Unocss from 'unocss/vite' 9 | import fsExtra from 'fs-extra' 10 | 11 | let config 12 | 13 | export default defineConfig({ 14 | build: { 15 | lib: { 16 | entry: path.resolve(__dirname, 'index.ts'), 17 | name: '@lucky-design/components', 18 | }, 19 | rollupOptions: { 20 | external: [ 21 | 'vue', 22 | ], 23 | output: { 24 | globals: { 25 | vue: 'Vue', 26 | }, 27 | }, 28 | }, 29 | }, 30 | plugins: [ 31 | Vue(), 32 | VueJSX(), 33 | AutoImport({ 34 | imports: ['vue'], 35 | include: [ 36 | /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx 37 | ], 38 | dts: 'auto-imports.d.ts', 39 | }), 40 | Unocss(), 41 | { 42 | name: 'vite-plugin-copy-style', 43 | apply: 'build', 44 | enforce: 'post', 45 | configResolved(_config) { 46 | config = _config 47 | }, 48 | async closeBundle() { 49 | const { root, build } = config 50 | const { outDir } = build 51 | const styleFile = resolve(root, outDir, 'style.css') 52 | if (fs.existsSync(styleFile)) { 53 | await fsExtra.copyFile( 54 | styleFile, 55 | resolve(__dirname, '../lucky-design/src/style.css'), 56 | ) 57 | } 58 | }, 59 | }, 60 | ], 61 | }) 62 | -------------------------------------------------------------------------------- /packages/lucky-design/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lucky-design", 3 | "type": "module", 4 | "version": "0.0.7", 5 | "license": "MIT", 6 | "keywords": [ 7 | "lucky-design", 8 | "unocss", 9 | "vueuse" 10 | ], 11 | "sideEffects": false, 12 | "exports": { 13 | ".": { 14 | "types": "./dist/lucky-design/src/index.d.ts", 15 | "require": "./dist/lucky-design.umd.cjs", 16 | "import": "./dist/lucky-design.js" 17 | }, 18 | "./dist/style.css": "./dist/style.css" 19 | }, 20 | "main": "./dist/lucky-design.umd.cjs", 21 | "module": "./dist/lucky-design.js", 22 | "types": "./dist/lucky-design/src/index.d.ts", 23 | "files": [ 24 | "dist" 25 | ], 26 | "scripts": { 27 | "build": "vue-tsc --declaration --emitDeclarationOnly --skipLibCheck && vite build", 28 | "dev": "esno ../../scripts/dev.ts" 29 | }, 30 | "dependencies": { 31 | "@lucky-design/components": "workspace:*" 32 | }, 33 | "publishConfig": { 34 | "access": "public" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/lucky-design/src/components.ts: -------------------------------------------------------------------------------- 1 | import { 2 | LBacktop, 3 | LButton, 4 | LCheckbox, 5 | LDrawer, 6 | LIcon, 7 | LMessage, 8 | LTable, 9 | LToolTip, 10 | LTree, 11 | LUpload, 12 | } from '@lucky-design/components' 13 | 14 | export const plugins = [ 15 | LButton, 16 | LTree, 17 | LMessage, 18 | LDrawer, 19 | LUpload, 20 | LBacktop, 21 | LCheckbox, 22 | LIcon, 23 | LToolTip, 24 | LTable, 25 | ] as const 26 | -------------------------------------------------------------------------------- /packages/lucky-design/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { App, Plugin } from 'vue' 2 | import { plugins } from './components' 3 | 4 | export * from './components' 5 | 6 | export const INSTALLED_KEY = Symbol('LuckyDesign_Installed') 7 | 8 | function createInstaller(components: Plugin[]) { 9 | const install = (app: App, options = {}) => { 10 | if (app[INSTALLED_KEY]) 11 | return 12 | 13 | app[INSTALLED_KEY] = true 14 | components.forEach(c => app.use(c)) 15 | 16 | if (options) 17 | app.provide(INSTALLED_KEY, options) 18 | } 19 | 20 | return { 21 | install, 22 | } 23 | } 24 | 25 | export * from '@lucky-design/components' 26 | 27 | export default createInstaller(plugins as unknown as Plugin[]) 28 | -------------------------------------------------------------------------------- /packages/lucky-design/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "exclude": ["**/dist/**"], 4 | "include": ["**/*.ts", "**/*.d.ts"], 5 | "compilerOptions": { 6 | "declaration": false, 7 | "composite": false, 8 | "outDir": "./dist" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/lucky-design/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { resolve } from 'path' 3 | import { defineConfig } from 'vite' 4 | import Vue from '@vitejs/plugin-vue' 5 | import fs from 'fs-extra' 6 | 7 | let config 8 | 9 | export default defineConfig({ 10 | build: { 11 | emptyOutDir: false, 12 | lib: { 13 | entry: path.resolve(__dirname, 'src/index.ts'), 14 | name: 'lucky-design', 15 | }, 16 | rollupOptions: { 17 | external: [ 18 | 'vue', 19 | ], 20 | output: { 21 | globals: { 22 | vue: 'Vue', 23 | }, 24 | }, 25 | }, 26 | }, 27 | plugins: [ 28 | Vue(), 29 | { 30 | name: 'vite-plugin-copy-style', 31 | apply: 'build', 32 | enforce: 'post', 33 | configResolved(_config) { 34 | config = _config 35 | }, 36 | async closeBundle() { 37 | const { build, root } = config 38 | const { outDir } = build 39 | const styleFile = resolve(__dirname, 'src/style.css') 40 | await fs.copyFile( 41 | styleFile, 42 | resolve(root, outDir, 'style.css'), 43 | ) 44 | }, 45 | }, 46 | ], 47 | }) 48 | -------------------------------------------------------------------------------- /packages/preset/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/colors' 2 | 3 | export * from './src/preset' 4 | -------------------------------------------------------------------------------- /packages/preset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lucky-design/preset", 3 | "version": "0.0.7", 4 | "description": "lucky-design preset library", 5 | "license": "MIT", 6 | "sideEffects": false, 7 | "exports": { 8 | ".": { 9 | "types": "./dist/index.d.ts", 10 | "require": "./dist/index.js", 11 | "import": "./dist/index.mjs" 12 | } 13 | }, 14 | "main": "dist/index.js", 15 | "module": "dist/index.mjs", 16 | "types": "dist/index.d.ts", 17 | "files": [ 18 | "dist" 19 | ], 20 | "scripts": { 21 | "build": "tsup", 22 | "dev": "tsup --watch" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "dependencies": { 28 | "@unocss/preset-mini": "^0.49.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/preset/src/colors.ts: -------------------------------------------------------------------------------- 1 | import { hex2rgba } from '@unocss/preset-mini/utils' 2 | 3 | export const lightTheme = { 4 | '--ld-colors-blue50': '#EDF5FF', 5 | '--ld-colors-blue100': '#E1EFFF', 6 | '--ld-colors-blue200': '#ecf5ff', 7 | '--ld-colors-blue300': '#B7D5F8', 8 | '--ld-colors-blue400': '#79bbff', 9 | '--ld-colors-blue500': '#409EFF', 10 | '--ld-colors-blue600': '#0072F5', 11 | '--ld-colors-blue700': '#005FCC', 12 | '--ld-colors-blue800': '#004799', 13 | '--ld-colors-blue900': '#00254D', 14 | '--ld-colors-purple50': '#F7F2FD', 15 | '--ld-colors-purple100': '#F1E8FB', 16 | '--ld-colors-purple200': '#EADCF8', 17 | '--ld-colors-purple300': '#E0CBF5', 18 | '--ld-colors-purple400': '#D1B1F0', 19 | '--ld-colors-purple500': '#BC8EE9', 20 | '--ld-colors-purple600': '#A855F7', 21 | '--ld-colors-purple700': '#6622AA', 22 | '--ld-colors-purple800': '#4D1980', 23 | '--ld-colors-purple900': '#290E44', 24 | '--ld-colors-green50': '#F1FDF7', 25 | '--ld-colors-green100': '#E8FCF1', 26 | '--ld-colors-green200': '#DAFBE8', 27 | '--ld-colors-green300': '#C8F9DD', 28 | '--ld-colors-green400': '#ADF5CC', 29 | '--ld-colors-green500': '#67eaa0', 30 | '--ld-colors-green600': '#0ACF83', 31 | '--ld-colors-green700': '#13A452', 32 | '--ld-colors-green800': '#108944', 33 | '--ld-colors-green900': '#06371B', 34 | '--ld-colors-yellow50': '#FEF9F0', 35 | '--ld-colors-yellow100': '#FEF5E7', 36 | '--ld-colors-yellow200': '#FDEFD8', 37 | '--ld-colors-yellow300': '#FCE7C5', 38 | '--ld-colors-yellow400': '#FBDBA7', 39 | '--ld-colors-yellow500': '#F9CB80', 40 | '--ld-colors-yellow600': '#F5A524', 41 | '--ld-colors-yellow700': '#B97509', 42 | '--ld-colors-yellow800': '#925D07', 43 | '--ld-colors-yellow900': '#4E3104', 44 | '--ld-colors-red50': '#FEF0F5', 45 | '--ld-colors-red100': '#FEE7EF', 46 | '--ld-colors-red200': '#FDD8E5', 47 | '--ld-colors-red300': '#FCC5D8', 48 | '--ld-colors-red400': '#FAA8C5', 49 | '--ld-colors-red500': '#f89898', 50 | '--ld-colors-red600': '#FF5C5C', 51 | '--ld-colors-red700': '#c45656', 52 | '--ld-colors-red800': '#910838', 53 | '--ld-colors-red900': '#4E041E', 54 | '--ld-colors-cyan50': '#F0FCFF', 55 | '--ld-colors-cyan100': '#E6FAFE', 56 | '--ld-colors-cyan200': '#D7F8FE', 57 | '--ld-colors-cyan300': '#C3F4FD', 58 | '--ld-colors-cyan400': '#A5EEFD', 59 | '--ld-colors-cyan500': '#7EE7FC', 60 | '--ld-colors-cyan600': '#06B7DB', 61 | '--ld-colors-cyan700': '#09AACD', 62 | '--ld-colors-cyan800': '#0E8AAA', 63 | '--ld-colors-cyan900': '#053B48', 64 | '--ld-colors-pink50': '#FFF0FB', 65 | '--ld-colors-pink100': '#FFE5F8', 66 | '--ld-colors-pink200': '#FFD6F3', 67 | '--ld-colors-pink300': '#FFC2EE', 68 | '--ld-colors-pink400': '#FFA3E5', 69 | '--ld-colors-pink500': '#FF7AD9', 70 | '--ld-colors-pink600': '#FF4ECD', 71 | '--ld-colors-pink700': '#D6009A', 72 | '--ld-colors-pink800': '#B80084', 73 | '--ld-colors-pink900': '#4D0037', 74 | '--ld-colors-gray50': '#F1F3F5', 75 | '--ld-colors-gray100': '#ECEEF0', 76 | '--ld-colors-gray200': '#E6E8EB', 77 | '--ld-colors-gray300': '#DFE3E6', 78 | '--ld-colors-gray400': '#D7DBDF', 79 | '--ld-colors-gray500': '#C1C8CD', 80 | '--ld-colors-gray600': '#889096', 81 | '--ld-colors-gray700': '#7E868C', 82 | '--ld-colors-gray800': '#687076', 83 | '--ld-colors-gray900': '#11181C', 84 | '--ld-colors-white': '#ffffff', 85 | '--ld-colors-black': '#000000', 86 | '--ld-colors-black-light': 'var(--ld-colors-white)', 87 | 88 | '--ld-colors-background': 'var(--ld-colors-white)', 89 | '--ld-colors-background-light': 'var(--ld-colors-black-light)', 90 | '--ld-colors-background-gray': 'var(--ld-colors-gray600)', 91 | '--ld-colors-backgroundAlpha': 'rgba(255, 255, 255, 0.8)', 92 | '--ld-colors-foreground': 'var(--ld-colors-black)', 93 | '--ld-colors-backgroundContrast': 'var(--ld-colors-white)', 94 | '--ld-colors-text': '#606266', 95 | '--ld-colors-text-darker': '#606266', 96 | '--ld-colors-text-light': '#909399', 97 | '--ld-colors-title': '#11181C', 98 | '--ld-colors-placeholder': '#a8abb2', 99 | '--ld-colors-grayBg': '#373739', 100 | '--ld-colors-lightContext': '#f9f9f9', 101 | '--ld-colors-embed': '#F1F3F5', 102 | '--ld-colors-darkContext': '#1c1f23', 103 | '--ld-colors-link': 'var(--ld-colors-blue600)', 104 | '--ld-colors-codeLight': 'var(--ld-colors-pink100)', 105 | '--ld-colors-code': 'var(--ld-colors-pink600)', 106 | '--ld-colors-selection': 'var(--ld-colors-blue200)', 107 | '--ld-colors-border': '#dcdfe6', 108 | '--ld-colors-border-light': '#efeff5', 109 | '--ld-colors-border-darker': '#cdd0d6', 110 | 111 | '--ld-colors-headerBackground': 'hsla(0,0%,100%,0.8)', 112 | '--ld-colors-menuBackground': 'rgba(255, 255, 255, 0.8)', 113 | '--ld-colors-headerIconColor': 'var(--ld-colors-gray400)', 114 | '--ld-colors-codeBackground': '#363449', 115 | '--ld-colors-codeComment': 'var(--ld-colors-gray700)', 116 | '--ld-colors-codeCopyIconColor': 'var(--ld-colors-gray200)', 117 | '--ld-colors-cardBackground': 'var(--ld-colors-white)', 118 | '--ld-colors-codeHighlight': 'hsl(243, 16%, 30%)', 119 | '--ld-colors-backgroundBlur': 'rgba(255, 255, 255, 0.3)', 120 | // '--ld-colors-blockLinkColor': '#FF1CF7', 121 | '--ld-colors-blockLinkBackground': 'var(--ld-colors-accents1)', 122 | '--ld-colors-blockLinkHoverBackground': '#FFD1ED', 123 | '--ld-shadows-xs': '0 2px 8px 1px rgb(104 112 118 / 0.07), 0 1px 1px -1px rgb(104 112 118 / 0.04)', 124 | '--ld-shadows-sm': '0 2px 8px 2px rgb(104 112 118 / 0.07), 0 2px 4px -1px rgb(104 112 118 / 0.04)', 125 | '--ld-shadows-md': '0 12px 20px 6px rgb(104 112 118 / 0.08)', 126 | '--ld-shadows-lg': '0 12px 34px 6px rgb(104 112 118 / 0.18)', 127 | '--ld-shadows-xl': '0 25px 65px 0px inset', 128 | '--ld-dropShadows-xs': 'drop-shadow(0 2px 4px rgb(104 112 118 / 0.07)) drop-shadow(0 1px 1px rgb(104 112 118 / 0.04))', 129 | '--ld-dropShadows-sm': 'drop-shadow(0 2px 8px rgb(104 112 118 / 0.07)) drop-shadow(0 2px 4px rgb(104 112 118 / 0.04))', 130 | '--ld-dropShadows-md': 'drop-shadow(0 4px 12px rgb(104 112 118 / 0.08)) drop-shadow(0 20px 8px rgb(104 112 118 / 0.04))', 131 | '--ld-dropShadows-lg': 'drop-shadow(0 12px 24px rgb(104 112 118 / 0.15)) drop-shadow(0 12px 14px rgb(104 112 118 / 0.1))', 132 | '--ld-dropShadows-xl': 'drop-shadow(0 25px 34px rgb(104 112 118 / 0.35))', 133 | 134 | '--ld-theme-primary': 'var(--ld-colors-purple500)', 135 | '--ld-theme-primaryHsl': `${hex2rgba('#A855F7')}`, 136 | '--ld-theme-primaryLight': 'var(--ld-colors-purple200)', 137 | '--ld-theme-primaryLightHover': 'var(--ld-colors-purple400)', 138 | '--ld-theme-primaryLightActive': 'var(--ld-colors-purple600)', 139 | '--ld-theme-primaryBorder': 'var(--ld-colors-purple500)', 140 | '--ld-theme-primaryBorderHover': 'var(--ld-colors-purple400)', 141 | '--ld-theme-primaryBorderActive': 'var(--ld-colors-purple600)', 142 | '--ld-theme-primaryShadow': 'var(--ld-colors-purple500)', 143 | 144 | '--ld-theme-secondary': 'var(--ld-colors-blue500)', 145 | '--ld-theme-secondaryHsl': `${hex2rgba('#409EFF')}`, 146 | '--ld-theme-secondaryLight': 'var(--ld-colors-blue200)', 147 | '--ld-theme-secondaryLightHover': 'var(--ld-colors-blue500)', 148 | '--ld-theme-secondaryLightActive': 'var(--ld-colors-blue700)', 149 | '--ld-theme-secondaryBorder': 'var(--ld-colors-blue600)', 150 | '--ld-theme-secondaryBorderHover': 'var(--ld-colors-blue500)', 151 | '--ld-theme-secondaryBorderActive': 'var(--ld-colors-blue700)', 152 | '--ld-theme-secondaryShadow': 'var(--ld-colors-blue500)', 153 | 154 | '--ld-theme-success': 'var(--ld-colors-green600)', 155 | '--ld-theme-successHsl': `${hex2rgba('#0ACF83')}`, 156 | '--ld-theme-successBorder': 'var(--ld-colors-green600)', 157 | '--ld-theme-successLightHover': 'var(--ld-colors-green500)', 158 | '--ld-theme-successLightActive': 'var(--ld-colors-green700)', 159 | '--ld-theme-successBorderHover': 'var(--ld-colors-green500)', 160 | '--ld-theme-successBorderActive': 'var(--ld-colors-green700)', 161 | '--ld-theme-successShadow': 'var(--ld-colors-green500)', 162 | 163 | '--ld-theme-warning': 'var(--ld-colors-yellow600)', 164 | '--ld-theme-warningHsl': `${hex2rgba('#F5A524')}`, 165 | '--ld-theme-warningBorder': 'var(--ld-colors-yellow500)', 166 | '--ld-theme-warningLightHover': 'var(--ld-colors-yellow500)', 167 | '--ld-theme-warningLightActive': 'var(--ld-colors-yellow700)', 168 | '--ld-theme-warningBorderHover': 'var(--ld-colors-yellow500)', 169 | '--ld-theme-warningBorderActive': 'var(--ld-colors-yellow700)', 170 | '--ld-theme-warningShadow': 'var(--ld-colors-yellow500)', 171 | 172 | '--ld-theme-error': 'var(--ld-colors-red600)', 173 | '--ld-theme-errorHsl': `${hex2rgba('#FF5C5C')}`, 174 | '--ld-theme-errorBorder': 'var(--ld-colors-red600)', 175 | '--ld-theme-errorLightHover': 'var(--ld-colors-red500)', 176 | '--ld-theme-errorLightActive': 'var(--ld-colors-red700)', 177 | '--ld-theme-errorBorderHover': 'var(--ld-colors-red500)', 178 | '--ld-theme-errorBorderActive': 'var(--ld-colors-red700)', 179 | '--ld-theme-errorShadow': 'var(--ld-colors-red500)', 180 | 181 | '--ld-theme-info': 'var(--ld-colors-gray700)', 182 | '--ld-theme-infoHsl': `${hex2rgba('#7E868C')}`, 183 | '--ld-theme-infoBorder': 'var(--ld-colors-gray700)', 184 | '--ld-theme-infoLightHover': 'var(--ld-colors-gray500)', 185 | '--ld-theme-infoLightActive': 'var(--ld-colors-gray800)', 186 | '--ld-theme-infoBorderHover': 'var(--ld-colors-gray500)', 187 | '--ld-theme-infoBorderActive': 'var(--ld-colors-gray800)', 188 | '--ld-theme-infoShadow': 'var(--ld-colors-gray400)', 189 | 190 | } 191 | 192 | export const darkTheme = { 193 | '--ld-colors-blue50': '#10253E', 194 | '--ld-colors-blue100': '#102C4C', 195 | '--ld-colors-blue200': '#18222c', 196 | '--ld-colors-blue300': '#0F3158', 197 | '--ld-colors-blue400': '#79bbff', 198 | '--ld-colors-blue500': '#0952A5', 199 | '--ld-colors-blue600': '#0072F5', 200 | '--ld-colors-blue700': '#3694FF', 201 | '--ld-colors-blue800': '#3694FF', 202 | '--ld-colors-blue900': '#EAF4FF', 203 | '--ld-colors-purple50': '#1F0A33', 204 | '--ld-colors-purple100': '#240C3C', 205 | '--ld-colors-purple200': '#2E0F4D', 206 | '--ld-colors-purple300': '#3B1362', 207 | '--ld-colors-purple400': '#451773', 208 | '--ld-colors-purple500': '#571D91', 209 | '--ld-colors-purple600': '#7828C8', 210 | '--ld-colors-purple700': '#9750DD', 211 | '--ld-colors-purple800': '#B583E7', 212 | '--ld-colors-purple900': '#F7ECFC', 213 | '--ld-colors-green50': '#042F14', 214 | '--ld-colors-green100': '#06381B', 215 | '--ld-colors-green200': '#074A24', 216 | '--ld-colors-green300': '#0A6130', 217 | '--ld-colors-green400': '#0B7439', 218 | '--ld-colors-green500': '#0F9549', 219 | '--ld-colors-green600': '#17C964', 220 | '--ld-colors-green700': '#41EC8B', 221 | '--ld-colors-green800': '#78F2AD', 222 | '--ld-colors-green900': '#ECFDF4', 223 | '--ld-colors-yellow50': '#3A2503', 224 | '--ld-colors-yellow100': '#442B03', 225 | '--ld-colors-yellow200': '#583804', 226 | '--ld-colors-yellow300': '#704705', 227 | '--ld-colors-yellow400': '#845306', 228 | '--ld-colors-yellow500': '#A66908', 229 | '--ld-colors-yellow600': '#F5A524', 230 | '--ld-colors-yellow700': '#F6AD37', 231 | '--ld-colors-yellow800': '#F8C572', 232 | '--ld-colors-yellow900': '#FEF7EC', 233 | '--ld-colors-red50': '#300313', 234 | '--ld-colors-red100': '#300313', 235 | '--ld-colors-red200': '#44041A', 236 | '--ld-colors-red300': '#5C0523', 237 | '--ld-colors-red400': '#6F062B', 238 | '--ld-colors-red500': '#c45656', 239 | '--ld-colors-red600': '#F31260', 240 | '--ld-colors-red700': '#f89898', 241 | '--ld-colors-red800': '#F75F94', 242 | '--ld-colors-red900': '#FDD8E5', 243 | '--ld-colors-cyan50': '#012A32', 244 | '--ld-colors-cyan100': '#023A46', 245 | '--ld-colors-cyan200': '#024B5A', 246 | '--ld-colors-cyan300': '#036072', 247 | '--ld-colors-cyan400': '#037086', 248 | '--ld-colors-cyan500': '#048EA9', 249 | '--ld-colors-cyan600': '#06B7DB', 250 | '--ld-colors-cyan700': '#33D9FA', 251 | '--ld-colors-cyan800': '#6FE4FB', 252 | '--ld-colors-cyan900': '#EBFBFE', 253 | '--ld-colors-pink50': '#330025', 254 | '--ld-colors-pink100': '#470033', 255 | '--ld-colors-pink200': '#5C0042', 256 | '--ld-colors-pink300': '#750054', 257 | '--ld-colors-pink400': '#8A0063', 258 | '--ld-colors-pink500': '#AD007C', 259 | '--ld-colors-pink600': '#FF4ECD', 260 | '--ld-colors-pink700': '#FF2EC4', 261 | '--ld-colors-pink800': '#FF6BD5', 262 | '--ld-colors-pink900': '#FFEBF9', 263 | '--ld-colors-gray50': '#16181A', 264 | '--ld-colors-gray100': '#26292B', 265 | '--ld-colors-gray200': '#2B2F31', 266 | '--ld-colors-gray300': '#313538', 267 | '--ld-colors-gray400': '#3A3F42', 268 | '--ld-colors-gray500': '#4C5155', 269 | '--ld-colors-gray600': '#697177', 270 | '--ld-colors-gray700': '#787F85', 271 | '--ld-colors-gray800': '#9BA1A6', 272 | '--ld-colors-gray900': '#ECEDEE', 273 | '--ld-colors-white-light': '#ffffff', 274 | 275 | '--ld-colors-text': '#CFD3DC', 276 | '--ld-colors-text-darker': '#7C7C7D', 277 | '--ld-colors-text-light': '#A3A6AD', 278 | '--ld-colors-title': '#ECEDEE', 279 | '--ld-colors-placeholder': '#8D9095', 280 | '--ld-colors-border': '#4C4D4F', 281 | '--ld-colors-border-light': '#414243', 282 | '--ld-colors-border-darker': '#636466', 283 | '--ld-colors-background': 'var(--ld-colors-black)', 284 | '--ld-colors-black-light': '#1d1e1f', 285 | '--ld-colors-arrow': '#373739', 286 | '--ld-colors-backgroundAlpha': 'rgba(0, 0, 0, 0.6)', 287 | '--ld-colors-foreground': 'var(--ld-colors-white)', 288 | '--ld-colors-backgroundContrast': 'var(--ld-colors-gray50)', 289 | 290 | '--ld-theme-primary': 'var(--ld-colors-purple500)', 291 | '--ld-theme-primaryHsl': `${hex2rgba('#A855F7')}`, 292 | '--ld-theme-primaryLight': 'var(--ld-colors-purple200)', 293 | '--ld-theme-primaryLightHover': 'var(--ld-colors-purple400)', 294 | '--ld-theme-primaryLightActive': 'var(--ld-colors-purple600)', 295 | '--ld-theme-primaryBorder': 'var(--ld-colors-purple500)', 296 | '--ld-theme-primaryBorderHover': 'var(--ld-colors-purple400)', 297 | '--ld-theme-primaryBorderActive': 'var(--ld-colors-purple600)', 298 | '--ld-theme-primaryShadow': 'var(--ld-colors-purple500)', 299 | 300 | '--ld-theme-secondary': 'var(--ld-colors-blue500)', 301 | '--ld-theme-secondaryHsl': `${hex2rgba('#409EFF')}`, 302 | '--ld-theme-secondaryLight': 'var(--ld-colors-blue200)', 303 | '--ld-theme-secondaryLightHover': 'var(--ld-colors-blue500)', 304 | '--ld-theme-secondaryLightActive': 'var(--ld-colors-blue700)', 305 | '--ld-theme-secondaryBorder': 'var(--ld-colors-blue600)', 306 | '--ld-theme-secondaryBorderHover': 'var(--ld-colors-blue500)', 307 | '--ld-theme-secondaryBorderActive': 'var(--ld-colors-blue700)', 308 | '--ld-theme-secondaryShadow': 'var(--ld-colors-blue500)', 309 | 310 | '--ld-theme-success': 'var(--ld-colors-green600)', 311 | 312 | '--ld-theme-warning': 'var(--ld-colors-yellow600)', 313 | 314 | '--ld-theme-error': 'var(--ld-colors-red600)', 315 | 316 | '--ld-theme-info': 'var(--ld-colors-gray700)', 317 | '--ld-theme-infoHsl': `${hex2rgba('#787F85')}`, 318 | '--ld-theme-infoLightHover': 'var(--ld-colors-gray600)', 319 | '--ld-theme-infoLightActive': 'var(--ld-colors-gray800)', 320 | '--ld-theme-infoBorderHover': 'var(--ld-colors-gray600)', 321 | '--ld-theme-infoBorderActive': 'var(--ld-colors-gray800)', 322 | } 323 | 324 | export const getCSSPreflights = (theme: any) => { 325 | return Object.entries(theme).map(([key, value]: [string, any]) => `${key}: ${value}`).join(';') 326 | } 327 | -------------------------------------------------------------------------------- /packages/preset/src/preflights.ts: -------------------------------------------------------------------------------- 1 | import { darkTheme, getCSSPreflights, lightTheme } from './colors' 2 | 3 | export const preflights = [{ 4 | layer: 'base', 5 | getCSS: () => ` 6 | :root { 7 | ${getCSSPreflights(lightTheme)} 8 | } 9 | :root.dark { 10 | ${getCSSPreflights(darkTheme)} 11 | }`.trim(), 12 | }] 13 | -------------------------------------------------------------------------------- /packages/preset/src/preset.ts: -------------------------------------------------------------------------------- 1 | import type { Preset } from 'unocss' 2 | import { rules } from './rules' 3 | import type { Theme } from './theme' 4 | import { theme } from './theme' 5 | import { preflights } from './preflights' 6 | import { shortcuts } from './shortcuts' 7 | 8 | export const presetLuckyDesign = (): Preset => { 9 | return { 10 | name: '@lucky-design/preset', 11 | rules, 12 | theme, 13 | preflights, 14 | shortcuts, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/preset/src/rules.ts: -------------------------------------------------------------------------------- 1 | import type { Rule, RuleContext } from 'unocss' 2 | import { parseColor } from 'unocss/preset-mini' 3 | import type { Theme } from './theme' 4 | 5 | export const rules: Rule[] = [ 6 | [/^ld-(.*)$/, ([, body]: string[], { theme }: RuleContext) => { 7 | const color = parseColor(body, theme) 8 | if (color?.cssColor?.type === 'rgb' && color.cssColor.components) { 9 | return { 10 | '--ld-c-context': `${color.cssColor.components.join(',')}`, 11 | } 12 | } 13 | else { 14 | return { 15 | '--ld-c-context': color?.color, 16 | } 17 | } 18 | }], 19 | ['ld-dashed', { 'border-style': 'dashed' }], 20 | ['ld-solid', { 'background-color': 'rgba(var(--ld-c-context), 1) !important', 'border-color': 'rgba(var(--ld-c-context), 1)', 'color': 'white !important' }], 21 | ] as Rule[] 22 | -------------------------------------------------------------------------------- /packages/preset/src/shortcuts/button.ts: -------------------------------------------------------------------------------- 1 | export const buttonShortcut = { 2 | 'ld-button-base': 'ld-blue bg-context', 3 | } 4 | -------------------------------------------------------------------------------- /packages/preset/src/shortcuts/index.ts: -------------------------------------------------------------------------------- 1 | import { buttonShortcut } from './button' 2 | 3 | export const shortcuts = [buttonShortcut] 4 | -------------------------------------------------------------------------------- /packages/preset/src/theme.ts: -------------------------------------------------------------------------------- 1 | const PREFIX_THEME = '--ld-theme' 2 | 3 | const getColorsTheme = (theme) => { 4 | return { 5 | [`${theme}`]: `var(${PREFIX_THEME}-${theme}Hsl)`, 6 | [`${theme}Base`]: `var(${PREFIX_THEME}-${theme})`, 7 | [`${theme}Light`]: `var(${PREFIX_THEME}-${theme}Light)`, 8 | [`${theme}LightHover`]: `var(${PREFIX_THEME}-${theme}LightHover)`, 9 | [`${theme}LightActive`]: `var(${PREFIX_THEME}-${theme}LightActive)`, 10 | [`${theme}LightContrast`]: `var(${PREFIX_THEME}-${theme}LightContrast)`, 11 | [`${theme}Border`]: `var(${PREFIX_THEME}-${theme}Border)`, 12 | [`${theme}BorderHover`]: `var(${PREFIX_THEME}-${theme}BorderHover)`, 13 | [`${theme}BorderActive`]: `var(${PREFIX_THEME}-${theme}BorderActive)`, 14 | [`${theme}SolidHover`]: `var(${PREFIX_THEME}-${theme}SolidHover)`, 15 | [`${theme}SolidContrast`]: `var(${PREFIX_THEME}-${theme}SolidContrast)`, 16 | [`${theme}Shadow`]: `var(${PREFIX_THEME}-${theme}Shadow)`, 17 | } 18 | } 19 | 20 | export const theme = { 21 | colors: { 22 | context: 'rgba(var(--ld-c-context),%alpha)', 23 | ...getColorsTheme('primary'), 24 | ...getColorsTheme('secondary'), 25 | ...getColorsTheme('success'), 26 | ...getColorsTheme('warning'), 27 | ...getColorsTheme('error'), 28 | ...getColorsTheme('info'), 29 | baseText: 'var(--ld-colors-text)', 30 | baseBorder: 'var(--ld-colors-border)', 31 | lightBorder: 'var(--ld-colors-border-light)', 32 | darkerBorder: 'var(--ld-colors-border-darker)', 33 | baseBackground: 'var(--ld-colors-background)', 34 | lightBackground: 'var(--ld-colors-background-light)', 35 | placeholder: 'var(--ld-colors-placeholder)', 36 | grayBd: '#var(--ld-colors-background-gray)', 37 | arrow: 'var(--ld-colors-arrow)', 38 | title: 'var(--ld-colors-title)', 39 | darkText: 'var(--ld-colors-text-darker)', 40 | darkSubText: 'var(--ld-colors-text-light)', 41 | grayBg: 'var(--ld-colors-grayBg)', 42 | embed: 'var(--ld-colors-embed)', 43 | darkContext: 'var(--ld-colors-darkContext)', 44 | lightContext: 'var(--ld-colors-lightContext)', 45 | }, 46 | fontFamily: { 47 | sans: 'Avenir, Helvetica, Arial, sans-serif', 48 | }, 49 | boxShadow: { 50 | xs: 'var(--un-shadow-inset) 0 1px 1px 0 var(--un-shadow-color, rgba(0,0,0,0.03))', 51 | switch: 52 | 'calc(var(--ld-switch-offset) * -1) 0 0 2px var(--ld-switch-bc) inset, 0 0 0 2px var(--ld-switch-bc) inset;', 53 | switchActive: 54 | 'calc(var(--ld-switch-offset)) 0 0 2px var(--ld-switch-c) inset, 0 0 0 2px var(--ld-switch-c) inset;', 55 | trigger: '0px 4px 10px #0000001a', 56 | cardMD: '0px 0px 12px rgb(0 0 0 / 12%)', 57 | cardSM: '0px 0px 6px rgb(0 0 0 / 12%)', 58 | }, 59 | animation: { 60 | keyframes: { 61 | switching: `{0%{ box-shadow: 0 0 0 2px #1890ff66; } 62 | 60%{ box-shadow: 0 0 0 4px #1890ff33; } 63 | 80%{ box-shadow: 0 0 0 6px #1890ff1a; } 64 | 100%{ box-shadow: 0 0 0 8px #1890ff0d; }}`, 65 | }, 66 | durations: { 67 | switching: '0.3s', 68 | }, 69 | }, 70 | } 71 | 72 | export type Theme = typeof theme 73 | -------------------------------------------------------------------------------- /packages/preset/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['./index.ts'], 5 | clean: true, 6 | format: ['cjs', 'esm'], 7 | external: ['vue'], 8 | dts: true, 9 | minify: true, 10 | }) 11 | -------------------------------------------------------------------------------- /playground/.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 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /playground/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | # Lucky Design Playground 2 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Vue + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "lucky-design": "workspace:*", 13 | "vue": "^3.2.45", 14 | "vue-router": "4" 15 | }, 16 | "devDependencies": { 17 | "@vitejs/plugin-vue": "^4.0.0", 18 | "typescript": "^4.9.3", 19 | "vite": "^4.0.0", 20 | "vue-tsc": "^1.0.11" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /playground/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /playground/src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 27 | -------------------------------------------------------------------------------- /playground/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import './style.css' 3 | import LuckyDesign from 'lucky-design' 4 | import App from './App.vue' 5 | import 'lucky-design/dist/style.css' 6 | import router from './router' 7 | 8 | const app = createApp(App) 9 | 10 | app.use(LuckyDesign) 11 | app.use(router) 12 | 13 | app.mount('#app') 14 | -------------------------------------------------------------------------------- /playground/src/router/dynamicRoutes.ts: -------------------------------------------------------------------------------- 1 | export default () => { 2 | const routes = [] 3 | const modules = (import.meta as any).glob('/src/views/*.vue') 4 | 5 | for (const key in modules) { 6 | routes.push({ 7 | path: `/${(key.split('/')[3].split('.')[0]).toLowerCase()}`, 8 | component: modules[key], 9 | }) 10 | } 11 | return routes 12 | } 13 | -------------------------------------------------------------------------------- /playground/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import routes from './routes' 3 | 4 | const router = createRouter({ 5 | history: createWebHistory(), 6 | routes, 7 | }) 8 | 9 | export default router 10 | -------------------------------------------------------------------------------- /playground/src/router/routes.ts: -------------------------------------------------------------------------------- 1 | import dynamicRoutes from './dynamicRoutes' 2 | 3 | const routes = [ 4 | { 5 | path: '/', 6 | component: () => import('../views/index.vue'), 7 | }, 8 | ...dynamicRoutes(), 9 | ] 10 | 11 | export default routes 12 | -------------------------------------------------------------------------------- /playground/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | -------------------------------------------------------------------------------- /playground/src/views/Backtop.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /playground/src/views/Button.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | 20 | 30 | -------------------------------------------------------------------------------- /playground/src/views/Checkbox.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 26 | -------------------------------------------------------------------------------- /playground/src/views/Drawer.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | 29 | 39 | -------------------------------------------------------------------------------- /playground/src/views/Icon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /playground/src/views/LTooltip.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 32 | 42 | -------------------------------------------------------------------------------- /playground/src/views/Message.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 23 | -------------------------------------------------------------------------------- /playground/src/views/Table.vue: -------------------------------------------------------------------------------- 1 | 76 | 77 | 89 | 90 | 100 | -------------------------------------------------------------------------------- /playground/src/views/Tree.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 73 | -------------------------------------------------------------------------------- /playground/src/views/Upload.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 55 | -------------------------------------------------------------------------------- /playground/src/views/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 27 | 28 | 57 | -------------------------------------------------------------------------------- /playground/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'lucky-design' { 2 | import { 3 | LButton, 4 | LCheckbox, 5 | LDrawer, 6 | LMessage, 7 | LTree, 8 | LBacktop, 9 | LUpload, 10 | LIcon, 11 | LToolTip, 12 | LTable, 13 | } from 'lucky-design' 14 | export { 15 | LButton, 16 | LCheckbox, 17 | LDrawer, 18 | LMessage, 19 | LTree, 20 | LBacktop, 21 | LUpload, 22 | LIcon, 23 | LToolTip, 24 | LTable, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /playground/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /playground/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | }) 8 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'docs' 4 | - 'playground' 5 | -------------------------------------------------------------------------------- /scripts/add-component.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | NAME=$1 4 | 5 | FILE_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")/../packages" && pwd) 6 | 7 | re="[[:space:]]+" 8 | 9 | if [ "$#" -ne 1 ] || [[ $NAME =~ $re ]] || [ "$NAME" == "" ]; then 10 | echo "Usage: pnpm gc \${name} with no space" 11 | exit 1 12 | fi 13 | 14 | DIRNAME="$FILE_PATH/components/src/$NAME" 15 | INPUT_NAME=$NAME 16 | 17 | if [ -d "$DIRNAME" ]; then 18 | echo "$NAME component already exists, please change it" 19 | exit 1 20 | fi 21 | 22 | NORMALIZED_NAME="" 23 | for i in $(echo $NAME | sed 's/[_|-]\([a-z]\)/\ \1/;s/^\([a-z]\)/\ \1/'); do 24 | C=$(echo "${i:0:1}" | tr "[:lower:]" "[:upper:]") 25 | NORMALIZED_NAME="$NORMALIZED_NAME${C}${i:1}" 26 | done 27 | NAME=$NORMALIZED_NAME 28 | 29 | mkdir -p "$DIRNAME" 30 | mkdir -p "$DIRNAME/__tests__" 31 | 32 | cat > $DIRNAME/style.scss < $DIRNAME/props.ts < 46 | EOF 47 | 48 | cat > $DIRNAME/$INPUT_NAME.vue < 50 | import { ${NAME}Props } from './props' 51 | 52 | const { } = defineProps(${NAME}Props) 53 | 54 | 55 | 60 | EOF 61 | 62 | cat <"$DIRNAME/index.ts" 63 | import { withInstall } from '@lucky-design/common' 64 | import $NAME from './$INPUT_NAME.vue' 65 | import './style.scss' 66 | 67 | export const L$NAME = withInstall($NAME, 'L$NAME') 68 | 69 | export default L$NAME 70 | 71 | export * from './props' 72 | EOF 73 | 74 | cat > $DIRNAME/__tests__/$INPUT_NAME.test.tsx < { 78 | it('hello world', () => { 79 | expect(1).toBe(1) 80 | }) 81 | }) 82 | EOF 83 | 84 | cat > docs/docs/components/$INPUT_NAME.md < docs/docs/zh-CN/components/$INPUT_NAME.md < playground/src/views//$INPUT_NAME.vue < 94 | import { L$NAME } from 'lucky-design' 95 | 96 | 97 | 102 | 103 | 113 | EOF 114 | 115 | echo >> packages/components/index.ts "export * from './src/$INPUT_NAME'" 116 | 117 | echo "Component $INPUT_NAME created successfully" 118 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import { isMac, logger, run } from './utils' 2 | 3 | async function build() { 4 | try { 5 | if (isMac) 6 | await run('pnpm', ['--filter', './packages/*', '--parallel', 'build']) 7 | else 8 | await run('pnpm run', ['--filter', './packages/*', '--parallel', 'build']) 9 | 10 | logger.success('All builds completed successfully') 11 | } 12 | catch (err) { 13 | logger.error((err as Error).toString()) 14 | } 15 | } 16 | 17 | build() 18 | -------------------------------------------------------------------------------- /scripts/dev-packages.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import * as process from 'process' 3 | import chokidar from 'chokidar' 4 | import { debounce } from 'perfect-debounce' 5 | import { isMac, logger, run } from './utils' 6 | 7 | async function rebuildLuckyDesign() { 8 | const luckyDesign = path.resolve(process.cwd(), 'packages/components') 9 | const watcher = chokidar.watch(luckyDesign, { 10 | ignored: [/(^|[\/\\])\../, '**/node_modules/**', '**/dist/**'], 11 | persistent: true, 12 | }) 13 | 14 | const build = async () => { 15 | if (isMac) 16 | await run('pnpm', ['--filter', './packages/lucky-design', 'build']) 17 | else 18 | await run('pnpm run', ['--filter', './packages/lucky-design', 'build']) 19 | } 20 | 21 | const debounceBuilder = debounce(async () => build(), 500) 22 | 23 | watcher.on('all', async () => { 24 | await debounceBuilder() 25 | }) 26 | } 27 | 28 | async function devPackages() { 29 | try { 30 | if (isMac) 31 | await run('pnpm', ['--filter', './packages/*', '--parallel', 'dev']) 32 | else 33 | await run('pnpm run', ['--filter', './packages/*', '--parallel', 'dev']) 34 | 35 | await rebuildLuckyDesign() 36 | logger.success('All packages are running in dev mode.') 37 | } 38 | catch (err) { 39 | logger.error((err as Error).toString()) 40 | process.exit() 41 | } 42 | } 43 | 44 | devPackages() 45 | -------------------------------------------------------------------------------- /scripts/dev.ts: -------------------------------------------------------------------------------- 1 | import * as process from 'process' 2 | import { logger, run } from './utils' 3 | 4 | async function dev() { 5 | try { 6 | run('vue-tsc', [ 7 | '--declaration', 8 | '--emitDeclarationOnly', 9 | '--skipLibCheck', 10 | '--watch', 11 | ]) 12 | run('vite', ['build', '--watch']) 13 | logger.success(`${process.cwd()}: are running in dev mode.`) 14 | } 15 | catch (err) { 16 | logger.error((err as Error).toString()) 17 | } 18 | } 19 | 20 | dev() 21 | -------------------------------------------------------------------------------- /scripts/utils.ts: -------------------------------------------------------------------------------- 1 | import type { Options } from 'execa' 2 | import { execa } from 'execa' 3 | import pc from 'picocolors' 4 | 5 | export async function run(bin: string, args: string[], opts: Options = {}) { 6 | return execa(bin, args, { stdio: 'inherit', ...opts }) 7 | } 8 | 9 | export const logger = { 10 | success(msg: string) { 11 | // eslint-disable-next-line no-console 12 | console.log(pc.green(msg)) 13 | }, 14 | error(msg: string) { 15 | // eslint-disable-next-line no-console 16 | console.log(pc.bgRed(msg)) 17 | }, 18 | } 19 | 20 | export const isMac = process.platform !== 'win32' 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "lib": ["esnext", "dom"], 6 | "moduleResolution": "node", 7 | "esModuleInterop": true, 8 | "strict": true, 9 | "noImplicitAny": false, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipDefaultLibCheck": true, 13 | "skipLibCheck": true, 14 | "jsx": "preserve", 15 | "types": ["node", "vite/client"], 16 | "baseUrl": ".", 17 | "paths": { 18 | "@lucky-design/components": ["./packages/components/index.ts"], 19 | "@lucky-design/common": ["./packages/common/index.ts"], 20 | "@lucky-design/preset": ["./packages/preset/index.ts"] 21 | } 22 | }, 23 | "exclude": [ 24 | "**/dist/**", 25 | "**/node_modules/**", 26 | "**/test/dts/**", 27 | "**/playground/**", 28 | "**/example/**" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | import Vue from '@vitejs/plugin-vue' 3 | import { alias } from './alias' 4 | 5 | export default defineConfig({ 6 | plugins: [Vue()], 7 | optimizeDeps: { 8 | disabled: true, 9 | }, 10 | test: { 11 | clearMocks: true, 12 | environment: 'jsdom', 13 | transformMode: { 14 | web: [/\.[jt]sx$/], 15 | }, 16 | }, 17 | resolve: { 18 | alias, 19 | }, 20 | }) 21 | --------------------------------------------------------------------------------