@a5gard/asgard 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +2 -0
- package/.gitignore copy +6 -0
- package/.vscode/ntrsync/.vscode/ocrmnavigator/id.txt +1 -0
- package/.vscode/ntrsync/.vscode/ocrmnavigator.code-snippets +3664 -0
- package/.vscode/ntrsync/00002_CRM URGENT_todo.md +79 -0
- package/.vscode/ntrsync/10005_notes repo url.md +3 -0
- package/.vscode/ntrsync/10012_vscode_color_settings.md +133 -0
- package/.vscode/ntrsync/10013_Googles Snapchat Upload Hack note.md +11 -0
- package/.vscode/ntrsync/10014_APP IDEA - Lawyer CRM.md +229 -0
- package/.vscode/ntrsync/10015_APP IDEA - Onlyfans.md +293 -0
- package/.vscode/ntrsync/10016_notes repo url.md +3 -0
- package/.vscode/ntrsync/10504_adhd symptom.md +3 -0
- package/.vscode/ntrsync/10505_APP IDEA - GMAIL.md +39 -0
- package/.vscode/ntrsync/10506_container home - build mats.md +18 -0
- package/.vscode/ntrsync/10507_cleint facing site meta and loader function.md +25 -0
- package/.vscode/ntrsync/10508_Sabaak VSCode 1-8 players - private teams, solo q, duos q.md +11 -0
- package/.vscode/ntrsync/10509_schema dump.md +80 -0
- package/.vscode/ntrsync/10510_APPT BEACONHILL_reminder.md +7 -0
- package/.vscode/ntrsync/10512_clipboard very usefull should use asap within all apps.md +101 -0
- package/.vscode/ntrsync/10516_DevStack_todo.md +130 -0
- package/.vscode/ntrsync/10517_CRM_todo.md +95 -0
- package/.vscode/ntrsync/10518_Catalyst POS_todo.md +73 -0
- package/.vscode/ntrsync/10519_Catalyst Software_todo.md +497 -0
- package/.vscode/ntrsync/10523_new note.md +6 -0
- package/.vscode/ntrsync/10524_New Reminder_reminder.md +5 -0
- package/.vscode/ntrsync/10525_Mobile - Notes, To-Dos And Things_todo.md +4 -0
- package/.vscode/ntrsync/90002_COMPLETED_todo.md +97 -0
- package/.vscode/ntrsync/README.md +1 -0
- package/.vscode/ocrmnavigator/id.txt +1 -0
- package/.vscode/ocrmnavigator.code-snippets +349 -0
- package/.vscode/settings.json +1 -0
- package/CHANGELOG.md +6 -0
- package/LICENSE.md +21 -0
- package/README.md +1612 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +17 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/config.asgard +8 -0
- package/dist/commands/add-source.d.ts +9 -0
- package/dist/commands/add-source.d.ts.map +1 -0
- package/dist/commands/add-source.js +68 -0
- package/dist/commands/add-source.js.map +1 -0
- package/dist/commands/baldr.d.ts +5 -0
- package/dist/commands/baldr.d.ts.map +1 -0
- package/dist/commands/baldr.js +35 -0
- package/dist/commands/baldr.js.map +1 -0
- package/dist/commands/combine-timelines.d.ts +5 -0
- package/dist/commands/combine-timelines.d.ts.map +1 -0
- package/dist/commands/combine-timelines.js +53 -0
- package/dist/commands/combine-timelines.js.map +1 -0
- package/dist/commands/create-project.d.ts +10 -0
- package/dist/commands/create-project.d.ts.map +1 -0
- package/dist/commands/create-project.js +195 -0
- package/dist/commands/create-project.js.map +1 -0
- package/dist/commands/create-timeline.d.ts +8 -0
- package/dist/commands/create-timeline.d.ts.map +1 -0
- package/dist/commands/create-timeline.js +54 -0
- package/dist/commands/create-timeline.js.map +1 -0
- package/dist/commands/delete-project.d.ts +5 -0
- package/dist/commands/delete-project.d.ts.map +1 -0
- package/dist/commands/delete-project.js +47 -0
- package/dist/commands/delete-project.js.map +1 -0
- package/dist/commands/delete-source.d.ts +8 -0
- package/dist/commands/delete-source.d.ts.map +1 -0
- package/dist/commands/delete-source.js +57 -0
- package/dist/commands/delete-source.js.map +1 -0
- package/dist/commands/delete-timeline.d.ts +8 -0
- package/dist/commands/delete-timeline.d.ts.map +1 -0
- package/dist/commands/delete-timeline.js +54 -0
- package/dist/commands/delete-timeline.js.map +1 -0
- package/dist/commands/delete-version.d.ts +8 -0
- package/dist/commands/delete-version.d.ts.map +1 -0
- package/dist/commands/delete-version.js +65 -0
- package/dist/commands/delete-version.js.map +1 -0
- package/dist/commands/download-file.d.ts +17 -0
- package/dist/commands/download-file.d.ts.map +1 -0
- package/dist/commands/download-file.js +87 -0
- package/dist/commands/download-file.js.map +1 -0
- package/dist/commands/download-folder.d.ts +18 -0
- package/dist/commands/download-folder.d.ts.map +1 -0
- package/dist/commands/download-folder.js +111 -0
- package/dist/commands/download-folder.js.map +1 -0
- package/dist/commands/download-source.d.ts +12 -0
- package/dist/commands/download-source.d.ts.map +1 -0
- package/dist/commands/download-source.js +46 -0
- package/dist/commands/download-source.js.map +1 -0
- package/dist/commands/gh-setup.d.ts +7 -0
- package/dist/commands/gh-setup.d.ts.map +1 -0
- package/dist/commands/gh-setup.js +106 -0
- package/dist/commands/gh-setup.js.map +1 -0
- package/dist/commands/load-project.d.ts +5 -0
- package/dist/commands/load-project.d.ts.map +1 -0
- package/dist/commands/load-project.js +56 -0
- package/dist/commands/load-project.js.map +1 -0
- package/dist/commands/menu.d.ts +5 -0
- package/dist/commands/menu.d.ts.map +1 -0
- package/dist/commands/menu.js +41 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/midgardr.d.ts +5 -0
- package/dist/commands/midgardr.d.ts.map +1 -0
- package/dist/commands/midgardr.js +24 -0
- package/dist/commands/midgardr.js.map +1 -0
- package/dist/commands/publish-project.d.ts +5 -0
- package/dist/commands/publish-project.d.ts.map +1 -0
- package/dist/commands/publish-project.js +102 -0
- package/dist/commands/publish-project.js.map +1 -0
- package/dist/commands/replace-timeline.d.ts +8 -0
- package/dist/commands/replace-timeline.d.ts.map +1 -0
- package/dist/commands/replace-timeline.js +63 -0
- package/dist/commands/replace-timeline.js.map +1 -0
- package/dist/commands/restore-version.d.ts +8 -0
- package/dist/commands/restore-version.d.ts.map +1 -0
- package/dist/commands/restore-version.js +67 -0
- package/dist/commands/restore-version.js.map +1 -0
- package/dist/commands/save-project.d.ts +8 -0
- package/dist/commands/save-project.d.ts.map +1 -0
- package/dist/commands/save-project.js +43 -0
- package/dist/commands/save-project.js.map +1 -0
- package/dist/commands/set-source.d.ts +9 -0
- package/dist/commands/set-source.d.ts.map +1 -0
- package/dist/commands/set-source.js +59 -0
- package/dist/commands/set-source.js.map +1 -0
- package/dist/commands/switch-timeline.d.ts +8 -0
- package/dist/commands/switch-timeline.d.ts.map +1 -0
- package/dist/commands/switch-timeline.js +61 -0
- package/dist/commands/switch-timeline.js.map +1 -0
- package/dist/commands/sync-source.d.ts +5 -0
- package/dist/commands/sync-source.d.ts.map +1 -0
- package/dist/commands/sync-source.js +29 -0
- package/dist/commands/sync-source.js.map +1 -0
- package/dist/commands/upload-project+++.d.ts +5 -0
- package/dist/commands/upload-project+++.d.ts.map +1 -0
- package/dist/commands/upload-project+++.js +32 -0
- package/dist/commands/upload-project+++.js.map +1 -0
- package/dist/commands/upload-project++.d.ts +5 -0
- package/dist/commands/upload-project++.d.ts.map +1 -0
- package/dist/commands/upload-project++.js +33 -0
- package/dist/commands/upload-project++.js.map +1 -0
- package/dist/commands/upload-project+.d.ts +5 -0
- package/dist/commands/upload-project+.d.ts.map +1 -0
- package/dist/commands/upload-project+.js +40 -0
- package/dist/commands/upload-project+.js.map +1 -0
- package/dist/commands/upload-project.d.ts +5 -0
- package/dist/commands/upload-project.d.ts.map +1 -0
- package/dist/commands/upload-project.js +29 -0
- package/dist/commands/upload-project.js.map +1 -0
- package/dist/commands/view-timeline.d.ts +5 -0
- package/dist/commands/view-timeline.d.ts.map +1 -0
- package/dist/commands/view-timeline.js +39 -0
- package/dist/commands/view-timeline.js.map +1 -0
- package/dist/commands/view-versions.d.ts +5 -0
- package/dist/commands/view-versions.d.ts.map +1 -0
- package/dist/commands/view-versions.js +45 -0
- package/dist/commands/view-versions.js.map +1 -0
- package/dist/git/helpers.d.ts +10 -0
- package/dist/git/helpers.d.ts.map +1 -0
- package/dist/git/helpers.js +300 -0
- package/dist/git/helpers.js.map +1 -0
- package/dist/git/sync-repo.d.ts +2 -0
- package/dist/git/sync-repo.d.ts.map +1 -0
- package/dist/git/sync-repo.js +17 -0
- package/dist/git/sync-repo.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/box.d.ts +11 -0
- package/dist/utils/box.d.ts.map +1 -0
- package/dist/utils/box.js +158 -0
- package/dist/utils/box.js.map +1 -0
- package/ideas.md +46 -0
- package/package.json +53 -0
- package/src/commands/add-source.js +72 -0
- package/src/commands/baldr.js +38 -0
- package/src/commands/combine-timelines.js +65 -0
- package/src/commands/create-project.js +216 -0
- package/src/commands/create-timeline.js +60 -0
- package/src/commands/delete-project.js +54 -0
- package/src/commands/delete-source.js +63 -0
- package/src/commands/delete-timeline.js +63 -0
- package/src/commands/delete-version.js +74 -0
- package/src/commands/download-file.js +101 -0
- package/src/commands/download-folder.js +123 -0
- package/src/commands/download-source.js +51 -0
- package/src/commands/gh-setup.js +77 -0
- package/src/commands/load-project.js +63 -0
- package/src/commands/menu.js +46 -0
- package/src/commands/midgardr.js +25 -0
- package/src/commands/publish-project.js +167 -0
- package/src/commands/replace-timeline.js +76 -0
- package/src/commands/restore-version.js +80 -0
- package/src/commands/save-project.js +48 -0
- package/src/commands/set-source.js +65 -0
- package/src/commands/switch-timeline.js +69 -0
- package/src/commands/sync-source.js +32 -0
- package/src/commands/upload-project+++.js +34 -0
- package/src/commands/upload-project++.js +35 -0
- package/src/commands/upload-project+.js +47 -0
- package/src/commands/upload-project.js +31 -0
- package/src/commands/view-timeline.js +43 -0
- package/src/commands/view-versions.js +50 -0
- package/src/git/helpers.js +333 -0
- package/src/git/sync-repo.js +16 -0
- package/src/index.js +2 -0
- package/src/utils/box.js +282 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,3664 @@
|
|
|
1
|
+
{
|
|
2
|
+
"loader_for_redirecting_bad_requests": {
|
|
3
|
+
"prefix": "loader-for-redirecting-bad-requiests",
|
|
4
|
+
"description": "Custom snippet from loader-for-redirecting-bad-requiests.snippet.tsx",
|
|
5
|
+
"scope": "typescript,typescriptreact",
|
|
6
|
+
"body": [
|
|
7
|
+
"export async function loader() { return json({ error: \"GET not allowed\" }, { status: 405 })}"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"action_for_redirecting_bad_requests": {
|
|
11
|
+
"prefix": "action-for-redirecting-bad-requests",
|
|
12
|
+
"description": "Custom snippet from action-for-redirecting-bad-requests.snippet.tsx",
|
|
13
|
+
"scope": "typescript,typescriptreact",
|
|
14
|
+
"body": [
|
|
15
|
+
"export async function action() { return json({ error: \"POST not allowed\" }, { status: 405 })}"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"submodules_cmds": {
|
|
19
|
+
"prefix": "submodules-cmds",
|
|
20
|
+
"description": "Custom snippet from submodules-cmds.snippet.tsx",
|
|
21
|
+
"scope": "typescript,typescriptreact",
|
|
22
|
+
"body": [
|
|
23
|
+
"cd apps/*",
|
|
24
|
+
"git init",
|
|
25
|
+
"git remote add origin https://github.com/8an3/crm-prod.git",
|
|
26
|
+
"git branch -m master main",
|
|
27
|
+
"git add .",
|
|
28
|
+
"git commit -m \"Initial commit for dev\"",
|
|
29
|
+
"git push -u origin main",
|
|
30
|
+
"Link Submodules Properly in the Main Repo",
|
|
31
|
+
"cd apps/*",
|
|
32
|
+
"git submodule init",
|
|
33
|
+
"git submodule update --remote --recursive",
|
|
34
|
+
"Push .gitmodules and the Updated Main Repo",
|
|
35
|
+
"cd F:/OpinionatedCRM",
|
|
36
|
+
"git add .gitmodules apps/*",
|
|
37
|
+
"git commit -m \"Added submodules for dev, cal, pdf, prod\"",
|
|
38
|
+
"git push origin main",
|
|
39
|
+
"Cloning the Monorepo with Submodules (for future use)",
|
|
40
|
+
"git clone --recurse-submodules https://github.com/8an3/crm.git"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"fresh_vercel_server_also_needs_these_installed": {
|
|
44
|
+
"prefix": "fresh-vercel-server-also-needs-these-installed",
|
|
45
|
+
"description": "Custom snippet from fresh-vercel-server-also-needs-these-installed.snippet.tsx",
|
|
46
|
+
"scope": "typescript,typescriptreact",
|
|
47
|
+
"body": [
|
|
48
|
+
"pnpm i base32-decode",
|
|
49
|
+
"pnpm i jos",
|
|
50
|
+
"pnpm i webapi",
|
|
51
|
+
"serverDependenciesToBundle: [",
|
|
52
|
+
" \"axios\",",
|
|
53
|
+
" \"@azure/msal-react\",",
|
|
54
|
+
" \"Path2D\",",
|
|
55
|
+
" \"chalk\",",
|
|
56
|
+
" 'jose',",
|
|
57
|
+
" \"crypto\",",
|
|
58
|
+
" \"@pdfme\",",
|
|
59
|
+
" \"remix-auth-totp\",",
|
|
60
|
+
" \"@epic-web/totp\",",
|
|
61
|
+
" \"base32-encode\",",
|
|
62
|
+
" \"to-data-view\"",
|
|
63
|
+
"],"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"nice_looking_text_classnames": {
|
|
67
|
+
"prefix": "nice-looking-text-classnames",
|
|
68
|
+
"description": "Custom snippet from nice-looking-text-classnames.snippet.tsx",
|
|
69
|
+
"scope": "typescript,typescriptreact",
|
|
70
|
+
"body": [
|
|
71
|
+
"<div className=\"prose\">",
|
|
72
|
+
" <h1>Header 1</h1>",
|
|
73
|
+
" <h2>Header 2</h2>",
|
|
74
|
+
" <h3>Header 3</h3>",
|
|
75
|
+
" <h4>Header 4</h4>",
|
|
76
|
+
" <h5>Header 5</h5>",
|
|
77
|
+
" <p>Paragraph text</p>",
|
|
78
|
+
"</div>",
|
|
79
|
+
"DO NOT USE BELOW, USE ABOVE INSTEAD",
|
|
80
|
+
"header 1",
|
|
81
|
+
"text-3xl font-bold leading-tight tracking-tighter md:text-4xl lg:leading-[1.1]",
|
|
82
|
+
"header 2",
|
|
83
|
+
"mt-3 text-muted-foreground text-thin text-center",
|
|
84
|
+
"header 3",
|
|
85
|
+
"font-semibold mb-4 mt-4",
|
|
86
|
+
"p",
|
|
87
|
+
"text-balance font-light text-foreground text-sm text-thin"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"Error_Checking_Action": {
|
|
91
|
+
"prefix": "error-checking-action",
|
|
92
|
+
"description": "Custom snippet from error-checking-action.snippet.tsx",
|
|
93
|
+
"scope": "typescript,typescriptreact",
|
|
94
|
+
"body": [
|
|
95
|
+
"// needs to be contained in a <Form method='post' > or else it wont work no fetcher no anything",
|
|
96
|
+
"const phone = formPayload.phone;",
|
|
97
|
+
"const phoneRegex = /^[2-9]\\d{2}[2-9]\\d{2}\\d{4}$/;",
|
|
98
|
+
"const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(ca|com)$/;",
|
|
99
|
+
"const errors = {",
|
|
100
|
+
" username: formPayload.username ? null : \"Full name is required...\",",
|
|
101
|
+
" year: formPayload.year.length === 4 ? null : \"Year needs to be a length of 4...\", ",
|
|
102
|
+
" email: formPayload.email ? null : \"Email is required...\",",
|
|
103
|
+
" phone: phoneRegex.test(phone) ? null : \"Phone must be in the format 4164164164\",",
|
|
104
|
+
" position: formPayload.userRole ? null : 'Position / Role is required...',",
|
|
105
|
+
" dept: formPayload.dept ? null : 'Dept is required...',",
|
|
106
|
+
" emailFormat: emailRegex.test(formPayload.email) ? null : 'Incorrect email format...',",
|
|
107
|
+
" phoneLength: phone.replace(/\\D/g, \"\").length === 10 ? null : 'Incorrect phone # length...', ",
|
|
108
|
+
"};",
|
|
109
|
+
"const hasErrors = Object.values(errors).some((errorMessage) => errorMessage);",
|
|
110
|
+
"if (hasErrors) { return json(errors); }",
|
|
111
|
+
"{errors?.username ? (<p className=\"text-[#ff0202] flex items-center\">{errors.username}</p>) : null}",
|
|
112
|
+
"{errors?.email ? (<p className=\"text-[#ff0202] flex items-center\">{errors.email}</p>) : null}",
|
|
113
|
+
"{errors?.phone ? (<p className=\"text-[#ff0202] flex items-center\">{errors.phone}</p>) : null}",
|
|
114
|
+
"{errors?.position ? (<p className=\"text-[#ff0202] flex items-center\">{errors.position}</p>) : null}",
|
|
115
|
+
"{errors?.dept ? (<p className=\"text-[#ff0202] flex items-center\">{errors.dept}</p>) : null}",
|
|
116
|
+
"{errors?.phoneLength ? (<p className=\"text-[#ff0202] flex items-center\">{errors.phoneLength}</p>) : null}",
|
|
117
|
+
"{errors?.emailFormat ? (<p className=\"text-[#ff0202] flex items-center\">{errors.emailFormat}</p>) : null}"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"map_function": {
|
|
121
|
+
"prefix": "map_function",
|
|
122
|
+
"description": "Custom snippet from map-function.snippet.tsx",
|
|
123
|
+
"scope": "typescript,typescriptreact",
|
|
124
|
+
"body": [
|
|
125
|
+
"{categories.map((item, index) => {",
|
|
126
|
+
" return (",
|
|
127
|
+
" <SelectItem key={index} value={item.value}>",
|
|
128
|
+
" {item.name}",
|
|
129
|
+
" </SelectItem>",
|
|
130
|
+
" );",
|
|
131
|
+
"})}",
|
|
132
|
+
" <div className='grid gap-4'>",
|
|
133
|
+
" {customerCard.map((item, index) => {",
|
|
134
|
+
" return (",
|
|
135
|
+
" <div className=\"relative mr-3\" key={index}>",
|
|
136
|
+
" <Input value={item.value} name={item.name} className='w-full' />",
|
|
137
|
+
" <label className=\" text-sm absolute left-3 rounded-full -top-3 px-2 bg-background transition-all peer-placeholder-shown:top-2.5 peer-placeholder-shown:text-gray-400 peer-focus:-top-3 peer-focus:text-blue-500\">",
|
|
138
|
+
" {item.placeholder}",
|
|
139
|
+
" </label>",
|
|
140
|
+
" </div>",
|
|
141
|
+
" );",
|
|
142
|
+
" })}",
|
|
143
|
+
" <Button",
|
|
144
|
+
" size=\"sm\"",
|
|
145
|
+
" variant=\"outline\"",
|
|
146
|
+
" className='ml-auto'",
|
|
147
|
+
" type='submit'",
|
|
148
|
+
" name='intent'",
|
|
149
|
+
" value='editProduct'",
|
|
150
|
+
" >",
|
|
151
|
+
" Save",
|
|
152
|
+
" </Button>",
|
|
153
|
+
" </div>"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
"cors": {
|
|
157
|
+
"prefix": "cors",
|
|
158
|
+
"description": "Custom snippet from cors.snippet.tsx",
|
|
159
|
+
"scope": "typescript,typescriptreact",
|
|
160
|
+
"body": [
|
|
161
|
+
"import { json, type LoaderFunction, redirect } from \"@remix-run/node\";",
|
|
162
|
+
"import { prisma } from \"~/libs\";",
|
|
163
|
+
"import { GetUser } from \"~/utils/loader.server\";",
|
|
164
|
+
"import { getSession } from \"~/sessions/auth-session.server\";",
|
|
165
|
+
"import { cors } from \"remix-utils\";",
|
|
166
|
+
"export async function loader({ request, params }: LoaderFunction) {",
|
|
167
|
+
" console.log(\"loader was hit\");",
|
|
168
|
+
" const session = await getSession(request.headers.get(\"Cookie\"));",
|
|
169
|
+
" const email = session.get(\"email\");",
|
|
170
|
+
" const user = await GetUser(email);",
|
|
171
|
+
" if (!user) return redirect(\"/authportal/auth/login\");",
|
|
172
|
+
" try {",
|
|
173
|
+
" const salesData = await prisma.clientApts.findMany({",
|
|
174
|
+
" where: { userId: user.id },",
|
|
175
|
+
" orderBy: { createdAt: \"desc\" },",
|
|
176
|
+
" // take: 20,",
|
|
177
|
+
" });",
|
|
178
|
+
" const Delivery = await prisma.clientApts.findMany({",
|
|
179
|
+
" where: { apptStatus: \"Delivery\" },",
|
|
180
|
+
" orderBy: { createdAt: \"desc\" },",
|
|
181
|
+
" });",
|
|
182
|
+
" const clientfiles = await prisma.clientfile.findMany({",
|
|
183
|
+
" orderBy: { createdAt: \"desc\" },",
|
|
184
|
+
" take: 20,",
|
|
185
|
+
" });",
|
|
186
|
+
" const data = { salesData, Delivery, clientfiles, user };",
|
|
187
|
+
" console.log(data, \"laoder data\");",
|
|
188
|
+
" return cors(request, json({ data }), {",
|
|
189
|
+
" origin: \"http://localhost:3003\", // Replace with the Vite app's origin",
|
|
190
|
+
" methods: [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\"], // Allowed methods",
|
|
191
|
+
" headers: [\"Content-Type\", \"Authorization\"], // Allowed headers",
|
|
192
|
+
" credentials: true, // Allow credentials",
|
|
193
|
+
" });",
|
|
194
|
+
" } catch (error) {",
|
|
195
|
+
" console.error(\"Error in getUser route:\", error);",
|
|
196
|
+
" return json({ error: \"Internal Server Error\" });",
|
|
197
|
+
" }",
|
|
198
|
+
"}"
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"toggle_prev_state": {
|
|
202
|
+
"prefix": "toggle-prev-state",
|
|
203
|
+
"description": "Custom snippet from toggle-prev-state.snippet.tsx",
|
|
204
|
+
"scope": "typescript,typescriptreact",
|
|
205
|
+
"body": [
|
|
206
|
+
"(prev) => !prev"
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
"links_function": {
|
|
210
|
+
"prefix": "links_function",
|
|
211
|
+
"body": [
|
|
212
|
+
"export const links: LinksFunction = () => {\r\n return [\r\n { rel: \"stylesheet\", href: \"/styles/page.css\" },\r\n { rel: \"preload\", href: \"/images/hero.jpg\", as: \"image\" },\r\n ];\r\n};"
|
|
213
|
+
],
|
|
214
|
+
"description": "",
|
|
215
|
+
"scope": "jsx / tsx"
|
|
216
|
+
},
|
|
217
|
+
"headers": {
|
|
218
|
+
"prefix": "headers",
|
|
219
|
+
"description": "Custom snippet from headers.snippet.tsx",
|
|
220
|
+
"scope": "typescript,typescriptreact",
|
|
221
|
+
"body": [
|
|
222
|
+
"export const headers = ({ loaderHeaders, parentHeaders }) => {",
|
|
223
|
+
" return {",
|
|
224
|
+
" \"Cache-Control\": \"no-store\",",
|
|
225
|
+
" \"Custom-Header\": \"value\",",
|
|
226
|
+
" };",
|
|
227
|
+
"};"
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
"action": {
|
|
231
|
+
"prefix": "action",
|
|
232
|
+
"body": [
|
|
233
|
+
"import { json, redirect, type LoaderArgs, type ActionArgs } from \"@remix-run/node\";\r\nimport { prisma } from \"~/libs\";\r\nimport { authSessionStorage } from \"~/sessions/auth-session.server\";\r\nimport eP from \"~/utils/ext.server\";\r\nimport axios from \"axios\";\r\n\r\nexport async function action({ request }: ActionArgs) {\r\n const session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\");\r\n const user = await eP.user.simple(email)\r\n if (!user) { return redirect(process.env.LOGIN); }\r\n\r\n const d = Object.fromEntries(await request.formData());\r\n const intent = d.intent\r\n\r\n try {\r\n if (intent === 'createFunction') {\r\n const result = await prisma.Function.create({\r\n data: {\r\n ...data\r\n }\r\n });\r\n return json({ success: true, result });\r\n } else if (intent === 'updateFunction') {\r\n const result = await prisma.Function.update({\r\n where: { id: String(id) },\r\n data\r\n });\r\n return json({ success: true, result });\r\n } else if (intent === 'deleteFunction') {\r\n const result = await prisma.Function.delete ({\r\n where: { id: String(id) },\r\n\r\n });\r\n return json({ success: true, result });\r\n } else {\r\n return json({ success: false, error: \"Invalid intent\" }, { status: 400 });\r\n }\r\n\r\n } catch (error) {\r\n return json({\r\n success: false,\r\n error: error instanceof Error ? error.message : \"Unknown error\"\r\n }, { status: 500 });\r\n }\r\n}"
|
|
234
|
+
],
|
|
235
|
+
"description": "",
|
|
236
|
+
"scope": "jsx / tsx"
|
|
237
|
+
},
|
|
238
|
+
"session_loader": {
|
|
239
|
+
"prefix": "session-loader",
|
|
240
|
+
"description": "Custom snippet from session-loader.snippet.tsx",
|
|
241
|
+
"scope": "typescript,typescriptreact",
|
|
242
|
+
"body": [
|
|
243
|
+
"import { type LoaderFunction, json, redirect } from \"@remix-run/node\";",
|
|
244
|
+
"import { getSession, commitSession } from \"~/sessions/auth-session.server\";",
|
|
245
|
+
"export async function loader({ request }: LoaderFunction) {",
|
|
246
|
+
" const session = await getSession(request.headers.get(\"Cookie\"));",
|
|
247
|
+
" const user = session.get(\"user\");",
|
|
248
|
+
" if (!user) {",
|
|
249
|
+
" return redirect(\"/login\", {",
|
|
250
|
+
" headers: {",
|
|
251
|
+
" \"Set-Cookie\": await commitSession(session),",
|
|
252
|
+
" },",
|
|
253
|
+
" });",
|
|
254
|
+
" }",
|
|
255
|
+
" return json({ user }, {",
|
|
256
|
+
" headers: {",
|
|
257
|
+
" \"Set-Cookie\": await commitSession(session),",
|
|
258
|
+
" },",
|
|
259
|
+
" });",
|
|
260
|
+
"}"
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"seo_handle": {
|
|
264
|
+
"prefix": "seo-handle",
|
|
265
|
+
"description": "Custom snippet from seo-handle.snippet.tsx",
|
|
266
|
+
"scope": "typescript,typescriptreact",
|
|
267
|
+
"body": [
|
|
268
|
+
"export const handle: SEOHandle = {",
|
|
269
|
+
" getSitemapEntries: () => {",
|
|
270
|
+
" return [",
|
|
271
|
+
" { url: \"/home\", changefreq: \"daily\", priority: 1.0 },",
|
|
272
|
+
" { url: \"/about\", changefreq: \"monthly\", priority: 0.8 },",
|
|
273
|
+
" ];",
|
|
274
|
+
" },",
|
|
275
|
+
"};"
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
"handle_for_use_with_usematches": {
|
|
279
|
+
"prefix": "handle-for-use-with-usematches",
|
|
280
|
+
"description": "Custom snippet from handle-for-use-with-usematches.snippet.tsx",
|
|
281
|
+
"scope": "typescript,typescriptreact",
|
|
282
|
+
"body": [
|
|
283
|
+
"export const handle = {",
|
|
284
|
+
" $1,",
|
|
285
|
+
"};"
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
"error_boundary": {
|
|
289
|
+
"prefix": "error_boundary",
|
|
290
|
+
"body": [
|
|
291
|
+
"export function ErrorBoundary() {\r\n const error = useRouteError();\r\n \r\n if (isRouteErrorResponse(error)) {\r\n return (\r\n <div className=\"error-container\">\r\n <h1>\r\n {error.status} {error.statusText}\r\n </h1>\r\n <p>{error.data}</p>\r\n </div>\r\n );\r\n }\r\n \r\n return (\r\n <div className=\"error-container\">\r\n <h1>Something went wrong</h1>\r\n <p>{error?.message || 'Unknown error occurred'}</p>\r\n </div>\r\n );\r\n}"
|
|
292
|
+
],
|
|
293
|
+
"description": "",
|
|
294
|
+
"scope": "jsx / tsx"
|
|
295
|
+
},
|
|
296
|
+
"meta_function": {
|
|
297
|
+
"prefix": "meta_function",
|
|
298
|
+
"body": [
|
|
299
|
+
"export const meta: MetaFunction<typeof loader> = ({ data, params }) => {\r\n return [\r\n { title: \"Page Title\" },\r\n { name: \"description\", content: \"Page description\" },\r\n { name: \"keywords\", content: \"remix, react, typescript\" },\r\n { property: \"og:title\", content: \"Page Title\" },\r\n { property: \"og:description\", content: \"Page description\" },\r\n { property: \"og:type\", content: \"website\" },\r\n ];\r\n};"
|
|
300
|
+
],
|
|
301
|
+
"description": "",
|
|
302
|
+
"scope": "jsx / tsx"
|
|
303
|
+
},
|
|
304
|
+
"headers_function": {
|
|
305
|
+
"prefix": "headers-function-static",
|
|
306
|
+
"description": "Custom snippet from headers-function.snippet.tsx",
|
|
307
|
+
"scope": "typescript,typescriptreact",
|
|
308
|
+
"body": [
|
|
309
|
+
"export const headers = ({ loaderHeaders, parentHeaders }) => {",
|
|
310
|
+
" return {",
|
|
311
|
+
" \"Content-Type\": \"application/json\",",
|
|
312
|
+
" };",
|
|
313
|
+
"};export const headers = ({ loaderHeaders, parentHeaders }) => {",
|
|
314
|
+
" return {",
|
|
315
|
+
" \"Content-Type\": \"application/json\",",
|
|
316
|
+
" };",
|
|
317
|
+
" };"
|
|
318
|
+
]
|
|
319
|
+
},
|
|
320
|
+
"client_only_with_out_remix_utils": {
|
|
321
|
+
"prefix": "client_only_with_out_remix-utils",
|
|
322
|
+
"description": "Custom snippet from client-only-with-out-remix-utils.snippet.tsx",
|
|
323
|
+
"scope": "typescript,typescriptreact",
|
|
324
|
+
"body": [
|
|
325
|
+
"import type { MetaFunction } from '@remix-run/cloudflare';",
|
|
326
|
+
"import React, { lazy, Suspense } from 'react';",
|
|
327
|
+
"import 'easymde/dist/easymde.min.css';",
|
|
328
|
+
"const SimpleMDE = lazy(async () => {",
|
|
329
|
+
" const module = await import('react-simplemde-editor');",
|
|
330
|
+
" return { default: module.default };",
|
|
331
|
+
"});",
|
|
332
|
+
"export const meta: MetaFunction = () => {",
|
|
333
|
+
" return { title: 'Simple MDE Editor' };",
|
|
334
|
+
"};",
|
|
335
|
+
"export default function Index() {",
|
|
336
|
+
" return (",
|
|
337
|
+
" <div>",
|
|
338
|
+
" <h1>Simple MDE</h1>",
|
|
339
|
+
" <Suspense fallback={<div>Loading...</div>}>",
|
|
340
|
+
" <SimpleMDE />",
|
|
341
|
+
" </Suspense>",
|
|
342
|
+
" </div>",
|
|
343
|
+
" );",
|
|
344
|
+
"}"
|
|
345
|
+
]
|
|
346
|
+
},
|
|
347
|
+
"client_only_with_remix_utils": {
|
|
348
|
+
"prefix": "client_only_with_remix_utils",
|
|
349
|
+
"description": "Custom snippet from client-only-with-remix-utils.snippet.tsx",
|
|
350
|
+
"scope": "typescript,typescriptreact",
|
|
351
|
+
"body": [
|
|
352
|
+
"import { ClientOnly } from 'remix-utils';",
|
|
353
|
+
"export default function MainApp() {",
|
|
354
|
+
" return (",
|
|
355
|
+
" <div className='h-screen justify-center bg-background'>",
|
|
356
|
+
" <ClientOnly fallback={<p>Fallback component ...</p>}>",
|
|
357
|
+
" {() => <App />}",
|
|
358
|
+
" </ClientOnly>",
|
|
359
|
+
" </div>",
|
|
360
|
+
" );",
|
|
361
|
+
"}"
|
|
362
|
+
]
|
|
363
|
+
},
|
|
364
|
+
"form_appearance": {
|
|
365
|
+
"prefix": "form_appearance",
|
|
366
|
+
"description": "Custom snippet from form-appearance.snippet.tsx",
|
|
367
|
+
"scope": "typescript,typescriptreact",
|
|
368
|
+
"body": [
|
|
369
|
+
"import { zodResolver } from \"@hookform/resolvers/zod\"",
|
|
370
|
+
"import { ChevronDown } from \"lucide-react\"",
|
|
371
|
+
"import { useForm } from \"react-hook-form\"",
|
|
372
|
+
"import { z } from \"zod\"",
|
|
373
|
+
"import { cn } from \"~/components/ui/utils\"",
|
|
374
|
+
"import { toast } from \"~/hooks/use-toast\"",
|
|
375
|
+
"import { Button, buttonVariants } from \"/components/ui/button\"",
|
|
376
|
+
"import {",
|
|
377
|
+
" Form,",
|
|
378
|
+
" FormControl,",
|
|
379
|
+
" FormDescription,",
|
|
380
|
+
" FormField,",
|
|
381
|
+
" FormItem,",
|
|
382
|
+
" FormLabel,",
|
|
383
|
+
" FormMessage,",
|
|
384
|
+
"} from \"/components/ui/form\"",
|
|
385
|
+
"import { RadioGroup, RadioGroupItem } from \"/components/ui/radio-group\"",
|
|
386
|
+
"const appearanceFormSchema = z.object({",
|
|
387
|
+
" theme: z.enum([\"light\", \"dark\"], {",
|
|
388
|
+
" required_error: \"Please select a theme.\",",
|
|
389
|
+
" }),",
|
|
390
|
+
" font: z.enum([\"inter\", \"manrope\", \"system\"], {",
|
|
391
|
+
" invalid_type_error: \"Select a font\",",
|
|
392
|
+
" required_error: \"Please select a font.\",",
|
|
393
|
+
" }),",
|
|
394
|
+
"})",
|
|
395
|
+
"type AppearanceFormValues = z.infer<typeof appearanceFormSchema>",
|
|
396
|
+
"// This can come from your database or API.",
|
|
397
|
+
"const defaultValues: Partial<AppearanceFormValues> = {",
|
|
398
|
+
" theme: \"light\",",
|
|
399
|
+
"}",
|
|
400
|
+
"export function AppearanceForm() {",
|
|
401
|
+
" const form = useForm<AppearanceFormValues>({",
|
|
402
|
+
" resolver: zodResolver(appearanceFormSchema),",
|
|
403
|
+
" defaultValues,",
|
|
404
|
+
" })",
|
|
405
|
+
" function onSubmit(data: AppearanceFormValues) {",
|
|
406
|
+
" toast({",
|
|
407
|
+
" title: \"You submitted the following values:\",",
|
|
408
|
+
" description: (",
|
|
409
|
+
" <pre className=\"mt-2 w-[340px] rounded-md bg-slate-950 p-4\">",
|
|
410
|
+
" <code className=\"text-white\">{JSON.stringify(data, null, 2)}</code>",
|
|
411
|
+
" </pre>",
|
|
412
|
+
" ),",
|
|
413
|
+
" })",
|
|
414
|
+
" }",
|
|
415
|
+
" return (",
|
|
416
|
+
" <Form {...form}>",
|
|
417
|
+
" <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-8\">",
|
|
418
|
+
" <FormField",
|
|
419
|
+
" control={form.control}",
|
|
420
|
+
" name=\"font\"",
|
|
421
|
+
" render={({ field }) => (",
|
|
422
|
+
" <FormItem>",
|
|
423
|
+
" <FormLabel>Font</FormLabel>",
|
|
424
|
+
" <div className=\"relative w-max\">",
|
|
425
|
+
" <FormControl>",
|
|
426
|
+
" <select",
|
|
427
|
+
" className={cn(",
|
|
428
|
+
" buttonVariants({ variant: \"outline\" }),",
|
|
429
|
+
" \"w-[200px] appearance-none font-normal\"",
|
|
430
|
+
" )}",
|
|
431
|
+
" {...field}",
|
|
432
|
+
" >",
|
|
433
|
+
" <option value=\"inter\">Inter</option>",
|
|
434
|
+
" <option value=\"manrope\">Manrope</option>",
|
|
435
|
+
" <option value=\"system\">System</option>",
|
|
436
|
+
" </select>",
|
|
437
|
+
" </FormControl>",
|
|
438
|
+
" <ChevronDown className=\"absolute right-3 top-2.5 h-4 w-4 opacity-50\" />",
|
|
439
|
+
" </div>",
|
|
440
|
+
" <FormDescription>",
|
|
441
|
+
" Set the font you want to use in the dashboard.",
|
|
442
|
+
" </FormDescription>",
|
|
443
|
+
" <FormMessage />",
|
|
444
|
+
" </FormItem>",
|
|
445
|
+
" )}",
|
|
446
|
+
" />",
|
|
447
|
+
" <FormField",
|
|
448
|
+
" control={form.control}",
|
|
449
|
+
" name=\"theme\"",
|
|
450
|
+
" render={({ field }) => (",
|
|
451
|
+
" <FormItem className=\"space-y-1\">",
|
|
452
|
+
" <FormLabel>Theme</FormLabel>",
|
|
453
|
+
" <FormDescription>",
|
|
454
|
+
" Select the theme for the dashboard.",
|
|
455
|
+
" </FormDescription>",
|
|
456
|
+
" <FormMessage />",
|
|
457
|
+
" <RadioGroup",
|
|
458
|
+
" onValueChange={field.onChange}",
|
|
459
|
+
" defaultValue={field.value}",
|
|
460
|
+
" className=\"grid max-w-md grid-cols-2 gap-8 pt-2\"",
|
|
461
|
+
" >",
|
|
462
|
+
" <FormItem>",
|
|
463
|
+
" <FormLabel className=\"[&:has([data-state=checked])>div]:border-primary\">",
|
|
464
|
+
" <FormControl>",
|
|
465
|
+
" <RadioGroupItem value=\"light\" className=\"sr-only\" />",
|
|
466
|
+
" </FormControl>",
|
|
467
|
+
" <div className=\"items-center rounded-md border-2 border-muted p-1 hover:border-accent\">",
|
|
468
|
+
" <div className=\"space-y-2 rounded-sm bg-[#ecedef] p-2\">",
|
|
469
|
+
" <div className=\"space-y-2 rounded-md bg-white p-2 shadow-sm\">",
|
|
470
|
+
" <div className=\"h-2 w-[80px] rounded-lg bg-[#ecedef]\" />",
|
|
471
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-[#ecedef]\" />",
|
|
472
|
+
" </div>",
|
|
473
|
+
" <div className=\"flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm\">",
|
|
474
|
+
" <div className=\"h-4 w-4 rounded-full bg-[#ecedef]\" />",
|
|
475
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-[#ecedef]\" />",
|
|
476
|
+
" </div>",
|
|
477
|
+
" <div className=\"flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm\">",
|
|
478
|
+
" <div className=\"h-4 w-4 rounded-full bg-[#ecedef]\" />",
|
|
479
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-[#ecedef]\" />",
|
|
480
|
+
" </div>",
|
|
481
|
+
" </div>",
|
|
482
|
+
" </div>",
|
|
483
|
+
" <span className=\"block w-full p-2 text-center font-normal\">",
|
|
484
|
+
" Light",
|
|
485
|
+
" </span>",
|
|
486
|
+
" </FormLabel>",
|
|
487
|
+
" </FormItem>",
|
|
488
|
+
" <FormItem>",
|
|
489
|
+
" <FormLabel className=\"[&:has([data-state=checked])>div]:border-primary\">",
|
|
490
|
+
" <FormControl>",
|
|
491
|
+
" <RadioGroupItem value=\"dark\" className=\"sr-only\" />",
|
|
492
|
+
" </FormControl>",
|
|
493
|
+
" <div className=\"items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground\">",
|
|
494
|
+
" <div className=\"space-y-2 rounded-sm bg-slate-950 p-2\">",
|
|
495
|
+
" <div className=\"space-y-2 rounded-md bg-slate-800 p-2 shadow-sm\">",
|
|
496
|
+
" <div className=\"h-2 w-[80px] rounded-lg bg-slate-400\" />",
|
|
497
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-slate-400\" />",
|
|
498
|
+
" </div>",
|
|
499
|
+
" <div className=\"flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm\">",
|
|
500
|
+
" <div className=\"h-4 w-4 rounded-full bg-slate-400\" />",
|
|
501
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-slate-400\" />",
|
|
502
|
+
" </div>",
|
|
503
|
+
" <div className=\"flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm\">",
|
|
504
|
+
" <div className=\"h-4 w-4 rounded-full bg-slate-400\" />",
|
|
505
|
+
" <div className=\"h-2 w-[100px] rounded-lg bg-slate-400\" />",
|
|
506
|
+
" </div>",
|
|
507
|
+
" </div>",
|
|
508
|
+
" </div>",
|
|
509
|
+
" <span className=\"block w-full p-2 text-center font-normal\">",
|
|
510
|
+
" Dark",
|
|
511
|
+
" </span>",
|
|
512
|
+
" </FormLabel>",
|
|
513
|
+
" </FormItem>",
|
|
514
|
+
" </RadioGroup>",
|
|
515
|
+
" </FormItem>",
|
|
516
|
+
" )}",
|
|
517
|
+
" />",
|
|
518
|
+
" <Button type=\"submit\">Update preferences</Button>",
|
|
519
|
+
" </form>",
|
|
520
|
+
" </Form>",
|
|
521
|
+
" )",
|
|
522
|
+
"}"
|
|
523
|
+
]
|
|
524
|
+
},
|
|
525
|
+
"cards_create_cookie": {
|
|
526
|
+
"prefix": "cards_create_cookie",
|
|
527
|
+
"description": "Custom snippet from cards-create-cookie.snippet.tsx",
|
|
528
|
+
"scope": "typescript,typescriptreact",
|
|
529
|
+
"body": [
|
|
530
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
531
|
+
"import {",
|
|
532
|
+
" Card,",
|
|
533
|
+
" CardContent,",
|
|
534
|
+
" CardDescription,",
|
|
535
|
+
" CardFooter,",
|
|
536
|
+
" CardHeader,",
|
|
537
|
+
" CardTitle,",
|
|
538
|
+
"} from \"~/components/ui/card\"",
|
|
539
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
540
|
+
"import { Switch } from \"~/components/ui/switch\"",
|
|
541
|
+
"export function DemoCookieSettings() {",
|
|
542
|
+
" return (",
|
|
543
|
+
" <Card>",
|
|
544
|
+
" <CardHeader>",
|
|
545
|
+
" <CardTitle>Cookie Settings</CardTitle>",
|
|
546
|
+
" <CardDescription>Manage your cookie settings here.</CardDescription>",
|
|
547
|
+
" </CardHeader>",
|
|
548
|
+
" <CardContent className=\"grid gap-6\">",
|
|
549
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
550
|
+
" <Label htmlFor=\"necessary\" className=\"flex flex-col space-y-1\">",
|
|
551
|
+
" <span>Strictly Necessary</span>",
|
|
552
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
553
|
+
" These cookies are essential in order to use the website and use",
|
|
554
|
+
" its features.",
|
|
555
|
+
" </span>",
|
|
556
|
+
" </Label>",
|
|
557
|
+
" <Switch id=\"necessary\" defaultChecked />",
|
|
558
|
+
" </div>",
|
|
559
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
560
|
+
" <Label htmlFor=\"functional\" className=\"flex flex-col space-y-1\">",
|
|
561
|
+
" <span>Functional Cookies</span>",
|
|
562
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
563
|
+
" These cookies allow the website to provide personalized",
|
|
564
|
+
" functionality.",
|
|
565
|
+
" </span>",
|
|
566
|
+
" </Label>",
|
|
567
|
+
" <Switch id=\"functional\" />",
|
|
568
|
+
" </div>",
|
|
569
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
570
|
+
" <Label htmlFor=\"performance\" className=\"flex flex-col space-y-1\">",
|
|
571
|
+
" <span>Performance Cookies</span>",
|
|
572
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
573
|
+
" These cookies help to improve the performance of the website.",
|
|
574
|
+
" </span>",
|
|
575
|
+
" </Label>",
|
|
576
|
+
" <Switch id=\"performance\" />",
|
|
577
|
+
" </div>",
|
|
578
|
+
" </CardContent>",
|
|
579
|
+
" <CardFooter>",
|
|
580
|
+
" <Button variant=\"outline\" className=\"w-full\">",
|
|
581
|
+
" Save preferences",
|
|
582
|
+
" </Button>",
|
|
583
|
+
" </CardFooter>",
|
|
584
|
+
" </Card>",
|
|
585
|
+
" )",
|
|
586
|
+
"}"
|
|
587
|
+
]
|
|
588
|
+
},
|
|
589
|
+
"cards_create_account": {
|
|
590
|
+
"prefix": "cards_create_account",
|
|
591
|
+
"description": "Custom snippet from cards-create-account.snippet.tsx",
|
|
592
|
+
"scope": "typescript,typescriptreact",
|
|
593
|
+
"body": [
|
|
594
|
+
"\"use client\"",
|
|
595
|
+
"import { Icons } from \"~/components/icons\"",
|
|
596
|
+
"import { Button } from \"~/registry/new-york/ui/button\"",
|
|
597
|
+
"import {",
|
|
598
|
+
" Card,",
|
|
599
|
+
" CardContent,",
|
|
600
|
+
" CardDescription,",
|
|
601
|
+
" CardFooter,",
|
|
602
|
+
" CardHeader,",
|
|
603
|
+
" CardTitle,",
|
|
604
|
+
"} from \"~/components/ui/card\"",
|
|
605
|
+
"import { Input } from \"~/components/ui/input\"",
|
|
606
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
607
|
+
"export function DemoCreateAccount() {",
|
|
608
|
+
" return (",
|
|
609
|
+
" <Card>",
|
|
610
|
+
" <CardHeader className=\"space-y-1\">",
|
|
611
|
+
" <CardTitle className=\"text-2xl\">Create an account</CardTitle>",
|
|
612
|
+
" <CardDescription>",
|
|
613
|
+
" Enter your email below to create your account",
|
|
614
|
+
" </CardDescription>",
|
|
615
|
+
" </CardHeader>",
|
|
616
|
+
" <CardContent className=\"grid gap-4\">",
|
|
617
|
+
" <div className=\"grid grid-cols-2 gap-6\">",
|
|
618
|
+
" <Button variant=\"outline\">",
|
|
619
|
+
" <Icons.gitHub className=\"mr-2 h-4 w-4\" />",
|
|
620
|
+
" Github",
|
|
621
|
+
" </Button>",
|
|
622
|
+
" <Button variant=\"outline\">",
|
|
623
|
+
" <Icons.google className=\"mr-2 h-4 w-4\" />",
|
|
624
|
+
" Google",
|
|
625
|
+
" </Button>",
|
|
626
|
+
" </div>",
|
|
627
|
+
" <div className=\"relative\">",
|
|
628
|
+
" <div className=\"absolute inset-0 flex items-center\">",
|
|
629
|
+
" <span className=\"w-full border-t\" />",
|
|
630
|
+
" </div>",
|
|
631
|
+
" <div className=\"relative flex justify-center text-xs uppercase\">",
|
|
632
|
+
" <span className=\"bg-background px-2 text-muted-foreground\">",
|
|
633
|
+
" Or continue with",
|
|
634
|
+
" </span>",
|
|
635
|
+
" </div>",
|
|
636
|
+
" </div>",
|
|
637
|
+
" <div className=\"grid gap-2\">",
|
|
638
|
+
" <Label htmlFor=\"email\">Email</Label>",
|
|
639
|
+
" <Input id=\"email\" type=\"email\" placeholder=\"m@example.com\" />",
|
|
640
|
+
" </div>",
|
|
641
|
+
" <div className=\"grid gap-2\">",
|
|
642
|
+
" <Label htmlFor=\"password\">Password</Label>",
|
|
643
|
+
" <Input id=\"password\" type=\"password\" />",
|
|
644
|
+
" </div>",
|
|
645
|
+
" </CardContent>",
|
|
646
|
+
" <CardFooter>",
|
|
647
|
+
" <Button className=\"w-full\">Create account</Button>",
|
|
648
|
+
" </CardFooter>",
|
|
649
|
+
" </Card>",
|
|
650
|
+
" )",
|
|
651
|
+
"}"
|
|
652
|
+
]
|
|
653
|
+
},
|
|
654
|
+
"authenticator": {
|
|
655
|
+
"prefix": "authenticator",
|
|
656
|
+
"description": "import { commitSession, getSession, sessionStorage } from \"./session.server\";",
|
|
657
|
+
"scope": "import { prisma } from \"~/lib/prisma.server\";",
|
|
658
|
+
"body": [
|
|
659
|
+
"import { json, LoaderFunction, ActionFunction } from \"@remix-run/node\";",
|
|
660
|
+
"import { MobileGitHubService, noteObject } from \"~/utils/github.server\";",
|
|
661
|
+
"export async function authenticate(request: Request, returnTo?: string) {",
|
|
662
|
+
" const session = await sessionStorage.getSession(request.headers.get(\"cookie\"));",
|
|
663
|
+
" const sessionUser = await session.get(\"user\");",
|
|
664
|
+
" if (sessionUser) {",
|
|
665
|
+
" const dbUser = await prisma.user.findUnique({ where: { email: sessionUser.email } });",
|
|
666
|
+
" if (!dbUser) {",
|
|
667
|
+
" throw redirect(\"/login\", { headers: { \"Set-Cookie\": await sessionStorage.commitSession(session) }, });",
|
|
668
|
+
" }",
|
|
669
|
+
" const mergedUser = {",
|
|
670
|
+
" id: sessionUser.id ? sessionUser.id : dbUser.id,",
|
|
671
|
+
" email: sessionUser.email ? sessionUser.email : dbUser.email,",
|
|
672
|
+
" username: sessionUser.username ? sessionUser.username : dbUser.username,",
|
|
673
|
+
" githubId: sessionUser.githubId ? sessionUser.githubId : dbUser.githubId,",
|
|
674
|
+
" url: sessionUser.url ? sessionUser.url : dbUser.url,",
|
|
675
|
+
" branch: sessionUser.branch ? sessionUser.branch : dbUser.branch,",
|
|
676
|
+
" repoId: sessionUser.repoId ? sessionUser.repoId : dbUser.repoId,",
|
|
677
|
+
" name: sessionUser.name ? sessionUser.name : dbUser.name,",
|
|
678
|
+
" owner: sessionUser.owner ? sessionUser.owner : dbUser.owner,",
|
|
679
|
+
" private: sessionUser.private ? sessionUser.private : dbUser.private,",
|
|
680
|
+
" autoSync: sessionUser.autoSync ? sessionUser.autoSync : dbUser.autoSync,",
|
|
681
|
+
" accessToken: sessionUser.accessToken ? sessionUser.accessToken : dbUser.accessToken,",
|
|
682
|
+
" refreshToken: sessionUser.refreshToken ? sessionUser.refreshToken : dbUser.refreshToken,",
|
|
683
|
+
" };",
|
|
684
|
+
" await session.set(\"user\", mergedUser);",
|
|
685
|
+
" return {",
|
|
686
|
+
" user: mergedUser,",
|
|
687
|
+
" headers: { \"Set-Cookie\": await sessionStorage.commitSession(session) }",
|
|
688
|
+
" };",
|
|
689
|
+
" }",
|
|
690
|
+
" if (returnTo) session.set(\"returnTo\", returnTo);",
|
|
691
|
+
" throw redirect(\"/login\", {",
|
|
692
|
+
" headers: { \"Set-Cookie\": await sessionStorage.commitSession(session) },",
|
|
693
|
+
" });",
|
|
694
|
+
"}"
|
|
695
|
+
]
|
|
696
|
+
},
|
|
697
|
+
"getHandlesync": {
|
|
698
|
+
"prefix": "get_handlesync",
|
|
699
|
+
"description": "gethandlesync",
|
|
700
|
+
"scope": "typescript,typescriptreact",
|
|
701
|
+
"body": [
|
|
702
|
+
"import { redirect } from \"@remix-run/node\";",
|
|
703
|
+
"import { commitSession, getSession, sessionStorage } from \"./session.server\";",
|
|
704
|
+
"import { prisma } from \"~/lib/prisma.server\";",
|
|
705
|
+
"import { json, LoaderFunction, ActionFunction } from \"@remix-run/node\";",
|
|
706
|
+
"import { MobileGitHubService, noteObject } from \"~/utils/github.server\";",
|
|
707
|
+
"export async function getHandleSync(request: Request) {",
|
|
708
|
+
" const session = await sessionStorage.getSession(request.headers.get(\"cookie\"));",
|
|
709
|
+
" const sessionUser = await session.get(\"user\");",
|
|
710
|
+
" const dbUser = await prisma.user.findUnique({ where: { email: sessionUser.email } });",
|
|
711
|
+
" if (!dbUser) { throw redirect(\"/login\", { headers: { \"Set-Cookie\": await sessionStorage.commitSession(session) } }); }",
|
|
712
|
+
" const mergedUser = {",
|
|
713
|
+
" id: sessionUser.id ? sessionUser.id : dbUser.id,",
|
|
714
|
+
" email: sessionUser.email ? sessionUser.email : dbUser.email,",
|
|
715
|
+
" username: sessionUser.username ? sessionUser.username : dbUser.username,",
|
|
716
|
+
" githubId: sessionUser.githubId ? sessionUser.githubId : dbUser.githubId,",
|
|
717
|
+
" url: sessionUser.url ? sessionUser.url : dbUser.url,",
|
|
718
|
+
" branch: sessionUser.branch ? sessionUser.branch : dbUser.branch,",
|
|
719
|
+
" repoId: sessionUser.repoId ? sessionUser.repoId : dbUser.repoId,",
|
|
720
|
+
" name: sessionUser.name ? sessionUser.name : dbUser.name,",
|
|
721
|
+
" owner: sessionUser.owner ? sessionUser.owner : dbUser.owner,",
|
|
722
|
+
" private: sessionUser.private ? sessionUser.private : dbUser.private,",
|
|
723
|
+
" autoSync: sessionUser.autoSync ? sessionUser.autoSync : dbUser.autoSync,",
|
|
724
|
+
" accessToken: sessionUser.accessToken ? sessionUser.accessToken : dbUser.accessToken,",
|
|
725
|
+
" refreshToken: sessionUser.refreshToken ? sessionUser.refreshToken : dbUser.refreshToken,",
|
|
726
|
+
" };",
|
|
727
|
+
" const accessToken = import.meta.env.VITE_ACCESS_TOKEN",
|
|
728
|
+
" const githubService = new MobileGitHubService(accessToken);",
|
|
729
|
+
" const notes = await prisma.note.findMany({ where: { User: { email: user.email } }, select: noteObject })",
|
|
730
|
+
" return {",
|
|
731
|
+
" user: mergedUser,",
|
|
732
|
+
" accessToken,",
|
|
733
|
+
" githubService,",
|
|
734
|
+
" notes",
|
|
735
|
+
" };",
|
|
736
|
+
"}"
|
|
737
|
+
]
|
|
738
|
+
},
|
|
739
|
+
"Display_Date_with_options": {
|
|
740
|
+
"prefix": "Display_Date_with_options",
|
|
741
|
+
"description": "Description_for_new_snippet",
|
|
742
|
+
"scope": "javascript, typescript",
|
|
743
|
+
"body": [
|
|
744
|
+
"const options = { weekday: \"short\", year: \"numeric\", month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\" };\nnew Date(d).toLocaleDateString(\"en-US\", options)"
|
|
745
|
+
]
|
|
746
|
+
},
|
|
747
|
+
"find_n_kill_process_on_port": {
|
|
748
|
+
"prefix": "find_n_kill_process_on_port",
|
|
749
|
+
"description": "Description_for_new_snippet",
|
|
750
|
+
"scope": "javascript, typescript",
|
|
751
|
+
"body": [
|
|
752
|
+
"taskkill /PID <PID> /F"
|
|
753
|
+
]
|
|
754
|
+
},
|
|
755
|
+
"load_dynamic_data_into_meta_function": {
|
|
756
|
+
"prefix": "load_dynamic_data_into_meta_function",
|
|
757
|
+
"description": "client_site_meta_and_loader",
|
|
758
|
+
"scope": "javascript, typescript",
|
|
759
|
+
"body": [
|
|
760
|
+
"import { type LoaderFunction, type MetaFunction, json } from '@remix-run/node';",
|
|
761
|
+
"import { dealerSelection, fullUserSelection } from '~/utils/loader.server';",
|
|
762
|
+
"import { prisma } from '~/libs';",
|
|
763
|
+
"",
|
|
764
|
+
"export async function loader({ request, params }: LoaderFunction) {",
|
|
765
|
+
" const d = await prisma.dealer.findUnique({ where: { id: 1 }, select: { dealerName: true, metaDesc: true} });",
|
|
766
|
+
" const URLS = { page: 'About Us' };",
|
|
767
|
+
" return json({",
|
|
768
|
+
" data: {",
|
|
769
|
+
" d: d,",
|
|
770
|
+
" URLS: URLS",
|
|
771
|
+
" }",
|
|
772
|
+
" });",
|
|
773
|
+
"}",
|
|
774
|
+
"",
|
|
775
|
+
"export const meta: MetaFunction<typeof loader> = ({ data }) => {",
|
|
776
|
+
" const { d, URLS } = data;",
|
|
777
|
+
" return [",
|
|
778
|
+
" { title: `${URLS.page} - ${d.dealerName}` },",
|
|
779
|
+
" { name: \"description\", keywords: \"Automotive Sales, dealership sales, automotive CRM, Service Center, Parts Department, Accessories Department, CRM, Dealership.\", content: d.metaDesc }",
|
|
780
|
+
" ];",
|
|
781
|
+
"};",
|
|
782
|
+
""
|
|
783
|
+
]
|
|
784
|
+
},
|
|
785
|
+
"shad_forms": {
|
|
786
|
+
"prefix": "shad_forms",
|
|
787
|
+
"description": "Description_for_new_snippet",
|
|
788
|
+
"scope": "javascript, typescript",
|
|
789
|
+
"body": [
|
|
790
|
+
"import { Metadata } from \"next\"",
|
|
791
|
+
"import Image from \"next/image\"",
|
|
792
|
+
"",
|
|
793
|
+
"import { Separator } from \"~/registry/new-york/ui/separator\"",
|
|
794
|
+
"import { SidebarNav } from \"~/app/(app)/examples/forms/components/sidebar-nav\"",
|
|
795
|
+
"",
|
|
796
|
+
"export const metadata: Metadata = {",
|
|
797
|
+
" title: \"Forms\",",
|
|
798
|
+
" description: \"Advanced form example using react-hook-form and Zod.\",",
|
|
799
|
+
"}",
|
|
800
|
+
"",
|
|
801
|
+
"const sidebarNavItems = [",
|
|
802
|
+
" {",
|
|
803
|
+
" title: \"Profile\",",
|
|
804
|
+
" href: \"/examples/forms\",",
|
|
805
|
+
" },",
|
|
806
|
+
" {",
|
|
807
|
+
" title: \"Account\",",
|
|
808
|
+
" href: \"/examples/forms/account\",",
|
|
809
|
+
" },",
|
|
810
|
+
" {",
|
|
811
|
+
" title: \"Appearance\",",
|
|
812
|
+
" href: \"/examples/forms/appearance\",",
|
|
813
|
+
" },",
|
|
814
|
+
" {",
|
|
815
|
+
" title: \"Notifications\",",
|
|
816
|
+
" href: \"/examples/forms/notifications\",",
|
|
817
|
+
" },",
|
|
818
|
+
" {",
|
|
819
|
+
" title: \"Display\",",
|
|
820
|
+
" href: \"/examples/forms/display\",",
|
|
821
|
+
" },",
|
|
822
|
+
"]",
|
|
823
|
+
"",
|
|
824
|
+
"interface SettingsLayoutProps {",
|
|
825
|
+
" children: React.ReactNode",
|
|
826
|
+
"}",
|
|
827
|
+
"",
|
|
828
|
+
"export default function SettingsLayout({ children }: SettingsLayoutProps) {",
|
|
829
|
+
" return (",
|
|
830
|
+
" <>",
|
|
831
|
+
" <div className=\"md:hidden\">",
|
|
832
|
+
" <Image",
|
|
833
|
+
" src=\"/examples/forms-light.png\"",
|
|
834
|
+
" width={1280}",
|
|
835
|
+
" height={791}",
|
|
836
|
+
" alt=\"Forms\"",
|
|
837
|
+
" className=\"block dark:hidden\"",
|
|
838
|
+
" />",
|
|
839
|
+
" <Image",
|
|
840
|
+
" src=\"/examples/forms-dark.png\"",
|
|
841
|
+
" width={1280}",
|
|
842
|
+
" height={791}",
|
|
843
|
+
" alt=\"Forms\"",
|
|
844
|
+
" className=\"hidden dark:block\"",
|
|
845
|
+
" />",
|
|
846
|
+
" </div>",
|
|
847
|
+
" <div className=\"hidden space-y-6 p-10 pb-16 md:block\">",
|
|
848
|
+
" <div className=\"space-y-0.5\">",
|
|
849
|
+
" <h2 className=\"text-2xl font-bold tracking-tight\">Settings</h2>",
|
|
850
|
+
" <p className=\"text-muted-foreground\">",
|
|
851
|
+
" Manage your account settings and set e-mail preferences.",
|
|
852
|
+
" </p>",
|
|
853
|
+
" </div>",
|
|
854
|
+
" <Separator className=\"my-6\" />",
|
|
855
|
+
" <div className=\"flex flex-col space-y-8 lg:flex-row lg:space-x-12 lg:space-y-0\">",
|
|
856
|
+
" <aside className=\"-mx-4 lg:w-1/5\">",
|
|
857
|
+
" <SidebarNav items={sidebarNavItems} />",
|
|
858
|
+
" </aside>",
|
|
859
|
+
" <div className=\"flex-1 lg:max-w-2xl\">{children}</div>",
|
|
860
|
+
" </div>",
|
|
861
|
+
" </div>",
|
|
862
|
+
" </>",
|
|
863
|
+
" )",
|
|
864
|
+
"}"
|
|
865
|
+
]
|
|
866
|
+
},
|
|
867
|
+
"working_roles_redirect": {
|
|
868
|
+
"prefix": "working_roles_redirect",
|
|
869
|
+
"description": "Description_for_new_snippet",
|
|
870
|
+
"scope": "javascript, typescript",
|
|
871
|
+
"body": [
|
|
872
|
+
"import { dealerFull } from \"~/utils/loader.server\"",
|
|
873
|
+
"import { useLoaderData } from \"@remix-run/react\"",
|
|
874
|
+
"import { json, redirect } from \"@remix-run/node\";",
|
|
875
|
+
"import { prisma } from \"~/libs\";",
|
|
876
|
+
"import { authSessionStorage, commitSession, destroySession, getSession, } from \"~/sessions/auth-session.server\";",
|
|
877
|
+
"",
|
|
878
|
+
"export async function loader({ request, params }: LoaderFunction) {",
|
|
879
|
+
" const d = await prisma.dealer.findUnique({ where: { id: 1 }, select: dealerFull });",
|
|
880
|
+
" const session = await getSession(request.headers.get(\"Cookie\"));",
|
|
881
|
+
" const email = session.get(\"email\");",
|
|
882
|
+
" const URLS = { page: 'Book Service' };",
|
|
883
|
+
" const u = await GetUser(email)",
|
|
884
|
+
" if (!u) { return redirect(process.env.LOGIN); }",
|
|
885
|
+
" const hasPosition = (positions, roles) => {",
|
|
886
|
+
" if (!positions || !Array.isArray(positions)) { return false; }",
|
|
887
|
+
" return positions.some((pos) => pos.position && roles.includes(pos.position));",
|
|
888
|
+
" };",
|
|
889
|
+
"",
|
|
890
|
+
" const isDev = hasPosition(u.positions, [\"DEV\"]);",
|
|
891
|
+
" const isManager = hasPosition(u.positions, [\"Manager\"]);",
|
|
892
|
+
" const isAdmin = hasPosition(u.positions, [\"Administrator\"]);",
|
|
893
|
+
"",
|
|
894
|
+
" if (!isDev && !isManager && !isAdmin) { return redirect('/portal/user/dashboard/settings'); }",
|
|
895
|
+
" return json({ URLS, d, client, u });",
|
|
896
|
+
"}",
|
|
897
|
+
""
|
|
898
|
+
]
|
|
899
|
+
},
|
|
900
|
+
"eP_import": {
|
|
901
|
+
"prefix": "eP_import",
|
|
902
|
+
"description": "Description_for_new_snippet",
|
|
903
|
+
"scope": "javascript, typescript",
|
|
904
|
+
"body": [
|
|
905
|
+
"import eP from '~/utils/ext.server'",
|
|
906
|
+
"const clients = await eP.clientfile.all()"
|
|
907
|
+
]
|
|
908
|
+
},
|
|
909
|
+
"filter": {
|
|
910
|
+
"prefix": "filter",
|
|
911
|
+
"description": "Description_for_new_snippet",
|
|
912
|
+
"scope": "javascript, typescript",
|
|
913
|
+
"body": [
|
|
914
|
+
"const filter = Highlight?.filter(h => h.model.model === modelH);"
|
|
915
|
+
]
|
|
916
|
+
},
|
|
917
|
+
"shad_cards_example": {
|
|
918
|
+
"prefix": "shad_cards_example",
|
|
919
|
+
"description": "Description_for_new_snippet",
|
|
920
|
+
"scope": "javascript, typescript",
|
|
921
|
+
"body": [
|
|
922
|
+
"import { cn } from \"~/components/ui/utils\"",
|
|
923
|
+
"import React from 'react'",
|
|
924
|
+
"import { ChevronDownIcon } from \"@radix-ui/react-icons\"",
|
|
925
|
+
"import { Avatar, AvatarFallback, AvatarImage,} from \"~/components/ui/avatar\"",
|
|
926
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
927
|
+
"import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from \"~/components/ui/card\"",
|
|
928
|
+
"import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList,} from \"~/components/ui/command\"",
|
|
929
|
+
"import { Popover, PopoverContent, PopoverTrigger,} from \"~/components/ui/popover\"",
|
|
930
|
+
"import { Input } from \"~/components/ui/input\"",
|
|
931
|
+
"import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from \"~/components/ui/select\"",
|
|
932
|
+
"import { Separator } from \"~/components/ui/separator\"",
|
|
933
|
+
"import { Textarea } from \"~/components/ui/textarea\"",
|
|
934
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
935
|
+
"import { RadioGroup, RadioGroupItem } from \"~/components/ui/radio-group\"",
|
|
936
|
+
"import { Icons } from \"~/components/icons\"",
|
|
937
|
+
"import { BellIcon, EyeNoneIcon, PersonIcon } from \"@radix-ui/react-icons\"",
|
|
938
|
+
"import { ChevronDownIcon, CircleIcon, PlusIcon, StarIcon,} from \"@radix-ui/react-icons\"",
|
|
939
|
+
"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger,} from \"~/components/ui/dropdown-menu\"",
|
|
940
|
+
"import { Switch } from \"~/components/ui/switch\"",
|
|
941
|
+
"function DemoContainer({",
|
|
942
|
+
" className,",
|
|
943
|
+
" ...props",
|
|
944
|
+
"}: React.HTMLAttributes<HTMLDivElement>) {",
|
|
945
|
+
" return (",
|
|
946
|
+
" <div",
|
|
947
|
+
" className={cn(",
|
|
948
|
+
" \"flex items-center justify-center [&>div]:w-full\",",
|
|
949
|
+
" className",
|
|
950
|
+
" )}",
|
|
951
|
+
" {...props}",
|
|
952
|
+
" />",
|
|
953
|
+
" )",
|
|
954
|
+
"}",
|
|
955
|
+
"export default function CardsPage() {",
|
|
956
|
+
" return (",
|
|
957
|
+
" <div className=\"hidden items-start justify-center gap-6 rounded-lg p-8 md:grid lg:grid-cols-2 xl:grid-cols-3\">",
|
|
958
|
+
" <div className=\"col-span-2 grid items-start gap-6 lg:col-span-1\">",
|
|
959
|
+
" <DemoContainer>",
|
|
960
|
+
" <DemoCreateAccount />",
|
|
961
|
+
" </DemoContainer>",
|
|
962
|
+
" <DemoContainer>",
|
|
963
|
+
" <DemoPaymentMethod />",
|
|
964
|
+
" </DemoContainer>",
|
|
965
|
+
" </div>",
|
|
966
|
+
" <div className=\"col-span-2 grid items-start gap-6 lg:col-span-1\">",
|
|
967
|
+
" <DemoContainer>",
|
|
968
|
+
" <DemoTeamMembers />",
|
|
969
|
+
" </DemoContainer>",
|
|
970
|
+
" <DemoContainer>",
|
|
971
|
+
" <DemoShareDocument />",
|
|
972
|
+
" </DemoContainer>",
|
|
973
|
+
" <DemoContainer>",
|
|
974
|
+
" <DemoDatePicker />",
|
|
975
|
+
" </DemoContainer>",
|
|
976
|
+
" <DemoContainer>",
|
|
977
|
+
" <DemoNotifications />",
|
|
978
|
+
" </DemoContainer>",
|
|
979
|
+
" </div>",
|
|
980
|
+
" <div className=\"col-span-2 grid items-start gap-6 lg:col-span-2 lg:grid-cols-2 xl:col-span-1 xl:grid-cols-1\">",
|
|
981
|
+
" <DemoContainer>",
|
|
982
|
+
" <DemoReportAnIssue />",
|
|
983
|
+
" </DemoContainer>",
|
|
984
|
+
" <DemoContainer>",
|
|
985
|
+
" <DemoGithub />",
|
|
986
|
+
" </DemoContainer>",
|
|
987
|
+
" <DemoContainer>",
|
|
988
|
+
" <DemoCookieSettings />",
|
|
989
|
+
" </DemoContainer>",
|
|
990
|
+
" </div>",
|
|
991
|
+
" </div>",
|
|
992
|
+
" )",
|
|
993
|
+
"}",
|
|
994
|
+
"function DemoTeamMembers() {",
|
|
995
|
+
" return (",
|
|
996
|
+
" <Card>",
|
|
997
|
+
" <CardHeader>",
|
|
998
|
+
" <CardTitle>Team Members</CardTitle>",
|
|
999
|
+
" <CardDescription>",
|
|
1000
|
+
" Invite your team members to collaborate.",
|
|
1001
|
+
" </CardDescription>",
|
|
1002
|
+
" </CardHeader>",
|
|
1003
|
+
" <CardContent className=\"grid gap-6\">",
|
|
1004
|
+
" <div className=\"flex items-center justify-between space-x-4\">",
|
|
1005
|
+
" <div className=\"flex items-center space-x-4\">",
|
|
1006
|
+
" <Avatar>",
|
|
1007
|
+
" <AvatarImage src=\"/avatars/01.png\" />",
|
|
1008
|
+
" <AvatarFallback>OM</AvatarFallback>",
|
|
1009
|
+
" </Avatar>",
|
|
1010
|
+
" <div>",
|
|
1011
|
+
" <p className=\"text-sm font-medium leading-none\">Sofia Davis</p>",
|
|
1012
|
+
" <p className=\"text-sm text-muted-foreground\">m@example.com</p>",
|
|
1013
|
+
" </div>",
|
|
1014
|
+
" </div>",
|
|
1015
|
+
" <Popover>",
|
|
1016
|
+
" <PopoverTrigger asChild>",
|
|
1017
|
+
" <Button variant=\"outline\" className=\"ml-auto\">",
|
|
1018
|
+
" Owner{\" \"}",
|
|
1019
|
+
" <ChevronDownIcon className=\"ml-2 h-4 w-4 text-muted-foreground\" />",
|
|
1020
|
+
" </Button>",
|
|
1021
|
+
" </PopoverTrigger>",
|
|
1022
|
+
" <PopoverContent className=\"p-0\" align=\"end\">",
|
|
1023
|
+
" <Command>",
|
|
1024
|
+
" <CommandInput placeholder=\"Select new role...\" />",
|
|
1025
|
+
" <CommandList>",
|
|
1026
|
+
" <CommandEmpty>No roles found.</CommandEmpty>",
|
|
1027
|
+
" <CommandGroup>",
|
|
1028
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1029
|
+
" <p>Viewer</p>",
|
|
1030
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1031
|
+
" Can view and comment.",
|
|
1032
|
+
" </p>",
|
|
1033
|
+
" </CommandItem>",
|
|
1034
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1035
|
+
" <p>Developer</p>",
|
|
1036
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1037
|
+
" Can view, comment and edit.",
|
|
1038
|
+
" </p>",
|
|
1039
|
+
" </CommandItem>",
|
|
1040
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1041
|
+
" <p>Billing</p>",
|
|
1042
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1043
|
+
" Can view, comment and manage billing.",
|
|
1044
|
+
" </p>",
|
|
1045
|
+
" </CommandItem>",
|
|
1046
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1047
|
+
" <p>Owner</p>",
|
|
1048
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1049
|
+
" Admin-level access to all resources.",
|
|
1050
|
+
" </p>",
|
|
1051
|
+
" </CommandItem>",
|
|
1052
|
+
" </CommandGroup>",
|
|
1053
|
+
" </CommandList>",
|
|
1054
|
+
" </Command>",
|
|
1055
|
+
" </PopoverContent>",
|
|
1056
|
+
" </Popover>",
|
|
1057
|
+
" </div>",
|
|
1058
|
+
" <div className=\"flex items-center justify-between space-x-4\">",
|
|
1059
|
+
" <div className=\"flex items-center space-x-4\">",
|
|
1060
|
+
" <Avatar>",
|
|
1061
|
+
" <AvatarImage src=\"/avatars/02.png\" />",
|
|
1062
|
+
" <AvatarFallback>JL</AvatarFallback>",
|
|
1063
|
+
" </Avatar>",
|
|
1064
|
+
" <div>",
|
|
1065
|
+
" <p className=\"text-sm font-medium leading-none\">Jackson Lee</p>",
|
|
1066
|
+
" <p className=\"text-sm text-muted-foreground\">p@example.com</p>",
|
|
1067
|
+
" </div>",
|
|
1068
|
+
" </div>",
|
|
1069
|
+
" <Popover>",
|
|
1070
|
+
" <PopoverTrigger asChild>",
|
|
1071
|
+
" <Button variant=\"outline\" className=\"ml-auto\">",
|
|
1072
|
+
" Member{\" \"}",
|
|
1073
|
+
" <ChevronDownIcon className=\"ml-2 h-4 w-4 text-muted-foreground\" />",
|
|
1074
|
+
" </Button>",
|
|
1075
|
+
" </PopoverTrigger>",
|
|
1076
|
+
" <PopoverContent className=\"p-0\" align=\"end\">",
|
|
1077
|
+
" <Command>",
|
|
1078
|
+
" <CommandInput placeholder=\"Select new role...\" />",
|
|
1079
|
+
" <CommandList>",
|
|
1080
|
+
" <CommandEmpty>No roles found.</CommandEmpty>",
|
|
1081
|
+
" <CommandGroup className=\"p-1.5\">",
|
|
1082
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1083
|
+
" <p>Viewer</p>",
|
|
1084
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1085
|
+
" Can view and comment.",
|
|
1086
|
+
" </p>",
|
|
1087
|
+
" </CommandItem>",
|
|
1088
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1089
|
+
" <p>Developer</p>",
|
|
1090
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1091
|
+
" Can view, comment and edit.",
|
|
1092
|
+
" </p>",
|
|
1093
|
+
" </CommandItem>",
|
|
1094
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1095
|
+
" <p>Billing</p>",
|
|
1096
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1097
|
+
" Can view, comment and manage billing.",
|
|
1098
|
+
" </p>",
|
|
1099
|
+
" </CommandItem>",
|
|
1100
|
+
" <CommandItem className=\"teamaspace-y-1 flex flex-col items-start px-4 py-2\">",
|
|
1101
|
+
" <p>Owner</p>",
|
|
1102
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1103
|
+
" Admin-level access to all resources.",
|
|
1104
|
+
" </p>",
|
|
1105
|
+
" </CommandItem>",
|
|
1106
|
+
" </CommandGroup>",
|
|
1107
|
+
" </CommandList>",
|
|
1108
|
+
" </Command>",
|
|
1109
|
+
" </PopoverContent>",
|
|
1110
|
+
" </Popover>",
|
|
1111
|
+
" </div>",
|
|
1112
|
+
" </CardContent>",
|
|
1113
|
+
" </Card>",
|
|
1114
|
+
" )",
|
|
1115
|
+
"}",
|
|
1116
|
+
"function DemoShareDocument() {",
|
|
1117
|
+
" return (",
|
|
1118
|
+
" <Card>",
|
|
1119
|
+
" <CardHeader>",
|
|
1120
|
+
" <CardTitle>Share this document</CardTitle>",
|
|
1121
|
+
" <CardDescription>",
|
|
1122
|
+
" Anyone with the link can view this document.",
|
|
1123
|
+
" </CardDescription>",
|
|
1124
|
+
" </CardHeader>",
|
|
1125
|
+
" <CardContent>",
|
|
1126
|
+
" <div className=\"flex space-x-2\">",
|
|
1127
|
+
" <Input value=\"http://example.com/link/to/document\" readOnly />",
|
|
1128
|
+
" <Button variant=\"secondary\" className=\"shrink-0\">",
|
|
1129
|
+
" Copy Link",
|
|
1130
|
+
" </Button>",
|
|
1131
|
+
" </div>",
|
|
1132
|
+
" <Separator className=\"my-4\" />",
|
|
1133
|
+
" <div className=\"space-y-4\">",
|
|
1134
|
+
" <h4 className=\"text-sm font-medium\">People with access</h4>",
|
|
1135
|
+
" <div className=\"grid gap-6\">",
|
|
1136
|
+
" <div className=\"flex items-center justify-between space-x-4\">",
|
|
1137
|
+
" <div className=\"flex items-center space-x-4\">",
|
|
1138
|
+
" <Avatar>",
|
|
1139
|
+
" <AvatarImage src=\"/avatars/03.png\" />",
|
|
1140
|
+
" <AvatarFallback>OM</AvatarFallback>",
|
|
1141
|
+
" </Avatar>",
|
|
1142
|
+
" <div>",
|
|
1143
|
+
" <p className=\"text-sm font-medium leading-none\">",
|
|
1144
|
+
" Olivia Martin",
|
|
1145
|
+
" </p>",
|
|
1146
|
+
" <p className=\"text-sm text-muted-foreground\">m@example.com</p>",
|
|
1147
|
+
" </div>",
|
|
1148
|
+
" </div>",
|
|
1149
|
+
" <Select defaultValue=\"edit\">",
|
|
1150
|
+
" <SelectTrigger className=\"ml-auto w-[110px]\">",
|
|
1151
|
+
" <SelectValue placeholder=\"Select\" />",
|
|
1152
|
+
" </SelectTrigger>",
|
|
1153
|
+
" <SelectContent>",
|
|
1154
|
+
" <SelectItem value=\"edit\">Can edit</SelectItem>",
|
|
1155
|
+
" <SelectItem value=\"view\">Can view</SelectItem>",
|
|
1156
|
+
" </SelectContent>",
|
|
1157
|
+
" </Select>",
|
|
1158
|
+
" </div>",
|
|
1159
|
+
" <div className=\"flex items-center justify-between space-x-4\">",
|
|
1160
|
+
" <div className=\"flex items-center space-x-4\">",
|
|
1161
|
+
" <Avatar>",
|
|
1162
|
+
" <AvatarImage src=\"/avatars/05.png\" />",
|
|
1163
|
+
" <AvatarFallback>IN</AvatarFallback>",
|
|
1164
|
+
" </Avatar>",
|
|
1165
|
+
" <div>",
|
|
1166
|
+
" <p className=\"text-sm font-medium leading-none\">",
|
|
1167
|
+
" Isabella Nguyen",
|
|
1168
|
+
" </p>",
|
|
1169
|
+
" <p className=\"text-sm text-muted-foreground\">b@example.com</p>",
|
|
1170
|
+
" </div>",
|
|
1171
|
+
" </div>",
|
|
1172
|
+
" <Select defaultValue=\"view\">",
|
|
1173
|
+
" <SelectTrigger className=\"ml-auto w-[110px]\">",
|
|
1174
|
+
" <SelectValue placeholder=\"Select\" />",
|
|
1175
|
+
" </SelectTrigger>",
|
|
1176
|
+
" <SelectContent>",
|
|
1177
|
+
" <SelectItem value=\"edit\">Can edit</SelectItem>",
|
|
1178
|
+
" <SelectItem value=\"view\">Can view</SelectItem>",
|
|
1179
|
+
" </SelectContent>",
|
|
1180
|
+
" </Select>",
|
|
1181
|
+
" </div>",
|
|
1182
|
+
" <div className=\"flex items-center justify-between space-x-4\">",
|
|
1183
|
+
" <div className=\"flex items-center space-x-4\">",
|
|
1184
|
+
" <Avatar>",
|
|
1185
|
+
" <AvatarImage src=\"/avatars/01.png\" />",
|
|
1186
|
+
" <AvatarFallback>SD</AvatarFallback>",
|
|
1187
|
+
" </Avatar>",
|
|
1188
|
+
" <div>",
|
|
1189
|
+
" <p className=\"text-sm font-medium leading-none\">",
|
|
1190
|
+
" Sofia Davis",
|
|
1191
|
+
" </p>",
|
|
1192
|
+
" <p className=\"text-sm text-muted-foreground\">p@example.com</p>",
|
|
1193
|
+
" </div>",
|
|
1194
|
+
" </div>",
|
|
1195
|
+
" <Select defaultValue=\"view\">",
|
|
1196
|
+
" <SelectTrigger className=\"ml-auto w-[110px]\">",
|
|
1197
|
+
" <SelectValue placeholder=\"Select\" />",
|
|
1198
|
+
" </SelectTrigger>",
|
|
1199
|
+
" <SelectContent>",
|
|
1200
|
+
" <SelectItem value=\"edit\">Can edit</SelectItem>",
|
|
1201
|
+
" <SelectItem value=\"view\">Can view</SelectItem>",
|
|
1202
|
+
" </SelectContent>",
|
|
1203
|
+
" </Select>",
|
|
1204
|
+
" </div>",
|
|
1205
|
+
" </div>",
|
|
1206
|
+
" </div>",
|
|
1207
|
+
" </CardContent>",
|
|
1208
|
+
" </Card>",
|
|
1209
|
+
" )",
|
|
1210
|
+
"}",
|
|
1211
|
+
"function DemoReportAnIssue() {",
|
|
1212
|
+
" return (",
|
|
1213
|
+
" <Card>",
|
|
1214
|
+
" <CardHeader>",
|
|
1215
|
+
" <CardTitle>Report an issue</CardTitle>",
|
|
1216
|
+
" <CardDescription>",
|
|
1217
|
+
" What area are you having problems with?",
|
|
1218
|
+
" </CardDescription>",
|
|
1219
|
+
" </CardHeader>",
|
|
1220
|
+
" <CardContent className=\"grid gap-6\">",
|
|
1221
|
+
" <div className=\"grid grid-cols-2 gap-4\">",
|
|
1222
|
+
" <div className=\"grid gap-2\">",
|
|
1223
|
+
" <Label htmlFor=\"area\">Area</Label>",
|
|
1224
|
+
" <Select defaultValue=\"billing\">",
|
|
1225
|
+
" <SelectTrigger id=\"area\">",
|
|
1226
|
+
" <SelectValue placeholder=\"Select\" />",
|
|
1227
|
+
" </SelectTrigger>",
|
|
1228
|
+
" <SelectContent>",
|
|
1229
|
+
" <SelectItem value=\"team\">Team</SelectItem>",
|
|
1230
|
+
" <SelectItem value=\"billing\">Billing</SelectItem>",
|
|
1231
|
+
" <SelectItem value=\"account\">Account</SelectItem>",
|
|
1232
|
+
" <SelectItem value=\"deployments\">Deployments</SelectItem>",
|
|
1233
|
+
" <SelectItem value=\"support\">Support</SelectItem>",
|
|
1234
|
+
" </SelectContent>",
|
|
1235
|
+
" </Select>",
|
|
1236
|
+
" </div>",
|
|
1237
|
+
" <div className=\"grid gap-2\">",
|
|
1238
|
+
" <Label htmlFor=\"security-level\">Security Level</Label>",
|
|
1239
|
+
" <Select defaultValue=\"2\">",
|
|
1240
|
+
" <SelectTrigger",
|
|
1241
|
+
" id=\"security-level\"",
|
|
1242
|
+
" className=\"line-clamp-1 w-[160px] truncate\"",
|
|
1243
|
+
" >",
|
|
1244
|
+
" <SelectValue placeholder=\"Select level\" />",
|
|
1245
|
+
" </SelectTrigger>",
|
|
1246
|
+
" <SelectContent>",
|
|
1247
|
+
" <SelectItem value=\"1\">Severity 1 (Highest)</SelectItem>",
|
|
1248
|
+
" <SelectItem value=\"2\">Severity 2</SelectItem>",
|
|
1249
|
+
" <SelectItem value=\"3\">Severity 3</SelectItem>",
|
|
1250
|
+
" <SelectItem value=\"4\">Severity 4 (Lowest)</SelectItem>",
|
|
1251
|
+
" </SelectContent>",
|
|
1252
|
+
" </Select>",
|
|
1253
|
+
" </div>",
|
|
1254
|
+
" </div>",
|
|
1255
|
+
" <div className=\"grid gap-2\">",
|
|
1256
|
+
" <Label htmlFor=\"subject\">Subject</Label>",
|
|
1257
|
+
" <Input id=\"subject\" placeholder=\"I need help with...\" />",
|
|
1258
|
+
" </div>",
|
|
1259
|
+
" <div className=\"grid gap-2\">",
|
|
1260
|
+
" <Label htmlFor=\"description\">Description</Label>",
|
|
1261
|
+
" <Textarea",
|
|
1262
|
+
" id=\"description\"",
|
|
1263
|
+
" placeholder=\"Please include all information relevant to your issue.\"",
|
|
1264
|
+
" />",
|
|
1265
|
+
" </div>",
|
|
1266
|
+
" </CardContent>",
|
|
1267
|
+
" <CardFooter className=\"justify-between space-x-2\">",
|
|
1268
|
+
" <Button variant=\"ghost\">Cancel</Button>",
|
|
1269
|
+
" <Button>Submit</Button>",
|
|
1270
|
+
" </CardFooter>",
|
|
1271
|
+
" </Card>",
|
|
1272
|
+
" )",
|
|
1273
|
+
"}",
|
|
1274
|
+
"function DemoPaymentMethod() {",
|
|
1275
|
+
" return (",
|
|
1276
|
+
" <Card>",
|
|
1277
|
+
" <CardHeader>",
|
|
1278
|
+
" <CardTitle>Payment Method</CardTitle>",
|
|
1279
|
+
" <CardDescription>",
|
|
1280
|
+
" Add a new payment method to your account.",
|
|
1281
|
+
" </CardDescription>",
|
|
1282
|
+
" </CardHeader>",
|
|
1283
|
+
" <CardContent className=\"grid gap-6\">",
|
|
1284
|
+
" <RadioGroup defaultValue=\"card\" className=\"grid grid-cols-3 gap-4\">",
|
|
1285
|
+
" <div>",
|
|
1286
|
+
" <RadioGroupItem value=\"card\" id=\"card\" className=\"peer sr-only\" />",
|
|
1287
|
+
" <Label",
|
|
1288
|
+
" htmlFor=\"card\"",
|
|
1289
|
+
" className=\"flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary\"",
|
|
1290
|
+
" >",
|
|
1291
|
+
" <svg",
|
|
1292
|
+
" xmlns=\"http://www.w3.org/2000/svg\"",
|
|
1293
|
+
" viewBox=\"0 0 24 24\"",
|
|
1294
|
+
" fill=\"none\"",
|
|
1295
|
+
" stroke=\"currentColor\"",
|
|
1296
|
+
" strokeLinecap=\"round\"",
|
|
1297
|
+
" strokeLinejoin=\"round\"",
|
|
1298
|
+
" strokeWidth=\"2\"",
|
|
1299
|
+
" className=\"mb-3 h-6 w-6\"",
|
|
1300
|
+
" >",
|
|
1301
|
+
" <rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\" />",
|
|
1302
|
+
" <path d=\"M2 10h20\" />",
|
|
1303
|
+
" </svg>",
|
|
1304
|
+
" Card",
|
|
1305
|
+
" </Label>",
|
|
1306
|
+
" </div>",
|
|
1307
|
+
" <div>",
|
|
1308
|
+
" <RadioGroupItem",
|
|
1309
|
+
" value=\"paypal\"",
|
|
1310
|
+
" id=\"paypal\"",
|
|
1311
|
+
" className=\"peer sr-only\"",
|
|
1312
|
+
" />",
|
|
1313
|
+
" <Label",
|
|
1314
|
+
" htmlFor=\"paypal\"",
|
|
1315
|
+
" className=\"flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary\"",
|
|
1316
|
+
" >",
|
|
1317
|
+
" <Icons.paypal className=\"mb-3 h-6 w-6\" />",
|
|
1318
|
+
" Paypal",
|
|
1319
|
+
" </Label>",
|
|
1320
|
+
" </div>",
|
|
1321
|
+
" <div>",
|
|
1322
|
+
" <RadioGroupItem value=\"apple\" id=\"apple\" className=\"peer sr-only\" />",
|
|
1323
|
+
" <Label",
|
|
1324
|
+
" htmlFor=\"apple\"",
|
|
1325
|
+
" className=\"flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary\"",
|
|
1326
|
+
" >",
|
|
1327
|
+
" <Icons.apple className=\"mb-3 h-6 w-6\" />",
|
|
1328
|
+
" Apple",
|
|
1329
|
+
" </Label>",
|
|
1330
|
+
" </div>",
|
|
1331
|
+
" </RadioGroup>",
|
|
1332
|
+
" <div className=\"grid gap-2\">",
|
|
1333
|
+
" <Label htmlFor=\"name\">Name</Label>",
|
|
1334
|
+
" <Input id=\"name\" placeholder=\"First Last\" />",
|
|
1335
|
+
" </div>",
|
|
1336
|
+
" <div className=\"grid gap-2\">",
|
|
1337
|
+
" <Label htmlFor=\"number\">Card number</Label>",
|
|
1338
|
+
" <Input id=\"number\" placeholder=\"\" />",
|
|
1339
|
+
" </div>",
|
|
1340
|
+
" <div className=\"grid grid-cols-3 gap-4\">",
|
|
1341
|
+
" <div className=\"grid gap-2\">",
|
|
1342
|
+
" <Label htmlFor=\"month\">Expires</Label>",
|
|
1343
|
+
" <Select>",
|
|
1344
|
+
" <SelectTrigger id=\"month\">",
|
|
1345
|
+
" <SelectValue placeholder=\"Month\" />",
|
|
1346
|
+
" </SelectTrigger>",
|
|
1347
|
+
" <SelectContent>",
|
|
1348
|
+
" <SelectItem value=\"1\">January</SelectItem>",
|
|
1349
|
+
" <SelectItem value=\"2\">February</SelectItem>",
|
|
1350
|
+
" <SelectItem value=\"3\">March</SelectItem>",
|
|
1351
|
+
" <SelectItem value=\"4\">April</SelectItem>",
|
|
1352
|
+
" <SelectItem value=\"5\">May</SelectItem>",
|
|
1353
|
+
" <SelectItem value=\"6\">June</SelectItem>",
|
|
1354
|
+
" <SelectItem value=\"7\">July</SelectItem>",
|
|
1355
|
+
" <SelectItem value=\"8\">August</SelectItem>",
|
|
1356
|
+
" <SelectItem value=\"9\">September</SelectItem>",
|
|
1357
|
+
" <SelectItem value=\"10\">October</SelectItem>",
|
|
1358
|
+
" <SelectItem value=\"11\">November</SelectItem>",
|
|
1359
|
+
" <SelectItem value=\"12\">December</SelectItem>",
|
|
1360
|
+
" </SelectContent>",
|
|
1361
|
+
" </Select>",
|
|
1362
|
+
" </div>",
|
|
1363
|
+
" <div className=\"grid gap-2\">",
|
|
1364
|
+
" <Label htmlFor=\"year\">Year</Label>",
|
|
1365
|
+
" <Select>",
|
|
1366
|
+
" <SelectTrigger id=\"year\">",
|
|
1367
|
+
" <SelectValue placeholder=\"Year\" />",
|
|
1368
|
+
" </SelectTrigger>",
|
|
1369
|
+
" <SelectContent>",
|
|
1370
|
+
" {Array.from({ length: 10 }, (_, i) => (",
|
|
1371
|
+
" <SelectItem key={i} value={`${new Date().getFullYear() + i}`}>",
|
|
1372
|
+
" {new Date().getFullYear() + i}",
|
|
1373
|
+
" </SelectItem>",
|
|
1374
|
+
" ))}",
|
|
1375
|
+
" </SelectContent>",
|
|
1376
|
+
" </Select>",
|
|
1377
|
+
" </div>",
|
|
1378
|
+
" <div className=\"grid gap-2\">",
|
|
1379
|
+
" <Label htmlFor=\"cvc\">CVC</Label>",
|
|
1380
|
+
" <Input id=\"cvc\" placeholder=\"CVC\" />",
|
|
1381
|
+
" </div>",
|
|
1382
|
+
" </div>",
|
|
1383
|
+
" </CardContent>",
|
|
1384
|
+
" <CardFooter>",
|
|
1385
|
+
" <Button className=\"w-full\">Continue</Button>",
|
|
1386
|
+
" </CardFooter>",
|
|
1387
|
+
" </Card>",
|
|
1388
|
+
" )",
|
|
1389
|
+
"}",
|
|
1390
|
+
"function DemoNotifications() {",
|
|
1391
|
+
" return (",
|
|
1392
|
+
" <Card>",
|
|
1393
|
+
" <CardHeader className=\"pb-3\">",
|
|
1394
|
+
" <CardTitle>Notifications</CardTitle>",
|
|
1395
|
+
" <CardDescription>",
|
|
1396
|
+
" Choose what you want to be notified about.",
|
|
1397
|
+
" </CardDescription>",
|
|
1398
|
+
" </CardHeader>",
|
|
1399
|
+
" <CardContent className=\"grid gap-1\">",
|
|
1400
|
+
" <div className=\"-mx-2 flex items-start space-x-4 rounded-md p-2 transition-all hover:bg-accent hover:text-accent-foreground\">",
|
|
1401
|
+
" <BellIcon className=\"mt-px h-5 w-5\" />",
|
|
1402
|
+
" <div className=\"space-y-1\">",
|
|
1403
|
+
" <p className=\"text-sm font-medium leading-none\">Everything</p>",
|
|
1404
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1405
|
+
" Email digest, mentions & all activity.",
|
|
1406
|
+
" </p>",
|
|
1407
|
+
" </div>",
|
|
1408
|
+
" </div>",
|
|
1409
|
+
" <div className=\"-mx-2 flex items-start space-x-4 rounded-md bg-accent p-2 text-accent-foreground transition-all\">",
|
|
1410
|
+
" <PersonIcon className=\"mt-px h-5 w-5\" />",
|
|
1411
|
+
" <div className=\"space-y-1\">",
|
|
1412
|
+
" <p className=\"text-sm font-medium leading-none\">Available</p>",
|
|
1413
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1414
|
+
" Only mentions and comments.",
|
|
1415
|
+
" </p>",
|
|
1416
|
+
" </div>",
|
|
1417
|
+
" </div>",
|
|
1418
|
+
" <div className=\"-mx-2 flex items-start space-x-4 rounded-md p-2 transition-all hover:bg-accent hover:text-accent-foreground\">",
|
|
1419
|
+
" <EyeNoneIcon className=\"mt-px h-5 w-5\" />",
|
|
1420
|
+
" <div className=\"space-y-1\">",
|
|
1421
|
+
" <p className=\"text-sm font-medium leading-none\">Ignoring</p>",
|
|
1422
|
+
" <p className=\"text-sm text-muted-foreground\">",
|
|
1423
|
+
" Turn off all notifications.",
|
|
1424
|
+
" </p>",
|
|
1425
|
+
" </div>",
|
|
1426
|
+
" </div>",
|
|
1427
|
+
" </CardContent>",
|
|
1428
|
+
" </Card>",
|
|
1429
|
+
" )",
|
|
1430
|
+
"}",
|
|
1431
|
+
" function DemoGithub() {",
|
|
1432
|
+
" return (",
|
|
1433
|
+
" <Card>",
|
|
1434
|
+
" <CardHeader className=\"grid grid-cols-[1fr_110px] items-start gap-4 space-y-0\">",
|
|
1435
|
+
" <div className=\"space-y-1\">",
|
|
1436
|
+
" <CardTitle>shadcn/ui</CardTitle>",
|
|
1437
|
+
" <CardDescription>",
|
|
1438
|
+
" Beautifully designed components that you can copy and paste into",
|
|
1439
|
+
" your apps. Accessible. Customizable. Open Source.",
|
|
1440
|
+
" </CardDescription>",
|
|
1441
|
+
" </div>",
|
|
1442
|
+
" <div className=\"flex items-center space-x-1 rounded-md bg-secondary text-secondary-foreground\">",
|
|
1443
|
+
" <Button variant=\"secondary\" className=\"px-3 shadow-none\">",
|
|
1444
|
+
" <StarIcon className=\"mr-2 h-4 w-4\" />",
|
|
1445
|
+
" Star",
|
|
1446
|
+
" </Button>",
|
|
1447
|
+
" <Separator orientation=\"vertical\" className=\"h-[20px]\" />",
|
|
1448
|
+
" <DropdownMenu>",
|
|
1449
|
+
" <DropdownMenuTrigger asChild>",
|
|
1450
|
+
" <Button variant=\"secondary\" className=\"px-2 shadow-none\">",
|
|
1451
|
+
" <ChevronDownIcon className=\"h-4 w-4 text-secondary-foreground\" />",
|
|
1452
|
+
" </Button>",
|
|
1453
|
+
" </DropdownMenuTrigger>",
|
|
1454
|
+
" <DropdownMenuContent",
|
|
1455
|
+
" align=\"end\"",
|
|
1456
|
+
" alignOffset={-5}",
|
|
1457
|
+
" className=\"w-[200px]\"",
|
|
1458
|
+
" forceMount",
|
|
1459
|
+
" >",
|
|
1460
|
+
" <DropdownMenuLabel>Suggested Lists</DropdownMenuLabel>",
|
|
1461
|
+
" <DropdownMenuSeparator />",
|
|
1462
|
+
" <DropdownMenuCheckboxItem checked>",
|
|
1463
|
+
" Future Ideas",
|
|
1464
|
+
" </DropdownMenuCheckboxItem>",
|
|
1465
|
+
" <DropdownMenuCheckboxItem>My Stack</DropdownMenuCheckboxItem>",
|
|
1466
|
+
" <DropdownMenuCheckboxItem>Inspiration</DropdownMenuCheckboxItem>",
|
|
1467
|
+
" <DropdownMenuSeparator />",
|
|
1468
|
+
" <DropdownMenuItem>",
|
|
1469
|
+
" <PlusIcon className=\"mr-2 h-4 w-4\" /> Create List",
|
|
1470
|
+
" </DropdownMenuItem>",
|
|
1471
|
+
" </DropdownMenuContent>",
|
|
1472
|
+
" </DropdownMenu>",
|
|
1473
|
+
" </div>",
|
|
1474
|
+
" </CardHeader>",
|
|
1475
|
+
" <CardContent>",
|
|
1476
|
+
" <div className=\"flex space-x-4 text-sm text-muted-foreground\">",
|
|
1477
|
+
" <div className=\"flex items-center\">",
|
|
1478
|
+
" <CircleIcon className=\"mr-1 h-3 w-3 fill-sky-400 text-sky-400\" />",
|
|
1479
|
+
" TypeScript",
|
|
1480
|
+
" </div>",
|
|
1481
|
+
" <div className=\"flex items-center\">",
|
|
1482
|
+
" <StarIcon className=\"mr-1 h-3 w-3\" />",
|
|
1483
|
+
" 20k",
|
|
1484
|
+
" </div>",
|
|
1485
|
+
" <div>Updated April 2023</div>",
|
|
1486
|
+
" </div>",
|
|
1487
|
+
" </CardContent>",
|
|
1488
|
+
" </Card>",
|
|
1489
|
+
" )",
|
|
1490
|
+
"}",
|
|
1491
|
+
"function DemoDatePicker() {",
|
|
1492
|
+
" return (",
|
|
1493
|
+
" <Card>",
|
|
1494
|
+
" <CardContent className=\"pt-6\">",
|
|
1495
|
+
" <div className=\"space-y-2\">",
|
|
1496
|
+
" <Label htmlFor=\"date\" className=\"shrink-0\">",
|
|
1497
|
+
" Pick a date",
|
|
1498
|
+
" </Label>",
|
|
1499
|
+
" <DatePickerWithRange className=\"[&>button]:w-[260px]\" />",
|
|
1500
|
+
" </div>",
|
|
1501
|
+
" </CardContent>",
|
|
1502
|
+
" </Card>",
|
|
1503
|
+
" )",
|
|
1504
|
+
"}",
|
|
1505
|
+
"function DemoCreateAccount() {",
|
|
1506
|
+
" return (",
|
|
1507
|
+
" <Card>",
|
|
1508
|
+
" <CardHeader className=\"space-y-1\">",
|
|
1509
|
+
" <CardTitle className=\"text-2xl\">Create an account</CardTitle>",
|
|
1510
|
+
" <CardDescription>",
|
|
1511
|
+
" Enter your email below to create your account",
|
|
1512
|
+
" </CardDescription>",
|
|
1513
|
+
" </CardHeader>",
|
|
1514
|
+
" <CardContent className=\"grid gap-4\">",
|
|
1515
|
+
" <div className=\"grid grid-cols-2 gap-6\">",
|
|
1516
|
+
" <Button variant=\"outline\">",
|
|
1517
|
+
" <Icons.gitHub className=\"mr-2 h-4 w-4\" />",
|
|
1518
|
+
" Github",
|
|
1519
|
+
" </Button>",
|
|
1520
|
+
" <Button variant=\"outline\">",
|
|
1521
|
+
" <Icons.google className=\"mr-2 h-4 w-4\" />",
|
|
1522
|
+
" Google",
|
|
1523
|
+
" </Button>",
|
|
1524
|
+
" </div>",
|
|
1525
|
+
" <div className=\"relative\">",
|
|
1526
|
+
" <div className=\"absolute inset-0 flex items-center\">",
|
|
1527
|
+
" <span className=\"w-full border-t\" />",
|
|
1528
|
+
" </div>",
|
|
1529
|
+
" <div className=\"relative flex justify-center text-xs uppercase\">",
|
|
1530
|
+
" <span className=\"bg-background px-2 text-muted-foreground\">",
|
|
1531
|
+
" Or continue with",
|
|
1532
|
+
" </span>",
|
|
1533
|
+
" </div>",
|
|
1534
|
+
" </div>",
|
|
1535
|
+
" <div className=\"grid gap-2\">",
|
|
1536
|
+
" <Label htmlFor=\"email\">Email</Label>",
|
|
1537
|
+
" <Input id=\"email\" type=\"email\" placeholder=\"m@example.com\" />",
|
|
1538
|
+
" </div>",
|
|
1539
|
+
" <div className=\"grid gap-2\">",
|
|
1540
|
+
" <Label htmlFor=\"password\">Password</Label>",
|
|
1541
|
+
" <Input id=\"password\" type=\"password\" />",
|
|
1542
|
+
" </div>",
|
|
1543
|
+
" </CardContent>",
|
|
1544
|
+
" <CardFooter>",
|
|
1545
|
+
" <Button className=\"w-full\">Create account</Button>",
|
|
1546
|
+
" </CardFooter>",
|
|
1547
|
+
" </Card>",
|
|
1548
|
+
" )",
|
|
1549
|
+
"}",
|
|
1550
|
+
"function DemoCookieSettings() {",
|
|
1551
|
+
" return (",
|
|
1552
|
+
" <Card>",
|
|
1553
|
+
" <CardHeader>",
|
|
1554
|
+
" <CardTitle>Cookie Settings</CardTitle>",
|
|
1555
|
+
" <CardDescription>Manage your cookie settings here.</CardDescription>",
|
|
1556
|
+
" </CardHeader>",
|
|
1557
|
+
" <CardContent className=\"grid gap-6\">",
|
|
1558
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
1559
|
+
" <Label htmlFor=\"necessary\" className=\"flex flex-col space-y-1\">",
|
|
1560
|
+
" <span>Strictly Necessary</span>",
|
|
1561
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
1562
|
+
" These cookies are essential in order to use the website and use",
|
|
1563
|
+
" its features.",
|
|
1564
|
+
" </span>",
|
|
1565
|
+
" </Label>",
|
|
1566
|
+
" <Switch id=\"necessary\" defaultChecked />",
|
|
1567
|
+
" </div>",
|
|
1568
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
1569
|
+
" <Label htmlFor=\"functional\" className=\"flex flex-col space-y-1\">",
|
|
1570
|
+
" <span>Functional Cookies</span>",
|
|
1571
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
1572
|
+
" These cookies allow the website to provide personalized",
|
|
1573
|
+
" functionality.",
|
|
1574
|
+
" </span>",
|
|
1575
|
+
" </Label>",
|
|
1576
|
+
" <Switch id=\"functional\" />",
|
|
1577
|
+
" </div>",
|
|
1578
|
+
" <div className=\"flex items-center justify-between space-x-2\">",
|
|
1579
|
+
" <Label htmlFor=\"performance\" className=\"flex flex-col space-y-1\">",
|
|
1580
|
+
" <span>Performance Cookies</span>",
|
|
1581
|
+
" <span className=\"font-normal leading-snug text-muted-foreground\">",
|
|
1582
|
+
" These cookies help to improve the performance of the website.",
|
|
1583
|
+
" </span>",
|
|
1584
|
+
" </Label>",
|
|
1585
|
+
" <Switch id=\"performance\" />",
|
|
1586
|
+
" </div>",
|
|
1587
|
+
" </CardContent>",
|
|
1588
|
+
" <CardFooter>",
|
|
1589
|
+
" <Button variant=\"outline\" className=\"w-full\">",
|
|
1590
|
+
" Save preferences",
|
|
1591
|
+
" </Button>",
|
|
1592
|
+
" </CardFooter>",
|
|
1593
|
+
" </Card>",
|
|
1594
|
+
" )",
|
|
1595
|
+
"}",
|
|
1596
|
+
"",
|
|
1597
|
+
"",
|
|
1598
|
+
"",
|
|
1599
|
+
""
|
|
1600
|
+
]
|
|
1601
|
+
},
|
|
1602
|
+
"draggable_responsive_dialog_drawer": {
|
|
1603
|
+
"prefix": "draggable_responsive_dialog_drawer",
|
|
1604
|
+
"body": [
|
|
1605
|
+
"export default function MainFunction() {\r\n const { isMobile } = useSidebar()\r\n const [isDialogOpen, setIsDialogOpen] = useState(false);\r\n // DRAGGING\r\n const [position, setPosition] = useState({ x: -200, y: -450 });\r\n const [isDragging, setIsDragging] = useState(false);\r\n const dragRef = useRef<HTMLDivElement>(null);\r\n const startPosRef = useRef<{ x: number; y: number } | null>(null);\r\n const shadowPosRef = useRef<{ x: number; y: number }>({ x: -350, y: -850 });\r\n\r\n const handleMouseMove = useCallback((e: MouseEvent) => {\r\n if (!isDragging || !startPosRef.current) return;\r\n\r\n const shadowX = e.clientX - (startPosRef.current?.x || 0);\r\n const shadowY = e.clientY - (startPosRef.current?.y || 0);\r\n\r\n shadowPosRef.current = { x: shadowX, y: shadowY };\r\n\r\n if (dragRef.current) {\r\n dragRef.current.style.transform = \\`translate($ {shadowX}px, $ {shadowY}px)\\`;\r\n }\r\n }, [isDragging]);\r\n\r\n const handleMouseUp = useCallback(() => {\r\n // Set final position when dragging ends\r\n setPosition(shadowPosRef.current);\r\n\r\n // Reset dragging state\r\n setIsDragging(false);\r\n startPosRef.current = null;\r\n\r\n // Remove visual transform\r\n if (dragRef.current) {\r\n dragRef.current.style.transform = 'none';\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n // Only add listeners when dragging\r\n if (isDragging) {\r\n document.addEventListener('mousemove', handleMouseMove, { passive: true });\r\n document.addEventListener('mouseup', handleMouseUp, { passive: true });\r\n }\r\n\r\n // Cleanup function\r\n return () => {\r\n document.removeEventListener('mousemove', handleMouseMove);\r\n document.removeEventListener('mouseup', handleMouseUp);\r\n };\r\n }, [isDragging, handleMouseMove, handleMouseUp]);\r\n\r\n const handleRef = useRef<HTMLButtonElement>(null);\r\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\r\n // Ensure we're dragging from the handle\r\n if (e.target !== handleRef.current) return;\r\n\r\n e.preventDefault();\r\n\r\n // Capture initial mouse position\r\n startPosRef.current = {\r\n x: e.clientX - position.x,\r\n y: e.clientY - position.y\r\n };\r\n\r\n // Initialize shadow position to current position\r\n shadowPosRef.current = { ...position };\r\n\r\n setIsDragging(true);\r\n }, [position.x, position.y]);\r\n\r\n return (\r\n <>\r\n <OpenButton setIsDialogOpen={setIsDialogOpen} />\r\n <ResponsiveDialogDrawer\r\n setIsDialogOpen={setIsDialogOpen}\r\n isDialogOpen={isDialogOpen}\r\n isMobile={isMobile}\r\n position={position}\r\n isDragging={isDragging}\r\n dragRef={dragRef}\r\n />\r\n </>\r\n )\r\n}\r\nfunction OpenButton({ setIsDialogOpen }) {\r\n return (\r\n <ButtonStyled\r\n primary={false}\r\n className=\" mr-auto ml-3 w-[150px] text-xs h-7 \"\r\n onClick={() => { setIsDialogOpen(true); }} >\r\n Open\r\n </ButtonStyled>\r\n )\r\n}\r\nfunction MoveButton({ handleMouseDown, handleRef }) {\r\n return (\r\n <Button\r\n ref={handleRef}\r\n size=\"icon\"\r\n variant=\"ghost\"\r\n type='button'\r\n onMouseDown={handleMouseDown}\r\n className=' cursor-move'\r\n >\r\n <Move />\r\n </Button>\r\n )\r\n}\r\nfunction ResponsiveDialogDrawer({ isDialogOpen, setIsDialogOpen, isMobile, position, isDragging, dragRef, }) {\r\n\r\n if (isMobile === false) {\r\n return (\r\n <Dialog\r\n open={isDialogOpen}\r\n onOpenChange={setIsDialogOpen}\r\n modal={false} >\r\n <DialogContent\r\n onInteractOutside={(e) => { e.preventDefault(); }}\r\n ref={dragRef}\r\n className={cn(\r\n isDragging ? \"pointer-events-none\" : \"\",\r\n isMobile === false ?\r\n \"absolute z-[100] bg-background border border-border border-dashed text-foreground shadow-md max-h-[90vh] h-auto\" :\r\n \"w-full h-full fixed bottom-0 left-0 right-0 z-[100] bg-background border-none border-dashed\"\r\n )}\r\n style={{\r\n ...(isMobile === false ? {\r\n transform: \\`translate($ {position.x}px, $ {position.y}px)\\`,\r\n transition: isDragging ? 'none' : 'transform 0.1s ease-out',\r\n willChange: 'transform',\r\n width: small ? '325px' : '750px'\r\n } : {\r\n transform: 'none',\r\n transition: 'none',\r\n })\r\n }}\r\n >\r\n <Content />\r\n </DialogContent>\r\n </Dialog>\r\n )\r\n }\r\n\r\n return (\r\n <Drawer open={isDialogOpen} onOpenChange={setIsDialogOpen}>\r\n <DrawerContent>\r\n <Content />\r\n <DrawerFooter className=\"pt-2\">\r\n <DrawerClose asChild>\r\n <Button variant=\"outline\">Cancel</Button>\r\n </DrawerClose>\r\n </DrawerFooter>\r\n </DrawerContent>\r\n </Drawer>\r\n )\r\n}\r\nfunction Content({ handleMouseDown, handleRef }) {\r\n return (\r\n <div className='grid grid-cols-1 gap-3' >\r\n <div className=\"flex justify-between items-center gap-1 p-2\">\r\n <div>\r\n\r\n </div>\r\n <div className='flex items-center gap-1'>\r\n <MoveButton handleRef={handleRef} handleMouseDown={handleMouseDown} />\r\n <Button\r\n size=\"icon\"\r\n variant=\"ghost\"\r\n type='button'\r\n onClick={() => setIsDialogOpen(false)}\r\n >\r\n <X />\r\n </Button>\r\n\r\n </div>\r\n </div>\r\n <div className='grid grid-cols-1 gap-3' >\r\n <div className=\"p-4 max-h-[75vh] h-auto overflow-y-auto\">\r\n \r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
1606
|
+
],
|
|
1607
|
+
"description": "",
|
|
1608
|
+
"scope": "jsx / tsx"
|
|
1609
|
+
},
|
|
1610
|
+
"calendar_with_time_presets": {
|
|
1611
|
+
"prefix": "calendar_with_time_presets",
|
|
1612
|
+
"description": "Description for calendar with time presets",
|
|
1613
|
+
"scope": "javascript,typescript",
|
|
1614
|
+
"body": [
|
|
1615
|
+
"",
|
|
1616
|
+
"import * as React from \"react\"",
|
|
1617
|
+
"",
|
|
1618
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
1619
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
1620
|
+
"import { Card, CardContent, CardFooter } from \"~/components/ui/card\"",
|
|
1621
|
+
"",
|
|
1622
|
+
"export function WithTimePresets() {",
|
|
1623
|
+
" const [date, setDate] = React.useState<Date | undefined>(",
|
|
1624
|
+
" new Date(2025, 5, 12)",
|
|
1625
|
+
" )",
|
|
1626
|
+
" const [selectedTime, setSelectedTime] = React.useState<string | null>(\"10:00\")",
|
|
1627
|
+
" const timeSlots = Array.from({ length: 37 }, (_, i) => {",
|
|
1628
|
+
" const totalMinutes = i * 15",
|
|
1629
|
+
" const hour = Math.floor(totalMinutes / 60) + 9",
|
|
1630
|
+
" const minute = totalMinutes % 60",
|
|
1631
|
+
" return `${hour.toString().padStart(2, \"0\")}:${minute.toString().padStart(2, \"0\")}`",
|
|
1632
|
+
" })",
|
|
1633
|
+
"",
|
|
1634
|
+
" const bookedDates = Array.from(",
|
|
1635
|
+
" { length: 3 },",
|
|
1636
|
+
" (_, i) => new Date(2025, 5, 17 + i)",
|
|
1637
|
+
" )",
|
|
1638
|
+
"",
|
|
1639
|
+
" return (",
|
|
1640
|
+
" <Card className=\"gap-0 p-0\">",
|
|
1641
|
+
" <CardContent className=\"relative p-0 md:pr-48\">",
|
|
1642
|
+
" <div className=\"p-6\">",
|
|
1643
|
+
" <Calendar",
|
|
1644
|
+
" mode=\"single\"",
|
|
1645
|
+
" selected={date}",
|
|
1646
|
+
" onSelect={setDate}",
|
|
1647
|
+
" defaultMonth={date}",
|
|
1648
|
+
" disabled={bookedDates}",
|
|
1649
|
+
" showOutsideDays={false}",
|
|
1650
|
+
" modifiers={{",
|
|
1651
|
+
" booked: bookedDates,",
|
|
1652
|
+
" }}",
|
|
1653
|
+
" modifiersClassNames={{",
|
|
1654
|
+
" booked: \"[&>button]:line-through opacity-100\",",
|
|
1655
|
+
" }}",
|
|
1656
|
+
" className=\"bg-transparent p-0 [--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]\"",
|
|
1657
|
+
" formatters={{",
|
|
1658
|
+
" formatWeekdayName: (date) => {",
|
|
1659
|
+
" return date.toLocaleString(\"en-US\", { weekday: \"short\" })",
|
|
1660
|
+
" },",
|
|
1661
|
+
" }}",
|
|
1662
|
+
" />",
|
|
1663
|
+
" </div>",
|
|
1664
|
+
" <div className=\"no-scrollbar inset-y-0 right-0 flex max-h-72 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t p-6 md:absolute md:max-h-none md:w-48 md:border-t-0 md:border-l\">",
|
|
1665
|
+
" <div className=\"grid gap-2\">",
|
|
1666
|
+
" {timeSlots.map((time) => (",
|
|
1667
|
+
" <Button",
|
|
1668
|
+
" key={time}",
|
|
1669
|
+
" variant={selectedTime === time ? \"default\" : \"outline\"}",
|
|
1670
|
+
" onClick={() => setSelectedTime(time)}",
|
|
1671
|
+
" className=\"w-full shadow-none\"",
|
|
1672
|
+
" >",
|
|
1673
|
+
" {time}",
|
|
1674
|
+
" </Button>",
|
|
1675
|
+
" ))}",
|
|
1676
|
+
" </div>",
|
|
1677
|
+
" </div>",
|
|
1678
|
+
" </CardContent>",
|
|
1679
|
+
" <CardFooter className=\"flex flex-col gap-4 border-t px-6 !py-5 md:flex-row\">",
|
|
1680
|
+
" <div className=\"text-sm\">",
|
|
1681
|
+
" {date && selectedTime ? (",
|
|
1682
|
+
" <>",
|
|
1683
|
+
" Your meeting is booked for{\" \"}",
|
|
1684
|
+
" <span className=\"font-medium\">",
|
|
1685
|
+
" {\" \"}",
|
|
1686
|
+
" {date?.toLocaleDateString(\"en-US\", {",
|
|
1687
|
+
" weekday: \"long\",",
|
|
1688
|
+
" day: \"numeric\",",
|
|
1689
|
+
" month: \"long\",",
|
|
1690
|
+
" })}{\" \"}",
|
|
1691
|
+
" </span>",
|
|
1692
|
+
" at <span className=\"font-medium\">{selectedTime}</span>.",
|
|
1693
|
+
" </>",
|
|
1694
|
+
" ) : (",
|
|
1695
|
+
" <>Select a date and time for your meeting.</>",
|
|
1696
|
+
" )}",
|
|
1697
|
+
" </div>",
|
|
1698
|
+
" <Button",
|
|
1699
|
+
" disabled={!date || !selectedTime}",
|
|
1700
|
+
" className=\"w-full md:ml-auto md:w-auto\"",
|
|
1701
|
+
" variant=\"outline\"",
|
|
1702
|
+
" >",
|
|
1703
|
+
" Continue",
|
|
1704
|
+
" </Button>",
|
|
1705
|
+
" </CardFooter>",
|
|
1706
|
+
" </Card>",
|
|
1707
|
+
" )",
|
|
1708
|
+
"}",
|
|
1709
|
+
""
|
|
1710
|
+
]
|
|
1711
|
+
},
|
|
1712
|
+
"dob": {
|
|
1713
|
+
"prefix": "dob",
|
|
1714
|
+
"description": "Description for dob",
|
|
1715
|
+
"scope": "javascript,typescript",
|
|
1716
|
+
"body": [
|
|
1717
|
+
"\"use client\"",
|
|
1718
|
+
"",
|
|
1719
|
+
"import * as React from \"react\"",
|
|
1720
|
+
"import { ChevronDownIcon } from \"lucide-react\"",
|
|
1721
|
+
"",
|
|
1722
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
1723
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
1724
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
1725
|
+
"import {",
|
|
1726
|
+
" Popover,",
|
|
1727
|
+
" PopoverContent,",
|
|
1728
|
+
" PopoverTrigger,",
|
|
1729
|
+
"} from \"~/components/ui/popover\"",
|
|
1730
|
+
"",
|
|
1731
|
+
"export function DOB() {",
|
|
1732
|
+
" const [open, setOpen] = React.useState(false)",
|
|
1733
|
+
" const [date, setDate] = React.useState<Date | undefined>(undefined)",
|
|
1734
|
+
"",
|
|
1735
|
+
" return (",
|
|
1736
|
+
" <div className=\"flex flex-col gap-3\">",
|
|
1737
|
+
" <Label htmlFor=\"date\" className=\"px-1\">",
|
|
1738
|
+
" Date of birth",
|
|
1739
|
+
" </Label>",
|
|
1740
|
+
" <Popover open={open} onOpenChange={setOpen}>",
|
|
1741
|
+
" <PopoverTrigger asChild>",
|
|
1742
|
+
" <Button",
|
|
1743
|
+
" variant=\"outline\"",
|
|
1744
|
+
" id=\"date\"",
|
|
1745
|
+
" className=\"w-48 justify-between font-normal\"",
|
|
1746
|
+
" >",
|
|
1747
|
+
" {date ? date.toLocaleDateString() : \"Select date\"}",
|
|
1748
|
+
" <ChevronDownIcon />",
|
|
1749
|
+
" </Button>",
|
|
1750
|
+
" </PopoverTrigger>",
|
|
1751
|
+
" <PopoverContent className=\"w-auto overflow-hidden p-0\" align=\"start\">",
|
|
1752
|
+
" <Calendar",
|
|
1753
|
+
" mode=\"single\"",
|
|
1754
|
+
" selected={date}",
|
|
1755
|
+
" captionLayout=\"dropdown\"",
|
|
1756
|
+
" onSelect={(date) => {",
|
|
1757
|
+
" setDate(date)",
|
|
1758
|
+
" setOpen(false)",
|
|
1759
|
+
" }}",
|
|
1760
|
+
" />",
|
|
1761
|
+
" </PopoverContent>",
|
|
1762
|
+
" </Popover>",
|
|
1763
|
+
" </div>",
|
|
1764
|
+
" )",
|
|
1765
|
+
"}",
|
|
1766
|
+
""
|
|
1767
|
+
]
|
|
1768
|
+
},
|
|
1769
|
+
"with_presets": {
|
|
1770
|
+
"prefix": "with_presets",
|
|
1771
|
+
"description": "Description for with presets",
|
|
1772
|
+
"scope": "javascript,typescript",
|
|
1773
|
+
"body": [
|
|
1774
|
+
"\"use client\"",
|
|
1775
|
+
"",
|
|
1776
|
+
"import * as React from \"react\"",
|
|
1777
|
+
"import { addDays } from \"date-fns\"",
|
|
1778
|
+
"",
|
|
1779
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
1780
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
1781
|
+
"import { Card, CardContent, CardFooter } from \"~/components/ui/card\"",
|
|
1782
|
+
"",
|
|
1783
|
+
"export function WithPresets() {",
|
|
1784
|
+
" const [date, setDate] = React.useState<Date | undefined>(",
|
|
1785
|
+
" new Date(2025, 5, 12)",
|
|
1786
|
+
" )",
|
|
1787
|
+
"",
|
|
1788
|
+
" return (",
|
|
1789
|
+
" <Card className=\"max-w-[300px] py-4\">",
|
|
1790
|
+
" <CardContent className=\"px-4\">",
|
|
1791
|
+
" <Calendar",
|
|
1792
|
+
" mode=\"single\"",
|
|
1793
|
+
" selected={date}",
|
|
1794
|
+
" onSelect={setDate}",
|
|
1795
|
+
" defaultMonth={date}",
|
|
1796
|
+
" className=\"bg-transparent p-0 [--cell-size:--spacing(9.5)]\"",
|
|
1797
|
+
" />",
|
|
1798
|
+
" </CardContent>",
|
|
1799
|
+
" <CardFooter className=\"flex flex-wrap gap-2 border-t px-4 !pt-4\">",
|
|
1800
|
+
" {[",
|
|
1801
|
+
" { label: \"Today\", value: 0 },",
|
|
1802
|
+
" { label: \"Tomorrow\", value: 1 },",
|
|
1803
|
+
" { label: \"In 3 days\", value: 3 },",
|
|
1804
|
+
" { label: \"In a week\", value: 7 },",
|
|
1805
|
+
" { label: \"In 2 weeks\", value: 14 },",
|
|
1806
|
+
" ].map((preset) => (",
|
|
1807
|
+
" <Button",
|
|
1808
|
+
" key={preset.value}",
|
|
1809
|
+
" variant=\"outline\"",
|
|
1810
|
+
" size=\"sm\"",
|
|
1811
|
+
" className=\"flex-1\"",
|
|
1812
|
+
" onClick={() => {",
|
|
1813
|
+
" const newDate = addDays(new Date(), preset.value)",
|
|
1814
|
+
" setDate(newDate)",
|
|
1815
|
+
" }}",
|
|
1816
|
+
" >",
|
|
1817
|
+
" {preset.label}",
|
|
1818
|
+
" </Button>",
|
|
1819
|
+
" ))}",
|
|
1820
|
+
" </CardFooter>",
|
|
1821
|
+
" </Card>",
|
|
1822
|
+
" )",
|
|
1823
|
+
"}",
|
|
1824
|
+
""
|
|
1825
|
+
]
|
|
1826
|
+
},
|
|
1827
|
+
"sidebar_dialog": {
|
|
1828
|
+
"prefix": "sidebar_dialog",
|
|
1829
|
+
"description": "Description for sidebar dialog",
|
|
1830
|
+
"scope": "javascript,typescript",
|
|
1831
|
+
"body": [
|
|
1832
|
+
"import * as React from \"react\"",
|
|
1833
|
+
"import {",
|
|
1834
|
+
" Bell,",
|
|
1835
|
+
" Check,",
|
|
1836
|
+
" Globe,",
|
|
1837
|
+
" Home,",
|
|
1838
|
+
" Keyboard,",
|
|
1839
|
+
" Link,",
|
|
1840
|
+
" Lock,",
|
|
1841
|
+
" Menu,",
|
|
1842
|
+
" MessageCircle,",
|
|
1843
|
+
" Paintbrush,",
|
|
1844
|
+
" Settings,",
|
|
1845
|
+
" Video,",
|
|
1846
|
+
"} from \"lucide-react\"",
|
|
1847
|
+
"import {",
|
|
1848
|
+
" Breadcrumb,",
|
|
1849
|
+
" BreadcrumbItem,",
|
|
1850
|
+
" BreadcrumbLink,",
|
|
1851
|
+
" BreadcrumbList,",
|
|
1852
|
+
" BreadcrumbPage,",
|
|
1853
|
+
" BreadcrumbSeparator,",
|
|
1854
|
+
"} from \"~/components/ui/breadcrumb\"",
|
|
1855
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
1856
|
+
"import {",
|
|
1857
|
+
" Dialog,",
|
|
1858
|
+
" DialogContent,",
|
|
1859
|
+
" DialogDescription,",
|
|
1860
|
+
" DialogTitle,",
|
|
1861
|
+
" DialogTrigger,",
|
|
1862
|
+
"} from \"~/components/ui/dialog\"",
|
|
1863
|
+
"import {",
|
|
1864
|
+
" Sidebar,",
|
|
1865
|
+
" SidebarContent,",
|
|
1866
|
+
" SidebarGroup,",
|
|
1867
|
+
" SidebarGroupContent,",
|
|
1868
|
+
" SidebarMenu,",
|
|
1869
|
+
" SidebarMenuButton,",
|
|
1870
|
+
" SidebarMenuItem,",
|
|
1871
|
+
" SidebarProvider,",
|
|
1872
|
+
"} from \"~/components/ui/sidebar\"",
|
|
1873
|
+
"export default function Page() {",
|
|
1874
|
+
" const [open, setOpen] = useState(true)",
|
|
1875
|
+
" const data = {",
|
|
1876
|
+
" nav: [",
|
|
1877
|
+
" { name: \"Notifications\", icon: Bell },",
|
|
1878
|
+
" { name: \"Navigation\", icon: Menu },",
|
|
1879
|
+
" { name: \"Home\", icon: Home },",
|
|
1880
|
+
" { name: \"Appearance\", icon: Paintbrush },",
|
|
1881
|
+
" { name: \"Messages & media\", icon: MessageCircle },",
|
|
1882
|
+
" { name: \"Language & region\", icon: Globe },",
|
|
1883
|
+
" { name: \"Accessibility\", icon: Keyboard },",
|
|
1884
|
+
" { name: \"Mark as read\", icon: Check },",
|
|
1885
|
+
" { name: \"Audio & video\", icon: Video },",
|
|
1886
|
+
" { name: \"Connected accounts\", icon: Link },",
|
|
1887
|
+
" { name: \"Privacy & visibility\", icon: Lock },",
|
|
1888
|
+
" { name: \"Advanced\", icon: Settings },",
|
|
1889
|
+
" ],",
|
|
1890
|
+
"}",
|
|
1891
|
+
"",
|
|
1892
|
+
" return (",
|
|
1893
|
+
" <div className=\"flex h-svh items-center justify-center\">",
|
|
1894
|
+
" <Dialog open={open} onOpenChange={setOpen}>",
|
|
1895
|
+
" <DialogTrigger asChild>",
|
|
1896
|
+
" <Button size=\"sm\">Open Dialog</Button>",
|
|
1897
|
+
" </DialogTrigger>",
|
|
1898
|
+
" <DialogContent className=\"overflow-hidden p-0 md:max-h-[500px] md:max-w-[700px] lg:max-w-[800px]\">",
|
|
1899
|
+
" <DialogTitle className=\"sr-only\">Settings</DialogTitle>",
|
|
1900
|
+
" <DialogDescription className=\"sr-only\">",
|
|
1901
|
+
" Customize your settings here.",
|
|
1902
|
+
" </DialogDescription>",
|
|
1903
|
+
" <SidebarProvider className=\"items-start\">",
|
|
1904
|
+
" <Sidebar collapsible=\"none\" className=\"hidden md:flex\">",
|
|
1905
|
+
" <SidebarContent>",
|
|
1906
|
+
" <SidebarGroup>",
|
|
1907
|
+
" <SidebarGroupContent>",
|
|
1908
|
+
" <SidebarMenu>",
|
|
1909
|
+
" {data.nav.map((item) => (",
|
|
1910
|
+
" <SidebarMenuItem key={item.name}>",
|
|
1911
|
+
" <SidebarMenuButton",
|
|
1912
|
+
" asChild",
|
|
1913
|
+
" isActive={item.name === \"Messages & media\"}",
|
|
1914
|
+
" >",
|
|
1915
|
+
" <a href=\"#\">",
|
|
1916
|
+
" <item.icon />",
|
|
1917
|
+
" <span>{item.name}</span>",
|
|
1918
|
+
" </a>",
|
|
1919
|
+
" </SidebarMenuButton>",
|
|
1920
|
+
" </SidebarMenuItem>",
|
|
1921
|
+
" ))}",
|
|
1922
|
+
" </SidebarMenu>",
|
|
1923
|
+
" </SidebarGroupContent>",
|
|
1924
|
+
" </SidebarGroup>",
|
|
1925
|
+
" </SidebarContent>",
|
|
1926
|
+
" </Sidebar>",
|
|
1927
|
+
" <main className=\"flex h-[480px] flex-1 flex-col overflow-hidden\">",
|
|
1928
|
+
" <header className=\"flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12\">",
|
|
1929
|
+
" <div className=\"flex items-center gap-2 px-4\">",
|
|
1930
|
+
" <Breadcrumb>",
|
|
1931
|
+
" <BreadcrumbList>",
|
|
1932
|
+
" <BreadcrumbItem className=\"hidden md:block\">",
|
|
1933
|
+
" <BreadcrumbLink href=\"#\">Settings</BreadcrumbLink>",
|
|
1934
|
+
" </BreadcrumbItem>",
|
|
1935
|
+
" <BreadcrumbSeparator className=\"hidden md:block\" />",
|
|
1936
|
+
" <BreadcrumbItem>",
|
|
1937
|
+
" <BreadcrumbPage>Messages & media</BreadcrumbPage>",
|
|
1938
|
+
" </BreadcrumbItem>",
|
|
1939
|
+
" </BreadcrumbList>",
|
|
1940
|
+
" </Breadcrumb>",
|
|
1941
|
+
" </div>",
|
|
1942
|
+
" </header>",
|
|
1943
|
+
" <div className=\"flex flex-1 flex-col gap-4 overflow-y-auto p-4 pt-0\">",
|
|
1944
|
+
" {Array.from({ length: 10 }).map((_, i) => (",
|
|
1945
|
+
" <div",
|
|
1946
|
+
" key={i}",
|
|
1947
|
+
" className=\"bg-muted/50 aspect-video max-w-3xl rounded-xl\"",
|
|
1948
|
+
" />",
|
|
1949
|
+
" ))}",
|
|
1950
|
+
" </div>",
|
|
1951
|
+
" </main>",
|
|
1952
|
+
" </SidebarProvider>",
|
|
1953
|
+
" </DialogContent>",
|
|
1954
|
+
" </Dialog>",
|
|
1955
|
+
"",
|
|
1956
|
+
" </div>",
|
|
1957
|
+
" )",
|
|
1958
|
+
"}"
|
|
1959
|
+
]
|
|
1960
|
+
},
|
|
1961
|
+
"login_page": {
|
|
1962
|
+
"prefix": "login_page",
|
|
1963
|
+
"description": "Description for login page",
|
|
1964
|
+
"scope": "javascript,typescript",
|
|
1965
|
+
"body": [
|
|
1966
|
+
"import { GalleryVerticalEnd } from \"lucide-react\"",
|
|
1967
|
+
"import { cn } from \"~/lib/utils\"",
|
|
1968
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
1969
|
+
"import { Input } from \"~/components/ui/input\"",
|
|
1970
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
1971
|
+
"",
|
|
1972
|
+
"",
|
|
1973
|
+
"",
|
|
1974
|
+
"export default function LoginPage() {",
|
|
1975
|
+
" return (",
|
|
1976
|
+
" <div className=\"bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10\">",
|
|
1977
|
+
" <div className=\"w-full max-w-sm\">",
|
|
1978
|
+
" <div className={cn(\"flex flex-col gap-6\", className)} {...props}>",
|
|
1979
|
+
" <form>",
|
|
1980
|
+
" <div className=\"flex flex-col gap-6\">",
|
|
1981
|
+
" <div className=\"flex flex-col items-center gap-2\">",
|
|
1982
|
+
" <a",
|
|
1983
|
+
" href=\"#\"",
|
|
1984
|
+
" className=\"flex flex-col items-center gap-2 font-medium\"",
|
|
1985
|
+
" >",
|
|
1986
|
+
" <div className=\"flex size-8 items-center justify-center rounded-md\">",
|
|
1987
|
+
" <GalleryVerticalEnd className=\"size-6\" />",
|
|
1988
|
+
" </div>",
|
|
1989
|
+
" <span className=\"sr-only\">Acme Inc.</span>",
|
|
1990
|
+
" </a>",
|
|
1991
|
+
" <h1 className=\"text-xl font-bold\">Welcome to Acme Inc.</h1>",
|
|
1992
|
+
" <div className=\"text-center text-sm\">",
|
|
1993
|
+
" Don't have an account?{\" \"}",
|
|
1994
|
+
" <a href=\"#\" className=\"underline underline-offset-4\">",
|
|
1995
|
+
" Sign up",
|
|
1996
|
+
" </a>",
|
|
1997
|
+
" </div>",
|
|
1998
|
+
" </div>",
|
|
1999
|
+
" <div className=\"flex flex-col gap-6\">",
|
|
2000
|
+
" <div className=\"grid gap-3\">",
|
|
2001
|
+
" <Label htmlFor=\"email\">Email</Label>",
|
|
2002
|
+
" <Input",
|
|
2003
|
+
" id=\"email\"",
|
|
2004
|
+
" type=\"email\"",
|
|
2005
|
+
" placeholder=\"m@example.com\"",
|
|
2006
|
+
" required",
|
|
2007
|
+
" />",
|
|
2008
|
+
" </div>",
|
|
2009
|
+
" <Button type=\"submit\" className=\"w-full\">",
|
|
2010
|
+
" Login",
|
|
2011
|
+
" </Button>",
|
|
2012
|
+
" </div>",
|
|
2013
|
+
" <div className=\"after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t\">",
|
|
2014
|
+
" <span className=\"bg-background text-muted-foreground relative z-10 px-2\">",
|
|
2015
|
+
" Or",
|
|
2016
|
+
" </span>",
|
|
2017
|
+
" </div>",
|
|
2018
|
+
" <div className=\"grid gap-4 sm:grid-cols-2\">",
|
|
2019
|
+
" <Button variant=\"outline\" type=\"button\" className=\"w-full\">",
|
|
2020
|
+
" <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">",
|
|
2021
|
+
" <path",
|
|
2022
|
+
" d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"",
|
|
2023
|
+
" fill=\"currentColor\"",
|
|
2024
|
+
" />",
|
|
2025
|
+
" </svg>",
|
|
2026
|
+
" Continue with Apple",
|
|
2027
|
+
" </Button>",
|
|
2028
|
+
" <Button variant=\"outline\" type=\"button\" className=\"w-full\">",
|
|
2029
|
+
" <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">",
|
|
2030
|
+
" <path",
|
|
2031
|
+
" d=\"M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z\"",
|
|
2032
|
+
" fill=\"currentColor\"",
|
|
2033
|
+
" />",
|
|
2034
|
+
" </svg>",
|
|
2035
|
+
" Continue with Google",
|
|
2036
|
+
" </Button>",
|
|
2037
|
+
" </div>",
|
|
2038
|
+
" </div>",
|
|
2039
|
+
" </form>",
|
|
2040
|
+
" <div className=\"text-muted-foreground *:[a]:hover:text-primary text-center text-xs text-balance *:[a]:underline *:[a]:underline-offset-4\">",
|
|
2041
|
+
" By clicking continue, you agree to our <a href=\"#\">Terms of Service</a>{\" \"}",
|
|
2042
|
+
" and <a href=\"#\">Privacy Policy</a>.",
|
|
2043
|
+
" </div>",
|
|
2044
|
+
" </div>",
|
|
2045
|
+
" </div>",
|
|
2046
|
+
" </div>",
|
|
2047
|
+
" )",
|
|
2048
|
+
"}",
|
|
2049
|
+
""
|
|
2050
|
+
]
|
|
2051
|
+
},
|
|
2052
|
+
"month_and_year_dropdown": {
|
|
2053
|
+
"prefix": "month_and_year_dropdown",
|
|
2054
|
+
"description": "Description for month and year dropdown",
|
|
2055
|
+
"scope": "javascript,typescript",
|
|
2056
|
+
"body": [
|
|
2057
|
+
"\"use client\"",
|
|
2058
|
+
"",
|
|
2059
|
+
"import * as React from \"react\"",
|
|
2060
|
+
"",
|
|
2061
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
2062
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
2063
|
+
"import {",
|
|
2064
|
+
" Select,",
|
|
2065
|
+
" SelectContent,",
|
|
2066
|
+
" SelectItem,",
|
|
2067
|
+
" SelectTrigger,",
|
|
2068
|
+
" SelectValue,",
|
|
2069
|
+
"} from \"~/components/ui/select\"",
|
|
2070
|
+
"",
|
|
2071
|
+
"export function MonthAndYearDropdown() {",
|
|
2072
|
+
" const [dropdown, setDropdown] =",
|
|
2073
|
+
" React.useState<React.ComponentProps<typeof Calendar>[\"captionLayout\"]>(",
|
|
2074
|
+
" \"dropdown\"",
|
|
2075
|
+
" )",
|
|
2076
|
+
" const [date, setDate] = React.useState<Date | undefined>(",
|
|
2077
|
+
" new Date(2025, 5, 12)",
|
|
2078
|
+
" )",
|
|
2079
|
+
"",
|
|
2080
|
+
" return (",
|
|
2081
|
+
" <div className=\"flex flex-col gap-4\">",
|
|
2082
|
+
" <Calendar",
|
|
2083
|
+
" mode=\"single\"",
|
|
2084
|
+
" defaultMonth={date}",
|
|
2085
|
+
" selected={date}",
|
|
2086
|
+
" onSelect={setDate}",
|
|
2087
|
+
" captionLayout={dropdown}",
|
|
2088
|
+
" className=\"rounded-lg border shadow-sm\"",
|
|
2089
|
+
" />",
|
|
2090
|
+
" <div className=\"flex flex-col gap-3\">",
|
|
2091
|
+
" <Label htmlFor=\"dropdown\" className=\"px-1\">",
|
|
2092
|
+
" Dropdown",
|
|
2093
|
+
" </Label>",
|
|
2094
|
+
" <Select",
|
|
2095
|
+
" value={dropdown}",
|
|
2096
|
+
" onValueChange={(value) =>",
|
|
2097
|
+
" setDropdown(",
|
|
2098
|
+
" value as React.ComponentProps<typeof Calendar>[\"captionLayout\"]",
|
|
2099
|
+
" )",
|
|
2100
|
+
" }",
|
|
2101
|
+
" >",
|
|
2102
|
+
" <SelectTrigger",
|
|
2103
|
+
" id=\"dropdown\"",
|
|
2104
|
+
" size=\"sm\"",
|
|
2105
|
+
" className=\"bg-background w-full\"",
|
|
2106
|
+
" >",
|
|
2107
|
+
" <SelectValue placeholder=\"Dropdown\" />",
|
|
2108
|
+
" </SelectTrigger>",
|
|
2109
|
+
" <SelectContent align=\"center\">",
|
|
2110
|
+
" <SelectItem value=\"dropdown\">Month and Year</SelectItem>",
|
|
2111
|
+
" <SelectItem value=\"dropdown-months\">Month Only</SelectItem>",
|
|
2112
|
+
" <SelectItem value=\"dropdown-years\">Year Only</SelectItem>",
|
|
2113
|
+
" </SelectContent>",
|
|
2114
|
+
" </Select>",
|
|
2115
|
+
" </div>",
|
|
2116
|
+
" </div>",
|
|
2117
|
+
" )",
|
|
2118
|
+
"}",
|
|
2119
|
+
""
|
|
2120
|
+
]
|
|
2121
|
+
},
|
|
2122
|
+
"sidebar": {
|
|
2123
|
+
"prefix": "sidebar",
|
|
2124
|
+
"description": "Description for sidebar",
|
|
2125
|
+
"scope": "javascript,typescript",
|
|
2126
|
+
"body": [
|
|
2127
|
+
"",
|
|
2128
|
+
"import { AppSidebar } from \"~/components/app-sidebar\"",
|
|
2129
|
+
"import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '~/components/ui/breadcrumb';",
|
|
2130
|
+
"import { Separator } from \"~/components/ui/separator\"",
|
|
2131
|
+
"import { SidebarInset, SidebarProvider, SidebarTrigger } from '~/components/ui/sidebar';",
|
|
2132
|
+
"import { AudioWaveform, BookOpen, Bot, Command, Frame, GalleryVerticalEnd, Map, PieChart, Settings2, SquareTerminal } from 'lucide-react';",
|
|
2133
|
+
"import { NavMain } from \"~/components/nav-main\"",
|
|
2134
|
+
"import { NavProjects } from \"~/components/nav-projects\"",
|
|
2135
|
+
"import { NavUser } from \"~/components/nav-user\"",
|
|
2136
|
+
"import { TeamSwitcher } from \"~/components/team-switcher\"",
|
|
2137
|
+
"import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from '~/components/ui/sidebar';",
|
|
2138
|
+
"import { Folder, Forward, MoreHorizontal, Trash2 } from 'lucide-react';",
|
|
2139
|
+
"import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '~/components/ui/dropdown-menu';",
|
|
2140
|
+
"import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, useSidebar } from '~/components/ui/sidebar';",
|
|
2141
|
+
"import { ChevronRight } from 'lucide-react';",
|
|
2142
|
+
"import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/collapsible';",
|
|
2143
|
+
"import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem } from '~/components/ui/sidebar';",
|
|
2144
|
+
"import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, LogOut, Sparkles, } from \"lucide-react\"",
|
|
2145
|
+
"import { Avatar, AvatarFallback, AvatarImage, } from \"~/components/ui/avatar\"",
|
|
2146
|
+
"import * as React from \"react\"",
|
|
2147
|
+
"import { ChevronsUpDown, Plus } from \"lucide-react\"",
|
|
2148
|
+
"import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger,} from \"~/components/ui/dropdown-menu\"",
|
|
2149
|
+
"import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar,} from \"~/components/ui/sidebar\"",
|
|
2150
|
+
"",
|
|
2151
|
+
"",
|
|
2152
|
+
"export function TeamSwitcher({",
|
|
2153
|
+
" teams,",
|
|
2154
|
+
"}: {",
|
|
2155
|
+
" teams: {",
|
|
2156
|
+
" name: string",
|
|
2157
|
+
" logo: React.ElementType",
|
|
2158
|
+
" plan: string",
|
|
2159
|
+
" }[]",
|
|
2160
|
+
"}) {",
|
|
2161
|
+
" const { isMobile } = useSidebar()",
|
|
2162
|
+
" const [activeTeam, setActiveTeam] = React.useState(teams[0])",
|
|
2163
|
+
" if (!activeTeam) {",
|
|
2164
|
+
" return null",
|
|
2165
|
+
" }",
|
|
2166
|
+
" return (",
|
|
2167
|
+
" <SidebarMenu>",
|
|
2168
|
+
" <SidebarMenuItem>",
|
|
2169
|
+
" <DropdownMenu>",
|
|
2170
|
+
" <DropdownMenuTrigger asChild>",
|
|
2171
|
+
" <SidebarMenuButton",
|
|
2172
|
+
" size=\"lg\"",
|
|
2173
|
+
" className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"",
|
|
2174
|
+
" >",
|
|
2175
|
+
" <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg\">",
|
|
2176
|
+
" <activeTeam.logo className=\"size-4\" />",
|
|
2177
|
+
" </div>",
|
|
2178
|
+
" <div className=\"grid flex-1 text-left text-sm leading-tight\">",
|
|
2179
|
+
" <span className=\"truncate font-medium\">{activeTeam.name}</span>",
|
|
2180
|
+
" <span className=\"truncate text-xs\">{activeTeam.plan}</span>",
|
|
2181
|
+
" </div>",
|
|
2182
|
+
" <ChevronsUpDown className=\"ml-auto\" />",
|
|
2183
|
+
" </SidebarMenuButton>",
|
|
2184
|
+
" </DropdownMenuTrigger>",
|
|
2185
|
+
" <DropdownMenuContent",
|
|
2186
|
+
" className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"",
|
|
2187
|
+
" align=\"start\"",
|
|
2188
|
+
" side={isMobile ? \"bottom\" : \"right\"}",
|
|
2189
|
+
" sideOffset={4}",
|
|
2190
|
+
" >",
|
|
2191
|
+
" <DropdownMenuLabel className=\"text-muted-foreground text-xs\">",
|
|
2192
|
+
" Teams",
|
|
2193
|
+
" </DropdownMenuLabel>",
|
|
2194
|
+
" {teams.map((team, index) => (",
|
|
2195
|
+
" <DropdownMenuItem",
|
|
2196
|
+
" key={team.name}",
|
|
2197
|
+
" onClick={() => setActiveTeam(team)}",
|
|
2198
|
+
" className=\"gap-2 p-2\"",
|
|
2199
|
+
" >",
|
|
2200
|
+
" <div className=\"flex size-6 items-center justify-center rounded-md border\">",
|
|
2201
|
+
" <team.logo className=\"size-3.5 shrink-0\" />",
|
|
2202
|
+
" </div>",
|
|
2203
|
+
" {team.name}",
|
|
2204
|
+
" <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>",
|
|
2205
|
+
" </DropdownMenuItem>",
|
|
2206
|
+
" ))}",
|
|
2207
|
+
" <DropdownMenuSeparator />",
|
|
2208
|
+
" <DropdownMenuItem className=\"gap-2 p-2\">",
|
|
2209
|
+
" <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">",
|
|
2210
|
+
" <Plus className=\"size-4\" />",
|
|
2211
|
+
" </div>",
|
|
2212
|
+
" <div className=\"text-muted-foreground font-medium\">Add team</div>",
|
|
2213
|
+
" </DropdownMenuItem>",
|
|
2214
|
+
" </DropdownMenuContent>",
|
|
2215
|
+
" </DropdownMenu>",
|
|
2216
|
+
" </SidebarMenuItem>",
|
|
2217
|
+
" </SidebarMenu>",
|
|
2218
|
+
" )",
|
|
2219
|
+
"}",
|
|
2220
|
+
"export function NavUser({",
|
|
2221
|
+
" user,",
|
|
2222
|
+
"}: {",
|
|
2223
|
+
" user: {",
|
|
2224
|
+
" name: string",
|
|
2225
|
+
" email: string",
|
|
2226
|
+
" avatar: string",
|
|
2227
|
+
" }",
|
|
2228
|
+
"}) {",
|
|
2229
|
+
" const { isMobile } = useSidebar()",
|
|
2230
|
+
" return (",
|
|
2231
|
+
" <SidebarMenu>",
|
|
2232
|
+
" <SidebarMenuItem>",
|
|
2233
|
+
" <DropdownMenu>",
|
|
2234
|
+
" <DropdownMenuTrigger asChild>",
|
|
2235
|
+
" <SidebarMenuButton",
|
|
2236
|
+
" size=\"lg\"",
|
|
2237
|
+
" className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"",
|
|
2238
|
+
" >",
|
|
2239
|
+
" <Avatar className=\"h-8 w-8 rounded-lg\">",
|
|
2240
|
+
" <AvatarImage src={user.avatar} alt={user.name} />",
|
|
2241
|
+
" <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>",
|
|
2242
|
+
" </Avatar>",
|
|
2243
|
+
" <div className=\"grid flex-1 text-left text-sm leading-tight\">",
|
|
2244
|
+
" <span className=\"truncate font-medium\">{user.name}</span>",
|
|
2245
|
+
" <span className=\"truncate text-xs\">{user.email}</span>",
|
|
2246
|
+
" </div>",
|
|
2247
|
+
" <ChevronsUpDown className=\"ml-auto size-4\" />",
|
|
2248
|
+
" </SidebarMenuButton>",
|
|
2249
|
+
" </DropdownMenuTrigger>",
|
|
2250
|
+
" <DropdownMenuContent",
|
|
2251
|
+
" className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"",
|
|
2252
|
+
" side={isMobile ? \"bottom\" : \"right\"}",
|
|
2253
|
+
" align=\"end\"",
|
|
2254
|
+
" sideOffset={4}",
|
|
2255
|
+
" >",
|
|
2256
|
+
" <DropdownMenuLabel className=\"p-0 font-normal\">",
|
|
2257
|
+
" <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">",
|
|
2258
|
+
" <Avatar className=\"h-8 w-8 rounded-lg\">",
|
|
2259
|
+
" <AvatarImage src={user.avatar} alt={user.name} />",
|
|
2260
|
+
" <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>",
|
|
2261
|
+
" </Avatar>",
|
|
2262
|
+
" <div className=\"grid flex-1 text-left text-sm leading-tight\">",
|
|
2263
|
+
" <span className=\"truncate font-medium\">{user.name}</span>",
|
|
2264
|
+
" <span className=\"truncate text-xs\">{user.email}</span>",
|
|
2265
|
+
" </div>",
|
|
2266
|
+
" </div>",
|
|
2267
|
+
" </DropdownMenuLabel>",
|
|
2268
|
+
" <DropdownMenuSeparator />",
|
|
2269
|
+
" <DropdownMenuGroup>",
|
|
2270
|
+
" <DropdownMenuItem>",
|
|
2271
|
+
" <Sparkles />",
|
|
2272
|
+
" Upgrade to Pro",
|
|
2273
|
+
" </DropdownMenuItem>",
|
|
2274
|
+
" </DropdownMenuGroup>",
|
|
2275
|
+
" <DropdownMenuSeparator />",
|
|
2276
|
+
" <DropdownMenuGroup>",
|
|
2277
|
+
" <DropdownMenuItem>",
|
|
2278
|
+
" <BadgeCheck />",
|
|
2279
|
+
" Account",
|
|
2280
|
+
" </DropdownMenuItem>",
|
|
2281
|
+
" <DropdownMenuItem>",
|
|
2282
|
+
" <CreditCard />",
|
|
2283
|
+
" Billing",
|
|
2284
|
+
" </DropdownMenuItem>",
|
|
2285
|
+
" <DropdownMenuItem>",
|
|
2286
|
+
" <Bell />",
|
|
2287
|
+
" Notifications",
|
|
2288
|
+
" </DropdownMenuItem>",
|
|
2289
|
+
" </DropdownMenuGroup>",
|
|
2290
|
+
" <DropdownMenuSeparator />",
|
|
2291
|
+
" <DropdownMenuItem>",
|
|
2292
|
+
" <LogOut />",
|
|
2293
|
+
" Log out",
|
|
2294
|
+
" </DropdownMenuItem>",
|
|
2295
|
+
" </DropdownMenuContent>",
|
|
2296
|
+
" </DropdownMenu>",
|
|
2297
|
+
" </SidebarMenuItem>",
|
|
2298
|
+
" </SidebarMenu>",
|
|
2299
|
+
" )",
|
|
2300
|
+
"}",
|
|
2301
|
+
"export function NavProjects({",
|
|
2302
|
+
" projects,",
|
|
2303
|
+
"}: {",
|
|
2304
|
+
" projects: {",
|
|
2305
|
+
" name: string",
|
|
2306
|
+
" url: string",
|
|
2307
|
+
" icon: LucideIcon",
|
|
2308
|
+
" }[]",
|
|
2309
|
+
"}) {",
|
|
2310
|
+
" const { isMobile } = useSidebar()",
|
|
2311
|
+
" return (",
|
|
2312
|
+
" <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">",
|
|
2313
|
+
" <SidebarGroupLabel>Projects</SidebarGroupLabel>",
|
|
2314
|
+
" <SidebarMenu>",
|
|
2315
|
+
" {projects.map((item) => (",
|
|
2316
|
+
" <SidebarMenuItem key={item.name}>",
|
|
2317
|
+
" <SidebarMenuButton asChild>",
|
|
2318
|
+
" <a href={item.url}>",
|
|
2319
|
+
" <item.icon />",
|
|
2320
|
+
" <span>{item.name}</span>",
|
|
2321
|
+
" </a>",
|
|
2322
|
+
" </SidebarMenuButton>",
|
|
2323
|
+
" <DropdownMenu>",
|
|
2324
|
+
" <DropdownMenuTrigger asChild>",
|
|
2325
|
+
" <SidebarMenuAction showOnHover>",
|
|
2326
|
+
" <MoreHorizontal />",
|
|
2327
|
+
" <span className=\"sr-only\">More</span>",
|
|
2328
|
+
" </SidebarMenuAction>",
|
|
2329
|
+
" </DropdownMenuTrigger>",
|
|
2330
|
+
" <DropdownMenuContent",
|
|
2331
|
+
" className=\"w-48 rounded-lg\"",
|
|
2332
|
+
" side={isMobile ? \"bottom\" : \"right\"}",
|
|
2333
|
+
" align={isMobile ? \"end\" : \"start\"}",
|
|
2334
|
+
" >",
|
|
2335
|
+
" <DropdownMenuItem>",
|
|
2336
|
+
" <Folder className=\"text-muted-foreground\" />",
|
|
2337
|
+
" <span>View Project</span>",
|
|
2338
|
+
" </DropdownMenuItem>",
|
|
2339
|
+
" <DropdownMenuItem>",
|
|
2340
|
+
" <Forward className=\"text-muted-foreground\" />",
|
|
2341
|
+
" <span>Share Project</span>",
|
|
2342
|
+
" </DropdownMenuItem>",
|
|
2343
|
+
" <DropdownMenuSeparator />",
|
|
2344
|
+
" <DropdownMenuItem>",
|
|
2345
|
+
" <Trash2 className=\"text-muted-foreground\" />",
|
|
2346
|
+
" <span>Delete Project</span>",
|
|
2347
|
+
" </DropdownMenuItem>",
|
|
2348
|
+
" </DropdownMenuContent>",
|
|
2349
|
+
" </DropdownMenu>",
|
|
2350
|
+
" </SidebarMenuItem>",
|
|
2351
|
+
" ))}",
|
|
2352
|
+
" <SidebarMenuItem>",
|
|
2353
|
+
" <SidebarMenuButton className=\"text-sidebar-foreground/70\">",
|
|
2354
|
+
" <MoreHorizontal className=\"text-sidebar-foreground/70\" />",
|
|
2355
|
+
" <span>More</span>",
|
|
2356
|
+
" </SidebarMenuButton>",
|
|
2357
|
+
" </SidebarMenuItem>",
|
|
2358
|
+
" </SidebarMenu>",
|
|
2359
|
+
" </SidebarGroup>",
|
|
2360
|
+
" )",
|
|
2361
|
+
"}",
|
|
2362
|
+
"export function NavMain({",
|
|
2363
|
+
" items,",
|
|
2364
|
+
"}: {",
|
|
2365
|
+
" items: {",
|
|
2366
|
+
" title: string",
|
|
2367
|
+
" url: string",
|
|
2368
|
+
" icon?: LucideIcon",
|
|
2369
|
+
" isActive?: boolean",
|
|
2370
|
+
" items?: {",
|
|
2371
|
+
" title: string",
|
|
2372
|
+
" url: string",
|
|
2373
|
+
" }[]",
|
|
2374
|
+
" }[]",
|
|
2375
|
+
"}) {",
|
|
2376
|
+
" return (",
|
|
2377
|
+
" <SidebarGroup>",
|
|
2378
|
+
" <SidebarGroupLabel>Platform</SidebarGroupLabel>",
|
|
2379
|
+
" <SidebarMenu>",
|
|
2380
|
+
" {items.map((item) => (",
|
|
2381
|
+
" <Collapsible",
|
|
2382
|
+
" key={item.title}",
|
|
2383
|
+
" asChild",
|
|
2384
|
+
" defaultOpen={item.isActive}",
|
|
2385
|
+
" className=\"group/collapsible\"",
|
|
2386
|
+
" >",
|
|
2387
|
+
" <SidebarMenuItem>",
|
|
2388
|
+
" <CollapsibleTrigger asChild>",
|
|
2389
|
+
" <SidebarMenuButton tooltip={item.title}>",
|
|
2390
|
+
" {item.icon && <item.icon />}",
|
|
2391
|
+
" <span>{item.title}</span>",
|
|
2392
|
+
" <ChevronRight className=\"ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90\" />",
|
|
2393
|
+
" </SidebarMenuButton>",
|
|
2394
|
+
" </CollapsibleTrigger>",
|
|
2395
|
+
" <CollapsibleContent>",
|
|
2396
|
+
" <SidebarMenuSub>",
|
|
2397
|
+
" {item.items?.map((subItem) => (",
|
|
2398
|
+
" <SidebarMenuSubItem key={subItem.title}>",
|
|
2399
|
+
" <SidebarMenuSubButton asChild>",
|
|
2400
|
+
" <a href={subItem.url}>",
|
|
2401
|
+
" <span>{subItem.title}</span>",
|
|
2402
|
+
" </a>",
|
|
2403
|
+
" </SidebarMenuSubButton>",
|
|
2404
|
+
" </SidebarMenuSubItem>",
|
|
2405
|
+
" ))}",
|
|
2406
|
+
" </SidebarMenuSub>",
|
|
2407
|
+
" </CollapsibleContent>",
|
|
2408
|
+
" </SidebarMenuItem>",
|
|
2409
|
+
" </Collapsible>",
|
|
2410
|
+
" ))}",
|
|
2411
|
+
" </SidebarMenu>",
|
|
2412
|
+
" </SidebarGroup>",
|
|
2413
|
+
" )",
|
|
2414
|
+
"}",
|
|
2415
|
+
"const data = {",
|
|
2416
|
+
" user: {",
|
|
2417
|
+
" name: \"shadcn\",",
|
|
2418
|
+
" email: \"m@example.com\",",
|
|
2419
|
+
" avatar: \"/avatars/shadcn.jpg\",",
|
|
2420
|
+
" },",
|
|
2421
|
+
" teams: [",
|
|
2422
|
+
" {",
|
|
2423
|
+
" name: \"Acme Inc\",",
|
|
2424
|
+
" logo: GalleryVerticalEnd,",
|
|
2425
|
+
" plan: \"Enterprise\",",
|
|
2426
|
+
" },",
|
|
2427
|
+
" {",
|
|
2428
|
+
" name: \"Acme Corp.\",",
|
|
2429
|
+
" logo: AudioWaveform,",
|
|
2430
|
+
" plan: \"Startup\",",
|
|
2431
|
+
" },",
|
|
2432
|
+
" {",
|
|
2433
|
+
" name: \"Evil Corp.\",",
|
|
2434
|
+
" logo: Command,",
|
|
2435
|
+
" plan: \"Free\",",
|
|
2436
|
+
" },",
|
|
2437
|
+
" ],",
|
|
2438
|
+
" navMain: [",
|
|
2439
|
+
" {",
|
|
2440
|
+
" title: \"Playground\",",
|
|
2441
|
+
" url: \"#\",",
|
|
2442
|
+
" icon: SquareTerminal,",
|
|
2443
|
+
" isActive: true,",
|
|
2444
|
+
" items: [",
|
|
2445
|
+
" {",
|
|
2446
|
+
" title: \"History\",",
|
|
2447
|
+
" url: \"#\",",
|
|
2448
|
+
" },",
|
|
2449
|
+
" {",
|
|
2450
|
+
" title: \"Starred\",",
|
|
2451
|
+
" url: \"#\",",
|
|
2452
|
+
" },",
|
|
2453
|
+
" {",
|
|
2454
|
+
" title: \"Settings\",",
|
|
2455
|
+
" url: \"#\",",
|
|
2456
|
+
" },",
|
|
2457
|
+
" ],",
|
|
2458
|
+
" },",
|
|
2459
|
+
" {",
|
|
2460
|
+
" title: \"Models\",",
|
|
2461
|
+
" url: \"#\",",
|
|
2462
|
+
" icon: Bot,",
|
|
2463
|
+
" items: [",
|
|
2464
|
+
" {",
|
|
2465
|
+
" title: \"Genesis\",",
|
|
2466
|
+
" url: \"#\",",
|
|
2467
|
+
" },",
|
|
2468
|
+
" {",
|
|
2469
|
+
" title: \"Explorer\",",
|
|
2470
|
+
" url: \"#\",",
|
|
2471
|
+
" },",
|
|
2472
|
+
" {",
|
|
2473
|
+
" title: \"Quantum\",",
|
|
2474
|
+
" url: \"#\",",
|
|
2475
|
+
" },",
|
|
2476
|
+
" ],",
|
|
2477
|
+
" },",
|
|
2478
|
+
" {",
|
|
2479
|
+
" title: \"Documentation\",",
|
|
2480
|
+
" url: \"#\",",
|
|
2481
|
+
" icon: BookOpen,",
|
|
2482
|
+
" items: [",
|
|
2483
|
+
" {",
|
|
2484
|
+
" title: \"Introduction\",",
|
|
2485
|
+
" url: \"#\",",
|
|
2486
|
+
" },",
|
|
2487
|
+
" {",
|
|
2488
|
+
" title: \"Get Started\",",
|
|
2489
|
+
" url: \"#\",",
|
|
2490
|
+
" },",
|
|
2491
|
+
" {",
|
|
2492
|
+
" title: \"Tutorials\",",
|
|
2493
|
+
" url: \"#\",",
|
|
2494
|
+
" },",
|
|
2495
|
+
" {",
|
|
2496
|
+
" title: \"Changelog\",",
|
|
2497
|
+
" url: \"#\",",
|
|
2498
|
+
" },",
|
|
2499
|
+
" ],",
|
|
2500
|
+
" },",
|
|
2501
|
+
" {",
|
|
2502
|
+
" title: \"Settings\",",
|
|
2503
|
+
" url: \"#\",",
|
|
2504
|
+
" icon: Settings2,",
|
|
2505
|
+
" items: [",
|
|
2506
|
+
" {",
|
|
2507
|
+
" title: \"General\",",
|
|
2508
|
+
" url: \"#\",",
|
|
2509
|
+
" },",
|
|
2510
|
+
" {",
|
|
2511
|
+
" title: \"Team\",",
|
|
2512
|
+
" url: \"#\",",
|
|
2513
|
+
" },",
|
|
2514
|
+
" {",
|
|
2515
|
+
" title: \"Billing\",",
|
|
2516
|
+
" url: \"#\",",
|
|
2517
|
+
" },",
|
|
2518
|
+
" {",
|
|
2519
|
+
" title: \"Limits\",",
|
|
2520
|
+
" url: \"#\",",
|
|
2521
|
+
" },",
|
|
2522
|
+
" ],",
|
|
2523
|
+
" },",
|
|
2524
|
+
" ],",
|
|
2525
|
+
" projects: [",
|
|
2526
|
+
" {",
|
|
2527
|
+
" name: \"Design Engineering\",",
|
|
2528
|
+
" url: \"#\",",
|
|
2529
|
+
" icon: Frame,",
|
|
2530
|
+
" },",
|
|
2531
|
+
" {",
|
|
2532
|
+
" name: \"Sales & Marketing\",",
|
|
2533
|
+
" url: \"#\",",
|
|
2534
|
+
" icon: PieChart,",
|
|
2535
|
+
" },",
|
|
2536
|
+
" {",
|
|
2537
|
+
" name: \"Travel\",",
|
|
2538
|
+
" url: \"#\",",
|
|
2539
|
+
" icon: Map,",
|
|
2540
|
+
" },",
|
|
2541
|
+
" ],",
|
|
2542
|
+
"}",
|
|
2543
|
+
"export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {",
|
|
2544
|
+
" return (",
|
|
2545
|
+
" <Sidebar collapsible=\"icon\" {...props}>",
|
|
2546
|
+
" <SidebarHeader>",
|
|
2547
|
+
" <TeamSwitcher teams={data.teams} />",
|
|
2548
|
+
" </SidebarHeader>",
|
|
2549
|
+
" <SidebarContent>",
|
|
2550
|
+
" <NavMain items={data.navMain} />",
|
|
2551
|
+
" <NavProjects projects={data.projects} />",
|
|
2552
|
+
" </SidebarContent>",
|
|
2553
|
+
" <SidebarFooter>",
|
|
2554
|
+
" <NavUser user={data.user} />",
|
|
2555
|
+
" </SidebarFooter>",
|
|
2556
|
+
" <SidebarRail />",
|
|
2557
|
+
" </Sidebar>",
|
|
2558
|
+
" )",
|
|
2559
|
+
"}",
|
|
2560
|
+
"export default function Page() {",
|
|
2561
|
+
" return (",
|
|
2562
|
+
" <SidebarProvider>",
|
|
2563
|
+
" <AppSidebar />",
|
|
2564
|
+
" <SidebarInset>",
|
|
2565
|
+
" <header className=\"flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12\">",
|
|
2566
|
+
" <div className=\"flex items-center gap-2 px-4\">",
|
|
2567
|
+
" <SidebarTrigger className=\"-ml-1\" />",
|
|
2568
|
+
" <Separator",
|
|
2569
|
+
" orientation=\"vertical\"",
|
|
2570
|
+
" className=\"mr-2 data-[orientation=vertical]:h-4\"",
|
|
2571
|
+
" />",
|
|
2572
|
+
" <Breadcrumb>",
|
|
2573
|
+
" <BreadcrumbList>",
|
|
2574
|
+
" <BreadcrumbItem className=\"hidden md:block\">",
|
|
2575
|
+
" <BreadcrumbLink href=\"#\">",
|
|
2576
|
+
" Building Your Application",
|
|
2577
|
+
" </BreadcrumbLink>",
|
|
2578
|
+
" </BreadcrumbItem>",
|
|
2579
|
+
" <BreadcrumbSeparator className=\"hidden md:block\" />",
|
|
2580
|
+
" <BreadcrumbItem>",
|
|
2581
|
+
" <BreadcrumbPage>Data Fetching</BreadcrumbPage>",
|
|
2582
|
+
" </BreadcrumbItem>",
|
|
2583
|
+
" </BreadcrumbList>",
|
|
2584
|
+
" </Breadcrumb>",
|
|
2585
|
+
" </div>",
|
|
2586
|
+
" </header>",
|
|
2587
|
+
" <div className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">",
|
|
2588
|
+
" <div className=\"grid auto-rows-min gap-4 md:grid-cols-3\">",
|
|
2589
|
+
" <div className=\"bg-muted/50 aspect-video rounded-xl\" />",
|
|
2590
|
+
" <div className=\"bg-muted/50 aspect-video rounded-xl\" />",
|
|
2591
|
+
" <div className=\"bg-muted/50 aspect-video rounded-xl\" />",
|
|
2592
|
+
" </div>",
|
|
2593
|
+
" <div className=\"bg-muted/50 min-h-[100vh] flex-1 rounded-xl md:min-h-min\" />",
|
|
2594
|
+
" </div>",
|
|
2595
|
+
" </SidebarInset>",
|
|
2596
|
+
" </SidebarProvider>",
|
|
2597
|
+
" )",
|
|
2598
|
+
"}",
|
|
2599
|
+
"",
|
|
2600
|
+
"",
|
|
2601
|
+
""
|
|
2602
|
+
]
|
|
2603
|
+
},
|
|
2604
|
+
"with_time_picker": {
|
|
2605
|
+
"prefix": "with_time_picker",
|
|
2606
|
+
"description": "Description for with time picker",
|
|
2607
|
+
"scope": "javascript,typescript",
|
|
2608
|
+
"body": [
|
|
2609
|
+
"\"use client\"",
|
|
2610
|
+
"",
|
|
2611
|
+
"import * as React from \"react\"",
|
|
2612
|
+
"import { Clock2Icon } from \"lucide-react\"",
|
|
2613
|
+
"",
|
|
2614
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
2615
|
+
"import { Card, CardContent, CardFooter } from \"~/components/ui/card\"",
|
|
2616
|
+
"import { Input } from \"~/components/ui/input\"",
|
|
2617
|
+
"import { Label } from \"~/components/ui/label\"",
|
|
2618
|
+
"",
|
|
2619
|
+
"export function WithTimePicker() {",
|
|
2620
|
+
" const [date, setDate] = React.useState<Date | undefined>(",
|
|
2621
|
+
" new Date(2025, 5, 12)",
|
|
2622
|
+
" )",
|
|
2623
|
+
"",
|
|
2624
|
+
" return (",
|
|
2625
|
+
" <Card className=\"w-fit py-4\">",
|
|
2626
|
+
" <CardContent className=\"px-4\">",
|
|
2627
|
+
" <Calendar",
|
|
2628
|
+
" mode=\"single\"",
|
|
2629
|
+
" selected={date}",
|
|
2630
|
+
" onSelect={setDate}",
|
|
2631
|
+
" className=\"bg-transparent p-0\"",
|
|
2632
|
+
" />",
|
|
2633
|
+
" </CardContent>",
|
|
2634
|
+
" <CardFooter className=\"flex flex-col gap-6 border-t px-4 !pt-4\">",
|
|
2635
|
+
" <div className=\"flex w-full flex-col gap-3\">",
|
|
2636
|
+
" <Label htmlFor=\"time-from\">Start Time</Label>",
|
|
2637
|
+
" <div className=\"relative flex w-full items-center gap-2\">",
|
|
2638
|
+
" <Clock2Icon className=\"text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none\" />",
|
|
2639
|
+
" <Input",
|
|
2640
|
+
" id=\"time-from\"",
|
|
2641
|
+
" type=\"time\"",
|
|
2642
|
+
" step=\"1\"",
|
|
2643
|
+
" defaultValue=\"10:30:00\"",
|
|
2644
|
+
" className=\"appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none\"",
|
|
2645
|
+
" />",
|
|
2646
|
+
" </div>",
|
|
2647
|
+
" </div>",
|
|
2648
|
+
" <div className=\"flex w-full flex-col gap-3\">",
|
|
2649
|
+
" <Label htmlFor=\"time-to\">End Time</Label>",
|
|
2650
|
+
" <div className=\"relative flex w-full items-center gap-2\">",
|
|
2651
|
+
" <Clock2Icon className=\"text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none\" />",
|
|
2652
|
+
" <Input",
|
|
2653
|
+
" id=\"time-to\"",
|
|
2654
|
+
" type=\"time\"",
|
|
2655
|
+
" step=\"1\"",
|
|
2656
|
+
" defaultValue=\"12:30:00\"",
|
|
2657
|
+
" className=\"appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none\"",
|
|
2658
|
+
" />",
|
|
2659
|
+
" </div>",
|
|
2660
|
+
" </div>",
|
|
2661
|
+
" </CardFooter>",
|
|
2662
|
+
" </Card>",
|
|
2663
|
+
" )",
|
|
2664
|
+
"}",
|
|
2665
|
+
""
|
|
2666
|
+
]
|
|
2667
|
+
},
|
|
2668
|
+
"calendar_chart_filter": {
|
|
2669
|
+
"prefix": "calendar_chart_filter",
|
|
2670
|
+
"description": "Description for calendar chart filter",
|
|
2671
|
+
"scope": "javascript,typescript",
|
|
2672
|
+
"body": [
|
|
2673
|
+
"\"use client\"",
|
|
2674
|
+
"",
|
|
2675
|
+
"import * as React from \"react\"",
|
|
2676
|
+
"import { CalendarIcon } from \"lucide-react\"",
|
|
2677
|
+
"import { DateRange } from \"react-day-picker\"",
|
|
2678
|
+
"import { Bar, BarChart, CartesianGrid, XAxis } from \"recharts\"",
|
|
2679
|
+
"",
|
|
2680
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
2681
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
2682
|
+
"import {",
|
|
2683
|
+
" Card,",
|
|
2684
|
+
" CardAction,",
|
|
2685
|
+
" CardContent,",
|
|
2686
|
+
" CardDescription,",
|
|
2687
|
+
" CardFooter,",
|
|
2688
|
+
" CardHeader,",
|
|
2689
|
+
" CardTitle,",
|
|
2690
|
+
"} from \"~/components/ui/card\"",
|
|
2691
|
+
"import {",
|
|
2692
|
+
" ChartConfig,",
|
|
2693
|
+
" ChartContainer,",
|
|
2694
|
+
" ChartTooltip,",
|
|
2695
|
+
" ChartTooltipContent,",
|
|
2696
|
+
"} from \"~/components/ui/chart\"",
|
|
2697
|
+
"import {",
|
|
2698
|
+
" Popover,",
|
|
2699
|
+
" PopoverContent,",
|
|
2700
|
+
" PopoverTrigger,",
|
|
2701
|
+
"} from \"~/components/ui/popover\"",
|
|
2702
|
+
"",
|
|
2703
|
+
"const chartData = [",
|
|
2704
|
+
" { date: \"2025-06-01\", visitors: 178 },",
|
|
2705
|
+
" { date: \"2025-06-02\", visitors: 470 },",
|
|
2706
|
+
" { date: \"2025-06-03\", visitors: 103 },",
|
|
2707
|
+
" { date: \"2025-06-04\", visitors: 439 },",
|
|
2708
|
+
" { date: \"2025-06-05\", visitors: 88 },",
|
|
2709
|
+
" { date: \"2025-06-06\", visitors: 294 },",
|
|
2710
|
+
" { date: \"2025-06-07\", visitors: 323 },",
|
|
2711
|
+
" { date: \"2025-06-08\", visitors: 385 },",
|
|
2712
|
+
" { date: \"2025-06-09\", visitors: 438 },",
|
|
2713
|
+
" { date: \"2025-06-10\", visitors: 155 },",
|
|
2714
|
+
" { date: \"2025-06-11\", visitors: 92 },",
|
|
2715
|
+
" { date: \"2025-06-12\", visitors: 492 },",
|
|
2716
|
+
" { date: \"2025-06-13\", visitors: 81 },",
|
|
2717
|
+
" { date: \"2025-06-14\", visitors: 426 },",
|
|
2718
|
+
" { date: \"2025-06-15\", visitors: 307 },",
|
|
2719
|
+
" { date: \"2025-06-16\", visitors: 371 },",
|
|
2720
|
+
" { date: \"2025-06-17\", visitors: 475 },",
|
|
2721
|
+
" { date: \"2025-06-18\", visitors: 107 },",
|
|
2722
|
+
" { date: \"2025-06-19\", visitors: 341 },",
|
|
2723
|
+
" { date: \"2025-06-20\", visitors: 408 },",
|
|
2724
|
+
" { date: \"2025-06-21\", visitors: 169 },",
|
|
2725
|
+
" { date: \"2025-06-22\", visitors: 317 },",
|
|
2726
|
+
" { date: \"2025-06-23\", visitors: 480 },",
|
|
2727
|
+
" { date: \"2025-06-24\", visitors: 132 },",
|
|
2728
|
+
" { date: \"2025-06-25\", visitors: 141 },",
|
|
2729
|
+
" { date: \"2025-06-26\", visitors: 434 },",
|
|
2730
|
+
" { date: \"2025-06-27\", visitors: 448 },",
|
|
2731
|
+
" { date: \"2025-06-28\", visitors: 149 },",
|
|
2732
|
+
" { date: \"2025-06-29\", visitors: 103 },",
|
|
2733
|
+
" { date: \"2025-06-30\", visitors: 446 },",
|
|
2734
|
+
"]",
|
|
2735
|
+
"",
|
|
2736
|
+
"const total = chartData.reduce((acc, curr) => acc + curr.visitors, 0)",
|
|
2737
|
+
"",
|
|
2738
|
+
"const chartConfig = {",
|
|
2739
|
+
" visitors: {",
|
|
2740
|
+
" label: \"Visitors\",",
|
|
2741
|
+
" color: \"var(--color-primary)\",",
|
|
2742
|
+
" },",
|
|
2743
|
+
"} satisfies ChartConfig",
|
|
2744
|
+
"",
|
|
2745
|
+
"export function Calendar27() {",
|
|
2746
|
+
" const [range, setRange] = React.useState<DateRange | undefined>({",
|
|
2747
|
+
" from: new Date(2025, 5, 5),",
|
|
2748
|
+
" to: new Date(2025, 5, 20),",
|
|
2749
|
+
" })",
|
|
2750
|
+
" const filteredData = React.useMemo(() => {",
|
|
2751
|
+
" if (!range?.from && !range?.to) {",
|
|
2752
|
+
" return chartData",
|
|
2753
|
+
" }",
|
|
2754
|
+
"",
|
|
2755
|
+
" return chartData.filter((item) => {",
|
|
2756
|
+
" const date = new Date(item.date)",
|
|
2757
|
+
" return date >= range.from! && date <= range.to!",
|
|
2758
|
+
" })",
|
|
2759
|
+
" }, [range])",
|
|
2760
|
+
"",
|
|
2761
|
+
" return (",
|
|
2762
|
+
" <Card className=\"@container/card w-full max-w-xl\">",
|
|
2763
|
+
" <CardHeader className=\"flex flex-col border-b @md/card:grid\">",
|
|
2764
|
+
" <CardTitle>Web Analytics</CardTitle>",
|
|
2765
|
+
" <CardDescription>",
|
|
2766
|
+
" Showing total visitors for this month.",
|
|
2767
|
+
" </CardDescription>",
|
|
2768
|
+
" <CardAction className=\"mt-2 @md/card:mt-0\">",
|
|
2769
|
+
" <Popover>",
|
|
2770
|
+
" <PopoverTrigger asChild>",
|
|
2771
|
+
" <Button variant=\"outline\">",
|
|
2772
|
+
" <CalendarIcon />",
|
|
2773
|
+
" {range?.from && range?.to",
|
|
2774
|
+
" ? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`",
|
|
2775
|
+
" : \"June 2025\"}",
|
|
2776
|
+
" </Button>",
|
|
2777
|
+
" </PopoverTrigger>",
|
|
2778
|
+
" <PopoverContent className=\"w-auto overflow-hidden p-0\" align=\"end\">",
|
|
2779
|
+
" <Calendar",
|
|
2780
|
+
" className=\"w-full\"",
|
|
2781
|
+
" mode=\"range\"",
|
|
2782
|
+
" defaultMonth={range?.from}",
|
|
2783
|
+
" selected={range}",
|
|
2784
|
+
" onSelect={setRange}",
|
|
2785
|
+
" disableNavigation",
|
|
2786
|
+
" startMonth={range?.from}",
|
|
2787
|
+
" fixedWeeks",
|
|
2788
|
+
" showOutsideDays",
|
|
2789
|
+
" disabled={{",
|
|
2790
|
+
" after: new Date(2025, 5, 31),",
|
|
2791
|
+
" }}",
|
|
2792
|
+
" />",
|
|
2793
|
+
" </PopoverContent>",
|
|
2794
|
+
" </Popover>",
|
|
2795
|
+
" </CardAction>",
|
|
2796
|
+
" </CardHeader>",
|
|
2797
|
+
" <CardContent className=\"px-4\">",
|
|
2798
|
+
" <ChartContainer",
|
|
2799
|
+
" config={chartConfig}",
|
|
2800
|
+
" className=\"aspect-auto h-[250px] w-full\"",
|
|
2801
|
+
" >",
|
|
2802
|
+
" <BarChart",
|
|
2803
|
+
" accessibilityLayer",
|
|
2804
|
+
" data={filteredData}",
|
|
2805
|
+
" margin={{",
|
|
2806
|
+
" left: 12,",
|
|
2807
|
+
" right: 12,",
|
|
2808
|
+
" }}",
|
|
2809
|
+
" >",
|
|
2810
|
+
" <CartesianGrid vertical={false} />",
|
|
2811
|
+
" <XAxis",
|
|
2812
|
+
" dataKey=\"date\"",
|
|
2813
|
+
" tickLine={false}",
|
|
2814
|
+
" axisLine={false}",
|
|
2815
|
+
" tickMargin={8}",
|
|
2816
|
+
" minTickGap={20}",
|
|
2817
|
+
" tickFormatter={(value) => {",
|
|
2818
|
+
" const date = new Date(value)",
|
|
2819
|
+
" return date.toLocaleDateString(\"en-US\", {",
|
|
2820
|
+
" day: \"numeric\",",
|
|
2821
|
+
" })",
|
|
2822
|
+
" }}",
|
|
2823
|
+
" />",
|
|
2824
|
+
" <ChartTooltip",
|
|
2825
|
+
" content={",
|
|
2826
|
+
" <ChartTooltipContent",
|
|
2827
|
+
" className=\"w-[150px]\"",
|
|
2828
|
+
" nameKey=\"visitors\"",
|
|
2829
|
+
" labelFormatter={(value) => {",
|
|
2830
|
+
" return new Date(value).toLocaleDateString(\"en-US\", {",
|
|
2831
|
+
" month: \"short\",",
|
|
2832
|
+
" day: \"numeric\",",
|
|
2833
|
+
" year: \"numeric\",",
|
|
2834
|
+
" })",
|
|
2835
|
+
" }}",
|
|
2836
|
+
" />",
|
|
2837
|
+
" }",
|
|
2838
|
+
" />",
|
|
2839
|
+
" <Bar dataKey=\"visitors\" fill={`var(--color-visitors)`} radius={4} />",
|
|
2840
|
+
" </BarChart>",
|
|
2841
|
+
" </ChartContainer>",
|
|
2842
|
+
" </CardContent>",
|
|
2843
|
+
" <CardFooter className=\"border-t\">",
|
|
2844
|
+
" <div className=\"text-sm\">",
|
|
2845
|
+
" You had{\" \"}",
|
|
2846
|
+
" <span className=\"font-semibold\">{total.toLocaleString()}</span>{\" \"}",
|
|
2847
|
+
" visitors for the month of June.",
|
|
2848
|
+
" </div>",
|
|
2849
|
+
" </CardFooter>",
|
|
2850
|
+
" </Card>",
|
|
2851
|
+
" )",
|
|
2852
|
+
"}",
|
|
2853
|
+
""
|
|
2854
|
+
]
|
|
2855
|
+
},
|
|
2856
|
+
"calendar_with_event_slots": {
|
|
2857
|
+
"prefix": "calendar_with_event_slots",
|
|
2858
|
+
"description": "Description for calendar with event slots",
|
|
2859
|
+
"scope": "javascript,typescript",
|
|
2860
|
+
"body": [
|
|
2861
|
+
"\"use client\"",
|
|
2862
|
+
"",
|
|
2863
|
+
"import * as React from \"react\"",
|
|
2864
|
+
"import { formatDateRange } from \"little-date\"",
|
|
2865
|
+
"import { PlusIcon } from \"lucide-react\"",
|
|
2866
|
+
"",
|
|
2867
|
+
"import { Button } from \"~/components/ui/button\"",
|
|
2868
|
+
"import { Calendar } from \"~/components/ui/calendar\"",
|
|
2869
|
+
"import { Card, CardContent, CardFooter } from \"~/components/ui/card\"",
|
|
2870
|
+
"",
|
|
2871
|
+
"const events = [",
|
|
2872
|
+
" {",
|
|
2873
|
+
" title: \"Team Sync Meeting\",",
|
|
2874
|
+
" from: \"2025-06-12T09:00:00\",",
|
|
2875
|
+
" to: \"2025-06-12T10:00:00\",",
|
|
2876
|
+
" },",
|
|
2877
|
+
" {",
|
|
2878
|
+
" title: \"Design Review\",",
|
|
2879
|
+
" from: \"2025-06-12T11:30:00\",",
|
|
2880
|
+
" to: \"2025-06-12T12:30:00\",",
|
|
2881
|
+
" },",
|
|
2882
|
+
" {",
|
|
2883
|
+
" title: \"Client Presentation\",",
|
|
2884
|
+
" from: \"2025-06-12T14:00:00\",",
|
|
2885
|
+
" to: \"2025-06-12T15:00:00\",",
|
|
2886
|
+
" },",
|
|
2887
|
+
"]",
|
|
2888
|
+
"",
|
|
2889
|
+
"export function Calendar31() {",
|
|
2890
|
+
" const [date, setDate] = React.useState<Date | undefined>(",
|
|
2891
|
+
" new Date(2025, 5, 12)",
|
|
2892
|
+
" )",
|
|
2893
|
+
"",
|
|
2894
|
+
" return (",
|
|
2895
|
+
" <Card className=\"w-fit py-4\">",
|
|
2896
|
+
" <CardContent className=\"px-4\">",
|
|
2897
|
+
" <Calendar",
|
|
2898
|
+
" mode=\"single\"",
|
|
2899
|
+
" selected={date}",
|
|
2900
|
+
" onSelect={setDate}",
|
|
2901
|
+
" className=\"bg-transparent p-0\"",
|
|
2902
|
+
" required",
|
|
2903
|
+
" />",
|
|
2904
|
+
" </CardContent>",
|
|
2905
|
+
" <CardFooter className=\"flex flex-col items-start gap-3 border-t px-4 !pt-4\">",
|
|
2906
|
+
" <div className=\"flex w-full items-center justify-between px-1\">",
|
|
2907
|
+
" <div className=\"text-sm font-medium\">",
|
|
2908
|
+
" {date?.toLocaleDateString(\"en-US\", {",
|
|
2909
|
+
" day: \"numeric\",",
|
|
2910
|
+
" month: \"long\",",
|
|
2911
|
+
" year: \"numeric\",",
|
|
2912
|
+
" })}",
|
|
2913
|
+
" </div>",
|
|
2914
|
+
" <Button",
|
|
2915
|
+
" variant=\"ghost\"",
|
|
2916
|
+
" size=\"icon\"",
|
|
2917
|
+
" className=\"size-6\"",
|
|
2918
|
+
" title=\"Add Event\"",
|
|
2919
|
+
" >",
|
|
2920
|
+
" <PlusIcon />",
|
|
2921
|
+
" <span className=\"sr-only\">Add Event</span>",
|
|
2922
|
+
" </Button>",
|
|
2923
|
+
" </div>",
|
|
2924
|
+
" <div className=\"flex w-full flex-col gap-2\">",
|
|
2925
|
+
" {events.map((event) => (",
|
|
2926
|
+
" <div",
|
|
2927
|
+
" key={event.title}",
|
|
2928
|
+
" className=\"bg-muted after:bg-primary/70 relative rounded-md p-2 pl-6 text-sm after:absolute after:inset-y-2 after:left-2 after:w-1 after:rounded-full\"",
|
|
2929
|
+
" >",
|
|
2930
|
+
" <div className=\"font-medium\">{event.title}</div>",
|
|
2931
|
+
" <div className=\"text-muted-foreground text-xs\">",
|
|
2932
|
+
" {formatDateRange(new Date(event.from), new Date(event.to))}",
|
|
2933
|
+
" </div>",
|
|
2934
|
+
" </div>",
|
|
2935
|
+
" ))}",
|
|
2936
|
+
" </div>",
|
|
2937
|
+
" </CardFooter>",
|
|
2938
|
+
" </Card>",
|
|
2939
|
+
" )",
|
|
2940
|
+
"}",
|
|
2941
|
+
""
|
|
2942
|
+
]
|
|
2943
|
+
},
|
|
2944
|
+
"save_on_key_down": {
|
|
2945
|
+
"prefix": "save_on_key_down",
|
|
2946
|
+
"body": [
|
|
2947
|
+
"const nav = useNavigate()\r\n\r\n const handleCancel = () => {\r\n nav('/DevStack/extension/snippets/home')\r\n };\r\n\r\n const handleKeyDown = (e) => {\r\n // Save with Ctrl+S or Cmd+S\r\n if ((e.ctrlKey || e.metaKey) && e.key === 's') {\r\n e.preventDefault();\r\n handleSubmit();\r\n }\r\n\r\n // Cancel with Escape\r\n if (e.key === 'Escape') {\r\n handleCancel();\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n document.addEventListener('keydown', handleKeyDown);\r\n return () => document.removeEventListener('keydown', handleKeyDown);\r\n }, [formData]);"
|
|
2948
|
+
],
|
|
2949
|
+
"description": "",
|
|
2950
|
+
"scope": "jsx / tsx"
|
|
2951
|
+
},
|
|
2952
|
+
"A_simple_email_only_login_page": {
|
|
2953
|
+
"prefix": "a_simple_email_only_login_page",
|
|
2954
|
+
"body": [
|
|
2955
|
+
"import { GalleryVerticalEnd } from \"lucide-react\"\n\nimport { cn } from \"~/lib/utils\"\nimport { Button } from \"~/components/ui/button\"\nimport { Input } from \"~/components/ui/input\"\nimport { Label } from \"~/components/ui/label\"\n\nexport function LoginForm({ className, ...props}) {\n return (\n <div className=\"bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10\">\n <div className=\"w-full max-w-sm\">\n <div className={cn(\"flex flex-col gap-6\", className)} {...props}>\n <form>\n <div className=\"flex flex-col gap-6\">\n <div className=\"flex flex-col items-center gap-2\">\n <a\n href=\"#\"\n className=\"flex flex-col items-center gap-2 font-medium\"\n >\n <div className=\"flex size-8 items-center justify-center rounded-md\">\n <GalleryVerticalEnd className=\"size-6\" />\n </div>\n <span className=\"sr-only\">Acme Inc.</span>\n </a>\n <h1 className=\"text-xl font-bold\">Welcome to Acme Inc.</h1>\n <div className=\"text-center text-sm\">\n Don't have an account?{\" \"}\n <a href=\"#\" className=\"underline underline-offset-4\">\n Sign up\n </a>\n </div>\n </div>\n <div className=\"flex flex-col gap-6\">\n <div className=\"grid gap-3\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n />\n </div>\n <Button type=\"submit\" className=\"w-full\">\n Login\n </Button>\n </div>\n <div className=\"after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t\">\n <span className=\"bg-background text-muted-foreground relative z-10 px-2\">\n Or\n </span>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <Button variant=\"outline\" type=\"button\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"\n fill=\"currentColor\"\n />\n </svg>\n Continue with Apple\n </Button>\n <Button variant=\"outline\" type=\"button\" className=\"w-full\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n <path\n d=\"M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z\"\n fill=\"currentColor\"\n />\n </svg>\n Continue with Google\n </Button>\n </div>\n </div>\n </form>\n <div className=\"text-muted-foreground *:[a]:hover:text-primary text-center text-xs text-balance *:[a]:underline *:[a]:underline-offset-4\">\n By clicking continue, you agree to our <a href=\"#\">Terms of Service</a>{\" \"}\n and <a href=\"#\">Privacy Policy</a>.\n </div>\n </div>\n </div>\n </div>\n )\n}"
|
|
2956
|
+
],
|
|
2957
|
+
"description": "shadcn login page",
|
|
2958
|
+
"scope": "jsx / tsx"
|
|
2959
|
+
},
|
|
2960
|
+
"simple_calendar": {
|
|
2961
|
+
"prefix": "simple_calendar",
|
|
2962
|
+
"body": [
|
|
2963
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar01() {\r\n const [date, setDate] = React.useState<Date | undefined>(\r\n new Date(2025, 5, 12)\r\n )\r\n\r\n return (\r\n <Calendar\r\n mode=\"single\"\r\n defaultMonth={date}\r\n selected={date}\r\n onSelect={setDate}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n )\r\n}"
|
|
2964
|
+
],
|
|
2965
|
+
"description": "",
|
|
2966
|
+
"scope": "jsx / tsx"
|
|
2967
|
+
},
|
|
2968
|
+
"multiple_months_with_single_selection": {
|
|
2969
|
+
"prefix": "multiple_months_with_single_selection",
|
|
2970
|
+
"body": [
|
|
2971
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar02() {\r\n const [date, setDate] = React.useState<Date | undefined>(\r\n new Date(2025, 5, 12)\r\n )\r\n\r\n return (\r\n <Calendar\r\n mode=\"single\"\r\n defaultMonth={date}\r\n numberOfMonths={2}\r\n selected={date}\r\n onSelect={setDate}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n )\r\n}"
|
|
2972
|
+
],
|
|
2973
|
+
"description": "",
|
|
2974
|
+
"scope": "jsx / tsx"
|
|
2975
|
+
},
|
|
2976
|
+
"multiple_months_with_multiple_selection": {
|
|
2977
|
+
"prefix": "multiple_months_with_multiple_selection",
|
|
2978
|
+
"body": [
|
|
2979
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar03() {\r\n const [dates, setDates] = React.useState<Date[]>([\r\n new Date(2025, 5, 12),\r\n new Date(2025, 6, 24),\r\n ])\r\n\r\n return (\r\n <Calendar\r\n mode=\"multiple\"\r\n numberOfMonths={2}\r\n defaultMonth={dates[0]}\r\n required\r\n selected={dates}\r\n onSelect={setDates}\r\n max={5}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n )\r\n}"
|
|
2980
|
+
],
|
|
2981
|
+
"description": "",
|
|
2982
|
+
"scope": "jsx / tsx"
|
|
2983
|
+
},
|
|
2984
|
+
"Single month with range selection": {
|
|
2985
|
+
"prefix": "single_month_with_range_selection",
|
|
2986
|
+
"body": [
|
|
2987
|
+
"\"use client\"\n\nimport * as React from \"react\"\nimport { type DateRange } from \"react-day-picker\"\n\nimport { Calendar } from \"@/components/ui/calendar\"\n\nexport function Calendar04() {\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\n from: new Date(2025, 5, 9),\n to: new Date(2025, 5, 26),\n })\n\n return (\n <Calendar\n mode=\"range\"\n defaultMonth={dateRange?.from}\n selected={dateRange}\n onSelect={setDateRange}\n className=\"rounded-lg border shadow-sm\"\n />\n )\n}"
|
|
2988
|
+
],
|
|
2989
|
+
"description": "",
|
|
2990
|
+
"scope": ""
|
|
2991
|
+
},
|
|
2992
|
+
"Multiple months with range selection": {
|
|
2993
|
+
"prefix": "multiple_months_with_range_selection",
|
|
2994
|
+
"body": [
|
|
2995
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar05() {\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 5, 12),\r\n to: new Date(2025, 6, 15),\r\n })\r\n\r\n return (\r\n <Calendar\r\n mode=\"range\"\r\n defaultMonth={dateRange?.from}\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n numberOfMonths={2}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n )\r\n}"
|
|
2996
|
+
],
|
|
2997
|
+
"description": "",
|
|
2998
|
+
"scope": "jsx / tsx"
|
|
2999
|
+
},
|
|
3000
|
+
"range_selection_with_minimum_days": {
|
|
3001
|
+
"prefix": "range_selection_with_minimum_days",
|
|
3002
|
+
"body": [
|
|
3003
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar06() {\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 5, 12),\r\n to: new Date(2025, 5, 26),\r\n })\r\n\r\n return (\r\n <div className=\"flex min-w-0 flex-col gap-2\">\r\n <Calendar\r\n mode=\"range\"\r\n defaultMonth={dateRange?.from}\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n numberOfMonths={1}\r\n min={5}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n <div className=\"text-muted-foreground text-center text-xs\">\r\n A minimum of 5 days is required\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
3004
|
+
],
|
|
3005
|
+
"description": "",
|
|
3006
|
+
"scope": "jsx / tsx"
|
|
3007
|
+
},
|
|
3008
|
+
"range_selection_with_minimum_and_maximum_days": {
|
|
3009
|
+
"prefix": "range_selection_with_minimum_and_maximum_days",
|
|
3010
|
+
"body": [
|
|
3011
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar07() {\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 5, 18),\r\n to: new Date(2025, 6, 7),\r\n })\r\n\r\n return (\r\n <div className=\"flex min-w-0 flex-col gap-2\">\r\n <Calendar\r\n mode=\"range\"\r\n defaultMonth={dateRange?.from}\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n numberOfMonths={2}\r\n min={2}\r\n max={20}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n <div className=\"text-muted-foreground text-center text-xs\">\r\n Your stay must be between 2 and 20 nights\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
3012
|
+
],
|
|
3013
|
+
"description": "",
|
|
3014
|
+
"scope": "jsx / tsx"
|
|
3015
|
+
},
|
|
3016
|
+
"calendar_with_disabled_days": {
|
|
3017
|
+
"prefix": "calendar_with_disabled_days",
|
|
3018
|
+
"body": [
|
|
3019
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar08() {\r\n const [date, setDate] = React.useState<Date | undefined>(\r\n new Date(2025, 5, 12)\r\n )\r\n\r\n return (\r\n <Calendar\r\n mode=\"single\"\r\n defaultMonth={date}\r\n selected={date}\r\n onSelect={setDate}\r\n disabled={{\r\n before: new Date(2025, 5, 12),\r\n }}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n )\r\n}"
|
|
3020
|
+
],
|
|
3021
|
+
"description": "",
|
|
3022
|
+
"scope": "jsx / tsx"
|
|
3023
|
+
},
|
|
3024
|
+
"calendar_with_disabled_weekends": {
|
|
3025
|
+
"prefix": "calendar_with_disabled_weekends",
|
|
3026
|
+
"body": [
|
|
3027
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar09() {\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 5, 17),\r\n to: new Date(2025, 5, 20),\r\n })\r\n\r\n return (\r\n <Calendar\r\n mode=\"range\"\r\n defaultMonth={dateRange?.from}\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n numberOfMonths={2}\r\n disabled={{ dayOfWeek: [0, 6] }}\r\n className=\"rounded-lg border shadow-sm\"\r\n excludeDisabled\r\n />\r\n )\r\n}"
|
|
3028
|
+
],
|
|
3029
|
+
"description": "",
|
|
3030
|
+
"scope": "jsx / tsx"
|
|
3031
|
+
},
|
|
3032
|
+
"today_button": {
|
|
3033
|
+
"prefix": "today_button",
|
|
3034
|
+
"body": [
|
|
3035
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Button } from \"@/components/ui/button\"\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\nimport {\r\n Card,\r\n CardAction,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from \"@/components/ui/card\"\r\n\r\nexport function Calendar10() {\r\n const [date, setDate] = React.useState<Date | undefined>(\r\n new Date(2025, 5, 12)\r\n )\r\n const [month, setMonth] = React.useState<Date | undefined>(new Date())\r\n\r\n return (\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>Appointment</CardTitle>\r\n <CardDescription>Find a date</CardDescription>\r\n <CardAction>\r\n <Button\r\n size=\"sm\"\r\n variant=\"outline\"\r\n onClick={() => {\r\n setMonth(new Date())\r\n setDate(new Date())\r\n }}\r\n >\r\n Today\r\n </Button>\r\n </CardAction>\r\n </CardHeader>\r\n <CardContent>\r\n <Calendar\r\n mode=\"single\"\r\n month={month}\r\n onMonthChange={setMonth}\r\n selected={date}\r\n onSelect={setDate}\r\n className=\"bg-transparent p-0\"\r\n />\r\n </CardContent>\r\n </Card>\r\n )\r\n}"
|
|
3036
|
+
],
|
|
3037
|
+
"description": "",
|
|
3038
|
+
"scope": "jsx / tsx"
|
|
3039
|
+
},
|
|
3040
|
+
"start_and_end_of_month": {
|
|
3041
|
+
"prefix": "start_and_end_of_month",
|
|
3042
|
+
"body": [
|
|
3043
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\n\r\nexport function Calendar11() {\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 5, 17),\r\n to: new Date(2025, 5, 20),\r\n })\r\n\r\n return (\r\n <div className=\"flex min-w-0 flex-col gap-2\">\r\n <Calendar\r\n mode=\"range\"\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n numberOfMonths={2}\r\n startMonth={new Date(2025, 5, 1)}\r\n endMonth={new Date(2025, 6, 31)}\r\n disableNavigation\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n <div className=\"text-muted-foreground text-center text-xs\">\r\n We are open in June and July only.\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
3044
|
+
],
|
|
3045
|
+
"description": "",
|
|
3046
|
+
"scope": "jsx / tsx"
|
|
3047
|
+
},
|
|
3048
|
+
"localized_calendar": {
|
|
3049
|
+
"prefix": "localized_calendar",
|
|
3050
|
+
"body": [
|
|
3051
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type DateRange } from \"react-day-picker\"\r\nimport { enUS, es } from \"react-day-picker/locale\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\nimport {\r\n Card,\r\n CardAction,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from \"@/components/ui/card\"\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from \"@/components/ui/select\"\r\n\r\nconst localizedStrings = {\r\n en: {\r\n title: \"Book an appointment\",\r\n description: \"Select the dates for your appointment\",\r\n },\r\n es: {\r\n title: \"Reserva una cita\",\r\n description: \"Selecciona las fechas para tu cita\",\r\n },\r\n} as const\r\n\r\nexport function Calendar12() {\r\n const [locale, setLocale] =\r\n React.useState<keyof typeof localizedStrings>(\"es\")\r\n const [dateRange, setDateRange] = React.useState<DateRange | undefined>({\r\n from: new Date(2025, 8, 9),\r\n to: new Date(2025, 8, 17),\r\n })\r\n\r\n return (\r\n <Card>\r\n <CardHeader className=\"border-b\">\r\n <CardTitle>{localizedStrings[locale].title}</CardTitle>\r\n <CardDescription>\r\n {localizedStrings[locale].description}\r\n </CardDescription>\r\n <CardAction>\r\n <Select\r\n value={locale}\r\n onValueChange={(value) =>\r\n setLocale(value as keyof typeof localizedStrings)\r\n }\r\n >\r\n <SelectTrigger className=\"w-[100px]\">\r\n <SelectValue placeholder=\"Language\" />\r\n </SelectTrigger>\r\n <SelectContent align=\"end\">\r\n <SelectItem value=\"es\">Español</SelectItem>\r\n <SelectItem value=\"en\">English</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </CardAction>\r\n </CardHeader>\r\n <CardContent>\r\n <Calendar\r\n mode=\"range\"\r\n selected={dateRange}\r\n onSelect={setDateRange}\r\n defaultMonth={dateRange?.from}\r\n numberOfMonths={2}\r\n locale={locale === \"es\" ? es : enUS}\r\n className=\"bg-transparent p-0\"\r\n buttonVariant=\"outline\"\r\n />\r\n </CardContent>\r\n </Card>\r\n )\r\n}"
|
|
3052
|
+
],
|
|
3053
|
+
"description": "",
|
|
3054
|
+
"scope": "jsx / tsx"
|
|
3055
|
+
},
|
|
3056
|
+
"with_month_and_year_dropdown": {
|
|
3057
|
+
"prefix": "with_month_and_year_dropdown",
|
|
3058
|
+
"body": [
|
|
3059
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Calendar } from \"@/components/ui/calendar\"\r\nimport { Label } from \"@/components/ui/label\"\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from \"@/components/ui/select\"\r\n\r\nexport function Calendar13() {\r\n const [dropdown, setDropdown] =\r\n React.useState<React.ComponentProps<typeof Calendar>[\"captionLayout\"]>(\r\n \"dropdown\"\r\n )\r\n const [date, setDate] = React.useState<Date | undefined>(\r\n new Date(2025, 5, 12)\r\n )\r\n\r\n return (\r\n <div className=\"flex flex-col gap-4\">\r\n <Calendar\r\n mode=\"single\"\r\n defaultMonth={date}\r\n selected={date}\r\n onSelect={setDate}\r\n captionLayout={dropdown}\r\n className=\"rounded-lg border shadow-sm\"\r\n />\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"dropdown\" className=\"px-1\">\r\n Dropdown\r\n </Label>\r\n <Select\r\n value={dropdown}\r\n onValueChange={(value) =>\r\n setDropdown(\r\n value as React.ComponentProps<typeof Calendar>[\"captionLayout\"]\r\n )\r\n }\r\n >\r\n <SelectTrigger\r\n id=\"dropdown\"\r\n size=\"sm\"\r\n className=\"bg-background w-full\"\r\n >\r\n <SelectValue placeholder=\"Dropdown\" />\r\n </SelectTrigger>\r\n <SelectContent align=\"center\">\r\n <SelectItem value=\"dropdown\">Month and Year</SelectItem>\r\n <SelectItem value=\"dropdown-months\">Month Only</SelectItem>\r\n <SelectItem value=\"dropdown-years\">Year Only</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
3060
|
+
],
|
|
3061
|
+
"description": "",
|
|
3062
|
+
"scope": "jsx / tsx"
|
|
3063
|
+
},
|
|
3064
|
+
"one_dashboard_page_tsx": {
|
|
3065
|
+
"prefix": "one/dashboard/page.tsx",
|
|
3066
|
+
"body": [
|
|
3067
|
+
"import { AppSidebar } from \"@/components/app-sidebar\"\r\nimport { ChartAreaInteractive } from \"@/components/chart-area-interactive\"\r\nimport { DataTable } from \"@/components/data-table\"\r\nimport { SectionCards } from \"@/components/section-cards\"\r\nimport { SiteHeader } from \"@/components/site-header\"\r\nimport {\r\n SidebarInset,\r\n SidebarProvider,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nimport data from \"./data.json\"\r\n\r\nexport default function Page() {\r\n return (\r\n <SidebarProvider\r\n style={\r\n {\r\n \"--sidebar-width\": \"calc(var(--spacing) * 72)\",\r\n \"--header-height\": \"calc(var(--spacing) * 12)\",\r\n } as React.CSSProperties\r\n }\r\n >\r\n <AppSidebar variant=\"inset\" />\r\n <SidebarInset>\r\n <SiteHeader />\r\n <div className=\"flex flex-1 flex-col\">\r\n <div className=\"@container/main flex flex-1 flex-col gap-2\">\r\n <div className=\"flex flex-col gap-4 py-4 md:gap-6 md:py-6\">\r\n <SectionCards />\r\n <div className=\"px-4 lg:px-6\">\r\n <ChartAreaInteractive />\r\n </div>\r\n <DataTable data={data} />\r\n </div>\r\n </div>\r\n </div>\r\n </SidebarInset>\r\n </SidebarProvider>\r\n )\r\n}"
|
|
3068
|
+
],
|
|
3069
|
+
"description": "",
|
|
3070
|
+
"scope": "jsx / tsx"
|
|
3071
|
+
},
|
|
3072
|
+
"one_dashboard_data_json": {
|
|
3073
|
+
"prefix": "one_dashboard_data_json",
|
|
3074
|
+
"body": [
|
|
3075
|
+
"[\r\n {\r\n \"id\": 1,\r\n \"header\": \"Cover page\",\r\n \"type\": \"Cover page\",\r\n \"status\": \"In Process\",\r\n \"target\": \"18\",\r\n \"limit\": \"5\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 2,\r\n \"header\": \"Table of contents\",\r\n \"type\": \"Table of contents\",\r\n \"status\": \"Done\",\r\n \"target\": \"29\",\r\n \"limit\": \"24\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 3,\r\n \"header\": \"Executive summary\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"10\",\r\n \"limit\": \"13\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 4,\r\n \"header\": \"Technical approach\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"27\",\r\n \"limit\": \"23\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 5,\r\n \"header\": \"Design\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"In Process\",\r\n \"target\": \"2\",\r\n \"limit\": \"16\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 6,\r\n \"header\": \"Capabilities\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"In Process\",\r\n \"target\": \"20\",\r\n \"limit\": \"8\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 7,\r\n \"header\": \"Integration with existing systems\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"In Process\",\r\n \"target\": \"19\",\r\n \"limit\": \"21\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 8,\r\n \"header\": \"Innovation and Advantages\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"25\",\r\n \"limit\": \"26\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 9,\r\n \"header\": \"Overview of EMR's Innovative Solutions\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"7\",\r\n \"limit\": \"23\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 10,\r\n \"header\": \"Advanced Algorithms and Machine Learning\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"30\",\r\n \"limit\": \"28\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 11,\r\n \"header\": \"Adaptive Communication Protocols\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"9\",\r\n \"limit\": \"31\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 12,\r\n \"header\": \"Advantages Over Current Technologies\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"12\",\r\n \"limit\": \"0\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 13,\r\n \"header\": \"Past Performance\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"22\",\r\n \"limit\": \"33\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 14,\r\n \"header\": \"Customer Feedback and Satisfaction Levels\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"15\",\r\n \"limit\": \"34\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 15,\r\n \"header\": \"Implementation Challenges and Solutions\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"3\",\r\n \"limit\": \"35\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 16,\r\n \"header\": \"Security Measures and Data Protection Policies\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"In Process\",\r\n \"target\": \"6\",\r\n \"limit\": \"36\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 17,\r\n \"header\": \"Scalability and Future Proofing\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"4\",\r\n \"limit\": \"37\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 18,\r\n \"header\": \"Cost-Benefit Analysis\",\r\n \"type\": \"Plain language\",\r\n \"status\": \"Done\",\r\n \"target\": \"14\",\r\n \"limit\": \"38\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 19,\r\n \"header\": \"User Training and Onboarding Experience\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"17\",\r\n \"limit\": \"39\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 20,\r\n \"header\": \"Future Development Roadmap\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"11\",\r\n \"limit\": \"40\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 21,\r\n \"header\": \"System Architecture Overview\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"24\",\r\n \"limit\": \"18\",\r\n \"reviewer\": \"Maya Johnson\"\r\n },\r\n {\r\n \"id\": 22,\r\n \"header\": \"Risk Management Plan\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"15\",\r\n \"limit\": \"22\",\r\n \"reviewer\": \"Carlos Rodriguez\"\r\n },\r\n {\r\n \"id\": 23,\r\n \"header\": \"Compliance Documentation\",\r\n \"type\": \"Legal\",\r\n \"status\": \"In Process\",\r\n \"target\": \"31\",\r\n \"limit\": \"27\",\r\n \"reviewer\": \"Sarah Chen\"\r\n },\r\n {\r\n \"id\": 24,\r\n \"header\": \"API Documentation\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"8\",\r\n \"limit\": \"12\",\r\n \"reviewer\": \"Raj Patel\"\r\n },\r\n {\r\n \"id\": 25,\r\n \"header\": \"User Interface Mockups\",\r\n \"type\": \"Visual\",\r\n \"status\": \"In Process\",\r\n \"target\": \"19\",\r\n \"limit\": \"25\",\r\n \"reviewer\": \"Leila Ahmadi\"\r\n },\r\n {\r\n \"id\": 26,\r\n \"header\": \"Database Schema\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"22\",\r\n \"limit\": \"20\",\r\n \"reviewer\": \"Thomas Wilson\"\r\n },\r\n {\r\n \"id\": 27,\r\n \"header\": \"Testing Methodology\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"17\",\r\n \"limit\": \"14\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 28,\r\n \"header\": \"Deployment Strategy\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"26\",\r\n \"limit\": \"30\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 29,\r\n \"header\": \"Budget Breakdown\",\r\n \"type\": \"Financial\",\r\n \"status\": \"In Process\",\r\n \"target\": \"13\",\r\n \"limit\": \"16\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 30,\r\n \"header\": \"Market Analysis\",\r\n \"type\": \"Research\",\r\n \"status\": \"Done\",\r\n \"target\": \"29\",\r\n \"limit\": \"32\",\r\n \"reviewer\": \"Sophia Martinez\"\r\n },\r\n {\r\n \"id\": 31,\r\n \"header\": \"Competitor Comparison\",\r\n \"type\": \"Research\",\r\n \"status\": \"In Process\",\r\n \"target\": \"21\",\r\n \"limit\": \"19\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 32,\r\n \"header\": \"Maintenance Plan\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"16\",\r\n \"limit\": \"23\",\r\n \"reviewer\": \"Alex Thompson\"\r\n },\r\n {\r\n \"id\": 33,\r\n \"header\": \"User Personas\",\r\n \"type\": \"Research\",\r\n \"status\": \"In Process\",\r\n \"target\": \"27\",\r\n \"limit\": \"24\",\r\n \"reviewer\": \"Nina Patel\"\r\n },\r\n {\r\n \"id\": 34,\r\n \"header\": \"Accessibility Compliance\",\r\n \"type\": \"Legal\",\r\n \"status\": \"Done\",\r\n \"target\": \"18\",\r\n \"limit\": \"21\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 35,\r\n \"header\": \"Performance Metrics\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"23\",\r\n \"limit\": \"26\",\r\n \"reviewer\": \"David Kim\"\r\n },\r\n {\r\n \"id\": 36,\r\n \"header\": \"Disaster Recovery Plan\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"14\",\r\n \"limit\": \"17\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 37,\r\n \"header\": \"Third-party Integrations\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"25\",\r\n \"limit\": \"28\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 38,\r\n \"header\": \"User Feedback Summary\",\r\n \"type\": \"Research\",\r\n \"status\": \"Done\",\r\n \"target\": \"20\",\r\n \"limit\": \"15\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 39,\r\n \"header\": \"Localization Strategy\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"In Process\",\r\n \"target\": \"12\",\r\n \"limit\": \"19\",\r\n \"reviewer\": \"Maria Garcia\"\r\n },\r\n {\r\n \"id\": 40,\r\n \"header\": \"Mobile Compatibility\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"28\",\r\n \"limit\": \"31\",\r\n \"reviewer\": \"James Wilson\"\r\n },\r\n {\r\n \"id\": 41,\r\n \"header\": \"Data Migration Plan\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"19\",\r\n \"limit\": \"22\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 42,\r\n \"header\": \"Quality Assurance Protocols\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"30\",\r\n \"limit\": \"33\",\r\n \"reviewer\": \"Priya Singh\"\r\n },\r\n {\r\n \"id\": 43,\r\n \"header\": \"Stakeholder Analysis\",\r\n \"type\": \"Research\",\r\n \"status\": \"In Process\",\r\n \"target\": \"11\",\r\n \"limit\": \"14\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 44,\r\n \"header\": \"Environmental Impact Assessment\",\r\n \"type\": \"Research\",\r\n \"status\": \"Done\",\r\n \"target\": \"24\",\r\n \"limit\": \"27\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 45,\r\n \"header\": \"Intellectual Property Rights\",\r\n \"type\": \"Legal\",\r\n \"status\": \"In Process\",\r\n \"target\": \"17\",\r\n \"limit\": \"20\",\r\n \"reviewer\": \"Sarah Johnson\"\r\n },\r\n {\r\n \"id\": 46,\r\n \"header\": \"Customer Support Framework\",\r\n \"type\": \"Narrative\",\r\n \"status\": \"Done\",\r\n \"target\": \"22\",\r\n \"limit\": \"25\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 47,\r\n \"header\": \"Version Control Strategy\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"15\",\r\n \"limit\": \"18\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 48,\r\n \"header\": \"Continuous Integration Pipeline\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"26\",\r\n \"limit\": \"29\",\r\n \"reviewer\": \"Michael Chen\"\r\n },\r\n {\r\n \"id\": 49,\r\n \"header\": \"Regulatory Compliance\",\r\n \"type\": \"Legal\",\r\n \"status\": \"In Process\",\r\n \"target\": \"13\",\r\n \"limit\": \"16\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 50,\r\n \"header\": \"User Authentication System\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"28\",\r\n \"limit\": \"31\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 51,\r\n \"header\": \"Data Analytics Framework\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"21\",\r\n \"limit\": \"24\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 52,\r\n \"header\": \"Cloud Infrastructure\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"16\",\r\n \"limit\": \"19\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 53,\r\n \"header\": \"Network Security Measures\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"29\",\r\n \"limit\": \"32\",\r\n \"reviewer\": \"Lisa Wong\"\r\n },\r\n {\r\n \"id\": 54,\r\n \"header\": \"Project Timeline\",\r\n \"type\": \"Planning\",\r\n \"status\": \"Done\",\r\n \"target\": \"14\",\r\n \"limit\": \"17\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 55,\r\n \"header\": \"Resource Allocation\",\r\n \"type\": \"Planning\",\r\n \"status\": \"In Process\",\r\n \"target\": \"27\",\r\n \"limit\": \"30\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 56,\r\n \"header\": \"Team Structure and Roles\",\r\n \"type\": \"Planning\",\r\n \"status\": \"Done\",\r\n \"target\": \"20\",\r\n \"limit\": \"23\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 57,\r\n \"header\": \"Communication Protocols\",\r\n \"type\": \"Planning\",\r\n \"status\": \"In Process\",\r\n \"target\": \"15\",\r\n \"limit\": \"18\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 58,\r\n \"header\": \"Success Metrics\",\r\n \"type\": \"Planning\",\r\n \"status\": \"Done\",\r\n \"target\": \"30\",\r\n \"limit\": \"33\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 59,\r\n \"header\": \"Internationalization Support\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"23\",\r\n \"limit\": \"26\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 60,\r\n \"header\": \"Backup and Recovery Procedures\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"18\",\r\n \"limit\": \"21\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 61,\r\n \"header\": \"Monitoring and Alerting System\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"25\",\r\n \"limit\": \"28\",\r\n \"reviewer\": \"Daniel Park\"\r\n },\r\n {\r\n \"id\": 62,\r\n \"header\": \"Code Review Guidelines\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"12\",\r\n \"limit\": \"15\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 63,\r\n \"header\": \"Documentation Standards\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"In Process\",\r\n \"target\": \"27\",\r\n \"limit\": \"30\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 64,\r\n \"header\": \"Release Management Process\",\r\n \"type\": \"Planning\",\r\n \"status\": \"Done\",\r\n \"target\": \"22\",\r\n \"limit\": \"25\",\r\n \"reviewer\": \"Assign reviewer\"\r\n },\r\n {\r\n \"id\": 65,\r\n \"header\": \"Feature Prioritization Matrix\",\r\n \"type\": \"Planning\",\r\n \"status\": \"In Process\",\r\n \"target\": \"19\",\r\n \"limit\": \"22\",\r\n \"reviewer\": \"Emma Davis\"\r\n },\r\n {\r\n \"id\": 66,\r\n \"header\": \"Technical Debt Assessment\",\r\n \"type\": \"Technical content\",\r\n \"status\": \"Done\",\r\n \"target\": \"24\",\r\n \"limit\": \"27\",\r\n \"reviewer\": \"Eddie Lake\"\r\n },\r\n {\r\n \"id\": 67,\r\n \"header\": \"Capacity Planning\",\r\n \"type\": \"Planning\",\r\n \"status\": \"In Process\",\r\n \"target\": \"21\",\r\n \"limit\": \"24\",\r\n \"reviewer\": \"Jamik Tashpulatov\"\r\n },\r\n {\r\n \"id\": 68,\r\n \"header\": \"Service Level Agreements\",\r\n \"type\": \"Legal\",\r\n \"status\": \"Done\",\r\n \"target\": \"26\",\r\n \"limit\": \"29\",\r\n \"reviewer\": \"Assign reviewer\"\r\n }\r\n]"
|
|
3076
|
+
],
|
|
3077
|
+
"description": "",
|
|
3078
|
+
"scope": "jsx / tsx"
|
|
3079
|
+
},
|
|
3080
|
+
"one_components_app-sidebar_tsx": {
|
|
3081
|
+
"prefix": "one_components_app-sidebar_tsx",
|
|
3082
|
+
"body": [
|
|
3083
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport {\r\n IconCamera,\r\n IconChartBar,\r\n IconDashboard,\r\n IconDatabase,\r\n IconFileAi,\r\n IconFileDescription,\r\n IconFileWord,\r\n IconFolder,\r\n IconHelp,\r\n IconInnerShadowTop,\r\n IconListDetails,\r\n IconReport,\r\n IconSearch,\r\n IconSettings,\r\n IconUsers,\r\n} from \"@tabler/icons-react\"\r\n\r\nimport { NavDocuments } from \"@/components/nav-documents\"\r\nimport { NavMain } from \"@/components/nav-main\"\r\nimport { NavSecondary } from \"@/components/nav-secondary\"\r\nimport { NavUser } from \"@/components/nav-user\"\r\nimport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarFooter,\r\n SidebarHeader,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nconst data = {\r\n user: {\r\n name: \"shadcn\",\r\n email: \"m@example.com\",\r\n avatar: \"/avatars/shadcn.jpg\",\r\n },\r\n navMain: [\r\n {\r\n title: \"Dashboard\",\r\n url: \"#\",\r\n icon: IconDashboard,\r\n },\r\n {\r\n title: \"Lifecycle\",\r\n url: \"#\",\r\n icon: IconListDetails,\r\n },\r\n {\r\n title: \"Analytics\",\r\n url: \"#\",\r\n icon: IconChartBar,\r\n },\r\n {\r\n title: \"Projects\",\r\n url: \"#\",\r\n icon: IconFolder,\r\n },\r\n {\r\n title: \"Team\",\r\n url: \"#\",\r\n icon: IconUsers,\r\n },\r\n ],\r\n navClouds: [\r\n {\r\n title: \"Capture\",\r\n icon: IconCamera,\r\n isActive: true,\r\n url: \"#\",\r\n items: [\r\n {\r\n title: \"Active Proposals\",\r\n url: \"#\",\r\n },\r\n {\r\n title: \"Archived\",\r\n url: \"#\",\r\n },\r\n ],\r\n },\r\n {\r\n title: \"Proposal\",\r\n icon: IconFileDescription,\r\n url: \"#\",\r\n items: [\r\n {\r\n title: \"Active Proposals\",\r\n url: \"#\",\r\n },\r\n {\r\n title: \"Archived\",\r\n url: \"#\",\r\n },\r\n ],\r\n },\r\n {\r\n title: \"Prompts\",\r\n icon: IconFileAi,\r\n url: \"#\",\r\n items: [\r\n {\r\n title: \"Active Proposals\",\r\n url: \"#\",\r\n },\r\n {\r\n title: \"Archived\",\r\n url: \"#\",\r\n },\r\n ],\r\n },\r\n ],\r\n navSecondary: [\r\n {\r\n title: \"Settings\",\r\n url: \"#\",\r\n icon: IconSettings,\r\n },\r\n {\r\n title: \"Get Help\",\r\n url: \"#\",\r\n icon: IconHelp,\r\n },\r\n {\r\n title: \"Search\",\r\n url: \"#\",\r\n icon: IconSearch,\r\n },\r\n ],\r\n documents: [\r\n {\r\n name: \"Data Library\",\r\n url: \"#\",\r\n icon: IconDatabase,\r\n },\r\n {\r\n name: \"Reports\",\r\n url: \"#\",\r\n icon: IconReport,\r\n },\r\n {\r\n name: \"Word Assistant\",\r\n url: \"#\",\r\n icon: IconFileWord,\r\n },\r\n ],\r\n}\r\n\r\nexport function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {\r\n return (\r\n <Sidebar collapsible=\"offcanvas\" {...props}>\r\n <SidebarHeader>\r\n <SidebarMenu>\r\n <SidebarMenuItem>\r\n <SidebarMenuButton\r\n asChild\r\n className=\"data-[slot=sidebar-menu-button]:!p-1.5\"\r\n >\r\n <a href=\"#\">\r\n <IconInnerShadowTop className=\"!size-5\" />\r\n <span className=\"text-base font-semibold\">Acme Inc.</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n </SidebarHeader>\r\n <SidebarContent>\r\n <NavMain items={data.navMain} />\r\n <NavDocuments items={data.documents} />\r\n <NavSecondary items={data.navSecondary} className=\"mt-auto\" />\r\n </SidebarContent>\r\n <SidebarFooter>\r\n <NavUser user={data.user} />\r\n </SidebarFooter>\r\n </Sidebar>\r\n )\r\n}"
|
|
3084
|
+
],
|
|
3085
|
+
"description": "",
|
|
3086
|
+
"scope": "jsx / tsx"
|
|
3087
|
+
},
|
|
3088
|
+
"one_components_chart-area-interactive_tsx": {
|
|
3089
|
+
"prefix": "one_components_chart-area-interactive_tsx",
|
|
3090
|
+
"body": [
|
|
3091
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Area, AreaChart, CartesianGrid, XAxis } from \"recharts\"\r\n\r\nimport { useIsMobile } from \"@/hooks/use-mobile\"\r\nimport {\r\n Card,\r\n CardAction,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from \"@/components/ui/card\"\r\nimport {\r\n ChartConfig,\r\n ChartContainer,\r\n ChartTooltip,\r\n ChartTooltipContent,\r\n} from \"@/components/ui/chart\"\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from \"@/components/ui/select\"\r\nimport {\r\n ToggleGroup,\r\n ToggleGroupItem,\r\n} from \"@/components/ui/toggle-group\"\r\n\r\nexport const description = \"An interactive area chart\"\r\n\r\nconst chartData = [\r\n { date: \"2024-04-01\", desktop: 222, mobile: 150 },\r\n { date: \"2024-04-02\", desktop: 97, mobile: 180 },\r\n { date: \"2024-04-03\", desktop: 167, mobile: 120 },\r\n { date: \"2024-04-04\", desktop: 242, mobile: 260 },\r\n { date: \"2024-04-05\", desktop: 373, mobile: 290 },\r\n { date: \"2024-04-06\", desktop: 301, mobile: 340 },\r\n { date: \"2024-04-07\", desktop: 245, mobile: 180 },\r\n { date: \"2024-04-08\", desktop: 409, mobile: 320 },\r\n { date: \"2024-04-09\", desktop: 59, mobile: 110 },\r\n { date: \"2024-04-10\", desktop: 261, mobile: 190 },\r\n { date: \"2024-04-11\", desktop: 327, mobile: 350 },\r\n { date: \"2024-04-12\", desktop: 292, mobile: 210 },\r\n { date: \"2024-04-13\", desktop: 342, mobile: 380 },\r\n { date: \"2024-04-14\", desktop: 137, mobile: 220 },\r\n { date: \"2024-04-15\", desktop: 120, mobile: 170 },\r\n { date: \"2024-04-16\", desktop: 138, mobile: 190 },\r\n { date: \"2024-04-17\", desktop: 446, mobile: 360 },\r\n { date: \"2024-04-18\", desktop: 364, mobile: 410 },\r\n { date: \"2024-04-19\", desktop: 243, mobile: 180 },\r\n { date: \"2024-04-20\", desktop: 89, mobile: 150 },\r\n { date: \"2024-04-21\", desktop: 137, mobile: 200 },\r\n { date: \"2024-04-22\", desktop: 224, mobile: 170 },\r\n { date: \"2024-04-23\", desktop: 138, mobile: 230 },\r\n { date: \"2024-04-24\", desktop: 387, mobile: 290 },\r\n { date: \"2024-04-25\", desktop: 215, mobile: 250 },\r\n { date: \"2024-04-26\", desktop: 75, mobile: 130 },\r\n { date: \"2024-04-27\", desktop: 383, mobile: 420 },\r\n { date: \"2024-04-28\", desktop: 122, mobile: 180 },\r\n { date: \"2024-04-29\", desktop: 315, mobile: 240 },\r\n { date: \"2024-04-30\", desktop: 454, mobile: 380 },\r\n { date: \"2024-05-01\", desktop: 165, mobile: 220 },\r\n { date: \"2024-05-02\", desktop: 293, mobile: 310 },\r\n { date: \"2024-05-03\", desktop: 247, mobile: 190 },\r\n { date: \"2024-05-04\", desktop: 385, mobile: 420 },\r\n { date: \"2024-05-05\", desktop: 481, mobile: 390 },\r\n { date: \"2024-05-06\", desktop: 498, mobile: 520 },\r\n { date: \"2024-05-07\", desktop: 388, mobile: 300 },\r\n { date: \"2024-05-08\", desktop: 149, mobile: 210 },\r\n { date: \"2024-05-09\", desktop: 227, mobile: 180 },\r\n { date: \"2024-05-10\", desktop: 293, mobile: 330 },\r\n { date: \"2024-05-11\", desktop: 335, mobile: 270 },\r\n { date: \"2024-05-12\", desktop: 197, mobile: 240 },\r\n { date: \"2024-05-13\", desktop: 197, mobile: 160 },\r\n { date: \"2024-05-14\", desktop: 448, mobile: 490 },\r\n { date: \"2024-05-15\", desktop: 473, mobile: 380 },\r\n { date: \"2024-05-16\", desktop: 338, mobile: 400 },\r\n { date: \"2024-05-17\", desktop: 499, mobile: 420 },\r\n { date: \"2024-05-18\", desktop: 315, mobile: 350 },\r\n { date: \"2024-05-19\", desktop: 235, mobile: 180 },\r\n { date: \"2024-05-20\", desktop: 177, mobile: 230 },\r\n { date: \"2024-05-21\", desktop: 82, mobile: 140 },\r\n { date: \"2024-05-22\", desktop: 81, mobile: 120 },\r\n { date: \"2024-05-23\", desktop: 252, mobile: 290 },\r\n { date: \"2024-05-24\", desktop: 294, mobile: 220 },\r\n { date: \"2024-05-25\", desktop: 201, mobile: 250 },\r\n { date: \"2024-05-26\", desktop: 213, mobile: 170 },\r\n { date: \"2024-05-27\", desktop: 420, mobile: 460 },\r\n { date: \"2024-05-28\", desktop: 233, mobile: 190 },\r\n { date: \"2024-05-29\", desktop: 78, mobile: 130 },\r\n { date: \"2024-05-30\", desktop: 340, mobile: 280 },\r\n { date: \"2024-05-31\", desktop: 178, mobile: 230 },\r\n { date: \"2024-06-01\", desktop: 178, mobile: 200 },\r\n { date: \"2024-06-02\", desktop: 470, mobile: 410 },\r\n { date: \"2024-06-03\", desktop: 103, mobile: 160 },\r\n { date: \"2024-06-04\", desktop: 439, mobile: 380 },\r\n { date: \"2024-06-05\", desktop: 88, mobile: 140 },\r\n { date: \"2024-06-06\", desktop: 294, mobile: 250 },\r\n { date: \"2024-06-07\", desktop: 323, mobile: 370 },\r\n { date: \"2024-06-08\", desktop: 385, mobile: 320 },\r\n { date: \"2024-06-09\", desktop: 438, mobile: 480 },\r\n { date: \"2024-06-10\", desktop: 155, mobile: 200 },\r\n { date: \"2024-06-11\", desktop: 92, mobile: 150 },\r\n { date: \"2024-06-12\", desktop: 492, mobile: 420 },\r\n { date: \"2024-06-13\", desktop: 81, mobile: 130 },\r\n { date: \"2024-06-14\", desktop: 426, mobile: 380 },\r\n { date: \"2024-06-15\", desktop: 307, mobile: 350 },\r\n { date: \"2024-06-16\", desktop: 371, mobile: 310 },\r\n { date: \"2024-06-17\", desktop: 475, mobile: 520 },\r\n { date: \"2024-06-18\", desktop: 107, mobile: 170 },\r\n { date: \"2024-06-19\", desktop: 341, mobile: 290 },\r\n { date: \"2024-06-20\", desktop: 408, mobile: 450 },\r\n { date: \"2024-06-21\", desktop: 169, mobile: 210 },\r\n { date: \"2024-06-22\", desktop: 317, mobile: 270 },\r\n { date: \"2024-06-23\", desktop: 480, mobile: 530 },\r\n { date: \"2024-06-24\", desktop: 132, mobile: 180 },\r\n { date: \"2024-06-25\", desktop: 141, mobile: 190 },\r\n { date: \"2024-06-26\", desktop: 434, mobile: 380 },\r\n { date: \"2024-06-27\", desktop: 448, mobile: 490 },\r\n { date: \"2024-06-28\", desktop: 149, mobile: 200 },\r\n { date: \"2024-06-29\", desktop: 103, mobile: 160 },\r\n { date: \"2024-06-30\", desktop: 446, mobile: 400 },\r\n]\r\n\r\nconst chartConfig = {\r\n visitors: {\r\n label: \"Visitors\",\r\n },\r\n desktop: {\r\n label: \"Desktop\",\r\n color: \"var(--primary)\",\r\n },\r\n mobile: {\r\n label: \"Mobile\",\r\n color: \"var(--primary)\",\r\n },\r\n} satisfies ChartConfig\r\n\r\nexport function ChartAreaInteractive() {\r\n const isMobile = useIsMobile()\r\n const [timeRange, setTimeRange] = React.useState(\"90d\")\r\n\r\n React.useEffect(() => {\r\n if (isMobile) {\r\n setTimeRange(\"7d\")\r\n }\r\n }, [isMobile])\r\n\r\n const filteredData = chartData.filter((item) => {\r\n const date = new Date(item.date)\r\n const referenceDate = new Date(\"2024-06-30\")\r\n let daysToSubtract = 90\r\n if (timeRange === \"30d\") {\r\n daysToSubtract = 30\r\n } else if (timeRange === \"7d\") {\r\n daysToSubtract = 7\r\n }\r\n const startDate = new Date(referenceDate)\r\n startDate.setDate(startDate.getDate() - daysToSubtract)\r\n return date >= startDate\r\n })\r\n\r\n return (\r\n <Card className=\"@container/card\">\r\n <CardHeader>\r\n <CardTitle>Total Visitors</CardTitle>\r\n <CardDescription>\r\n <span className=\"hidden @[540px]/card:block\">\r\n Total for the last 3 months\r\n </span>\r\n <span className=\"@[540px]/card:hidden\">Last 3 months</span>\r\n </CardDescription>\r\n <CardAction>\r\n <ToggleGroup\r\n type=\"single\"\r\n value={timeRange}\r\n onValueChange={setTimeRange}\r\n variant=\"outline\"\r\n className=\"hidden *:data-[slot=toggle-group-item]:!px-4 @[767px]/card:flex\"\r\n >\r\n <ToggleGroupItem value=\"90d\">Last 3 months</ToggleGroupItem>\r\n <ToggleGroupItem value=\"30d\">Last 30 days</ToggleGroupItem>\r\n <ToggleGroupItem value=\"7d\">Last 7 days</ToggleGroupItem>\r\n </ToggleGroup>\r\n <Select value={timeRange} onValueChange={setTimeRange}>\r\n <SelectTrigger\r\n className=\"flex w-40 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate @[767px]/card:hidden\"\r\n size=\"sm\"\r\n aria-label=\"Select a value\"\r\n >\r\n <SelectValue placeholder=\"Last 3 months\" />\r\n </SelectTrigger>\r\n <SelectContent className=\"rounded-xl\">\r\n <SelectItem value=\"90d\" className=\"rounded-lg\">\r\n Last 3 months\r\n </SelectItem>\r\n <SelectItem value=\"30d\" className=\"rounded-lg\">\r\n Last 30 days\r\n </SelectItem>\r\n <SelectItem value=\"7d\" className=\"rounded-lg\">\r\n Last 7 days\r\n </SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </CardAction>\r\n </CardHeader>\r\n <CardContent className=\"px-2 pt-4 sm:px-6 sm:pt-6\">\r\n <ChartContainer\r\n config={chartConfig}\r\n className=\"aspect-auto h-[250px] w-full\"\r\n >\r\n <AreaChart data={filteredData}>\r\n <defs>\r\n <linearGradient id=\"fillDesktop\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\r\n <stop\r\n offset=\"5%\"\r\n stopColor=\"var(--color-desktop)\"\r\n stopOpacity={1.0}\r\n />\r\n <stop\r\n offset=\"95%\"\r\n stopColor=\"var(--color-desktop)\"\r\n stopOpacity={0.1}\r\n />\r\n </linearGradient>\r\n <linearGradient id=\"fillMobile\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\r\n <stop\r\n offset=\"5%\"\r\n stopColor=\"var(--color-mobile)\"\r\n stopOpacity={0.8}\r\n />\r\n <stop\r\n offset=\"95%\"\r\n stopColor=\"var(--color-mobile)\"\r\n stopOpacity={0.1}\r\n />\r\n </linearGradient>\r\n </defs>\r\n <CartesianGrid vertical={false} />\r\n <XAxis\r\n dataKey=\"date\"\r\n tickLine={false}\r\n axisLine={false}\r\n tickMargin={8}\r\n minTickGap={32}\r\n tickFormatter={(value) => {\r\n const date = new Date(value)\r\n return date.toLocaleDateString(\"en-US\", {\r\n month: \"short\",\r\n day: \"numeric\",\r\n })\r\n }}\r\n />\r\n <ChartTooltip\r\n cursor={false}\r\n content={\r\n <ChartTooltipContent\r\n labelFormatter={(value) => {\r\n return new Date(value).toLocaleDateString(\"en-US\", {\r\n month: \"short\",\r\n day: \"numeric\",\r\n })\r\n }}\r\n indicator=\"dot\"\r\n />\r\n }\r\n />\r\n <Area\r\n dataKey=\"mobile\"\r\n type=\"natural\"\r\n fill=\"url(#fillMobile)\"\r\n stroke=\"var(--color-mobile)\"\r\n stackId=\"a\"\r\n />\r\n <Area\r\n dataKey=\"desktop\"\r\n type=\"natural\"\r\n fill=\"url(#fillDesktop)\"\r\n stroke=\"var(--color-desktop)\"\r\n stackId=\"a\"\r\n />\r\n </AreaChart>\r\n </ChartContainer>\r\n </CardContent>\r\n </Card>\r\n )\r\n}"
|
|
3092
|
+
],
|
|
3093
|
+
"description": "",
|
|
3094
|
+
"scope": "jsx / tsx"
|
|
3095
|
+
},
|
|
3096
|
+
"one_components_data-table_tsx": {
|
|
3097
|
+
"prefix": "one_components_data-table_tsx",
|
|
3098
|
+
"body": [
|
|
3099
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport {\r\n closestCenter,\r\n DndContext,\r\n KeyboardSensor,\r\n MouseSensor,\r\n TouchSensor,\r\n useSensor,\r\n useSensors,\r\n type DragEndEvent,\r\n type UniqueIdentifier,\r\n} from \"@dnd-kit/core\"\r\nimport { restrictToVerticalAxis } from \"@dnd-kit/modifiers\"\r\nimport {\r\n arrayMove,\r\n SortableContext,\r\n useSortable,\r\n verticalListSortingStrategy,\r\n} from \"@dnd-kit/sortable\"\r\nimport { CSS } from \"@dnd-kit/utilities\"\r\nimport {\r\n IconChevronDown,\r\n IconChevronLeft,\r\n IconChevronRight,\r\n IconChevronsLeft,\r\n IconChevronsRight,\r\n IconCircleCheckFilled,\r\n IconDotsVertical,\r\n IconGripVertical,\r\n IconLayoutColumns,\r\n IconLoader,\r\n IconPlus,\r\n IconTrendingUp,\r\n} from \"@tabler/icons-react\"\r\nimport {\r\n ColumnDef,\r\n ColumnFiltersState,\r\n flexRender,\r\n getCoreRowModel,\r\n getFacetedRowModel,\r\n getFacetedUniqueValues,\r\n getFilteredRowModel,\r\n getPaginationRowModel,\r\n getSortedRowModel,\r\n Row,\r\n SortingState,\r\n useReactTable,\r\n VisibilityState,\r\n} from \"@tanstack/react-table\"\r\nimport { Area, AreaChart, CartesianGrid, XAxis } from \"recharts\"\r\nimport { toast } from \"sonner\"\r\nimport { z } from \"zod\"\r\n\r\nimport { useIsMobile } from \"@/hooks/use-mobile\"\r\nimport { Badge } from \"@/components/ui/badge\"\r\nimport { Button } from \"@/components/ui/button\"\r\nimport {\r\n ChartConfig,\r\n ChartContainer,\r\n ChartTooltip,\r\n ChartTooltipContent,\r\n} from \"@/components/ui/chart\"\r\nimport { Checkbox } from \"@/components/ui/checkbox\"\r\nimport {\r\n Drawer,\r\n DrawerClose,\r\n DrawerContent,\r\n DrawerDescription,\r\n DrawerFooter,\r\n DrawerHeader,\r\n DrawerTitle,\r\n DrawerTrigger,\r\n} from \"@/components/ui/drawer\"\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuCheckboxItem,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from \"@/components/ui/dropdown-menu\"\r\nimport { Input } from \"@/components/ui/input\"\r\nimport { Label } from \"@/components/ui/label\"\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from \"@/components/ui/select\"\r\nimport { Separator } from \"@/components/ui/separator\"\r\nimport {\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableHead,\r\n TableHeader,\r\n TableRow,\r\n} from \"@/components/ui/table\"\r\nimport {\r\n Tabs,\r\n TabsContent,\r\n TabsList,\r\n TabsTrigger,\r\n} from \"@/components/ui/tabs\"\r\n\r\nexport const schema = z.object({\r\n id: z.number(),\r\n header: z.string(),\r\n type: z.string(),\r\n status: z.string(),\r\n target: z.string(),\r\n limit: z.string(),\r\n reviewer: z.string(),\r\n})\r\n\r\n// Create a separate component for the drag handle\r\nfunction DragHandle({ id }: { id: number }) {\r\n const { attributes, listeners } = useSortable({\r\n id,\r\n })\r\n\r\n return (\r\n <Button\r\n {...attributes}\r\n {...listeners}\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className=\"text-muted-foreground size-7 hover:bg-transparent\"\r\n >\r\n <IconGripVertical className=\"text-muted-foreground size-3\" />\r\n <span className=\"sr-only\">Drag to reorder</span>\r\n </Button>\r\n )\r\n}\r\n\r\nconst columns: ColumnDef<z.infer<typeof schema>>[] = [\r\n {\r\n id: \"drag\",\r\n header: () => null,\r\n cell: ({ row }) => <DragHandle id={row.original.id} />,\r\n },\r\n {\r\n id: \"select\",\r\n header: ({ table }) => (\r\n <div className=\"flex items-center justify-center\">\r\n <Checkbox\r\n checked={\r\n table.getIsAllPageRowsSelected() ||\r\n (table.getIsSomePageRowsSelected() && \"indeterminate\")\r\n }\r\n onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\r\n aria-label=\"Select all\"\r\n />\r\n </div>\r\n ),\r\n cell: ({ row }) => (\r\n <div className=\"flex items-center justify-center\">\r\n <Checkbox\r\n checked={row.getIsSelected()}\r\n onCheckedChange={(value) => row.toggleSelected(!!value)}\r\n aria-label=\"Select row\"\r\n />\r\n </div>\r\n ),\r\n enableSorting: false,\r\n enableHiding: false,\r\n },\r\n {\r\n accessorKey: \"header\",\r\n header: \"Header\",\r\n cell: ({ row }) => {\r\n return <TableCellViewer item={row.original} />\r\n },\r\n enableHiding: false,\r\n },\r\n {\r\n accessorKey: \"type\",\r\n header: \"Section Type\",\r\n cell: ({ row }) => (\r\n <div className=\"w-32\">\r\n <Badge variant=\"outline\" className=\"text-muted-foreground px-1.5\">\r\n {row.original.type}\r\n </Badge>\r\n </div>\r\n ),\r\n },\r\n {\r\n accessorKey: \"status\",\r\n header: \"Status\",\r\n cell: ({ row }) => (\r\n <Badge variant=\"outline\" className=\"text-muted-foreground px-1.5\">\r\n {row.original.status === \"Done\" ? (\r\n <IconCircleCheckFilled className=\"fill-green-500 dark:fill-green-400\" />\r\n ) : (\r\n <IconLoader />\r\n )}\r\n {row.original.status}\r\n </Badge>\r\n ),\r\n },\r\n {\r\n accessorKey: \"target\",\r\n header: () => <div className=\"w-full text-right\">Target</div>,\r\n cell: ({ row }) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault()\r\n toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {\r\n loading: `Saving ${row.original.header}`,\r\n success: \"Done\",\r\n error: \"Error\",\r\n })\r\n }}\r\n >\r\n <Label htmlFor={`${row.original.id}-target`} className=\"sr-only\">\r\n Target\r\n </Label>\r\n <Input\r\n className=\"hover:bg-input/30 focus-visible:bg-background dark:hover:bg-input/30 dark:focus-visible:bg-input/30 h-8 w-16 border-transparent bg-transparent text-right shadow-none focus-visible:border dark:bg-transparent\"\r\n defaultValue={row.original.target}\r\n id={`${row.original.id}-target`}\r\n />\r\n </form>\r\n ),\r\n },\r\n {\r\n accessorKey: \"limit\",\r\n header: () => <div className=\"w-full text-right\">Limit</div>,\r\n cell: ({ row }) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault()\r\n toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {\r\n loading: `Saving ${row.original.header}`,\r\n success: \"Done\",\r\n error: \"Error\",\r\n })\r\n }}\r\n >\r\n <Label htmlFor={`${row.original.id}-limit`} className=\"sr-only\">\r\n Limit\r\n </Label>\r\n <Input\r\n className=\"hover:bg-input/30 focus-visible:bg-background dark:hover:bg-input/30 dark:focus-visible:bg-input/30 h-8 w-16 border-transparent bg-transparent text-right shadow-none focus-visible:border dark:bg-transparent\"\r\n defaultValue={row.original.limit}\r\n id={`${row.original.id}-limit`}\r\n />\r\n </form>\r\n ),\r\n },\r\n {\r\n accessorKey: \"reviewer\",\r\n header: \"Reviewer\",\r\n cell: ({ row }) => {\r\n const isAssigned = row.original.reviewer !== \"Assign reviewer\"\r\n\r\n if (isAssigned) {\r\n return row.original.reviewer\r\n }\r\n\r\n return (\r\n <>\r\n <Label htmlFor={`${row.original.id}-reviewer`} className=\"sr-only\">\r\n Reviewer\r\n </Label>\r\n <Select>\r\n <SelectTrigger\r\n className=\"w-38 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate\"\r\n size=\"sm\"\r\n id={`${row.original.id}-reviewer`}\r\n >\r\n <SelectValue placeholder=\"Assign reviewer\" />\r\n </SelectTrigger>\r\n <SelectContent align=\"end\">\r\n <SelectItem value=\"Eddie Lake\">Eddie Lake</SelectItem>\r\n <SelectItem value=\"Jamik Tashpulatov\">\r\n Jamik Tashpulatov\r\n </SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </>\r\n )\r\n },\r\n },\r\n {\r\n id: \"actions\",\r\n cell: () => (\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n className=\"data-[state=open]:bg-muted text-muted-foreground flex size-8\"\r\n size=\"icon\"\r\n >\r\n <IconDotsVertical />\r\n <span className=\"sr-only\">Open menu</span>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\" className=\"w-32\">\r\n <DropdownMenuItem>Edit</DropdownMenuItem>\r\n <DropdownMenuItem>Make a copy</DropdownMenuItem>\r\n <DropdownMenuItem>Favorite</DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem variant=\"destructive\">Delete</DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n ),\r\n },\r\n]\r\n\r\nfunction DraggableRow({ row }: { row: Row<z.infer<typeof schema>> }) {\r\n const { transform, transition, setNodeRef, isDragging } = useSortable({\r\n id: row.original.id,\r\n })\r\n\r\n return (\r\n <TableRow\r\n data-state={row.getIsSelected() && \"selected\"}\r\n data-dragging={isDragging}\r\n ref={setNodeRef}\r\n className=\"relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80\"\r\n style={{\r\n transform: CSS.Transform.toString(transform),\r\n transition: transition,\r\n }}\r\n >\r\n {row.getVisibleCells().map((cell) => (\r\n <TableCell key={cell.id}>\r\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\r\n </TableCell>\r\n ))}\r\n </TableRow>\r\n )\r\n}\r\n\r\nexport function DataTable({\r\n data: initialData,\r\n}: {\r\n data: z.infer<typeof schema>[]\r\n}) {\r\n const [data, setData] = React.useState(() => initialData)\r\n const [rowSelection, setRowSelection] = React.useState({})\r\n const [columnVisibility, setColumnVisibility] =\r\n React.useState<VisibilityState>({})\r\n const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(\r\n []\r\n )\r\n const [sorting, setSorting] = React.useState<SortingState>([])\r\n const [pagination, setPagination] = React.useState({\r\n pageIndex: 0,\r\n pageSize: 10,\r\n })\r\n const sortableId = React.useId()\r\n const sensors = useSensors(\r\n useSensor(MouseSensor, {}),\r\n useSensor(TouchSensor, {}),\r\n useSensor(KeyboardSensor, {})\r\n )\r\n\r\n const dataIds = React.useMemo<UniqueIdentifier[]>(\r\n () => data?.map(({ id }) => id) || [],\r\n [data]\r\n )\r\n\r\n const table = useReactTable({\r\n data,\r\n columns,\r\n state: {\r\n sorting,\r\n columnVisibility,\r\n rowSelection,\r\n columnFilters,\r\n pagination,\r\n },\r\n getRowId: (row) => row.id.toString(),\r\n enableRowSelection: true,\r\n onRowSelectionChange: setRowSelection,\r\n onSortingChange: setSorting,\r\n onColumnFiltersChange: setColumnFilters,\r\n onColumnVisibilityChange: setColumnVisibility,\r\n onPaginationChange: setPagination,\r\n getCoreRowModel: getCoreRowModel(),\r\n getFilteredRowModel: getFilteredRowModel(),\r\n getPaginationRowModel: getPaginationRowModel(),\r\n getSortedRowModel: getSortedRowModel(),\r\n getFacetedRowModel: getFacetedRowModel(),\r\n getFacetedUniqueValues: getFacetedUniqueValues(),\r\n })\r\n\r\n function handleDragEnd(event: DragEndEvent) {\r\n const { active, over } = event\r\n if (active && over && active.id !== over.id) {\r\n setData((data) => {\r\n const oldIndex = dataIds.indexOf(active.id)\r\n const newIndex = dataIds.indexOf(over.id)\r\n return arrayMove(data, oldIndex, newIndex)\r\n })\r\n }\r\n }\r\n\r\n return (\r\n <Tabs\r\n defaultValue=\"outline\"\r\n className=\"w-full flex-col justify-start gap-6\"\r\n >\r\n <div className=\"flex items-center justify-between px-4 lg:px-6\">\r\n <Label htmlFor=\"view-selector\" className=\"sr-only\">\r\n View\r\n </Label>\r\n <Select defaultValue=\"outline\">\r\n <SelectTrigger\r\n className=\"flex w-fit @4xl/main:hidden\"\r\n size=\"sm\"\r\n id=\"view-selector\"\r\n >\r\n <SelectValue placeholder=\"Select a view\" />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"outline\">Outline</SelectItem>\r\n <SelectItem value=\"past-performance\">Past Performance</SelectItem>\r\n <SelectItem value=\"key-personnel\">Key Personnel</SelectItem>\r\n <SelectItem value=\"focus-documents\">Focus Documents</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n <TabsList className=\"**:data-[slot=badge]:bg-muted-foreground/30 hidden **:data-[slot=badge]:size-5 **:data-[slot=badge]:rounded-full **:data-[slot=badge]:px-1 @4xl/main:flex\">\r\n <TabsTrigger value=\"outline\">Outline</TabsTrigger>\r\n <TabsTrigger value=\"past-performance\">\r\n Past Performance <Badge variant=\"secondary\">3</Badge>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"key-personnel\">\r\n Key Personnel <Badge variant=\"secondary\">2</Badge>\r\n </TabsTrigger>\r\n <TabsTrigger value=\"focus-documents\">Focus Documents</TabsTrigger>\r\n </TabsList>\r\n <div className=\"flex items-center gap-2\">\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button variant=\"outline\" size=\"sm\">\r\n <IconLayoutColumns />\r\n <span className=\"hidden lg:inline\">Customize Columns</span>\r\n <span className=\"lg:hidden\">Columns</span>\r\n <IconChevronDown />\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\" className=\"w-56\">\r\n {table\r\n .getAllColumns()\r\n .filter(\r\n (column) =>\r\n typeof column.accessorFn !== \"undefined\" &&\r\n column.getCanHide()\r\n )\r\n .map((column) => {\r\n return (\r\n <DropdownMenuCheckboxItem\r\n key={column.id}\r\n className=\"capitalize\"\r\n checked={column.getIsVisible()}\r\n onCheckedChange={(value) =>\r\n column.toggleVisibility(!!value)\r\n }\r\n >\r\n {column.id}\r\n </DropdownMenuCheckboxItem>\r\n )\r\n })}\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n <Button variant=\"outline\" size=\"sm\">\r\n <IconPlus />\r\n <span className=\"hidden lg:inline\">Add Section</span>\r\n </Button>\r\n </div>\r\n </div>\r\n <TabsContent\r\n value=\"outline\"\r\n className=\"relative flex flex-col gap-4 overflow-auto px-4 lg:px-6\"\r\n >\r\n <div className=\"overflow-hidden rounded-lg border\">\r\n <DndContext\r\n collisionDetection={closestCenter}\r\n modifiers={[restrictToVerticalAxis]}\r\n onDragEnd={handleDragEnd}\r\n sensors={sensors}\r\n id={sortableId}\r\n >\r\n <Table>\r\n <TableHeader className=\"bg-muted sticky top-0 z-10\">\r\n {table.getHeaderGroups().map((headerGroup) => (\r\n <TableRow key={headerGroup.id}>\r\n {headerGroup.headers.map((header) => {\r\n return (\r\n <TableHead key={header.id} colSpan={header.colSpan}>\r\n {header.isPlaceholder\r\n ? null\r\n : flexRender(\r\n header.column.columnDef.header,\r\n header.getContext()\r\n )}\r\n </TableHead>\r\n )\r\n })}\r\n </TableRow>\r\n ))}\r\n </TableHeader>\r\n <TableBody className=\"**:data-[slot=table-cell]:first:w-8\">\r\n {table.getRowModel().rows?.length ? (\r\n <SortableContext\r\n items={dataIds}\r\n strategy={verticalListSortingStrategy}\r\n >\r\n {table.getRowModel().rows.map((row) => (\r\n <DraggableRow key={row.id} row={row} />\r\n ))}\r\n </SortableContext>\r\n ) : (\r\n <TableRow>\r\n <TableCell\r\n colSpan={columns.length}\r\n className=\"h-24 text-center\"\r\n >\r\n No results.\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n </TableBody>\r\n </Table>\r\n </DndContext>\r\n </div>\r\n <div className=\"flex items-center justify-between px-4\">\r\n <div className=\"text-muted-foreground hidden flex-1 text-sm lg:flex\">\r\n {table.getFilteredSelectedRowModel().rows.length} of{\" \"}\r\n {table.getFilteredRowModel().rows.length} row(s) selected.\r\n </div>\r\n <div className=\"flex w-full items-center gap-8 lg:w-fit\">\r\n <div className=\"hidden items-center gap-2 lg:flex\">\r\n <Label htmlFor=\"rows-per-page\" className=\"text-sm font-medium\">\r\n Rows per page\r\n </Label>\r\n <Select\r\n value={`${table.getState().pagination.pageSize}`}\r\n onValueChange={(value) => {\r\n table.setPageSize(Number(value))\r\n }}\r\n >\r\n <SelectTrigger size=\"sm\" className=\"w-20\" id=\"rows-per-page\">\r\n <SelectValue\r\n placeholder={table.getState().pagination.pageSize}\r\n />\r\n </SelectTrigger>\r\n <SelectContent side=\"top\">\r\n {[10, 20, 30, 40, 50].map((pageSize) => (\r\n <SelectItem key={pageSize} value={`${pageSize}`}>\r\n {pageSize}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <div className=\"flex w-fit items-center justify-center text-sm font-medium\">\r\n Page {table.getState().pagination.pageIndex + 1} of{\" \"}\r\n {table.getPageCount()}\r\n </div>\r\n <div className=\"ml-auto flex items-center gap-2 lg:ml-0\">\r\n <Button\r\n variant=\"outline\"\r\n className=\"hidden h-8 w-8 p-0 lg:flex\"\r\n onClick={() => table.setPageIndex(0)}\r\n disabled={!table.getCanPreviousPage()}\r\n >\r\n <span className=\"sr-only\">Go to first page</span>\r\n <IconChevronsLeft />\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n className=\"size-8\"\r\n size=\"icon\"\r\n onClick={() => table.previousPage()}\r\n disabled={!table.getCanPreviousPage()}\r\n >\r\n <span className=\"sr-only\">Go to previous page</span>\r\n <IconChevronLeft />\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n className=\"size-8\"\r\n size=\"icon\"\r\n onClick={() => table.nextPage()}\r\n disabled={!table.getCanNextPage()}\r\n >\r\n <span className=\"sr-only\">Go to next page</span>\r\n <IconChevronRight />\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n className=\"hidden size-8 lg:flex\"\r\n size=\"icon\"\r\n onClick={() => table.setPageIndex(table.getPageCount() - 1)}\r\n disabled={!table.getCanNextPage()}\r\n >\r\n <span className=\"sr-only\">Go to last page</span>\r\n <IconChevronsRight />\r\n </Button>\r\n </div>\r\n </div>\r\n </div>\r\n </TabsContent>\r\n <TabsContent\r\n value=\"past-performance\"\r\n className=\"flex flex-col px-4 lg:px-6\"\r\n >\r\n <div className=\"aspect-video w-full flex-1 rounded-lg border border-dashed\"></div>\r\n </TabsContent>\r\n <TabsContent value=\"key-personnel\" className=\"flex flex-col px-4 lg:px-6\">\r\n <div className=\"aspect-video w-full flex-1 rounded-lg border border-dashed\"></div>\r\n </TabsContent>\r\n <TabsContent\r\n value=\"focus-documents\"\r\n className=\"flex flex-col px-4 lg:px-6\"\r\n >\r\n <div className=\"aspect-video w-full flex-1 rounded-lg border border-dashed\"></div>\r\n </TabsContent>\r\n </Tabs>\r\n )\r\n}\r\n\r\nconst chartData = [\r\n { month: \"January\", desktop: 186, mobile: 80 },\r\n { month: \"February\", desktop: 305, mobile: 200 },\r\n { month: \"March\", desktop: 237, mobile: 120 },\r\n { month: \"April\", desktop: 73, mobile: 190 },\r\n { month: \"May\", desktop: 209, mobile: 130 },\r\n { month: \"June\", desktop: 214, mobile: 140 },\r\n]\r\n\r\nconst chartConfig = {\r\n desktop: {\r\n label: \"Desktop\",\r\n color: \"var(--primary)\",\r\n },\r\n mobile: {\r\n label: \"Mobile\",\r\n color: \"var(--primary)\",\r\n },\r\n} satisfies ChartConfig\r\n\r\nfunction TableCellViewer({ item }: { item: z.infer<typeof schema> }) {\r\n const isMobile = useIsMobile()\r\n\r\n return (\r\n <Drawer direction={isMobile ? \"bottom\" : \"right\"}>\r\n <DrawerTrigger asChild>\r\n <Button variant=\"link\" className=\"text-foreground w-fit px-0 text-left\">\r\n {item.header}\r\n </Button>\r\n </DrawerTrigger>\r\n <DrawerContent>\r\n <DrawerHeader className=\"gap-1\">\r\n <DrawerTitle>{item.header}</DrawerTitle>\r\n <DrawerDescription>\r\n Showing total visitors for the last 6 months\r\n </DrawerDescription>\r\n </DrawerHeader>\r\n <div className=\"flex flex-col gap-4 overflow-y-auto px-4 text-sm\">\r\n {!isMobile && (\r\n <>\r\n <ChartContainer config={chartConfig}>\r\n <AreaChart\r\n accessibilityLayer\r\n data={chartData}\r\n margin={{\r\n left: 0,\r\n right: 10,\r\n }}\r\n >\r\n <CartesianGrid vertical={false} />\r\n <XAxis\r\n dataKey=\"month\"\r\n tickLine={false}\r\n axisLine={false}\r\n tickMargin={8}\r\n tickFormatter={(value) => value.slice(0, 3)}\r\n hide\r\n />\r\n <ChartTooltip\r\n cursor={false}\r\n content={<ChartTooltipContent indicator=\"dot\" />}\r\n />\r\n <Area\r\n dataKey=\"mobile\"\r\n type=\"natural\"\r\n fill=\"var(--color-mobile)\"\r\n fillOpacity={0.6}\r\n stroke=\"var(--color-mobile)\"\r\n stackId=\"a\"\r\n />\r\n <Area\r\n dataKey=\"desktop\"\r\n type=\"natural\"\r\n fill=\"var(--color-desktop)\"\r\n fillOpacity={0.4}\r\n stroke=\"var(--color-desktop)\"\r\n stackId=\"a\"\r\n />\r\n </AreaChart>\r\n </ChartContainer>\r\n <Separator />\r\n <div className=\"grid gap-2\">\r\n <div className=\"flex gap-2 leading-none font-medium\">\r\n Trending up by 5.2% this month{\" \"}\r\n <IconTrendingUp className=\"size-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n Showing total visitors for the last 6 months. This is just\r\n some random text to test the layout. It spans multiple lines\r\n and should wrap around.\r\n </div>\r\n </div>\r\n <Separator />\r\n </>\r\n )}\r\n <form className=\"flex flex-col gap-4\">\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"header\">Header</Label>\r\n <Input id=\"header\" defaultValue={item.header} />\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"type\">Type</Label>\r\n <Select defaultValue={item.type}>\r\n <SelectTrigger id=\"type\" className=\"w-full\">\r\n <SelectValue placeholder=\"Select a type\" />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"Table of Contents\">\r\n Table of Contents\r\n </SelectItem>\r\n <SelectItem value=\"Executive Summary\">\r\n Executive Summary\r\n </SelectItem>\r\n <SelectItem value=\"Technical Approach\">\r\n Technical Approach\r\n </SelectItem>\r\n <SelectItem value=\"Design\">Design</SelectItem>\r\n <SelectItem value=\"Capabilities\">Capabilities</SelectItem>\r\n <SelectItem value=\"Focus Documents\">\r\n Focus Documents\r\n </SelectItem>\r\n <SelectItem value=\"Narrative\">Narrative</SelectItem>\r\n <SelectItem value=\"Cover Page\">Cover Page</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"status\">Status</Label>\r\n <Select defaultValue={item.status}>\r\n <SelectTrigger id=\"status\" className=\"w-full\">\r\n <SelectValue placeholder=\"Select a status\" />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"Done\">Done</SelectItem>\r\n <SelectItem value=\"In Progress\">In Progress</SelectItem>\r\n <SelectItem value=\"Not Started\">Not Started</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </div>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"target\">Target</Label>\r\n <Input id=\"target\" defaultValue={item.target} />\r\n </div>\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"limit\">Limit</Label>\r\n <Input id=\"limit\" defaultValue={item.limit} />\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-3\">\r\n <Label htmlFor=\"reviewer\">Reviewer</Label>\r\n <Select defaultValue={item.reviewer}>\r\n <SelectTrigger id=\"reviewer\" className=\"w-full\">\r\n <SelectValue placeholder=\"Select a reviewer\" />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"Eddie Lake\">Eddie Lake</SelectItem>\r\n <SelectItem value=\"Jamik Tashpulatov\">\r\n Jamik Tashpulatov\r\n </SelectItem>\r\n <SelectItem value=\"Emily Whalen\">Emily Whalen</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n </form>\r\n </div>\r\n <DrawerFooter>\r\n <Button>Submit</Button>\r\n <DrawerClose asChild>\r\n <Button variant=\"outline\">Done</Button>\r\n </DrawerClose>\r\n </DrawerFooter>\r\n </DrawerContent>\r\n </Drawer>\r\n )\r\n}"
|
|
3100
|
+
],
|
|
3101
|
+
"description": "",
|
|
3102
|
+
"scope": "jsx / tsx"
|
|
3103
|
+
},
|
|
3104
|
+
"one_components_nav-documents_tsx": {
|
|
3105
|
+
"prefix": "one_components_nav-documents_tsx",
|
|
3106
|
+
"body": [
|
|
3107
|
+
"\"use client\"\r\n\r\nimport {\r\n IconDots,\r\n IconFolder,\r\n IconShare3,\r\n IconTrash,\r\n type Icon,\r\n} from \"@tabler/icons-react\"\r\n\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from \"@/components/ui/dropdown-menu\"\r\nimport {\r\n SidebarGroup,\r\n SidebarGroupLabel,\r\n SidebarMenu,\r\n SidebarMenuAction,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n useSidebar,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nexport function NavDocuments({\r\n items,\r\n}: {\r\n items: {\r\n name: string\r\n url: string\r\n icon: Icon\r\n }[]\r\n}) {\r\n const { isMobile } = useSidebar()\r\n\r\n return (\r\n <SidebarGroup className=\"group-data-[collapsible=icon]:hidden\">\r\n <SidebarGroupLabel>Documents</SidebarGroupLabel>\r\n <SidebarMenu>\r\n {items.map((item) => (\r\n <SidebarMenuItem key={item.name}>\r\n <SidebarMenuButton asChild>\r\n <a href={item.url}>\r\n <item.icon />\r\n <span>{item.name}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <SidebarMenuAction\r\n showOnHover\r\n className=\"data-[state=open]:bg-accent rounded-sm\"\r\n >\r\n <IconDots />\r\n <span className=\"sr-only\">More</span>\r\n </SidebarMenuAction>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent\r\n className=\"w-24 rounded-lg\"\r\n side={isMobile ? \"bottom\" : \"right\"}\r\n align={isMobile ? \"end\" : \"start\"}\r\n >\r\n <DropdownMenuItem>\r\n <IconFolder />\r\n <span>Open</span>\r\n </DropdownMenuItem>\r\n <DropdownMenuItem>\r\n <IconShare3 />\r\n <span>Share</span>\r\n </DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem variant=\"destructive\">\r\n <IconTrash />\r\n <span>Delete</span>\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </SidebarMenuItem>\r\n ))}\r\n <SidebarMenuItem>\r\n <SidebarMenuButton className=\"text-sidebar-foreground/70\">\r\n <IconDots className=\"text-sidebar-foreground/70\" />\r\n <span>More</span>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n </SidebarGroup>\r\n )\r\n}"
|
|
3108
|
+
],
|
|
3109
|
+
"description": "",
|
|
3110
|
+
"scope": "jsx / tsx"
|
|
3111
|
+
},
|
|
3112
|
+
"one_components_nav-main_tsx": {
|
|
3113
|
+
"prefix": "one_components_nav-main_tsx",
|
|
3114
|
+
"body": [
|
|
3115
|
+
"\"use client\"\r\n\r\nimport { IconCirclePlusFilled, IconMail, type Icon } from \"@tabler/icons-react\"\r\n\r\nimport { Button } from \"@/components/ui/button\"\r\nimport {\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nexport function NavMain({\r\n items,\r\n}: {\r\n items: {\r\n title: string\r\n url: string\r\n icon?: Icon\r\n }[]\r\n}) {\r\n return (\r\n <SidebarGroup>\r\n <SidebarGroupContent className=\"flex flex-col gap-2\">\r\n <SidebarMenu>\r\n <SidebarMenuItem className=\"flex items-center gap-2\">\r\n <SidebarMenuButton\r\n tooltip=\"Quick Create\"\r\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground min-w-8 duration-200 ease-linear\"\r\n >\r\n <IconCirclePlusFilled />\r\n <span>Quick Create</span>\r\n </SidebarMenuButton>\r\n <Button\r\n size=\"icon\"\r\n className=\"size-8 group-data-[collapsible=icon]:opacity-0\"\r\n variant=\"outline\"\r\n >\r\n <IconMail />\r\n <span className=\"sr-only\">Inbox</span>\r\n </Button>\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n <SidebarMenu>\r\n {items.map((item) => (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton tooltip={item.title}>\r\n {item.icon && <item.icon />}\r\n <span>{item.title}</span>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n )\r\n}"
|
|
3116
|
+
],
|
|
3117
|
+
"description": "",
|
|
3118
|
+
"scope": "jsx / tsx"
|
|
3119
|
+
},
|
|
3120
|
+
"one_components_nav-secondary_tsx": {
|
|
3121
|
+
"prefix": "one_components_nav-secondary_tsx",
|
|
3122
|
+
"body": [
|
|
3123
|
+
"\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { type Icon } from \"@tabler/icons-react\"\r\n\r\nimport {\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nexport function NavSecondary({\r\n items,\r\n ...props\r\n}: {\r\n items: {\r\n title: string\r\n url: string\r\n icon: Icon\r\n }[]\r\n} & React.ComponentPropsWithoutRef<typeof SidebarGroup>) {\r\n return (\r\n <SidebarGroup {...props}>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {items.map((item) => (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <a href={item.url}>\r\n <item.icon />\r\n <span>{item.title}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n )\r\n}"
|
|
3124
|
+
],
|
|
3125
|
+
"description": "",
|
|
3126
|
+
"scope": "jsx / tsx"
|
|
3127
|
+
},
|
|
3128
|
+
"one_components_nav-user_tsx": {
|
|
3129
|
+
"prefix": "one_components_nav-user_tsx",
|
|
3130
|
+
"body": [
|
|
3131
|
+
"\"use client\"\r\n\r\nimport {\r\n IconCreditCard,\r\n IconDotsVertical,\r\n IconLogout,\r\n IconNotification,\r\n IconUserCircle,\r\n} from \"@tabler/icons-react\"\r\n\r\nimport {\r\n Avatar,\r\n AvatarFallback,\r\n AvatarImage,\r\n} from \"@/components/ui/avatar\"\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuContent,\r\n DropdownMenuGroup,\r\n DropdownMenuItem,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from \"@/components/ui/dropdown-menu\"\r\nimport {\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n useSidebar,\r\n} from \"@/components/ui/sidebar\"\r\n\r\nexport function NavUser({\r\n user,\r\n}: {\r\n user: {\r\n name: string\r\n email: string\r\n avatar: string\r\n }\r\n}) {\r\n const { isMobile } = useSidebar()\r\n\r\n return (\r\n <SidebarMenu>\r\n <SidebarMenuItem>\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <SidebarMenuButton\r\n size=\"lg\"\r\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\r\n >\r\n <Avatar className=\"h-8 w-8 rounded-lg grayscale\">\r\n <AvatarImage src={user.avatar} alt={user.name} />\r\n <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>\r\n </Avatar>\r\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\r\n <span className=\"truncate font-medium\">{user.name}</span>\r\n <span className=\"text-muted-foreground truncate text-xs\">\r\n {user.email}\r\n </span>\r\n </div>\r\n <IconDotsVertical className=\"ml-auto size-4\" />\r\n </SidebarMenuButton>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent\r\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\r\n side={isMobile ? \"bottom\" : \"right\"}\r\n align=\"end\"\r\n sideOffset={4}\r\n >\r\n <DropdownMenuLabel className=\"p-0 font-normal\">\r\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\r\n <Avatar className=\"h-8 w-8 rounded-lg\">\r\n <AvatarImage src={user.avatar} alt={user.name} />\r\n <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>\r\n </Avatar>\r\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\r\n <span className=\"truncate font-medium\">{user.name}</span>\r\n <span className=\"text-muted-foreground truncate text-xs\">\r\n {user.email}\r\n </span>\r\n </div>\r\n </div>\r\n </DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuGroup>\r\n <DropdownMenuItem>\r\n <IconUserCircle />\r\n Account\r\n </DropdownMenuItem>\r\n <DropdownMenuItem>\r\n <IconCreditCard />\r\n Billing\r\n </DropdownMenuItem>\r\n <DropdownMenuItem>\r\n <IconNotification />\r\n Notifications\r\n </DropdownMenuItem>\r\n </DropdownMenuGroup>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem>\r\n <IconLogout />\r\n Log out\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n )\r\n}"
|
|
3132
|
+
],
|
|
3133
|
+
"description": "",
|
|
3134
|
+
"scope": "jsx / tsx"
|
|
3135
|
+
},
|
|
3136
|
+
"one_components_section-cards_tsx": {
|
|
3137
|
+
"prefix": "one_components_section-cards_tsx",
|
|
3138
|
+
"body": [
|
|
3139
|
+
"import { IconTrendingDown, IconTrendingUp } from \"@tabler/icons-react\"\r\n\r\nimport { Badge } from \"@/components/ui/badge\"\r\nimport {\r\n Card,\r\n CardAction,\r\n CardDescription,\r\n CardFooter,\r\n CardHeader,\r\n CardTitle,\r\n} from \"@/components/ui/card\"\r\n\r\nexport function SectionCards() {\r\n return (\r\n <div className=\"*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-4 px-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:shadow-xs lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4\">\r\n <Card className=\"@container/card\">\r\n <CardHeader>\r\n <CardDescription>Total Revenue</CardDescription>\r\n <CardTitle className=\"text-2xl font-semibold tabular-nums @[250px]/card:text-3xl\">\r\n $1,250.00\r\n </CardTitle>\r\n <CardAction>\r\n <Badge variant=\"outline\">\r\n <IconTrendingUp />\r\n +12.5%\r\n </Badge>\r\n </CardAction>\r\n </CardHeader>\r\n <CardFooter className=\"flex-col items-start gap-1.5 text-sm\">\r\n <div className=\"line-clamp-1 flex gap-2 font-medium\">\r\n Trending up this month <IconTrendingUp className=\"size-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n Visitors for the last 6 months\r\n </div>\r\n </CardFooter>\r\n </Card>\r\n <Card className=\"@container/card\">\r\n <CardHeader>\r\n <CardDescription>New Customers</CardDescription>\r\n <CardTitle className=\"text-2xl font-semibold tabular-nums @[250px]/card:text-3xl\">\r\n 1,234\r\n </CardTitle>\r\n <CardAction>\r\n <Badge variant=\"outline\">\r\n <IconTrendingDown />\r\n -20%\r\n </Badge>\r\n </CardAction>\r\n </CardHeader>\r\n <CardFooter className=\"flex-col items-start gap-1.5 text-sm\">\r\n <div className=\"line-clamp-1 flex gap-2 font-medium\">\r\n Down 20% this period <IconTrendingDown className=\"size-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground\">\r\n Acquisition needs attention\r\n </div>\r\n </CardFooter>\r\n </Card>\r\n <Card className=\"@container/card\">\r\n <CardHeader>\r\n <CardDescription>Active Accounts</CardDescription>\r\n <CardTitle className=\"text-2xl font-semibold tabular-nums @[250px]/card:text-3xl\">\r\n 45,678\r\n </CardTitle>\r\n <CardAction>\r\n <Badge variant=\"outline\">\r\n <IconTrendingUp />\r\n +12.5%\r\n </Badge>\r\n </CardAction>\r\n </CardHeader>\r\n <CardFooter className=\"flex-col items-start gap-1.5 text-sm\">\r\n <div className=\"line-clamp-1 flex gap-2 font-medium\">\r\n Strong user retention <IconTrendingUp className=\"size-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground\">Engagement exceed targets</div>\r\n </CardFooter>\r\n </Card>\r\n <Card className=\"@container/card\">\r\n <CardHeader>\r\n <CardDescription>Growth Rate</CardDescription>\r\n <CardTitle className=\"text-2xl font-semibold tabular-nums @[250px]/card:text-3xl\">\r\n 4.5%\r\n </CardTitle>\r\n <CardAction>\r\n <Badge variant=\"outline\">\r\n <IconTrendingUp />\r\n +4.5%\r\n </Badge>\r\n </CardAction>\r\n </CardHeader>\r\n <CardFooter className=\"flex-col items-start gap-1.5 text-sm\">\r\n <div className=\"line-clamp-1 flex gap-2 font-medium\">\r\n Steady performance increase <IconTrendingUp className=\"size-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground\">Meets growth projections</div>\r\n </CardFooter>\r\n </Card>\r\n </div>\r\n )\r\n}"
|
|
3140
|
+
],
|
|
3141
|
+
"description": "",
|
|
3142
|
+
"scope": "jsx / tsx"
|
|
3143
|
+
},
|
|
3144
|
+
"one_components_site-header_tsx": {
|
|
3145
|
+
"prefix": "one_components_site-header_tsx",
|
|
3146
|
+
"body": [
|
|
3147
|
+
"import { Button } from \"@/components/ui/button\"\r\nimport { Separator } from \"@/components/ui/separator\"\r\nimport { SidebarTrigger } from \"@/components/ui/sidebar\"\r\n\r\nexport function SiteHeader() {\r\n return (\r\n <header className=\"flex h-(--header-height) shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-(--header-height)\">\r\n <div className=\"flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6\">\r\n <SidebarTrigger className=\"-ml-1\" />\r\n <Separator\r\n orientation=\"vertical\"\r\n className=\"mx-2 data-[orientation=vertical]:h-4\"\r\n />\r\n <h1 className=\"text-base font-medium\">Documents</h1>\r\n <div className=\"ml-auto flex items-center gap-2\">\r\n <Button variant=\"ghost\" asChild size=\"sm\" className=\"hidden sm:flex\">\r\n <a\r\n href=\"https://github.com/shadcn-ui/ui/tree/main/apps/v4/app/(examples)/dashboard\"\r\n rel=\"noopener noreferrer\"\r\n target=\"_blank\"\r\n className=\"dark:text-foreground\"\r\n >\r\n GitHub\r\n </a>\r\n </Button>\r\n </div>\r\n </div>\r\n </header>\r\n )\r\n}"
|
|
3148
|
+
],
|
|
3149
|
+
"description": "",
|
|
3150
|
+
"scope": "jsx / tsx"
|
|
3151
|
+
},
|
|
3152
|
+
"error_loading": {
|
|
3153
|
+
"prefix": "error_loading",
|
|
3154
|
+
"body": [
|
|
3155
|
+
"export function ErrorLoading({ loadError }) {\n const nav = useNavigate()\n if (loadError) {\n return (\n <div className=\"min-h-screen bg-gbackground flex items-center justify-center\">\n <div className=\"text-center max-w-md\">\n <AlertCircle className=\"w-12 h-12 text-red-500 mx-auto mb-4\" />\n <div className=\"text-lg font-medium text-foreground mb-2\">Failed to Load Configuration</div>\n <div className=\"text-sm text-muted-foreground mb-4\">{loadError}</div>\n <Button\n onClick={() => nav(0)}\n className=\"px-4 py-2 bg-primary hover:bg-primary/20 text-foreground rounded-lg transition-colors\"\n >\n Retry\n </Button>\n </div>\n </div>\n );\n }\n}"
|
|
3156
|
+
],
|
|
3157
|
+
"description": "",
|
|
3158
|
+
"scope": "jsx / tsx"
|
|
3159
|
+
},
|
|
3160
|
+
"under_construction": {
|
|
3161
|
+
"prefix": "under_construction",
|
|
3162
|
+
"body": [
|
|
3163
|
+
"export function UnderConstruction({ dealerName }) {\r\n /**\r\n * \r\nimport { type ActionFunction, json, type LoaderFunction, redirect,} from \"@remix-run/node\";\r\n\r\nexport async function loader({ request, params, req }: LoaderFunction) {\r\n const DEALER_NAME = process.env.DEALER_NAME;\r\n return json({DEALER_NAME});\r\n}\r\n\r\nexport default function Commissions() {\r\n const { DEALER_NAME} = useLoaderData()\r\n return (\r\n <UnderConstruction dealerName={DEALER_NAME} />\r\n )\r\n}\r\n * \r\n */\r\n return (\r\n <div className=\"flex max-h-[300px] flex-col items-center justify-center gap-6 bg-background p-6 md:p-10\">\r\n <div className=\"w-full max-w-sm\">\r\n <div className=\"flex flex-col gap-6\">\r\n <form>\r\n <div className=\"flex flex-col gap-6\">\r\n <div className=\"flex flex-col items-center gap-2\">\r\n <div className=\"flex flex-col items-center gap-2 font-medium\" >\r\n <div className=\"flex h-8 w-8 items-center justify-center rounded-md\">\r\n <CarFront className=\"size-6\" />\r\n </div>\r\n <span className=\"sr-only\">{dealerName}.</span>\r\n </div>\r\n <h1 className=\"text-xl font-bold\">{dealerName}.</h1>\r\n <div className=\"text-center text-sm\">\r\n UNDER CONSTRUCTION\r\n </div>\r\n </div> <div className=\"flex flex-col gap-1\">\r\n <p className='text-center'>Please check back later once this page is developed. Thank you for your patience and understanding.</p>\r\n <div className=\"relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t after:border-border\">\r\n <span className=\"relative z-10 bg-background px-2 text-muted-foreground\">\r\n <p>The dev.</p>\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n <div className=\"text-balance text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 hover:[&_a]:text-primary \">\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}"
|
|
3164
|
+
],
|
|
3165
|
+
"description": "",
|
|
3166
|
+
"scope": "jsx / tsx"
|
|
3167
|
+
},
|
|
3168
|
+
"loading": {
|
|
3169
|
+
"prefix": "loading",
|
|
3170
|
+
"body": [
|
|
3171
|
+
"export function Loading({ text = 'Loading...', size = 6, color = 'border-blue-500' }) {\r\n return (\r\n <div className='flex items-center gap-3'>\r\n <div className=\"flex items-center justify-center h-full\">\r\n <div className={`animate-spin rounded-full h-${size} w-${size} border-t-4 border-${color} border-solid`}></div>\r\n </div>\r\n <p className='ml-3'>{text}</p>\r\n </div>\r\n );\r\n}"
|
|
3172
|
+
],
|
|
3173
|
+
"description": "",
|
|
3174
|
+
"scope": "jsx / tsx"
|
|
3175
|
+
},
|
|
3176
|
+
"tooltip_button": {
|
|
3177
|
+
"prefix": "tooltip_button",
|
|
3178
|
+
"body": [
|
|
3179
|
+
"function TooltipButton({ icon, content, onClick = null }) {\r\n return (\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button\r\n variant='ghost'\r\n size='icon'\r\n className='toolbar-button format-active'\r\n onClick={onClick} // Fixed: Pass onClick directly\r\n >\r\n {icon}\r\n </Button>\r\n </TooltipTrigger>\r\n <TooltipContent>\r\n <p>{content}</p>\r\n </TooltipContent>\r\n </Tooltip>\r\n );\r\n }"
|
|
3180
|
+
],
|
|
3181
|
+
"description": "",
|
|
3182
|
+
"scope": "jsx / tsx"
|
|
3183
|
+
},
|
|
3184
|
+
"action_template": {
|
|
3185
|
+
"prefix": "action_template",
|
|
3186
|
+
"body": [
|
|
3187
|
+
"export async function action({ request }: ActionFunction) {\n const d = Object.fromEntries(await request.formData());\n const session = await getAuthSession(request.headers.get(\"Cookie\"));\n const email = session.get(\"email\");\n const user = await GetUser(email);\n if (!user) { return redirect(process.env.LOGIN); }\n if (d.intent === \"clientTurnover\") {\n const existingTurnover = await prisma.test.findFirst({\n where: {\n dealerId: d.dealerId,\n locked: true,\n response: false\n }\n });\n return json({ success: true, existingTurnover });\n }\n return json({ error: \"Invalid intent\" }, { status: 400 });\n}"
|
|
3188
|
+
],
|
|
3189
|
+
"description": "",
|
|
3190
|
+
"scope": "jsx / tsx"
|
|
3191
|
+
},
|
|
3192
|
+
"loader_template": {
|
|
3193
|
+
"prefix": "loader_template",
|
|
3194
|
+
"body": [
|
|
3195
|
+
"import { getAuthSession } from \"~/sessions/auth-session.server\";\r\nimport { GetUser } from \"~/utils/loader.server\";\r\nimport eP from \"~/utils/ext.server\";\r\nimport { prisma } from \"~/libs\";\r\nimport { type LinksFunction, MetaFunction, json } from \"@remix-run/node\";\r\n\r\nexport async function loader({ request, params }: LoaderFunction) {\r\n const session = await getAuthSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\");\r\n const user = await GetUser(email);\r\n if (!user) { return redirect(process.env.LOGIN) }\r\n return json({ user })\r\n}"
|
|
3196
|
+
],
|
|
3197
|
+
"description": "",
|
|
3198
|
+
"scope": "jsx / tsx"
|
|
3199
|
+
},
|
|
3200
|
+
"onsubmit_w_buttonstyled": {
|
|
3201
|
+
"prefix": "onsubmit_w_buttonstyled",
|
|
3202
|
+
"body": [
|
|
3203
|
+
"<ButtonStyled onClick={() => {\r\n const formData = new FormData();\r\n {/** user */ }\r\n formData.append(\"id\", item.id);\r\n formData.append(\"intent\", \"deleteProgress\");\r\n fetcher.submit(formData, { method: \"post\" });\r\n }}>\r\n Save\r\n </ButtonStyled>"
|
|
3204
|
+
],
|
|
3205
|
+
"description": "",
|
|
3206
|
+
"scope": "jsx / tsx"
|
|
3207
|
+
},
|
|
3208
|
+
"testttt": {
|
|
3209
|
+
"prefix": "testttt",
|
|
3210
|
+
"body": [
|
|
3211
|
+
"setDevstackFormData({\r\n label: noSpace,\r\n type: 'md',\r\n path: \"c:/Users/skyle/AppData/Roaming/Code - Insiders/User/globalStorage/skyler.ocrmnav/ocrmnavigator.code-snippets\",\r\n })"
|
|
3212
|
+
],
|
|
3213
|
+
"description": "",
|
|
3214
|
+
"scope": "jsx / tsx"
|
|
3215
|
+
},
|
|
3216
|
+
"test1234": {
|
|
3217
|
+
"prefix": "test1234",
|
|
3218
|
+
"body": [
|
|
3219
|
+
"{\r\n label: noSpace,\r\n type: 'md',\r\n path: \"c:/Users/skyle/AppData/Roaming/Code - Insiders/User/globalStorage/skyler.ocrmnav/ocrmnavigator.code-snippets\",\r\n }"
|
|
3220
|
+
],
|
|
3221
|
+
"description": "",
|
|
3222
|
+
"scope": "jsx / tsx"
|
|
3223
|
+
},
|
|
3224
|
+
"default_route_scaffolding": {
|
|
3225
|
+
"prefix": "default_route_scaffolding",
|
|
3226
|
+
"body": [
|
|
3227
|
+
"import { React, useCallback, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { NavLink, Outlet, useActionData, useFetcher, useLoaderData, useLocation, useNavigate, useNavigation, useParams, useRouteLoaderData, useSearchParams, useSubmit } from '@remix-run/react';\r\nimport { eP } from '~/utils/ext';\r\nimport { authSessionStorage } from '~/sessions/session';\r\nimport { axios } from 'axios';\r\nimport { ActionArgs, defer, json, redirect, type ActionArgs, type LoaderArgs } from '@remix-run/node';\r\nimport { prisma } from \"~/libs\";\r\nimport { CarFront, Link } from 'lucide-react';\r\nimport { ButtonStyled } from '~/components/ui/button-loading';\r\nimport { Label } from '~/components/ui/label';\r\n\r\n\r\n\r\nexport default function Dashboard() {\r\n const { user } = useLoaderData()\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [loadError, setLoadError] = useState(null);\r\n\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"min-h-screen bg-background flex items-center justify-center\">\r\n <div className=\"text-center\">\r\n <div className=\"w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4\"></div>\r\n <div className=\"text-lg font-medium text-gray-700\">Loading configuration...</div>\r\n <div className=\"text-sm text-gray-500 mt-2\">Fetching build settings from server</div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n if (loadError) {\r\n return (\r\n <div className=\"min-h-screen bg-background flex items-center justify-center\">\r\n <div className=\"text-center max-w-md\">\r\n <AlertCircle className=\"w-12 h-12 text-red-500 mx-auto mb-4\" />\r\n <div className=\"text-lg font-medium text-foreground mb-2\">Failed to Load Configuration</div>\r\n <div className=\"text-sm text-muted-foreground mb-4\">{loadError}</div>\r\n <Button\r\n onClick={() => nav(0)}\r\n className=\"px-4 py-2 bg-primary hover:bg-primary/20 text-foreground rounded-lg transition-colors\"\r\n >\r\n Retry\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n return (\r\n <div className=\"flex flex-col justify-center gap-3\">\r\n\r\n </div>\r\n )\r\n}\r\n\r\nexport async function action({ request }: ActionArgs) {\r\n const session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\");\r\n const user = await eP.user.simple(email)\r\n if (!user) { return redirect(process.env.LOGIN); }\r\n\r\n const d = Object.fromEntries(await request.formData());\r\n const intent = d.intent\r\n\r\n try {\r\n if (intent === 'createFunction') {\r\n const result = await prisma.Function.create({\r\n data: {\r\n ...data\r\n }\r\n });\r\n return json({ success: true, result });\r\n } else if (intent === 'updateFunction') {\r\n const result = await prisma.Function.update({\r\n where: { id: String(id) },\r\n data\r\n });\r\n return json({ success: true, result });\r\n } else if (intent === 'deleteFunction') {\r\n const result = await prisma.Function.delete({\r\n where: { id: String(id) },\r\n\r\n });\r\n return json({ success: true, result });\r\n } else {\r\n return json({ success: false, error: \"Invalid intent\" }, { status: 400 });\r\n }\r\n\r\n } catch (error) {\r\n return json({\r\n success: false,\r\n error: error instanceof Error ? error.message : \"Unknown error\"\r\n }, { status: 500 });\r\n }\r\n}\r\n\r\nexport async function loader({ request }: LoaderArgs) {\r\n const session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\");\r\n const user = await eP.user.all(email)\r\n if (!user) { return redirect(import.meta.env.VITE_LOGIN); }\r\n\r\n return json({ user })\r\n}\r\n\r\nexport const meta: MetaFunction = () => {\r\n return [\r\n { title: \"Dashboard - Catalyst\" },\r\n { name: \"description\", content: \"Catalyst software dashboard.\" },\r\n ];\r\n};"
|
|
3228
|
+
],
|
|
3229
|
+
"description": "",
|
|
3230
|
+
"scope": "jsx / tsx"
|
|
3231
|
+
},
|
|
3232
|
+
"use_hydrated": {
|
|
3233
|
+
"prefix": "use_hydrated",
|
|
3234
|
+
"body": [
|
|
3235
|
+
"import { useSyncExternalStore } from \"react\";\r\n\r\nfunction subscribe() {\r\n\t// biome-ignore lint/suspicious/noEmptyBlockStatements: Mock function\r\n\treturn () => {};\r\n}\r\n\r\n/**\r\n * Return a boolean indicating if the JS has been hydrated already.\r\n * When doing Server-Side Rendering, the result will always be false.\r\n * When doing Client-Side Rendering, the result will always be false on the\r\n * first render and true from then on. Even if a new component renders it will\r\n * always start with true.\r\n *\r\n * Example: Disable a button that needs JS to work.\r\n */\r\nexport function useHydrated() {\r\n\treturn useSyncExternalStore(\r\n\t\tsubscribe,\r\n\t\t() => true,\r\n\t\t() => false,\r\n\t);\r\n}"
|
|
3236
|
+
],
|
|
3237
|
+
"description": "",
|
|
3238
|
+
"scope": "jsx / tsx"
|
|
3239
|
+
},
|
|
3240
|
+
"themed_scrollbar": {
|
|
3241
|
+
"prefix": "themed_scrollbar",
|
|
3242
|
+
"body": [
|
|
3243
|
+
"/* scroll bar */\n::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n::-webkit-scrollbar-track {\n background-color: hsl(var(--muted));\n border-radius: 0.25rem;\n\n}\n\n::-webkit-scrollbar-thumb {\n background-color: hsl(var(--primary) / 0.3);\n border-radius: 0.25rem;\n}\n\n::-webkit-scrollbar-thumb:hover {\n background-color:hsl(var(--primary));\n}"
|
|
3244
|
+
],
|
|
3245
|
+
"description": "",
|
|
3246
|
+
"scope": "jsx / tsx"
|
|
3247
|
+
},
|
|
3248
|
+
"client_only_without_remix_utils": {
|
|
3249
|
+
"prefix": "client_only_without_remix_utils",
|
|
3250
|
+
"body": [
|
|
3251
|
+
"client-only',\r\n template: `import * as React from \"react\";\r\nimport { useHydrated } from \"./use-hydrated\";\r\n\r\ntype Props = {\r\n\t/**\r\n\t * You are encouraged to add a fallback that is the same dimensions\r\n\t * as the client rendered children. This will avoid content layout\r\n\t * shift which is disgusting\r\n\t */\r\n\tchildren(): React.ReactNode;\r\n\tfallback?: React.ReactNode;\r\n};\r\n\r\n/**\r\n * Render the children only after the JS has loaded client-side. Use an optional\r\n * fallback component if the JS is not yet loaded.\r\n *\r\n * Example: Render a Chart component if JS loads, renders a simple FakeChart\r\n * component server-side or if there is no JS. The FakeChart can have only the\r\n * UI without the behavior or be a loading spinner or skeleton.\r\n * <ClientOnly fallback={<FakeChart />}>\r\n * {() => <Chart />}\r\n * </ClientOnly>\r\n */\r\nexport function ClientOnly({ children, fallback = null }: Props) {\r\n\treturn useHydrated() ? <>{children()}</> : <>{fallback}</>;\r\n}"
|
|
3252
|
+
],
|
|
3253
|
+
"description": "",
|
|
3254
|
+
"scope": "jsx / tsx"
|
|
3255
|
+
},
|
|
3256
|
+
"search_with_fuse_js": {
|
|
3257
|
+
"prefix": "search_with_fuse_js",
|
|
3258
|
+
"body": [
|
|
3259
|
+
"const searchRef = useRef()\r\n const [list, setLists] = useState()\r\n <div className=\"relative ml-auto flex-1 md:grow-0\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n ref={searchRef}\r\n type=\"search\"\r\n name=\"q\"\r\n onChange={(e) => {\r\n let q = e.currentTarget.value\r\n if (!q) return [];\r\n const searchThrough = galleryImages\r\n const options = { keys: ['year', 'brand', 'model', 'name'], threshold: 0.3, ignoreLocation: true, includeScore: true };\r\n const fuse = new Fuse(searchThrough, options);\r\n const searchResults = fuse.search(q);\r\n const items = searchResults.map(result => result.item);\r\n setList(items)\r\n }}\r\n autoFocus\r\n className=\"w-full rounded-[0px] border-x-none border-t-none bg-background pl-8\"\r\n />\r\n <Button onClick={() => { setList(note) }} size=\"sm\" variant=\"ghost\" className=\"absolute right-2 top-1/2 transform -translate-y-1/2 bg-transparent hover:bg-transparent text-muted-foreground\" >\r\n <X />\r\n </Button>\r\n </div>"
|
|
3260
|
+
],
|
|
3261
|
+
"description": "",
|
|
3262
|
+
"scope": "jsx / tsx"
|
|
3263
|
+
},
|
|
3264
|
+
"search_with_filter": {
|
|
3265
|
+
"prefix": "search_with_filter",
|
|
3266
|
+
"body": [
|
|
3267
|
+
"const searchRef = useRef()\r\n const [list, setLists] = useState()\r\n <div className=\"relative ml-auto flex-1 md:grow-0\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n ref={searchRef}\r\n type=\"search\"\r\n name=\"q\"\r\n onChange={(e) => {\r\n let q = e.currentTarget.value;\r\n if (!q) return setList(t?.FinanceNote);\r\n q = q.toLowerCase();\r\n const getit = products;\r\n const result = getit.filter(\r\n (result) =>\r\n result.body?.toLowerCase().includes(q) ||\r\n result.createdAt?.toLowerCase().includes(q) ||\r\n result.userEmail?.toLowerCase().includes(q) ||\r\n result.userName?.toLowerCase().includes(q)\r\n );\r\n setList(result);\r\n }}\r\n autoFocus\r\n className=\"w-full rounded-[0px] border-x-none border-t-none bg-background pl-8\"\r\n />\r\n <Button onClick={() => { setList(note) }} size=\"sm\" variant=\"ghost\" className=\"absolute right-2 top-1/2 transform -translate-y-1/2 bg-transparent hover:bg-transparent text-muted-foreground\" >\r\n <X />\r\n </Button>\r\n </div>"
|
|
3268
|
+
],
|
|
3269
|
+
"description": "",
|
|
3270
|
+
"scope": "jsx / tsx"
|
|
3271
|
+
},
|
|
3272
|
+
"stock_command_with_map": {
|
|
3273
|
+
"prefix": "stock_command_with_map",
|
|
3274
|
+
"body": [
|
|
3275
|
+
"const searchRef = useRef()\r\n const [list, setLists] = useState()\r\n <Command className=\"rounded-lg border shadow-md\">\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <CommandInput className=\"pl-3\" placeholder=\"Search clients...\" />\r\n </div>\r\n <CommandList>\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n <CommandGroup heading=\"Clients\">\r\n {clients.map((item, index) => (\r\n <CommandItem\r\n key={index}\r\n onSelect={() => setClient(item)}\r\n className='flex flex-col items-start gap-1 p-3'\r\n >\r\n <span className=\"font-medium\">{item.firstName} {item.lastName}</span>\r\n <span className='text-sm text-muted-foreground'>{item.email}</span>\r\n </CommandItem>\r\n ))}\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>"
|
|
3276
|
+
],
|
|
3277
|
+
"description": "",
|
|
3278
|
+
"scope": "jsx / tsx"
|
|
3279
|
+
},
|
|
3280
|
+
"command_with_search": {
|
|
3281
|
+
"prefix": "command_with_search",
|
|
3282
|
+
"body": [
|
|
3283
|
+
"const searchRef = useRef()\r\n const [list, setLists] = useState()\r\n <Command className=\"rounded-[0px] border border-border shadow-md mb-5 flex flex-col max-h-[450px] overflow-y-auto\">\r\n <div className=\"relative ml-auto flex-1 md:grow-0\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n ref={searchRef}\r\n type=\"search\"\r\n name=\"q\"\r\n onChange={(e) => {\r\n let q = e.currentTarget.value;\r\n if (!q) return setList(t?.FinanceNote);\r\n q = q.toLowerCase();\r\n const getit = products;\r\n const result = getit.filter(\r\n (result) =>\r\n result.body?.toLowerCase().includes(q) ||\r\n result.createdAt?.toLowerCase().includes(q) ||\r\n result.userEmail?.toLowerCase().includes(q) ||\r\n result.userName?.toLowerCase().includes(q)\r\n );\r\n setList(result);\r\n }}\r\n autoFocus\r\n className=\"w-full rounded-[0px] border-x-none border-t-none bg-background pl-8\"\r\n />\r\n <Button onClick={() => { setList(note) }} size=\"sm\" variant=\"ghost\" className=\"absolute right-2 top-1/2 transform -translate-y-1/2 bg-transparent hover:bg-transparent text-muted-foreground\" >\r\n <X />\r\n </Button>\r\n </div>\r\n <CommandList className=\"overflow-y-auto overflow-x-clip min-h-0 flex-grow\">\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n <CommandGroup heading=\"Notes\">\r\n {list.map((r, index) => (\r\n <CommandItem key={index}>\r\n <Search className=\"mr-2 h-4 w-4\" />\r\n <span>Search</span>\r\n </CommandItem>\r\n ))}\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>"
|
|
3284
|
+
],
|
|
3285
|
+
"description": "",
|
|
3286
|
+
"scope": "jsx / tsx"
|
|
3287
|
+
},
|
|
3288
|
+
"auth_design_page": {
|
|
3289
|
+
"prefix": "auth_design_page",
|
|
3290
|
+
"body": [
|
|
3291
|
+
"<div className=\"bg-background flex min-h-[60vh] flex-col items-start justify-center gap-6 p-6 md:p-10\">\r\n <div className=\"w-full max-w-sm\">\r\n <div className=\"flex flex-col gap-6\" >\r\n <div className=\"flex flex-col gap-6\">\r\n <div className=\"flex flex-col items-center gap-2\">\r\n <div className=\"flex size-8 items-center justify-center rounded-md\">\r\n <Banknote className=\"size-6\" />\r\n </div>\r\n <h1 className=\"text-xl font-bold\">Finance Buffer</h1>\r\n <div className=\"text-center text-sm\">\r\n Adds a monetary buffer to contracts. Some dealers do this, while other do not. It's not necessary, and you have to keep this in mind when finalizing contracts.\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-6\">\r\n <fetcher.Form method='post' >\r\n <div className=\"grid w-full max-w-sm items-center gap-3\">\r\n <Label>Buffer</Label>\r\n <Input name='financeBuffer' defaultValue={d.financeBuffer} />\r\n </div>\r\n <ButtonStyled value='buffer' >\r\n Save\r\n </ButtonStyled>\r\n </fetcher.Form>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>"
|
|
3292
|
+
],
|
|
3293
|
+
"description": "",
|
|
3294
|
+
"scope": "jsx / tsx"
|
|
3295
|
+
},
|
|
3296
|
+
"prevstate": {
|
|
3297
|
+
"prefix": "prevstate",
|
|
3298
|
+
"body": [
|
|
3299
|
+
"const [data, setData] = useState((prev) => !prev);"
|
|
3300
|
+
],
|
|
3301
|
+
"description": "",
|
|
3302
|
+
"scope": "jsx / tsx"
|
|
3303
|
+
},
|
|
3304
|
+
"command_with_pagination": {
|
|
3305
|
+
"prefix": "command_with_pagination",
|
|
3306
|
+
"body": [
|
|
3307
|
+
"function EmailTemplateCommand({ templates, setTextValue, textValue }) {\r\n const [search, setSearch] = useState('')\r\n const [pages, setPages] = useState([])\r\n const [selectedCategory, setSelectedCategory] = useState(null)\r\n const page = pages[pages.length - 1]\r\n\r\n const categories = Array.from(new Set(templates.map(t => t.category)))\r\n\r\n const subCategories = templates\r\n .filter(t => t.category === selectedCategory)\r\n .map(t => t.subCat)\r\n .filter((value, index, self) => self.indexOf(value) === index)\r\n return (\r\n <Command className=\"rounded-lg border shadow-md md:min-w-[450px]\">\r\n <CommandInput placeholder=\"Search templates...\" value={search} onValueChange={setSearch} />\r\n <CommandList>\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n {!page && (\r\n <CommandGroup heading=\"Categories\">\r\n {categories.map((category) => (\r\n <CommandItem key={category}\r\n onSelect={() => {\r\n setSelectedCategory(category)\r\n setPages([...pages, category])\r\n }} >\r\n {category}\r\n </CommandItem>\r\n ))}\r\n </CommandGroup>\r\n )}\r\n {page && selectedCategory && (\r\n <CommandGroup heading={'$ {selectedCategory}'}>\r\n {subCategories.map((subCat) => (\r\n <TooltipProvider>\r\n <Tooltip key={subCat}>\r\n <TooltipTrigger asChild>\r\n <CommandItem onSelect={() => {\r\n const selectedTemplate = templates.find(t => t.category === selectedCategory && t.subCat === subCat)\r\n if (selectedTemplate) {\r\n console.log('Selected template:', selectedTemplate)\r\n setTextValue('$ {textValue} $ {selectedTemplate.body}')\r\n }\r\n }} >\r\n {subCat}\r\n </CommandItem>\r\n </TooltipTrigger>\r\n <TooltipContent\r\n className=\"max-w-md p-4 bg-white border shadow-lg\"\r\n side=\"top\"\r\n align=\"start\"\r\n >\r\n <div className=\"space-y-3\">\r\n {/* Header */}\r\n <div className=\"flex items-center gap-2 pb-2 border-b\">\r\n <Mail className=\"h-4 w-4 text-blue-600\" />\r\n <span className=\"font-semibold text-gray-900\">Email Template</span>\r\n </div>\r\n\r\n {/* Category */}\r\n <div className=\"flex items-start gap-2\">\r\n <Tag className=\"h-4 w-4 text-green-600 mt-0.5 flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-xs font-medium text-gray-500 uppercase tracking-wide\">Category</span>\r\n <p className=\"text-sm font-medium text-gray-900\">{template.category}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Sub Category */}\r\n <div className=\"flex items-start gap-2\">\r\n <Tag className=\"h-4 w-4 text-orange-600 mt-0.5 flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-xs font-medium text-gray-500 uppercase tracking-wide\">Sub Category</span>\r\n <p className=\"text-sm font-medium text-gray-900\">{template.subCat}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"flex items-start gap-2\">\r\n <FileText className=\"h-4 w-4 text-purple-600 mt-0.5 flex-shrink-0\" />\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"text-xs font-medium text-gray-500 uppercase tracking-wide\">Template Body</span>\r\n <div className=\"mt-1 p-2 bg-gray-50 rounded text-xs text-gray-700 max-h-32 overflow-y-auto\">\r\n <pre className=\"whitespace-pre-wrap font-sans\">{template.body}</pre>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </TooltipContent>\r\n </Tooltip>\r\n </TooltipProvider>\r\n\r\n ))}\r\n </CommandGroup>\r\n )}\r\n\r\n {/* Back button when in subcategory view */}\r\n {page && (\r\n <CommandGroup>\r\n <CommandItem\r\n onSelect={() => setPages(pages.slice(0, -1))}\r\n className=\"text-muted-foreground\"\r\n >\r\n ← Back to categories\r\n </CommandItem>\r\n </CommandGroup>\r\n )}\r\n </CommandList>\r\n </Command>\r\n )\r\n }"
|
|
3308
|
+
],
|
|
3309
|
+
"description": "",
|
|
3310
|
+
"scope": "jsx / tsx"
|
|
3311
|
+
},
|
|
3312
|
+
"fetch_w_state_and_useeffect": {
|
|
3313
|
+
"prefix": "fetch_w_state_and_useeffect",
|
|
3314
|
+
"body": [
|
|
3315
|
+
"const [scripts, setScripts] = useState([]);\r\n \r\n async function fetchServiceData() {\r\n const response = await axios.get('/portal/api/sidebar/workorder');\r\n if (response.status !== 200) { return { error: \"Failed to fetch data.\" }; }\r\n const data = response.data\r\n setScripts(data)\r\n return null;\r\n }\r\n useEffect(() => {\r\n fetchServiceData()\r\n }, []);"
|
|
3316
|
+
],
|
|
3317
|
+
"description": "",
|
|
3318
|
+
"scope": "jsx / tsx"
|
|
3319
|
+
},
|
|
3320
|
+
"designed_button_classname": {
|
|
3321
|
+
"prefix": "designed_button_classname",
|
|
3322
|
+
"body": [
|
|
3323
|
+
"className={cn(\r\n \"bg-background relative rounded-md p-3 pl-6 text-sm cursor-pointer transition-colors hover:ring-2 hover:ring-blue-200\",\r\n \"after:bg-[#155dfc] after:absolute after:inset-y-2 after:right-2 after:w-1 after:rounded-full\",\r\n selectedChat?.id === chat.id ? \"bg-background ring-2 ring-blue-200\" : \"hover:bg-background\",\r\n chat.completed === true && \"opacity-60 after:bg-green-500\",\r\n new Date(Date.parse(chat.start)) < new Date() && \"opacity-60 after:bg-red-500\"\r\n )}"
|
|
3324
|
+
],
|
|
3325
|
+
"description": "",
|
|
3326
|
+
"scope": "jsx / tsx"
|
|
3327
|
+
},
|
|
3328
|
+
"fuse_input_w_x": {
|
|
3329
|
+
"prefix": "fuse_input_w_x",
|
|
3330
|
+
"body": [
|
|
3331
|
+
"<div className=\"relative group\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n onChange={(e) => {\r\n let q = e.currentTarget.value\r\n if (!q) return [];\r\n const options = { \r\n keys: ['clientName', 'clientEmail', 'clientPhone', 'messages.text'], \r\n threshold: 0.2, \r\n ignoreLocation: true, \r\n includeScore: true \r\n };\r\n const fuse = new Fuse(chats, options);\r\n const searchResults = fuse.search(q);\r\n setChatsList(searchResults.map(result => result.item))\r\n }}\r\n className=\"w-full pl-8 focus:pr-8 group-hover:pr-8\"\r\n />\r\n <Button\r\n className='absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity'\r\n size='icon'\r\n variant='ghost'\r\n onClick={() => {\r\n setChatsList(chats || [])\r\n }}\r\n >\r\n <X />\r\n </Button>\r\n </div>"
|
|
3332
|
+
],
|
|
3333
|
+
"description": "",
|
|
3334
|
+
"scope": "jsx / tsx"
|
|
3335
|
+
},
|
|
3336
|
+
"buttonstyled": {
|
|
3337
|
+
"prefix": "buttonstyled",
|
|
3338
|
+
"body": [
|
|
3339
|
+
"<ButtonStyled \n value='intentsValue'\n onClick={() => onSave()} >\n Save \n</ButtonStyled>"
|
|
3340
|
+
],
|
|
3341
|
+
"description": "",
|
|
3342
|
+
"scope": "jsx / tsx"
|
|
3343
|
+
},
|
|
3344
|
+
"input": {
|
|
3345
|
+
"prefix": "input",
|
|
3346
|
+
"body": [
|
|
3347
|
+
"<div className=\"grid w-full max-w-sm items-center gap-1.5\">\r\n <Label>Email</Label>\r\n <Input name=\"email\" value={email} />\r\n </div>"
|
|
3348
|
+
],
|
|
3349
|
+
"description": "",
|
|
3350
|
+
"scope": "jsx / tsx"
|
|
3351
|
+
},
|
|
3352
|
+
"card": {
|
|
3353
|
+
"prefix": "card",
|
|
3354
|
+
"body": [
|
|
3355
|
+
"<Card>\r\n <CardHeader>\r\n <CardTitle>Card Title</CardTitle>\r\n <CardDescription>Card Description</CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <p>Card Content</p>\r\n </CardContent>\r\n <CardFooter>\r\n <p>Card Footer</p>\r\n </CardFooter>\r\n </Card>"
|
|
3356
|
+
],
|
|
3357
|
+
"description": "",
|
|
3358
|
+
"scope": "jsx / tsx"
|
|
3359
|
+
},
|
|
3360
|
+
"dialog": {
|
|
3361
|
+
"prefix": "dialog",
|
|
3362
|
+
"body": [
|
|
3363
|
+
"<Dialog>\r\n <DialogTrigger asChild>\r\n <Button variant=\"outline\">Open Dialog</Button>\r\n </DialogTrigger>\r\n <DialogContent className=\"sm:max-w-[425px]\">\r\n <DialogHeader>\r\n <DialogTitle>Edit profile</DialogTitle>\r\n <DialogDescription>\r\n Make changes to your profile here. Click save when you're done.\r\n </DialogDescription>\r\n </DialogHeader>\r\n <div className=\"grid gap-4 py-4\">\r\n <div className=\"grid grid-cols-4 items-center gap-4\">\r\n <Label htmlFor=\"name\" className=\"text-right\">\r\n Name\r\n </Label>\r\n <Input id=\"name\" value=\"Pedro Duarte\" className=\"col-span-3\" />\r\n </div>\r\n </div>\r\n <DialogFooter>\r\n <Button type=\"submit\">Save changes</Button>\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>"
|
|
3364
|
+
],
|
|
3365
|
+
"description": "",
|
|
3366
|
+
"scope": "jsx / tsx"
|
|
3367
|
+
},
|
|
3368
|
+
"fetcher_form": {
|
|
3369
|
+
"prefix": "fetcher_form",
|
|
3370
|
+
"body": [
|
|
3371
|
+
"<fetcher.Form method='post' className=\"space-y-8\">\r\n <div className=\"grid w-full max-w-sm items-center gap-1.5\">\r\n <Label>Email</Label>\r\n <Input name=\"email\" value={email} />\r\n </div>\r\n <Button type=\"submit\">Submit</Button>\r\n </fetcher.Form>"
|
|
3372
|
+
],
|
|
3373
|
+
"description": "",
|
|
3374
|
+
"scope": "jsx / tsx"
|
|
3375
|
+
},
|
|
3376
|
+
"select": {
|
|
3377
|
+
"prefix": "select",
|
|
3378
|
+
"body": [
|
|
3379
|
+
"<div className=\"grid w-full max-w-sm items-center gap-1.5\">\r\n <Label>Dept</Label>\r\n <Select value={dept} onValueChange={(value) => {\r\n setDept(value)\r\n }}>\r\n <SelectTrigger >\r\n <SelectValue />\r\n </SelectTrigger>\r\n <SelectContent>\r\n <SelectItem value=\"Sales\">Sales</SelectItem>\r\n <SelectItem value=\"Service\">Service</SelectItem>\r\n <SelectItem value=\"PAC\">PAC</SelectItem>\r\n <SelectItem value=\"Office\">Office</SelectItem>\r\n </SelectContent>\r\n </Select>\r\n </div>"
|
|
3380
|
+
],
|
|
3381
|
+
"description": "",
|
|
3382
|
+
"scope": "jsx / tsx"
|
|
3383
|
+
},
|
|
3384
|
+
"table": {
|
|
3385
|
+
"prefix": "table",
|
|
3386
|
+
"body": [
|
|
3387
|
+
"<Table>\r\n <TableCaption>A list of your recent invoices.</TableCaption>\r\n <TableHeader>\r\n <TableRow>\r\n <TableHead className=\"w-[100px]\">Invoice</TableHead>\r\n <TableHead>Status</TableHead>\r\n <TableHead>Method</TableHead>\r\n <TableHead className=\"text-right\">Amount</TableHead>\r\n </TableRow>\r\n </TableHeader>\r\n <TableBody>\r\n <TableRow>\r\n <TableCell className=\"font-medium\">INV001</TableCell>\r\n <TableCell>Paid</TableCell>\r\n <TableCell>Credit Card</TableCell>\r\n <TableCell className=\"text-right\">$250.00</TableCell>\r\n </TableRow>\r\n </TableBody>\r\n </Table>"
|
|
3388
|
+
],
|
|
3389
|
+
"description": "",
|
|
3390
|
+
"scope": "jsx / tsx"
|
|
3391
|
+
},
|
|
3392
|
+
"tabs": {
|
|
3393
|
+
"prefix": "tabs",
|
|
3394
|
+
"body": [
|
|
3395
|
+
"<Tabs defaultValue=\"account\">\r\n <TabsList>\r\n <TabsTrigger value=\"account\">Account</TabsTrigger>\r\n <TabsTrigger value=\"password\">Password</TabsTrigger>\r\n </TabsList>\r\n <TabsContent value=\"account\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>Account</CardTitle>\r\n <CardDescription>\r\n Make changes to your account here. Click save when you're done.\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-2\">\r\n <div className=\"space-y-1\">\r\n <Label htmlFor=\"name\">Name</Label>\r\n <Input id=\"name\" defaultValue=\"Pedro Duarte\" />\r\n </div>\r\n </CardContent>\r\n <CardFooter>\r\n <Button>Save changes</Button>\r\n </CardFooter>\r\n </Card>\r\n </TabsContent>\r\n <TabsContent value=\"password\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>Password</CardTitle>\r\n <CardDescription>\r\n Change your password here. After saving, you'll be logged out.\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-2\">\r\n <div className=\"space-y-1\">\r\n <Label htmlFor=\"current\">Current password</Label>\r\n <Input id=\"current\" type=\"password\" />\r\n </div>\r\n </CardContent>\r\n <CardFooter>\r\n <Button>Save password</Button>\r\n </CardFooter>\r\n </Card>\r\n </TabsContent>\r\n </Tabs>"
|
|
3396
|
+
],
|
|
3397
|
+
"description": "",
|
|
3398
|
+
"scope": "jsx / tsx"
|
|
3399
|
+
},
|
|
3400
|
+
"alert": {
|
|
3401
|
+
"prefix": "alert",
|
|
3402
|
+
"body": [
|
|
3403
|
+
"<Alert>\r\n <AlertCircle className=\"h-4 w-4\" />\r\n <AlertTitle>Heads up!</AlertTitle>\r\n <AlertDescription>\r\n You can add components to your app using the cli.\r\n </AlertDescription>\r\n </Alert>"
|
|
3404
|
+
],
|
|
3405
|
+
"description": "",
|
|
3406
|
+
"scope": "jsx / tsx"
|
|
3407
|
+
},
|
|
3408
|
+
"badge": {
|
|
3409
|
+
"prefix": "badge",
|
|
3410
|
+
"body": [
|
|
3411
|
+
"<Badge variant=\"default\">Badge</Badge>"
|
|
3412
|
+
],
|
|
3413
|
+
"description": "",
|
|
3414
|
+
"scope": "jsx / tsx"
|
|
3415
|
+
},
|
|
3416
|
+
"checkbox": {
|
|
3417
|
+
"prefix": "checkbox",
|
|
3418
|
+
"body": [
|
|
3419
|
+
"<div className=\"flex items-center space-x-2\">\r\n <Checkbox name=\"inPerson\" checked={selectedMethod === \"inPerson\"} onCheckedChange={() => handleCheckboxChange(\"inPerson\")} />\r\n <Label>In Person</Label>\r\n </div>"
|
|
3420
|
+
],
|
|
3421
|
+
"description": "",
|
|
3422
|
+
"scope": "jsx / tsx"
|
|
3423
|
+
},
|
|
3424
|
+
"textarea": {
|
|
3425
|
+
"prefix": "textarea",
|
|
3426
|
+
"body": [
|
|
3427
|
+
"<div className=\"grid w-full gap-1.5\">\r\n <Label htmlFor=\"message\">Your message</Label>\r\n <Textarea placeholder=\"Type your message here.\" id=\"message\" />\r\n </div>"
|
|
3428
|
+
],
|
|
3429
|
+
"description": "",
|
|
3430
|
+
"scope": "jsx / tsx"
|
|
3431
|
+
},
|
|
3432
|
+
"toast": {
|
|
3433
|
+
"prefix": "toast",
|
|
3434
|
+
"body": [
|
|
3435
|
+
"toast.success('A Sonner toast', {\r\n className: 'my-classname',\r\n description: 'With a description and an icon',\r\n duration: 5000,\r\n icon: <MyIcon />,\r\n action: {\r\n label: 'Action',\r\n onClick: () => console.log('Action!'),\r\n },\r\n cancel: {\r\n label: 'Cancel',\r\n onClick: () => console.log('Cancel!'),\r\n },\r\n });\r\n toast.loading('Loading…');"
|
|
3436
|
+
],
|
|
3437
|
+
"description": "",
|
|
3438
|
+
"scope": "jsx / tsx"
|
|
3439
|
+
},
|
|
3440
|
+
"sheet": {
|
|
3441
|
+
"prefix": "sheet",
|
|
3442
|
+
"body": [
|
|
3443
|
+
"<Sheet>\r\n <SheetTrigger asChild>\r\n <Button variant=\"outline\">Open Sheet</Button>\r\n </SheetTrigger>\r\n <SheetContent>\r\n <SheetHeader>\r\n <SheetTitle>Edit profile</SheetTitle>\r\n <SheetDescription>\r\n Make changes to your profile here. Click save when you're done.\r\n </SheetDescription>\r\n </SheetHeader>\r\n <div className=\"grid gap-4 py-4\">\r\n <div className=\"grid grid-cols-4 items-center gap-4\">\r\n <Label htmlFor=\"name\" className=\"text-right\">\r\n Name\r\n </Label>\r\n <Input id=\"name\" value=\"Pedro Duarte\" className=\"col-span-3\" />\r\n </div>\r\n </div>\r\n <SheetFooter>\r\n <SheetClose asChild>\r\n <Button type=\"submit\">Save changes</Button>\r\n </SheetClose>\r\n </SheetFooter>\r\n </SheetContent>\r\n </Sheet>"
|
|
3444
|
+
],
|
|
3445
|
+
"description": "",
|
|
3446
|
+
"scope": "jsx / tsx"
|
|
3447
|
+
},
|
|
3448
|
+
"accordian": {
|
|
3449
|
+
"prefix": "accordian",
|
|
3450
|
+
"body": [
|
|
3451
|
+
"<Accordion type=\"single\" collapsible className=\"w-full\">\r\n <AccordionItem value=\"item-1\">\r\n <AccordionTrigger>Is it accessible?</AccordionTrigger>\r\n <AccordionContent>\r\n Yes. It adheres to the WAI-ARIA design pattern.\r\n </AccordionContent>\r\n </AccordionItem>\r\n <AccordionItem value=\"item-2\">\r\n <AccordionTrigger>Is it styled?</AccordionTrigger>\r\n <AccordionContent>\r\n Yes. It comes with default styles that matches the other components' aesthetic.\r\n </AccordionContent>\r\n </AccordionItem>\r\n </Accordion>"
|
|
3452
|
+
],
|
|
3453
|
+
"description": "",
|
|
3454
|
+
"scope": "jsx / tsx"
|
|
3455
|
+
},
|
|
3456
|
+
"basic_command": {
|
|
3457
|
+
"prefix": "basic_command",
|
|
3458
|
+
"body": [
|
|
3459
|
+
"<Command>\r\n <CommandInput placeholder=\"Type a command or search...\" />\r\n <CommandList>\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n <CommandGroup heading=\"Suggestions\">\r\n <CommandItem>\r\n <Search className=\"mr-2 h-4 w-4\" />\r\n <span>Search</span>\r\n </CommandItem>\r\n <CommandItem>\r\n <Settings className=\"mr-2 h-4 w-4\" />\r\n <span>Settings</span>\r\n </CommandItem>\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>"
|
|
3460
|
+
],
|
|
3461
|
+
"description": "",
|
|
3462
|
+
"scope": "jsx / tsx"
|
|
3463
|
+
},
|
|
3464
|
+
"combobox": {
|
|
3465
|
+
"prefix": "combobox",
|
|
3466
|
+
"body": [
|
|
3467
|
+
"const [open, setOpen] = React.useState(false)\r\n const [value, setValue] = React.useState(\"\")\r\n \r\n <Popover>\r\n <PopoverTrigger asChild>\r\n <Button\r\n variant=\"outline\"\r\n role=\"combobox\"\r\n className=\"w-[200px] justify-between\"\r\n >\r\n Select framework...\r\n <ChevronsUpDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-[200px] p-0\">\r\n <Command>\r\n <CommandInput placeholder=\"Search framework...\" />\r\n <CommandEmpty>No framework found.</CommandEmpty>\r\n <CommandGroup>\r\n <CommandItem>\r\n <Check className=\"mr-2 h-4 w-4\" />\r\n Next.js\r\n </CommandItem>\r\n <CommandItem>\r\n <Check className=\"mr-2 h-4 w-4\" />\r\n SvelteKit\r\n </CommandItem>\r\n </CommandGroup>\r\n </Command>\r\n </PopoverContent>\r\n </Popover>"
|
|
3468
|
+
],
|
|
3469
|
+
"description": "",
|
|
3470
|
+
"scope": "jsx / tsx"
|
|
3471
|
+
},
|
|
3472
|
+
"bar_chart": {
|
|
3473
|
+
"prefix": "bar_chart",
|
|
3474
|
+
"body": [
|
|
3475
|
+
"import { TrendingUp } from \"lucide-react\"\r\nimport { Bar, BarChart, CartesianGrid, XAxis } from \"recharts\"\r\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from \"~/components/ui/card\"\r\nimport { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent,} from \"~/components/ui/chart\"\r\n\r\nexport const description = \"A bar chart\"\r\n\r\nconst chartData = [\r\n { month: \"January\", desktop: 186 },\r\n { month: \"February\", desktop: 305 },\r\n { month: \"March\", desktop: 237 },\r\n { month: \"April\", desktop: 73 },\r\n { month: \"May\", desktop: 209 },\r\n { month: \"June\", desktop: 214 },\r\n]\r\n\r\nconst chartConfig = {\r\n desktop: {\r\n label: \"Desktop\",\r\n color: \"var(--chart-1)\",\r\n },\r\n} satisfies ChartConfig\r\n\r\nexport function ChartBarDefault() {\r\n return (\r\n <Card>\r\n <CardHeader>\r\n <CardTitle>Bar Chart</CardTitle>\r\n <CardDescription>January - June 2024</CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <ChartContainer config={chartConfig}>\r\n <BarChart accessibilityLayer data={chartData}>\r\n <CartesianGrid vertical={false} />\r\n <XAxis\r\n dataKey=\"month\"\r\n tickLine={false}\r\n tickMargin={10}\r\n axisLine={false}\r\n tickFormatter={(value) => value.slice(0, 3)}\r\n />\r\n <ChartTooltip\r\n cursor={false}\r\n content={<ChartTooltipContent hideLabel />}\r\n />\r\n <Bar dataKey=\"desktop\" fill=\"var(--color-desktop)\" radius={8} />\r\n </BarChart>\r\n </ChartContainer>\r\n </CardContent>\r\n <CardFooter className=\"flex-col items-start gap-2 text-sm\">\r\n <div className=\"flex gap-2 leading-none font-medium\">\r\n Trending up by 5.2% this month <TrendingUp className=\"h-4 w-4\" />\r\n </div>\r\n <div className=\"text-muted-foreground leading-none\">\r\n Showing total visitors for the last 6 months\r\n </div>\r\n </CardFooter>\r\n </Card>\r\n )\r\n}"
|
|
3476
|
+
],
|
|
3477
|
+
"description": "",
|
|
3478
|
+
"scope": "jsx / tsx"
|
|
3479
|
+
},
|
|
3480
|
+
"drawer": {
|
|
3481
|
+
"prefix": "drawer",
|
|
3482
|
+
"body": [
|
|
3483
|
+
"<Drawer>\r\n <DrawerTrigger asChild>\r\n <Button variant=\"outline\">Open Drawer</Button>\r\n </DrawerTrigger>\r\n <DrawerContent>\r\n <div className=\"mx-auto w-full max-w-sm\">\r\n <DrawerHeader>\r\n <DrawerTitle>Are you absolutely sure?</DrawerTitle>\r\n <DrawerDescription>This action cannot be undone.</DrawerDescription>\r\n </DrawerHeader>\r\n <DrawerFooter>\r\n <Button>Submit</Button>\r\n <DrawerClose asChild>\r\n <Button variant=\"outline\">Cancel</Button>\r\n </DrawerClose>\r\n </DrawerFooter>\r\n </div>\r\n </DrawerContent>\r\n</Drawer>"
|
|
3484
|
+
],
|
|
3485
|
+
"description": "",
|
|
3486
|
+
"scope": "jsx / tsx"
|
|
3487
|
+
},
|
|
3488
|
+
"dropdown": {
|
|
3489
|
+
"prefix": "dropdown",
|
|
3490
|
+
"body": [
|
|
3491
|
+
"<DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button variant=\"outline\">Open</Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent className=\"w-56\">\r\n <DropdownMenuLabel>My Account</DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuGroup>\r\n <DropdownMenuItem>\r\n <User className=\"mr-2 h-4 w-4\" />\r\n <span>Profile</span>\r\n </DropdownMenuItem>\r\n <DropdownMenuItem>\r\n <Settings className=\"mr-2 h-4 w-4\" />\r\n <span>Settings</span>\r\n </DropdownMenuItem>\r\n </DropdownMenuGroup>\r\n </DropdownMenuContent>\r\n</DropdownMenu>"
|
|
3492
|
+
],
|
|
3493
|
+
"description": "",
|
|
3494
|
+
"scope": "jsx / tsx"
|
|
3495
|
+
},
|
|
3496
|
+
"hovercard": {
|
|
3497
|
+
"prefix": "hovercard",
|
|
3498
|
+
"body": [
|
|
3499
|
+
"<HoverCard>\r\n <HoverCardTrigger asChild>\r\n <Button variant=\"link\">@nextjs</Button>\r\n </HoverCardTrigger>\r\n <HoverCardContent className=\"w-80\">\r\n <div className=\"flex justify-between space-x-4\">\r\n <div className=\"space-y-1\">\r\n <h4 className=\"text-sm font-semibold\">@nextjs</h4>\r\n <p className=\"text-sm\">\r\n The React Framework – created and maintained by @vercel.\r\n </p>\r\n </div>\r\n </div>\r\n </HoverCardContent>\r\n</HoverCard>"
|
|
3500
|
+
],
|
|
3501
|
+
"description": "",
|
|
3502
|
+
"scope": "jsx / tsx"
|
|
3503
|
+
},
|
|
3504
|
+
"input_otp": {
|
|
3505
|
+
"prefix": "input_otp",
|
|
3506
|
+
"body": [
|
|
3507
|
+
"<InputOTP maxLength={6}>\r\n <InputOTPGroup>\r\n <InputOTPSlot index={0} />\r\n <InputOTPSlot index={1} />\r\n <InputOTPSlot index={2} />\r\n </InputOTPGroup>\r\n <InputOTPSeparator />\r\n <InputOTPGroup>\r\n <InputOTPSlot index={3} />\r\n <InputOTPSlot index={4} />\r\n <InputOTPSlot index={5} />\r\n </InputOTPGroup>\r\n</InputOTP>"
|
|
3508
|
+
],
|
|
3509
|
+
"description": "",
|
|
3510
|
+
"scope": "jsx / tsx"
|
|
3511
|
+
},
|
|
3512
|
+
"menubar": {
|
|
3513
|
+
"prefix": "menubar",
|
|
3514
|
+
"body": [
|
|
3515
|
+
"<Menubar>\r\n <MenubarMenu>\r\n <MenubarTrigger>File</MenubarTrigger>\r\n <MenubarContent>\r\n <MenubarItem>\r\n New Tab <MenubarShortcut>⌘T</MenubarShortcut>\r\n </MenubarItem>\r\n <MenubarItem>New Window</MenubarItem>\r\n <MenubarSeparator />\r\n <MenubarItem>Share</MenubarItem>\r\n </MenubarContent>\r\n </MenubarMenu>\r\n <MenubarMenu>\r\n <MenubarTrigger>Edit</MenubarTrigger>\r\n <MenubarContent>\r\n <MenubarItem>Undo</MenubarItem>\r\n <MenubarItem>Redo</MenubarItem>\r\n </MenubarContent>\r\n </MenubarMenu>\r\n</Menubar>"
|
|
3516
|
+
],
|
|
3517
|
+
"description": "",
|
|
3518
|
+
"scope": "jsx / tsx"
|
|
3519
|
+
},
|
|
3520
|
+
"popover": {
|
|
3521
|
+
"prefix": "popover",
|
|
3522
|
+
"body": [
|
|
3523
|
+
"<Popover>\r\n <PopoverTrigger asChild>\r\n <Button variant=\"outline\">Open popover</Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-80\">\r\n <div className=\"grid gap-4\">\r\n <div className=\"space-y-2\">\r\n <h4 className=\"font-medium leading-none\">Dimensions</h4>\r\n <p className=\"text-sm text-muted-foreground\">\r\n Set the dimensions for the layer.\r\n </p>\r\n </div>\r\n </div>\r\n </PopoverContent>\r\n</Popover>"
|
|
3524
|
+
],
|
|
3525
|
+
"description": "",
|
|
3526
|
+
"scope": "jsx / tsx"
|
|
3527
|
+
},
|
|
3528
|
+
"tooltip": {
|
|
3529
|
+
"prefix": "tooltip",
|
|
3530
|
+
"body": [
|
|
3531
|
+
"<TooltipProvider>\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button variant=\"outline\">Hover</Button>\r\n </TooltipTrigger>\r\n <TooltipContent>\r\n <p>Add to library</p>\r\n </TooltipContent>\r\n </Tooltip>\r\n</TooltipProvider>"
|
|
3532
|
+
],
|
|
3533
|
+
"description": "",
|
|
3534
|
+
"scope": "jsx / tsx"
|
|
3535
|
+
},
|
|
3536
|
+
"toggle_group": {
|
|
3537
|
+
"prefix": "toggle_group",
|
|
3538
|
+
"body": [
|
|
3539
|
+
"<ToggleGroup type=\"multiple\">\r\n <ToggleGroupItem value=\"bold\">Bold</ToggleGroupItem>\r\n <ToggleGroupItem value=\"italic\">Italic</ToggleGroupItem>\r\n <ToggleGroupItem value=\"underline\">Underline</ToggleGroupItem>\r\n</ToggleGroup>"
|
|
3540
|
+
],
|
|
3541
|
+
"description": "",
|
|
3542
|
+
"scope": "jsx / tsx"
|
|
3543
|
+
},
|
|
3544
|
+
"context_menu": {
|
|
3545
|
+
"prefix": "context_menu",
|
|
3546
|
+
"body": [
|
|
3547
|
+
"<ContextMenu>\r\n <ContextMenuTrigger className=\"flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm\">\r\n Right click here\r\n </ContextMenuTrigger>\r\n <ContextMenuContent className=\"w-64\">\r\n <ContextMenuItem inset>\r\n Back\r\n <ContextMenuShortcut>⌘[</ContextMenuShortcut>\r\n </ContextMenuItem>\r\n <ContextMenuItem inset disabled>\r\n Forward\r\n <ContextMenuShortcut>⌘]</ContextMenuShortcut>\r\n </ContextMenuItem>\r\n <ContextMenuItem inset>\r\n Reload\r\n <ContextMenuShortcut>⌘R</ContextMenuShortcut>\r\n </ContextMenuItem>\r\n <ContextMenuSeparator />\r\n <ContextMenuCheckboxItem checked>\r\n Show Bookmarks Bar\r\n <ContextMenuShortcut>⌘⇧B</ContextMenuShortcut>\r\n </ContextMenuCheckboxItem>\r\n </ContextMenuContent>\r\n</ContextMenu>"
|
|
3548
|
+
],
|
|
3549
|
+
"description": "",
|
|
3550
|
+
"scope": "jsx / tsx"
|
|
3551
|
+
},
|
|
3552
|
+
"command_dialog": {
|
|
3553
|
+
"prefix": "command_dialog",
|
|
3554
|
+
"body": [
|
|
3555
|
+
"export function CommandMenu() {\r\n const [open, setOpen] = useState(false)\r\n\r\n useEffect(() => {\r\n const down = (e: KeyboardEvent) => {\r\n if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\r\n e.preventDefault()\r\n setOpen((open) => !open)\r\n }\r\n }\r\n document.addEventListener(\"keydown\", down)\r\n return () => document.removeEventListener(\"keydown\", down)\r\n }, [])\r\n\r\n return (\r\n <CommandDialog open={open} onOpenChange={setOpen}>\r\n <CommandInput placeholder=\"Type a command or search...\" />\r\n <CommandList>\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n <CommandGroup heading=\"Suggestions\">\r\n <CommandItem>Calendar</CommandItem>\r\n <CommandItem>Search Emoji</CommandItem>\r\n <CommandItem>Calculator</CommandItem>\r\n </CommandGroup>\r\n </CommandList>\r\n </CommandDialog>\r\n )\r\n}"
|
|
3556
|
+
],
|
|
3557
|
+
"description": "",
|
|
3558
|
+
"scope": "jsx / tsx"
|
|
3559
|
+
},
|
|
3560
|
+
"route_file": {
|
|
3561
|
+
"prefix": "route_file",
|
|
3562
|
+
"body": [
|
|
3563
|
+
"import { React, useCallback, useEffect, useMemo, useRef, useState } from 'react';\r\n\timport { NavLink, Outlet, useActionData, useFetcher, useLoaderData, useLocation, useNavigate, useNavigation, useParams, useRouteLoaderData, useSearchParams, useSubmit } from '@remix-run/react';\r\n\timport { eP } from '~/utils/ext';\r\n\timport { authSessionStorage } from '~/sessions/session';\r\n\timport { axios } from 'axios';\r\n\timport { ActionArgs, defer, json, redirect, type ActionArgs, type LoaderArgs } from '@remix-run/node';\r\n\timport { prisma } from \"~/libs\";\r\n\timport { CarFront, Link } from 'lucide-react';\r\n\timport { ButtonStyled } from '~/components/ui/button-loading';\r\n\timport { Label } from '~/components/ui/label';\r\n\t\r\n\t\r\n\t\r\n\texport default function Dashboard() {\r\n\t\tconst { user } = useLoaderData()\r\n\t\tconst [isLoading, setIsLoading] = useState(true);\r\n\t\tconst [loadError, setLoadError] = useState(null);\r\n\t\r\n\t\r\n\t\tif (isLoading) {\r\n\t\t\treturn (\r\n\t\t\t\t<div className=\"min-h-screen bg-background flex items-center justify-center\">\r\n\t\t\t\t\t<div className=\"text-center\">\r\n\t\t\t\t\t\t<div className=\"w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4\"></div>\r\n\t\t\t\t\t\t<div className=\"text-lg font-medium text-gray-700\">Loading configuration...</div>\r\n\t\t\t\t\t\t<div className=\"text-sm text-gray-500 mt-2\">Fetching build settings from server</div>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (loadError) {\r\n\t\t\treturn (\r\n\t\t\t\t<div className=\"min-h-screen bg-background flex items-center justify-center\">\r\n\t\t\t\t\t<div className=\"text-center max-w-md\">\r\n\t\t\t\t\t\t<AlertCircle className=\"w-12 h-12 text-red-500 mx-auto mb-4\" />\r\n\t\t\t\t\t\t<div className=\"text-lg font-medium text-foreground mb-2\">Failed to Load Configuration</div>\r\n\t\t\t\t\t\t<div className=\"text-sm text-muted-foreground mb-4\">{loadError}</div>\r\n\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\tonClick={() => nav(0)}\r\n\t\t\t\t\t\t\tclassName=\"px-4 py-2 bg-primary hover:bg-primary/20 text-foreground rounded-lg transition-colors\"\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\tRetry\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\t\t\t);\r\n\t\t}\r\n\t\treturn (\r\n\t\t\t<div className=\"flex flex-col justify-center gap-3\">\r\n\t\r\n\t\t\t</div>\r\n\t\t)\r\n\t}\r\n\t\r\n\texport async function action({ request }: ActionArgs) {\r\n\t\tconst session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n\t\tconst email = session.get(\"email\");\r\n\t\tconst user = await eP.user.simple(email)\r\n\t\tif (!user) { return redirect(process.env.LOGIN); }\r\n\t\r\n\t\tconst d = Object.fromEntries(await request.formData());\r\n\t\tconst intent = d.intent\r\n\t\r\n\t\ttry {\r\n\t\t\tif (intent === 'createFunction') {\r\n\t\t\t\tconst result = await prisma.Function.create({\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t...data\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\treturn json({ success: true, result });\r\n\t\t\t} else if (intent === 'updateFunction') {\r\n\t\t\t\tconst result = await prisma.Function.update({\r\n\t\t\t\t\twhere: { id: String(id) },\r\n\t\t\t\t\tdata\r\n\t\t\t\t});\r\n\t\t\t\treturn json({ success: true, result });\r\n\t\t\t} else if (intent === 'deleteFunction') {\r\n\t\t\t\tconst result = await prisma.Function.delete({\r\n\t\t\t\t\twhere: { id: String(id) },\r\n\t\r\n\t\t\t\t});\r\n\t\t\t\treturn json({ success: true, result });\r\n\t\t\t} else {\r\n\t\t\t\treturn json({ success: false, error: \"Invalid intent\" }, { status: 400 });\r\n\t\t\t}\r\n\t\r\n\t\t} catch (error) {\r\n\t\t\treturn json({\r\n\t\t\t\tsuccess: false,\r\n\t\t\t\terror: error instanceof Error ? error.message : \"Unknown error\"\r\n\t\t\t}, { status: 500 });\r\n\t\t}\r\n\t}\r\n\t\r\n\texport async function loader({ request }: LoaderArgs) {\r\n\t\tconst session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n\t\tconst email = session.get(\"email\");\r\n\t\tconst user = await eP.user.all(email)\r\n\t\tif (!user) { return redirect(import.meta.env.VITE_LOGIN); }\r\n\t\r\n\t\treturn json({ user })\r\n\t}\r\n\t\r\n\texport const meta: MetaFunction = () => {\r\n\t\treturn [\r\n\t\t\t{ title: \"Dashboard - Catalyst\" },\r\n\t\t\t{ name: \"description\", content: \"Catalyst software dashboard.\" },\r\n\t\t];\r\n\t}"
|
|
3564
|
+
],
|
|
3565
|
+
"description": "",
|
|
3566
|
+
"scope": "jsx / tsx"
|
|
3567
|
+
},
|
|
3568
|
+
"loader": {
|
|
3569
|
+
"prefix": "loader",
|
|
3570
|
+
"body": [
|
|
3571
|
+
"import { json, redirect, type LoaderArgs, type ActionArgs } from \"@remix-run/node\";\r\nimport { prisma } from \"~/libs\";\r\nimport { authSessionStorage } from \"~/sessions/auth-session.server\";\r\nimport eP from \"~/utils/ext.server\";\r\nimport axios from \"axios\";\r\n\r\n// LOADER\r\nexport async function loader({ request }: LoaderArgs) {\r\n const session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\");\r\n const user = await eP.user.simple(email)\r\n if (!user) { return redirect(process.env.LOGIN); }\r\n\r\n const url = new URL(request.url);\r\n const intent = url.searchParams.get(\"intent\");\r\n const id = url.searchParams.get(\"id\");\r\n\r\n try {\r\n if (intent === 'findUnique' && id) {\r\n const result = await prisma.prisma.findUnique({\r\n where: { id }\r\n });\r\n return json({ success: true, result });\r\n\r\n } else if (intent === 'findFirst') {\r\n const params = Object.fromEntries(url.searchParams);\r\n const result = await prisma.prisma.findFirst({\r\n where: params\r\n });\r\n return json({ success: true, result });\r\n\r\n } else {\r\n const result = await prisma.prisma.findMany();\r\n return json({ success: true, result });\r\n }\r\n } catch (error) {\r\n return json({\r\n success: false,\r\n error: error instanceof Error ? error.message : \"Unknown error\"\r\n }, { status: 500 });\r\n }\r\n}"
|
|
3572
|
+
],
|
|
3573
|
+
"description": "",
|
|
3574
|
+
"scope": "jsx / tsx"
|
|
3575
|
+
},
|
|
3576
|
+
"api_route": {
|
|
3577
|
+
"prefix": "api_route",
|
|
3578
|
+
"body": [
|
|
3579
|
+
"import { json, redirect, type LoaderArgs, type ActionArgs } from \"@remix-run/node\";\r\nimport { prisma } from \"~/libs\";\r\nimport { authSessionStorage } from \"~/sessions/auth-session.server\";\r\nimport eP from \"~/utils/ext.server\";\r\nimport axios from \"axios\";\r\n\r\nexport async function loader({ request, params }: LoaderFunction) {\r\n const session = await authSessionStorage.getSession(request.headers.get(\"Cookie\"));\r\n const email = session.get(\"email\")\r\n const user = await eP.user.simple(email)\r\n if (!user) return redirect(process.env.LOGIN)\r\n const financeRequest = await prisma.dealRequest.findMany();\r\n return financeRequest\r\n}\r\n async function fetchFunctionData() {\r\n const response = await axios.get('/portal/api/sidebar/workorder');\r\n if (response.status !== 200) { return { error: \"Failed to fetch data.\" }; }\r\n //const data = JSON.parse(response.data)\r\n const data = response.data\r\n setAppointments(data)\r\n return null;\r\n }"
|
|
3580
|
+
],
|
|
3581
|
+
"description": "",
|
|
3582
|
+
"scope": "jsx / tsx"
|
|
3583
|
+
},
|
|
3584
|
+
"use_effect": {
|
|
3585
|
+
"prefix": "use_effect",
|
|
3586
|
+
"body": [
|
|
3587
|
+
"useEffect(() => {\r\n\r\n}, []);"
|
|
3588
|
+
],
|
|
3589
|
+
"description": "",
|
|
3590
|
+
"scope": "jsx / tsx"
|
|
3591
|
+
},
|
|
3592
|
+
"mapp": {
|
|
3593
|
+
"prefix": "mapp",
|
|
3594
|
+
"body": [
|
|
3595
|
+
"{categories.map((item, index) => {\r\n return (\r\n <SelectItem key={index} value={item.value}>\r\n {item.name}\r\n </SelectItem>\r\n );\r\n})}"
|
|
3596
|
+
],
|
|
3597
|
+
"description": "",
|
|
3598
|
+
"scope": "jsx / tsx"
|
|
3599
|
+
},
|
|
3600
|
+
"on_submit_function": {
|
|
3601
|
+
"prefix": "on_submit_function",
|
|
3602
|
+
"body": [
|
|
3603
|
+
"const fetcher = useFetcher()\r\nconst formData = new FormData();\r\nformData.append(\"id\", item.id);\r\nformData.append(\"intent\", \"deleteProgress\");\r\nfetcher.submit(formData, { method: \"post\" });"
|
|
3604
|
+
],
|
|
3605
|
+
"description": "",
|
|
3606
|
+
"scope": "jsx / tsx"
|
|
3607
|
+
},
|
|
3608
|
+
"button_with_on_click_submit": {
|
|
3609
|
+
"prefix": "button_with_on_click_submit",
|
|
3610
|
+
"body": [
|
|
3611
|
+
"<ButtonStyled\r\n type='submit'\r\n onClick={() => {\r\n const formData = new FormData();\r\n formData.append(\"id\", item.id);\r\n formData.append(\"intent\", \"deleteProgress\");\r\n fetcher.submit(formData, { method: \"post\" });\r\n}}>\r\n Save\r\n</ButtonStyled>"
|
|
3612
|
+
],
|
|
3613
|
+
"description": "",
|
|
3614
|
+
"scope": "jsx / tsx"
|
|
3615
|
+
},
|
|
3616
|
+
"fetcher_form_with_button_and_inputs": {
|
|
3617
|
+
"prefix": "fetcher_form_with_button_and_inputs",
|
|
3618
|
+
"body": [
|
|
3619
|
+
"const fetcher = useFetcher()\r\n\r\n<fetcher.Form method='post'>\r\n <div className=\"grid w-full max-w-sm items-center gap-3\">\r\n <Label>Email</Label>\r\n <Input value={data} onChange={(e) => { setData(e.currentTarget.value) }} className=\"\" />\r\n </div>\r\n <div className=\"grid w-full max-w-sm items-center gap-3\">\r\n <Label>Email</Label>\r\n <Textarea name=\"email\" value=\"email\" className=\"\" />\r\n </div>\r\n <ButtonStyled value='updateForm'>\r\n Save\r\n </ButtonStyled>\r\n</fetcher.Form>"
|
|
3620
|
+
],
|
|
3621
|
+
"description": "",
|
|
3622
|
+
"scope": "jsx / tsx"
|
|
3623
|
+
},
|
|
3624
|
+
"properly_escape_variables_in_backtick_const_calling": {
|
|
3625
|
+
"prefix": "properly_escape_variables_in_backtick_const_calling",
|
|
3626
|
+
"body": [
|
|
3627
|
+
"routes.push(layout(`./${relativePath}`, children)); \nto properly escape\na '\\' before each '`' \nand before the '$'\nroutes.push(layout(\\`./\\${relativePath}\\`, children));"
|
|
3628
|
+
],
|
|
3629
|
+
"description": "",
|
|
3630
|
+
"scope": "jsx / tsx"
|
|
3631
|
+
},
|
|
3632
|
+
"get_set_localstorage": {
|
|
3633
|
+
"prefix": "get_set_localstorage",
|
|
3634
|
+
"body": [
|
|
3635
|
+
"const [config, setConfig] = useState(\"cols/left\")\r\n\r\n useEffect(() => {\r\n const savedConfig = localStorage.getItem(\"config\")\r\n if (savedConfig) {\r\n setConfig(savedConfig)\r\n }\r\n }, [])\r\n\r\n useEffect(() => {\r\n localStorage.setItem(\"config\", config)\r\n }, [config])"
|
|
3636
|
+
],
|
|
3637
|
+
"description": "",
|
|
3638
|
+
"scope": "jsx / tsx"
|
|
3639
|
+
},
|
|
3640
|
+
"title_here_will_be_converted_changing_spaces_to___unless_you_toggle_it_off_it_also_copies_your_title_into_your_prefix": {
|
|
3641
|
+
"prefix": "title_here_will_be_converted_changing_spaces_to___unless_you_toggle_it_off_it_also_copies_your_title_into_your_prefix",
|
|
3642
|
+
"body": [
|
|
3643
|
+
"```javascript\nimport { Button } from 'my-library'\n\nfunction App() {\n return <Button>Click me</Button>\n}\n```\n\nwhatever you have in your clipboard will be pasted on page load"
|
|
3644
|
+
],
|
|
3645
|
+
"description": "",
|
|
3646
|
+
"scope": "jsx / tsx"
|
|
3647
|
+
},
|
|
3648
|
+
"snippet_title": {
|
|
3649
|
+
"prefix": "snippet_title",
|
|
3650
|
+
"body": [
|
|
3651
|
+
"on page load it takes anything you have in your clipboard and pastes it\n\nthe title unless switch off at the top will convert the title spaces into _ and copy the title to the prefix so you dont waste as much time creating snippets, you can also select a folder to save it straight to the devstack nav"
|
|
3652
|
+
],
|
|
3653
|
+
"description": "",
|
|
3654
|
+
"scope": "jsx / tsx"
|
|
3655
|
+
},
|
|
3656
|
+
"test_title": {
|
|
3657
|
+
"prefix": "test_title",
|
|
3658
|
+
"body": [
|
|
3659
|
+
"const saveThemeToVsCodeGlobally = async () => {\r\n const themeJson = JSON.stringify(vsCodeTheme, null, 2);\r\n await axios.post(DEVSTACK_URL + `/api/theme/config/save/global`, {\r\n data: themeJson\r\n });\r\n toast.success('Saving theme to global settings!')\r\n setWhichCopied('SaveVSCodeGlobally')\r\n setTimeout(() => setWhichCopied(null), 2000);\r\n return themeJson;\r\n };\r\n const copyThemeToVsCode = () => {\r\n const themeJson = JSON.stringify(vsCodeTheme, null, 2);\r\n navigator.clipboard.writeText(themeJson);\r\n toast.success('Copied VSCode theme!')\r\n setWhichCopied('CopyVSCode')\r\n setTimeout(() => setWhichCopied(null), 2000);\r\n return themeJson;\r\n };\r\n\r\n const copyThemeCSS = () => {\r\n if (selectedTheme) {\r\n setCopiedText(selectedTheme.fullCSS);\r\n toast.success('Copied tailwind css theme!')\r\n setWhichCopied('CopyCSS')\r\n setTimeout(() => setWhichCopied(null), 2000);\r\n }\r\n };"
|
|
3660
|
+
],
|
|
3661
|
+
"description": "",
|
|
3662
|
+
"scope": "jsx / tsx"
|
|
3663
|
+
}
|
|
3664
|
+
}
|