New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

shadcn-ui

Package Overview
Dependencies
Maintainers
2
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shadcn-ui - npm Package Compare versions

Comparing version 0.0.0-beta.a2cd57d to 0.0.0-beta.b99465d

1102

dist/index.js
#!/usr/bin/env node
import{existsSync as B,promises as he}from"fs";import R from"path";import X from"path";import{createMatchPath as Fe}from"tsconfig-paths";async function b(t,e){return Fe(e.absoluteBaseUrl,e.paths)(t,void 0,()=>!0,[".ts",".tsx"])}import{cosmiconfig as je}from"cosmiconfig";import{loadConfig as Ne}from"tsconfig-paths";import*as m from"zod";var Y="@/components",Z="@/lib/utils",Q="app/globals.css",ee="tailwind.config.js";var Oe=je("components",{searchPlaces:["components.json"]}),k=m.object({$schema:m.string().optional(),style:m.string(),rsc:m.coerce.boolean().default(!1),tsx:m.coerce.boolean().default(!0),tailwind:m.object({config:m.string(),css:m.string(),baseColor:m.string(),cssVariables:m.boolean().default(!0),prefix:m.string().default("").optional()}),aliases:m.object({components:m.string(),utils:m.string(),ui:m.string().optional()})}).strict(),We=k.extend({resolvedPaths:m.object({tailwindConfig:m.string(),tailwindCss:m.string(),utils:m.string(),components:m.string(),ui:m.string()})});async function C(t){let e=await _e(t);return e?await U(t,e):null}async function U(t,e){let o=await Ne(t);if(o.resultType==="failed")throw new Error(`Failed to load ${e.tsx?"tsconfig":"jsconfig"}.json. ${o.message??""}`.trim());return We.parse({...e,resolvedPaths:{tailwindConfig:X.resolve(t,e.tailwind.config),tailwindCss:X.resolve(t,e.tailwind.css),utils:await b(e.aliases.utils,o),components:await b(e.aliases.components,o),ui:e.aliases.ui?await b(e.aliases.ui,o):await b(e.aliases.components,o)}})}async function _e(t){try{let e=await Oe.search(t);return e?k.parse(e.config):null}catch{throw new Error(`Invalid configuration found in ${t}/components.json.`)}}import{detect as Re}from"@antfu/ni";async function L(t){let e=await Re({programmatic:!0,cwd:t});return e==="yarn@berry"?"yarn":e==="pnpm@6"?"pnpm":e==="bun"?"bun":e??"npm"}import D from"chalk";var l={error(...t){console.log(D.red(...t))},warn(...t){console.log(D.yellow(...t))},info(...t){console.log(D.cyan(...t))},success(...t){console.log(D.green(...t))},break(){console.log("")}};function T(t){typeof t=="string"&&(l.error(t),process.exit(1)),t instanceof Error&&(l.error(t.message),process.exit(1)),l.error("Something went wrong. Please try again."),process.exit(1)}import Ke from"path";import*as s from"zod";var te=s.object({name:s.string(),dependencies:s.array(s.string()).optional(),devDependencies:s.array(s.string()).optional(),registryDependencies:s.array(s.string()).optional(),files:s.array(s.string()),type:s.enum(["components:ui","components:component","components:example"])}),re=s.array(te),Ue=te.extend({files:s.array(s.object({name:s.string(),content:s.string()}))}),oe=s.array(Ue),ne=s.array(s.object({name:s.string(),label:s.string()})),ie=s.object({inlineColors:s.object({light:s.record(s.string(),s.string()),dark:s.record(s.string(),s.string())}),cssVars:s.object({light:s.record(s.string(),s.string()),dark:s.record(s.string(),s.string())}),inlineColorsTemplate:s.string(),cssVarsTemplate:s.string()});import{HttpsProxyAgent as Me}from"https-proxy-agent";import Be from"node-fetch";var se=process.env.COMPONENTS_REGISTRY_URL??"https://ui.shadcn.com",Ve=process.env.https_proxy?new Me(process.env.https_proxy):void 0;async function F(){try{let[t]=await O(["index.json"]);return re.parse(t)}catch{throw new Error("Failed to fetch components from registry.")}}async function ae(){try{let[t]=await O(["styles/index.json"]);return ne.parse(t)}catch{throw new Error("Failed to fetch styles from registry.")}}async function ce(){return[{name:"slate",label:"Slate"},{name:"gray",label:"Gray"},{name:"zinc",label:"Zinc"},{name:"neutral",label:"Neutral"},{name:"stone",label:"Stone"}]}async function S(t){try{let[e]=await O([`colors/${t}.json`]);return ie.parse(e)}catch{throw new Error("Failed to fetch base color from registry.")}}async function K(t,e){let o=[];for(let r of e){let n=t.find(i=>i.name===r);if(n&&(o.push(n),n.registryDependencies)){let i=await K(t,n.registryDependencies);o.push(...i)}}return o.filter((r,n,i)=>i.findIndex(a=>a.name===r.name)===n)}async function j(t,e){try{let o=e.map(n=>`styles/${t}/${n.name}.json`),r=await O(o);return oe.parse(r)}catch{throw new Error("Failed to fetch tree from registry.")}}async function N(t,e,o){if(o)return o;if(e.type==="components:ui"&&t.aliases.ui)return t.resolvedPaths.ui;let[r,n]=e.type.split(":");return r in t.resolvedPaths?Ke.join(t.resolvedPaths[r],n):null}async function O(t){try{return await Promise.all(t.map(async o=>await(await Be(`${se}/registry/${o}`,{agent:Ve})).json()))}catch(e){throw console.log(e),new Error(`Failed to fetch registry from ${se}.`)}}import{promises as et}from"fs";import{tmpdir as tt}from"os";import ue from"path";import{SyntaxKind as Ge}from"ts-morph";var le=async({sourceFile:t,config:e,baseColor:o})=>(e.tailwind?.cssVariables||!o?.inlineColors||t.getDescendantsOfKind(Ge.StringLiteral).forEach(r=>{let n=r.getText();if(n){let i=He(n.replace(/"/g,""),o.inlineColors);r.replaceWithText(`"${i.trim()}"`)}}),t);function M(t){if(!t.includes("/")&&!t.includes(":"))return[null,t,null];let e=[],[o,r]=t.split("/");if(!o.includes(":"))return[null,o,r];let n=o.split(":"),i=n.pop(),a=n.join(":");return e.push(a??null,i??null,r??null),e}var Je=["bg-","text-","border-","ring-offset-","ring-"];function He(t,e){t.includes(" border ")&&(t=t.replace(" border "," border border-border "));let o=t.split(" "),r=new Set,n=new Set;for(let i of o){let[a,f,d]=M(i),h=Je.find(c=>f?.startsWith(c));if(!h){r.has(i)||r.add(i);continue}let p=f?.replace(h,"");if(p&&p in e.light){r.add([a,`${h}${e.light[p]}`].filter(Boolean).join(":")+(d?`/${d}`:"")),n.add(["dark",a,`${h}${e.dark[p]}`].filter(Boolean).join(":")+(d?`/${d}`:""));continue}r.has(i)||r.add(i)}return[...Array.from(r),...Array.from(n)].join(" ").trim()}var pe=async({sourceFile:t,config:e})=>{let o=t.getImportDeclarations();for(let r of o){let n=r.getModuleSpecifierValue();n.startsWith("@/registry/")&&(e.aliases.ui?r.setModuleSpecifier(n.replace(/^@\/registry\/[^/]+\/ui/,e.aliases.ui)):r.setModuleSpecifier(n.replace(/^@\/registry\/[^/]+/,e.aliases.components))),n=="@/lib/utils"&&r.getNamedImports().find(f=>f.getName()==="cn")&&r.setModuleSpecifier(n.replace(/^@\/lib\/utils/,e.aliases.utils))}return t};import{transformFromAstSync as qe}from"@babel/core";import{parse as Xe}from"@babel/parser";import Ye from"@babel/plugin-transform-typescript";import*as W from"recast";var Ze={sourceType:"module",allowImportExportEverywhere:!0,allowReturnOutsideFunction:!0,startLine:1,tokens:!0,plugins:["asyncGenerators","bigInt","classPrivateMethods","classPrivateProperties","classProperties","classStaticBlock","decimal","decorators-legacy","doExpressions","dynamicImport","exportDefaultFrom","exportNamespaceFrom","functionBind","functionSent","importAssertions","importMeta","nullishCoalescingOperator","numericSeparator","objectRestSpread","optionalCatchBinding","optionalChaining",["pipelineOperator",{proposal:"minimal"}],["recordAndTuple",{syntaxType:"hash"}],"throwExpressions","topLevelAwait","v8intrinsic","typescript","jsx"]},me=async({sourceFile:t,config:e})=>{let o=t.getFullText();if(e.tsx)return o;let r=W.parse(o,{parser:{parse:i=>Xe(i,Ze)}}),n=qe(r,o,{cloneInputAst:!1,code:!1,ast:!0,plugins:[Ye],configFile:!1});if(!n||!n.ast)throw new Error("Failed to transform JSX");return W.print(n.ast).code};import{SyntaxKind as Qe}from"ts-morph";var fe=async({sourceFile:t,config:e})=>{if(e.rsc)return t;let o=t.getFirstChildByKind(Qe.ExpressionStatement);return o?.getText()==='"use client"'&&o.remove(),t};import{Project as rt,ScriptKind as ot}from"ts-morph";import{SyntaxKind as g}from"ts-morph";var de=async({sourceFile:t,config:e})=>(e.tailwind?.prefix&&(t.getDescendantsOfKind(g.CallExpression).filter(o=>o.getExpression().getText()==="cva").forEach(o=>{if(o.getArguments()[0]?.isKind(g.StringLiteral)){let r=o.getArguments()[0];r&&r.replaceWithText(`"${y(r.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)}o.getArguments()[1]?.isKind(g.ObjectLiteralExpression)&&o.getArguments()[1]?.getDescendantsOfKind(g.PropertyAssignment).find(r=>r.getName()==="variants")?.getDescendantsOfKind(g.PropertyAssignment).forEach(r=>{r.getDescendantsOfKind(g.PropertyAssignment).forEach(n=>{let i=n.getInitializerIfKind(g.StringLiteral);i&&i?.replaceWithText(`"${y(i.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)})})}),t.getDescendantsOfKind(g.JsxAttribute).forEach(o=>{if(o.getName()==="className"){if(o.getInitializer()?.isKind(g.StringLiteral)){let r=o.getInitializer();r&&r.replaceWithText(`"${y(r.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)}if(o.getInitializer()?.isKind(g.JsxExpression)){let r=o.getInitializer()?.getDescendantsOfKind(g.CallExpression).find(n=>n.getExpression().getText()==="cn");r&&r.getArguments().forEach(n=>{(n.isKind(g.ConditionalExpression)||n.isKind(g.BinaryExpression))&&n.getChildrenOfKind(g.StringLiteral).forEach(i=>{i.replaceWithText(`"${y(i.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)}),n.isKind(g.StringLiteral)&&n.replaceWithText(`"${y(n.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)})}}o.getName()==="classNames"&&o.getInitializer()?.isKind(g.JsxExpression)&&o.getDescendantsOfKind(g.PropertyAssignment).forEach(r=>{if(r.getInitializer()?.isKind(g.CallExpression)){let n=r.getInitializerIfKind(g.CallExpression);n&&n.getArguments().forEach(i=>{i.isKind(g.ConditionalExpression)&&i.getChildrenOfKind(g.StringLiteral).forEach(a=>{a.replaceWithText(`"${y(a.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)}),i.isKind(g.StringLiteral)&&i.replaceWithText(`"${y(i.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)})}if(r.getInitializer()?.isKind(g.StringLiteral)&&r.getName()!=="variant"){let n=r.getInitializer();n&&n.replaceWithText(`"${y(n.getText()?.replace(/"/g,""),e.tailwind.prefix)}"`)}})})),t);function y(t,e=""){let o=t.split(" "),r=[];for(let n of o){let[i,a,f]=M(n);i?f?r.push(`${i}:${e}${a}/${f}`):r.push(`${i}:${e}${a}`):f?r.push(`${e}${a}/${f}`):r.push(`${e}${a}`)}return r.join(" ")}function ge(t,e){let o=t.split(`
`);for(let r of o)if(r.includes("@apply")){let n=r.replace("@apply","").trim(),i=y(n,e);t=t.replace(n,i)}return t}var nt=[pe,fe,le,de],it=new rt({compilerOptions:{}});async function st(t){let e=await et.mkdtemp(ue.join(tt(),"shadcn-"));return ue.join(e,t)}async function _(t){let e=await st(t.filename),o=it.createSourceFile(e,t.raw,{scriptKind:ot.TSX});for(let r of nt)r({sourceFile:o,...t});return await me({sourceFile:o,...t})}import xe from"chalk";import{Command as at}from"commander";import{execa as ye}from"execa";import ct from"ora";import V from"prompts";import*as x from"zod";var lt=x.object({components:x.array(x.string()).optional(),yes:x.boolean(),overwrite:x.boolean(),cwd:x.string(),all:x.boolean(),path:x.string().optional()}),we=new at().name("add").description("add a component to your project").argument("[components...]","the components to add").option("-y, --yes","skip confirmation prompt.",!0).option("-o, --overwrite","overwrite existing files.",!1).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-a, --all","add all available components",!1).option("-p, --path <path>","the path to add the component to.").action(async(t,e)=>{try{let o=lt.parse({components:t,...e}),r=R.resolve(o.cwd);B(r)||(l.error(`The path ${r} does not exist. Please try again.`),process.exit(1));let n=await C(r);n||(l.warn(`Configuration is missing. Please run ${xe.green("init")} to create a components.json file.`),process.exit(1));let i=await F(),a=o.all?i.map(c=>c.name):o.components;if(!o.components?.length&&!o.all){let{components:c}=await V({type:"multiselect",name:"components",message:"Which components would you like to add?",hint:"Space to select. A to toggle all. Enter to submit.",instructions:!1,choices:i.map(u=>({title:u.name,value:u.name,selected:o.all?!0:o.components?.includes(u.name)}))});a=c}a?.length||(l.warn("No components selected. Exiting."),process.exit(0));let f=await K(i,a),d=await j(n.style,f),h=await S(n.tailwind.baseColor);if(d.length||(l.warn("Selected components not found. Exiting."),process.exit(0)),!o.yes){let{proceed:c}=await V({type:"confirm",name:"proceed",message:"Ready to install components and dependencies. Proceed?",initial:!0});c||process.exit(0)}let p=ct("Installing components...").start();for(let c of d){p.text=`Installing ${c.name}...`;let u=await N(n,c,o.path?R.resolve(r,o.path):void 0);if(!u)continue;if(B(u)||await he.mkdir(u,{recursive:!0}),c.files.filter(v=>B(R.resolve(u,v.name))).length&&!o.overwrite)if(a.includes(c.name)){p.stop();let{overwrite:v}=await V({type:"confirm",name:"overwrite",message:`Component ${c.name} already exists. Would you like to overwrite?`,initial:!1});if(!v){l.info(`Skipped ${c.name}. To overwrite, run with the ${xe.green("--overwrite")} flag.`);continue}p.start(`Installing ${c.name}...`)}else continue;for(let v of c.files){let z=R.resolve(u,v.name),De=await _({filename:v.name,raw:v.content,config:n,baseColor:h});n.tsx||(z=z.replace(/\.tsx$/,".jsx"),z=z.replace(/\.ts$/,".js")),await he.writeFile(z,De)}let A=await L(r);c.dependencies?.length&&await ye(A,[A==="npm"?"install":"add",...c.dependencies],{cwd:r}),c.devDependencies?.length&&await ye(A,[A==="npm"?"install":"add","-D",...c.devDependencies],{cwd:r})}p.succeed("Done.")}catch(o){T(o)}});import{existsSync as G,promises as pt}from"fs";import J from"path";import E from"chalk";import{Command as mt}from"commander";import{diffLines as ft}from"diff";import*as w from"zod";var dt=w.object({component:w.string().optional(),yes:w.boolean(),cwd:w.string(),path:w.string().optional()}),Ce=new mt().name("diff").description("check for updates against the registry").argument("[component]","the component name").option("-y, --yes","skip confirmation prompt.",!1).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).action(async(t,e)=>{try{let o=dt.parse({component:t,...e}),r=J.resolve(o.cwd);G(r)||(l.error(`The path ${r} does not exist. Please try again.`),process.exit(1));let n=await C(r);n||(l.warn(`Configuration is missing. Please run ${E.green("init")} to create a components.json file.`),process.exit(1));let i=await F();if(!o.component){let d=n.resolvedPaths.components,h=i.filter(c=>{for(let u of c.files){let q=J.resolve(d,u);if(G(q))return!0}return!1}),p=[];for(let c of h){let u=await ve(c,n);u.length&&p.push({name:c.name,changes:u})}p.length||(l.info("No updates found."),process.exit(0)),l.info("The following components have updates available:");for(let c of p){l.info(`- ${c.name}`);for(let u of c.changes)l.info(` - ${u.filePath}`)}l.break(),l.info(`Run ${E.green("diff <component>")} to see the changes.`),process.exit(0)}let a=i.find(d=>d.name===o.component);a||(l.error(`The component ${E.green(o.component)} does not exist.`),process.exit(1));let f=await ve(a,n);f.length||(l.info(`No updates found for ${o.component}.`),process.exit(0));for(let d of f)l.info(`- ${d.filePath}`),await gt(d.patch),l.info("")}catch(o){T(o)}});async function ve(t,e){let o=await j(e.style,[t]),r=await S(e.tailwind.baseColor),n=[];for(let i of o){let a=await N(e,i);if(a)for(let f of i.files){let d=J.resolve(a,f.name);if(!G(d))continue;let h=await pt.readFile(d,"utf8"),p=await _({filename:f.name,raw:f.content,config:e,baseColor:r}),c=ft(p,h);c.length>1&&n.push({file:f.name,filePath:d,patch:c})}}return n}async function gt(t){t.forEach(e=>{if(e)return e.added?process.stdout.write(E.green(e.value)):e.removed?process.stdout.write(E.red(e.value)):process.stdout.write(e.value)})}import{existsSync as $e,promises as P}from"fs";import $ from"path";var Te=`import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
// src/commands/add.ts
import { existsSync, promises as fs3 } from "fs";
import path5 from "path";
// src/utils/get-config.ts
import path from "path";
// src/utils/resolve-import.ts
import { createMatchPath } from "tsconfig-paths";
async function resolveImport(importPath, config) {
return createMatchPath(config.absoluteBaseUrl, config.paths)(
importPath,
void 0,
() => true,
[".ts", ".tsx"]
);
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
`,Se=`import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
// src/utils/get-config.ts
import { cosmiconfig } from "cosmiconfig";
import { loadConfig } from "tsconfig-paths";
import * as z from "zod";
var DEFAULT_COMPONENTS = "@/components";
var DEFAULT_UTILS = "@/lib/utils";
var DEFAULT_TAILWIND_CSS = "app/globals.css";
var DEFAULT_TAILWIND_CONFIG = "tailwind.config.js";
var explorer = cosmiconfig("components", {
searchPlaces: ["components.json"]
});
var rawConfigSchema = z.object({
style: z.string(),
rsc: z.coerce.boolean().default(false),
tailwind: z.object({
config: z.string(),
css: z.string(),
baseColor: z.string(),
cssVariables: z.boolean().default(true)
}),
aliases: z.object({
components: z.string(),
utils: z.string()
})
}).strict();
var configSchema = rawConfigSchema.extend({
resolvedPaths: z.object({
tailwindConfig: z.string(),
tailwindCss: z.string(),
utils: z.string(),
components: z.string()
})
});
async function getConfig(cwd) {
const config = await getRawConfig(cwd);
if (!config) {
return null;
}
return await resolveConfigPaths(cwd, config);
}
async function resolveConfigPaths(cwd, config) {
const tsConfig = await loadConfig(cwd);
if (tsConfig.resultType === "failed") {
throw new Error(
`Failed to load tsconfig.json. ${tsConfig.message ?? ""}`.trim()
);
}
return configSchema.parse({
...config,
resolvedPaths: {
tailwindConfig: path.resolve(cwd, config.tailwind.config),
tailwindCss: path.resolve(cwd, config.tailwind.css),
utils: await resolveImport(config.aliases["utils"], tsConfig),
components: await resolveImport(config.aliases["components"], tsConfig)
}
});
}
async function getRawConfig(cwd) {
try {
const configResult = await explorer.search(cwd);
if (!configResult) {
return null;
}
return rawConfigSchema.parse(configResult.config);
} catch (error) {
throw new Error(`Invald configuration found in ${cwd}/components.json.`);
}
}
// src/utils/get-package-manager.ts
import { promises as fs } from "fs";
import path2 from "path";
async function fileExists(path9) {
try {
await fs.access(path9);
return true;
} catch {
return false;
}
}
async function getPackageManager(targetDir) {
const [yarnLock, npmLock, pnpmLock] = await Promise.all([
fileExists(path2.resolve(targetDir, "yarn.lock")),
fileExists(path2.resolve(targetDir, "package-lock.json")),
fileExists(path2.resolve(targetDir, "pnpm-lock.yaml"))
]);
if (yarnLock) {
return "yarn";
}
if (pnpmLock) {
return "pnpm";
}
if (npmLock) {
return "npm";
}
const userAgent = process.env.npm_config_user_agent;
if (!userAgent) {
return "npm";
}
if (userAgent.startsWith("yarn")) {
return "yarn";
}
if (userAgent.startsWith("pnpm")) {
return "pnpm";
}
return "npm";
}
// src/utils/logger.ts
import chalk from "chalk";
var logger = {
error(...args) {
console.log(chalk.red(...args));
},
warn(...args) {
console.log(chalk.yellow(...args));
},
info(...args) {
console.log(chalk.cyan(...args));
},
success(...args) {
console.log(chalk.green(...args));
},
break() {
console.log("");
}
};
// src/utils/handle-error.ts
function handleError(error) {
if (typeof error === "string") {
logger.error(error);
process.exit(1);
}
if (error instanceof Error) {
logger.error(error.message);
process.exit(1);
}
logger.error("Something went wrong. Please try again.");
process.exit(1);
}
// src/utils/registry/index.ts
import path3 from "path";
// src/utils/registry/schema.ts
import * as z2 from "zod";
var registryItemSchema = z2.object({
name: z2.string(),
dependencies: z2.array(z2.string()).optional(),
registryDependencies: z2.array(z2.string()).optional(),
files: z2.array(z2.string()),
type: z2.enum(["components:ui", "components:component", "components:example"])
});
var registryIndexSchema = z2.array(registryItemSchema);
var registryItemWithContentSchema = registryItemSchema.extend({
files: z2.array(
z2.object({
name: z2.string(),
content: z2.string()
})
)
});
var registryWithContentSchema = z2.array(registryItemWithContentSchema);
var stylesSchema = z2.array(
z2.object({
name: z2.string(),
label: z2.string()
})
);
var registryBaseColorSchema = z2.object({
inlineColors: z2.object({
light: z2.record(z2.string(), z2.string()),
dark: z2.record(z2.string(), z2.string())
}),
cssVars: z2.object({
light: z2.record(z2.string(), z2.string()),
dark: z2.record(z2.string(), z2.string())
}),
inlineColorsTemplate: z2.string(),
cssVarsTemplate: z2.string()
});
// src/utils/registry/index.ts
import { HttpsProxyAgent } from "https-proxy-agent";
import fetch from "node-fetch";
var baseUrl = process.env.COMPONENTS_REGISTRY_URL ?? "https://ui.shadcn.com";
var agent = process.env.https_proxy ? new HttpsProxyAgent(process.env.https_proxy) : void 0;
async function getRegistryIndex() {
try {
const [result] = await fetchRegistry(["index.json"]);
return registryIndexSchema.parse(result);
} catch (error) {
throw new Error(`Failed to fetch components from registry.`);
}
}
async function getRegistryStyles() {
try {
const [result] = await fetchRegistry(["styles/index.json"]);
return stylesSchema.parse(result);
} catch (error) {
throw new Error(`Failed to fetch styles from registry.`);
}
}
async function getRegistryBaseColors() {
return [
{
name: "slate",
label: "Slate"
},
{
name: "gray",
label: "Gray"
},
{
name: "zinc",
label: "Zinc"
},
{
name: "neutral",
label: "Neutral"
},
{
name: "stone",
label: "Stone"
}
];
}
async function getRegistryBaseColor(baseColor) {
try {
const [result] = await fetchRegistry([`colors/${baseColor}.json`]);
return registryBaseColorSchema.parse(result);
} catch (error) {
throw new Error(`Failed to fetch base color from registry.`);
}
}
async function resolveTree(index, names) {
const tree = [];
for (const name of names) {
const entry = index.find((entry2) => entry2.name === name);
if (!entry) {
continue;
}
tree.push(entry);
if (entry.registryDependencies) {
const dependencies = await resolveTree(index, entry.registryDependencies);
tree.push(...dependencies);
}
}
return tree.filter(
(component, index2, self) => self.findIndex((c) => c.name === component.name) === index2
);
}
async function fetchTree(style, tree) {
try {
const paths = tree.map((item) => `styles/${style}/${item.name}.json`);
const result = await fetchRegistry(paths);
return registryWithContentSchema.parse(result);
} catch (error) {
throw new Error(`Failed to fetch tree from registry.`);
}
}
async function getItemTargetPath(config, item, override) {
if (override && item.type !== "components:ui") {
return override;
}
const [parent, type] = item.type.split(":");
if (!(parent in config.resolvedPaths)) {
return null;
}
return path3.join(
config.resolvedPaths[parent],
type
);
}
async function fetchRegistry(paths) {
try {
const results = await Promise.all(
paths.map(async (path9) => {
const response = await fetch(`${baseUrl}/registry/${path9}`, {
agent
});
return await response.json();
})
);
return results;
} catch (error) {
console.log(error);
throw new Error(`Failed to fetch registry from ${baseUrl}.`);
}
}
// src/utils/transformers/index.ts
import { promises as fs2 } from "fs";
import { tmpdir } from "os";
import path4 from "path";
// src/utils/transformers/transform-css-vars.ts
import { SyntaxKind } from "ts-morph";
var transformCssVars = async ({
sourceFile,
config,
baseColor
}) => {
if (config.tailwind?.cssVariables || !baseColor?.inlineColors) {
return sourceFile;
}
sourceFile.getDescendantsOfKind(SyntaxKind.StringLiteral).forEach((node) => {
const value = node.getText();
if (value) {
const valueWithColorMapping = applyColorMapping(
value.replace(/"/g, ""),
baseColor.inlineColors
);
node.replaceWithText(`"${valueWithColorMapping.trim()}"`);
}
});
return sourceFile;
};
function splitClassName(className) {
if (!className.includes("/") && !className.includes(":")) {
return [null, className, null];
}
const parts = [];
let [rest, alpha] = className.split("/");
if (!rest.includes(":")) {
return [null, rest, alpha];
}
const split = rest.split(":");
const name = split.pop();
const variant = split.join(":");
parts.push(variant ?? null, name ?? null, alpha ?? null);
return parts;
}
var PREFIXES = ["bg-", "text-", "border-", "ring-offset-", "ring-"];
function applyColorMapping(input, mapping) {
if (input.includes(" border ")) {
input = input.replace(" border ", " border border-border ");
}
const classNames = input.split(" ");
const lightMode = [];
const darkMode = [];
for (let className of classNames) {
const [variant, value, modifier] = splitClassName(className);
const prefix = PREFIXES.find((prefix2) => value?.startsWith(prefix2));
if (!prefix) {
if (!lightMode.includes(className)) {
lightMode.push(className);
}
continue;
}
const needle = value?.replace(prefix, "");
if (needle && needle in mapping.light) {
lightMode.push(
[variant, `${prefix}${mapping.light[needle]}`, modifier].filter(Boolean).join(":")
);
darkMode.push(
["dark", variant, `${prefix}${mapping.dark[needle]}`, modifier].filter(Boolean).join(":")
);
continue;
}
if (!lightMode.includes(className)) {
lightMode.push(className);
}
}
return lightMode.join(" ") + " " + darkMode.join(" ").trim();
}
// src/utils/transformers/transform-import.ts
var transformImport = async ({ sourceFile, config }) => {
const importDeclarations = sourceFile.getImportDeclarations();
for (const importDeclaration of importDeclarations) {
const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
if (moduleSpecifier.startsWith("@/registry/")) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(
/^@\/registry\/[^/]+/,
config.aliases.components
)
);
}
if (moduleSpecifier == "@/lib/utils") {
const namedImports = importDeclaration.getNamedImports();
const cnImport = namedImports.find((i) => i.getName() === "cn");
if (cnImport) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils)
);
}
}
}
return sourceFile;
};
// src/utils/transformers/transform-rsc.ts
import { SyntaxKind as SyntaxKind2 } from "ts-morph";
var transformRsc = async ({ sourceFile, config }) => {
if (config.rsc) {
return sourceFile;
}
const first = sourceFile.getFirstChildByKind(SyntaxKind2.ExpressionStatement);
if (first?.getText() === `"use client"`) {
first.remove();
}
return sourceFile;
};
// src/utils/transformers/index.ts
import { Project, ScriptKind as ScriptKind2 } from "ts-morph";
var transformers = [
transformImport,
transformRsc,
transformCssVars
];
var project = new Project({
compilerOptions: {}
});
async function createTempSourceFile(filename) {
const dir = await fs2.mkdtemp(path4.join(tmpdir(), "shadcn-"));
return path4.join(dir, filename);
}
async function transform(opts) {
const tempFile = await createTempSourceFile(opts.filename);
const sourceFile = project.createSourceFile(tempFile, opts.raw, {
scriptKind: ScriptKind2.TSX
});
for (const transformer of transformers) {
transformer({ sourceFile, ...opts });
}
return sourceFile.getFullText();
}
// src/commands/add.ts
import chalk2 from "chalk";
import { Command } from "commander";
import { execa } from "execa";
import ora from "ora";
import prompts from "prompts";
import * as z3 from "zod";
var addOptionsSchema = z3.object({
components: z3.array(z3.string()).optional(),
yes: z3.boolean(),
overwrite: z3.boolean(),
cwd: z3.string(),
path: z3.string().optional()
});
var add = new Command().name("add").description("add a component to your project").argument("[components...]", "the components to add").option("-y, --yes", "skip confirmation prompt.", false).option("-o, --overwrite", "overwrite existing files.", false).option(
"-c, --cwd <cwd>",
"the working directory. defaults to the current directory.",
process.cwd()
).option("-p, --path <path>", "the path to add the component to.").action(async (components, opts) => {
try {
const options = addOptionsSchema.parse({
components,
...opts
});
const cwd = path5.resolve(options.cwd);
if (!existsSync(cwd)) {
logger.error(`The path ${cwd} does not exist. Please try again.`);
process.exit(1);
}
const config = await getConfig(cwd);
if (!config) {
logger.warn(
`Configuration is missing. Please run ${chalk2.green(
`init`
)} to create a components.json file.`
);
process.exit(1);
}
const registryIndex = await getRegistryIndex();
let selectedComponents = options.components;
if (!options.components?.length) {
const { components: components2 } = await prompts({
type: "multiselect",
name: "components",
message: "Which components would you like to add?",
hint: "Space to select. A to toggle all. Enter to submit.",
instructions: false,
choices: registryIndex.map((entry) => ({
title: entry.name,
value: entry.name
}))
});
selectedComponents = components2;
}
if (!selectedComponents?.length) {
logger.warn("No components selected. Exiting.");
process.exit(0);
}
const tree = await resolveTree(registryIndex, selectedComponents);
const payload = await fetchTree(config.style, tree);
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor);
if (!payload.length) {
logger.warn("Selected components not found. Exiting.");
process.exit(0);
}
if (!options.yes) {
const { proceed } = await prompts({
type: "confirm",
name: "proceed",
message: `Ready to install components and dependencies. Proceed?`,
initial: true
});
if (!proceed) {
process.exit(0);
}
}
const spinner = ora(`Installing components...`).start();
for (const item of payload) {
spinner.text = `Installing ${item.name}...`;
const targetDir = await getItemTargetPath(
config,
item,
options.path ? path5.resolve(cwd, options.path) : void 0
);
if (!targetDir) {
continue;
}
if (!existsSync(targetDir)) {
await fs3.mkdir(targetDir, { recursive: true });
}
const existingComponent = item.files.filter(
(file) => existsSync(path5.resolve(targetDir, file.name))
);
if (existingComponent.length && !options.overwrite) {
if (selectedComponents.includes(item.name)) {
logger.warn(
`Component ${item.name} already exists. Use ${chalk2.green(
"--overwrite"
)} to overwrite.`
);
process.exit(1);
}
continue;
}
for (const file of item.files) {
const filePath = path5.resolve(targetDir, file.name);
const content = await transform({
filename: file.name,
raw: file.content,
config,
baseColor
});
await fs3.writeFile(filePath, content);
}
if (item.dependencies?.length) {
const packageManager = await getPackageManager(cwd);
await execa(
packageManager,
[
packageManager === "npm" ? "install" : "add",
...item.dependencies
],
{
cwd
}
);
}
}
spinner.succeed(`Done.`);
} catch (error) {
handleError(error);
}
});
// src/commands/diff.ts
import { existsSync as existsSync2, promises as fs4 } from "fs";
import path6 from "path";
import chalk3 from "chalk";
import { Command as Command2 } from "commander";
import { diffLines } from "diff";
import * as z4 from "zod";
var updateOptionsSchema = z4.object({
component: z4.string().optional(),
yes: z4.boolean(),
cwd: z4.string(),
path: z4.string().optional()
});
var diff = new Command2().name("diff").description("check for updates against the registry").argument("[component]", "the component name").option("-y, --yes", "skip confirmation prompt.", false).option(
"-c, --cwd <cwd>",
"the working directory. defaults to the current directory.",
process.cwd()
).action(async (name, opts) => {
try {
const options = updateOptionsSchema.parse({
component: name,
...opts
});
const cwd = path6.resolve(options.cwd);
if (!existsSync2(cwd)) {
logger.error(`The path ${cwd} does not exist. Please try again.`);
process.exit(1);
}
const config = await getConfig(cwd);
if (!config) {
logger.warn(
`Configuration is missing. Please run ${chalk3.green(
`init`
)} to create a components.json file.`
);
process.exit(1);
}
const registryIndex = await getRegistryIndex();
if (!options.component) {
const targetDir = config.resolvedPaths.components;
const projectComponents = registryIndex.filter((item) => {
for (const file of item.files) {
const filePath = path6.resolve(targetDir, file);
if (existsSync2(filePath)) {
return true;
}
}
return false;
});
const componentsWithUpdates = [];
for (const component2 of projectComponents) {
const changes2 = await diffComponent(component2, config);
if (changes2.length) {
componentsWithUpdates.push({
name: component2.name,
changes: changes2
});
}
}
if (!componentsWithUpdates.length) {
logger.info("No updates found.");
process.exit(0);
}
logger.info("The following components have updates available:");
for (const component2 of componentsWithUpdates) {
logger.info(`- ${component2.name}`);
for (const change of component2.changes) {
logger.info(` - ${change.filePath}`);
}
}
logger.break();
logger.info(
`Run ${chalk3.green(`diff <component>`)} to see the changes.`
);
process.exit(0);
}
const component = registryIndex.find(
(item) => item.name === options.component
);
if (!component) {
logger.error(
`The component ${chalk3.green(options.component)} does not exist.`
);
process.exit(1);
}
const changes = await diffComponent(component, config);
if (!changes.length) {
logger.info(`No updates found for ${options.component}.`);
process.exit(0);
}
for (const change of changes) {
logger.info(`- ${change.filePath}`);
await printDiff(change.patch);
logger.info("");
}
} catch (error) {
handleError(error);
}
});
async function diffComponent(component, config) {
const payload = await fetchTree(config.style, [component]);
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor);
const changes = [];
for (const item of payload) {
const targetDir = await getItemTargetPath(config, item);
if (!targetDir) {
continue;
}
for (const file of item.files) {
const filePath = path6.resolve(targetDir, file.name);
if (!existsSync2(filePath)) {
continue;
}
const fileContent = await fs4.readFile(filePath, "utf8");
const registryContent = await transform({
filename: file.name,
raw: file.content,
config,
baseColor
});
const patch = diffLines(registryContent, fileContent);
if (patch.length > 1) {
changes.push({
file: file.name,
filePath,
patch
});
}
}
}
return changes;
}
async function printDiff(diff2) {
diff2.forEach((part) => {
if (part) {
if (part.added) {
return process.stdout.write(chalk3.green(part.value));
}
if (part.removed) {
return process.stdout.write(chalk3.red(part.value));
}
return process.stdout.write(part.value);
}
});
}
// src/commands/init.ts
import { existsSync as existsSync3, promises as fs5 } from "fs";
import path7 from "path";
// src/utils/templates.ts
var UTILS = `import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
export function cn(...inputs) {
return twMerge(clsx(inputs))
}
`;
var TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */
`,Ie=`/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
'./pages/**/*.{<%- extension %>,<%- extension %>x}',
'./components/**/*.{<%- extension %>,<%- extension %>x}',
'./app/**/*.{<%- extension %>,<%- extension %>x}',
'./src/**/*.{<%- extension %>,<%- extension %>x}',
],
prefix: "<%- prefix %>",
theme: {

@@ -765,3 +36,3 @@ container: {

"accordion-down": {
from: { height: 0 },
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },

@@ -771,3 +42,3 @@ },

from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
to: { height: "0" },
},

