Compare commits
429 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47f53cb985 | ||
| 1e1f335853 | |||
| 32d6b8b397 | |||
|
|
3eaef4a748 | ||
|
|
5b1f952e0a | ||
|
|
693b0d2a08 | ||
|
|
8a24d11a65 | ||
|
|
e4fea78b33 | ||
|
|
5869165a84 | ||
|
|
857f10de51 | ||
|
|
5ada562803 | ||
|
|
6c0ab55e92 | ||
|
|
3ddd70dd6b | ||
|
|
2d5ad5b962 | ||
|
|
16f1d19460 | ||
|
|
ac69980ac9 | ||
|
|
58fc125974 | ||
|
|
383c846c02 | ||
|
|
b7ef4653f7 | ||
|
|
384c87a91c | ||
|
|
75a5bce92f | ||
|
|
3d0db2de7b | ||
|
|
a5b25a9c43 | ||
|
|
be888c80b6 | ||
|
|
93be758257 | ||
|
|
26df827d33 | ||
|
|
f267b0ba4a | ||
|
|
3c506ef188 | ||
|
|
df60e15a97 | ||
|
|
3646203d4f | ||
|
|
68c40f6908 | ||
|
|
ff1b5f0a1b | ||
|
|
15f3eb305b | ||
|
|
baceb4ce91 | ||
|
|
2cb767122a | ||
|
|
eff3e75466 | ||
|
|
83419c4dc3 | ||
|
|
52b9b20b3c | ||
|
|
e0d4980e31 | ||
|
|
6760ebb5ae | ||
|
|
d143272fb8 | ||
|
|
4f3bb61283 | ||
|
|
f9615d3657 | ||
|
|
d48ffcfffb | ||
|
|
e63d5553e3 | ||
|
|
a01a1bd94d | ||
|
|
f5b02256bc | ||
|
|
c164421e58 | ||
|
|
5c71911104 | ||
|
|
982f918e53 | ||
|
|
f8f3fc754f | ||
|
|
1c7c60330a | ||
|
|
ff6d9d0da6 | ||
|
|
603497e822 | ||
|
|
235ec8a691 | ||
|
|
ec350df9d4 | ||
|
|
64b6d6ac38 | ||
|
|
775d59b51d | ||
|
|
7c9aac46a1 | ||
|
|
ccbdc2f90f | ||
|
|
573443f352 | ||
|
|
481bebf413 | ||
|
|
cc84ac172c | ||
|
|
501137a672 | ||
|
|
f73e1ddaaf | ||
|
|
85b10641c2 | ||
|
|
68d9804109 | ||
|
|
1a1dd4a611 | ||
|
|
0fc50183e4 | ||
|
|
2a50f65ec5 | ||
|
|
3dc6e10897 | ||
|
|
12657dab5c | ||
|
|
bdcd555c84 | ||
|
|
514949706f | ||
|
|
0d5d2d0d10 | ||
|
|
6ac90c10ab | ||
|
|
5708af535a | ||
|
|
b2952b6416 | ||
|
|
0ee23fb53d | ||
|
|
dbb29de523 | ||
|
|
183da0890d | ||
|
|
bec12b1653 | ||
|
|
45557fd8e7 | ||
|
|
6757908fe1 | ||
|
|
6550f34842 | ||
|
|
4d4804231b | ||
|
|
edad815fd9 | ||
|
|
9ddbd5c0d2 | ||
|
|
7a03a4caab | ||
|
|
b371e5f3ad | ||
|
|
d50ea38f4a | ||
|
|
f03778304d | ||
|
|
0f1befad1f | ||
|
|
cdfbd51190 | ||
|
|
f597d258b0 | ||
|
|
eeca60d09b | ||
|
|
6aebbc1a90 | ||
|
|
2e93d15af4 | ||
|
|
f1a2dab738 | ||
|
|
63732f1c47 | ||
|
|
9d303e91ca | ||
|
|
edc4ee9437 | ||
|
|
36ad0f846d | ||
|
|
88a93ce22e | ||
|
|
8cbd55660f | ||
|
|
ae43e5e08a | ||
|
|
a1faecc7d2 | ||
|
|
9960925881 | ||
|
|
ce6eb79a3d | ||
|
|
f48d1d4f4c | ||
|
|
47ff130ffb | ||
|
|
e54e06bb98 | ||
|
|
15f630552f | ||
|
|
80f06066c6 | ||
|
|
6a6968b8ee | ||
|
|
ebe3e6d8d2 | ||
|
|
bd0a8206ef | ||
|
|
63bb21808f | ||
|
|
e63eec02e4 | ||
|
|
dce0bd0c30 | ||
|
|
af5d0b323d | ||
|
|
1aa9b6172e | ||
|
|
18c64563a1 | ||
|
|
175762a959 | ||
|
|
61dcd63ef2 | ||
|
|
61ed5f1758 | ||
|
|
5eb41b0ba9 | ||
|
|
7f73e4d74b | ||
|
|
ead6ad8437 | ||
|
|
3e5dd97fc5 | ||
|
|
cc3503689f | ||
|
|
08e10236fc | ||
|
|
7fdf916443 | ||
|
|
b20a45552a | ||
|
|
0721d1c864 | ||
|
|
60e12b962f | ||
|
|
bcbfab5c9b | ||
|
|
631ffb81d5 | ||
|
|
3dd2fbda95 | ||
|
|
9ebbd30175 | ||
|
|
d17bb2bb2a | ||
|
|
10319df960 | ||
|
|
e67c98b485 | ||
|
|
9dfb0b86c0 | ||
|
|
b468704853 | ||
|
|
db3fff29c8 | ||
|
|
77c6a16040 | ||
|
|
32d7b9ca4a | ||
|
|
18e40cf002 | ||
|
|
f6bc669106 | ||
|
|
d21fa783e9 | ||
|
|
8633bc95f2 | ||
|
|
93b98252a4 | ||
|
|
5f774f83d9 | ||
|
|
919770c6ca | ||
|
|
042321a3f4 | ||
|
|
0937fb6af5 | ||
|
|
8e132b1987 | ||
|
|
95f4e6b56d | ||
|
|
c77b087c9c | ||
|
|
6774842937 | ||
|
|
57ee2fc017 | ||
|
|
fbe14a20c1 | ||
|
|
f7e475f16a | ||
|
|
cedce319ba | ||
|
|
798aa0ec24 | ||
|
|
f51a8da08d | ||
|
|
8052eb1a33 | ||
|
|
cfccb8e510 | ||
|
|
11d77fb9a1 | ||
|
|
e36402491b | ||
|
|
92d3e2c7f0 | ||
|
|
9712ba9bae | ||
|
|
75d10d5b8e | ||
|
|
8aa0e2a41d | ||
|
|
cb955c82a7 | ||
|
|
0c3c703cb0 | ||
|
|
3e2e4ec5a3 | ||
|
|
4f9a5af907 | ||
|
|
d868c9fd48 | ||
|
|
81a7515617 | ||
|
|
f91cfe9add | ||
|
|
f55633ab8a | ||
|
|
46f7ffb65a | ||
|
|
c1c1f171fe | ||
|
|
623fe06aa6 | ||
|
|
1f97ce0d24 | ||
|
|
cd3d24438a | ||
|
|
a03bace32c | ||
|
|
8982ec3862 | ||
|
|
d34c620055 | ||
|
|
24fc8f755a | ||
|
|
ac434a3d24 | ||
|
|
67777d64f3 | ||
|
|
38f5672e59 | ||
|
|
874ee643aa | ||
|
|
8e58b6e196 | ||
|
|
4672f2247d | ||
|
|
4aeb6140d4 | ||
|
|
d4c7b0107f | ||
|
|
6d0cde4b8e | ||
|
|
72f9bd5ef5 | ||
|
|
4d08adc81e | ||
|
|
454ecf0df7 | ||
|
|
7af3b612d6 | ||
|
|
f2f5641b33 | ||
|
|
f530e3e4a7 | ||
|
|
7e8d658c21 | ||
|
|
86a0ef2854 | ||
|
|
d832e9f48a | ||
|
|
e817da4b8b | ||
|
|
b516995e15 | ||
|
|
d5802370f0 | ||
|
|
a3e1db9578 | ||
|
|
33003deadf | ||
|
|
a02d16ca62 | ||
|
|
126e1877fd | ||
|
|
0e84af73de | ||
|
|
c487137ac5 | ||
|
|
75cf9c40c4 | ||
|
|
3ec55ada1b | ||
|
|
edd713fd08 | ||
|
|
64e2f9c199 | ||
|
|
0265b48b35 | ||
|
|
5d9176725b | ||
|
|
3d3c5ab3e6 | ||
|
|
6aa1ce4f1b | ||
|
|
c9012b3157 | ||
|
|
27fae5c24c | ||
|
|
83c3c207cd | ||
|
|
0aaad536fb | ||
|
|
24576e3ef6 | ||
|
|
2d22ef1878 | ||
|
|
48f3ee050f | ||
|
|
915df39075 | ||
|
|
28efdc07c4 | ||
|
|
43f9f56077 | ||
|
|
60fbe49004 | ||
|
|
9c015067e3 | ||
|
|
406e4ff8a8 | ||
|
|
999676aef7 | ||
|
|
a01c83c718 | ||
|
|
5cc6ef1e9d | ||
|
|
3d99ca42b7 | ||
|
|
41660d36cd | ||
|
|
08d6ea6a53 | ||
|
|
aef277bbfe | ||
|
|
25f4a7292a | ||
|
|
6ab704a6fb | ||
|
|
b0e1b55537 | ||
|
|
67d10e1191 | ||
|
|
b486a10129 | ||
|
|
32552dc83a | ||
|
|
5dc01fa62a | ||
|
|
69576afcff | ||
|
|
6c99fd6dd1 | ||
|
|
83d0a06e6f | ||
|
|
5c69b2160c | ||
|
|
ed70e4e4b8 | ||
|
|
fc718145ae | ||
|
|
6d24fb801b | ||
|
|
a829212d42 | ||
|
|
8875261576 | ||
|
|
1758a91d72 | ||
|
|
8bd5525368 | ||
|
|
42f0086586 | ||
|
|
c94443eabe | ||
|
|
eba85c6b5c | ||
|
|
f9ab01e11b | ||
|
|
f41642f5d8 | ||
|
|
50586487d5 | ||
|
|
5336fce443 | ||
|
|
cb974f95e0 | ||
|
|
8e7bbe3a8d | ||
|
|
948a9c9e7c | ||
|
|
e65fe20e6d | ||
|
|
7727c7282c | ||
|
|
53c539ddae | ||
|
|
f1c62676c5 | ||
|
|
18fafd7c95 | ||
|
|
8860b44715 | ||
|
|
2a590360b6 | ||
|
|
6ff7b6f3c4 | ||
|
|
5409b33992 | ||
|
|
72ed16a343 | ||
|
|
0c7da48f8f | ||
|
|
c33acba4ff | ||
|
|
72857b6a56 | ||
|
|
825f14e8b5 | ||
|
|
d3806fc056 | ||
|
|
ab835ff46e | ||
|
|
7a7cf9d05d | ||
|
|
dfbb738aee | ||
|
|
b941b92dee | ||
|
|
f46e2b98cd | ||
|
|
1d563bbcdc | ||
|
|
f05922dfd0 | ||
|
|
1ff244c475 | ||
|
|
856ab15179 | ||
|
|
97c7417352 | ||
|
|
4214134e18 | ||
|
|
54a846f93a | ||
|
|
1702ca75ad | ||
|
|
dbdf91294e | ||
|
|
989c0e2024 | ||
|
|
5332610012 | ||
|
|
9d9a6f929c | ||
|
|
0f0f1ef3ca | ||
|
|
1d2cce5a40 | ||
|
|
9adf96dd2b | ||
|
|
755d864f14 | ||
|
|
af57b63458 | ||
|
|
2f4f5a8291 | ||
|
|
f6f87d3cd6 | ||
|
|
ef3ec54a4e | ||
|
|
c2e05239f6 | ||
|
|
583bf60ce8 | ||
|
|
15c42f9ee0 | ||
|
|
5e22ffc037 | ||
|
|
9d66d15801 | ||
|
|
c75b40245f | ||
|
|
eccfc9940d | ||
|
|
3a049d53ad | ||
|
|
2513dc5429 | ||
|
|
010e377669 | ||
|
|
b40321e3d9 | ||
|
|
96da2d8ffe | ||
|
|
f82e4011e6 | ||
|
|
24027aa1a1 | ||
|
|
269caf00b0 | ||
|
|
58bad186dc | ||
|
|
c38624cb50 | ||
|
|
3778a51feb | ||
|
|
7a09929887 | ||
|
|
1a1e229849 | ||
|
|
692191104d | ||
|
|
7586b5e15c | ||
|
|
caa8994d22 | ||
|
|
13ba39e2aa | ||
|
|
e2d9e04daa | ||
|
|
3a941e101e | ||
|
|
4156bf6703 | ||
|
|
8d1dfe8da9 | ||
|
|
89874ca324 | ||
|
|
a9c3c8709f | ||
|
|
9074d75d96 | ||
|
|
c242a7955a | ||
|
|
87da925085 | ||
|
|
cbb40522dc | ||
|
|
71f5ce3c04 | ||
|
|
31a7198b70 | ||
|
|
de4f12c38a | ||
|
|
447b7a021a | ||
|
|
c07223a92c | ||
|
|
46892bf9c9 | ||
|
|
3ea532a5b4 | ||
|
|
31b701429f | ||
|
|
5da2eefd50 | ||
|
|
6e5963ebe9 | ||
|
|
9d8035566f | ||
|
|
e26d73416b | ||
|
|
ceb090d60d | ||
|
|
e5cecae352 | ||
|
|
a2c5834255 | ||
|
|
4fcfb4edf2 | ||
|
|
670b12c4c9 | ||
|
|
cd3c767c71 | ||
|
|
3e74fe7de6 | ||
|
|
8332ab6022 | ||
|
|
f9243d4efe | ||
|
|
6c39518e43 | ||
|
|
c9402fe9e7 | ||
|
|
91d0553412 | ||
|
|
ef4609abbf | ||
|
|
a4774ff48d | ||
|
|
67e6f1a979 | ||
|
|
5120ad2742 | ||
|
|
27dc777d19 | ||
|
|
73c561d698 | ||
|
|
c8551d58ff | ||
|
|
b677d3fe5f | ||
|
|
2494c55ccc | ||
|
|
537416f88f | ||
|
|
90e926b14b | ||
|
|
b2caaca1e2 | ||
|
|
63197f03ce | ||
|
|
ccfe4a891d | ||
|
|
f96d00ec6f | ||
|
|
03e1fcebb8 | ||
|
|
f995f53aa2 | ||
|
|
b46f4f75c8 | ||
|
|
f4b5b3fbc4 | ||
|
|
2f9845efcd | ||
|
|
c7d323b080 | ||
|
|
4013634c00 | ||
|
|
e5b33f652f | ||
|
|
9b75dcf9d2 | ||
|
|
137ecb8d01 | ||
|
|
d2aa7534fe | ||
|
|
9b4b0c289e | ||
|
|
d03067db67 | ||
|
|
8c2e6f1539 | ||
|
|
a46215fb89 | ||
|
|
e0cecc34d6 | ||
|
|
1d678d9564 | ||
|
|
7fd9ebecfe | ||
|
|
223583b217 | ||
|
|
417368bcd4 | ||
|
|
97a6369f2f | ||
|
|
b9bbaaa696 | ||
|
|
9355cd1671 | ||
|
|
d49126ecc8 | ||
|
|
bd1953d35f | ||
|
|
2001d1be3f | ||
|
|
02fe76d1f0 | ||
|
|
88c159dc82 | ||
|
|
46d0645313 | ||
|
|
a92b15deee | ||
|
|
8b4a0b455e | ||
|
|
5613a70b18 | ||
|
|
2f1579941b | ||
|
|
05e3f9484e | ||
|
|
45eeb25149 | ||
|
|
3e9d8063cc | ||
|
|
97e9b57eb0 | ||
|
|
9b2447b249 | ||
|
|
f192d154c1 | ||
|
|
48ec8b33aa | ||
|
|
2040d594c7 |
12
.editorconfig
Normal file
12
.editorconfig
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// const process = require('node:process')
|
|
||||||
// process.env.ESLINT_TSCONFIG = 'tsconfig.json'
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
extends: '@antfu',
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
'vue/one-component-per-file': 'off',
|
|
||||||
'vue/no-reserved-component-names': 'off',
|
|
||||||
'vue/no-useless-v-bind': 'off',
|
|
||||||
'symbol-description': 'off',
|
|
||||||
'no-console': 'warn',
|
|
||||||
'no-tabs': 'off',
|
|
||||||
'no-invalid-character': 'off',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
55
.gitea/ISSUE_TEMPLATE/bug-report.yml
Normal file
55
.gitea/ISSUE_TEMPLATE/bug-report.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
name: 🐞 Bug report
|
||||||
|
description: Create a report to help us improve shadcn-vue.
|
||||||
|
title: '[Bug]: '
|
||||||
|
labels: [bug]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
This form is only for submitting bug reports. If you have a usage question
|
||||||
|
or are unsure if this is really a bug, make sure to:
|
||||||
|
|
||||||
|
- Read the [docs](https://radix-vue.com/)
|
||||||
|
- Ask on [Discord Chat](https://chat.radix-vue.com/)
|
||||||
|
- Ask on [GitHub Discussions](https://github.com/shadcn-vue/shadcn-vue/discussions)
|
||||||
|
- type: input
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Reproduction
|
||||||
|
description: |
|
||||||
|
A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is **required**, otherwise the issue might be closed without further notice. [**Why?**](https://antfu.me/posts/why-reproductions-are-required)
|
||||||
|
|
||||||
|
To get started, you can use the StackBlitz and CodeSandbox playgrounds in shadcn-vue demos:
|
||||||
|
https://www.shadcn-vue.com/docs/components/accordion.html
|
||||||
|
|
||||||
|
or use template presets
|
||||||
|
https://vite.new
|
||||||
|
https://nuxt.new
|
||||||
|
placeholder: Reproduction
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: bug-description
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
|
||||||
|
placeholder: Bug description
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: system-info
|
||||||
|
attributes:
|
||||||
|
label: System Info
|
||||||
|
description: Output of `npx envinfo --system --npmPackages vue,@vueuse/core,radix-vue,nuxt,shadcn-vue,shadcn-nuxt,unplugin-auto-import --binaries --browsers`
|
||||||
|
render: bash
|
||||||
|
placeholder: System, Binaries, Browsers
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: contributes
|
||||||
|
attributes:
|
||||||
|
label: Contributes
|
||||||
|
options:
|
||||||
|
- label: I am willing to submit a PR to fix this issue
|
||||||
|
- label: I am willing to submit a PR with failing tests
|
||||||
17
.gitea/actions/setup/action.yml
Normal file
17
.gitea/actions/setup/action.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: Setup
|
||||||
|
description: Installs Node, Enables Corepack and caches pnpm.
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Enable corepack
|
||||||
|
run: corepack enable
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Setup node & pnpm
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: lts/*
|
||||||
|
cache: pnpm
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
90
.gitea/workflows/publish.yaml
Normal file
90
.gitea/workflows/publish.yaml
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
name: Publish www
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- 'apps/www/**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- 'apps/www/**'
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
# When a created pull request from forked repo, it will be comment 'Should deploy to add label'
|
||||||
|
- opened
|
||||||
|
# When a labeled '🚀request-deploy' pull request from forked repo, it will be deploy to Cloudflare Pages
|
||||||
|
- labeled
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
# default contents: read & write (in forked repos, only read)
|
||||||
|
contents: write
|
||||||
|
# default deployments: read & write (in forked repos, only read)
|
||||||
|
deployments: write
|
||||||
|
# default pull-requests: read & write (in forked repos, only read)
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Publish to Cloudflare Pages
|
||||||
|
# push event in main branch
|
||||||
|
# workflow_dispatch event
|
||||||
|
# pull_request event from not forked repo
|
||||||
|
# pull_request_target event with label "🚀request-deploy" from forked repo
|
||||||
|
if: ${{
|
||||||
|
github.event_name == 'push' ||
|
||||||
|
github.event_name == 'workflow_dispatch' ||
|
||||||
|
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) ||
|
||||||
|
(github.event_name == 'pull_request_target' &&
|
||||||
|
github.event.action == 'labeled' &&
|
||||||
|
github.event.pull_request.head.repo.fork == true &&
|
||||||
|
contains(github.event.label.name, '🚀request-deploy'))
|
||||||
|
}}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup (Install Node & pnpm)
|
||||||
|
uses: ./.github/actions/setup
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm i --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build www
|
||||||
|
run: pnpm build
|
||||||
|
|
||||||
|
# Run a action to publish docs
|
||||||
|
- name: Publish to Cloudflare Pages
|
||||||
|
uses: zernonia/cloudflare-pages-action@v0.0.7
|
||||||
|
with:
|
||||||
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
|
projectName: shadcn-vue
|
||||||
|
directory: .vitepress/dist
|
||||||
|
# Optional: Enable this if you want to have GitHub Deployments triggered
|
||||||
|
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Optional: Switch what branch you are publishing to.
|
||||||
|
# By default this will be the branch which triggered this workflow
|
||||||
|
branch: ${{ github.ref == 'refs/heads/dev' && 'dev' || format('refs/pull/{0}/merge', github.event.number) }}
|
||||||
|
# Optional: Change the working directory
|
||||||
|
workingDirectory: apps/www
|
||||||
|
wranglerVersion: '3'
|
||||||
|
|
||||||
|
- name: Remove label
|
||||||
|
if: ${{ github.event_name == 'pull_request_target' && contains(github.event.label.name, '🚀request-deploy') }}
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.removeLabel({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
name: ['🚀request-deploy']
|
||||||
|
})
|
||||||
39
.gitea/workflows/release.yaml
Normal file
39
.gitea/workflows/release.yaml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
# .github/workflows/release.yml
|
||||||
|
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup (Install Node & pnpm)
|
||||||
|
uses: ./.github/actions/setup
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm i --frozen-lockfile
|
||||||
|
|
||||||
|
- run: pnpm dlx changelogithub
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
|
||||||
|
- name: Build CLI & Publish to npm
|
||||||
|
run: pnpm --filter shadcn-vue pub:release
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build Module & Publish to npm
|
||||||
|
run: pnpm --filter shadcn-nuxt pub:release
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
31
.gitea/workflows/test.yaml
Normal file
31
.gitea/workflows/test.yaml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- 'packages/**'
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- 'packages/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup (Install Node & pnpm)
|
||||||
|
uses: ./.github/actions/setup
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm i --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm test
|
||||||
86
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
86
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
|
|
@ -1,86 +0,0 @@
|
||||||
name: 🐞 Bug report
|
|
||||||
description: Create a report to help us improve shadcn-vue.
|
|
||||||
title: '[Bug]: '
|
|
||||||
labels: [bug]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
**Before You Start...**
|
|
||||||
|
|
||||||
This form is only for submitting bug reports. If you have a usage question
|
|
||||||
or are unsure if this is really a bug, make sure to:
|
|
||||||
|
|
||||||
- Read the [docs](https://radix-vue.com/)
|
|
||||||
- Ask on [Discord Chat](https://chat.radix-vue.com/)
|
|
||||||
- Ask on [GitHub Discussions](https://github.com/shadcn-vue/shadcn-vue/discussions)
|
|
||||||
|
|
||||||
Also try to search for your issue - it may have already been answered or even fixed.
|
|
||||||
However, if you find that an old, closed issue still persists in the latest version,
|
|
||||||
you should open a new issue using the form below instead of commenting on the old issue.
|
|
||||||
- type: textarea
|
|
||||||
id: bug-env
|
|
||||||
attributes:
|
|
||||||
label: Environment
|
|
||||||
description: Please provide the following information about your environment.
|
|
||||||
value: |
|
|
||||||
Developement/Production OS: Windows 10 19043.1110
|
|
||||||
Node version: 16.0.0
|
|
||||||
Package manager: pnpm@8.6.0
|
|
||||||
Radix Vue version: 1.0.0
|
|
||||||
Shadcn Vue version: 1.0.0
|
|
||||||
Vue version: 3.0.0
|
|
||||||
Nuxt version: 3.0.0
|
|
||||||
Nuxt mode: universal
|
|
||||||
Nuxt target: server
|
|
||||||
CSS framework: tailwindcss@3.3.3
|
|
||||||
Client OS: Windows 10 19043.1110
|
|
||||||
Browser: Chrome 90.0.4430.212
|
|
||||||
render: bash
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: reproduction-link
|
|
||||||
attributes:
|
|
||||||
label: Link to minimal reproduction
|
|
||||||
description: |
|
|
||||||
Please provide a link to a minimal reproduction of the bug.
|
|
||||||
A minimal reproduction is a CodeSandbox, CodePen, or a StackBlitz that contains the bare minimum amount of code needed to show the bug.
|
|
||||||
A minimal reproduction is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem
|
|
||||||
|
|
||||||
This is **required** for us to be able to triage your issue in a timely manner.
|
|
||||||
|
|
||||||
Please do not just fill in a random link. The issue will be closed if no valid reproduction is provided.
|
|
||||||
placeholder: Reproduction Link
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: steps-to-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce
|
|
||||||
description: |
|
|
||||||
How do you trigger this bug? Please walk us through it step by step.
|
|
||||||
Note that you can use [Markdown](https://guides.github.com/features/mastering-markdown/) to format lists and code.
|
|
||||||
placeholder: Steps to reproduce
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: bug-description
|
|
||||||
attributes:
|
|
||||||
label: Describe the bug
|
|
||||||
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
|
|
||||||
placeholder: Bug description
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: expected-behavior
|
|
||||||
attributes:
|
|
||||||
label: Expected behavior
|
|
||||||
description: A clear and concise description of what you expected to happen.
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Conext & Screenshots (if applicable)
|
|
||||||
description: |
|
|
||||||
If applicable, provide any additional context or screenshots of the bug.
|
|
||||||
You can drag and drop images here to add them to the issue.
|
|
||||||
72
.github/workflows/publish.yaml
vendored
72
.github/workflows/publish.yaml
vendored
|
|
@ -1,72 +0,0 @@
|
||||||
name: Publish www
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- 'apps/www/**'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- 'apps/www/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
deployments: write
|
|
||||||
name: Publish to Cloudflare Pages
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
# Run a build step here
|
|
||||||
- name: Setup Node.js environment
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ env.STORE_PATH }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm i --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Build www
|
|
||||||
run: pnpm build
|
|
||||||
|
|
||||||
# Run a action to publish docs
|
|
||||||
- name: Publish to Cloudflare Pages
|
|
||||||
uses: cloudflare/pages-action@v1.5.0
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: shadcn-vue
|
|
||||||
directory: .vitepress/dist
|
|
||||||
# Optional: Enable this if you want to have GitHub Deployments triggered
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# Optional: Switch what branch you are publishing to.
|
|
||||||
# By default this will be the branch which triggered this workflow
|
|
||||||
# branch: main
|
|
||||||
# Optional: Change the working directory
|
|
||||||
workingDirectory: apps/www
|
|
||||||
wranglerVersion: '3'
|
|
||||||
52
.github/workflows/test.yaml
vendored
52
.github/workflows/test.yaml
vendored
|
|
@ -1,52 +0,0 @@
|
||||||
name: Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- 'packages/**'
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- 'packages/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Setup Node.js environment
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
name: Install pnpm
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
run_install: false
|
|
||||||
|
|
||||||
- name: Get pnpm store directory
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: Setup pnpm cache
|
|
||||||
with:
|
|
||||||
path: ${{ env.STORE_PATH }}
|
|
||||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pnpm-store-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm i --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm test
|
|
||||||
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"Vue.volar",
|
"Vue.volar",
|
||||||
"Vue.vscode-typescript-vue-plugin",
|
"dbaeumer.vscode-eslint",
|
||||||
"dbaeumer.vscode-eslint"
|
"bradlc.vscode-tailwindcss"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
.vscode/settings.json
vendored
27
.vscode/settings.json
vendored
|
|
@ -1,11 +1,28 @@
|
||||||
{
|
{
|
||||||
|
"vue.server.hybridMode": true,
|
||||||
|
"vue.server.includeLanguages": [
|
||||||
|
"vue",
|
||||||
|
"markdown"
|
||||||
|
],
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true,
|
"source.fixAll.eslint": "explicit",
|
||||||
"source.organizeImports": false
|
"source.organizeImports": "never"
|
||||||
},
|
},
|
||||||
|
"eslint.useFlatConfig": true,
|
||||||
|
"eslint.rules.customizations": [
|
||||||
|
{ "rule": "style/*", "severity": "off" },
|
||||||
|
{ "rule": "format/*", "severity": "off" },
|
||||||
|
{ "rule": "*-indent", "severity": "off" },
|
||||||
|
{ "rule": "*-spacing", "severity": "off" },
|
||||||
|
{ "rule": "*-spaces", "severity": "off" },
|
||||||
|
{ "rule": "*-order", "severity": "off" },
|
||||||
|
{ "rule": "*-dangle", "severity": "off" },
|
||||||
|
{ "rule": "*-newline", "severity": "off" },
|
||||||
|
{ "rule": "*quotes", "severity": "off" },
|
||||||
|
{ "rule": "*semi", "severity": "off" }
|
||||||
|
],
|
||||||
"eslint.validate": [
|
"eslint.validate": [
|
||||||
"javascript",
|
"javascript",
|
||||||
"javascriptreact",
|
"javascriptreact",
|
||||||
|
|
@ -17,5 +34,9 @@
|
||||||
"json",
|
"json",
|
||||||
"jsonc",
|
"jsonc",
|
||||||
"yaml"
|
"yaml"
|
||||||
|
],
|
||||||
|
"tailwindCSS.experimental.classRegex": [
|
||||||
|
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
|
||||||
|
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ This repository is structured as follows:
|
||||||
```
|
```
|
||||||
apps
|
apps
|
||||||
└── www
|
└── www
|
||||||
├── src
|
├── src
|
||||||
│ └── content
|
│ └── content
|
||||||
└── registry
|
└── registry
|
||||||
├── default
|
├── default
|
||||||
|
|
@ -32,12 +32,12 @@ packages
|
||||||
└── cli
|
└── cli
|
||||||
```
|
```
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| --------------------- | ---------------------------------------- |
|
| ----------------------------| -------------------------------------------|
|
||||||
| `apps/www/app` | The Next.js application for the website. |
|
| `apps/www/.vitepress` | The Vitepress application for the website. |
|
||||||
| `apps/www/content` | The content for the website. |
|
| `apps/www/src/content` | The content for the website. |
|
||||||
| `apps/www/registry` | The registry for the components. |
|
| `apps/www/src/lib/registry` | The registry for the components. |
|
||||||
| `packages/cli` | The `shadcn-vue` package. |
|
| `packages/cli` | The `shadcn-vue` package. |
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|
@ -79,22 +79,24 @@ The documentation for this project is located in the `www` workspace. You can ru
|
||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/content/docs` directory.
|
Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/src/content` directory.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
We use a registry system for developing components. You can find the source code for the components under `apps/www/registry`. The components are organized by styles.
|
We use a registry system for developing components. You can find the source code for the components under `apps/www/src/lib/registry`. The components are organized by styles.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
apps
|
apps
|
||||||
└── www
|
└── www
|
||||||
└── registry
|
└── src
|
||||||
├── default
|
└── lib
|
||||||
│ ├── example
|
└── registry
|
||||||
│ └── ui
|
├── default
|
||||||
└── new-york
|
│ ├── example
|
||||||
├── example
|
│ └── ui
|
||||||
└── ui
|
└── new-york
|
||||||
|
├── example
|
||||||
|
└── ui
|
||||||
```
|
```
|
||||||
|
|
||||||
When adding or modifying components, please ensure that:
|
When adding or modifying components, please ensure that:
|
||||||
|
|
@ -130,13 +132,10 @@ the following categories:
|
||||||
|
|
||||||
e.g. `feat(components): add new prop to the avatar component`
|
e.g. `feat(components): add new prop to the avatar component`
|
||||||
|
|
||||||
|
|
||||||
If you are interested in the detailed specification you can visit
|
If you are interested in the detailed specification you can visit
|
||||||
https://www.conventionalcommits.org/ or check out the
|
https://www.conventionalcommits.org/ or check out the
|
||||||
[Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines).
|
[Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Requests for new components
|
## Requests for new components
|
||||||
|
|
||||||
If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out.
|
If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out.
|
||||||
|
|
@ -155,4 +154,4 @@ Tests are written using [Vitest](https://vitest.dev). You can run all the tests
|
||||||
pnpm test
|
pnpm test
|
||||||
```
|
```
|
||||||
|
|
||||||
Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests.
|
Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img align="center" src="https://raw.githubusercontent.com/radix-vue/shadcn-vue/dev/apps/www/src/public/android-chrome-192x192.png" height="96" />
|
<img align="center" src="https://raw.githubusercontent.com/radix-vue/shadcn-vue/dev/apps/www/src/public/android-chrome-192x192.png" height="96" />
|
||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
shadcn-vue
|
shadcn-vue by Niklas Hermanns
|
||||||
</h1>
|
</h1>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -31,3 +31,7 @@ All credits go to these open-source works and resources
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under the [MIT license](https://github.com/shadcn/ui/blob/main/LICENSE.md).
|
Licensed under the [MIT license](https://github.com/shadcn/ui/blob/main/LICENSE.md).
|
||||||
|
|
||||||
|
## Actions
|
||||||
|
|
||||||
|
- Test
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { defineConfig } from 'vitepress'
|
import { transformerMetaWordHighlight } from '@shikijs/transformers'
|
||||||
import Icons from 'unplugin-icons/vite'
|
|
||||||
import tailwind from 'tailwindcss'
|
|
||||||
import autoprefixer from 'autoprefixer'
|
import autoprefixer from 'autoprefixer'
|
||||||
|
import tailwind from 'tailwindcss'
|
||||||
|
import Icons from 'unplugin-icons/vite'
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
|
||||||
import { siteConfig } from './theme/config/site'
|
import { siteConfig } from './theme/config/site'
|
||||||
|
import CodeWrapperPlugin from './theme/plugins/codewrapper'
|
||||||
import ComponentPreviewPlugin from './theme/plugins/previewer'
|
import ComponentPreviewPlugin from './theme/plugins/previewer'
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
|
|
@ -17,6 +20,9 @@ export default defineConfig({
|
||||||
['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }],
|
['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }],
|
||||||
['link', { rel: 'manifest', href: '/site.webmanifest' }],
|
['link', { rel: 'manifest', href: '/site.webmanifest' }],
|
||||||
|
|
||||||
|
['meta', { name: 'theme-color', media: '(prefers-color-scheme: light)', content: 'white' }],
|
||||||
|
['meta', { name: 'theme-color', media: '(prefers-color-scheme: dark)', content: 'black' }],
|
||||||
|
|
||||||
['meta', { name: 'creator', content: 'radix-vue' }],
|
['meta', { name: 'creator', content: 'radix-vue' }],
|
||||||
['meta', { name: 'theme-color', content: '#41b883' }],
|
['meta', { name: 'theme-color', content: '#41b883' }],
|
||||||
['meta', { name: 'og:type', content: 'website' }],
|
['meta', { name: 'og:type', content: 'website' }],
|
||||||
|
|
@ -24,7 +30,6 @@ export default defineConfig({
|
||||||
['meta', { name: 'og:site_name', content: siteConfig.name }],
|
['meta', { name: 'og:site_name', content: siteConfig.name }],
|
||||||
['meta', { name: 'og:image', content: siteConfig.ogImage }],
|
['meta', { name: 'og:image', content: siteConfig.ogImage }],
|
||||||
['meta', { name: 'twitter:image', content: siteConfig.ogImage }],
|
['meta', { name: 'twitter:image', content: siteConfig.ogImage }],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
sitemap: {
|
sitemap: {
|
||||||
|
|
@ -43,13 +48,20 @@ export default defineConfig({
|
||||||
pattern: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/:path',
|
pattern: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/:path',
|
||||||
text: 'Edit this page on GitHub',
|
text: 'Edit this page on GitHub',
|
||||||
},
|
},
|
||||||
|
carbonAds: {
|
||||||
|
code: 'CW7DK27U',
|
||||||
|
placement: 'wwwshadcn-vuecom',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
srcDir: path.resolve(__dirname, '../src'),
|
srcDir: path.resolve(__dirname, '../src'),
|
||||||
markdown: {
|
markdown: {
|
||||||
theme: 'css-variables',
|
codeTransformers: [
|
||||||
|
transformerMetaWordHighlight(),
|
||||||
|
],
|
||||||
config(md) {
|
config(md) {
|
||||||
md.use(ComponentPreviewPlugin)
|
md.use(ComponentPreviewPlugin)
|
||||||
|
md.use(CodeWrapperPlugin)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rewrites: {
|
rewrites: {
|
||||||
|
|
@ -59,13 +71,13 @@ export default defineConfig({
|
||||||
css: {
|
css: {
|
||||||
postcss: {
|
postcss: {
|
||||||
plugins: [
|
plugins: [
|
||||||
tailwind(),
|
tailwind() as any,
|
||||||
autoprefixer(),
|
autoprefixer(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
Icons({ compiler: 'vue3', autoInstall: true }),
|
Icons({ compiler: 'vue3', autoInstall: true }) as any,
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|
|
||||||
26
apps/www/.vitepress/theme/components/APITable.vue
Normal file
26
apps/www/.vitepress/theme/components/APITable.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { capitalize } from 'vue'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
type: 'prop' | 'emit' | 'slot' | 'method'
|
||||||
|
data: { name: string, description: string, type: string, required: boolean }[]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h3>{{ capitalize(type) }}</h3>
|
||||||
|
|
||||||
|
<div v-for="(item, index) in data" :key="index" class="py-4 border-b text-sm">
|
||||||
|
<div class="flex items-center gap-2 flex-wrap">
|
||||||
|
<h5 class="text-sm">
|
||||||
|
<code>{{ item.name }}</code>
|
||||||
|
</h5>
|
||||||
|
<code>{{ item.type }}</code>
|
||||||
|
<span v-if="item.required" class="font-normal text-red-500 text-xs">Required*</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="[&_p]:!my-2 ml-1" v-html="item.description" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
19
apps/www/.vitepress/theme/components/Announcement.vue
Normal file
19
apps/www/.vitepress/theme/components/Announcement.vue
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Separator } from '@/lib/registry/default/ui/separator'
|
||||||
|
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
||||||
|
import { announcementConfig } from '../config/site'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a
|
||||||
|
:href="announcementConfig.link"
|
||||||
|
class="inline-flex items-center rounded-lg bg-muted px-3 py-1 text-sm font-medium"
|
||||||
|
>
|
||||||
|
{{ announcementConfig.icon }} <Separator class="mx-2 h-4" orientation="vertical" />
|
||||||
|
<span class="sm:hidden">{{ announcementConfig.title }}</span>
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
{{ announcementConfig.title }}
|
||||||
|
</span>
|
||||||
|
<ArrowRightIcon class="ml-1 h-4 w-4" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
233
apps/www/.vitepress/theme/components/BlockContainer.vue
Normal file
233
apps/www/.vitepress/theme/components/BlockContainer.vue
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { CircleHelp, Info, Monitor, Smartphone, Tablet } from 'lucide-vue-next'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
import { compileScript, parse, walk } from 'vue/compiler-sfc'
|
||||||
|
import { highlight } from '../config/shiki'
|
||||||
|
import BlockCopyButton from './BlockCopyButton.vue'
|
||||||
|
import StyleSwitcher from './StyleSwitcher.vue'
|
||||||
|
|
||||||
|
// import { V0Button } from '@/components/v0-button'
|
||||||
|
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
||||||
|
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/lib/registry/new-york/ui/resizable'
|
||||||
|
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/new-york/ui/tabs'
|
||||||
|
import { ToggleGroup, ToggleGroupItem } from '@/lib/registry/new-york/ui/toggle-group'
|
||||||
|
import BlockPreview from './BlockPreview.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { style, codeConfig } = useConfigStore()
|
||||||
|
|
||||||
|
const isLoading = ref(true)
|
||||||
|
const tabValue = ref('preview')
|
||||||
|
const resizableRef = ref<InstanceType<typeof ResizablePanel>>()
|
||||||
|
|
||||||
|
const rawString = ref('')
|
||||||
|
const codeHtml = ref('')
|
||||||
|
const metadata = reactive({
|
||||||
|
description: null as string | null,
|
||||||
|
iframeHeight: null as string | null,
|
||||||
|
containerClass: null as string | null,
|
||||||
|
})
|
||||||
|
|
||||||
|
function removeScript(code: string) {
|
||||||
|
const s = new MagicString(code)
|
||||||
|
const scriptTagRegex = /<script\s+lang="ts"\s*>[\s\S]+?<\/script>/g
|
||||||
|
let match
|
||||||
|
// eslint-disable-next-line no-cond-assign
|
||||||
|
while ((match = scriptTagRegex.exec(code)) !== null) {
|
||||||
|
const start = match.index
|
||||||
|
const end = match.index + match[0].length
|
||||||
|
s.overwrite(start, end, '') // Replace the script tag with an empty string
|
||||||
|
}
|
||||||
|
return s.trimStart().toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformImportPath(code: string) {
|
||||||
|
const s = new MagicString(code)
|
||||||
|
s.replaceAll(`@/lib/registry/${style.value}`, codeConfig.value.componentsPath)
|
||||||
|
s.replaceAll(`@/lib/utils`, codeConfig.value.utilsPath)
|
||||||
|
return s.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([style, codeConfig], async () => {
|
||||||
|
try {
|
||||||
|
const baseRawString = await import(`../../../src/lib/registry/${style.value}/block/${props.name}.vue?raw`).then(res => res.default.trim())
|
||||||
|
rawString.value = transformImportPath(removeScript(baseRawString))
|
||||||
|
|
||||||
|
if (!metadata.description) {
|
||||||
|
const { descriptor } = parse(baseRawString)
|
||||||
|
const ast = compileScript(descriptor, { id: '' })
|
||||||
|
walk(ast.scriptAst, {
|
||||||
|
enter(node: any) {
|
||||||
|
const declaration = node.declaration
|
||||||
|
// Check if the declaration is a variable declaration
|
||||||
|
if (declaration?.type === 'VariableDeclaration') {
|
||||||
|
// Extract variable names and their values
|
||||||
|
declaration.declarations.forEach((decl: any) => {
|
||||||
|
// @ts-expect-error ignore missing type
|
||||||
|
metadata[decl.id.name] = decl.init ? decl.init.value : null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
codeHtml.value = highlight(rawString.value, 'vue')
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}, { immediate: true, deep: true })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Tabs
|
||||||
|
:id="name"
|
||||||
|
v-model="tabValue"
|
||||||
|
class="relative grid w-full scroll-m-20 gap-4"
|
||||||
|
:style=" {
|
||||||
|
'--container-height': metadata.iframeHeight ?? '600px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col items-center gap-4 sm:flex-row">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<TabsList class="hidden sm:flex">
|
||||||
|
<TabsTrigger value="preview">
|
||||||
|
Preview
|
||||||
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="code">
|
||||||
|
Code
|
||||||
|
</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
<div class="hidden items-center gap-2 sm:flex">
|
||||||
|
<Separator
|
||||||
|
orientation="vertical"
|
||||||
|
class="mx-2 hidden h-4 md:flex"
|
||||||
|
/>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<a :href="`#${name}`">
|
||||||
|
<Badge variant="outline">{{ name }}</Badge>
|
||||||
|
</a>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||||
|
<Info class="h-3.5 w-3.5" />
|
||||||
|
<span class="sr-only">Block description</span>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent
|
||||||
|
side="right"
|
||||||
|
:side-offset="10"
|
||||||
|
class="text-sm"
|
||||||
|
>
|
||||||
|
{{ metadata.description }}
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2 pr-[14px] sm:ml-auto">
|
||||||
|
<div class="hidden h-[28px] items-center gap-1.5 rounded-md border p-[2px] shadow-sm md:flex">
|
||||||
|
<ToggleGroup
|
||||||
|
type="single"
|
||||||
|
default-value="100"
|
||||||
|
@update:model-value="(value) => {
|
||||||
|
resizableRef?.resize(parseInt(value as string))
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<ToggleGroupItem
|
||||||
|
value="100"
|
||||||
|
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||||
|
>
|
||||||
|
<Monitor class="h-3.5 w-3.5" />
|
||||||
|
</ToggleGroupItem>
|
||||||
|
<ToggleGroupItem
|
||||||
|
value="60"
|
||||||
|
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||||
|
>
|
||||||
|
<Tablet class="h-3.5 w-3.5" />
|
||||||
|
</ToggleGroupItem>
|
||||||
|
<ToggleGroupItem
|
||||||
|
value="30"
|
||||||
|
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||||
|
>
|
||||||
|
<Smartphone class="h-3.5 w-3.5" />
|
||||||
|
</ToggleGroupItem>
|
||||||
|
</ToggleGroup>
|
||||||
|
</div>
|
||||||
|
<Separator
|
||||||
|
orientation="vertical"
|
||||||
|
class="mx-2 hidden h-4 md:flex"
|
||||||
|
/>
|
||||||
|
<StyleSwitcher class="h-7" />
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||||
|
<CircleHelp class="h-3.5 w-3.5" />
|
||||||
|
<span class="sr-only">Block description</span>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent
|
||||||
|
side="top"
|
||||||
|
:side-offset="20"
|
||||||
|
class="space-y-3 rounded-[0.5rem] text-sm"
|
||||||
|
>
|
||||||
|
<p class="font-medium">
|
||||||
|
What is the difference between the New York and Default style?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A style comes with its own set of components, animations,
|
||||||
|
icons and more.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <span class="font-medium">Default</span> style has
|
||||||
|
larger inputs, uses lucide-vue-next for icons and
|
||||||
|
tailwindcss-animate for animations.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <span class="font-medium">New York</span> style ships
|
||||||
|
with smaller buttons and inputs. It also uses shadows on cards
|
||||||
|
and buttons.
|
||||||
|
</p>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<Separator orientation="vertical" class="mx-2 h-4" />
|
||||||
|
<BlockCopyButton :code="rawString" />
|
||||||
|
<!-- <V0Button
|
||||||
|
name="{block.name}"
|
||||||
|
description="{block.description" || "Edit in v0"}
|
||||||
|
code="{block.code}"
|
||||||
|
style="{block.style}"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TabsContent
|
||||||
|
v-show="tabValue === 'preview'"
|
||||||
|
force-mount
|
||||||
|
value="preview"
|
||||||
|
class="relative after:absolute after:inset-0 after:right-3 after:z-0 after:rounded-lg after:bg-muted h-[--container-height] px-0"
|
||||||
|
>
|
||||||
|
<ResizablePanelGroup id="block-resizable" direction="horizontal" class="relative z-10">
|
||||||
|
<ResizablePanel
|
||||||
|
id="block-resizable-panel-1"
|
||||||
|
ref="resizableRef"
|
||||||
|
:default-size="100"
|
||||||
|
:min-size="30"
|
||||||
|
:as-child="true"
|
||||||
|
>
|
||||||
|
<BlockPreview :name="name" styles="default" :container-class="metadata.containerClass ?? ''" container />
|
||||||
|
</ResizablePanel>
|
||||||
|
<ResizableHandle id="block-resizable-handle" class="relative hidden w-3 bg-transparent p-0 after:absolute after:right-0 after:top-1/2 after:h-8 after:w-[6px] after:-translate-y-1/2 after:translate-x-[-1px] after:rounded-full after:bg-border after:transition-all after:hover:h-10 sm:block" />
|
||||||
|
<ResizablePanel id="block-resizable-panel-2" :default-size="0" :min-size="0" />
|
||||||
|
</ResizablePanelGroup>
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="code" class="h-[--container-height]">
|
||||||
|
<div
|
||||||
|
class="language-vue !h-full !max-h-[none] !mt-0"
|
||||||
|
v-html="codeHtml"
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</template>
|
||||||
38
apps/www/.vitepress/theme/components/BlockCopyButton.vue
Normal file
38
apps/www/.vitepress/theme/components/BlockCopyButton.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@/lib/registry/new-york/ui/tooltip'
|
||||||
|
import { CheckIcon, ClipboardIcon } from '@radix-icons/vue'
|
||||||
|
import { useClipboard } from '@vueuse/core'
|
||||||
|
import { toRefs } from 'vue'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
code?: string
|
||||||
|
}>(), {
|
||||||
|
code: '',
|
||||||
|
})
|
||||||
|
const { code } = toRefs(props)
|
||||||
|
|
||||||
|
const { copy, copied } = useClipboard({ source: code })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Tooltip :delay-duration="100">
|
||||||
|
<TooltipTrigger as-child>
|
||||||
|
<Button
|
||||||
|
size="icon"
|
||||||
|
variant="outline"
|
||||||
|
class="h-7 w-7 [&_svg]:size-3.5"
|
||||||
|
@click="copy()"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Copy</span>
|
||||||
|
<CheckIcon v-if="copied" />
|
||||||
|
<ClipboardIcon v-else />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Copy code</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</template>
|
||||||
12
apps/www/.vitepress/theme/components/BlockPage.vue
Normal file
12
apps/www/.vitepress/theme/components/BlockPage.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useUrlSearchParams } from '@vueuse/core'
|
||||||
|
import ComponentLoader from './ComponentLoader.vue'
|
||||||
|
|
||||||
|
const params = useUrlSearchParams('history')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="params.name" :class="params.containerClass">
|
||||||
|
<ComponentLoader :key="params.style?.toString()" :name="params.name?.toString()" :type-name="'block'" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
44
apps/www/.vitepress/theme/components/BlockPreview.vue
Normal file
44
apps/www/.vitepress/theme/components/BlockPreview.vue
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import Spinner from './Spinner.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: string
|
||||||
|
styles?: string
|
||||||
|
containerClass?: string
|
||||||
|
container?: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const isLoading = ref(true)
|
||||||
|
|
||||||
|
const iframeURL = computed(() => {
|
||||||
|
// @ts-expect-error env available in import.meta
|
||||||
|
if (import.meta.env.SSR)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
const url = new URL(`${window.location.origin}/blocks/renderer`)
|
||||||
|
Object.entries(props).forEach(([key, value]) => {
|
||||||
|
if (value)
|
||||||
|
url.searchParams.append(key, value as string)
|
||||||
|
})
|
||||||
|
return url.href
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative rounded-lg border overflow-hidden bg-background" :class="[container ? '' : 'aspect-[4/2.5]']">
|
||||||
|
<div v-if="isLoading" class="flex items-center justify-center h-full">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="[container ? 'w-full' : 'absolute inset-0 hidden w-[1600px] bg-background md:block']"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
v-show="!isLoading"
|
||||||
|
:src="iframeURL"
|
||||||
|
class="relative z-20 w-full bg-background" :class="[container ? 'h-[--container-height]' : 'size-full']"
|
||||||
|
@load="isLoading = false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
53
apps/www/.vitepress/theme/components/Blocks.vue
Normal file
53
apps/www/.vitepress/theme/components/Blocks.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import GitHubIcon from '~icons/radix-icons/github-logo'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import Announcement from '../components/Announcement.vue'
|
||||||
|
import PageAction from '../components/PageAction.vue'
|
||||||
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
|
|
||||||
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
|
import BlockContainer from './BlockContainer.vue'
|
||||||
|
|
||||||
|
const blocks = ref<string[]>([])
|
||||||
|
|
||||||
|
import('../../../__registry__/index').then((res) => {
|
||||||
|
blocks.value = Object.values(res.Index.default).filter(i => i.type === 'components:block').map(i => i.name)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageHeader class="page-header pb-8">
|
||||||
|
<Announcement />
|
||||||
|
<PageHeaderHeading>Building Blocks for the Web</PageHeaderHeading>
|
||||||
|
<PageHeaderDescription>
|
||||||
|
Beautifully designed. Copy and paste into your apps. Open Source.
|
||||||
|
</PageHeaderDescription>
|
||||||
|
|
||||||
|
<PageAction>
|
||||||
|
<a
|
||||||
|
href="/blocks.html#blocks"
|
||||||
|
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
||||||
|
>
|
||||||
|
Browse
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://github.com/radix-vue/shadcn-vue"
|
||||||
|
target="_blank"
|
||||||
|
:class="cn(
|
||||||
|
buttonVariants({ variant: 'outline' }),
|
||||||
|
'rounded-[6px]',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<GitHubIcon class="mr-2 h-4 w-4" />
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
</PageAction>
|
||||||
|
</PageHeader>
|
||||||
|
|
||||||
|
<section id="blocks" class="grid scroll-mt-24 gap-24 lg:gap-48">
|
||||||
|
<BlockContainer v-for="block in blocks" :key="block" :name="block" />
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
@ -19,7 +19,7 @@ defineProps<CalloutProps>()
|
||||||
<AlertTitle v-if="title">
|
<AlertTitle v-if="title">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</AlertTitle>
|
</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription class="[&_a]:underline">
|
||||||
<slot />
|
<slot />
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
|
||||||
71
apps/www/.vitepress/theme/components/CarbonAds.vue
Normal file
71
apps/www/.vitepress/theme/components/CarbonAds.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useData } from 'vitepress'
|
||||||
|
import { onMounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
|
const { page, theme } = useData()
|
||||||
|
const carbonOptions = theme.value.carbonAds
|
||||||
|
const container = ref()
|
||||||
|
|
||||||
|
let isInitialized = false
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (!isInitialized) {
|
||||||
|
isInitialized = true
|
||||||
|
const s = document.createElement('script')
|
||||||
|
s.type = 'text/javascript'
|
||||||
|
s.id = '_carbonads_js'
|
||||||
|
s.src = `//cdn.carbonads.com/carbon.js?serve=${carbonOptions.code}&placement=${carbonOptions.placement}&format=cover`
|
||||||
|
s.async = true
|
||||||
|
container.value.appendChild(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => page.value.relativePath, () => {
|
||||||
|
if (isInitialized) {
|
||||||
|
;(window as any)._carbonads?.refresh()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// no need to account for option changes during dev, we can just
|
||||||
|
// refresh the page
|
||||||
|
if (carbonOptions) {
|
||||||
|
onMounted(() => {
|
||||||
|
// @ts-expect-error ignoring env
|
||||||
|
if (import.meta.env.DEV)
|
||||||
|
return
|
||||||
|
|
||||||
|
// if the page is loaded when aside is active, load carbon directly.
|
||||||
|
// otherwise, only load it if the page resizes to wide enough. this avoids
|
||||||
|
// loading carbon at all on mobile where it's never shown
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="container"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#carbon-responsive {
|
||||||
|
@apply w-[238px] !mt-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carbon-responsive-wrap {
|
||||||
|
@apply bg-muted/50 border border-muted p-4 rounded-md flex flex-col items-center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carbon-responsive-wrap .carbon-img {
|
||||||
|
@apply flex-none rounded overflow-hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carbon-responsive-wrap .carbon-text {
|
||||||
|
@apply text-muted-foreground text-sm flex-none text-center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#carbonads .carbon-poweredby {
|
||||||
|
@apply bg-background text-muted-foreground block text-right text-[10px] uppercase no-underline !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/lib/registry/new-york/ui/form'
|
||||||
|
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||||
|
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@/lib/registry/new-york/ui/sheet'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import RadixIconsGear from '~icons/radix-icons/gear'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
const { codeConfig, setCodeConfig } = useConfigStore()
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(z.object({
|
||||||
|
prefix: z.string().default(''),
|
||||||
|
componentsPath: z.string().default('@/components'),
|
||||||
|
utilsPath: z.string().default('@/utils'),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { handleSubmit, setValues } = useForm({
|
||||||
|
validationSchema: formSchema,
|
||||||
|
initialValues: codeConfig.value,
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit((values) => {
|
||||||
|
setCodeConfig(values)
|
||||||
|
setValues(values)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Sheet
|
||||||
|
@update:open="(open) => {
|
||||||
|
if (open) setValues(codeConfig)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<SheetTrigger as-child>
|
||||||
|
<Button
|
||||||
|
class="w-9 h-9"
|
||||||
|
:variant="'ghost'"
|
||||||
|
:size="'icon'"
|
||||||
|
>
|
||||||
|
<RadixIconsGear class="w-5 h-5" />
|
||||||
|
</Button>
|
||||||
|
</SheetTrigger>
|
||||||
|
<SheetContent>
|
||||||
|
<form @submit="onSubmit">
|
||||||
|
<SheetHeader>
|
||||||
|
<SheetTitle>Edit code config</SheetTitle>
|
||||||
|
<SheetDescription>
|
||||||
|
Configure how the CodeBlock should render on the site.
|
||||||
|
</SheetDescription>
|
||||||
|
</SheetHeader>
|
||||||
|
|
||||||
|
<div class="my-4">
|
||||||
|
<!-- <FormField v-slot="{ componentField }" name="prefix">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Prefix</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="" v-bind="componentField" />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription />
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField> -->
|
||||||
|
<FormField v-slot="{ componentField }" name="componentsPath">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Components Path</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="@/components" v-bind="componentField" />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription />
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
<FormField v-slot="{ componentField }" name="utilsPath">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Utils Path</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="@/utils" v-bind="componentField" />
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription />
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SheetFooter>
|
||||||
|
<SheetClose as-child>
|
||||||
|
<Button type="submit">
|
||||||
|
Save changes
|
||||||
|
</Button>
|
||||||
|
</SheetClose>
|
||||||
|
</SheetFooter>
|
||||||
|
</form>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
</template>
|
||||||
36
apps/www/.vitepress/theme/components/CodeSandbox.vue
Normal file
36
apps/www/.vitepress/theme/components/CodeSandbox.vue
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Style } from '@/lib/registry/styles'
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { Icon } from '@iconify/vue'
|
||||||
|
import { ref, toRefs, watch } from 'vue'
|
||||||
|
import { makeCodeSandboxParams } from '../utils/codeeditor'
|
||||||
|
import Tooltip from './Tooltip.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: string
|
||||||
|
code: string
|
||||||
|
style: Style
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { code } = toRefs(props)
|
||||||
|
const sources = ref<Record<string, string>>({})
|
||||||
|
|
||||||
|
watch(code, () => {
|
||||||
|
sources.value['App.vue'] = code.value
|
||||||
|
}, { immediate: true })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<form action="https://codesandbox.io/api/v1/sandboxes/define" method="POST" target="_blank">
|
||||||
|
<input type="hidden" name="query" value="file=src/App.vue">
|
||||||
|
<input type="hidden" name="environment" value="server">
|
||||||
|
<input type="hidden" name="hidedevtools" value="1">
|
||||||
|
<input type="hidden" name="parameters" :value="makeCodeSandboxParams(name, style, sources)">
|
||||||
|
|
||||||
|
<Tooltip :content="`Open ${name} in CodeSandbox`">
|
||||||
|
<Button :variant="'ghost'" :size="'icon'" type="submit">
|
||||||
|
<Icon icon="ph-codesandbox-logo" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
46
apps/www/.vitepress/theme/components/CodeWrapper.ts
Normal file
46
apps/www/.vitepress/theme/components/CodeWrapper.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { cloneVNode, defineComponent, type VNode, type VNodeArrayChildren } from 'vue'
|
||||||
|
|
||||||
|
function crawlSpan(children: VNodeArrayChildren, cb: (vnode: VNode) => void) {
|
||||||
|
children.forEach((childNode) => {
|
||||||
|
if (!Array.isArray(childNode) && typeof childNode === 'object') {
|
||||||
|
if (typeof childNode?.children === 'string')
|
||||||
|
cb(childNode)
|
||||||
|
else
|
||||||
|
crawlSpan(childNode?.children as VNodeArrayChildren ?? [], cb)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent(
|
||||||
|
(props, { slots }) => {
|
||||||
|
const { codeConfig } = useConfigStore()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const clonedVNode = slots.default?.()?.[0]
|
||||||
|
? cloneVNode(slots.default?.()?.[0], {
|
||||||
|
key: JSON.stringify(codeConfig.value),
|
||||||
|
})
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
// @ts-expect-error cloneVNode
|
||||||
|
const preVNode = [...clonedVNode?.children].find((node: VNode) => node.type === 'pre') as VNode
|
||||||
|
// @ts-expect-error cloneVNode
|
||||||
|
const codeVNode = preVNode.children?.at(0) as VNode
|
||||||
|
|
||||||
|
if (codeVNode) {
|
||||||
|
crawlSpan(codeVNode.children as VNodeArrayChildren, (vnode) => {
|
||||||
|
if (typeof vnode.children === 'string') {
|
||||||
|
vnode.children = vnode.children.replaceAll('@/components', codeConfig.value.componentsPath)
|
||||||
|
vnode.children = vnode.children.replaceAll('@/libs', codeConfig.value.utilsPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return clonedVNode
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return slots.default?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import Spinner from './Spinner.vue'
|
import Spinner from './Spinner.vue'
|
||||||
import { useConfigStore } from '@/stores/config'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string
|
name: string
|
||||||
|
typeName?: 'example' | 'block'
|
||||||
}>()
|
}>()
|
||||||
const { style } = useConfigStore()
|
const { style } = useConfigStore()
|
||||||
|
|
||||||
const Component = defineAsyncComponent({
|
const Component = defineAsyncComponent({
|
||||||
loadingComponent: Spinner,
|
loadingComponent: Spinner,
|
||||||
loader: () => import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue`),
|
loader: () => import(`../../../src/lib/registry/${style.value}/${props.typeName}/${props.name}.vue`),
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,49 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import StyleSwitcher from './StyleSwitcher.vue'
|
|
||||||
import ComponentLoader from './ComponentLoader.vue'
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||||
import { useConfigStore } from '@/stores/config'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { useClipboard } from '@vueuse/core'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import { highlight } from '../config/shiki'
|
||||||
|
import CodeSandbox from './CodeSandbox.vue'
|
||||||
|
import ComponentLoader from './ComponentLoader.vue'
|
||||||
|
import Stackblitz from './Stackblitz.vue'
|
||||||
|
import StyleSwitcher from './StyleSwitcher.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
})
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
name: string
|
name: string
|
||||||
align?: 'center' | 'start' | 'end'
|
align?: 'center' | 'start' | 'end'
|
||||||
sfcTsCode?: string
|
|
||||||
sfcTsHtml?: string
|
|
||||||
}>(), { align: 'center' })
|
}>(), { align: 'center' })
|
||||||
|
|
||||||
const { style } = useConfigStore()
|
const { style, codeConfig } = useConfigStore()
|
||||||
|
|
||||||
|
const rawString = ref('')
|
||||||
|
const codeHtml = ref('')
|
||||||
|
const transformedRawString = computed(() => transformImportPath(rawString.value))
|
||||||
|
|
||||||
|
function transformImportPath(code: string) {
|
||||||
|
const s = new MagicString(code)
|
||||||
|
s.replaceAll(`@/lib/registry/${style.value}`, codeConfig.value.componentsPath)
|
||||||
|
s.replaceAll(`@/lib/utils`, codeConfig.value.utilsPath)
|
||||||
|
return s.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([style, codeConfig], async () => {
|
||||||
|
try {
|
||||||
|
rawString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => res.default.trim())
|
||||||
|
codeHtml.value = highlight(transformedRawString.value, 'vue')
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}, { immediate: true, deep: true })
|
||||||
|
|
||||||
|
const { copy, copied } = useClipboard()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -39,19 +70,28 @@ const { style } = useConfigStore()
|
||||||
<TabsContent value="preview" class="relative rounded-md border">
|
<TabsContent value="preview" class="relative rounded-md border">
|
||||||
<div class="flex items-center justify-between p-4">
|
<div class="flex items-center justify-between p-4">
|
||||||
<StyleSwitcher />
|
<StyleSwitcher />
|
||||||
|
|
||||||
|
<div class="flex items-center gap-x-1">
|
||||||
|
<Stackblitz :key="style" :style="style" :name="name" :code="rawString" />
|
||||||
|
<CodeSandbox :key="style" :style="style" :name="name" :code="rawString" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="cn('preview flex min-h-[350px] w-full justify-center p-6 lg:p-10', {
|
:class="cn('preview flex min-h-[350px] w-full justify-center p-10 items-center', {
|
||||||
'items-center': align === 'center',
|
'items-center': align === 'center',
|
||||||
'items-start': align === 'start',
|
'items-start': align === 'start',
|
||||||
'items-end': align === 'end',
|
'items-end': align === 'end',
|
||||||
})"
|
})"
|
||||||
>
|
>
|
||||||
<ComponentLoader :key="style" :name="name" />
|
<ComponentLoader v-bind="$attrs" :key="style" :name="name" :type-name="'example'" />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="code">
|
<TabsContent value="code" class="vp-doc">
|
||||||
<div v-if="sfcTsHtml" class="language-vue" style="flex: 1;" v-html="decodeURIComponent(sfcTsHtml)" />
|
<div v-if="codeHtml" class="language-vue" style="flex: 1;">
|
||||||
|
<button title="Copy Code" class="copy" :class="{ copied }" @click="copy(transformedRawString)" />
|
||||||
|
|
||||||
|
<div v-html="codeHtml" />
|
||||||
|
</div>
|
||||||
<slot v-else />
|
<slot v-else />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
import { useClipboard } from '@vueuse/core'
|
|
||||||
import { useConfigStore } from '@/stores/config'
|
|
||||||
import { themes } from '@/lib/registry'
|
import { themes } from '@/lib/registry'
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { useClipboard } from '@vueuse/core'
|
||||||
import CheckIcon from '~icons/radix-icons/check'
|
import CheckIcon from '~icons/radix-icons/check'
|
||||||
import CopyIcon from '~icons/radix-icons/copy'
|
import CopyIcon from '~icons/radix-icons/copy'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
const { theme, config } = useConfigStore()
|
const { theme, config } = useConfigStore()
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ const { copy, copied } = useClipboard()
|
||||||
|
|
||||||
const codeRef = ref<HTMLElement>()
|
const codeRef = ref<HTMLElement>()
|
||||||
async function copyCode() {
|
async function copyCode() {
|
||||||
await copy(codeRef.value?.innerText ?? '')
|
await copy(codeRef.value?.textContent?.replace(/\u00A0/g, ' ') ?? '')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -23,32 +23,32 @@ async function copyCode() {
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<pre class="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 !py-0 dark:bg-zinc-900">
|
<pre class="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 !py-0 dark:bg-zinc-900">
|
||||||
<code ref="codeRef" class="relative block rounded font-mono text-sm">
|
<code ref="codeRef" class="relative block rounded font-mono text-sm">
|
||||||
<span class="line">@layer base {</span>
|
<span class="line text-white">@layer base {</span>
|
||||||
<span class="line">:root {</span>
|
<span class="line text-white">:root {</span>
|
||||||
<span class="line"> --background: {{ activeTheme?.cssVars.light.background }};</span>
|
<span class="line text-white"> --background: {{ activeTheme?.cssVars.light.background }};</span>
|
||||||
<span class="line"> --foreground: {{ activeTheme?.cssVars.light.foreground }};</span>
|
<span class="line text-white"> --foreground: {{ activeTheme?.cssVars.light.foreground }};</span>
|
||||||
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
||||||
<span class="line">--{{ prefix }}: {{ activeTheme?.cssVars.light[prefix] }};</span>
|
<span class="line text-white">--{{ prefix }}: {{ activeTheme?.cssVars.light[prefix] }};</span>
|
||||||
<span class="line">--{{ prefix }}-foreground: {{ activeTheme?.cssVars.light[ `${prefix}-foreground`] }};</span>
|
<span class="line text-white">--{{ prefix }}-foreground: {{ activeTheme?.cssVars.light[ `${prefix}-foreground`] }};</span>
|
||||||
</template>
|
</template>
|
||||||
<span class="line"> --border:{{ activeTheme?.cssVars.light.border }};</span>
|
<span class="line text-white"> --border:{{ activeTheme?.cssVars.light.border }};</span>
|
||||||
<span class="line"> --input:{{ activeTheme?.cssVars.light.input }};</span>
|
<span class="line text-white"> --input:{{ activeTheme?.cssVars.light.input }};</span>
|
||||||
<span class="line"> --ring:{{ activeTheme?.cssVars.light.ring }};</span>
|
<span class="line text-white"> --ring:{{ activeTheme?.cssVars.light.ring }};</span>
|
||||||
<span class="line"> --radius: {{ config.radius }}rem;</span>
|
<span class="line text-white"> --radius: {{ config.radius }}rem;</span>
|
||||||
<span class="line">}</span>
|
<span class="line text-white">}</span>
|
||||||
<span class="line"> </span>
|
<span class="line text-white"> </span>
|
||||||
<span class="line">.dark {</span>
|
<span class="line text-white">.dark {</span>
|
||||||
<span class="line"> --background:{{ activeTheme?.cssVars.dark.background }};</span>
|
<span class="line text-white"> --background:{{ activeTheme?.cssVars.dark.background }};</span>
|
||||||
<span class="line"> --foreground:{{ activeTheme?.cssVars.dark.foreground }};</span>
|
<span class="line text-white"> --foreground:{{ activeTheme?.cssVars.dark.foreground }};</span>
|
||||||
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
||||||
<span class="line">--{{ prefix }}:{{ activeTheme?.cssVars.dark[ prefix] }};</span>
|
<span class="line text-white">--{{ prefix }}:{{ activeTheme?.cssVars.dark[ prefix] }};</span>
|
||||||
<span class="line">--{{ prefix }}-foreground:{{ activeTheme?.cssVars.dark[ `${prefix}-foreground`] }};</span>
|
<span class="line text-white">--{{ prefix }}-foreground:{{ activeTheme?.cssVars.dark[ `${prefix}-foreground`] }};</span>
|
||||||
</template>
|
</template>
|
||||||
<span class="line"> --border:{{ activeTheme?.cssVars.dark.border }};</span>
|
<span class="line text-white"> --border:{{ activeTheme?.cssVars.dark.border }};</span>
|
||||||
<span class="line"> --input:{{ activeTheme?.cssVars.dark.input }};</span>
|
<span class="line text-white"> --input:{{ activeTheme?.cssVars.dark.input }};</span>
|
||||||
<span class="line"> --ring:{{ activeTheme?.cssVars.dark.ring }};</span>
|
<span class="line text-white"> --ring:{{ activeTheme?.cssVars.dark.ring }};</span>
|
||||||
<span class="line">}</span>
|
<span class="line text-white">}</span>
|
||||||
<span class="line">}</span>
|
<span class="line text-white">}</span>
|
||||||
</code>
|
</code>
|
||||||
</pre>
|
</pre>
|
||||||
<Button size="sm" class="absolute right-4 top-4 bg-muted text-muted-foreground hover:bg-muted hover:text-muted-foreground" @click="copyCode">
|
<Button size="sm" class="absolute right-4 top-4 bg-muted text-muted-foreground hover:bg-muted hover:text-muted-foreground" @click="copyCode">
|
||||||
|
|
|
||||||
53
apps/www/.vitepress/theme/components/DocsBreadcrumb.vue
Normal file
53
apps/www/.vitepress/theme/components/DocsBreadcrumb.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbSeparator,
|
||||||
|
} from '@/lib/registry/new-york/ui/breadcrumb'
|
||||||
|
import { useRoute } from 'vitepress'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
interface Item {
|
||||||
|
title: string
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateBreadcrumb(url: string): Item[] {
|
||||||
|
const breadcrumbItems: Item[] = []
|
||||||
|
const segments = url.split('/').filter(segment => segment !== '') // Remove empty segments
|
||||||
|
|
||||||
|
// Construct breadcrumb for each segment
|
||||||
|
let href = ''
|
||||||
|
for (let i = 0; i < segments.length; i++) {
|
||||||
|
const segment = segments[i].replace('.html', '')
|
||||||
|
href += `/${segment}`
|
||||||
|
breadcrumbItems.push({ title: segment, href })
|
||||||
|
}
|
||||||
|
return breadcrumbItems
|
||||||
|
}
|
||||||
|
|
||||||
|
const breadcrumbs = computed(() => generateBreadcrumb(route.path))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Breadcrumb>
|
||||||
|
<BreadcrumbList>
|
||||||
|
<template v-for="(breadcrumb, index) in breadcrumbs" :key="breadcrumb.title">
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbLink
|
||||||
|
class="capitalize"
|
||||||
|
:href="index === 0 ? undefined : breadcrumb.href"
|
||||||
|
:class="{ 'text-foreground': index === breadcrumbs.length - 1 }"
|
||||||
|
>
|
||||||
|
{{ breadcrumb.title }}
|
||||||
|
</BreadcrumbLink>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
<BreadcrumbSeparator v-if="index !== breadcrumbs.length - 1" />
|
||||||
|
</template>
|
||||||
|
</BreadcrumbList>
|
||||||
|
</Breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import Pencil2Icon from '~icons/radix-icons/pencil-2'
|
||||||
import { useData } from 'vitepress'
|
import { useData } from 'vitepress'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import Pencil2Icon from '~icons/radix-icons/pencil-2'
|
|
||||||
import { Button } from '@/lib/registry/default/ui/button'
|
|
||||||
|
|
||||||
const { theme, page } = useData()
|
const { theme, page } = useData()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,18 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ScrollArea, ScrollBar } from '@/lib/registry/default/ui/scroll-area'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
||||||
import { useRoute } from 'vitepress'
|
import { useRoute } from 'vitepress'
|
||||||
import { computed, toRefs } from 'vue'
|
import { computed, toRefs } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import { ScrollArea, ScrollBar } from '@/lib/registry/default/ui/scroll-area'
|
|
||||||
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
|
||||||
|
|
||||||
const { path } = toRefs(useRoute())
|
const { path } = toRefs(useRoute())
|
||||||
|
|
||||||
const examples = [
|
const examples = [
|
||||||
|
{
|
||||||
|
name: 'Mail',
|
||||||
|
href: '/examples/mail',
|
||||||
|
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/mail',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
href: '/examples/dashboard',
|
href: '/examples/dashboard',
|
||||||
|
|
@ -30,7 +35,7 @@ const examples = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Forms',
|
name: 'Forms',
|
||||||
href: '/examples/forms/forms',
|
href: '/examples/forms',
|
||||||
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/forms',
|
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/forms',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +63,7 @@ const currentExample = computed(() => examples.find(ex => path.value.startsWith(
|
||||||
:href="example.href"
|
:href="example.href"
|
||||||
:class="cn(
|
:class="cn(
|
||||||
'flex items-center px-4',
|
'flex items-center px-4',
|
||||||
path?.startsWith(example.href) || (path === '/' && example.name === 'Dashboard')
|
path?.startsWith(example.href) || (path === '/' && example.name === 'Mail')
|
||||||
? 'font-bold text-primary'
|
? 'font-bold text-primary'
|
||||||
: 'font-medium text-muted-foreground',
|
: 'font-medium text-muted-foreground',
|
||||||
)"
|
)"
|
||||||
|
|
|
||||||
54
apps/www/.vitepress/theme/components/InlineThemePicker.vue
Normal file
54
apps/www/.vitepress/theme/components/InlineThemePicker.vue
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Color } from '../types/colors'
|
||||||
|
import { colors } from '@/lib/registry'
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/registry/new-york/ui/tooltip'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import RadixIconsCheck from '~icons/radix-icons/check'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
allColors: Color[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { theme, setTheme } = useConfigStore()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<TooltipProvider
|
||||||
|
v-for="(color, index) in allColors.slice(0, 5)"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger as-child>
|
||||||
|
<button
|
||||||
|
:key="index"
|
||||||
|
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-border text-xs"
|
||||||
|
:class="
|
||||||
|
color === theme
|
||||||
|
? 'border-primary'
|
||||||
|
: 'border-transparent'
|
||||||
|
"
|
||||||
|
@click="setTheme(color)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex h-6 w-6 items-center justify-center rounded-full"
|
||||||
|
:style="{ backgroundColor: colors[color][6].rgb }"
|
||||||
|
>
|
||||||
|
<RadixIconsCheck
|
||||||
|
v-if="color === theme"
|
||||||
|
class="h-4 w-4 text-white"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent
|
||||||
|
align="center"
|
||||||
|
:side-offset="1"
|
||||||
|
class="capitalize bg-zinc-900 text-zinc-50"
|
||||||
|
>
|
||||||
|
{{ allColors[index] }}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -18,9 +18,9 @@ const kbdClass = computed(() => {
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
size: {
|
size: {
|
||||||
xs: 'min-h-[16px] text-[10px] h-4 px-1',
|
xs: 'min-h-4 text-[10px] h-4 px-1',
|
||||||
sm: 'min-h-[20px] text-[11px] h-5 px-1',
|
sm: 'min-h-5 text-[11px] h-5 px-1',
|
||||||
md: 'min-h-[24px] text-[12px] h-6 px-1.5',
|
md: 'min-h-6 text-[12px] h-6 px-1.5',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,28 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import PageHeader from '../components/PageHeader.vue'
|
import MailExample from '@/examples/mail/Example.vue'
|
||||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
|
||||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
|
||||||
import ExamplesNav from '../components/ExamplesNav.vue'
|
|
||||||
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
|
||||||
import GitHubIcon from '~icons/radix-icons/github-logo'
|
|
||||||
|
|
||||||
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
||||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import GitHubIcon from '~icons/radix-icons/github-logo'
|
||||||
|
import Announcement from '../components/Announcement.vue'
|
||||||
|
import ExamplesNav from '../components/ExamplesNav.vue'
|
||||||
|
import PageAction from '../components/PageAction.vue'
|
||||||
|
|
||||||
import DashboardExample from '@/examples/dashboard/Example.vue'
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
|
|
||||||
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageHeader class="page-header pb-8">
|
<PageHeader class="page-header pb-8">
|
||||||
<a
|
<Announcement />
|
||||||
href="/docs/changelog"
|
|
||||||
class="inline-flex items-center rounded-lg bg-muted px-3 py-1 text-sm font-medium"
|
|
||||||
>
|
|
||||||
🚧 <Separator class="mx-2 h-4" orientation="vertical" />
|
|
||||||
<span class="sm:hidden">WIP</span>
|
|
||||||
<span class="hidden sm:inline">WIP
|
|
||||||
</span>
|
|
||||||
<!-- <ArrowRightIcon class="ml-1 h-4 w-4" /> -->
|
|
||||||
</a>
|
|
||||||
<PageHeaderHeading>Build your component library.</PageHeaderHeading>
|
<PageHeaderHeading>Build your component library.</PageHeaderHeading>
|
||||||
<PageHeaderDescription>
|
<PageHeaderDescription>
|
||||||
Beautifully designed components that you can copy and paste into your
|
Beautifully designed components that you can copy and paste into your
|
||||||
apps. Accessible. Customizable. Open Source.
|
apps. Accessible. Customizable. Open Source.
|
||||||
</PageHeaderDescription>
|
</PageHeaderDescription>
|
||||||
|
|
||||||
<section class="flex w-full items-center space-x-4 pb-8 pt-4 md:pb-10">
|
<PageAction>
|
||||||
<a
|
<a
|
||||||
href="/docs/introduction"
|
href="/docs/introduction"
|
||||||
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
||||||
|
|
@ -49,22 +40,22 @@ import DashboardExample from '@/examples/dashboard/Example.vue'
|
||||||
<GitHubIcon class="mr-2 h-4 w-4" />
|
<GitHubIcon class="mr-2 h-4 w-4" />
|
||||||
GitHub
|
GitHub
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</PageAction>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<ExamplesNav />
|
<ExamplesNav />
|
||||||
<section class="space-y-8 overflow-hidden rounded-lg border-2 border-primary dark:border-muted md:hidden">
|
<section class="space-y-8 overflow-hidden rounded-lg border-2 border-primary dark:border-muted md:hidden">
|
||||||
<VPImage
|
<VPImage
|
||||||
alt="Dashboard"
|
alt="Mail"
|
||||||
width="1280"
|
width="1280"
|
||||||
height="866" class="block" :image="{
|
height="866" class="block" :image="{
|
||||||
dark: '/examples/dashboard-dark.png',
|
dark: '/examples/mail-dark.png',
|
||||||
light: '/examples/dashboard-light.png',
|
light: '/examples/mail-light.png',
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section class="hidden md:block">
|
<section class="hidden md:block">
|
||||||
<div class="overflow-hidden rounded-[0.5rem] border bg-background shadow">
|
<div class="overflow-hidden rounded-[0.5rem] border bg-background shadow">
|
||||||
<DashboardExample />
|
<MailExample />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a :class="cn('flex w-full flex-col items-center rounded-xl border bg-card p-6 text-card-foreground shadow transition-colors hover:bg-muted/50 sm:p-10', $attrs.class ?? '')">
|
<a :class="cn('flex w-full flex-col items-center rounded-lg border bg-card p-6 text-card-foreground shadow transition-colors hover:bg-muted/50 sm:p-10', $attrs.class ?? '')">
|
||||||
<slot />
|
<slot />
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a href="/" class="mr-6 flex items-center space-x-2">
|
<a href="/" class="mr-4 md:mr-2 lg:mr-6 flex items-center lg:space-x1 xl:space-x-2">
|
||||||
<svg class="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g clip-path="url(#clip0_102_1338)">
|
<g clip-path="url(#clip0_102_1338)">
|
||||||
<path d="M208 128L128 208" stroke="#41B883" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
|
<path d="M208 128L128 208" stroke="#41B883" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<span class="font-bold ">
|
<span class="font-bold">
|
||||||
shadcn-vue
|
shadcn-vue
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||||
|
import { Sheet, SheetContent, SheetTrigger } from '@/lib/registry/default/ui/sheet'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { docsConfig } from '../config/docs'
|
import { docsConfig } from '../config/docs'
|
||||||
import Logo from './Logo.vue'
|
import Logo from './Logo.vue'
|
||||||
import { Sheet, SheetContent, SheetTrigger } from '@/lib/registry/default/ui/sheet'
|
|
||||||
import { Button } from '@/lib/registry/default/ui/button'
|
|
||||||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
|
||||||
import ViewVerticalIcon from '~icons/radix-icons/view-vertical'
|
|
||||||
|
|
||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -17,7 +16,35 @@ const open = ref(false)
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="mr-2 px-2 text-base flex-shrink-0 hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
|
class="mr-2 px-2 text-base flex-shrink-0 hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
|
||||||
>
|
>
|
||||||
<ViewVerticalIcon class="h-5 w-5" />
|
<svg
|
||||||
|
strokeWidth="1.5"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 5H11"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3 12H16"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3 19H21"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
<span class="sr-only">Toggle Menu</span>
|
<span class="sr-only">Toggle Menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
|
|
@ -36,17 +63,26 @@ const open = ref(false)
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-2">
|
<div class="flex flex-col space-y-2">
|
||||||
<div v-for="(items, index) in docsConfig.sidebarNav" :key="index" class="flex flex-col space-y-3 pt-6">
|
<div v-for="(items, index) in docsConfig.sidebarNav" :key="index" class="flex flex-col space-y-3 pt-6">
|
||||||
<h4 class="font-medium">
|
<div class="flex items-center">
|
||||||
{{ items.title }}
|
<h4 class="font-medium">
|
||||||
</h4>
|
{{ items.title }}
|
||||||
|
</h4>
|
||||||
|
<span v-if="items.label" class="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||||
|
{{ items.label }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
v-for="item in items.items" :key="item.href"
|
v-for="item in items.items" :key="item.href"
|
||||||
:href="item.href"
|
:href="item.href"
|
||||||
class="text-muted-foreground"
|
class="text-muted-foreground inline-flex items-center"
|
||||||
@click="open = false"
|
@click="open = false"
|
||||||
>
|
>
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
|
|
||||||
|
<span v-if="item.label" class="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||||
|
{{ item.label }}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
14
apps/www/.vitepress/theme/components/PageAction.vue
Normal file
14
apps/www/.vitepress/theme/components/PageAction.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section
|
||||||
|
:class="cn(
|
||||||
|
'flex w-full items-center justify-center space-x-4 py-4 md:pb-10',
|
||||||
|
$attrs.class ?? '',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
@ -7,7 +7,7 @@ import { cn } from '@/lib/utils'
|
||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
:class="cn(
|
:class="cn(
|
||||||
'flex max-w-[980px] flex-col items-start gap-2 px-4 pt-8 md:pt-12',
|
'mx-auto flex max-w-[980px] flex-col items-center gap-2 py-8 md:py-12 md:pb-8 lg:py-24 lg:pb-20',
|
||||||
$attrs.class ?? '',
|
$attrs.class ?? '',
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import WrapBalancer from 'vue-wrap-balancer'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import WrapBalancer from 'vue-wrap-balancer'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<WrapBalancer :class="cn('max-w-[750px] text-lg text-muted-foreground sm:text-xl', $attrs.class ?? '')">
|
<WrapBalancer :class="cn('max-w-[750px] text-center text-lg font-light text-foreground', $attrs.class ?? '')" :prefer-native="false">
|
||||||
<slot />
|
<slot />
|
||||||
</WrapBalancer>
|
</WrapBalancer>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { cn } from '@/lib/utils'
|
||||||
<template>
|
<template>
|
||||||
<h1
|
<h1
|
||||||
:class="cn(
|
:class="cn(
|
||||||
'text-3xl font-bold leading-tight tracking-tighter md:text-5xl lg:leading-[1.1]',
|
'text-center text-3xl font-bold leading-tight tracking-tighter md:text-5xl lg:leading-[1.1]',
|
||||||
$attrs.class ?? '',
|
$attrs.class ?? '',
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
35
apps/www/.vitepress/theme/components/Stackblitz.vue
Normal file
35
apps/www/.vitepress/theme/components/Stackblitz.vue
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Style } from '@/lib/registry/styles'
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { Icon } from '@iconify/vue'
|
||||||
|
import { ref, toRefs, watch } from 'vue'
|
||||||
|
import { makeStackblitzParams } from '../utils/codeeditor'
|
||||||
|
import Tooltip from './Tooltip.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
name: string
|
||||||
|
code: string
|
||||||
|
style: Style
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { code } = toRefs(props)
|
||||||
|
const sources = ref<Record<string, string>>({})
|
||||||
|
|
||||||
|
watch(code, () => {
|
||||||
|
sources.value['App.vue'] = code.value
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
makeStackblitzParams(props.name, props.style, sources.value)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Tooltip :content="`Open ${name} in Stackblitz`">
|
||||||
|
<Button :variant="'ghost'" :size="'icon'" @click="handleClick">
|
||||||
|
<Icon icon="simple-icons:stackblitz" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type SelectTriggerProps } from 'radix-vue'
|
import type { SelectTriggerProps } from 'radix-vue'
|
||||||
import { useConfigStore } from '@/stores/config'
|
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
|
@ -10,7 +7,10 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/lib/registry/new-york/ui/select'
|
} from '@/lib/registry/new-york/ui/select'
|
||||||
|
|
||||||
import { styles } from '@/lib/registry/styles'
|
import { styles } from '@/lib/registry/styles'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
|
||||||
const props = defineProps<SelectTriggerProps & { class?: string }>()
|
const props = defineProps<SelectTriggerProps & { class?: string }>()
|
||||||
const { config } = useConfigStore()
|
const { config } = useConfigStore()
|
||||||
|
|
|
||||||
15
apps/www/.vitepress/theme/components/TabMarkdown.vue
Normal file
15
apps/www/.vitepress/theme/components/TabMarkdown.vue
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TabsContent } from '@/lib/registry/default/ui/tabs'
|
||||||
|
|
||||||
|
withDefaults(defineProps<{
|
||||||
|
title?: string
|
||||||
|
}>(), {
|
||||||
|
title: '',
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TabsContent :value="title" class="relative space-y-10">
|
||||||
|
<slot />
|
||||||
|
</TabsContent>
|
||||||
|
</template>
|
||||||
|
|
@ -3,10 +3,14 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
name: string
|
name: string
|
||||||
|
names?: string[]
|
||||||
align?: 'center' | 'start' | 'end'
|
align?: 'center' | 'start' | 'end'
|
||||||
sfcTsCode?: string
|
sfcTsCode?: string
|
||||||
sfcTsHtml?: string
|
sfcTsHtml?: string
|
||||||
}>(), { align: 'center' })
|
}>(), {
|
||||||
|
align: 'center',
|
||||||
|
names: () => ['CLI', 'Manual'],
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -15,24 +19,17 @@ const props = withDefaults(defineProps<{
|
||||||
<div class="flex items-center justify-between pb-3">
|
<div class="flex items-center justify-between pb-3">
|
||||||
<TabsList class="w-full justify-start rounded-none border-b bg-transparent p-0">
|
<TabsList class="w-full justify-start rounded-none border-b bg-transparent p-0">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="CLI"
|
v-for="(tab, index) in props.names"
|
||||||
|
:key="index"
|
||||||
|
:value="tab"
|
||||||
class="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
|
class="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
|
||||||
>
|
>
|
||||||
CLI
|
{{ tab }}
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger
|
|
||||||
value="Manual"
|
|
||||||
class="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
|
|
||||||
>
|
|
||||||
Manual
|
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</div>
|
</div>
|
||||||
<TabsContent value="CLI" class="relative space-y-10">
|
<TabsContent v-for="(tab, index) in props.names" :key="index" :value="tab" class="relative space-y-10">
|
||||||
<slot name="CLI" />
|
<slot :name="tab" />
|
||||||
</TabsContent>
|
|
||||||
<TabsContent value="Manual">
|
|
||||||
<slot name="Manual" />
|
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { TableOfContents, TableOfContentsItem } from '../types/docs'
|
||||||
|
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/lib/registry/default/ui/collapsible'
|
||||||
|
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||||
import { onContentUpdated } from 'vitepress'
|
import { onContentUpdated } from 'vitepress'
|
||||||
import { shallowRef } from 'vue'
|
import { shallowRef } from 'vue'
|
||||||
import type { TableOfContents, TableOfContentsItem } from '../types/docs'
|
import CarbonAds from '../components/CarbonAds.vue'
|
||||||
import TableOfContentTree from './TableOfContentTree.vue'
|
import TableOfContentTree from './TableOfContentTree.vue'
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/lib/registry/default/ui/collapsible'
|
|
||||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
defineProps<{
|
||||||
|
showCarbonAds?: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
const headers = shallowRef<TableOfContents>()
|
const headers = shallowRef<TableOfContents>()
|
||||||
|
|
||||||
|
|
@ -22,8 +28,8 @@ function getHeadingsWithHierarchy(divId: string) {
|
||||||
headings.forEach((heading: HTMLHeadingElement) => {
|
headings.forEach((heading: HTMLHeadingElement) => {
|
||||||
const level = Number.parseInt(heading.tagName.charAt(1))
|
const level = Number.parseInt(heading.tagName.charAt(1))
|
||||||
if (!heading.id) {
|
if (!heading.id) {
|
||||||
const newId = heading.innerText
|
const newId = heading.textContent
|
||||||
.replaceAll(/[^a-zA-Z0-9 ]/g, '')
|
?.replaceAll(/[^a-z0-9 ]/gi, '')
|
||||||
.replaceAll(' ', '-')
|
.replaceAll(' ', '-')
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
heading.id = `${newId}`
|
heading.id = `${newId}`
|
||||||
|
|
@ -55,11 +61,16 @@ onContentUpdated(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="space-y-2 hidden xl:block">
|
<div class="hidden xl:block">
|
||||||
<p class="font-medium">
|
<ScrollArea orientation="vertical" class="h-[calc(100vh-6.5rem)] z-30 md:block overflow-y-auto" type="hover">
|
||||||
On This Page
|
<div class="space-y-2">
|
||||||
</p>
|
<p class="font-medium">
|
||||||
<TableOfContentTree :tree="headers" :level="1" />
|
On This Page
|
||||||
|
</p>
|
||||||
|
<TableOfContentTree :tree="headers" :level="1" />
|
||||||
|
<CarbonAds v-if="showCarbonAds" />
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block xl:hidden mb-6">
|
<div class="block xl:hidden mb-6">
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
|
||||||
import { useRoute } from 'vitepress'
|
|
||||||
import type { TableOfContentsItem } from '../types/docs'
|
import type { TableOfContentsItem } from '../types/docs'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { useRoute } from 'vitepress'
|
||||||
|
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
level: number
|
level: number
|
||||||
|
|
|
||||||
22
apps/www/.vitepress/theme/components/TabsMarkdown.vue
Normal file
22
apps/www/.vitepress/theme/components/TabsMarkdown.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Tabs, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||||
|
import { computed, useSlots } from 'vue'
|
||||||
|
|
||||||
|
const slots = useSlots()
|
||||||
|
|
||||||
|
const tabs = computed(() => slots.default?.()?.map(i => i?.props?.title as string) ?? [])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Tabs :default-value="tabs[0]" class="relative mr-auto w-full">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<TabsList class="w-full justify-start rounded-none border-b bg-transparent p-0">
|
||||||
|
<TabsTrigger v-for="tab in tabs" :key="tab" :value="tab" class="relative h-9 rounded-none border-b-2 border-b-transparent bg-transparent px-4 pb-3 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none">
|
||||||
|
{{ tab }}
|
||||||
|
</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</Tabs>
|
||||||
|
</template>
|
||||||
106
apps/www/.vitepress/theme/components/ThemeCustomizer.vue
Normal file
106
apps/www/.vitepress/theme/components/ThemeCustomizer.vue
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Color } from '../types/colors'
|
||||||
|
import { colors } from '@/lib/registry'
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||||
|
import { RADII, useConfigStore } from '@/stores/config'
|
||||||
|
import RadixIconsCheck from '~icons/radix-icons/check'
|
||||||
|
import RadixIconsMoon from '~icons/radix-icons/moon'
|
||||||
|
import RadixIconsSun from '~icons/radix-icons/sun'
|
||||||
|
import { useData } from 'vitepress'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
allColors: Color[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { theme, radius, setRadius, setTheme } = useConfigStore()
|
||||||
|
const { isDark } = useData()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="grid space-y-1">
|
||||||
|
<h1 class="text-md text-foreground font-semibold">
|
||||||
|
Customize
|
||||||
|
</h1>
|
||||||
|
<p class="text-xs text-muted-foreground">
|
||||||
|
Pick a style and color for your components.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1.5 pt-6">
|
||||||
|
<Label for="color" class="text-xs"> Color </Label>
|
||||||
|
<div class="grid grid-cols-3 gap-2 py-1.5">
|
||||||
|
<Button
|
||||||
|
v-for="(color, index) in allColors"
|
||||||
|
:key="index"
|
||||||
|
variant="outline"
|
||||||
|
class="h-8 justify-start px-3"
|
||||||
|
:class="
|
||||||
|
color === theme
|
||||||
|
? 'border-foreground border-2'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
@click="setTheme(color)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="h-5 w-5 rounded-full flex items-center justify-center shrink-0"
|
||||||
|
:style="{ backgroundColor: colors[color][7].rgb }"
|
||||||
|
>
|
||||||
|
<RadixIconsCheck
|
||||||
|
v-if="color === theme"
|
||||||
|
class="h-3 w-3 text-white"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span class="ml-2 text-xs capitalize">
|
||||||
|
{{ color }}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1.5 pt-6">
|
||||||
|
<Label for="radius" class="text-xs"> Radius </Label>
|
||||||
|
<div class="grid grid-cols-5 gap-2 py-1.5">
|
||||||
|
<Button
|
||||||
|
v-for="(r, index) in RADII"
|
||||||
|
:key="index"
|
||||||
|
variant="outline"
|
||||||
|
class="h-8 justify-center px-3"
|
||||||
|
:class="
|
||||||
|
r === radius
|
||||||
|
? 'border-foreground border-2'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
@click="setRadius(r)"
|
||||||
|
>
|
||||||
|
<span class="text-xs">
|
||||||
|
{{ r }}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1.5 pt-6">
|
||||||
|
<Label for="theme" class="text-xs"> Theme </Label>
|
||||||
|
|
||||||
|
<div class="flex space-x-2 py-1.5">
|
||||||
|
<Button
|
||||||
|
class="h-8"
|
||||||
|
variant="outline"
|
||||||
|
:class="{ 'border-2 border-foreground': !isDark }"
|
||||||
|
@click="isDark = false"
|
||||||
|
>
|
||||||
|
<RadixIconsSun class="w-4 h-4 mr-2" />
|
||||||
|
<span class="text-xs">Light</span>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
class="h-8"
|
||||||
|
variant="outline"
|
||||||
|
:class="{ 'border-2 border-foreground': isDark }"
|
||||||
|
@click="isDark = true"
|
||||||
|
>
|
||||||
|
<RadixIconsMoon class="w-4 h-4 mr-2" />
|
||||||
|
<span class="text-xs">Dark</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
47
apps/www/.vitepress/theme/components/ThemePopover.vue
Normal file
47
apps/www/.vitepress/theme/components/ThemePopover.vue
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { Paintbrush } from 'lucide-vue-next'
|
||||||
|
import { onMounted, watch } from 'vue'
|
||||||
|
import ThemeCustomizer from './ThemeCustomizer.vue'
|
||||||
|
import { allColors } from './theming/utils/data'
|
||||||
|
|
||||||
|
const { theme, radius } = useConfigStore()
|
||||||
|
|
||||||
|
// Whenever the component is mounted, update the document class list
|
||||||
|
onMounted(() => {
|
||||||
|
document.documentElement.style.setProperty('--radius', `${radius.value}rem`)
|
||||||
|
document.documentElement.classList.add(`theme-${theme.value}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Whenever the theme value changes, update the document class list
|
||||||
|
watch(theme, (theme) => {
|
||||||
|
document.documentElement.classList.remove(
|
||||||
|
...allColors.map(color => `theme-${color}`),
|
||||||
|
)
|
||||||
|
document.documentElement.classList.add(`theme-${theme}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Whenever the radius value changes, update the document style
|
||||||
|
watch(radius, (radius) => {
|
||||||
|
document.documentElement.style.setProperty('--radius', `${radius}rem`)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
class="w-9 h-9"
|
||||||
|
:variant="'ghost'"
|
||||||
|
:size="'icon'"
|
||||||
|
>
|
||||||
|
<Paintbrush class="w-4 h-4" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent :side-offset="8" align="end" class="w-96">
|
||||||
|
<ThemeCustomizer :all-colors="allColors" />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
25
apps/www/.vitepress/theme/components/Tooltip.vue
Normal file
25
apps/www/.vitepress/theme/components/Tooltip.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/tooltip'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
content: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger as-child>
|
||||||
|
<slot />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
{{ content }}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</template>
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
export { default as ComponentPreview } from './ComponentPreview.vue'
|
export { default as APITable } from './APITable.vue'
|
||||||
export { default as TabPreview } from './TabPreview.vue'
|
export { default as BlockPreview } from './BlockPreview.vue'
|
||||||
export { default as Callout } from './Callout.vue'
|
export { default as Callout } from './Callout.vue'
|
||||||
|
export { default as CodeWrapper } from './CodeWrapper'
|
||||||
|
export { default as ComponentPreview } from './ComponentPreview.vue'
|
||||||
export { default as LinkedCard } from './LinkedCard.vue'
|
export { default as LinkedCard } from './LinkedCard.vue'
|
||||||
export { default as ManualInstall } from './ManualInstall.vue'
|
export { default as ManualInstall } from './ManualInstall.vue'
|
||||||
export { default as Steps } from './Steps.vue'
|
export { default as Steps } from './Steps.vue'
|
||||||
|
export { default as TabMarkdown } from './TabMarkdown.vue'
|
||||||
|
export { default as TabPreview } from './TabPreview.vue'
|
||||||
|
export { default as TabsMarkdown } from './TabsMarkdown.vue'
|
||||||
export { default as VPImage } from './VPImage.vue'
|
export { default as VPImage } from './VPImage.vue'
|
||||||
|
|
|
||||||
|
|
@ -1,79 +1,32 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import type { DateRange } from 'radix-vue'
|
||||||
import { ChevronDown, Minus, Plus, Send } from 'lucide-vue-next'
|
import CookieSettings from '@/examples/cards/components/CookieSettings.vue'
|
||||||
import { addDays, startOfToday } from 'date-fns'
|
import CreateAccount from '@/examples/cards/components/CreateAccount.vue'
|
||||||
|
|
||||||
|
import PaymentMethod from '@/examples/cards/components/PaymentMethod.vue'
|
||||||
|
|
||||||
|
import ReportAnIssue from '@/examples/cards/components/ReportAnIssue.vue'
|
||||||
|
import ShareDocument from '@/examples/cards/components/ShareDocument.vue'
|
||||||
|
import TeamMembers from '@/examples/cards/components/TeamMembers.vue'
|
||||||
|
import CardChat from '@/lib/registry/new-york/example/CardChat.vue'
|
||||||
|
import ActivityGoal from '@/lib/registry/new-york/example/Cards/ActivityGoal.vue'
|
||||||
|
import DataTable from '@/lib/registry/new-york/example/Cards/DataTable.vue'
|
||||||
|
|
||||||
|
import Metric from '@/lib/registry/new-york/example/Cards/Metric.vue'
|
||||||
|
import CardStats from '@/lib/registry/new-york/example/CardStats.vue'
|
||||||
|
import { Card } from '@/lib/registry/new-york/ui/card'
|
||||||
|
import { RangeCalendar } from '@/lib/registry/new-york/ui/range-calendar'
|
||||||
|
import { getLocalTimeZone, today } from '@internationalized/date'
|
||||||
|
|
||||||
|
import { type Ref, ref } from 'vue'
|
||||||
import ThemingLayout from './../../layout/ThemingLayout.vue'
|
import ThemingLayout from './../../layout/ThemingLayout.vue'
|
||||||
import {
|
|
||||||
months,
|
|
||||||
payments,
|
|
||||||
roles,
|
|
||||||
teamMembers,
|
|
||||||
years,
|
|
||||||
} from './utils/data'
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from '@/lib/registry/new-york/ui/card'
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
AvatarImage,
|
|
||||||
} from '@/lib/registry/new-york/ui/avatar'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import { Textarea } from '@/lib/registry/new-york/ui/textarea'
|
|
||||||
import { Calendar } from '@/lib/registry/new-york/ui/calendar'
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuGroup,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
|
||||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
|
||||||
import { Switch } from '@/lib/registry/new-york/ui/switch'
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectGroup,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from '@/lib/registry/new-york/ui/select'
|
|
||||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/tooltip'
|
|
||||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
|
||||||
import RadixIconsGithubLogo from '~icons/radix-icons/github-logo'
|
|
||||||
import RiGoogleLine from '~icons/ri/google-line'
|
|
||||||
|
|
||||||
const strictlyNecessarySwitch = ref<boolean>(true)
|
const now = today(getLocalTimeZone())
|
||||||
const functionalCookiesSwitch = ref<boolean>(false)
|
|
||||||
const performanceCookiesSwitch = ref<boolean>(false)
|
|
||||||
const selectedArea = ref('Billing')
|
|
||||||
const selectedSecurity = ref('Medium')
|
|
||||||
const selectedMonth = ref<string>(months[0])
|
|
||||||
const selectedYear = ref<string>(years[0])
|
|
||||||
const selectedPayment = ref(payments[0])
|
|
||||||
const goal = ref(350)
|
|
||||||
|
|
||||||
function switchPayment(payment: any) {
|
|
||||||
selectedPayment.value = payment
|
|
||||||
}
|
|
||||||
|
|
||||||
const range = ref({
|
const range = ref({
|
||||||
start: startOfToday(),
|
start: now,
|
||||||
end: addDays(startOfToday(), 8),
|
end: now.add({ days: 8 }),
|
||||||
})
|
}) as Ref<DateRange>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -82,599 +35,40 @@ const range = ref({
|
||||||
class="items-start justify-center gap-6 rounded-lg md:grids-col-2 grid md:gap-4 lg:grid-cols-10 xl:grid-cols-11 xl:gap-4"
|
class="items-start justify-center gap-6 rounded-lg md:grids-col-2 grid md:gap-4 lg:grid-cols-10 xl:grid-cols-11 xl:gap-4"
|
||||||
>
|
>
|
||||||
<div class="space-y-4 lg:col-span-4 xl:col-span-6 xl:space-y-4">
|
<div class="space-y-4 lg:col-span-4 xl:col-span-6 xl:space-y-4">
|
||||||
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-2">
|
<CardStats />
|
||||||
<Card>
|
|
||||||
<CardHeader class="pb-2">
|
|
||||||
<CardTitle class="text-lg">
|
|
||||||
Total Revenue
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="text-2xl font-bold">
|
|
||||||
$15,231.89
|
|
||||||
</div>
|
|
||||||
<p class="text-xs text-muted-foreground">
|
|
||||||
+20.1% from last month
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="h-24" />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader class="pb-2">
|
|
||||||
<CardTitle class="text-lg">
|
|
||||||
Subscriptions
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="text-2xl font-bold">
|
|
||||||
+2,350
|
|
||||||
</div>
|
|
||||||
<p class="text-xs text-muted-foreground">
|
|
||||||
+54.8% from last month
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="h-24" />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2">
|
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<Card>
|
<TeamMembers />
|
||||||
<CardHeader>
|
<CookieSettings />
|
||||||
<CardTitle> Team Members </CardTitle>
|
<PaymentMethod />
|
||||||
<CardDescription>
|
|
||||||
Invite your team members to collaborate.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div
|
|
||||||
v-for="teamMember in teamMembers"
|
|
||||||
:key="teamMember.name"
|
|
||||||
class="flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<div class="flex items-center space-x-3 my-4">
|
|
||||||
<Avatar size="sm">
|
|
||||||
<AvatarImage :src="teamMember.avatar" />
|
|
||||||
<AvatarFallback>
|
|
||||||
{{ teamMember.name.slice(0, 2) }}
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<p class="text-foreground text-sm font-semibold">
|
|
||||||
{{ teamMember.name }}
|
|
||||||
</p>
|
|
||||||
<p class="text-muted-foreground text-sm">
|
|
||||||
{{ teamMember.username }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger>
|
|
||||||
<Button variant="outline" class="h-9">
|
|
||||||
{{ teamMember.role }}
|
|
||||||
<ChevronDown class="w-3 h-3 ml-2" />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent class="w-[280px]" align="end">
|
|
||||||
<DropdownMenuGroup>
|
|
||||||
<DropdownMenuLabel>
|
|
||||||
Actions
|
|
||||||
</DropdownMenuLabel>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItem v-for="role in roles" :key="role.name">
|
|
||||||
<div class="grid space-y-0.5">
|
|
||||||
<span class="text-foreground font-semibold">
|
|
||||||
{{ role.name }}
|
|
||||||
</span>
|
|
||||||
<span class="text-muted-foreground text-sm">
|
|
||||||
{{ role.description }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuGroup>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle> Cookies Settings </CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Manage your cookies preferences.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="grid grid-rows-3 gap-y-5">
|
|
||||||
<div class="flex justify-between items-center space-x-2">
|
|
||||||
<Label for="strictly_necessary" class="flex flex-col">
|
|
||||||
Strictly Necessary
|
|
||||||
<span
|
|
||||||
class="text-muted-foreground mt-1 text-xs max-w-[18rem]"
|
|
||||||
>
|
|
||||||
These cookies are essential in order to use the website
|
|
||||||
and use its features.
|
|
||||||
</span>
|
|
||||||
</Label>
|
|
||||||
<Switch
|
|
||||||
id="strictly_necessary"
|
|
||||||
v-model:checked="strictlyNecessarySwitch"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center space-x-2">
|
|
||||||
<Label for="functional_cookies" class="flex flex-col">
|
|
||||||
Functional Cookies
|
|
||||||
<span
|
|
||||||
class="text-muted-foreground text-xs mt-1 max-w-[18rem]"
|
|
||||||
>
|
|
||||||
These cookies enable the website to provide enhanced
|
|
||||||
functionality and personalization.
|
|
||||||
</span>
|
|
||||||
</Label>
|
|
||||||
<Switch
|
|
||||||
id="functional_cookies"
|
|
||||||
v-model:checked="functionalCookiesSwitch"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center space-x-2">
|
|
||||||
<Label for="performance_cookies" class="flex flex-col">
|
|
||||||
Performance Cookies
|
|
||||||
<span
|
|
||||||
class="text-muted-foreground text-xs mt-1 max-w-[18rem]"
|
|
||||||
>
|
|
||||||
These cookies are used to collect information about how
|
|
||||||
you use our website.
|
|
||||||
</span>
|
|
||||||
</Label>
|
|
||||||
<Switch
|
|
||||||
id="performance_cookies"
|
|
||||||
v-model:checked="performanceCookiesSwitch"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
|
|
||||||
<CardFooter>
|
|
||||||
<Button variant="outline" class="w-full">
|
|
||||||
Save Preferences
|
|
||||||
</Button>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle class="text-lg">
|
|
||||||
Payment Method
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Add a new payment method or update your existing payment
|
|
||||||
method.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="grid grid-cols-3 gap-x-4">
|
|
||||||
<div
|
|
||||||
v-for="payment in payments"
|
|
||||||
:key="payment.name"
|
|
||||||
class="flex flex-col justify-center items-center p-4 rounded-lg cursor-pointer transition-colors ease-in-out duration-200"
|
|
||||||
:class="[
|
|
||||||
selectedPayment.name === payment.name
|
|
||||||
? 'border-2 border-primary'
|
|
||||||
: 'border border-border hover:bg-accent',
|
|
||||||
]"
|
|
||||||
@click="switchPayment(payment)"
|
|
||||||
>
|
|
||||||
<component :is="payment.icon" class="w-6 h-6" />
|
|
||||||
<span class="text-foreground text-sm font-medium mt-1.5">
|
|
||||||
{{ payment.name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-2 pt-4">
|
|
||||||
<Label for="name" class="text-sm"> Name </Label>
|
|
||||||
<Input id="name" placeholder="Name" />
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-2 pt-4">
|
|
||||||
<Label for="card_number" class="text-sm"> Card number </Label>
|
|
||||||
<Input id="card_number" placeholder="4242 4242 4242 4242" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-4 pt-4">
|
|
||||||
<div class="flex flex-col space-y-1.5">
|
|
||||||
<Label for="expires_month">Month</Label>
|
|
||||||
<Select v-model="selectedMonth">
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue placeholder="Month" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent side="top">
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem
|
|
||||||
v-for="month in months"
|
|
||||||
:key="month"
|
|
||||||
:value="month"
|
|
||||||
>
|
|
||||||
{{ month }}
|
|
||||||
</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col space-y-1.5">
|
|
||||||
<Label for="expires_year"> Year </Label>
|
|
||||||
<Select v-model="selectedYear">
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue placeholder="Year" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent side="top">
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem
|
|
||||||
v-for="year in years"
|
|
||||||
:key="year"
|
|
||||||
:value="year"
|
|
||||||
>
|
|
||||||
{{ year }}
|
|
||||||
</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col space-y-1.5">
|
|
||||||
<Label for="cvc">CVC</Label>
|
|
||||||
<Input id="cvc" placeholder="123" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
<CardFooter>
|
|
||||||
<Button class="w-full">
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<Card>
|
<CardChat />
|
||||||
<CardHeader class="flex flex-row items-center justify-between">
|
<CreateAccount />
|
||||||
<div class="flex items-center space-x-3 my-2">
|
<ReportAnIssue />
|
||||||
<Avatar size="sm">
|
|
||||||
<AvatarImage
|
|
||||||
src="https://api.dicebear.com/6.x/lorelei/svg?seed=Bear"
|
|
||||||
/>
|
|
||||||
<AvatarFallback>B</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<p class="text-foreground text-sm font-semibold">
|
|
||||||
Bear Brown
|
|
||||||
</p>
|
|
||||||
<p class="text-muted-foreground text-sm">
|
|
||||||
bear@example.com
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip :delay-duration="200">
|
|
||||||
<TooltipTrigger as-child>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
class="rounded-full p-2.5 flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<Plus class="w-4 h-4" />
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent :side-offset="10">
|
|
||||||
New message
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="space-y-4">
|
|
||||||
<div
|
|
||||||
class="flex w-auto max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm bg-muted"
|
|
||||||
>
|
|
||||||
Hi, how can I help you today?
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex w-auto max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm ml-auto bg-primary text-primary-foreground"
|
|
||||||
>
|
|
||||||
Hey, I'm having trouble with my account.
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex w-auto max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm bg-muted"
|
|
||||||
>
|
|
||||||
Sure, I can help you with that. What seems to be the problem?
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex w-auto max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm ml-auto bg-primary text-primary-foreground"
|
|
||||||
>
|
|
||||||
I can't log in.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
<CardFooter>
|
|
||||||
<div class="flex w-full space-x-2 items-center">
|
|
||||||
<Input placeholder="Type a message..." class="flex-1" />
|
|
||||||
<Button class="p-2.5 flex items-center justify-center">
|
|
||||||
<Send class="w-4 h-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Create an account</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Enter your details below to create your account.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="grid grid-cols-2 gap-6">
|
|
||||||
<Button variant="outline">
|
|
||||||
<RiGoogleLine class="w-4 h-4 mr-2" />
|
|
||||||
Google
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline">
|
|
||||||
<RadixIconsGithubLogo class="w-4 h-4 mr-2" />
|
|
||||||
Github
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div class="relative mt-4">
|
|
||||||
<div class="absolute inset-0 flex items-center">
|
|
||||||
<span class="w-full border-t border-border" />
|
|
||||||
</div>
|
|
||||||
<div class="relative flex justify-center text-xs uppercase">
|
|
||||||
<span class="bg-card text-muted-foreground px-2"> Or </span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-2 pt-4">
|
|
||||||
<Label for="email">Email</Label>
|
|
||||||
<Input id="email" placeholder="name@example.com" />
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-2 pt-4">
|
|
||||||
<Label for="password">Password</Label>
|
|
||||||
<Input id="password" type="password" placeholder="••••••••" />
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
<CardFooter>
|
|
||||||
<Button class="w-full">
|
|
||||||
Create account
|
|
||||||
</Button>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle> Report an issue </CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
What area are you having problems with?
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="grid gap-4 sm:grid-cols-2">
|
|
||||||
<div class="grid gap-2">
|
|
||||||
<Label for="area">Area</Label>
|
|
||||||
<Select v-model="selectedArea">
|
|
||||||
<SelectTrigger>
|
|
||||||
{{ selectedArea || "Area" }}
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent class="w-[139px]">
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem value="Team">
|
|
||||||
Team
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Billing">
|
|
||||||
Billing
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Account">
|
|
||||||
Account
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Deployment">
|
|
||||||
Deployment
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Support">
|
|
||||||
Support
|
|
||||||
</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-2">
|
|
||||||
<Label for="security">Security Level</Label>
|
|
||||||
<Select v-model="selectedSecurity">
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue placeholder="Medium" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent class="w-[139px]">
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem value="Low">
|
|
||||||
Low
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Medium">
|
|
||||||
Medium
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="High">
|
|
||||||
High
|
|
||||||
</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-2 py-4">
|
|
||||||
<Label for="subject">Subject</Label>
|
|
||||||
<Input id="subject" placeholder="I need help with..." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-2">
|
|
||||||
<Label for="description">Description</Label>
|
|
||||||
<Textarea
|
|
||||||
id="description"
|
|
||||||
placeholder="Describe your issue..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
|
|
||||||
<CardFooter class="flex justify-between items-center">
|
|
||||||
<Button variant="outline">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button> Submit </Button>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-4 lg:col-span-6 xl:col-span-5 xl:space-y-4">
|
<div class="space-y-4 lg:col-span-6 xl:col-span-5 xl:space-y-4">
|
||||||
<div class="hidden gap-1 sm:grid-cols-[280px_1fr] md:grid">
|
<div class="hidden gap-1 sm:grid-cols-[280px_1fr] md:grid">
|
||||||
<Card class="max-w-[280px]">
|
<Card class="max-w-[280px]">
|
||||||
<Calendar v-model.range="range" />
|
<RangeCalendar v-model="range" />
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div class="pt-3 sm:pl-2 sm:pt-0 xl:pl-3">
|
<div class="pt-3 sm:pl-2 sm:pt-0 xl:pl-3">
|
||||||
<Card>
|
<ActivityGoal />
|
||||||
<CardHeader>
|
|
||||||
<CardTitle class="text-md">
|
|
||||||
Move Goal
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Set your daily activity goal.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent class="pb-2">
|
|
||||||
<div class="flex items-center justify-center space-x-2">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
class="w-8 h-8 rounded-full p-0"
|
|
||||||
:disabled="goal <= 200"
|
|
||||||
@click="goal -= 10"
|
|
||||||
>
|
|
||||||
<Minus class="w-4 h-4" />
|
|
||||||
</Button>
|
|
||||||
<div class="flex-1 text-center">
|
|
||||||
<p
|
|
||||||
class="text-foreground text-5xl font-bold tracking-tight"
|
|
||||||
>
|
|
||||||
{{ goal }}
|
|
||||||
</p>
|
|
||||||
<span class="text-muted-foreground text-[11px] uppercase">
|
|
||||||
Calories/day
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
class="w-8 h-8 rounded-full p-0"
|
|
||||||
:disabled="goal >= 500"
|
|
||||||
@click="goal += 10"
|
|
||||||
>
|
|
||||||
<Plus class="w-4 h-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="my-2" />
|
|
||||||
</CardContent>
|
|
||||||
<CardFooter>
|
|
||||||
<Button class="w-full">
|
|
||||||
Set Goal
|
|
||||||
</Button>
|
|
||||||
</CardFooter>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
||||||
<Card>
|
<Metric />
|
||||||
<CardHeader>
|
|
||||||
<CardTitle> Exercise Minutes </CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Your exercise minutes are ahead of where you normally are.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent />
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
||||||
<Card>
|
<DataTable />
|
||||||
<CardHeader>
|
|
||||||
<CardTitle> Payments </CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Manage your payment methods and view your billing history.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent />
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
<div class="pt-3 sm:col-span-2 xl:pt-3">
|
||||||
<Card>
|
<ShareDocument />
|
||||||
<CardHeader>
|
|
||||||
<CardTitle> Share this document </CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Anyone with this link will be able to view this document.
|
|
||||||
</CardDescription>
|
|
||||||
|
|
||||||
<div class="flex space-x-2 items-center pt-2.5">
|
|
||||||
<Input
|
|
||||||
class="flex-1"
|
|
||||||
placeholder="http://..."
|
|
||||||
value="http://example.com/link/to/document"
|
|
||||||
/>
|
|
||||||
<Button variant="secondary">
|
|
||||||
Copy Link
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<Separator />
|
|
||||||
<Label class="mt-4"> People with access </Label>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="teamMember in teamMembers"
|
|
||||||
:key="teamMember.name"
|
|
||||||
class="flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<div class="flex items-center space-x-3 my-4">
|
|
||||||
<Avatar size="sm">
|
|
||||||
<AvatarImage :src="teamMember.avatar" />
|
|
||||||
<AvatarFallback>
|
|
||||||
{{ teamMember.name.slice(0, 2) }}
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<p class="text-foreground text-sm font-medium">
|
|
||||||
{{ teamMember.name }}
|
|
||||||
</p>
|
|
||||||
<p class="text-muted-foreground text-sm">
|
|
||||||
{{ teamMember.username }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Select v-model="teamMember.access">
|
|
||||||
<SelectTrigger class="w-28">
|
|
||||||
<SelectValue :placeholder="teamMember.access" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectItem value="Can edit">
|
|
||||||
Can edit
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="Can view">
|
|
||||||
Can view
|
|
||||||
</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,42 @@
|
||||||
import { CreditCard } from 'lucide-vue-next'
|
|
||||||
import RiAppleFill from '~icons/ri/apple-fill'
|
import RiAppleFill from '~icons/ri/apple-fill'
|
||||||
import RiPaypalFill from '~icons/ri/paypal-fill'
|
import RiPaypalFill from '~icons/ri/paypal-fill'
|
||||||
|
import { CreditCard } from 'lucide-vue-next'
|
||||||
|
|
||||||
interface Payment {
|
type Color =
|
||||||
status: string
|
| 'zinc'
|
||||||
email: string
|
| 'slate'
|
||||||
amount: number
|
| 'stone'
|
||||||
}
|
| 'gray'
|
||||||
|
| 'neutral'
|
||||||
|
| 'red'
|
||||||
|
| 'rose'
|
||||||
|
| 'orange'
|
||||||
|
| 'green'
|
||||||
|
| 'blue'
|
||||||
|
| 'yellow'
|
||||||
|
| 'violet'
|
||||||
|
|
||||||
|
// Create an array of color values
|
||||||
|
export const allColors: Color[] = [
|
||||||
|
'zinc',
|
||||||
|
'rose',
|
||||||
|
'blue',
|
||||||
|
'green',
|
||||||
|
'orange',
|
||||||
|
'red',
|
||||||
|
'slate',
|
||||||
|
'stone',
|
||||||
|
'gray',
|
||||||
|
'neutral',
|
||||||
|
'yellow',
|
||||||
|
'violet',
|
||||||
|
]
|
||||||
|
|
||||||
|
// interface Payment {
|
||||||
|
// status: string
|
||||||
|
// email: string
|
||||||
|
// amount: number
|
||||||
|
// }
|
||||||
|
|
||||||
interface TeamMember {
|
interface TeamMember {
|
||||||
name: string
|
name: string
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ export interface NavItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SidebarNavItem = NavItem & {
|
export type SidebarNavItem = NavItem & {
|
||||||
items: SidebarNavItem[]
|
items?: SidebarNavItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NavItemWithChildren = NavItem & {
|
export type NavItemWithChildren = NavItem & {
|
||||||
items: NavItemWithChildren[]
|
items?: NavItemWithChildren[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DocsConfig {
|
interface DocsConfig {
|
||||||
|
|
@ -23,7 +23,7 @@ interface DocsConfig {
|
||||||
export const docsConfig: DocsConfig = {
|
export const docsConfig: DocsConfig = {
|
||||||
mainNav: [
|
mainNav: [
|
||||||
{
|
{
|
||||||
title: 'Documentation',
|
title: 'Docs',
|
||||||
href: '/docs/introduction',
|
href: '/docs/introduction',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +36,11 @@ export const docsConfig: DocsConfig = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Examples',
|
title: 'Examples',
|
||||||
href: '/examples/dashboard',
|
href: '/examples/mail',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Blocks',
|
||||||
|
href: '/blocks',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'GitHub',
|
title: 'GitHub',
|
||||||
|
|
@ -51,46 +55,47 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Introduction',
|
title: 'Introduction',
|
||||||
href: '/docs/introduction',
|
href: '/docs/introduction',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Installation',
|
title: 'Installation',
|
||||||
href: '/docs/installation',
|
href: '/docs/installation',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'components.json',
|
title: 'components.json',
|
||||||
href: '/docs/components-json',
|
href: '/docs/components-json',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Theming',
|
title: 'Theming',
|
||||||
href: '/docs/theming',
|
href: '/docs/theming',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Dark Mode',
|
||||||
|
href: '/docs/dark-mode',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CLI',
|
title: 'CLI',
|
||||||
href: '/docs/cli',
|
href: '/docs/cli',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Typography',
|
title: 'Typography',
|
||||||
href: '/docs/typography',
|
href: '/docs/typography',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Figma',
|
title: 'Figma',
|
||||||
href: '/docs/figma',
|
href: '/docs/figma',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Changelog',
|
title: 'Changelog',
|
||||||
href: '/docs/changelog',
|
href: '/docs/changelog',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'About',
|
title: 'About',
|
||||||
href: '/docs/about',
|
href: '/docs/about',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Contribution',
|
||||||
|
href: '/docs/contribution',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -101,21 +106,32 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Vite',
|
title: 'Vite',
|
||||||
href: '/docs/installation/vite',
|
href: '/docs/installation/vite',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Nuxt',
|
title: 'Nuxt',
|
||||||
href: '/docs/installation/nuxt',
|
href: '/docs/installation/nuxt',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: 'Astro',
|
title: 'Astro',
|
||||||
// href: '/docs/installation/astro',
|
href: '/docs/installation/astro',
|
||||||
// items: [],
|
},
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
title: 'Laravel',
|
title: 'Laravel',
|
||||||
href: '/docs/installation/laravel',
|
href: '/docs/installation/laravel',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Extended',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
title: 'Auto Form',
|
||||||
|
href: '/docs/components/auto-form',
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Charts',
|
||||||
|
href: '/docs/charts',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -123,40 +139,43 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Components',
|
title: 'Components',
|
||||||
items: [
|
items: [
|
||||||
|
{
|
||||||
|
title: 'Sidebar',
|
||||||
|
href: '/docs/components/sidebar',
|
||||||
|
label: 'New',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Accordion',
|
title: 'Accordion',
|
||||||
href: '/docs/components/accordion',
|
href: '/docs/components/accordion',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Alert',
|
title: 'Alert',
|
||||||
href: '/docs/components/alert',
|
href: '/docs/components/alert',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Alert Dialog',
|
title: 'Alert Dialog',
|
||||||
href: '/docs/components/alert-dialog',
|
href: '/docs/components/alert-dialog',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Aspect Ratio',
|
title: 'Aspect Ratio',
|
||||||
href: '/docs/components/aspect-ratio',
|
href: '/docs/components/aspect-ratio',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Avatar',
|
title: 'Avatar',
|
||||||
href: '/docs/components/avatar',
|
href: '/docs/components/avatar',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Badge',
|
title: 'Badge',
|
||||||
href: '/docs/components/badge',
|
href: '/docs/components/badge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Breadcrumb',
|
||||||
|
href: '/docs/components/breadcrumb',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Button',
|
title: 'Button',
|
||||||
href: '/docs/components/button',
|
href: '/docs/components/button',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Calendar',
|
title: 'Calendar',
|
||||||
|
|
@ -166,39 +185,35 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Card',
|
title: 'Card',
|
||||||
href: '/docs/components/card',
|
href: '/docs/components/card',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Carousel',
|
||||||
|
href: '/docs/components/carousel',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Checkbox',
|
title: 'Checkbox',
|
||||||
href: '/docs/components/checkbox',
|
href: '/docs/components/checkbox',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Collapsible',
|
title: 'Collapsible',
|
||||||
href: '/docs/components/collapsible',
|
href: '/docs/components/collapsible',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Combobox',
|
title: 'Combobox',
|
||||||
href: '/docs/components/combobox',
|
href: '/docs/components/combobox',
|
||||||
label: 'New',
|
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Command',
|
title: 'Command',
|
||||||
href: '/docs/components/command',
|
href: '/docs/components/command',
|
||||||
label: 'New',
|
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Context Menu',
|
title: 'Context Menu',
|
||||||
href: '/docs/components/context-menu',
|
href: '/docs/components/context-menu',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Data Table',
|
title: 'Data Table',
|
||||||
href: '/docs/components/data-table',
|
href: '/docs/components/data-table',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Date Picker',
|
title: 'Date Picker',
|
||||||
|
|
@ -208,126 +223,144 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Dialog',
|
title: 'Dialog',
|
||||||
href: '/docs/components/dialog',
|
href: '/docs/components/dialog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Drawer',
|
||||||
|
href: '/docs/components/drawer',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Dropdown Menu',
|
title: 'Dropdown Menu',
|
||||||
href: '/docs/components/dropdown-menu',
|
href: '/docs/components/dropdown-menu',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Form',
|
title: 'Form',
|
||||||
href: '#',
|
href: '/docs/components/form',
|
||||||
label: 'Soon',
|
|
||||||
disabled: true,
|
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Hover Card',
|
title: 'Hover Card',
|
||||||
href: '/docs/components/hover-card',
|
href: '/docs/components/hover-card',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Input',
|
title: 'Input',
|
||||||
href: '/docs/components/input',
|
href: '/docs/components/input',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Label',
|
title: 'Label',
|
||||||
href: '/docs/components/label',
|
href: '/docs/components/label',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Menubar',
|
title: 'Menubar',
|
||||||
href: '/docs/components/menubar',
|
href: '/docs/components/menubar',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Navigation Menu',
|
title: 'Navigation Menu',
|
||||||
href: '/docs/components/navigation-menu',
|
href: '/docs/components/navigation-menu',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Number Field',
|
||||||
|
href: '/docs/components/number-field',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Pagination',
|
||||||
|
href: '/docs/components/pagination',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'PIN Input',
|
||||||
|
href: '/docs/components/pin-input',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Popover',
|
title: 'Popover',
|
||||||
href: '/docs/components/popover',
|
href: '/docs/components/popover',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Progress',
|
title: 'Progress',
|
||||||
href: '/docs/components/progress',
|
href: '/docs/components/progress',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Radio Group',
|
title: 'Radio Group',
|
||||||
href: '/docs/components/radio-group',
|
href: '/docs/components/radio-group',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Range Calendar',
|
||||||
|
href: '/docs/components/range-calendar',
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Resizable',
|
||||||
|
href: '/docs/components/resizable',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Scroll Area',
|
title: 'Scroll Area',
|
||||||
href: '/docs/components/scroll-area',
|
href: '/docs/components/scroll-area',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Select',
|
title: 'Select',
|
||||||
href: '/docs/components/select',
|
href: '/docs/components/select',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Separator',
|
title: 'Separator',
|
||||||
href: '/docs/components/separator',
|
href: '/docs/components/separator',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Sheet',
|
title: 'Sheet',
|
||||||
href: '/docs/components/sheet',
|
href: '/docs/components/sheet',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Skeleton',
|
title: 'Skeleton',
|
||||||
href: '/docs/components/skeleton',
|
href: '/docs/components/skeleton',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Slider',
|
title: 'Slider',
|
||||||
href: '/docs/components/slider',
|
href: '/docs/components/slider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Sonner',
|
||||||
|
href: '/docs/components/sonner',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Stepper',
|
||||||
|
href: '/docs/components/stepper',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Switch',
|
title: 'Switch',
|
||||||
href: '/docs/components/switch',
|
href: '/docs/components/switch',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Table',
|
title: 'Table',
|
||||||
href: '/docs/components/table',
|
href: '/docs/components/table',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tabs',
|
title: 'Tabs',
|
||||||
href: '/docs/components/tabs',
|
href: '/docs/components/tabs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tags Input',
|
||||||
|
href: '/docs/components/tags-input',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Textarea',
|
title: 'Textarea',
|
||||||
href: '/docs/components/textarea',
|
href: '/docs/components/textarea',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: "Toast",
|
title: 'Toast',
|
||||||
// href: "#",
|
href: '/docs/components/toast',
|
||||||
// label: "Soon",
|
},
|
||||||
// disabled: true,
|
|
||||||
// items: []
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
title: 'Toggle',
|
title: 'Toggle',
|
||||||
href: '/docs/components/toggle',
|
href: '/docs/components/toggle',
|
||||||
items: [],
|
},
|
||||||
|
{
|
||||||
|
title: 'Toggle Group',
|
||||||
|
href: '/docs/components/toggle-group',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tooltip',
|
title: 'Tooltip',
|
||||||
href: '/docs/components/tooltip',
|
href: '/docs/components/tooltip',
|
||||||
items: [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -341,6 +374,11 @@ interface Example {
|
||||||
code: string
|
code: string
|
||||||
}
|
}
|
||||||
export const examples: Example[] = [
|
export const examples: Example[] = [
|
||||||
|
{
|
||||||
|
name: 'Mail',
|
||||||
|
href: '/examples/mail',
|
||||||
|
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/mail',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
href: '/examples/dashboard',
|
href: '/examples/dashboard',
|
||||||
|
|
@ -352,10 +390,10 @@ export const examples: Example[] = [
|
||||||
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/cards',
|
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/cards',
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// name: "Tasks",
|
// name: "Tasks",
|
||||||
// href: "/examples/tasks",
|
// href: "/examples/tasks",
|
||||||
// label: "New",
|
// label: "New",
|
||||||
// code: "https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/tasks"
|
// code: "https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/tasks"
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
name: 'Playground',
|
name: 'Playground',
|
||||||
|
|
|
||||||
41
apps/www/.vitepress/theme/config/shiki.ts
Normal file
41
apps/www/.vitepress/theme/config/shiki.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import type { HighlighterCore } from 'shiki/core'
|
||||||
|
import type { ThemeOptions } from 'vitepress'
|
||||||
|
import { computedAsync } from '@vueuse/core'
|
||||||
|
import { createHighlighterCore } from 'shiki/core'
|
||||||
|
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
|
||||||
|
|
||||||
|
export const shikiThemes: ThemeOptions = {
|
||||||
|
light: 'github-light-default',
|
||||||
|
dark: 'github-dark-default',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const highlighter = computedAsync<HighlighterCore>(async (onCancel) => {
|
||||||
|
const shiki = await createHighlighterCore({
|
||||||
|
engine: createJavaScriptRegexEngine(),
|
||||||
|
themes: [
|
||||||
|
() => import('shiki/themes/github-dark-default.mjs'),
|
||||||
|
() => import('shiki/themes/github-light-default.mjs'),
|
||||||
|
],
|
||||||
|
langs: [
|
||||||
|
() => import('shiki/langs/javascript.mjs'),
|
||||||
|
() => import('shiki/langs/vue.mjs'),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
onCancel(() => shiki?.dispose())
|
||||||
|
return shiki
|
||||||
|
})
|
||||||
|
|
||||||
|
export function highlight(code: string, lang: string) {
|
||||||
|
if (!highlighter.value)
|
||||||
|
return code
|
||||||
|
|
||||||
|
return highlighter.value.codeToHtml(code, {
|
||||||
|
lang,
|
||||||
|
defaultColor: false,
|
||||||
|
themes: {
|
||||||
|
dark: 'github-dark-default',
|
||||||
|
light: 'github-light-default',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -12,3 +12,9 @@ export const siteConfig = {
|
||||||
},
|
},
|
||||||
keywords: 'shadcn,Vue,Nuxt,Vue Components,TailwindCSS,Radix Vue',
|
keywords: 'shadcn,Vue,Nuxt,Vue Components,TailwindCSS,Radix Vue',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const announcementConfig = {
|
||||||
|
icon: '✨',
|
||||||
|
title: 'Extended: Auto Form, Charts',
|
||||||
|
link: '/docs/components/auto-form.html',
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
/* eslint-disable vue/component-definition-name-casing */
|
import * as components from './components'
|
||||||
// https://vitepress.dev/guide/custom-theme
|
|
||||||
import Layout from './layout/MainLayout.vue'
|
|
||||||
import DocsLayout from './layout/DocsLayout.vue'
|
import DocsLayout from './layout/DocsLayout.vue'
|
||||||
import ExamplesLayout from './layout/ExamplesLayout.vue'
|
import ExamplesLayout from './layout/ExamplesLayout.vue'
|
||||||
import * as components from './components'
|
// https://vitepress.dev/guide/custom-theme
|
||||||
|
import Layout from './layout/MainLayout.vue'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import './styles/vp-doc.css'
|
import './styles/vp-doc.css'
|
||||||
import './styles/shiki.css'
|
import './styles/shiki.css'
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useData, useRoute } from 'vitepress'
|
|
||||||
import { docsConfig } from '../config/docs'
|
|
||||||
import TableOfContentVue from '../components/TableOfContent.vue'
|
|
||||||
import EditLink from '../components/EditLink.vue'
|
|
||||||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||||
import { Badge } from '@/lib/registry/default/ui/badge'
|
|
||||||
import RadixIconsCode from '~icons/radix-icons/code'
|
import RadixIconsCode from '~icons/radix-icons/code'
|
||||||
import ChevronRightIcon from '~icons/lucide/chevron-right'
|
import RadixIconsExternalLink from '~icons/radix-icons/external-link'
|
||||||
|
import { useData, useRoute } from 'vitepress'
|
||||||
|
import DocsBreadcrumb from '../components/DocsBreadcrumb.vue'
|
||||||
|
import EditLink from '../components/EditLink.vue'
|
||||||
|
import TableOfContent from '../components/TableOfContent.vue'
|
||||||
|
import { docsConfig } from '../config/docs'
|
||||||
|
|
||||||
const $route = useRoute()
|
const $route = useRoute()
|
||||||
const { frontmatter } = useData()
|
const { frontmatter } = useData()
|
||||||
|
|
@ -20,13 +20,17 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
<aside
|
<aside
|
||||||
class="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block overflow-y-auto"
|
class="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block overflow-y-auto"
|
||||||
>
|
>
|
||||||
<ScrollArea orientation="vertical" class="h-full py-6 pl-8 pr-6 lg:py-8" :type="'auto'">
|
<ScrollArea orientation="vertical" class="relative overflow-hidden h-full py-6 pr-6 lg:py-8" :type="'auto'">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div v-for="docsGroup in docsConfig.sidebarNav" :key="docsGroup.title" class="pb-4">
|
<div v-for="docsGroup in docsConfig.sidebarNav" :key="docsGroup.title" class="pb-4">
|
||||||
<h4
|
<h4
|
||||||
class="mb-1 rounded-md px-2 py-1 text-sm font-semibold"
|
class="mb-1 rounded-md px-2 py-1 text-sm font-semibold"
|
||||||
>
|
>
|
||||||
{{ docsGroup.title }}
|
{{ docsGroup.title }}
|
||||||
|
|
||||||
|
<span v-if="docsGroup.label" class="ml-2 font-normal rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||||
|
{{ docsGroup.label }}
|
||||||
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -45,9 +49,9 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
>
|
>
|
||||||
{{ doc.title }}
|
{{ doc.title }}
|
||||||
|
|
||||||
<Badge v-if="doc.label" class="ml-2" :variant="'secondary'">
|
<span v-if="doc.label" class="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||||
{{ doc.label }}
|
{{ doc.label }}
|
||||||
</Badge>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -58,29 +62,30 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
<main class="relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]">
|
<main class="relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]">
|
||||||
<div class="mx-auto w-full min-w-0">
|
<div class="mx-auto w-full min-w-0">
|
||||||
<div class="block xl:hidden">
|
<div class="block xl:hidden">
|
||||||
<TableOfContentVue />
|
<TableOfContent />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-4 flex items-center space-x-1 text-sm text-muted-foreground">
|
<DocsBreadcrumb class="mb-4" />
|
||||||
<div class="overflow-hidden text-ellipsis whitespace-nowrap">
|
|
||||||
Docs
|
|
||||||
</div>
|
|
||||||
<ChevronRightIcon class="h-4 w-4" />
|
|
||||||
<div class="font-medium text-foreground">
|
|
||||||
{{ frontmatter.title }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h1 class="scroll-m-20 text-4xl font-bold tracking-tight">
|
<div class="flex items-center space-x-4">
|
||||||
{{ frontmatter.title }}
|
<h1 class="scroll-m-20 text-4xl font-bold tracking-tight">
|
||||||
</h1>
|
{{ frontmatter.title }}
|
||||||
|
</h1>
|
||||||
|
<span v-if="frontmatter.label" class="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||||
|
{{ frontmatter.label }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<p class="text-lg text-muted-foreground">
|
<p class="text-lg text-muted-foreground">
|
||||||
{{ frontmatter.description }}
|
{{ frontmatter.description }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2 pt-4">
|
<div class="flex items-center space-x-2 pt-4">
|
||||||
|
<a v-if="frontmatter.docs" :href="frontmatter.docs" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||||
|
<RadixIconsExternalLink class="mr-1" />
|
||||||
|
Docs
|
||||||
|
</a>
|
||||||
<a v-if="frontmatter.source" :href="sourceLink + frontmatter.source" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
<a v-if="frontmatter.source" :href="sourceLink + frontmatter.source" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||||
<RadixIconsCode class="mr-1" />
|
<RadixIconsCode class="mr-1" />
|
||||||
Component Source
|
Component Source
|
||||||
|
|
@ -99,7 +104,7 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
|
|
||||||
<div class="hidden text-sm xl:block">
|
<div class="hidden text-sm xl:block">
|
||||||
<div class="sticky top-16 -mt-10 h-[calc(100vh-3.5rem)] overflow-hidden pt-6">
|
<div class="sticky top-16 -mt-10 h-[calc(100vh-3.5rem)] overflow-hidden pt-6">
|
||||||
<TableOfContentVue />
|
<TableOfContent show-carbon-ads />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,19 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import PageHeader from '../components/PageHeader.vue'
|
|
||||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
|
||||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
|
||||||
import ExamplesNav from '../components/ExamplesNav.vue'
|
|
||||||
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
|
||||||
|
|
||||||
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
||||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import Announcement from '../components/Announcement.vue'
|
||||||
|
import ExamplesNav from '../components/ExamplesNav.vue'
|
||||||
|
import PageAction from '../components/PageAction.vue'
|
||||||
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
|
|
||||||
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container relative">
|
<div class="container relative">
|
||||||
<PageHeader class="page-header pb-8">
|
<PageHeader class="page-header pb-8">
|
||||||
<a
|
<Announcement />
|
||||||
href="/docs/changelog"
|
|
||||||
class="inline-flex items-center rounded-lg bg-muted px-3 py-1 text-sm font-medium"
|
|
||||||
>
|
|
||||||
🎉 <Separator class="mx-2 h-4" orientation="vertical" />
|
|
||||||
<span class="sm:hidden">Style, a new CLI and more.</span>
|
|
||||||
<span class="hidden sm:inline">
|
|
||||||
Introducing Style, a new CLI and more.
|
|
||||||
</span>
|
|
||||||
<ArrowRightIcon class="ml-1 h-4 w-4" />
|
|
||||||
</a>
|
|
||||||
<PageHeaderHeading class="hidden md:block">
|
<PageHeaderHeading class="hidden md:block">
|
||||||
Check out some examples.
|
Check out some examples.
|
||||||
</PageHeaderHeading>
|
</PageHeaderHeading>
|
||||||
|
|
@ -35,7 +25,7 @@ import { cn } from '@/lib/utils'
|
||||||
components. Use this as a guide to build your own.
|
components. Use this as a guide to build your own.
|
||||||
</PageHeaderDescription>
|
</PageHeaderDescription>
|
||||||
|
|
||||||
<section class="flex w-full items-center space-x-4 pb-8 pt-4 md:pb-10">
|
<PageAction>
|
||||||
<a
|
<a
|
||||||
href="/docs/introduction"
|
href="/docs/introduction"
|
||||||
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
||||||
|
|
@ -51,7 +41,7 @@ import { cn } from '@/lib/utils'
|
||||||
>
|
>
|
||||||
Components
|
Components
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</PageAction>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<section>
|
<section>
|
||||||
<ExamplesNav />
|
<ExamplesNav />
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,29 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '@/lib/registry/default/ui/command'
|
||||||
|
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
||||||
|
import { Toaster as DefaultToaster } from '@/lib/registry/default/ui/toast'
|
||||||
|
import { Toaster as NewYorkSonner } from '@/lib/registry/new-york/ui/sonner'
|
||||||
|
import { Toaster as NewYorkToaster } from '@/lib/registry/new-york/ui/toast'
|
||||||
|
import { TooltipProvider } from '@/lib/registry/new-york/ui/tooltip'
|
||||||
|
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { useMagicKeys, useToggle } from '@vueuse/core'
|
import { useMagicKeys, useToggle } from '@vueuse/core'
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import Circle from '~icons/radix-icons/circle'
|
||||||
|
|
||||||
|
import File from '~icons/radix-icons/file'
|
||||||
|
import RadixIconsGithubLogo from '~icons/radix-icons/github-logo'
|
||||||
|
import RadixIconsMoon from '~icons/radix-icons/moon'
|
||||||
|
import RadixIconsSun from '~icons/radix-icons/sun'
|
||||||
import { Content, useData, useRoute, useRouter } from 'vitepress'
|
import { Content, useData, useRoute, useRouter } from 'vitepress'
|
||||||
import { SearchIcon } from 'lucide-vue-next'
|
import { onMounted, ref, watch } from 'vue'
|
||||||
import { type NavItem, docsConfig } from '../config/docs'
|
import CodeConfigCustomizer from '../components/CodeConfigCustomizer.vue'
|
||||||
|
import Kbd from '../components/Kbd.vue'
|
||||||
import Logo from '../components/Logo.vue'
|
import Logo from '../components/Logo.vue'
|
||||||
import MobileNav from '../components/MobileNav.vue'
|
import MobileNav from '../components/MobileNav.vue'
|
||||||
|
|
||||||
import Kbd from '../components/Kbd.vue'
|
import ThemePopover from '../components/ThemePopover.vue'
|
||||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '@/lib/registry/default/ui/command'
|
import { docsConfig, type NavItem } from '../config/docs'
|
||||||
|
|
||||||
import { Button } from '@/lib/registry/default/ui/button'
|
|
||||||
import RadixIconsGithubLogo from '~icons/radix-icons/github-logo'
|
|
||||||
import TablerBrandX from '~icons/tabler/brand-x'
|
|
||||||
import RadixIconsMoon from '~icons/radix-icons/moon'
|
|
||||||
import RadixIconsSun from '~icons/radix-icons/sun'
|
|
||||||
import { useConfigStore } from '@/stores/config'
|
|
||||||
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
|
||||||
|
|
||||||
import File from '~icons/radix-icons/file'
|
|
||||||
import Circle from '~icons/radix-icons/circle'
|
|
||||||
|
|
||||||
const { radius, theme } = useConfigStore()
|
const { radius, theme } = useConfigStore()
|
||||||
// Whenever the component is mounted, update the document class list
|
// Whenever the component is mounted, update the document class list
|
||||||
|
|
@ -37,7 +41,7 @@ const toggleDark = useToggle(isDark)
|
||||||
const links = [
|
const links = [
|
||||||
{
|
{
|
||||||
name: 'GitHub',
|
name: 'GitHub',
|
||||||
href: 'https://github.com/radix-vue/shadcn-vue',
|
href: 'https://github.com/unovue/shadcn-vue',
|
||||||
icon: RadixIconsGithubLogo,
|
icon: RadixIconsGithubLogo,
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|
@ -48,7 +52,13 @@ const links = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const { Meta_K, Ctrl_K } = useMagicKeys()
|
const { Meta_K, Ctrl_K } = useMagicKeys({
|
||||||
|
passive: false,
|
||||||
|
onEventFired(e) {
|
||||||
|
if (e.key === 'k' && (e.metaKey || e.ctrlKey))
|
||||||
|
e.preventDefault()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
watch([Meta_K, Ctrl_K], (v) => {
|
watch([Meta_K, Ctrl_K], (v) => {
|
||||||
if (v[0] || v[1])
|
if (v[0] || v[1])
|
||||||
|
|
@ -76,205 +86,225 @@ watch(() => $route.path, (n) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex min-h-screen flex-col bg-background">
|
<TooltipProvider>
|
||||||
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
|
<div v-if="$route.data.frontmatter.layout === false">
|
||||||
<div
|
<Content :key="$route.path" />
|
||||||
class="container flex justify-between h-14 items-center"
|
|
||||||
>
|
|
||||||
<MobileNav />
|
|
||||||
|
|
||||||
<div class="mr-4 hidden md:flex">
|
|
||||||
<Logo />
|
|
||||||
|
|
||||||
<nav
|
|
||||||
class="flex items-center space-x-6 text-sm font-medium"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
v-for="route in docsConfig.mainNav"
|
|
||||||
:key="route.title"
|
|
||||||
:href="route.href"
|
|
||||||
:target="route.external ? '_target' : undefined"
|
|
||||||
class="transition-colors hover:text-foreground/80 text-foreground/60"
|
|
||||||
:class="{
|
|
||||||
'font-semibold !text-foreground': $route.path === `${route.href}.html`,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ route.title }}
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class=" flex items-center justify-end space-x-4 ">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
class="w-72 h-8 px-3 hidden lg:flex lg:justify-between lg:items-center"
|
|
||||||
@click="isOpen = true"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<SearchIcon class="w-4 h-4 mr-2 text-muted-foreground" />
|
|
||||||
<span class="text-muted-foreground"> Search for anything... </span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-x-1">
|
|
||||||
<Kbd> <span>⌘</span>K </Kbd>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="link in links"
|
|
||||||
:key="link.name"
|
|
||||||
class="flex items-center space-x-1"
|
|
||||||
>
|
|
||||||
<a :href="link.href" target="_blank" class="text-foreground">
|
|
||||||
<component :is="link.icon" class="w-5 h-5" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="flex items-center justify-center"
|
|
||||||
aria-label="Toggle dark mode"
|
|
||||||
@click="toggleDark()"
|
|
||||||
>
|
|
||||||
<component
|
|
||||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
|
||||||
class="w-5 h-5 text-foreground"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="flex-1 bg-background">
|
|
||||||
<Transition name="fade" mode="out-in">
|
|
||||||
<component :is="'docs'" v-if="$route.path.includes('docs')">
|
|
||||||
<Transition name="fade" mode="out-in">
|
|
||||||
<Content :key="$route.path" />
|
|
||||||
</Transition>
|
|
||||||
</component>
|
|
||||||
<component :is="'examples'" v-else-if="$route.path.includes('examples')">
|
|
||||||
<Transition name="fade" mode="out-in">
|
|
||||||
<Content :key="$route.path" />
|
|
||||||
</Transition>
|
|
||||||
</component>
|
|
||||||
<component :is="frontmatter.layout" v-else-if="frontmatter.layout">
|
|
||||||
<slot />
|
|
||||||
</component>
|
|
||||||
<main v-else class="container">
|
|
||||||
<Transition name="fade" mode="out-in">
|
|
||||||
<Content :key="$route.path" />
|
|
||||||
</Transition>
|
|
||||||
</main>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
|
||||||
|
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
|
||||||
|
<div
|
||||||
|
class="container flex h-14 max-w-screen-2xl items-center"
|
||||||
|
>
|
||||||
|
<div class="mr-4 md:mr-1 hidden md:flex">
|
||||||
|
<Logo />
|
||||||
|
|
||||||
<footer class="py-6 md:px-8 md:py-0">
|
<nav
|
||||||
<div class="container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row">
|
class="flex items-center max-lg:space-x-4 space-x-6 text-sm font-medium"
|
||||||
<div class="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
|
||||||
<span class="inline-block">
|
|
||||||
Built and designed by
|
|
||||||
<a
|
|
||||||
href="https://twitter.com/shadcn"
|
|
||||||
target="_blank"
|
|
||||||
class="underline underline-offset-4 font-bold decoration-foreground"
|
|
||||||
>
|
>
|
||||||
shadcn
|
<a
|
||||||
</a>
|
v-for="route in docsConfig.mainNav"
|
||||||
</span>
|
:key="route.title"
|
||||||
<span class="ml-0.5"> . </span>
|
:href="route.href"
|
||||||
<span class="inline-block ml-2">
|
:target="route.external ? '_target' : undefined"
|
||||||
Ported to Vue by
|
class="transition-colors hover:text-foreground/80 text-foreground/60"
|
||||||
<a
|
:class="{
|
||||||
href="https://github.com/radix-vue"
|
'font-semibold !text-foreground': $route.path === `${route.href}.html`,
|
||||||
target="_blank"
|
'hidden lg:block': route?.href?.includes('github'),
|
||||||
class="underline underline-offset-4 font-bold decoration-foreground"
|
}"
|
||||||
>
|
>
|
||||||
Radix Vue
|
{{ route.title }}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</nav>
|
||||||
<span class="ml-0.5"> . </span>
|
</div>
|
||||||
<span class="inline-block ml-2">
|
<MobileNav />
|
||||||
The code source is available on
|
|
||||||
<a
|
<div class="flex flex-1 items-center justify-between space-x-2 md:justify-end">
|
||||||
href="https://github.com/radix-vue/shadcn-vue"
|
<div class="w-full flex-1 md:w-auto md:flex-none">
|
||||||
target="_blank"
|
<Button
|
||||||
class="underline underline-offset-4 font-bold decoration-foreground"
|
variant="outline"
|
||||||
>
|
class="relative h-8 w-full justify-start rounded-[0.5rem] bg-background text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64"
|
||||||
GitHub
|
@click="isOpen = true"
|
||||||
</a>
|
>
|
||||||
</span>
|
<span class="hidden lg:inline-flex">Search documentation...</span>
|
||||||
|
<span class="inline-flex lg:hidden">Search...</span>
|
||||||
|
<Kbd class="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
|
||||||
|
<span class="text-xs">⌘</span>K
|
||||||
|
</Kbd>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="flex items-center">
|
||||||
|
<ThemePopover />
|
||||||
|
|
||||||
|
<CodeConfigCustomizer />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
v-for="link in links"
|
||||||
|
:key="link.name"
|
||||||
|
as="a"
|
||||||
|
class="w-9 h-9"
|
||||||
|
:href="link.href" target="_blank"
|
||||||
|
:variant="'ghost'"
|
||||||
|
:size="'icon'"
|
||||||
|
>
|
||||||
|
<component :is="link.icon" class="w-5 h-5" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<ClientOnly>
|
||||||
|
<Button
|
||||||
|
class="w-9 h-9"
|
||||||
|
aria-label="Toggle dark mode"
|
||||||
|
:variant="'ghost'"
|
||||||
|
:size="'icon'"
|
||||||
|
@click="toggleDark()"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||||
|
class="w-5 h-5 text-foreground"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</ClientOnly>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
</footer>
|
|
||||||
|
|
||||||
<Dialog v-model:open="isOpen">
|
<div class="flex-1 bg-background">
|
||||||
<DialogContent class="p-0">
|
<Transition name="fade" mode="out-in">
|
||||||
<Command>
|
<component :is="'docs'" v-if="$route.path.includes('docs')">
|
||||||
<CommandInput placeholder="Type a command or search..." />
|
<Transition name="fade" mode="out-in">
|
||||||
<CommandEmpty>
|
<Content :key="$route.path" />
|
||||||
No results found.
|
</Transition>
|
||||||
</CommandEmpty>
|
</component>
|
||||||
<CommandList
|
<component :is="'examples'" v-else-if="$route.path.includes('examples')">
|
||||||
@escape-key-down=" isOpen = false"
|
<Transition name="fade" mode="out-in">
|
||||||
>
|
<Content :key="$route.path" />
|
||||||
<CommandGroup heading="Links">
|
</Transition>
|
||||||
<CommandItem
|
</component>
|
||||||
v-for="item in docsConfig.mainNav"
|
<component :is="frontmatter.layout" v-else-if="frontmatter.layout">
|
||||||
:key="item.title"
|
<slot />
|
||||||
:heading="item.title"
|
</component>
|
||||||
:value="item.title"
|
<main v-else class="container">
|
||||||
class="py-3"
|
<Transition name="fade" mode="out-in">
|
||||||
@select="handleSelectLink(item)"
|
<Content :key="$route.path" />
|
||||||
|
</Transition>
|
||||||
|
</main>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="py-6 md:px-8 md:py-0">
|
||||||
|
<div class="container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row">
|
||||||
|
<div class="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
||||||
|
<span class="inline-block">
|
||||||
|
Built and designed by
|
||||||
|
<a
|
||||||
|
href="https://twitter.com/shadcn"
|
||||||
|
target="_blank"
|
||||||
|
class="underline underline-offset-4 font-bold decoration-foreground"
|
||||||
>
|
>
|
||||||
<File class="mr-2 h-5 w-5" />
|
shadcn
|
||||||
<span>{{ item.title }}</span>
|
</a>
|
||||||
</CommandItem>
|
</span>
|
||||||
</CommandGroup>
|
<span class="ml-0.5"> . </span>
|
||||||
<CommandSeparator />
|
<span class="inline-block ml-2">
|
||||||
<CommandGroup v-for="item in docsConfig.sidebarNav" :key="item.title" :heading="item.title">
|
Ported to Vue by
|
||||||
<CommandItem
|
<a
|
||||||
v-for="subItem in item.items"
|
href="https://github.com/unovue"
|
||||||
:key="subItem.title"
|
target="_blank"
|
||||||
:heading="subItem.title"
|
class="underline underline-offset-4 font-bold decoration-foreground"
|
||||||
:value="subItem.title"
|
|
||||||
class="py-3"
|
|
||||||
@select="
|
|
||||||
handleSelectLink(subItem)"
|
|
||||||
>
|
>
|
||||||
<Circle class="mr-2 h-4 w-4" />
|
Radix Vue
|
||||||
<span>{{ subItem.title }}</span>
|
</a>
|
||||||
</CommandItem>
|
</span>
|
||||||
</CommandGroup>
|
<span class="ml-0.5"> . </span>
|
||||||
<CommandSeparator />
|
<span class="inline-block ml-2">
|
||||||
<CommandGroup heading="Theme">
|
The code source is available on
|
||||||
<CommandItem
|
<a
|
||||||
value="light-theme"
|
href="https://github.com/unovue/shadcn-vue"
|
||||||
class="py-3"
|
target="_blank"
|
||||||
@select="
|
class="underline underline-offset-4 font-bold decoration-foreground"
|
||||||
() => {
|
|
||||||
isDark = false;
|
|
||||||
isOpen = false;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<RadixIconsSun class="mr-2 h-5 w-5" />
|
GitHub
|
||||||
<span>Light Theme</span>
|
</a>
|
||||||
</CommandItem>
|
</span>
|
||||||
<CommandItem
|
</div>
|
||||||
value="dark-theme"
|
</div>
|
||||||
class="py-3"
|
</footer>
|
||||||
@select="
|
|
||||||
() => {
|
<Dialog v-model:open="isOpen">
|
||||||
isDark = true;
|
<DialogContent class="p-0">
|
||||||
isOpen = false;
|
<Command>
|
||||||
}
|
<CommandInput placeholder="Type a command or search..." />
|
||||||
"
|
<CommandEmpty>
|
||||||
>
|
No results found.
|
||||||
<RadixIconsMoon class="mr-2 h-5 w-5" />
|
</CommandEmpty>
|
||||||
<span>Dark Theme</span>
|
<CommandList
|
||||||
</CommandItem>
|
@escape-key-down=" isOpen = false"
|
||||||
</CommandGroup>
|
>
|
||||||
</CommandList>
|
<CommandGroup heading="Links">
|
||||||
</Command>
|
<CommandItem
|
||||||
</DialogContent>
|
v-for="item in docsConfig.mainNav"
|
||||||
</Dialog>
|
:key="item.title"
|
||||||
</div>
|
:heading="item.title"
|
||||||
|
:value="item.title"
|
||||||
|
class="py-3"
|
||||||
|
@select="handleSelectLink(item)"
|
||||||
|
>
|
||||||
|
<File class="mr-2 h-5 w-5" />
|
||||||
|
<span>{{ item.title }}</span>
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
<CommandSeparator />
|
||||||
|
<CommandGroup v-for="item in docsConfig.sidebarNav" :key="item.title" :heading="item.title">
|
||||||
|
<CommandItem
|
||||||
|
v-for="subItem in item.items"
|
||||||
|
:key="subItem.title"
|
||||||
|
:heading="subItem.title"
|
||||||
|
:value="subItem.title"
|
||||||
|
class="py-3"
|
||||||
|
@select="
|
||||||
|
handleSelectLink(subItem)"
|
||||||
|
>
|
||||||
|
<Circle class="mr-2 h-4 w-4" />
|
||||||
|
<span>{{ subItem.title }}</span>
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
<CommandSeparator />
|
||||||
|
<CommandGroup heading="Theme">
|
||||||
|
<CommandItem
|
||||||
|
value="light-theme"
|
||||||
|
class="py-3"
|
||||||
|
@select="
|
||||||
|
() => {
|
||||||
|
isDark = false;
|
||||||
|
isOpen = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<RadixIconsSun class="mr-2 h-5 w-5" />
|
||||||
|
<span>Light Theme</span>
|
||||||
|
</CommandItem>
|
||||||
|
<CommandItem
|
||||||
|
value="dark-theme"
|
||||||
|
class="py-3"
|
||||||
|
@select="
|
||||||
|
() => {
|
||||||
|
isDark = true;
|
||||||
|
isOpen = false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<RadixIconsMoon class="mr-2 h-5 w-5" />
|
||||||
|
<span>Dark Theme</span>
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
<DefaultToaster />
|
||||||
|
<NewYorkSonner class="pointer-events-auto" :theme="'system'" />
|
||||||
|
<NewYorkToaster />
|
||||||
|
</div>
|
||||||
|
</TooltipProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,19 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, watch } from 'vue'
|
import type { Color } from '../types/colors'
|
||||||
import { Paintbrush } from 'lucide-vue-next'
|
|
||||||
import { useData } from 'vitepress'
|
|
||||||
import PageHeader from '../components/PageHeader.vue'
|
|
||||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
|
||||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
|
||||||
import CustomizerCode from '../components/CustomizerCode.vue'
|
|
||||||
import { RADII, useConfigStore } from '@/stores/config'
|
|
||||||
import { colors } from '@/lib/registry'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/registry/new-york/ui/tooltip'
|
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/lib/registry/new-york/ui/dialog'
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/lib/registry/new-york/ui/dialog'
|
||||||
import RadixIconsCheck from '~icons/radix-icons/check'
|
import { Drawer, DrawerContent, DrawerTrigger } from '@/lib/registry/new-york/ui/drawer'
|
||||||
import RadixIconsSun from '~icons/radix-icons/sun'
|
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
||||||
import RadixIconsMoon from '~icons/radix-icons/moon'
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { Paintbrush } from 'lucide-vue-next'
|
||||||
type Color =
|
import { onMounted, watch } from 'vue'
|
||||||
| 'zinc'
|
import CustomizerCode from '../components/CustomizerCode.vue'
|
||||||
| 'slate'
|
import InlineThemePicker from '../components/InlineThemePicker.vue'
|
||||||
| 'stone'
|
import PageAction from '../components/PageAction.vue'
|
||||||
| 'gray'
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
| 'neutral'
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
| 'red'
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
| 'rose'
|
import ThemeCustomizer from '../components/ThemeCustomizer.vue'
|
||||||
| 'orange'
|
|
||||||
| 'green'
|
|
||||||
| 'blue'
|
|
||||||
| 'yellow'
|
|
||||||
| 'violet'
|
|
||||||
|
|
||||||
// Create an array of color values
|
// Create an array of color values
|
||||||
const allColors: Color[] = [
|
const allColors: Color[] = [
|
||||||
|
|
@ -47,8 +31,7 @@ const allColors: Color[] = [
|
||||||
'violet',
|
'violet',
|
||||||
]
|
]
|
||||||
|
|
||||||
const { theme, radius, setRadius, setTheme } = useConfigStore()
|
const { theme, radius } = useConfigStore()
|
||||||
const { isDark } = useData()
|
|
||||||
|
|
||||||
// Whenever the component is mounted, update the document class list
|
// Whenever the component is mounted, update the document class list
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -72,173 +55,63 @@ watch(radius, (radius) => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container relative">
|
<div class="container relative">
|
||||||
<div class="flex justify-between items-center">
|
<PageHeader>
|
||||||
<div>
|
<PageHeaderHeading class="hidden md:block">
|
||||||
<PageHeader class="page-header pb-8">
|
Add colors. Make it yours.
|
||||||
<PageHeaderHeading class="hidden md:block">
|
</PageHeaderHeading>
|
||||||
Make it yours.
|
<PageHeaderHeading class="md:hidden">
|
||||||
</PageHeaderHeading>
|
Make it yours
|
||||||
<PageHeaderDescription>
|
</PageHeaderHeading>
|
||||||
Hand-picked themes that you can copy and paste into your apps.
|
<PageHeaderDescription>
|
||||||
</PageHeaderDescription>
|
Hand-picked themes that you can copy and paste into your apps.
|
||||||
</PageHeader>
|
</PageHeaderDescription>
|
||||||
</div>
|
|
||||||
<div class="px-4 pb-8 md:ml-auto md:pb-0">
|
<PageAction>
|
||||||
<div class="flex items-center space-x-2">
|
<InlineThemePicker class="gap-x-1 me-4 hidden lg:flex" :all-colors="allColors" />
|
||||||
<div class="hidden md:flex">
|
|
||||||
<div class="mr-4 hidden items-center space-x-1 lg:flex">
|
<Drawer>
|
||||||
<TooltipProvider
|
<DrawerTrigger as-child>
|
||||||
v-for="(color, index) in allColors.slice(0, 5)"
|
<Button variant="outline" class="md:hidden h-9 rounded-[0.5rem]">
|
||||||
:key="index"
|
<Paintbrush class="w-4 h-4 mr-2" />
|
||||||
>
|
Customize
|
||||||
<Tooltip>
|
</Button>
|
||||||
<TooltipTrigger as-child>
|
</DrawerTrigger>
|
||||||
<button
|
<DrawerContent class="p-6 pt-0">
|
||||||
:key="index"
|
<ThemeCustomizer :all-colors="allColors" />
|
||||||
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-border text-xs"
|
</DrawerContent>
|
||||||
:class="
|
</Drawer>
|
||||||
color === theme
|
|
||||||
? 'border-foreground'
|
<Popover>
|
||||||
: 'border-transparent'
|
<PopoverTrigger as-child>
|
||||||
"
|
<Button variant="outline" class="hidden md:flex h-9 rounded-[0.5rem]">
|
||||||
@click="setTheme(color)"
|
<Paintbrush class="w-4 h-4 mr-2" />
|
||||||
>
|
Customize
|
||||||
<span
|
</Button>
|
||||||
class="flex h-6 w-6 items-center justify-center rounded-full"
|
</PopoverTrigger>
|
||||||
:style="{ backgroundColor: colors[color][7].rgb }"
|
<PopoverContent :side-offset="8" align="end" class="w-96">
|
||||||
>
|
<ThemeCustomizer :all-colors="allColors" />
|
||||||
<RadixIconsCheck
|
</PopoverContent>
|
||||||
v-if="color === theme"
|
</Popover>
|
||||||
class="h-4 w-4 text-white"
|
|
||||||
/>
|
<Dialog>
|
||||||
</span>
|
<DialogTrigger as-child>
|
||||||
</button>
|
<Button class="h-9 ml-2 rounded-[0.5rem]">
|
||||||
</TooltipTrigger>
|
Copy code
|
||||||
<TooltipContent
|
</Button>
|
||||||
align="center"
|
</DialogTrigger>
|
||||||
:side-offset="1"
|
<DialogContent class="sm:max-w-[625px]">
|
||||||
class="capitalize"
|
<DialogHeader>
|
||||||
>
|
<DialogTitle>Theme</DialogTitle>
|
||||||
{{ allColors[index] }}
|
<DialogDescription>
|
||||||
</TooltipContent>
|
Copy and paste the following code into your CSS file.
|
||||||
</Tooltip>
|
</DialogDescription>
|
||||||
</TooltipProvider>
|
</DialogHeader>
|
||||||
</div>
|
<CustomizerCode />
|
||||||
<Popover>
|
</DialogContent>
|
||||||
<PopoverTrigger as-child>
|
</Dialog>
|
||||||
<Button variant="outline" class="h-9 rounded-[0.5rem]">
|
</PageAction>
|
||||||
<Paintbrush class="w-4 h-4 mr-2" />
|
</PageHeader>
|
||||||
Customize
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent :side-offset="8" align="end" class="w-96">
|
|
||||||
<div class="p-4">
|
|
||||||
<div class="grid space-y-1">
|
|
||||||
<h1 class="text-md text-foreground font-semibold">
|
|
||||||
Customize
|
|
||||||
</h1>
|
|
||||||
<p class="text-xs text-muted-foreground">
|
|
||||||
Pick a style and color for your components.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-1.5 pt-6">
|
|
||||||
<Label for="color" class="text-xs"> Color </Label>
|
|
||||||
<div class="grid grid-cols-3 gap-2 py-1.5">
|
|
||||||
<Button
|
|
||||||
v-for="(color, index) in allColors"
|
|
||||||
:key="index"
|
|
||||||
variant="outline"
|
|
||||||
class="h-8 justify-start px-3"
|
|
||||||
:class="
|
|
||||||
color === theme
|
|
||||||
? 'border-foreground border-2'
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
@click="setTheme(color)"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="h-5 w-5 rounded-full flex items-center justify-center"
|
|
||||||
:style="{ backgroundColor: colors[color][7].rgb }"
|
|
||||||
>
|
|
||||||
<RadixIconsCheck
|
|
||||||
v-if="color === theme"
|
|
||||||
class="h-3 w-3 text-white"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span class="ml-2 text-xs capitalize">
|
|
||||||
{{ color }}
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-1.5 pt-6">
|
|
||||||
<Label for="radius" class="text-xs"> Radius </Label>
|
|
||||||
<div class="grid grid-cols-5 gap-2 py-1.5">
|
|
||||||
<Button
|
|
||||||
v-for="(r, index) in RADII"
|
|
||||||
:key="index"
|
|
||||||
variant="outline"
|
|
||||||
class="h-8 justify-center px-3"
|
|
||||||
:class="
|
|
||||||
r === radius
|
|
||||||
? 'border-foreground border-2'
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
@click="setRadius(r)"
|
|
||||||
>
|
|
||||||
<span class="text-xs">
|
|
||||||
{{ r }}
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-1.5 pt-6">
|
|
||||||
<Label for="theme" class="text-xs"> Theme </Label>
|
|
||||||
|
|
||||||
<div class="flex space-x-2 py-1.5">
|
|
||||||
<Button
|
|
||||||
class="h-8"
|
|
||||||
variant="outline"
|
|
||||||
:class="{ 'border-2 border-foreground': !isDark }"
|
|
||||||
@click="isDark = false"
|
|
||||||
>
|
|
||||||
<RadixIconsSun class="w-4 h-4 mr-2" />
|
|
||||||
<span class="text-xs">Light</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
class="h-8"
|
|
||||||
variant="outline"
|
|
||||||
:class="{ 'border-2 border-foreground': isDark }"
|
|
||||||
@click="isDark = true"
|
|
||||||
>
|
|
||||||
<RadixIconsMoon class="w-4 h-4 mr-2" />
|
|
||||||
<span class="text-xs">Dark</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger as-child>
|
|
||||||
<Button class="h-9 ml-2 rounded-[0.5rem]">
|
|
||||||
Copy code
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent class="sm:max-w-[625px]">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Theme</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Copy and paste the following code into your CSS file.
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
<CustomizerCode />
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<section>
|
<section>
|
||||||
<slot />
|
<slot />
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
20
apps/www/.vitepress/theme/plugins/codewrapper.ts
Normal file
20
apps/www/.vitepress/theme/plugins/codewrapper.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { MarkdownRenderer } from 'vitepress'
|
||||||
|
|
||||||
|
export default function (md: MarkdownRenderer) {
|
||||||
|
const defaultFenceRenderer = md.renderer.rules.fence
|
||||||
|
if (!defaultFenceRenderer)
|
||||||
|
return
|
||||||
|
|
||||||
|
md.renderer.rules.fence = function (tokens, idx, options, env, self) {
|
||||||
|
// Check if this is a code block
|
||||||
|
const token = tokens[idx]
|
||||||
|
const isAllowedExtension = (token.info.includes('vue') || token.info.includes('astro') || token.info.includes('ts'))
|
||||||
|
if (token && token.tag === 'code' && isAllowedExtension) {
|
||||||
|
// Wrap the code block in CodeWrapper
|
||||||
|
return `<CodeWrapper>${defaultFenceRenderer(tokens, idx, options, env, self)}</CodeWrapper>`
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not a code block, return the default rendering
|
||||||
|
return defaultFenceRenderer(tokens, idx, options, env, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { dirname, resolve } from 'node:path'
|
import type { MarkdownRenderer } from 'vitepress'
|
||||||
import fs from 'node:fs'
|
import { parseProps } from './utils'
|
||||||
import type { MarkdownEnv, MarkdownRenderer } from 'vitepress'
|
|
||||||
import { generateDemoComponent, parseProps } from './utils'
|
|
||||||
|
|
||||||
export default function (md: MarkdownRenderer) {
|
export default function (md: MarkdownRenderer) {
|
||||||
function addRenderRule(type: string) {
|
function addRenderRule(type: string) {
|
||||||
|
|
@ -12,25 +10,9 @@ export default function (md: MarkdownRenderer) {
|
||||||
if (!content.match(/^<ComponentPreview\s/) || !content.endsWith('/>'))
|
if (!content.match(/^<ComponentPreview\s/) || !content.endsWith('/>'))
|
||||||
return defaultRender!(tokens, idx, options, env, self)
|
return defaultRender!(tokens, idx, options, env, self)
|
||||||
|
|
||||||
const { path } = env as MarkdownEnv
|
|
||||||
const props = parseProps(content)
|
const props = parseProps(content)
|
||||||
|
const { attrs } = props
|
||||||
const { name, attrs } = props
|
const demoScripts = `<ComponentPreview ${attrs ?? ''} v-bind='${JSON.stringify(props)}'></ComponentPreview>`.trim()
|
||||||
const pluginPath = dirname(__dirname)
|
|
||||||
const srcPath = resolve(pluginPath, '../../src/lib/registry/default/example/', `${name}.vue`).replace(/\\/g, '/')
|
|
||||||
|
|
||||||
if (!fs.existsSync(srcPath)) {
|
|
||||||
console.error(`rendering ${path}: ${srcPath} does not exist`)
|
|
||||||
return defaultRender!(tokens, idx, options, env, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
const demoScripts = generateDemoComponent(md, env, {
|
|
||||||
attrs,
|
|
||||||
props,
|
|
||||||
code: fs.readFileSync(srcPath, 'utf-8'),
|
|
||||||
path: srcPath,
|
|
||||||
})
|
|
||||||
|
|
||||||
return demoScripts
|
return demoScripts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// Credit to @hairyf https://github.com/hairyf/markdown-it-vitepress-demo
|
// Credit to @hairyf https://github.com/hairyf/markdown-it-vitepress-demo
|
||||||
|
|
||||||
import type { MarkdownEnv, MarkdownRenderer } from 'vitepress'
|
|
||||||
import { baseParse } from '@vue/compiler-core'
|
|
||||||
import type { AttributeNode, ElementNode } from '@vue/compiler-core'
|
import type { AttributeNode, ElementNode } from '@vue/compiler-core'
|
||||||
|
import { baseParse } from '@vue/compiler-core'
|
||||||
|
|
||||||
export interface GenerateOptions {
|
export interface GenerateOptions {
|
||||||
attrs?: string
|
attrs?: string
|
||||||
|
|
@ -11,36 +10,6 @@ export interface GenerateOptions {
|
||||||
code: string
|
code: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse(
|
|
||||||
md: MarkdownRenderer,
|
|
||||||
env: MarkdownEnv,
|
|
||||||
{ code, attrs: _attrs, props }: GenerateOptions,
|
|
||||||
) {
|
|
||||||
const highlightedHtml = md.options.highlight!(code, 'vue', _attrs || '')
|
|
||||||
const sfcTsHtml = highlightedHtml
|
|
||||||
|
|
||||||
const attrs
|
|
||||||
= `sfcTsCode="${encodeURIComponent(code)}"\n`
|
|
||||||
+ `sfcTsHtml="${encodeURIComponent(sfcTsHtml)}"\n`
|
|
||||||
+ `v-bind='${JSON.stringify(props)}'\n`
|
|
||||||
|
|
||||||
return {
|
|
||||||
attrs,
|
|
||||||
highlightedHtml,
|
|
||||||
sfcTsCode: code,
|
|
||||||
sfcTsHtml,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateDemoComponent(
|
|
||||||
md: MarkdownRenderer,
|
|
||||||
env: MarkdownEnv,
|
|
||||||
options: GenerateOptions,
|
|
||||||
) {
|
|
||||||
const { attrs } = parse(md, env, options)
|
|
||||||
return `<ComponentPreview \n${attrs}></ComponentPreview>`.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isUndefined(v: any): v is undefined {
|
export function isUndefined(v: any): v is undefined {
|
||||||
return v === undefined || v === null
|
return v === undefined || v === null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
|
--font-geist-sans: "geist-sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
|
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 240 10% 3.9%;
|
--foreground: 240 10% 3.9%;
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
|
|
@ -19,39 +21,75 @@
|
||||||
--muted-foreground: 240 3.8% 46.1%;
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
--accent: 240 4.8% 95.9%;
|
--accent: 240 4.8% 95.9%;
|
||||||
--accent-foreground: 240 5.9% 10%;
|
--accent-foreground: 240 5.9% 10%;
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 72.22% 50.59%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 240 5.9% 90%;
|
--border: 240 5.9% 90%;
|
||||||
--input: 240 5.9% 90%;
|
--input: 240 5.9% 90%;
|
||||||
--ring: 240 5% 64.9%;
|
--ring: 240 5% 64.9%;
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
--sidebar-background: 0 0% 98%;
|
||||||
--background: 240 10% 3.9%;
|
--sidebar-foreground: 240 5.3% 26.1%;
|
||||||
--foreground: 0 0% 98%;
|
--sidebar-primary: 240 5.9% 10%;
|
||||||
--card: 240 10% 3.9%;
|
--sidebar-primary-foreground: 0 0% 98%;
|
||||||
--card-foreground: 0 0% 98%;
|
--sidebar-accent: 240 4.8% 95.9%;
|
||||||
--popover: 240 10% 3.9%;
|
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||||
--popover-foreground: 0 0% 98%;
|
--sidebar-border: 220 13% 91%;
|
||||||
--primary: 0 0% 98%;
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
--primary-foreground: 240 5.9% 10%;
|
|
||||||
--secondary: 240 3.7% 15.9%;
|
|
||||||
--secondary-foreground: 0 0% 98%;
|
--vis-primary-color: var(--primary);
|
||||||
--muted: 240 3.7% 15.9%;
|
--vis-secondary-color: 160 81% 40%;
|
||||||
--muted-foreground: 240 5% 64.9%;
|
--vis-text-color: var(--muted-foreground);
|
||||||
--accent: 240 3.7% 15.9%;
|
|
||||||
--accent-foreground: 0 0% 98%;
|
|
||||||
--destructive: 0 62.8% 30.6%;
|
--vis-font-family: inherit !important;
|
||||||
--destructive-foreground: 0 85.7% 97.3%;
|
--vis-area-stroke-width: 2px !important;
|
||||||
--border: 240 3.7% 15.9%;
|
--vis-donut-central-label-text-color: hsl(var(--muted-foreground)) !important;
|
||||||
--input: 240 3.7% 15.9%;
|
--vis-tooltip-background-color: none !important;
|
||||||
--ring: 240 4.9% 83.9%;
|
--vis-tooltip-border-color: none !important;
|
||||||
}
|
--vis-tooltip-text-color: none !important;
|
||||||
|
--vis-tooltip-shadow-color: none !important;
|
||||||
|
--vis-tooltip-backdrop-filter: none !important;
|
||||||
|
--vis-tooltip-padding: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 240 10% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 240 10% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 240 10% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary: 0 0% 98%;
|
||||||
|
--primary-foreground: 240 5.9% 10%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 240 3.7% 15.9%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 240 3.7% 15.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 240 4.9% 83.9%;
|
||||||
|
|
||||||
|
--sidebar-background: 240 5.9% 10%;
|
||||||
|
--sidebar-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-primary: 224.3 76.3% 48%;
|
||||||
|
--sidebar-primary-foreground: 0 0% 100%;
|
||||||
|
--sidebar-accent: 240 3.7% 15.9%;
|
||||||
|
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-border: 240 3.7% 15.9%;
|
||||||
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: hsl(var(--border)) transparent;
|
||||||
}
|
}
|
||||||
html {
|
html {
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
|
|
@ -59,7 +97,9 @@
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground min-h-screen antialiased font-sans;
|
@apply bg-background text-foreground min-h-screen antialiased font-sans;
|
||||||
font-feature-settings: "rlig" 1, "calt" 1;
|
/* font-feature-settings: "rlig" 1, "calt" 1; */
|
||||||
|
font-synthesis-weight: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile tap highlight */
|
/* Mobile tap highlight */
|
||||||
|
|
@ -68,19 +108,16 @@
|
||||||
-webkit-tap-highlight-color: rgba(128, 128, 128, 0.5);
|
-webkit-tap-highlight-color: rgba(128, 128, 128, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* === Scrollbars === */
|
/* Font face Geist font */
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
@font-face {
|
||||||
@apply w-2;
|
font-family: "geist-sans";
|
||||||
@apply h-2;
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("/fonts/Geist/GeistVariableVF.woff2") format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
@apply !bg-muted;
|
|
||||||
}
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
@apply rounded-sm !bg-muted-foreground/30;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Firefox */
|
/* Firefox */
|
||||||
/* https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color#browser_compatibility */
|
/* https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color#browser_compatibility */
|
||||||
|
|
@ -92,14 +129,14 @@
|
||||||
scrollbar-color: hsl(215.4 16.3% 56.9% / 0.3);
|
scrollbar-color: hsl(215.4 16.3% 56.9% / 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-scrollbar::-webkit-scrollbar {
|
html.dark .shiki,
|
||||||
display: none;
|
html.dark .shiki span {
|
||||||
}
|
color: var(--shiki-dark);
|
||||||
|
}
|
||||||
.hide-scrollbar {
|
html:not(.dark) .shiki,
|
||||||
-ms-overflow-style: none;
|
html:not(.dark) .shiki span {
|
||||||
scrollbar-width: none;
|
color: var(--shiki-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.antialised {
|
.antialised {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
@ -116,9 +153,9 @@
|
||||||
|
|
||||||
.step:before {
|
.step:before {
|
||||||
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
|
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
|
||||||
@apply ml-[-50px] mt-[-4px];
|
@apply -ml-[50px] -mt-1;
|
||||||
content: counter(step);
|
content: counter(step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
|
|
@ -128,25 +165,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
div[class^="language-"] {
|
div[class^="language-"] {
|
||||||
@apply mb-4 mt-6 max-h-[650px] overflow-x-auto md:rounded-lg border !bg-zinc-950 dark:!bg-zinc-900
|
@apply mb-4 mt-6 max-h-[650px] overflow-x-auto md:rounded-lg border
|
||||||
}
|
}
|
||||||
pre {
|
pre {
|
||||||
@apply py-4;
|
@apply py-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre code {
|
pre code {
|
||||||
@apply relative font-mono text-sm ;
|
@apply relative font-mono text-sm ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-wrapper, code {
|
||||||
|
--vp-code-line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-wrapper {
|
||||||
|
@apply font-mono;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre code .line {
|
pre code .line {
|
||||||
@apply px-4 min-h-[1.5rem] !py-0.5 w-full inline-block;
|
@apply px-4 min-h-4 !py-0.5 w-full inline-block leading-[--vp-code-line-height];
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-number {
|
.line-number {
|
||||||
@apply min-h-[1.375rem] !text-sm !inline-block text-muted-foreground;
|
@apply !text-[.75rem] !inline-block text-muted-foreground leading-[--vp-code-line-height];
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-old(root),
|
::view-transition-old(root),
|
||||||
::view-transition-new(root) {
|
::view-transition-new(root) {
|
||||||
animation-duration: 0.3s;
|
animation-duration: 0.3s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
:root {
|
:root {
|
||||||
--shiki-color-text: #EEEEEE;
|
--shiki-foreground: #FFF8;
|
||||||
--shiki-color-background: #ffffff;
|
--shiki-color-background: #ffffff;
|
||||||
--shiki-token-constant: #ffffff;
|
--shiki-token-constant: #ffffff;
|
||||||
--shiki-token-string: #ffffff88;
|
--shiki-token-string: #ffffff88;
|
||||||
|
|
@ -7,7 +7,14 @@
|
||||||
--shiki-token-keyword: #ffffff88;
|
--shiki-token-keyword: #ffffff88;
|
||||||
--shiki-token-parameter: #AA0000;
|
--shiki-token-parameter: #AA0000;
|
||||||
--shiki-token-function: #ffffff;
|
--shiki-token-function: #ffffff;
|
||||||
--shiki-token-string-expression: #ffffff88;
|
--shiki-token-string-expression: #ebebeb;
|
||||||
--shiki-token-punctuation: #ffffff;
|
--shiki-token-punctuation: #ffffff;
|
||||||
--shiki-token-link: #EE0000;
|
--shiki-token-link: #EE0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shiki .highlighted-word {
|
||||||
|
border-radius: calc(var(--radius) - 2px);
|
||||||
|
border-color: rgba(63,63,70,.7);
|
||||||
|
background-color: rgba(63,63,70,.5);
|
||||||
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,11 @@
|
||||||
|
html {
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
.theme-zinc {
|
.theme-zinc {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 240 10% 3.9%;
|
--foreground: 240 10% 3.9%;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
|
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
|
||||||
--vp-code-bg: hsl(var(--muted));
|
--vp-code-bg: hsl(var(--muted));
|
||||||
--vp-c-divider: hsl(var(--muted));
|
--vp-c-divider: hsl(var(--muted));
|
||||||
|
--vp-code-block-color: #fff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -344,13 +345,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-doc [class*='language-'] code .highlighted {
|
.vp-doc [class*='language-'] code .highlighted {
|
||||||
background-color: hsl(240 3.7% 15.9%);
|
|
||||||
transition: background-color 0.5s;
|
transition: background-color 0.5s;
|
||||||
/* margin: 0 -24px;
|
/* margin: 0 -24px;
|
||||||
padding: 0 24px; */
|
padding: 0 24px; */
|
||||||
width: calc(100% + 2 * 24px);
|
width: calc(100% + 2 * 24px);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
@apply bg-[hsl(var(--muted))] dark:bg-[hsl(var(--muted))]
|
||||||
|
}
|
||||||
|
|
||||||
.vp-doc [class*='language-'] code .highlighted.error {
|
.vp-doc [class*='language-'] code .highlighted.error {
|
||||||
background-color: var(--vp-code-line-error-color);
|
background-color: var(--vp-code-line-error-color);
|
||||||
|
|
@ -414,7 +415,7 @@
|
||||||
|
|
||||||
.vp-doc div[class*='language-'].line-numbers-mode {
|
.vp-doc div[class*='language-'].line-numbers-mode {
|
||||||
/*rtl:ignore*/
|
/*rtl:ignore*/
|
||||||
padding-left: 32px;
|
padding-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-doc .line-numbers-wrapper {
|
.vp-doc .line-numbers-wrapper {
|
||||||
|
|
@ -566,4 +567,12 @@
|
||||||
|
|
||||||
.vp-external-link-icon::after {
|
.vp-external-link-icon::after {
|
||||||
content: '';
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.vp-doc [class*=language-] code {
|
||||||
|
color: var(--vp-code-block-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-mode pre code .line {
|
||||||
|
padding-left: 3rem !important;
|
||||||
}
|
}
|
||||||
13
apps/www/.vitepress/theme/types/colors.ts
Normal file
13
apps/www/.vitepress/theme/types/colors.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export type Color =
|
||||||
|
| 'zinc'
|
||||||
|
| 'slate'
|
||||||
|
| 'stone'
|
||||||
|
| 'gray'
|
||||||
|
| 'neutral'
|
||||||
|
| 'red'
|
||||||
|
| 'rose'
|
||||||
|
| 'orange'
|
||||||
|
| 'green'
|
||||||
|
| 'blue'
|
||||||
|
| 'yellow'
|
||||||
|
| 'violet'
|
||||||
219
apps/www/.vitepress/theme/utils/codeeditor.ts
Normal file
219
apps/www/.vitepress/theme/utils/codeeditor.ts
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
import type { Style } from '@/lib/registry/styles'
|
||||||
|
import sdk from '@stackblitz/sdk'
|
||||||
|
import { getParameters } from 'codesandbox/lib/api/define'
|
||||||
|
import { Index as demoIndex } from '../../../../www/__registry__'
|
||||||
|
// @ts-expect-error ?raw
|
||||||
|
import tailwindConfigRaw from '../../../tailwind.config?raw'
|
||||||
|
// @ts-expect-error ?raw
|
||||||
|
import cssRaw from '../../../../../packages/cli/test/fixtures/nuxt/assets/css/tailwind.css?raw'
|
||||||
|
|
||||||
|
export function makeCodeSandboxParams(componentName: string, style: Style, sources: Record<string, string>) {
|
||||||
|
let files: Record<string, any> = {}
|
||||||
|
files = constructFiles(componentName, style, sources)
|
||||||
|
files['.codesandbox/Dockerfile'] = {
|
||||||
|
content: 'FROM node:18',
|
||||||
|
}
|
||||||
|
return getParameters({ files, template: 'node' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeStackblitzParams(componentName: string, style: Style, sources: Record<string, string>) {
|
||||||
|
const files: Record<string, string> = {}
|
||||||
|
Object.entries(constructFiles(componentName, style, sources)).forEach(([k, v]) => (files[`${k}`] = typeof v.content === 'object' ? JSON.stringify(v.content, null, 2) : v.content))
|
||||||
|
|
||||||
|
return sdk.openProject({
|
||||||
|
title: `${componentName} - Radix Vue`,
|
||||||
|
files,
|
||||||
|
template: 'node',
|
||||||
|
}, {
|
||||||
|
newWindow: true,
|
||||||
|
openFile: ['src/App.vue'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const viteConfig = {
|
||||||
|
'vite.config.js': {
|
||||||
|
content: `import path from "path"
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
import tailwind from 'tailwindcss';
|
||||||
|
import autoprefixer from 'autoprefixer';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
css: {
|
||||||
|
postcss: {
|
||||||
|
plugins: [tailwind(), autoprefixer()],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [vue()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})`,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'index.html': {
|
||||||
|
content: `<!DOCTYPE html>
|
||||||
|
<html class="dark" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + Vue + TS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div vaul-drawer-wrapper id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function constructFiles(componentName: string, style: Style, sources: Record<string, string>) {
|
||||||
|
const componentsJson = {
|
||||||
|
style,
|
||||||
|
tailwind: {
|
||||||
|
config: 'tailwind.config.js',
|
||||||
|
css: 'src/assets/index.css',
|
||||||
|
baseColor: 'zinc',
|
||||||
|
cssVariables: true,
|
||||||
|
},
|
||||||
|
aliases: {
|
||||||
|
utils: '@/utils',
|
||||||
|
components: '@/components',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconPackage = style === 'default' ? 'lucide-vue-next' : '@radix-icons/vue'
|
||||||
|
const dependencies = {
|
||||||
|
'vue': 'latest',
|
||||||
|
'radix-vue': 'latest',
|
||||||
|
'@radix-ui/colors': 'latest',
|
||||||
|
'clsx': 'latest',
|
||||||
|
'class-variance-authority': 'latest',
|
||||||
|
'tailwind-merge': 'latest',
|
||||||
|
'tailwindcss-animate': 'latest',
|
||||||
|
[iconPackage]: 'latest',
|
||||||
|
'shadcn-vue': 'latest',
|
||||||
|
'typescript': 'latest',
|
||||||
|
'vaul-vue': 'latest',
|
||||||
|
'vue-sonner': 'latest',
|
||||||
|
'@unovis/vue': 'latest',
|
||||||
|
'@unovis/ts': 'latest',
|
||||||
|
}
|
||||||
|
|
||||||
|
const devDependencies = {
|
||||||
|
'vite': 'latest',
|
||||||
|
'@vitejs/plugin-vue': 'latest',
|
||||||
|
'vue-tsc': 'latest',
|
||||||
|
'tailwindcss': 'latest',
|
||||||
|
'autoprefixer': 'latest',
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have static replace here as this is only showing for code reproduction, doesn't need dynamic codeConfig
|
||||||
|
const transformImportPath = (code: string) => {
|
||||||
|
let parsed = code
|
||||||
|
parsed = parsed.replaceAll(`@/lib/registry/${style}`, '@/components')
|
||||||
|
parsed = parsed.replaceAll('@/lib/utils', '@/utils')
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
|
||||||
|
const componentFiles = Object.keys(sources).filter(key => key.endsWith('.vue') && key !== 'index.vue')
|
||||||
|
const components: Record<string, any> = {}
|
||||||
|
componentFiles.forEach((i) => {
|
||||||
|
components[`src/${i}`] = {
|
||||||
|
isBinary: false,
|
||||||
|
content: transformImportPath(sources[i]),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-expect-error componentName might not exist in Index
|
||||||
|
const registryDependencies = demoIndex[style][componentName as any]?.registryDependencies?.filter(i => i !== 'utils')
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'package.json': {
|
||||||
|
content: {
|
||||||
|
name: `shadcn-vue-${componentName.toLowerCase().replace(/ /g, '-')}`,
|
||||||
|
scripts: { start: `shadcn-vue add ${registryDependencies.join(' ')} -y && vite` },
|
||||||
|
dependencies,
|
||||||
|
devDependencies,
|
||||||
|
},
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'components.json': {
|
||||||
|
content: componentsJson,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
...viteConfig,
|
||||||
|
'tailwind.config.js': {
|
||||||
|
content: tailwindConfigRaw,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'tsconfig.json': {
|
||||||
|
content: `{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/utils.ts': {
|
||||||
|
isBinary: false,
|
||||||
|
content: `import { type ClassValue, clsx } from 'clsx'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
'src/assets/index.css': {
|
||||||
|
content: cssRaw,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/main.ts': {
|
||||||
|
content: `import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import './assets/global.css';
|
||||||
|
import './assets/index.css';
|
||||||
|
|
||||||
|
createApp(App).mount('#app')`,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/App.vue': {
|
||||||
|
isBinary: false,
|
||||||
|
content: sources['index.vue'],
|
||||||
|
},
|
||||||
|
...components,
|
||||||
|
'src/assets/global.css': {
|
||||||
|
content: `body {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 120px;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: hsl(var(--background));
|
||||||
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
font-feature-settings: "rlig" 1, "calt" 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
@apply w-full flex items-center justify-center px-12;
|
||||||
|
}`,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
> Files inside this directory is autogenerated by `./scripts/build-registry.ts`. **Do not edit them manually.**
|
> Files inside this directory is autogenerated by `./scripts/build-registry.ts`. **Do not edit them manually.**
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "www",
|
"name": "www",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.1",
|
"version": "0.11.3",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
|
|
@ -9,45 +9,73 @@
|
||||||
"dev": "vitepress dev",
|
"dev": "vitepress dev",
|
||||||
"build": "vitepress build",
|
"build": "vitepress build",
|
||||||
"preview": "vitepress preview",
|
"preview": "vitepress preview",
|
||||||
"build:registry": "tsx ./scripts/build-registry.ts"
|
"typecheck": "vue-tsc",
|
||||||
|
"typecheck:registry": "vue-tsc -p tsconfig.registry.json",
|
||||||
|
"build:registry": "tsx ./scripts/build-registry.ts",
|
||||||
|
"build:registry-strict": "pnpm typecheck:registry && tsx ./scripts/build-registry.ts",
|
||||||
|
"docs:gen": "tsx ./scripts/autogen.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@morev/vue-transitions": "^2.3.6",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@tanstack/vue-table": "^8.9.9",
|
"@internationalized/date": "^3.5.5",
|
||||||
"@unovis/ts": "^1.2.1",
|
"@radix-icons/vue": "^1.0.0",
|
||||||
"@vueuse/core": "^10.4.1",
|
"@stackblitz/sdk": "^1.11.0",
|
||||||
|
"@tanstack/vue-table": "^8.20.5",
|
||||||
|
"@unovis/ts": "^1.4.4",
|
||||||
|
"@unovis/vue": "^1.4.4",
|
||||||
|
"@vee-validate/zod": "^4.13.2",
|
||||||
|
"@vueuse/core": "^11.1.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.1.1",
|
||||||
"date-fns": "^2.30.0",
|
"codesandbox": "^2.2.3",
|
||||||
"lucide-vue-next": "^0.276.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"embla-carousel-autoplay": "^8.3.0",
|
||||||
|
"embla-carousel-vue": "^8.3.0",
|
||||||
|
"lucide-vue-next": "^0.441.0",
|
||||||
|
"magic-string": "^0.30.11",
|
||||||
|
"radix-vue": "catalog:",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"v-calendar": "^3.0.3",
|
"v-calendar": "^3.1.2",
|
||||||
"vue": "^3.3.4",
|
"vaul-vue": "^0.2.0",
|
||||||
"vue-wrap-balancer": "^1.1.3",
|
"vee-validate": "4.13.2",
|
||||||
"zod": "^3.22.2"
|
"vue": "^3.5.6",
|
||||||
|
"vue-sonner": "^1.1.5",
|
||||||
|
"vue-wrap-balancer": "^1.2.1",
|
||||||
|
"zod": "catalog:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/radix-icons": "^1.1.11",
|
"@babel/traverse": "^7.25.6",
|
||||||
"@iconify-json/tabler": "^1.1.89",
|
"@iconify-json/gravity-ui": "^1.1.3",
|
||||||
"@iconify/json": "^2.2.108",
|
"@iconify-json/lucide": "^1.1.198",
|
||||||
"@iconify/vue": "^4.1.1",
|
"@iconify-json/ph": "^1.1.13",
|
||||||
"@types/lodash.template": "^4.5.1",
|
"@iconify-json/radix-icons": "^1.1.14",
|
||||||
"@types/node": "^20.6.0",
|
"@iconify-json/ri": "^1.1.21",
|
||||||
"@vitejs/plugin-vue": "^4.3.4",
|
"@iconify-json/simple-icons": "^1.1.108",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
"@iconify-json/tabler": "^1.1.116",
|
||||||
"@vue/compiler-core": "^3.3.4",
|
"@iconify/vue": "^4.1.2",
|
||||||
"@vue/compiler-dom": "^3.3.4",
|
"@oxc-parser/wasm": "catalog:",
|
||||||
"autoprefixer": "^10.4.15",
|
"@shikijs/transformers": "^1.17.7",
|
||||||
"lodash.template": "^4.5.0",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"radix-vue": "^0.2.2",
|
"@types/node": "^22.5.5",
|
||||||
"rimraf": "^5.0.1",
|
"@vitejs/plugin-vue": "^5.1.4",
|
||||||
"tailwind-merge": "^1.14.0",
|
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"@vue/compiler-core": "^3.5.6",
|
||||||
"tsx": "^3.12.10",
|
"@vue/compiler-dom": "^3.5.6",
|
||||||
"typescript": "^5.2.2",
|
"@vue/tsconfig": "^0.5.1",
|
||||||
"unplugin-icons": "^0.17.0",
|
"autoprefixer": "^10.4.20",
|
||||||
"vite": "^4.4.9",
|
"fast-glob": "^3.3.2",
|
||||||
"vitepress": "^1.0.0-rc.13",
|
"lodash-es": "^4.17.21",
|
||||||
"vue-tsc": "^1.8.11"
|
"markdown-it": "^14.1.0",
|
||||||
|
"pathe": "^1.1.2",
|
||||||
|
"rimraf": "^6.0.1",
|
||||||
|
"shiki": "^1.22.1",
|
||||||
|
"tailwind-merge": "^2.5.2",
|
||||||
|
"tailwindcss": "^3.4.12",
|
||||||
|
"tsx": "^4.19.1",
|
||||||
|
"typescript": "catalog:",
|
||||||
|
"unplugin-icons": "^0.19.3",
|
||||||
|
"vitepress": "^1.3.4",
|
||||||
|
"vue-component-meta": "^2.1.6",
|
||||||
|
"vue-tsc": "^2.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
150
apps/www/scripts/autogen.ts
Normal file
150
apps/www/scripts/autogen.ts
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
import type { ComponentMeta, MetaCheckerOptions, PropertyMeta, PropertyMetaSchema } from 'vue-component-meta'
|
||||||
|
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
||||||
|
import { join, parse, resolve } from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import fg from 'fast-glob'
|
||||||
|
import MarkdownIt from 'markdown-it'
|
||||||
|
import { createComponentMetaChecker } from 'vue-component-meta'
|
||||||
|
|
||||||
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
||||||
|
|
||||||
|
const md = new MarkdownIt()
|
||||||
|
|
||||||
|
const ROOTPATH = '../'
|
||||||
|
const OUTPUTPATH = '../src/content/meta'
|
||||||
|
|
||||||
|
const checkerOptions: MetaCheckerOptions = {
|
||||||
|
forceUseTs: true,
|
||||||
|
printer: { newLine: 1 },
|
||||||
|
}
|
||||||
|
|
||||||
|
const tsconfigChecker = createComponentMetaChecker(
|
||||||
|
resolve(__dirname, ROOTPATH, 'tsconfig.registry.json'),
|
||||||
|
checkerOptions,
|
||||||
|
)
|
||||||
|
|
||||||
|
const components = fg.sync(['chart/**/*.vue', 'chart*/**/*.vue'], {
|
||||||
|
cwd: resolve(__dirname, ROOTPATH, 'src/lib/registry/default/ui/'),
|
||||||
|
absolute: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
components.forEach((componentPath) => {
|
||||||
|
try {
|
||||||
|
const componentName = parse(componentPath).name
|
||||||
|
const meta = parseMeta(tsconfigChecker.getComponentMeta(componentPath))
|
||||||
|
|
||||||
|
const metaDirPath = resolve(__dirname, OUTPUTPATH)
|
||||||
|
// if meta dir doesn't exist create
|
||||||
|
if (!existsSync(metaDirPath))
|
||||||
|
mkdirSync(metaDirPath)
|
||||||
|
|
||||||
|
const metaMdFilePath = join(metaDirPath, `${componentName}.md`)
|
||||||
|
|
||||||
|
let parsedString = '<!-- This file was automatic generated. Do not edit it manually -->\n\n'
|
||||||
|
if (meta.props.length)
|
||||||
|
parsedString += `<APITable :type="'prop'" :data="${JSON.stringify(meta.props, null, 2).replace(/"/g, '\'')}" />\n`
|
||||||
|
|
||||||
|
if (meta.events.length)
|
||||||
|
parsedString += `\n<APITable :type="'emit'" :data="${JSON.stringify(meta.events, null, 2).replace(/"/g, '\'')}" />\n`
|
||||||
|
|
||||||
|
if (meta.slots.length)
|
||||||
|
parsedString += `\n<APITable :type="'slot'" :data="${JSON.stringify(meta.slots, null, 2).replace(/"/g, '\'')}" />\n`
|
||||||
|
|
||||||
|
if (meta.methods.length)
|
||||||
|
parsedString += `\n<APITable :type="'method'" :data="${JSON.stringify(meta.methods, null, 2).replace(/"/g, '\'')}" />\n`
|
||||||
|
|
||||||
|
writeFileSync(metaMdFilePath, parsedString)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function parseTypeFromSchema(schema: PropertyMetaSchema): string {
|
||||||
|
if (typeof schema === 'object' && (schema.kind === 'enum' || schema.kind === 'array')) {
|
||||||
|
const isFlatEnum = schema.schema?.every(val => typeof val === 'string')
|
||||||
|
const enumValue = schema?.schema?.filter(i => i !== 'undefined') ?? []
|
||||||
|
|
||||||
|
if (isFlatEnum && /^[A-Z]/.test(schema.type))
|
||||||
|
return enumValue.join(' | ')
|
||||||
|
else if (typeof schema.schema?.[0] === 'object' && schema.schema?.[0].kind === 'enum')
|
||||||
|
return schema.schema.map((s: PropertyMetaSchema) => parseTypeFromSchema(s)).join(' | ')
|
||||||
|
else
|
||||||
|
return schema.type
|
||||||
|
}
|
||||||
|
else if (typeof schema === 'object' && schema.kind === 'object') {
|
||||||
|
return schema.type
|
||||||
|
}
|
||||||
|
else if (typeof schema === 'string') {
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
function parseMeta(meta: ComponentMeta) {
|
||||||
|
const props = meta.props
|
||||||
|
// Exclude global props
|
||||||
|
.filter(prop => !prop.global)
|
||||||
|
.map((prop) => {
|
||||||
|
let defaultValue = prop.default
|
||||||
|
const { name, description, required } = prop
|
||||||
|
|
||||||
|
if (name === 'as')
|
||||||
|
defaultValue = defaultValue ?? '"div"'
|
||||||
|
|
||||||
|
if (defaultValue === 'undefined')
|
||||||
|
defaultValue = undefined
|
||||||
|
|
||||||
|
return ({
|
||||||
|
name,
|
||||||
|
description: md.render(description),
|
||||||
|
type: prop.type.replace(/\s*\|\s*undefined/g, ''),
|
||||||
|
required,
|
||||||
|
default: defaultValue ?? undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const events = meta.events
|
||||||
|
.map((event) => {
|
||||||
|
const { name, type } = event
|
||||||
|
return ({
|
||||||
|
name,
|
||||||
|
type: type.replace(/\s*\|\s*undefined/g, ''),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const defaultSlot = meta.slots?.[0]
|
||||||
|
const slots: { name: string, description: string, type: string }[] = []
|
||||||
|
|
||||||
|
if (defaultSlot && defaultSlot.type !== '{}') {
|
||||||
|
const schema = defaultSlot.schema
|
||||||
|
if (typeof schema === 'object' && schema.schema) {
|
||||||
|
Object.values(schema.schema).forEach((childMeta: PropertyMeta) => {
|
||||||
|
slots.push({
|
||||||
|
name: childMeta.name,
|
||||||
|
description: md.render(childMeta.description),
|
||||||
|
type: parseTypeFromSchema(childMeta.schema),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exposed method
|
||||||
|
const methods = meta.exposed
|
||||||
|
.filter(expose => typeof expose.schema === 'object' && expose.schema.kind === 'event')
|
||||||
|
.map(expose => ({
|
||||||
|
name: expose.name,
|
||||||
|
description: md.render(expose.description),
|
||||||
|
type: expose.type,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return {
|
||||||
|
props,
|
||||||
|
events,
|
||||||
|
slots,
|
||||||
|
methods,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import path, { basename } from 'node:path'
|
import path, { basename } from 'node:path'
|
||||||
import template from 'lodash.template'
|
import { template } from 'lodash-es'
|
||||||
import { rimraf } from 'rimraf'
|
import { rimraf } from 'rimraf'
|
||||||
|
|
||||||
import { colorMapping, colors } from '../src/lib/registry/colors'
|
import { colorMapping, colors } from '../src/lib/registry/colors'
|
||||||
|
import { buildRegistry } from '../src/lib/registry/registry'
|
||||||
import { registrySchema } from '../src/lib/registry/schema'
|
import { registrySchema } from '../src/lib/registry/schema'
|
||||||
import { styles } from '../src/lib/registry/styles'
|
import { styles } from '../src/lib/registry/styles'
|
||||||
import { themes } from '../src/lib/registry/themes'
|
import { themes } from '../src/lib/registry/themes'
|
||||||
import { buildRegistry } from '../src/lib/registry/registry'
|
|
||||||
|
|
||||||
const REGISTRY_PATH = path.join(process.cwd(), 'src/public/registry')
|
const REGISTRY_PATH = path.join(process.cwd(), 'src/public/registry')
|
||||||
|
|
||||||
|
|
@ -40,15 +40,13 @@ for (const style of styles) {
|
||||||
file => `../src/lib/registry/${style.name}/${file}`,
|
file => `../src/lib/registry/${style.name}/${file}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const type = item.type.split(':')[1]
|
// const type = item.type.split(':')[1]
|
||||||
index += `
|
index += `
|
||||||
"${item.name}": {
|
"${item.name}": {
|
||||||
name: "${item.name}",
|
name: "${item.name}",
|
||||||
type: "${item.type}",
|
type: "${item.type}",
|
||||||
registryDependencies: ${JSON.stringify(item.registryDependencies)},
|
registryDependencies: ${JSON.stringify(item.registryDependencies)},
|
||||||
component: () => import("../src/lib/registry/${style.name}/${type}/${
|
component: () => import("${resolveFiles[0]}").then((m) => m.default),
|
||||||
item.name
|
|
||||||
}.vue").then((m) => m.default),
|
|
||||||
files: [${resolveFiles.map(file => `"${file}"`)}],
|
files: [${resolveFiles.map(file => `"${file}"`)}],
|
||||||
},`
|
},`
|
||||||
}
|
}
|
||||||
|
|
@ -68,6 +66,8 @@ fs.writeFileSync(path.join(process.cwd(), '__registry__/index.ts'), index)
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Build registry/styles/[style]/[name].json.
|
// Build registry/styles/[style]/[name].json.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
const newLine = '\n'
|
||||||
|
|
||||||
for (const style of styles) {
|
for (const style of styles) {
|
||||||
const targetPath = path.join(REGISTRY_PATH, 'styles', style.name)
|
const targetPath = path.join(REGISTRY_PATH, 'styles', style.name)
|
||||||
|
|
||||||
|
|
@ -80,10 +80,20 @@ for (const style of styles) {
|
||||||
continue
|
continue
|
||||||
|
|
||||||
const files = item.files?.map((file) => {
|
const files = item.files?.map((file) => {
|
||||||
const content = fs.readFileSync(
|
let content: string = ''
|
||||||
path.join(process.cwd(), 'src/lib/registry', style.name, file),
|
|
||||||
'utf8',
|
try {
|
||||||
)
|
content = fs.readFileSync(
|
||||||
|
path.join(process.cwd(), 'src/lib/registry', style.name, file),
|
||||||
|
'utf8',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(`'${file}' is missing`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace Windows-style newlines with Unix-style newlines
|
||||||
|
content = content.replace(/\r\n/g, newLine)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: basename(file),
|
name: basename(file),
|
||||||
|
|
@ -96,9 +106,11 @@ for (const style of styles) {
|
||||||
files,
|
files,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const payloadStr = `${JSON.stringify(payload, null, 2).replace(/\r\n/g, newLine)}\n`
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(targetPath, `${item.name}.json`),
|
path.join(targetPath, `${item.name}.json`),
|
||||||
JSON.stringify(payload, null, 2),
|
payloadStr,
|
||||||
'utf8',
|
'utf8',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -190,73 +202,73 @@ export const BASE_STYLES = `@tailwind base;
|
||||||
export const BASE_STYLES_WITH_VARIABLES = `@tailwind base;
|
export const BASE_STYLES_WITH_VARIABLES = `@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: <%- colors.light["background"] %>;
|
--background: <%- colors.light["background"] %>;
|
||||||
--foreground: <%- colors.light["foreground"] %>;
|
--foreground: <%- colors.light["foreground"] %>;
|
||||||
|
|
||||||
--muted: <%- colors.light["muted"] %>;
|
--muted: <%- colors.light["muted"] %>;
|
||||||
--muted-foreground: <%- colors.light["muted-foreground"] %>;
|
--muted-foreground: <%- colors.light["muted-foreground"] %>;
|
||||||
|
|
||||||
--popover: <%- colors.light["popover"] %>;
|
--popover: <%- colors.light["popover"] %>;
|
||||||
--popover-foreground: <%- colors.light["popover-foreground"] %>;
|
--popover-foreground: <%- colors.light["popover-foreground"] %>;
|
||||||
|
|
||||||
--card: <%- colors.light["card"] %>;
|
--card: <%- colors.light["card"] %>;
|
||||||
--card-foreground: <%- colors.light["card-foreground"] %>;
|
--card-foreground: <%- colors.light["card-foreground"] %>;
|
||||||
|
|
||||||
--border: <%- colors.light["border"] %>;
|
--border: <%- colors.light["border"] %>;
|
||||||
--input: <%- colors.light["input"] %>;
|
--input: <%- colors.light["input"] %>;
|
||||||
|
|
||||||
--primary: <%- colors.light["primary"] %>;
|
--primary: <%- colors.light["primary"] %>;
|
||||||
--primary-foreground: <%- colors.light["primary-foreground"] %>;
|
--primary-foreground: <%- colors.light["primary-foreground"] %>;
|
||||||
|
|
||||||
--secondary: <%- colors.light["secondary"] %>;
|
--secondary: <%- colors.light["secondary"] %>;
|
||||||
--secondary-foreground: <%- colors.light["secondary-foreground"] %>;
|
--secondary-foreground: <%- colors.light["secondary-foreground"] %>;
|
||||||
|
|
||||||
--accent: <%- colors.light["accent"] %>;
|
--accent: <%- colors.light["accent"] %>;
|
||||||
--accent-foreground: <%- colors.light["accent-foreground"] %>;
|
--accent-foreground: <%- colors.light["accent-foreground"] %>;
|
||||||
|
|
||||||
--destructive: <%- colors.light["destructive"] %>;
|
--destructive: <%- colors.light["destructive"] %>;
|
||||||
--destructive-foreground: <%- colors.light["destructive-foreground"] %>;
|
--destructive-foreground: <%- colors.light["destructive-foreground"] %>;
|
||||||
|
|
||||||
--ring: <%- colors.light["ring"] %>;
|
--ring: <%- colors.light["ring"] %>;
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: <%- colors.dark["background"] %>;
|
--background: <%- colors.dark["background"] %>;
|
||||||
--foreground: <%- colors.dark["foreground"] %>;
|
--foreground: <%- colors.dark["foreground"] %>;
|
||||||
|
|
||||||
--muted: <%- colors.dark["muted"] %>;
|
--muted: <%- colors.dark["muted"] %>;
|
||||||
--muted-foreground: <%- colors.dark["muted-foreground"] %>;
|
--muted-foreground: <%- colors.dark["muted-foreground"] %>;
|
||||||
|
|
||||||
--popover: <%- colors.dark["popover"] %>;
|
--popover: <%- colors.dark["popover"] %>;
|
||||||
--popover-foreground: <%- colors.dark["popover-foreground"] %>;
|
--popover-foreground: <%- colors.dark["popover-foreground"] %>;
|
||||||
|
|
||||||
--card: <%- colors.dark["card"] %>;
|
--card: <%- colors.dark["card"] %>;
|
||||||
--card-foreground: <%- colors.dark["card-foreground"] %>;
|
--card-foreground: <%- colors.dark["card-foreground"] %>;
|
||||||
|
|
||||||
--border: <%- colors.dark["border"] %>;
|
--border: <%- colors.dark["border"] %>;
|
||||||
--input: <%- colors.dark["input"] %>;
|
--input: <%- colors.dark["input"] %>;
|
||||||
|
|
||||||
--primary: <%- colors.dark["primary"] %>;
|
--primary: <%- colors.dark["primary"] %>;
|
||||||
--primary-foreground: <%- colors.dark["primary-foreground"] %>;
|
--primary-foreground: <%- colors.dark["primary-foreground"] %>;
|
||||||
|
|
||||||
--secondary: <%- colors.dark["secondary"] %>;
|
--secondary: <%- colors.dark["secondary"] %>;
|
||||||
--secondary-foreground: <%- colors.dark["secondary-foreground"] %>;
|
--secondary-foreground: <%- colors.dark["secondary-foreground"] %>;
|
||||||
|
|
||||||
--accent: <%- colors.dark["accent"] %>;
|
--accent: <%- colors.dark["accent"] %>;
|
||||||
--accent-foreground: <%- colors.dark["accent-foreground"] %>;
|
--accent-foreground: <%- colors.dark["accent-foreground"] %>;
|
||||||
|
|
||||||
--destructive: <%- colors.dark["destructive"] %>;
|
--destructive: <%- colors.dark["destructive"] %>;
|
||||||
--destructive-foreground: <%- colors.dark["destructive-foreground"] %>;
|
--destructive-foreground: <%- colors.dark["destructive-foreground"] %>;
|
||||||
|
|
||||||
--ring: <%- colors.dark["ring"] %>;
|
--ring: <%- colors.dark["ring"] %>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
|
@ -277,8 +289,8 @@ for (const baseColor of ['slate', 'gray', 'zinc', 'neutral', 'stone', 'lime']) {
|
||||||
for (const [key, value] of Object.entries(values)) {
|
for (const [key, value] of Object.entries(values)) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
const resolvedColor = value.replace(
|
const resolvedColor = value.replace(
|
||||||
/{{base}}-/g,
|
/\{\{base\}\}-/g,
|
||||||
`${baseColor}-`,
|
`${baseColor}-`,
|
||||||
)
|
)
|
||||||
base.inlineColors[mode][key] = resolvedColor
|
base.inlineColors[mode][key] = resolvedColor
|
||||||
|
|
||||||
|
|
@ -314,68 +326,68 @@ export const THEME_STYLES_WITH_VARIABLES = `
|
||||||
.theme-<%- theme %> {
|
.theme-<%- theme %> {
|
||||||
--background: <%- colors.light["background"] %>;
|
--background: <%- colors.light["background"] %>;
|
||||||
--foreground: <%- colors.light["foreground"] %>;
|
--foreground: <%- colors.light["foreground"] %>;
|
||||||
|
|
||||||
--muted: <%- colors.light["muted"] %>;
|
--muted: <%- colors.light["muted"] %>;
|
||||||
--muted-foreground: <%- colors.light["muted-foreground"] %>;
|
--muted-foreground: <%- colors.light["muted-foreground"] %>;
|
||||||
|
|
||||||
--popover: <%- colors.light["popover"] %>;
|
--popover: <%- colors.light["popover"] %>;
|
||||||
--popover-foreground: <%- colors.light["popover-foreground"] %>;
|
--popover-foreground: <%- colors.light["popover-foreground"] %>;
|
||||||
|
|
||||||
--card: <%- colors.light["card"] %>;
|
--card: <%- colors.light["card"] %>;
|
||||||
--card-foreground: <%- colors.light["card-foreground"] %>;
|
--card-foreground: <%- colors.light["card-foreground"] %>;
|
||||||
|
|
||||||
--border: <%- colors.light["border"] %>;
|
--border: <%- colors.light["border"] %>;
|
||||||
--input: <%- colors.light["input"] %>;
|
--input: <%- colors.light["input"] %>;
|
||||||
|
|
||||||
--primary: <%- colors.light["primary"] %>;
|
--primary: <%- colors.light["primary"] %>;
|
||||||
--primary-foreground: <%- colors.light["primary-foreground"] %>;
|
--primary-foreground: <%- colors.light["primary-foreground"] %>;
|
||||||
|
|
||||||
--secondary: <%- colors.light["secondary"] %>;
|
--secondary: <%- colors.light["secondary"] %>;
|
||||||
--secondary-foreground: <%- colors.light["secondary-foreground"] %>;
|
--secondary-foreground: <%- colors.light["secondary-foreground"] %>;
|
||||||
|
|
||||||
--accent: <%- colors.light["accent"] %>;
|
--accent: <%- colors.light["accent"] %>;
|
||||||
--accent-foreground: <%- colors.light["accent-foreground"] %>;
|
--accent-foreground: <%- colors.light["accent-foreground"] %>;
|
||||||
|
|
||||||
--destructive: <%- colors.light["destructive"] %>;
|
--destructive: <%- colors.light["destructive"] %>;
|
||||||
--destructive-foreground: <%- colors.light["destructive-foreground"] %>;
|
--destructive-foreground: <%- colors.light["destructive-foreground"] %>;
|
||||||
|
|
||||||
--ring: <%- colors.light["ring"] %>;
|
--ring: <%- colors.light["ring"] %>;
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .theme-<%- theme %> {
|
.dark .theme-<%- theme %> {
|
||||||
--background: <%- colors.dark["background"] %>;
|
--background: <%- colors.dark["background"] %>;
|
||||||
--foreground: <%- colors.dark["foreground"] %>;
|
--foreground: <%- colors.dark["foreground"] %>;
|
||||||
|
|
||||||
--muted: <%- colors.dark["muted"] %>;
|
--muted: <%- colors.dark["muted"] %>;
|
||||||
--muted-foreground: <%- colors.dark["muted-foreground"] %>;
|
--muted-foreground: <%- colors.dark["muted-foreground"] %>;
|
||||||
|
|
||||||
--popover: <%- colors.dark["popover"] %>;
|
--popover: <%- colors.dark["popover"] %>;
|
||||||
--popover-foreground: <%- colors.dark["popover-foreground"] %>;
|
--popover-foreground: <%- colors.dark["popover-foreground"] %>;
|
||||||
|
|
||||||
--card: <%- colors.dark["card"] %>;
|
--card: <%- colors.dark["card"] %>;
|
||||||
--card-foreground: <%- colors.dark["card-foreground"] %>;
|
--card-foreground: <%- colors.dark["card-foreground"] %>;
|
||||||
|
|
||||||
--border: <%- colors.dark["border"] %>;
|
--border: <%- colors.dark["border"] %>;
|
||||||
--input: <%- colors.dark["input"] %>;
|
--input: <%- colors.dark["input"] %>;
|
||||||
|
|
||||||
--primary: <%- colors.dark["primary"] %>;
|
--primary: <%- colors.dark["primary"] %>;
|
||||||
--primary-foreground: <%- colors.dark["primary-foreground"] %>;
|
--primary-foreground: <%- colors.dark["primary-foreground"] %>;
|
||||||
|
|
||||||
--secondary: <%- colors.dark["secondary"] %>;
|
--secondary: <%- colors.dark["secondary"] %>;
|
||||||
--secondary-foreground: <%- colors.dark["secondary-foreground"] %>;
|
--secondary-foreground: <%- colors.dark["secondary-foreground"] %>;
|
||||||
|
|
||||||
--accent: <%- colors.dark["accent"] %>;
|
--accent: <%- colors.dark["accent"] %>;
|
||||||
--accent-foreground: <%- colors.dark["accent-foreground"] %>;
|
--accent-foreground: <%- colors.dark["accent-foreground"] %>;
|
||||||
|
|
||||||
--destructive: <%- colors.dark["destructive"] %>;
|
--destructive: <%- colors.dark["destructive"] %>;
|
||||||
--destructive-foreground: <%- colors.dark["destructive-foreground"] %>;
|
--destructive-foreground: <%- colors.dark["destructive-foreground"] %>;
|
||||||
|
|
||||||
--ring: <%- colors.dark["ring"] %>;
|
--ring: <%- colors.dark["ring"] %>;
|
||||||
}`
|
}`
|
||||||
|
|
||||||
const themeCSS = []
|
const themeCSS: Array<string> = []
|
||||||
for (const theme of themes) {
|
for (const theme of themes) {
|
||||||
themeCSS.push(
|
themeCSS.push(
|
||||||
template(THEME_STYLES_WITH_VARIABLES)({
|
template(THEME_STYLES_WITH_VARIABLES)({
|
||||||
|
|
@ -391,4 +403,4 @@ fs.writeFileSync(
|
||||||
'utf8',
|
'utf8',
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log('✅ Done!')
|
console.log('✅ Done!!')
|
||||||
|
|
|
||||||
176
apps/www/src/assets/diagrams.drawio
Normal file
176
apps/www/src/assets/diagrams.drawio
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
<mxfile host="app.diagrams.net" modified="2024-03-15T08:14:00.888Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0" etag="eUNOuIh_rCPXdI6LG0BE" version="24.0.6" type="device">
|
||||||
|
<diagram name="Page-1" id="10a91c8b-09ff-31b1-d368-03940ed4cc9e">
|
||||||
|
<mxGraphModel dx="1636" dy="971" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0" />
|
||||||
|
<mxCell id="1" parent="0" />
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-41" value="" style="rounded=0;whiteSpace=wrap;html=1;fontColor=none;noLabel=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="30" y="70" width="1010" height="680" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-1" value="Shadcn/Vue" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="380" y="130" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-2" value="Packages" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="160" y="250" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-3" value="Apps/www" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="630" y="250" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-4" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="PaMXV6_IjdSjTMUUNi7L-27" target="62893188c0fa7362-3" edge="1">
|
||||||
|
<mxGeometry x="-0.3002" y="13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-5" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-1" target="62893188c0fa7362-2" edge="1">
|
||||||
|
<mxGeometry x="-0.359" y="-11" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-8" value="Module" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="80" y="360" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-9" value="CLI" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="220" y="360" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-14" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-2" target="62893188c0fa7362-8" edge="1">
|
||||||
|
<mxGeometry x="-0.2" y="-14" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-15" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-2" target="62893188c0fa7362-9" edge="1">
|
||||||
|
<mxGeometry x="-0.2" y="14" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-16" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.75;entryY=0;entryDx=0;entryDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-2" edge="1">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="644.5454545454545" y="360" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="62893188c0fa7362-17" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.25;entryY=0;entryDx=0;entryDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-1" edge="1">
|
||||||
|
<mxGeometry x="-0.1294" y="17" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="782.7272727272725" y="360" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-1" value="Registry" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="720" y="370" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-2" value=".vitepress" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="420" y="370" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-3" value="Scripts" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="870" y="370" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-4" value="Src" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="570" y="370" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-7" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.333;entryY=0.017;entryDx=0;entryDy=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-3">
|
||||||
|
<mxGeometry x="-0.1294" y="17" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="841" y="270" as="sourcePoint" />
|
||||||
|
<mxPoint x="910" y="320" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-9" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.358;exitY=1.017;exitDx=0;exitDy=0;exitPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-4">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="720" y="540" as="sourcePoint" />
|
||||||
|
<mxPoint x="613" y="600" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-11" value="Content" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="420" y="500" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-12" value="Examples" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="570" y="500" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-13" value="Lib/Registry" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="720" y="500" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-14" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.308;exitY=1.033;exitDx=0;exitDy=0;exitPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-11">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="560" y="470" as="sourcePoint" />
|
||||||
|
<mxPoint x="507" y="529" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-15" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-12">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="657" y="442" as="sourcePoint" />
|
||||||
|
<mxPoint x="540" y="560" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-16" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-13">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="660" y="435" as="sourcePoint" />
|
||||||
|
<mxPoint x="660" y="555" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-20" value="Default" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="630" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-21" value="New York" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="800" y="630" width="120" height="60" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-22" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-13" target="PaMXV6_IjdSjTMUUNi7L-20">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="730" y="670" as="sourcePoint" />
|
||||||
|
<mxPoint x="530" y="818" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-23" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-13" target="PaMXV6_IjdSjTMUUNi7L-21">
|
||||||
|
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="790" y="670" as="sourcePoint" />
|
||||||
|
<mxPoint x="750" y="820" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-26" value="1" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="140" y="230" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-28" value="3" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="400" y="350" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-29" value="4" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="550" y="350" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-30" value="5" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="700" y="350" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-31" value="6" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="850" y="350" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-32" value="7" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="400" y="480" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-33" value="8" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="550" y="480" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-34" value="9" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="700" y="480" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-36" value="10" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="630" y="610" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-38" value="11" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="780" y="610" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-39" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-1" target="PaMXV6_IjdSjTMUUNi7L-27">
|
||||||
|
<mxGeometry x="-0.3002" y="13" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset" />
|
||||||
|
<mxPoint x="500" y="189" as="sourcePoint" />
|
||||||
|
<mxPoint x="630" y="251" as="targetPoint" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="PaMXV6_IjdSjTMUUNi7L-27" value="2" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="610" y="230" width="40" height="40" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
10
apps/www/src/components.d.ts
vendored
Normal file
10
apps/www/src/components.d.ts
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
export {}
|
||||||
|
|
||||||
|
/* prettier-ignore */
|
||||||
|
declare module 'vue' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
ComponentPreview: typeof import('../.vitepress/theme/components/ComponentPreview.vue')['default']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -47,3 +47,5 @@ const { site, theme, page, frontmatter } = useData()
|
||||||
## More
|
## More
|
||||||
|
|
||||||
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
|
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
|
||||||
|
|
||||||
|
kick
|
||||||
|
|
|
||||||
9
apps/www/src/content/blocks.md
Normal file
9
apps/www/src/content/blocks.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: Building Blocks
|
||||||
|
---
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Blocks from "../../.vitepress/theme/components/Blocks.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Blocks />
|
||||||
10
apps/www/src/content/blocks/renderer.md
Normal file
10
apps/www/src/content/blocks/renderer.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
title: Blocks - shadcn-vue
|
||||||
|
layout: false
|
||||||
|
---
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import BlockPage from "../../../.vitepress/theme/components/BlockPage.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<BlockPage />
|
||||||
|
|
@ -5,7 +5,7 @@ description: Powered by amazing open source projects.
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
[shadcn-vue](https://shadcn-vuee.com) is a port of [shadcn/ui](https://ui.shadcn.com) for Vue/Nuxt. It's maintained by [radix-vue](https://github.com/radix-vue).
|
[shadcn-vue](https://shadcn-vue.com) is a port of [shadcn/ui](https://ui.shadcn.com) for Vue/Nuxt. It's maintained by [radix-vue](https://github.com/radix-vue).
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|
@ -17,4 +17,4 @@ description: Powered by amazing open source projects.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT © [shadcn](https://shadcn.com) & [radix-vue](https://github.com/radix-vue)
|
MIT © [shadcn](https://shadcn.com) & [radix-vue](https://github.com/radix-vue)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,139 @@
|
||||||
---
|
---
|
||||||
title: Changelog
|
title: Changelog
|
||||||
|
description: Latest updates and announcements.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## June 2024
|
||||||
|
|
||||||
|
### New Component - Number Field
|
||||||
|
A new component has been added to the project [`NumberField`](/docs/components/number-field.html).
|
||||||
|
|
||||||
|
A number field allows a user to enter a number and increment or decrement the value using stepper buttons.
|
||||||
|
|
||||||
|
<ComponentPreview name="NumberFieldDemo" class="max-w-[180px]" />
|
||||||
|
|
||||||
|
## May 2024
|
||||||
|
|
||||||
|
### New Component - Charts
|
||||||
|
Several kinds of chart components has been added to the project.
|
||||||
|
|
||||||
|
Charts are versatile visualization tools, allowing users to represent data using various options for effective analysis.
|
||||||
|
|
||||||
|
1. [`Area Chart`](/docs/charts/area) - An area chart visually represents data over time, displaying trends and patterns through filled-in areas under a line graph.
|
||||||
|
|
||||||
|
<ComponentPreview name="AreaChartDemo" />
|
||||||
|
|
||||||
|
2. [`Bar Chart`](/docs/charts/bar) - A line chart visually represents data using rectangular bars of varying lengths to compare quantities across different categories or groups.
|
||||||
|
|
||||||
|
<ComponentPreview name="BarChartDemo" />
|
||||||
|
|
||||||
|
3. [`Donut Chart`](/docs/charts/donut) - A line chart visually represents data in a circular form, similar to a pie chart but with a central void, emphasizing proportions within categories.
|
||||||
|
|
||||||
|
<ComponentPreview name="DonutChartDemo" />
|
||||||
|
|
||||||
|
4. [`Line Chart`](/docs/charts/line) - A line chart visually displays data points connected by straight lines, illustrating trends or relationships over a continuous axis.
|
||||||
|
|
||||||
|
<ComponentPreview name="LineChartDemo" />
|
||||||
|
|
||||||
|
### New Component - Auto Form
|
||||||
|
|
||||||
|
[`Auto Form`](/docs/components/auto-form.html) is a drop-in form builder for your internal and low-priority forms with existing zod schemas.
|
||||||
|
|
||||||
|
For example, if you already have zod schemas for your API and want to create a simple admin panel to edit user profiles, simply pass the schema to AutoForm and you're done.
|
||||||
|
|
||||||
|
The following form has been created by passing a `zod` schema object to our `AutoForm` component.
|
||||||
|
|
||||||
|
<ComponentPreview name="AutoFormBasic" />
|
||||||
|
|
||||||
|
## April 2024
|
||||||
|
|
||||||
|
### Component Updated - Calendar
|
||||||
|
|
||||||
|
The [`Calendar`](/docs/components/calendar.html) component has been updated and is now built on top of the [RadixVue Calendar](https://www.radix-vue.com/components/calendar.html) component, which uses the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package to handle dates.
|
||||||
|
|
||||||
|
If you're looking for a range calendar, check out the [`Range Calendar`](/docs/components/range-calendar.html) component.
|
||||||
|
|
||||||
|
And if you're looking for a date picker input, check out the [`Date Picker`](/docs/components/date-picker.html) component.
|
||||||
|
|
||||||
|
<ComponentPreview name="CalendarDemo" />
|
||||||
|
|
||||||
|
<ComponentPreview name="RangeCalendarDemo" />
|
||||||
|
|
||||||
|
<ComponentPreview name="DatePickerDemo" />
|
||||||
|
|
||||||
|
### Building Blocks for the Web
|
||||||
|
|
||||||
|
[`Blocks`](/blocks) are composed of different components that can be used to build your apps, with each block being a standalone section of your application. These blocks are fully responsive, accessible, and composable, and are built using the same principles as the other components in `shadcn-vue`.
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<image
|
||||||
|
src="/examples/block-dark.png"
|
||||||
|
:width="1280"
|
||||||
|
:height="727"
|
||||||
|
alt="Building Blocks"
|
||||||
|
class="hidden dark:block"
|
||||||
|
/>
|
||||||
|
<image
|
||||||
|
src="/examples/block-light.png"
|
||||||
|
:width="1280"
|
||||||
|
:height="727"
|
||||||
|
alt="Building Blocks"
|
||||||
|
class="block dark:hidden"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## March 2024
|
||||||
|
|
||||||
|
### New Component - Breadcrumb
|
||||||
|
|
||||||
|
[`Breadcrumb`](/docs/components/breadcrumb.html) displays the path to the current resource using a hierarchy of links.
|
||||||
|
|
||||||
|
<ComponentPreview name="BreadcrumbDemo" />
|
||||||
|
|
||||||
|
### New Component - Pin Input (OTP Input)
|
||||||
|
|
||||||
|
[`Pin Input`](/docs/components/pin-input.html) allows users to input a sequence of one-character alphanumeric inputs.
|
||||||
|
|
||||||
|
<ComponentPreview name="PinInputDemo" />
|
||||||
|
|
||||||
|
### New Component - Resizable
|
||||||
|
|
||||||
|
[`Resizable`](/docs/components/resizable.html) - Accessible resizable panel groups and layouts with keyboard support.
|
||||||
|
|
||||||
|
<ComponentPreview name="ResizableDemo" />
|
||||||
|
|
||||||
|
### New Component - Drawer
|
||||||
|
|
||||||
|
[`Drawer`](/docs/components/drawer.html) - A drawer component for vue that is built on top of [Vaul Vue](https://github.com/radix-vue/vaul-vue).
|
||||||
|
|
||||||
|
<ComponentPreview name="DrawerDemo" />
|
||||||
|
|
||||||
|
## February 2024
|
||||||
|
|
||||||
|
### New Component - Tag Inputs
|
||||||
|
|
||||||
|
[`Tag inputs`](/docs/components/tags-input.html) render tags inside an input, followed by an actual text input.
|
||||||
|
|
||||||
|
<ComponentPreview name="TagsInputDemo" />
|
||||||
|
|
||||||
|
## January 2024
|
||||||
|
|
||||||
|
### New Component - Sonner
|
||||||
|
|
||||||
|
[`Sonner`](/docs/components/sonner.html) is an opinionated toast component for Vue.
|
||||||
|
|
||||||
|
The Sonner component is provided by [vue-sonner](https://vue-sonner.vercel.app/), which is a Vue port of Sonner, originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
|
||||||
|
|
||||||
|
<ComponentPreview name="SonnerDemo" />
|
||||||
|
|
||||||
|
### New Component - Toggle Group
|
||||||
|
|
||||||
|
[`Toggle Group`](/docs/components/toggle-group.html) - A set of two-state buttons that can be toggled on or off.
|
||||||
|
|
||||||
|
<ComponentPreview name="ToggleGroupDemo" />
|
||||||
|
|
||||||
|
### New Component - Carousel
|
||||||
|
|
||||||
|
[`Carousel`](/docs/components/carousel.html) - A carousel with motion and swipe built using [Embla](https://www.embla-carousel.com/) library.
|
||||||
|
|
||||||
|
<ComponentPreview name="CarouselDemo" />
|
||||||
|
|
|
||||||
107
apps/www/src/content/docs/charts.md
Normal file
107
apps/www/src/content/docs/charts.md
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
---
|
||||||
|
title: Charts
|
||||||
|
description: Versatile visualization tool, allowing users to represent data using various types of charts for effective analysis.
|
||||||
|
label: Alpha
|
||||||
|
---
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Area from '~icons/gravity-ui/chart-area-stacked'
|
||||||
|
import Bar from '~icons/gravity-ui/chart-column'
|
||||||
|
import Line from '~icons/gravity-ui/chart-line'
|
||||||
|
import Pie from '~icons/gravity-ui/chart-pie'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Callout>
|
||||||
|
Only works with Vue >3.3
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
`Charts` components were built on top of [Unovis](https://unovis.dev/) (a modular data visualization framework), and inspired by [tremor](https://www.tremor.so).
|
||||||
|
|
||||||
|
## Chart type
|
||||||
|
|
||||||
|
<div class="grid gap-4 mt-8 sm:grid-cols-2 sm:gap-6 not-docs">
|
||||||
|
<LinkedCard href="/docs/charts/area">
|
||||||
|
<Area class="text-foreground/80 w-11 h-11" />
|
||||||
|
<p class="mt-2 font-medium">Area</p>
|
||||||
|
</LinkedCard>
|
||||||
|
|
||||||
|
<LinkedCard href="/docs/charts/line">
|
||||||
|
<Line class="text-foreground/80 w-11 h-11" />
|
||||||
|
<p class="mt-2 font-medium">Line</p>
|
||||||
|
</LinkedCard>
|
||||||
|
|
||||||
|
<LinkedCard href="/docs/charts/bar">
|
||||||
|
<Bar class="text-foreground/80 w-11 h-11" />
|
||||||
|
<p class="mt-2 font-medium">Bar</p>
|
||||||
|
</LinkedCard>
|
||||||
|
|
||||||
|
<LinkedCard href="/docs/charts/donut">
|
||||||
|
<Pie class="text-foreground/80 w-11 h-11" />
|
||||||
|
<p class="mt-2 font-medium">Donut</p>
|
||||||
|
</LinkedCard>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Update `css`
|
||||||
|
|
||||||
|
Add the following tooltip styling to your `tailwind.css` file:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
/* ... */
|
||||||
|
--vis-tooltip-background-color: none !important;
|
||||||
|
--vis-tooltip-border-color: none !important;
|
||||||
|
--vis-tooltip-text-color: none !important;
|
||||||
|
--vis-tooltip-shadow-color: none !important;
|
||||||
|
--vis-tooltip-backdrop-filter: none !important;
|
||||||
|
--vis-tooltip-padding: none !important;
|
||||||
|
|
||||||
|
--vis-primary-color: var(--primary);
|
||||||
|
/* change to any hsl value you want */
|
||||||
|
--vis-secondary-color: 160 81% 40%;
|
||||||
|
--vis-text-color: var(--muted-foreground);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are not using `css-variables` for your component, you need to update the `--vis-primary-color` and `--vis-text-color` to your desired hsl value.
|
||||||
|
|
||||||
|
You may use [this tool](https://redpixelthemes.com/blog/tailwindcss-colors-different-formats/) to help you find the hsl value for your primary color and text color. Be sure to provide `dark` mode styling as well.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Colors
|
||||||
|
|
||||||
|
By default, we construct the primary theme color, and secondary (`--vis-secondary-color`) color with different opacity for the graph.
|
||||||
|
|
||||||
|
However, you can always pass in the desired `color` into each chart.
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<AreaChart
|
||||||
|
:data="data"
|
||||||
|
:colors="['blue', 'pink', 'orange', 'red']"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom tooltip
|
||||||
|
|
||||||
|
If you want to customize the `Tooltip` for the chart, you can pass `customTooltip` prop with a custom Vue component.
|
||||||
|
The custom component would receive `title` and `data` props, check out [ChartTooltip.vue component](https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/lib/registry/default/ui/chart/ChartTooltip.vue) for example.
|
||||||
|
|
||||||
|
The expected prop definition would be:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
defineProps<{
|
||||||
|
title?: string
|
||||||
|
data: {
|
||||||
|
name: string
|
||||||
|
color: string
|
||||||
|
value: any
|
||||||
|
}[]
|
||||||
|
}>()
|
||||||
|
```
|
||||||
46
apps/www/src/content/docs/charts/area.md
Normal file
46
apps/www/src/content/docs/charts/area.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
title: Area
|
||||||
|
description: An area chart visually represents data over time, displaying trends and patterns through filled-in areas under a line graph.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/chart-area
|
||||||
|
label: Alpha
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="AreaChartDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Callout>
|
||||||
|
Only works with Vue >3.3
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Run the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add chart-area
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Follow the [guide](/docs/charts.html#installation) to complete the setup.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<!-- @include: @/content/meta/AreaChart.md -->
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### Sparkline
|
||||||
|
|
||||||
|
We can turn the chart into sparkline chart by hiding axis, gridline and legends.
|
||||||
|
|
||||||
|
<ComponentPreview name="AreaChartSparkline" />
|
||||||
|
|
||||||
|
### Custom Tooltip
|
||||||
|
|
||||||
|
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
|
||||||
|
|
||||||
|
<ComponentPreview name="AreaChartCustomTooltip" />
|
||||||
50
apps/www/src/content/docs/charts/bar.md
Normal file
50
apps/www/src/content/docs/charts/bar.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
title: Bar
|
||||||
|
description: A line chart visually represents data using rectangular bars of varying lengths to compare quantities across different categories or groups.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/chart-bar
|
||||||
|
label: Alpha
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="BarChartDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Callout>
|
||||||
|
Only works with Vue >3.3
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Run the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add chart-bar
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Follow the [guide](/docs/charts.html#installation) to complete the setup.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<!-- @include: @/content/meta/BarChart.md -->
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### Stacked
|
||||||
|
|
||||||
|
You can stack the bar chart by settings prop `type` to `stacked`.
|
||||||
|
|
||||||
|
<ComponentPreview name="BarChartStacked" />
|
||||||
|
|
||||||
|
### Rounded
|
||||||
|
|
||||||
|
<ComponentPreview name="BarChartRounded" />
|
||||||
|
|
||||||
|
### Custom Tooltip
|
||||||
|
|
||||||
|
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
|
||||||
|
|
||||||
|
<ComponentPreview name="BarChartCustomTooltip" />
|
||||||
52
apps/www/src/content/docs/charts/donut.md
Normal file
52
apps/www/src/content/docs/charts/donut.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
title: Donut
|
||||||
|
description: A line chart visually represents data in a circular form, similar to a pie chart but with a central void, emphasizing proportions within categories.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/chart-donut
|
||||||
|
label: Alpha
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="DonutChartDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Callout>
|
||||||
|
Only works with Vue >3.3
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Run the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add chart-donut
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Follow the [guide](/docs/charts.html#installation) to complete the setup.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<!-- @include: @/content/meta/DonutChart.md -->
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### Pie Chart
|
||||||
|
|
||||||
|
If you want to render pie chart instead, pass `type` as `pie`.
|
||||||
|
|
||||||
|
<ComponentPreview name="DonutChartPie" />
|
||||||
|
|
||||||
|
### Color
|
||||||
|
|
||||||
|
We generate colors automatically based on the primary and secondary color and assigned them accordingly. Feel free to pass in your own array of colors.
|
||||||
|
|
||||||
|
<ComponentPreview name="DonutChartColor" />
|
||||||
|
|
||||||
|
### Custom Tooltip
|
||||||
|
|
||||||
|
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
|
||||||
|
|
||||||
|
<ComponentPreview name="DonutChartCustomTooltip" />
|
||||||
46
apps/www/src/content/docs/charts/line.md
Normal file
46
apps/www/src/content/docs/charts/line.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
title: Line
|
||||||
|
description: A line chart visually displays data points connected by straight lines, illustrating trends or relationships over a continuous axis.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/chart-line
|
||||||
|
label: Alpha
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="LineChartDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Callout>
|
||||||
|
Only works with Vue >3.3
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Run the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add chart-line
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Follow the [guide](/docs/charts.html#installation) to complete the setup.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
<!-- @include: @/content/meta/LineChart.md -->
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### Sparkline
|
||||||
|
|
||||||
|
We can turn the chart into sparkline chart by hiding axis, gridline and legends.
|
||||||
|
|
||||||
|
<ComponentPreview name="LineChartSparkline" />
|
||||||
|
|
||||||
|
### Custom Tooltip
|
||||||
|
|
||||||
|
If you want to render custom tooltip, you can easily pass in a custom component. Refer to prop definition [here](/docs/charts.html#custom-tooltip).
|
||||||
|
|
||||||
|
<ComponentPreview name="LineChartCustomTooltip" />
|
||||||
|
|
@ -15,7 +15,7 @@ npx shadcn-vue@latest init
|
||||||
|
|
||||||
You will be asked a few questions to configure `components.json`:
|
You will be asked a few questions to configure `components.json`:
|
||||||
|
|
||||||
```txt:line-numbers
|
```ansi:line-numbers
|
||||||
Would you like to use TypeScript (recommended)? no / yes
|
Would you like to use TypeScript (recommended)? no / yes
|
||||||
Which framework are you using? Vite / Nuxt / Laravel
|
Which framework are you using? Vite / Nuxt / Laravel
|
||||||
Which style would you like to use? › Default
|
Which style would you like to use? › Default
|
||||||
|
|
@ -24,12 +24,12 @@ Where is your global CSS file? › › src/index.css
|
||||||
Do you want to use CSS variables for colors? › no / yes
|
Do you want to use CSS variables for colors? › no / yes
|
||||||
Where is your tailwind.config.js located? › tailwind.config.js
|
Where is your tailwind.config.js located? › tailwind.config.js
|
||||||
Configure the import alias for components: › @/components
|
Configure the import alias for components: › @/components
|
||||||
Configure the import alias for utils: › @/lib/utils
|
Configure the import alias for utils: › @/lib/utils
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```txt
|
```ansi
|
||||||
Usage: shadcn-vue init [options]
|
Usage: shadcn-vue init [options]
|
||||||
|
|
||||||
initialize your project and install dependencies
|
initialize your project and install dependencies
|
||||||
|
|
@ -50,7 +50,7 @@ npx shadcn-vue@latest add [component]
|
||||||
|
|
||||||
You will be presented with a list of components to choose from:
|
You will be presented with a list of components to choose from:
|
||||||
|
|
||||||
```txt
|
```ansi
|
||||||
Which components would you like to add? › Space to select. Return to submit.
|
Which components would you like to add? › Space to select. Return to submit.
|
||||||
|
|
||||||
◯ accordion
|
◯ accordion
|
||||||
|
|
@ -67,7 +67,7 @@ Which components would you like to add? › Space to select. Return to submit.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```txt
|
```ansi
|
||||||
Usage: shadcn-vue add [options] [components...]
|
Usage: shadcn-vue add [options] [components...]
|
||||||
|
|
||||||
add components to your project
|
add components to your project
|
||||||
|
|
@ -90,7 +90,7 @@ Use the `update` command to update components in your project. This will overwri
|
||||||
|
|
||||||
We plan on improving this command in the future to improve the update experience.
|
We plan on improving this command in the future to improve the update experience.
|
||||||
|
|
||||||
```txt
|
```ansi
|
||||||
Usage: shadcn-vue update [options] [components...]
|
Usage: shadcn-vue update [options] [components...]
|
||||||
|
|
||||||
update components in your project
|
update components in your project
|
||||||
|
|
@ -101,4 +101,4 @@ Arguments:
|
||||||
Options:
|
Options:
|
||||||
-c, --cwd <cwd> the working directory. (default: the current directory)
|
-c, --cwd <cwd> the working directory. (default: the current directory)
|
||||||
-h, --help display help for command
|
-h, --help display help for command
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,6 @@ This is used to generate the default color palette for your components. **This c
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### tailwind.cssVariables
|
### tailwind.cssVariables
|
||||||
|
|
||||||
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
|
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
|
||||||
|
|
@ -109,7 +108,6 @@ For more information, see the [theming docs](/docs/theming).
|
||||||
|
|
||||||
**This cannot be changed after initialization.** To switch between CSS variables and utility classes, you'll have to delete and re-install your components.
|
**This cannot be changed after initialization.** To switch between CSS variables and utility classes, you'll have to delete and re-install your components.
|
||||||
|
|
||||||
|
|
||||||
## aliases
|
## aliases
|
||||||
|
|
||||||
The CLI uses these values and the `paths` config from your `tsconfig.json` or `jsconfig.json` file to place generated components in the correct location.
|
The CLI uses these values and the `paths` config from your `tsconfig.json` or `jsconfig.json` file to place generated components in the correct location.
|
||||||
|
|
@ -117,7 +115,6 @@ The CLI uses these values and the `paths` config from your `tsconfig.json` or `j
|
||||||
Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
|
Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
|
||||||
|
|
||||||
> A fallback to `tsconfig.app.json` if no `paths` were found in `tsconfig.json`
|
> A fallback to `tsconfig.app.json` if no `paths` were found in `tsconfig.json`
|
||||||
|
|
||||||
|
|
||||||
<Callout class="mt-6">
|
<Callout class="mt-6">
|
||||||
|
|
||||||
|
|
@ -126,7 +123,6 @@ Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
|
||||||
|
|
||||||
</Callout>
|
</Callout>
|
||||||
|
|
||||||
|
|
||||||
### aliases.utils
|
### aliases.utils
|
||||||
|
|
||||||
Import alias for your utility functions.
|
Import alias for your utility functions.
|
||||||
|
|
@ -146,7 +142,21 @@ Import alias for your components.
|
||||||
```json title="components.json"
|
```json title="components.json"
|
||||||
{
|
{
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "@/lib/components"
|
"components": "@/components"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### aliases.ui
|
||||||
|
|
||||||
|
Import alias for `ui` components.
|
||||||
|
|
||||||
|
The CLI will use the `aliases.ui` value to determine where to place your `ui` components. Use this config if you want to customize the installation directory for your `ui` components.
|
||||||
|
|
||||||
|
```json title="components.json"
|
||||||
|
{
|
||||||
|
"aliases": {
|
||||||
|
"ui": "@/app/ui"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
||||||
6
apps/www/src/content/docs/components.md
Normal file
6
apps/www/src/content/docs/components.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<script setup>
|
||||||
|
import { useRouter } from 'vitepress'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
router.go('/docs/components/accordion')
|
||||||
|
</script>
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
---
|
---
|
||||||
title: Accordion
|
title: Accordion
|
||||||
description: A vertically stacked set of interactive headings that each reveal a section of content.
|
description: A vertically stacked set of interactive headings that each reveal a section of content.
|
||||||
source: apps/www/src/lib/registry/default/ui/accordion
|
source: apps/www/src/lib/registry/default/ui/accordion
|
||||||
primitive: https://www.radix-vue.com/components/accordion.html
|
primitive: https://www.radix-vue.com/components/accordion.html
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="AccordionDemo" class="sm:max-w-[70%]" />
|
||||||
<ComponentPreview name="AccordionDemo" class="[&_.accordion]:sm:max-w-[70%]" />
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
|
|
@ -46,9 +44,8 @@ module.exports = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
@ -68,4 +65,3 @@ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,18 @@
|
||||||
---
|
---
|
||||||
title: Alert Dialog
|
title: Alert Dialog
|
||||||
description: A modal dialog that interrupts the user with important content and expects a response.
|
description: A modal dialog that interrupts the user with important content and expects a response.
|
||||||
source: apps/www/src/lib/registry/default/ui/alert-dialog
|
source: apps/www/src/lib/registry/default/ui/alert-dialog
|
||||||
primitive: https://www.radix-vue.com/components/alert-dialog.html
|
primitive: https://www.radix-vue.com/components/alert-dialog.html
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
<ComponentPreview name="AlertDialogDemo" />
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
|
<ComponentPreview name="AlertDialogDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx shadcn-vue@latest add alert-dialog
|
npx shadcn-vue@latest add alert-dialog
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
|
|
@ -51,4 +48,4 @@ import {
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,14 @@ title: Alert
|
||||||
description: Displays a callout for user attention.
|
description: Displays a callout for user attention.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="AlertDemo" />
|
||||||
<ComponentPreview name="AlertDemo" />
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx shadcn-vue@latest add alert
|
npx shadcn-vue@latest add alert
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
|
|
@ -28,4 +26,14 @@ import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Default
|
||||||
|
|
||||||
|
<ComponentPreview name="AlertDemo" />
|
||||||
|
|
||||||
|
### Destructive
|
||||||
|
|
||||||
|
<ComponentPreview name="AlertDestructiveDemo" />
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user