shadcn-vue 2.0.1 → 2.1.0
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/dist/chunk-MOIE35VS.js +1254 -0
- package/dist/chunk-MOIE35VS.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +371 -1429
- package/dist/index.js.map +1 -1
- package/dist/registry/index.d.ts +1047 -0
- package/dist/registry/index.js +31 -0
- package/dist/registry/index.js.map +1 -0
- package/package.json +11 -2
|
@@ -0,0 +1,1254 @@
|
|
|
1
|
+
// src/registry/schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var registryItemTypeSchema = z.enum([
|
|
4
|
+
"registry:lib",
|
|
5
|
+
"registry:block",
|
|
6
|
+
"registry:component",
|
|
7
|
+
"registry:ui",
|
|
8
|
+
"registry:hook",
|
|
9
|
+
"registry:page",
|
|
10
|
+
"registry:file",
|
|
11
|
+
"registry:theme",
|
|
12
|
+
"registry:style",
|
|
13
|
+
// Internal use only
|
|
14
|
+
"registry:example",
|
|
15
|
+
"registry:internal"
|
|
16
|
+
]);
|
|
17
|
+
var registryItemFileSchema = z.discriminatedUnion("type", [
|
|
18
|
+
// Target is required for registry:file and registry:page
|
|
19
|
+
z.object({
|
|
20
|
+
path: z.string(),
|
|
21
|
+
content: z.string().optional(),
|
|
22
|
+
type: z.enum(["registry:file", "registry:page"]),
|
|
23
|
+
target: z.string()
|
|
24
|
+
}),
|
|
25
|
+
z.object({
|
|
26
|
+
path: z.string(),
|
|
27
|
+
content: z.string().optional(),
|
|
28
|
+
type: registryItemTypeSchema.exclude(["registry:file", "registry:page"]),
|
|
29
|
+
target: z.string().optional()
|
|
30
|
+
})
|
|
31
|
+
]);
|
|
32
|
+
var registryItemTailwindSchema = z.object({
|
|
33
|
+
config: z.object({
|
|
34
|
+
content: z.array(z.string()).optional(),
|
|
35
|
+
theme: z.record(z.string(), z.any()).optional(),
|
|
36
|
+
plugins: z.array(z.string()).optional()
|
|
37
|
+
}).optional()
|
|
38
|
+
});
|
|
39
|
+
var registryItemCssVarsSchema = z.object({
|
|
40
|
+
theme: z.record(z.string(), z.string()).optional(),
|
|
41
|
+
light: z.record(z.string(), z.string()).optional(),
|
|
42
|
+
dark: z.record(z.string(), z.string()).optional()
|
|
43
|
+
});
|
|
44
|
+
var registryItemCssSchema = z.record(
|
|
45
|
+
z.string(),
|
|
46
|
+
z.lazy(
|
|
47
|
+
() => z.union([
|
|
48
|
+
z.string(),
|
|
49
|
+
z.record(
|
|
50
|
+
z.string(),
|
|
51
|
+
z.union([z.string(), z.record(z.string(), z.string())])
|
|
52
|
+
)
|
|
53
|
+
])
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
var registryItemSchema = z.object({
|
|
57
|
+
$schema: z.string().optional(),
|
|
58
|
+
extends: z.string().optional(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
type: registryItemTypeSchema,
|
|
61
|
+
title: z.string().optional(),
|
|
62
|
+
author: z.string().min(2).optional(),
|
|
63
|
+
description: z.string().optional(),
|
|
64
|
+
dependencies: z.array(z.string()).optional(),
|
|
65
|
+
devDependencies: z.array(z.string()).optional(),
|
|
66
|
+
registryDependencies: z.array(z.string()).optional(),
|
|
67
|
+
files: z.array(registryItemFileSchema).optional(),
|
|
68
|
+
tailwind: registryItemTailwindSchema.optional(),
|
|
69
|
+
cssVars: registryItemCssVarsSchema.optional(),
|
|
70
|
+
css: registryItemCssSchema.optional(),
|
|
71
|
+
meta: z.record(z.string(), z.any()).optional(),
|
|
72
|
+
docs: z.string().optional(),
|
|
73
|
+
categories: z.array(z.string()).optional()
|
|
74
|
+
});
|
|
75
|
+
var registrySchema = z.object({
|
|
76
|
+
name: z.string(),
|
|
77
|
+
homepage: z.string(),
|
|
78
|
+
items: z.array(registryItemSchema)
|
|
79
|
+
});
|
|
80
|
+
var registryIndexSchema = z.array(registryItemSchema);
|
|
81
|
+
var stylesSchema = z.array(
|
|
82
|
+
z.object({
|
|
83
|
+
name: z.string(),
|
|
84
|
+
label: z.string()
|
|
85
|
+
})
|
|
86
|
+
);
|
|
87
|
+
var iconsSchema = z.record(
|
|
88
|
+
z.string(),
|
|
89
|
+
z.record(z.string(), z.string())
|
|
90
|
+
);
|
|
91
|
+
var registryBaseColorSchema = z.object({
|
|
92
|
+
inlineColors: z.object({
|
|
93
|
+
light: z.record(z.string(), z.string()),
|
|
94
|
+
dark: z.record(z.string(), z.string())
|
|
95
|
+
}),
|
|
96
|
+
cssVars: registryItemCssVarsSchema,
|
|
97
|
+
cssVarsV4: registryItemCssVarsSchema.optional(),
|
|
98
|
+
inlineColorsTemplate: z.string(),
|
|
99
|
+
cssVarsTemplate: z.string()
|
|
100
|
+
});
|
|
101
|
+
var registryResolvedItemsTreeSchema = registryItemSchema.pick({
|
|
102
|
+
dependencies: true,
|
|
103
|
+
devDependencies: true,
|
|
104
|
+
files: true,
|
|
105
|
+
tailwind: true,
|
|
106
|
+
cssVars: true,
|
|
107
|
+
css: true,
|
|
108
|
+
docs: true
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// src/utils/frameworks.ts
|
|
112
|
+
var FRAMEWORKS = {
|
|
113
|
+
vite: {
|
|
114
|
+
name: "vite",
|
|
115
|
+
label: "Vite",
|
|
116
|
+
links: {
|
|
117
|
+
installation: "https://shadcn-vue.com/docs/installation/vite",
|
|
118
|
+
tailwind: "https://tailwindcss.com/docs/guides/vite"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
nuxt: {
|
|
122
|
+
name: "nuxt",
|
|
123
|
+
label: "Nuxt",
|
|
124
|
+
links: {
|
|
125
|
+
installation: "https://shadcn-vue.com/docs/installation/nuxt",
|
|
126
|
+
tailwind: "https://tailwindcss.com/docs/guides/nuxtjs"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
astro: {
|
|
130
|
+
name: "astro",
|
|
131
|
+
label: "Astro",
|
|
132
|
+
links: {
|
|
133
|
+
installation: "https://shadcn-vue.com/docs/installation/astro",
|
|
134
|
+
tailwind: "https://tailwindcss.com/docs/guides/astro"
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
laravel: {
|
|
138
|
+
name: "laravel",
|
|
139
|
+
label: "Laravel",
|
|
140
|
+
links: {
|
|
141
|
+
installation: "https://shadcn-vue.com/docs/installation/laravel",
|
|
142
|
+
tailwind: "https://tailwindcss.com/docs/guides/laravel"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
manual: {
|
|
146
|
+
name: "manual",
|
|
147
|
+
label: "Manual",
|
|
148
|
+
links: {
|
|
149
|
+
installation: "https://shadcn-vue.com/docs/installation/manual",
|
|
150
|
+
tailwind: "https://tailwindcss.com/docs/installation"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// src/utils/get-package-info.ts
|
|
156
|
+
import fs from "fs-extra";
|
|
157
|
+
import path from "pathe";
|
|
158
|
+
function getPackageInfo(cwd = "", shouldThrow = true) {
|
|
159
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
160
|
+
return fs.readJSONSync(packageJsonPath, {
|
|
161
|
+
throws: shouldThrow
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/utils/get-project-info.ts
|
|
166
|
+
import fs2 from "fs-extra";
|
|
167
|
+
import { parseTsconfig } from "get-tsconfig";
|
|
168
|
+
import path2 from "pathe";
|
|
169
|
+
import { glob } from "tinyglobby";
|
|
170
|
+
import { z as z2 } from "zod";
|
|
171
|
+
var PROJECT_SHARED_IGNORE = [
|
|
172
|
+
"**/node_modules/**",
|
|
173
|
+
".nuxt",
|
|
174
|
+
"public",
|
|
175
|
+
"dist",
|
|
176
|
+
"build"
|
|
177
|
+
];
|
|
178
|
+
var TS_CONFIG_SCHEMA = z2.object({
|
|
179
|
+
compilerOptions: z2.object({
|
|
180
|
+
paths: z2.record(z2.string().or(z2.array(z2.string())))
|
|
181
|
+
})
|
|
182
|
+
});
|
|
183
|
+
async function getProjectInfo(cwd) {
|
|
184
|
+
const [
|
|
185
|
+
configFiles,
|
|
186
|
+
typescript,
|
|
187
|
+
tailwindConfigFile,
|
|
188
|
+
tailwindCssFile,
|
|
189
|
+
tailwindVersion,
|
|
190
|
+
aliasPrefix,
|
|
191
|
+
packageJson
|
|
192
|
+
] = await Promise.all([
|
|
193
|
+
glob("**/{nuxt,vite,astro}.config.*|composer.json", {
|
|
194
|
+
cwd,
|
|
195
|
+
deep: 3,
|
|
196
|
+
ignore: PROJECT_SHARED_IGNORE
|
|
197
|
+
}),
|
|
198
|
+
isTypeScriptProject(cwd),
|
|
199
|
+
getTailwindConfigFile(cwd),
|
|
200
|
+
getTailwindCssFile(cwd),
|
|
201
|
+
getTailwindVersion(cwd),
|
|
202
|
+
getTsConfigAliasPrefix(cwd),
|
|
203
|
+
getPackageInfo(cwd, false)
|
|
204
|
+
]);
|
|
205
|
+
const type = {
|
|
206
|
+
framework: FRAMEWORKS.manual,
|
|
207
|
+
typescript,
|
|
208
|
+
tailwindConfigFile,
|
|
209
|
+
tailwindCssFile,
|
|
210
|
+
tailwindVersion,
|
|
211
|
+
aliasPrefix
|
|
212
|
+
};
|
|
213
|
+
if (configFiles.find((file) => file.startsWith("nuxt.config."))?.length) {
|
|
214
|
+
type.framework = FRAMEWORKS.nuxt;
|
|
215
|
+
return type;
|
|
216
|
+
}
|
|
217
|
+
if (configFiles.find((file) => file.startsWith("astro.config."))?.length) {
|
|
218
|
+
type.framework = FRAMEWORKS.astro;
|
|
219
|
+
return type;
|
|
220
|
+
}
|
|
221
|
+
if (configFiles.find((file) => file.startsWith("composer.json"))?.length) {
|
|
222
|
+
type.framework = FRAMEWORKS.laravel;
|
|
223
|
+
return type;
|
|
224
|
+
}
|
|
225
|
+
if (configFiles.find((file) => file.startsWith("vite.config."))?.length) {
|
|
226
|
+
type.framework = FRAMEWORKS.vite;
|
|
227
|
+
return type;
|
|
228
|
+
}
|
|
229
|
+
return type;
|
|
230
|
+
}
|
|
231
|
+
async function getTailwindVersion(cwd) {
|
|
232
|
+
const [packageInfo, config] = await Promise.all([
|
|
233
|
+
getPackageInfo(cwd),
|
|
234
|
+
getConfig(cwd)
|
|
235
|
+
]);
|
|
236
|
+
if (config?.tailwind?.config === "") {
|
|
237
|
+
return "v4";
|
|
238
|
+
}
|
|
239
|
+
if (!packageInfo?.dependencies?.tailwindcss && !packageInfo?.devDependencies?.tailwindcss) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
if (/^(?:\^|~)?3(?:\.\d+)*(?:-.*)?$/.test(
|
|
243
|
+
packageInfo?.dependencies?.tailwindcss || packageInfo?.devDependencies?.tailwindcss || ""
|
|
244
|
+
)) {
|
|
245
|
+
return "v3";
|
|
246
|
+
}
|
|
247
|
+
return "v4";
|
|
248
|
+
}
|
|
249
|
+
async function getTailwindCssFile(cwd) {
|
|
250
|
+
const [files, tailwindVersion] = await Promise.all([
|
|
251
|
+
glob(["**/*.css", "**/*.scss"], {
|
|
252
|
+
cwd,
|
|
253
|
+
deep: 5,
|
|
254
|
+
ignore: PROJECT_SHARED_IGNORE
|
|
255
|
+
}),
|
|
256
|
+
getTailwindVersion(cwd)
|
|
257
|
+
]);
|
|
258
|
+
if (!files.length) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const needle = tailwindVersion === "v4" ? `@import "tailwindcss"` : "@tailwind base";
|
|
262
|
+
for (const file of files) {
|
|
263
|
+
const contents = await fs2.readFile(path2.resolve(cwd, file), "utf8");
|
|
264
|
+
if (contents.includes(`@import "tailwindcss"`) || contents.includes(`@import 'tailwindcss'`) || contents.includes(`@tailwind base`)) {
|
|
265
|
+
return file;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
async function getTailwindConfigFile(cwd) {
|
|
271
|
+
const files = await glob("tailwind.config.*", {
|
|
272
|
+
cwd,
|
|
273
|
+
deep: 3,
|
|
274
|
+
ignore: PROJECT_SHARED_IGNORE
|
|
275
|
+
});
|
|
276
|
+
if (!files.length) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return files[0];
|
|
280
|
+
}
|
|
281
|
+
async function getTsConfigAliasPrefix(cwd) {
|
|
282
|
+
const isTypescript = await isTypeScriptProject(cwd);
|
|
283
|
+
const tsconfigType = isTypescript ? "tsconfig.json" : "jsconfig.json";
|
|
284
|
+
const tsConfig = getTSConfig(cwd, tsconfigType);
|
|
285
|
+
const parsedTsConfig = parseTsconfig(tsConfig.path);
|
|
286
|
+
const aliasPaths = parsedTsConfig.compilerOptions?.paths ?? {};
|
|
287
|
+
for (const [alias, paths] of Object.entries(aliasPaths)) {
|
|
288
|
+
if (paths.includes("./*") || paths.includes("./src/*") || paths.includes("./app/*") || paths.includes("./resources/js/*")) {
|
|
289
|
+
const cleanAlias = alias.replace(/\/\*$/, "") ?? null;
|
|
290
|
+
return cleanAlias === "#build" ? "@" : cleanAlias;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return Object.keys(aliasPaths)?.[0]?.replace(/\/\*$/, "") ?? null;
|
|
294
|
+
}
|
|
295
|
+
async function isTypeScriptProject(cwd) {
|
|
296
|
+
const files = await glob("tsconfig.*", {
|
|
297
|
+
cwd,
|
|
298
|
+
deep: 1,
|
|
299
|
+
ignore: PROJECT_SHARED_IGNORE
|
|
300
|
+
});
|
|
301
|
+
return files.length > 0;
|
|
302
|
+
}
|
|
303
|
+
async function getProjectConfig(cwd, defaultProjectInfo = null) {
|
|
304
|
+
const [existingConfig, projectInfo] = await Promise.all([
|
|
305
|
+
getConfig(cwd),
|
|
306
|
+
!defaultProjectInfo ? getProjectInfo(cwd) : Promise.resolve(defaultProjectInfo)
|
|
307
|
+
]);
|
|
308
|
+
if (existingConfig) {
|
|
309
|
+
return existingConfig;
|
|
310
|
+
}
|
|
311
|
+
if (!projectInfo || !projectInfo.tailwindCssFile || projectInfo.tailwindVersion === "v3" && !projectInfo.tailwindConfigFile) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
const config = {
|
|
315
|
+
$schema: "https://shadcn-vue.com/schema.json",
|
|
316
|
+
typescript: projectInfo.typescript,
|
|
317
|
+
style: "new-york",
|
|
318
|
+
tailwind: {
|
|
319
|
+
config: projectInfo.tailwindConfigFile ?? "",
|
|
320
|
+
baseColor: "zinc",
|
|
321
|
+
css: projectInfo.tailwindCssFile,
|
|
322
|
+
cssVariables: true,
|
|
323
|
+
prefix: ""
|
|
324
|
+
},
|
|
325
|
+
iconLibrary: "lucide",
|
|
326
|
+
aliases: {
|
|
327
|
+
components: `${projectInfo.aliasPrefix}/components`,
|
|
328
|
+
ui: `${projectInfo.aliasPrefix}/components/ui`,
|
|
329
|
+
composables: `${projectInfo.aliasPrefix}/composables`,
|
|
330
|
+
lib: `${projectInfo.aliasPrefix}/lib`,
|
|
331
|
+
utils: `${projectInfo.aliasPrefix}/lib/utils`
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
return await resolveConfigPaths(cwd, config);
|
|
335
|
+
}
|
|
336
|
+
async function getProjectTailwindVersionFromConfig(config) {
|
|
337
|
+
if (!config.resolvedPaths?.cwd) {
|
|
338
|
+
return "v3";
|
|
339
|
+
}
|
|
340
|
+
const projectInfo = await getProjectInfo(config.resolvedPaths.cwd);
|
|
341
|
+
if (!projectInfo?.tailwindVersion) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
return projectInfo.tailwindVersion;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/utils/resolve-import.ts
|
|
348
|
+
import { createPathsMatcher } from "get-tsconfig";
|
|
349
|
+
function resolveImport(importPath, config) {
|
|
350
|
+
const matcher = createPathsMatcher(config);
|
|
351
|
+
if (matcher === null) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const paths = matcher(importPath);
|
|
355
|
+
return paths[0];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// src/utils/get-config.ts
|
|
359
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
360
|
+
import { getTsconfig } from "get-tsconfig";
|
|
361
|
+
import path3 from "pathe";
|
|
362
|
+
import { z as z3 } from "zod";
|
|
363
|
+
|
|
364
|
+
// src/utils/highlighter.ts
|
|
365
|
+
import { colors } from "consola/utils";
|
|
366
|
+
var highlighter = {
|
|
367
|
+
error: colors.red,
|
|
368
|
+
warn: colors.yellow,
|
|
369
|
+
info: colors.cyan,
|
|
370
|
+
success: colors.green
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// src/utils/get-config.ts
|
|
374
|
+
var TAILWIND_CSS_PATH = {
|
|
375
|
+
nuxt: "assets/css/tailwind.css",
|
|
376
|
+
vite: "src/assets/index.css",
|
|
377
|
+
laravel: "resources/css/app.css",
|
|
378
|
+
astro: "src/styles/globals.css"
|
|
379
|
+
};
|
|
380
|
+
var DEFAULT_COMPONENTS = "@/components";
|
|
381
|
+
var DEFAULT_UTILS = "@/lib/utils";
|
|
382
|
+
var DEFAULT_TAILWIND_CSS = TAILWIND_CSS_PATH.nuxt;
|
|
383
|
+
var DEFAULT_TAILWIND_CONFIG = "tailwind.config.js";
|
|
384
|
+
var explorer = cosmiconfig("components", {
|
|
385
|
+
searchPlaces: ["components.json"]
|
|
386
|
+
});
|
|
387
|
+
var rawConfigSchema = z3.object({
|
|
388
|
+
$schema: z3.string().optional(),
|
|
389
|
+
style: z3.string(),
|
|
390
|
+
typescript: z3.boolean().default(true),
|
|
391
|
+
tailwind: z3.object({
|
|
392
|
+
config: z3.string().optional(),
|
|
393
|
+
css: z3.string(),
|
|
394
|
+
baseColor: z3.string(),
|
|
395
|
+
cssVariables: z3.boolean().default(true),
|
|
396
|
+
prefix: z3.string().default("").optional()
|
|
397
|
+
}),
|
|
398
|
+
aliases: z3.object({
|
|
399
|
+
components: z3.string(),
|
|
400
|
+
composables: z3.string().optional(),
|
|
401
|
+
utils: z3.string(),
|
|
402
|
+
ui: z3.string().optional(),
|
|
403
|
+
lib: z3.string().optional()
|
|
404
|
+
}),
|
|
405
|
+
iconLibrary: z3.string().optional()
|
|
406
|
+
}).strict();
|
|
407
|
+
var configSchema = rawConfigSchema.extend({
|
|
408
|
+
resolvedPaths: z3.object({
|
|
409
|
+
cwd: z3.string(),
|
|
410
|
+
tailwindConfig: z3.string(),
|
|
411
|
+
tailwindCss: z3.string(),
|
|
412
|
+
utils: z3.string(),
|
|
413
|
+
components: z3.string(),
|
|
414
|
+
composables: z3.string(),
|
|
415
|
+
lib: z3.string(),
|
|
416
|
+
ui: z3.string()
|
|
417
|
+
})
|
|
418
|
+
});
|
|
419
|
+
async function getConfig(cwd) {
|
|
420
|
+
const config = await getRawConfig(cwd);
|
|
421
|
+
if (!config) {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
if (!config.iconLibrary) {
|
|
425
|
+
config.iconLibrary = config.style === "new-york" ? "radix" : "lucide";
|
|
426
|
+
}
|
|
427
|
+
return await resolveConfigPaths(cwd, config);
|
|
428
|
+
}
|
|
429
|
+
function getTSConfig(cwd, tsconfigName) {
|
|
430
|
+
const parsedConfig = getTsconfig(path3.resolve(cwd, "package.json"), tsconfigName);
|
|
431
|
+
if (parsedConfig === null) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
`Failed to find ${highlighter.info(tsconfigName)}`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
return parsedConfig;
|
|
437
|
+
}
|
|
438
|
+
async function resolveConfigPaths(cwd, config) {
|
|
439
|
+
const tsconfigType = config.typescript ? "tsconfig.json" : "jsconfig.json";
|
|
440
|
+
const tsConfig = getTSConfig(cwd, tsconfigType);
|
|
441
|
+
return configSchema.parse({
|
|
442
|
+
...config,
|
|
443
|
+
resolvedPaths: {
|
|
444
|
+
cwd,
|
|
445
|
+
tailwindConfig: config.tailwind.config ? path3.resolve(cwd, config.tailwind.config) : "",
|
|
446
|
+
tailwindCss: path3.resolve(cwd, config.tailwind.css),
|
|
447
|
+
utils: await resolveImport(config.aliases.utils, tsConfig),
|
|
448
|
+
components: await resolveImport(config.aliases.components, tsConfig),
|
|
449
|
+
ui: config.aliases.ui ? await resolveImport(config.aliases.ui, tsConfig) : path3.resolve(
|
|
450
|
+
await resolveImport(config.aliases.components, tsConfig) ?? cwd,
|
|
451
|
+
"ui"
|
|
452
|
+
),
|
|
453
|
+
// TODO: Make this configurable.
|
|
454
|
+
// For now, we assume the lib and hooks directories are one level up from the components directory.
|
|
455
|
+
lib: config.aliases.lib ? await resolveImport(config.aliases.lib, tsConfig) : path3.resolve(
|
|
456
|
+
await resolveImport(config.aliases.utils, tsConfig) ?? cwd,
|
|
457
|
+
".."
|
|
458
|
+
),
|
|
459
|
+
composables: config.aliases.composables ? await resolveImport(config.aliases.composables, tsConfig) : path3.resolve(
|
|
460
|
+
await resolveImport(config.aliases.components, tsConfig) ?? cwd,
|
|
461
|
+
"..",
|
|
462
|
+
"composables"
|
|
463
|
+
)
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
async function getRawConfig(cwd) {
|
|
468
|
+
try {
|
|
469
|
+
const configResult = await explorer.search(cwd);
|
|
470
|
+
if (!configResult) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
return rawConfigSchema.parse(configResult.config);
|
|
474
|
+
} catch (error) {
|
|
475
|
+
throw new Error(`Invalid configuration found in ${cwd}/components.json.`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async function getTargetStyleFromConfig(cwd, fallback) {
|
|
479
|
+
const projectInfo = await getProjectInfo(cwd);
|
|
480
|
+
return projectInfo?.tailwindVersion === "v4" ? "new-york-v4" : fallback;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/utils/handle-error.ts
|
|
484
|
+
import { consola } from "consola";
|
|
485
|
+
function handleError(error) {
|
|
486
|
+
consola.log("this is error: ", error);
|
|
487
|
+
if (typeof error === "string") {
|
|
488
|
+
consola.error(error);
|
|
489
|
+
process.exit(1);
|
|
490
|
+
}
|
|
491
|
+
if (error instanceof Error) {
|
|
492
|
+
consola.error(error.message);
|
|
493
|
+
process.exit(1);
|
|
494
|
+
}
|
|
495
|
+
consola.error("Something went wrong. Please try again.");
|
|
496
|
+
process.exit(1);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/utils/logger.ts
|
|
500
|
+
import consola2 from "consola";
|
|
501
|
+
var logger = {
|
|
502
|
+
error(...args) {
|
|
503
|
+
consola2.log(highlighter.error(args.join(" ")));
|
|
504
|
+
},
|
|
505
|
+
warn(...args) {
|
|
506
|
+
consola2.log(highlighter.warn(args.join(" ")));
|
|
507
|
+
},
|
|
508
|
+
info(...args) {
|
|
509
|
+
consola2.log(highlighter.info(args.join(" ")));
|
|
510
|
+
},
|
|
511
|
+
success(...args) {
|
|
512
|
+
consola2.log(highlighter.success(args.join(" ")));
|
|
513
|
+
},
|
|
514
|
+
log(...args) {
|
|
515
|
+
consola2.log(args.join(" "));
|
|
516
|
+
},
|
|
517
|
+
break() {
|
|
518
|
+
consola2.log("");
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// src/utils/updaters/update-tailwind-config.ts
|
|
523
|
+
import { promises as fs3 } from "node:fs";
|
|
524
|
+
import { tmpdir } from "node:os";
|
|
525
|
+
|
|
526
|
+
// src/utils/spinner.ts
|
|
527
|
+
import ora from "ora";
|
|
528
|
+
function spinner(text, options) {
|
|
529
|
+
return ora({
|
|
530
|
+
text,
|
|
531
|
+
isSilent: options?.silent
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/utils/updaters/update-tailwind-config.ts
|
|
536
|
+
import deepmerge from "deepmerge";
|
|
537
|
+
import path4 from "pathe";
|
|
538
|
+
import objectToString from "stringify-object";
|
|
539
|
+
import {
|
|
540
|
+
Project,
|
|
541
|
+
QuoteKind,
|
|
542
|
+
ScriptKind,
|
|
543
|
+
SyntaxKind
|
|
544
|
+
} from "ts-morph";
|
|
545
|
+
async function updateTailwindConfig(tailwindConfig, config, options) {
|
|
546
|
+
if (!tailwindConfig) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
options = {
|
|
550
|
+
silent: false,
|
|
551
|
+
tailwindVersion: "v3",
|
|
552
|
+
...options
|
|
553
|
+
};
|
|
554
|
+
if (options.tailwindVersion === "v4") {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const tailwindFileRelativePath = path4.relative(
|
|
558
|
+
config.resolvedPaths.cwd,
|
|
559
|
+
config.resolvedPaths.tailwindConfig
|
|
560
|
+
);
|
|
561
|
+
const tailwindSpinner = spinner(
|
|
562
|
+
`Updating ${highlighter.info(tailwindFileRelativePath)}`,
|
|
563
|
+
{
|
|
564
|
+
silent: options.silent
|
|
565
|
+
}
|
|
566
|
+
).start();
|
|
567
|
+
const raw = await fs3.readFile(config.resolvedPaths.tailwindConfig, "utf8");
|
|
568
|
+
const output = await transformTailwindConfig(raw, tailwindConfig, config);
|
|
569
|
+
await fs3.writeFile(config.resolvedPaths.tailwindConfig, output, "utf8");
|
|
570
|
+
tailwindSpinner?.succeed();
|
|
571
|
+
}
|
|
572
|
+
async function transformTailwindConfig(input, tailwindConfig, config) {
|
|
573
|
+
const sourceFile = await _createSourceFile(input, config);
|
|
574
|
+
const configObject = sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression).find(
|
|
575
|
+
(node) => node.getProperties().some(
|
|
576
|
+
(property) => property.isKind(SyntaxKind.PropertyAssignment) && property.getName() === "content"
|
|
577
|
+
)
|
|
578
|
+
);
|
|
579
|
+
if (!configObject) {
|
|
580
|
+
return input;
|
|
581
|
+
}
|
|
582
|
+
const quoteChar = _getQuoteChar(configObject);
|
|
583
|
+
addTailwindConfigProperty(
|
|
584
|
+
configObject,
|
|
585
|
+
{
|
|
586
|
+
name: "darkMode",
|
|
587
|
+
value: "class"
|
|
588
|
+
},
|
|
589
|
+
{ quoteChar }
|
|
590
|
+
);
|
|
591
|
+
tailwindConfig.plugins?.forEach((plugin) => {
|
|
592
|
+
addTailwindConfigPlugin(configObject, plugin);
|
|
593
|
+
});
|
|
594
|
+
if (tailwindConfig.theme) {
|
|
595
|
+
await addTailwindConfigTheme(configObject, tailwindConfig.theme);
|
|
596
|
+
}
|
|
597
|
+
return sourceFile.getFullText();
|
|
598
|
+
}
|
|
599
|
+
function addTailwindConfigProperty(configObject, property, {
|
|
600
|
+
quoteChar
|
|
601
|
+
}) {
|
|
602
|
+
const existingProperty = configObject.getProperty("darkMode");
|
|
603
|
+
if (!existingProperty) {
|
|
604
|
+
const newProperty = {
|
|
605
|
+
name: property.name,
|
|
606
|
+
initializer: `[${quoteChar}${property.value}${quoteChar}]`
|
|
607
|
+
};
|
|
608
|
+
if (property.name === "darkMode") {
|
|
609
|
+
configObject.insertPropertyAssignment(0, newProperty);
|
|
610
|
+
return configObject;
|
|
611
|
+
}
|
|
612
|
+
configObject.addPropertyAssignment(newProperty);
|
|
613
|
+
return configObject;
|
|
614
|
+
}
|
|
615
|
+
if (existingProperty.isKind(SyntaxKind.PropertyAssignment)) {
|
|
616
|
+
const initializer = existingProperty.getInitializer();
|
|
617
|
+
const newValue = `${quoteChar}${property.value}${quoteChar}`;
|
|
618
|
+
if (initializer?.isKind(SyntaxKind.StringLiteral)) {
|
|
619
|
+
const initializerText = initializer.getText();
|
|
620
|
+
initializer.replaceWithText(`[${initializerText}, ${newValue}]`);
|
|
621
|
+
return configObject;
|
|
622
|
+
}
|
|
623
|
+
if (initializer?.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
624
|
+
if (initializer.getElements().map((element) => element.getText()).includes(newValue)) {
|
|
625
|
+
return configObject;
|
|
626
|
+
}
|
|
627
|
+
initializer.addElement(newValue);
|
|
628
|
+
}
|
|
629
|
+
return configObject;
|
|
630
|
+
}
|
|
631
|
+
return configObject;
|
|
632
|
+
}
|
|
633
|
+
async function addTailwindConfigTheme(configObject, theme) {
|
|
634
|
+
if (!configObject.getProperty("theme")) {
|
|
635
|
+
configObject.addPropertyAssignment({
|
|
636
|
+
name: "theme",
|
|
637
|
+
initializer: "{}"
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
nestSpreadProperties(configObject);
|
|
641
|
+
const themeProperty = configObject.getPropertyOrThrow("theme")?.asKindOrThrow(SyntaxKind.PropertyAssignment);
|
|
642
|
+
const themeInitializer = themeProperty.getInitializer();
|
|
643
|
+
if (themeInitializer?.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
644
|
+
const themeObjectString = themeInitializer.getText();
|
|
645
|
+
const themeObject = await parseObjectLiteral(themeObjectString);
|
|
646
|
+
const result = deepmerge(themeObject, theme, {
|
|
647
|
+
arrayMerge: (dst, src) => src
|
|
648
|
+
});
|
|
649
|
+
const resultString = objectToString(result).replace(/'\.\.\.(.*)'/g, "...$1").replace(/'"/g, "'").replace(/"'/g, "'").replace(/'\[/g, "[").replace(/\]'/g, "]").replace(/'\\'/g, "'").replace(/\\'/g, "'").replace(/\\''/g, "'").replace(/''/g, "'");
|
|
650
|
+
themeInitializer.replaceWithText(resultString);
|
|
651
|
+
}
|
|
652
|
+
unnestSpreadProperties(configObject);
|
|
653
|
+
}
|
|
654
|
+
function addTailwindConfigPlugin(configObject, plugin) {
|
|
655
|
+
const existingPlugins = configObject.getProperty("plugins");
|
|
656
|
+
if (!existingPlugins) {
|
|
657
|
+
configObject.addPropertyAssignment({
|
|
658
|
+
name: "plugins",
|
|
659
|
+
initializer: `[${plugin}]`
|
|
660
|
+
});
|
|
661
|
+
return configObject;
|
|
662
|
+
}
|
|
663
|
+
if (existingPlugins.isKind(SyntaxKind.PropertyAssignment)) {
|
|
664
|
+
const initializer = existingPlugins.getInitializer();
|
|
665
|
+
if (initializer?.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
666
|
+
if (initializer.getElements().map((element) => {
|
|
667
|
+
return element.getText().replace(/["']/g, "");
|
|
668
|
+
}).includes(plugin.replace(/["']/g, ""))) {
|
|
669
|
+
return configObject;
|
|
670
|
+
}
|
|
671
|
+
initializer.addElement(plugin);
|
|
672
|
+
}
|
|
673
|
+
return configObject;
|
|
674
|
+
}
|
|
675
|
+
return configObject;
|
|
676
|
+
}
|
|
677
|
+
async function _createSourceFile(input, config) {
|
|
678
|
+
const dir = await fs3.mkdtemp(path4.join(tmpdir(), "shadcn-"));
|
|
679
|
+
const resolvedPath = config?.resolvedPaths?.tailwindConfig || "tailwind.config.ts";
|
|
680
|
+
const tempFile = path4.join(dir, `shadcn-${path4.basename(resolvedPath)}`);
|
|
681
|
+
const project = new Project({
|
|
682
|
+
compilerOptions: {}
|
|
683
|
+
});
|
|
684
|
+
const sourceFile = project.createSourceFile(tempFile, input, {
|
|
685
|
+
// Note: .js and .mjs can still be valid for TS projects.
|
|
686
|
+
// We can't infer TypeScript from config.tsx.
|
|
687
|
+
scriptKind: path4.extname(resolvedPath) === ".ts" ? ScriptKind.TS : ScriptKind.JS
|
|
688
|
+
});
|
|
689
|
+
return sourceFile;
|
|
690
|
+
}
|
|
691
|
+
function _getQuoteChar(configObject) {
|
|
692
|
+
return configObject.getFirstDescendantByKind(SyntaxKind.StringLiteral)?.getQuoteKind() === QuoteKind.Single ? "'" : '"';
|
|
693
|
+
}
|
|
694
|
+
function nestSpreadProperties(obj) {
|
|
695
|
+
const properties = obj.getProperties();
|
|
696
|
+
for (let i = 0; i < properties.length; i++) {
|
|
697
|
+
const prop = properties[i];
|
|
698
|
+
if (prop.isKind(SyntaxKind.SpreadAssignment)) {
|
|
699
|
+
const spreadAssignment = prop.asKindOrThrow(SyntaxKind.SpreadAssignment);
|
|
700
|
+
const spreadText = spreadAssignment.getExpression().getText();
|
|
701
|
+
obj.insertPropertyAssignment(i, {
|
|
702
|
+
// Need to escape the name with " so that deepmerge doesn't mishandle the key
|
|
703
|
+
name: `"___${spreadText.replace(/^\.\.\./, "")}"`,
|
|
704
|
+
initializer: `"...${spreadText.replace(/^\.\.\./, "")}"`
|
|
705
|
+
});
|
|
706
|
+
spreadAssignment.remove();
|
|
707
|
+
} else if (prop.isKind(SyntaxKind.PropertyAssignment)) {
|
|
708
|
+
const propAssignment = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);
|
|
709
|
+
const initializer = propAssignment.getInitializer();
|
|
710
|
+
if (initializer && initializer.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
711
|
+
nestSpreadProperties(
|
|
712
|
+
initializer.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
|
|
713
|
+
);
|
|
714
|
+
} else if (initializer && initializer.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
715
|
+
nestSpreadElements(
|
|
716
|
+
initializer.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function nestSpreadElements(arr) {
|
|
723
|
+
const elements = arr.getElements();
|
|
724
|
+
for (let j = 0; j < elements.length; j++) {
|
|
725
|
+
const element = elements[j];
|
|
726
|
+
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
727
|
+
nestSpreadProperties(
|
|
728
|
+
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
|
|
729
|
+
);
|
|
730
|
+
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
731
|
+
nestSpreadElements(
|
|
732
|
+
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
|
|
733
|
+
);
|
|
734
|
+
} else if (element.isKind(SyntaxKind.SpreadElement)) {
|
|
735
|
+
const spreadText = element.getText();
|
|
736
|
+
arr.removeElement(j);
|
|
737
|
+
arr.insertElement(j, `"${spreadText}"`);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
function unnestSpreadProperties(obj) {
|
|
742
|
+
const properties = obj.getProperties();
|
|
743
|
+
for (let i = 0; i < properties.length; i++) {
|
|
744
|
+
const prop = properties[i];
|
|
745
|
+
if (prop.isKind(SyntaxKind.PropertyAssignment)) {
|
|
746
|
+
const propAssignment = prop;
|
|
747
|
+
const initializer = propAssignment.getInitializer();
|
|
748
|
+
if (initializer && initializer.isKind(SyntaxKind.StringLiteral)) {
|
|
749
|
+
const value = initializer.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
|
|
750
|
+
if (value.startsWith("...")) {
|
|
751
|
+
obj.insertSpreadAssignment(i, { expression: value.slice(3) });
|
|
752
|
+
propAssignment.remove();
|
|
753
|
+
}
|
|
754
|
+
} else if (initializer?.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
755
|
+
unnestSpreadProperties(initializer);
|
|
756
|
+
} else if (initializer && initializer.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
757
|
+
unnsetSpreadElements(
|
|
758
|
+
initializer.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function unnsetSpreadElements(arr) {
|
|
765
|
+
const elements = arr.getElements();
|
|
766
|
+
for (let j = 0; j < elements.length; j++) {
|
|
767
|
+
const element = elements[j];
|
|
768
|
+
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
769
|
+
unnestSpreadProperties(
|
|
770
|
+
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
|
|
771
|
+
);
|
|
772
|
+
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
773
|
+
unnsetSpreadElements(
|
|
774
|
+
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
|
|
775
|
+
);
|
|
776
|
+
} else if (element.isKind(SyntaxKind.StringLiteral)) {
|
|
777
|
+
const spreadText = element.getText();
|
|
778
|
+
const spreadTest = /^['"](\.\.\..*)['"]$/g;
|
|
779
|
+
if (spreadTest.test(spreadText)) {
|
|
780
|
+
arr.removeElement(j);
|
|
781
|
+
arr.insertElement(j, spreadText.replace(spreadTest, "$1"));
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
async function parseObjectLiteral(objectLiteralString) {
|
|
787
|
+
const sourceFile = await _createSourceFile(
|
|
788
|
+
`const theme = ${objectLiteralString}`,
|
|
789
|
+
null
|
|
790
|
+
);
|
|
791
|
+
const statement = sourceFile.getStatements()[0];
|
|
792
|
+
if (statement?.getKind() === SyntaxKind.VariableStatement) {
|
|
793
|
+
const declaration = statement.getDeclarationList()?.getDeclarations()[0];
|
|
794
|
+
const initializer = declaration.getInitializer();
|
|
795
|
+
if (initializer?.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
796
|
+
return await parseObjectLiteralExpression(initializer);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
throw new Error("Invalid input: not an object literal");
|
|
800
|
+
}
|
|
801
|
+
function parseObjectLiteralExpression(node) {
|
|
802
|
+
const result = {};
|
|
803
|
+
for (const property of node.getProperties()) {
|
|
804
|
+
if (property.isKind(SyntaxKind.PropertyAssignment)) {
|
|
805
|
+
const name = property.getName().replace(/'/g, "");
|
|
806
|
+
if (property.getInitializer()?.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
807
|
+
result[name] = parseObjectLiteralExpression(
|
|
808
|
+
property.getInitializer()
|
|
809
|
+
);
|
|
810
|
+
} else if (property.getInitializer()?.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
811
|
+
result[name] = parseArrayLiteralExpression(
|
|
812
|
+
property.getInitializer()
|
|
813
|
+
);
|
|
814
|
+
} else {
|
|
815
|
+
result[name] = parseValue(property.getInitializer());
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return result;
|
|
820
|
+
}
|
|
821
|
+
function parseArrayLiteralExpression(node) {
|
|
822
|
+
const result = [];
|
|
823
|
+
for (const element of node.getElements()) {
|
|
824
|
+
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
825
|
+
result.push(
|
|
826
|
+
parseObjectLiteralExpression(
|
|
827
|
+
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
|
|
828
|
+
)
|
|
829
|
+
);
|
|
830
|
+
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
|
|
831
|
+
result.push(
|
|
832
|
+
parseArrayLiteralExpression(
|
|
833
|
+
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
|
|
834
|
+
)
|
|
835
|
+
);
|
|
836
|
+
} else {
|
|
837
|
+
result.push(parseValue(element));
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return result;
|
|
841
|
+
}
|
|
842
|
+
function parseValue(node) {
|
|
843
|
+
switch (node.getKind()) {
|
|
844
|
+
case SyntaxKind.StringLiteral:
|
|
845
|
+
return node.getText();
|
|
846
|
+
case SyntaxKind.NumericLiteral:
|
|
847
|
+
return Number(node.getText());
|
|
848
|
+
case SyntaxKind.TrueKeyword:
|
|
849
|
+
return true;
|
|
850
|
+
case SyntaxKind.FalseKeyword:
|
|
851
|
+
return false;
|
|
852
|
+
case SyntaxKind.NullKeyword:
|
|
853
|
+
return null;
|
|
854
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
855
|
+
return node.getElements().map(parseValue);
|
|
856
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
857
|
+
return parseObjectLiteralExpression(node);
|
|
858
|
+
default:
|
|
859
|
+
return node.getText();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
function buildTailwindThemeColorsFromCssVars(cssVars) {
|
|
863
|
+
const result = {};
|
|
864
|
+
for (const key of Object.keys(cssVars)) {
|
|
865
|
+
const parts = key.split("-");
|
|
866
|
+
const colorName = parts[0];
|
|
867
|
+
const subType = parts.slice(1).join("-");
|
|
868
|
+
if (subType === "") {
|
|
869
|
+
if (typeof result[colorName] === "object") {
|
|
870
|
+
result[colorName].DEFAULT = `hsl(var(--${key}))`;
|
|
871
|
+
} else {
|
|
872
|
+
result[colorName] = `hsl(var(--${key}))`;
|
|
873
|
+
}
|
|
874
|
+
} else {
|
|
875
|
+
if (typeof result[colorName] !== "object") {
|
|
876
|
+
result[colorName] = { DEFAULT: `hsl(var(--${colorName}))` };
|
|
877
|
+
}
|
|
878
|
+
result[colorName][subType] = `hsl(var(--${key}))`;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
for (const [colorName, value] of Object.entries(result)) {
|
|
882
|
+
if (typeof value === "object" && value.DEFAULT === `hsl(var(--${colorName}))` && !(colorName in cssVars)) {
|
|
883
|
+
delete value.DEFAULT;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return result;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// src/registry/api.ts
|
|
890
|
+
import deepmerge2 from "deepmerge";
|
|
891
|
+
import { ofetch } from "ofetch";
|
|
892
|
+
import path5 from "pathe";
|
|
893
|
+
import { ProxyAgent } from "undici";
|
|
894
|
+
import { z as z4 } from "zod";
|
|
895
|
+
var REGISTRY_URL = process.env.REGISTRY_URL ?? "https://shadcn-vue.com/r";
|
|
896
|
+
var agent = process.env.https_proxy ? new ProxyAgent(process.env.https_proxy) : void 0;
|
|
897
|
+
var registryCache = /* @__PURE__ */ new Map();
|
|
898
|
+
async function getRegistryIndex() {
|
|
899
|
+
try {
|
|
900
|
+
const [result] = await fetchRegistry(["index.json"]);
|
|
901
|
+
return registryIndexSchema.parse(result);
|
|
902
|
+
} catch (error) {
|
|
903
|
+
logger.error("\n");
|
|
904
|
+
handleError(error);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async function getRegistryStyles() {
|
|
908
|
+
try {
|
|
909
|
+
const [result] = await fetchRegistry(["styles/index.json"]);
|
|
910
|
+
return stylesSchema.parse(result);
|
|
911
|
+
} catch (error) {
|
|
912
|
+
logger.error("\n");
|
|
913
|
+
handleError(error);
|
|
914
|
+
return [];
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
async function getRegistryIcons() {
|
|
918
|
+
try {
|
|
919
|
+
const [result] = await fetchRegistry(["icons/index.json"]);
|
|
920
|
+
return iconsSchema.parse(result);
|
|
921
|
+
} catch (error) {
|
|
922
|
+
handleError(error);
|
|
923
|
+
return {};
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
async function getRegistryItem(name, style) {
|
|
927
|
+
try {
|
|
928
|
+
const [result] = await fetchRegistry([
|
|
929
|
+
isUrl(name) ? name : `styles/${style}/${name}.json`
|
|
930
|
+
]);
|
|
931
|
+
return registryItemSchema.parse(result);
|
|
932
|
+
} catch (error) {
|
|
933
|
+
logger.break();
|
|
934
|
+
handleError(error);
|
|
935
|
+
return null;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
var BASE_COLORS = [
|
|
939
|
+
{
|
|
940
|
+
name: "neutral",
|
|
941
|
+
label: "Neutral"
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
name: "gray",
|
|
945
|
+
label: "Gray"
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
name: "zinc",
|
|
949
|
+
label: "Zinc"
|
|
950
|
+
},
|
|
951
|
+
{
|
|
952
|
+
name: "stone",
|
|
953
|
+
label: "Stone"
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
name: "slate",
|
|
957
|
+
label: "Slate"
|
|
958
|
+
}
|
|
959
|
+
];
|
|
960
|
+
async function getRegistryBaseColors() {
|
|
961
|
+
return BASE_COLORS;
|
|
962
|
+
}
|
|
963
|
+
async function getRegistryBaseColor(baseColor) {
|
|
964
|
+
try {
|
|
965
|
+
const [result] = await fetchRegistry([`colors/${baseColor}.json`]);
|
|
966
|
+
return registryBaseColorSchema.parse(result);
|
|
967
|
+
} catch (error) {
|
|
968
|
+
handleError(error);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
async function fetchTree(style, tree) {
|
|
972
|
+
try {
|
|
973
|
+
const paths = tree.map((item) => `styles/${style}/${item.name}.json`);
|
|
974
|
+
const result = await fetchRegistry(paths);
|
|
975
|
+
return registryIndexSchema.parse(result);
|
|
976
|
+
} catch (error) {
|
|
977
|
+
handleError(error);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
async function getItemTargetPath(config, item, override) {
|
|
981
|
+
if (override) {
|
|
982
|
+
return override;
|
|
983
|
+
}
|
|
984
|
+
if (item.type === "registry:ui") {
|
|
985
|
+
return config.resolvedPaths.ui ?? config.resolvedPaths.components;
|
|
986
|
+
}
|
|
987
|
+
const [parent, type] = item.type?.split(":") ?? [];
|
|
988
|
+
if (!(parent in config.resolvedPaths)) {
|
|
989
|
+
return null;
|
|
990
|
+
}
|
|
991
|
+
return path5.join(
|
|
992
|
+
config.resolvedPaths[parent],
|
|
993
|
+
type
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
async function fetchRegistry(paths) {
|
|
997
|
+
try {
|
|
998
|
+
const results = await Promise.all(
|
|
999
|
+
paths.map(async (path6) => {
|
|
1000
|
+
const url = getRegistryUrl(path6);
|
|
1001
|
+
if (registryCache.has(url)) {
|
|
1002
|
+
return registryCache.get(url);
|
|
1003
|
+
}
|
|
1004
|
+
const response = await ofetch(url, { dispatcher: agent, parseResponse: JSON.parse }).catch((error) => {
|
|
1005
|
+
throw new Error(error.data);
|
|
1006
|
+
});
|
|
1007
|
+
registryCache.set(url, response);
|
|
1008
|
+
return response;
|
|
1009
|
+
})
|
|
1010
|
+
);
|
|
1011
|
+
return results;
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
logger.error("\n");
|
|
1014
|
+
handleError(error);
|
|
1015
|
+
return [];
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
async function registryResolveItemsTree(names, config) {
|
|
1019
|
+
try {
|
|
1020
|
+
const index = await getRegistryIndex();
|
|
1021
|
+
if (!index) {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
if (names.includes("index")) {
|
|
1025
|
+
names.unshift("index");
|
|
1026
|
+
}
|
|
1027
|
+
const registryDependencies = /* @__PURE__ */ new Set();
|
|
1028
|
+
for (const name of names) {
|
|
1029
|
+
const itemRegistryDependencies = await resolveRegistryDependencies(
|
|
1030
|
+
name,
|
|
1031
|
+
config
|
|
1032
|
+
);
|
|
1033
|
+
itemRegistryDependencies.forEach((dep) => registryDependencies.add(dep));
|
|
1034
|
+
}
|
|
1035
|
+
const uniqueRegistryDependencies = Array.from(registryDependencies);
|
|
1036
|
+
const result = await fetchRegistry(uniqueRegistryDependencies);
|
|
1037
|
+
const payload = z4.array(registryItemSchema).parse(result);
|
|
1038
|
+
if (!payload) {
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
if (names.includes("index")) {
|
|
1042
|
+
if (config.tailwind.baseColor) {
|
|
1043
|
+
const theme = await registryGetTheme(config.tailwind.baseColor, config);
|
|
1044
|
+
if (theme) {
|
|
1045
|
+
payload.unshift(theme);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
let tailwind = {};
|
|
1050
|
+
payload.forEach((item) => {
|
|
1051
|
+
tailwind = deepmerge2(tailwind, item.tailwind ?? {});
|
|
1052
|
+
});
|
|
1053
|
+
let cssVars = {};
|
|
1054
|
+
payload.forEach((item) => {
|
|
1055
|
+
cssVars = deepmerge2(cssVars, item.cssVars ?? {});
|
|
1056
|
+
});
|
|
1057
|
+
let docs = "";
|
|
1058
|
+
payload.forEach((item) => {
|
|
1059
|
+
if (item.docs) {
|
|
1060
|
+
docs += `${item.docs}
|
|
1061
|
+
`;
|
|
1062
|
+
}
|
|
1063
|
+
});
|
|
1064
|
+
return registryResolvedItemsTreeSchema.parse({
|
|
1065
|
+
dependencies: Array.from(new Set(payload.flatMap((item) => item.dependencies ?? []))),
|
|
1066
|
+
devDependencies: Array.from(new Set(payload.flatMap((item) => item.devDependencies ?? []))),
|
|
1067
|
+
files: deepmerge2.all(payload.map((item) => item.files ?? [])),
|
|
1068
|
+
tailwind,
|
|
1069
|
+
cssVars,
|
|
1070
|
+
docs
|
|
1071
|
+
});
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
handleError(error);
|
|
1074
|
+
return null;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
async function resolveRegistryDependencies(url, config) {
|
|
1078
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1079
|
+
const payload = [];
|
|
1080
|
+
const style = config.resolvedPaths?.cwd ? await getTargetStyleFromConfig(config.resolvedPaths.cwd, config.style) : config.style;
|
|
1081
|
+
async function resolveDependencies(itemUrl) {
|
|
1082
|
+
const url2 = getRegistryUrl(
|
|
1083
|
+
isUrl(itemUrl) ? itemUrl : `styles/${style}/${itemUrl}.json`
|
|
1084
|
+
);
|
|
1085
|
+
if (visited.has(url2)) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
visited.add(url2);
|
|
1089
|
+
try {
|
|
1090
|
+
const [result] = await fetchRegistry([url2]);
|
|
1091
|
+
const item = registryItemSchema.parse(result);
|
|
1092
|
+
payload.push(url2);
|
|
1093
|
+
if (item.registryDependencies) {
|
|
1094
|
+
for (const dependency of item.registryDependencies) {
|
|
1095
|
+
await resolveDependencies(dependency);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
} catch (error) {
|
|
1099
|
+
console.error(
|
|
1100
|
+
`Error fetching or parsing registry item at ${itemUrl}:`,
|
|
1101
|
+
error
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
await resolveDependencies(url);
|
|
1106
|
+
return Array.from(new Set(payload));
|
|
1107
|
+
}
|
|
1108
|
+
async function registryGetTheme(name, config) {
|
|
1109
|
+
const [baseColor, tailwindVersion] = await Promise.all([
|
|
1110
|
+
getRegistryBaseColor(name),
|
|
1111
|
+
getProjectTailwindVersionFromConfig(config)
|
|
1112
|
+
]);
|
|
1113
|
+
if (!baseColor) {
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
const theme = {
|
|
1117
|
+
name,
|
|
1118
|
+
type: "registry:theme",
|
|
1119
|
+
tailwind: {
|
|
1120
|
+
config: {
|
|
1121
|
+
theme: {
|
|
1122
|
+
extend: {
|
|
1123
|
+
borderRadius: {
|
|
1124
|
+
lg: "var(--radius)",
|
|
1125
|
+
md: "calc(var(--radius) - 2px)",
|
|
1126
|
+
sm: "calc(var(--radius) - 4px)"
|
|
1127
|
+
},
|
|
1128
|
+
colors: {}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
cssVars: {
|
|
1134
|
+
theme: {},
|
|
1135
|
+
light: {
|
|
1136
|
+
radius: "0.5rem"
|
|
1137
|
+
},
|
|
1138
|
+
dark: {}
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
if (config.tailwind.cssVariables) {
|
|
1142
|
+
theme.tailwind.config.theme.extend.colors = {
|
|
1143
|
+
...theme.tailwind.config.theme.extend.colors,
|
|
1144
|
+
...buildTailwindThemeColorsFromCssVars(baseColor.cssVars.dark ?? {})
|
|
1145
|
+
};
|
|
1146
|
+
theme.cssVars = {
|
|
1147
|
+
theme: {
|
|
1148
|
+
...baseColor.cssVars.theme,
|
|
1149
|
+
...theme.cssVars.theme
|
|
1150
|
+
},
|
|
1151
|
+
light: {
|
|
1152
|
+
...baseColor.cssVars.light,
|
|
1153
|
+
...theme.cssVars.light
|
|
1154
|
+
},
|
|
1155
|
+
dark: {
|
|
1156
|
+
...baseColor.cssVars.dark,
|
|
1157
|
+
...theme.cssVars.dark
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
if (tailwindVersion === "v4" && baseColor.cssVarsV4) {
|
|
1161
|
+
theme.cssVars = {
|
|
1162
|
+
theme: {
|
|
1163
|
+
...baseColor.cssVarsV4.theme,
|
|
1164
|
+
...theme.cssVars.theme
|
|
1165
|
+
},
|
|
1166
|
+
light: {
|
|
1167
|
+
...theme.cssVars.light,
|
|
1168
|
+
...baseColor.cssVarsV4.light
|
|
1169
|
+
},
|
|
1170
|
+
dark: {
|
|
1171
|
+
...theme.cssVars.dark,
|
|
1172
|
+
...baseColor.cssVarsV4.dark
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
return theme;
|
|
1178
|
+
}
|
|
1179
|
+
function getRegistryUrl(path6) {
|
|
1180
|
+
if (isUrl(path6)) {
|
|
1181
|
+
const url = new URL(path6);
|
|
1182
|
+
if (url.pathname.match(/\/chat\/b\//) && !url.pathname.endsWith("/json")) {
|
|
1183
|
+
url.pathname = `${url.pathname}/json`;
|
|
1184
|
+
}
|
|
1185
|
+
return url.toString();
|
|
1186
|
+
}
|
|
1187
|
+
return `${REGISTRY_URL}/${path6}`;
|
|
1188
|
+
}
|
|
1189
|
+
function isUrl(path6) {
|
|
1190
|
+
try {
|
|
1191
|
+
new URL(path6);
|
|
1192
|
+
return true;
|
|
1193
|
+
} catch (error) {
|
|
1194
|
+
return false;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
async function resolveRegistryItems(names, config) {
|
|
1198
|
+
const registryDependencies = [];
|
|
1199
|
+
for (const name of names) {
|
|
1200
|
+
const itemRegistryDependencies = await resolveRegistryDependencies(
|
|
1201
|
+
name,
|
|
1202
|
+
config
|
|
1203
|
+
);
|
|
1204
|
+
registryDependencies.push(...itemRegistryDependencies);
|
|
1205
|
+
}
|
|
1206
|
+
return Array.from(new Set(registryDependencies));
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
export {
|
|
1210
|
+
highlighter,
|
|
1211
|
+
DEFAULT_COMPONENTS,
|
|
1212
|
+
DEFAULT_UTILS,
|
|
1213
|
+
DEFAULT_TAILWIND_CSS,
|
|
1214
|
+
DEFAULT_TAILWIND_CONFIG,
|
|
1215
|
+
rawConfigSchema,
|
|
1216
|
+
getConfig,
|
|
1217
|
+
resolveConfigPaths,
|
|
1218
|
+
getPackageInfo,
|
|
1219
|
+
getProjectInfo,
|
|
1220
|
+
getProjectConfig,
|
|
1221
|
+
getProjectTailwindVersionFromConfig,
|
|
1222
|
+
logger,
|
|
1223
|
+
spinner,
|
|
1224
|
+
registryItemTypeSchema,
|
|
1225
|
+
registryItemFileSchema,
|
|
1226
|
+
registryItemTailwindSchema,
|
|
1227
|
+
registryItemCssVarsSchema,
|
|
1228
|
+
registryItemCssSchema,
|
|
1229
|
+
registryItemSchema,
|
|
1230
|
+
registrySchema,
|
|
1231
|
+
registryIndexSchema,
|
|
1232
|
+
stylesSchema,
|
|
1233
|
+
iconsSchema,
|
|
1234
|
+
registryBaseColorSchema,
|
|
1235
|
+
registryResolvedItemsTreeSchema,
|
|
1236
|
+
handleError,
|
|
1237
|
+
updateTailwindConfig,
|
|
1238
|
+
_createSourceFile,
|
|
1239
|
+
_getQuoteChar,
|
|
1240
|
+
getRegistryIndex,
|
|
1241
|
+
getRegistryStyles,
|
|
1242
|
+
getRegistryIcons,
|
|
1243
|
+
getRegistryItem,
|
|
1244
|
+
BASE_COLORS,
|
|
1245
|
+
getRegistryBaseColors,
|
|
1246
|
+
getRegistryBaseColor,
|
|
1247
|
+
fetchTree,
|
|
1248
|
+
getItemTargetPath,
|
|
1249
|
+
fetchRegistry,
|
|
1250
|
+
registryResolveItemsTree,
|
|
1251
|
+
isUrl,
|
|
1252
|
+
resolveRegistryItems
|
|
1253
|
+
};
|
|
1254
|
+
//# sourceMappingURL=chunk-MOIE35VS.js.map
|