├── .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 |
6 |
7 |
8 | click
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/docs/examples/backtop/custom.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | click
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/docs/examples/button/basic.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
31 |
--------------------------------------------------------------------------------
/docs/docs/examples/button/disabled.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
--------------------------------------------------------------------------------
/docs/docs/examples/button/shape.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
22 |
--------------------------------------------------------------------------------
/docs/docs/examples/button/size.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/docs/docs/examples/checkbox/basic.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 | 北京
12 |
13 |
14 | 上海
15 |
16 |
17 | 广州
18 |
19 |
20 | 杭州
21 |
22 |
23 |
24 |
25 |
34 |
--------------------------------------------------------------------------------
/docs/docs/examples/drawer/basic.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
27 |
31 |
35 |
39 |
46 | 123123123
47 |
48 |
49 |
50 |
51 |
61 |
--------------------------------------------------------------------------------
/docs/docs/examples/icon/basic.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/docs/examples/message/Basic.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
15 |
20 |
25 |
30 |
31 |
32 |
33 |
39 |
--------------------------------------------------------------------------------
/docs/docs/examples/message/Duration.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
15 |
20 |
25 |
37 |
38 |
39 |
40 |
46 |
--------------------------------------------------------------------------------
/docs/docs/examples/message/Offset.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
15 |
20 |
25 |
26 |
27 |
28 |
34 |
--------------------------------------------------------------------------------
/docs/docs/examples/tooltip/basic.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
25 |
--------------------------------------------------------------------------------
/docs/docs/examples/tree/basic.vue:
--------------------------------------------------------------------------------
1 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/docs/docs/examples/upload/basic.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
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 |
28 | click
29 |
30 | ```
31 |
32 | :::
33 |
34 | ## 自定义
35 |
36 |
37 |
38 | :::info
39 |
40 | 你可以自定义组件的偏移量以及隐藏高度
41 |
42 | :::
43 |
44 | ::: details code
45 |
46 | ```vue
47 |
50 |
51 |
52 |
53 |
54 | click
55 |
56 |
57 |
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 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ```
44 |
45 | :::
46 |
47 | ## 按钮大小
48 |
49 | :::info
50 |
51 |
52 |
53 | :::
54 |
55 | ::: details code
56 |
57 | ```vue
58 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | ```
71 |
72 | :::
73 |
74 | ## 按钮形状
75 |
76 | :::info
77 |
78 |
79 |
80 | :::
81 |
82 | ::: details code
83 |
84 | ```vue
85 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | ```
97 |
98 | :::
99 |
100 | ## 禁用状态
101 |
102 | :::info
103 |
104 |
105 |
106 | :::
107 |
108 | ::: details code
109 |
110 | ```vue
111 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
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 |
35 |
36 |
37 |
38 |
39 |
40 |
47 | 123123123
48 |
49 |
50 |
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 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
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 |
27 |
28 |
33 |
38 |
43 |
48 |
49 |
50 | ```
51 |
52 | :::
53 |
54 | ## 延时关闭
55 |
56 | :::info
57 |
58 |
59 |
60 | :::
61 |
62 | ::: details code
63 |
64 | ```vue
65 |
68 |
69 |
70 |
71 |
76 |
81 |
86 |
98 |
99 |
100 | ```
101 |
102 | :::
103 |
104 | ## 偏移量
105 |
106 | :::info
107 |
108 |
109 |
110 | :::
111 |
112 | ::: details code
113 |
114 | ```vue
115 |
118 |
119 |
120 |
121 |
126 |
131 |
136 |
137 |
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 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
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 |
83 |
84 |
85 |
86 |
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 |
23 |
24 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
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 |
18 |
19 |
25 |
26 |
27 |
28 |
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 |
8 |
14 |
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 |
21 |
31 |
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 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/packages/components/src/container/src/container.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
42 |
43 |
--------------------------------------------------------------------------------
/packages/components/src/container/src/footer.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/components/src/container/src/header.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/components/src/container/src/main.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
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 |
11 |
12 |
13 |
19 |
20 |
21 |
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 |
7 |
8 |
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 |
53 |
54 |
64 |
65 |
66 | {{ message }}
67 |
68 |
69 | ×
70 |
71 |
72 |
73 |
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 |
186 |
187 |
188 |
189 |
193 | {{ column.label }} {{ sortIonClass(column) }}
194 |
195 |
196 | |
197 |
198 |
199 |
200 |
201 |
202 | {{ row[column.prop] }}
203 | |
204 |
205 |
206 |
207 |
208 |
209 |
278 |
--------------------------------------------------------------------------------
/packages/components/src/tooltip/content.vue:
--------------------------------------------------------------------------------
1 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
83 |
84 |
85 |
86 |
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 |
74 |
75 |
76 |
77 |
85 |
86 | {{ content }}
87 |
88 |
89 |
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 |
21 |
32 |
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 |
116 |
117 |
118 |
128 |
129 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
--------------------------------------------------------------------------------
/playground/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
13 |
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 |
6 |
7 |
123
8 |
9 | back top
10 |
11 |
12 |
13 |
14 |
19 |
--------------------------------------------------------------------------------
/playground/src/views/Button.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/playground/src/views/Checkbox.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 | 北京
13 |
14 |
15 | 上海
16 |
17 |
18 | 广州
19 |
20 |
21 | 杭州
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/playground/src/views/Drawer.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 123
25 |
26 |
27 |
28 |
29 |
39 |
--------------------------------------------------------------------------------
/playground/src/views/Icon.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/playground/src/views/LTooltip.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
42 |
--------------------------------------------------------------------------------
/playground/src/views/Message.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/playground/src/views/Table.vue:
--------------------------------------------------------------------------------
1 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
86 |
87 |
88 |
89 |
90 |
100 |
--------------------------------------------------------------------------------
/playground/src/views/Tree.vue:
--------------------------------------------------------------------------------
1 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/playground/src/views/Upload.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
40 |
41 |
42 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/playground/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
22 |
{{ url.split('/')[1] }}
23 |
24 |
25 |
26 |
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 |
56 |
57 |
58 |
59 |
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 |
98 |
99 |
100 |
101 |
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 |
--------------------------------------------------------------------------------