@@ -782,12 +53,12 @@ },

plugins: [require("tailwindcss-animate")],
}`;
var TAILWIND_CONFIG_WITH_VARIABLES = `/** @type {import('tailwindcss').Config} */
}`,ze=`/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
'./pages/**/*.{<%- extension %>,<%- extension %>x}',
'./components/**/*.{<%- extension %>,<%- extension %>x}',
'./app/**/*.{<%- extension %>,<%- extension %>x}',
'./src/**/*.{<%- extension %>,<%- extension %>x}',
],
prefix: "<%- prefix %>",
theme: {

@@ -844,3 +115,3 @@ container: {

"accordion-down": {
from: { height: 0 },
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },

@@ -850,3 +121,3 @@ },

from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
to: { height: "0" },
},

@@ -861,216 +132,121 @@ },

plugins: [require("tailwindcss-animate")],
}`;
}`,be=`import type { Config } from "tailwindcss"
// src/commands/init.ts
import chalk4 from "chalk";
import { Command as Command3 } from "commander";
import { execa as execa2 } from "execa";
import ora2 from "ora";
import prompts2 from "prompts";
import * as z5 from "zod";
var PROJECT_DEPENDENCIES = [
"tailwindcss-animate",
"class-variance-authority",
"clsx",
"tailwind-merge"
];
var initOptionsSchema = z5.object({
cwd: z5.string(),
yes: z5.boolean()
});
var init = new Command3().name("init").description("initialize your project and install dependencies").option("-y, --yes", "skip confirmation prompt.", false).option(
"-c, --cwd <cwd>",
"the working directory. defaults to the current directory.",
process.cwd()
).action(async (opts) => {
try {
const options = initOptionsSchema.parse(opts);
const cwd = path7.resolve(options.cwd);
if (!existsSync3(cwd)) {
logger.error(`The path ${cwd} does not exist. Please try again.`);
process.exit(1);
}
const existingConfig = await getConfig(cwd);
const config = await promptForConfig(cwd, existingConfig, options.yes);
await runInit(cwd, config);
logger.info("");
logger.info(
`${chalk4.green("Success!")} Project initialization completed.`
);
logger.info("");
} catch (error) {
handleError(error);
}
});
async function promptForConfig(cwd, defaultConfig = null, skip = false) {
const highlight = (text) => chalk4.cyan(text);
const styles = await getRegistryStyles();
const baseColors = await getRegistryBaseColors();
const options = await prompts2([
{
type: "select",
name: "style",
message: `Which ${highlight("style")} would you like to use?`,
choices: styles.map((style) => ({
title: style.label,
value: style.name
}))
const config = {
darkMode: ["class"],
content: [
'./pages/**/*.{<%- extension %>,<%- extension %>x}',
'./components/**/*.{<%- extension %>,<%- extension %>x}',
'./app/**/*.{<%- extension %>,<%- extension %>x}',
'./src/**/*.{<%- extension %>,<%- extension %>x}',
],
prefix: "<%- prefix %>",
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
{
type: "select",
name: "tailwindBaseColor",
message: `Which color would you like to use as ${highlight(
"base color"
)}?`,
choices: baseColors.map((color) => ({
title: color.label,
value: color.name
}))
extend: {
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
{
type: "text",
name: "tailwindCss",
message: `Where is your ${highlight("global CSS")} file?`,
initial: defaultConfig?.tailwind.css ?? DEFAULT_TAILWIND_CSS
},
plugins: [require("tailwindcss-animate")],
} satisfies Config
export default config`,Ee=`import type { Config } from "tailwindcss"
const config = {
darkMode: ["class"],
content: [
'./pages/**/*.{<%- extension %>,<%- extension %>x}',
'./components/**/*.{<%- extension %>,<%- extension %>x}',
'./app/**/*.{<%- extension %>,<%- extension %>x}',
'./src/**/*.{<%- extension %>,<%- extension %>x}',
],
prefix: "<%- prefix %>",
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
{
type: "toggle",
name: "tailwindCssVariables",
message: `Do you want to use ${highlight("CSS variables")} for colors?`,
initial: defaultConfig?.tailwind.cssVariables ?? true,
active: "yes",
inactive: "no"
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
{
type: "text",
name: "tailwindConfig",
message: `Where is your ${highlight("tailwind.config.js")} located?`,
initial: defaultConfig?.tailwind.config ?? DEFAULT_TAILWIND_CONFIG
},
{
type: "text",
name: "components",
message: `Configure the import alias for ${highlight("components")}:`,
initial: defaultConfig?.aliases["components"] ?? DEFAULT_COMPONENTS
},
{
type: "text",
name: "utils",
message: `Configure the import alias for ${highlight("utils")}:`,
initial: defaultConfig?.aliases["utils"] ?? DEFAULT_UTILS
},
{
type: "toggle",
name: "rsc",
message: `Are you using ${highlight("React Server Components")}?`,
initial: defaultConfig?.rsc ?? true,
active: "yes",
inactive: "no"
}
]);
const config = rawConfigSchema.parse({
style: options.style,
tailwind: {
config: options.tailwindConfig,
css: options.tailwindCss,
baseColor: options.tailwindBaseColor,
cssVariables: options.tailwindCssVariables
},
rsc: options.rsc,
aliases: {
utils: options.utils,
components: options.components
}
});
if (!skip) {
const { proceed } = await prompts2({
type: "confirm",
name: "proceed",
message: `Write configuration to ${highlight(
"components.json"
)}. Proceed?`,
initial: true
});
if (!proceed) {
process.exit(0);
}
}
logger.info("");
const spinner = ora2(`Writing components.json...`).start();
const targetPath = path7.resolve(cwd, "components.json");
await fs5.writeFile(targetPath, JSON.stringify(config, null, 2), "utf8");
spinner.succeed();
return await resolveConfigPaths(cwd, config);
}
async function runInit(cwd, config) {
const spinner = ora2(`Initializing project...`)?.start();
for (const [key, resolvedPath] of Object.entries(config.resolvedPaths)) {
let dirname = path7.extname(resolvedPath) ? path7.dirname(resolvedPath) : resolvedPath;
if (key === "utils" && resolvedPath.endsWith("/utils")) {
dirname = dirname.replace(/\/utils$/, "");
}
if (!existsSync3(dirname)) {
await fs5.mkdir(dirname, { recursive: true });
}
}
await fs5.writeFile(
config.resolvedPaths.tailwindConfig,
config.tailwind.cssVariables ? TAILWIND_CONFIG_WITH_VARIABLES : TAILWIND_CONFIG,
"utf8"
);
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor);
if (baseColor) {
await fs5.writeFile(
config.resolvedPaths.tailwindCss,
config.tailwind.cssVariables ? baseColor.cssVarsTemplate : baseColor.inlineColorsTemplate,
"utf8"
);
}
await fs5.writeFile(
`${config.resolvedPaths.utils}.ts`,
UTILS,
"utf8"
);
spinner?.succeed();
const dependenciesSpinner = ora2(`Installing dependencies...`)?.start();
const packageManager = await getPackageManager(cwd);
const deps = [
...PROJECT_DEPENDENCIES,
config.style === "new-york" ? "@radix-ui/react-icons" : "lucide-react"
];
await execa2(
packageManager,
[packageManager === "npm" ? "install" : "add", ...deps],
{
cwd
}
);
dependenciesSpinner?.succeed();
}
},
plugins: [require("tailwindcss-animate")],
} satisfies Config
// src/index.ts
import { Command as Command4 } from "commander";
// src/utils/get-package-info.ts
import path8 from "path";
import fs6 from "fs-extra";
function getPackageInfo() {
const packageJsonPath = path8.join("package.json");
return fs6.readJSONSync(packageJsonPath);
}
// src/index.ts
process.on("SIGINT", () => process.exit(0));
process.on("SIGTERM", () => process.exit(0));
async function main() {
const packageInfo = await getPackageInfo();
const program = new Command4().name("shadcn-ui").description("add components and dependencies to your project").version(
packageInfo.version || "1.0.0",
"-v, --version",
"display the version number"
);
program.addCommand(init).addCommand(add).addCommand(diff);
program.parse();
}
main();
export default config`;import Ae from"chalk";import{Command as ht}from"commander";import{execa as xt}from"execa";import yt from"lodash.template";import H from"ora";import Pe from"prompts";import*as I from"zod";var wt=["tailwindcss-animate","class-variance-authority","clsx","tailwind-merge"],vt=I.object({cwd:I.string(),yes:I.boolean()}),ke=new ht().name("init").description("initialize your project and install dependencies").option("-y, --yes","skip confirmation prompt.",!1).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).action(async t=>{try{let e=vt.parse(t),o=$.resolve(e.cwd);$e(o)||(l.error(`The path ${o} does not exist. Please try again.`),process.exit(1));let r=await C(o),n=await Ct(o,r,e.yes);await Tt(o,n),l.info(""),l.info(`${Ae.green("Success!")} Project initialization completed.`),l.info("")}catch(e){T(e)}});async function Ct(t,e=null,o=!1){let r=p=>Ae.cyan(p),n=await ae(),i=await ce(),a=await Pe([{type:"toggle",name:"typescript",message:`Would you like to use ${r("TypeScript")} (recommended)?`,initial:e?.tsx??!0,active:"yes",inactive:"no"},{type:"select",name:"style",message:`Which ${r("style")} would you like to use?`,choices:n.map(p=>({title:p.label,value:p.name}))},{type:"select",name:"tailwindBaseColor",message:`Which color would you like to use as ${r("base color")}?`,choices:i.map(p=>({title:p.label,value:p.name}))},{type:"text",name:"tailwindCss",message:`Where is your ${r("global CSS")} file?`,initial:e?.tailwind.css??Q},{type:"toggle",name:"tailwindCssVariables",message:`Would you like to use ${r("CSS variables")} for colors?`,initial:e?.tailwind.cssVariables??!0,active:"yes",inactive:"no"},{type:"text",name:"tailwindPrefix",message:`Are you using a custom ${r("tailwind prefix eg. tw-")}? (Leave blank if not)`,initial:""},{type:"text",name:"tailwindConfig",message:`Where is your ${r("tailwind.config.js")} located?`,initial:e?.tailwind.config??ee},{type:"text",name:"components",message:`Configure the import alias for ${r("components")}:`,initial:e?.aliases.components??Y},{type:"text",name:"utils",message:`Configure the import alias for ${r("utils")}:`,initial:e?.aliases.utils??Z},{type:"toggle",name:"rsc",message:`Are you using ${r("React Server Components")}?`,initial:e?.rsc??!0,active:"yes",inactive:"no"}]),f=k.parse({$schema:"https://ui.shadcn.com/schema.json",style:a.style,tailwind:{config:a.tailwindConfig,css:a.tailwindCss,baseColor:a.tailwindBaseColor,cssVariables:a.tailwindCssVariables,prefix:a.tailwindPrefix},rsc:a.rsc,tsx:a.typescript,aliases:{utils:a.utils,components:a.components}});if(!o){let{proceed:p}=await Pe({type:"confirm",name:"proceed",message:`Write configuration to ${r("components.json")}. Proceed?`,initial:!0});p||process.exit(0)}l.info("");let d=H("Writing components.json...").start(),h=$.resolve(t,"components.json");return await P.writeFile(h,JSON.stringify(f,null,2),"utf8"),d.succeed(),await U(t,f)}async function Tt(t,e){let o=H("Initializing project...")?.start();for(let[p,c]of Object.entries(e.resolvedPaths)){let u=$.extname(c)?$.dirname(c):c;p==="utils"&&c.endsWith("/utils")&&(u=u.replace(/\/utils$/,"")),$e(u)||await P.mkdir(u,{recursive:!0})}let r=e.tsx?"ts":"js",n=$.extname(e.resolvedPaths.tailwindConfig),i;n===".ts"?i=e.tailwind.cssVariables?Ee:be:i=e.tailwind.cssVariables?ze:Ie,await P.writeFile(e.resolvedPaths.tailwindConfig,yt(i)({extension:r,prefix:e.tailwind.prefix}),"utf8");let a=await S(e.tailwind.baseColor);a&&await P.writeFile(e.resolvedPaths.tailwindCss,e.tailwind.cssVariables?e.tailwind.prefix?ge(a.cssVarsTemplate,e.tailwind.prefix):a.cssVarsTemplate:a.inlineColorsTemplate,"utf8"),await P.writeFile(`${e.resolvedPaths.utils}.${r}`,r==="ts"?Te:Se,"utf8"),o?.succeed();let f=H("Installing dependencies...")?.start(),d=await L(t),h=[...wt,e.style==="new-york"?"@radix-ui/react-icons":"lucide-react"];await xt(d,[d==="npm"?"install":"add",...h],{cwd:t}),f?.succeed()}import{Command as zt}from"commander";import St from"path";import It from"fs-extra";function Le(){let t=St.join("package.json");return It.readJSONSync(t)}process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function bt(){let t=await Le(),e=new zt().name("shadcn-ui").description("add components and dependencies to your project").version(t.version||"1.0.0","-v, --version","display the version number");e.addCommand(ke).addCommand(we).addCommand(Ce),e.parse()}bt();
//# sourceMappingURL=index.js.map

10

package.json
{
"name": "shadcn-ui",
"version": "0.0.0-beta.a2cd57d",
"version": "0.0.0-beta.b99465d",
"description": "Add components to your apps.",

@@ -32,2 +32,6 @@ "publishConfig": {

"dependencies": {
"@antfu/ni": "^0.21.4",
"@babel/core": "^7.22.1",
"@babel/parser": "^7.22.6",
"@babel/plugin-transform-typescript": "^7.22.5",
"chalk": "5.2.0",

@@ -40,5 +44,7 @@ "commander": "^10.0.0",

"https-proxy-agent": "^6.2.0",
"lodash.template": "^4.5.0",
"node-fetch": "^3.3.0",
"ora": "^6.1.2",
"prompts": "^2.4.2",
"recast": "^0.23.2",
"ts-morph": "^18.0.0",

@@ -49,4 +55,6 @@ "tsconfig-paths": "^4.2.0",

"devDependencies": {
"@types/babel__core": "^7.20.1",
"@types/diff": "^5.0.3",
"@types/fs-extra": "^11.0.1",
"@types/lodash.template": "^4.5.1",
"@types/prompts": "^2.4.2",

@@ -53,0 +61,0 @@ "rimraf": "^4.1.3",

@@ -39,3 +39,3 @@ # shadcn-ui

Visit http://ui.shadcn.com/docs to view the documentation.
Visit https://ui.shadcn.com/docs/cli to view the documentation.

@@ -42,0 +42,0 @@ ## License

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc