UNPKG

@radianos/radianbeta

Version:

Add components to your project

348 lines (292 loc) 38.1 kB
#!/usr/bin/env node var T={name:"@radianos/radianbeta",version:"1.1.15",main:"index.js",type:"module",publishConfig:{access:"public"},exports:"./dist/index.js",bin:{radianos:"dist/index.js"},files:["dist","README.md","package.json"],scripts:{dev:"tsup --watch && tsup",build:"tsup"},keywords:["radian","radianos","radianos cli","components","ui","tailwind","radix-ui"],author:"Radian OS",license:"ISC",description:"Add components to your project",dependencies:{"@clack/prompts":"^0.9.1","adm-zip":"^0.5.16",chalk:"^5.3.0",commander:"^12.1.0",cosmiconfig:"^9.0.0",execa:"^9.5.0","fast-glob":"^3.3.2","fs-extra":"^11.2.0","gradient-string":"^3.0.0",json5:"^2.2.3","node-fetch":"^3.3.2",ora:"^8.1.0","package-manager-detector":"^1.3.0",postcss:"^8.5.6",prompts:"^2.4.2","ts-morph":"^25.0.1","tsconfig-paths":"^4.2.0",tsup:"^8.3.5","type-fest":"^4.26.1",zod:"^3.23.8"},devDependencies:{"@trivago/prettier-plugin-sort-imports":"^5.2.2","@types/adm-zip":"^0.5.7","@types/fs-extra":"^11.0.4","@types/node":"^22.7.9","@types/prompts":"^2.4.9",prettier:"^3.4.2","prettier-plugin-organize-imports":"^4.1.0","semantic-release":"^24.2.7",typescript:"^5.6.3"}};import{Command as Ge}from"commander";import{Command as Be}from"commander";import G from"fs-extra";import A from"path";import Me from"prompts";import{z as C}from"zod";import it from"fs-extra";import Ht from"path";import{cosmiconfig as Kt}from"cosmiconfig";import{z as g}from"zod";import f from"chalk";var l={error:f.redBright,success:f.greenBright,warning:f.yellowBright,info:f.blueBright,dark:f.blackBright,light:f.whiteBright,deprecated:f.gray,magenta:f.magentaBright,cyan:f.cyanBright,bold:f.bold,italic:f.italic,underline:f.underline,strikethrough:f.strikethrough},Xe={error:f.bgRedBright,success:f.bgGreenBright,warning:f.bgYellowBright,info:f.bgBlueBright,dark:f.bgBlackBright,light:f.bgWhiteBright,magenta:f.bgMagentaBright,cyan:f.bgCyanBright};var Yt=Kt("components",{searchPlaces:["components.json"]}),nt=g.object({hasSrcDir:g.boolean(),aliases:g.object({components:g.string(),utils:g.string(),ui:g.string(),animated:g.string().optional(),lib:g.string().optional(),hooks:g.string().optional()})}),eo=nt.extend({resolvedPaths:g.object({cwd:g.string(),tailwindConfig:g.string(),tailwindCss:g.string(),utils:g.string(),components:g.string(),lib:g.string(),hooks:g.string(),ui:g.string()})});async function _(t=process.cwd()){let e=await Yt.search(t);if(!e)throw new Error(`components.json is missing. Run ${l.info("npx radianos init")} command to initialize project`);try{return nt.parse(e.config)}catch(o){throw new Error(`Error loading components.json configuration: ${o instanceof Error?o.message:"Unknown error"}`)}}var st=async t=>!it.existsSync(t.cwd)||!it.existsSync(Ht.resolve(t.cwd,"package.json"))?{config:null}:{config:await _(t.cwd)};import{execa as Qt}from"execa";import at from"fs-extra";import{detect as Xt,getUserAgent as qt}from"package-manager-detector";import ct from"path";var O=async(t,{withFallback:e}={withFallback:!1})=>{let o=ct.resolve(t);if(!at.existsSync(o))throw new Error(`The path "${o}" does not exist.`);if(!at.existsSync(ct.join(o,"package.json"))&&e)return lt();let n=await Xt({cwd:o});switch(n?.name){case"npm":case"pnpm":case"bun":case"yarn":return n.name;default:return e?lt():"npm"}};function lt(){let t=qt()||"";return t.startsWith("pnpm")?"pnpm":t.startsWith("yarn")?"yarn":t.startsWith("bun")?"bun":"npm"}var pt=async t=>{let e=await O(t);if(!e)return null;switch(e){case"npm":return"install";case"pnpm":return"install";case"bun":return"add";case"yarn":return"add";default:return null}};var c={success:(...t)=>{console.log(l.success(t.join(" ")))},info:(...t)=>{console.log(l.info(t.join(" ")))},warn:(...t)=>{console.log(l.warning(t.join(" ")))},error:(...t)=>{console.log(l.error(t.join(" ")))},log:(...t)=>{console.log(l.dark(t.join("")))},break:()=>{console.log("")}};function w(t){typeof t=="string"&&(c.break(),c.error(t),c.break(),process.exit(1)),t instanceof Error&&(c.break(),c.error(t.message),c.break(),process.exit(1)),c.error("Something went wrong. Please try again."),process.exit(1)}import Zt from"ora";function u(t,e){return Zt({text:t,isSilent:e?.silent})}var K=async(t,e,o)=>{if(!e.length)return;let r=await O(t,{withFallback:!0}),n=await pt(t);n||w("Failed to install dependencies: Dependency installer not found");let i=u("Installing dependencies",{silent:o}).start();try{await Qt(r,[n,...e],{cwd:t}),i.succeed()}catch(s){i.fail(),console.log(s),w("Failed to install dependencies.")}};async function mt(t,e){let o=new Set;for(let n of t)n.dependencies?.length&&n.dependencies.forEach(i=>o.add(i));if(!o.size)return;let r=Array.from(o);await K(e.cwd,r)}function ft(t){let e=t.filter(r=>r.type==="block"),o=new Set;return e.forEach(r=>{r.registryDependencies&&r.registryDependencies.forEach(n=>{o.add(n),dt(n,t,o)})}),o}function dt(t,e,o){let r=e.find(n=>n.name===t);if(r&&r.registryDependencies)for(let n of r.registryDependencies)o.has(n)||(o.add(n),dt(n,e,o))}import V from"fast-glob";import Y from"fs-extra";import b from"path";import{loadConfig as te}from"tsconfig-paths";var D={manual:{name:"manual",label:"Manual",link:{installation:"https://radianos.com/documentation/installation",tailwind:"https://tailwindcss.com/docs/guides/manual"}},"next-app":{name:"next-app",label:"Next.js",link:{installation:"https://radianos.com/documentation/installation",tailwind:"https://tailwindcss.com/docs/guides/nextjs"}},"next-pages":{name:"next-pages",label:"Next.js",link:{installation:"https://radianos.com/documentation/installation",tailwind:"https://tailwindcss.com/docs/guides/nextjs"}},vite:{name:"vite",label:"Vite",link:{installation:"https://radianos.com/documentation/installation",tailwind:"https://tailwindcss.com/docs/guides/vite"}}};var B=["**/node_modules/**","dist","build",".next","public"],M=async t=>{let[e,o,r,n,i,s]=await Promise.all([ee(t),Y.pathExists(b.resolve(t,"src")),ne(t),oe(t),re(t),ie(t)]),m=await Y.pathExists(b.resolve(t,`${o?"src/":""}app`)),d={framework:D.manual,hasSrcDir:o,isRSC:!1,isTsx:r,tailwindConfigFile:n,tailwindCssFile:i,aliasPrefix:s};return e?.startsWith("next.config.")?(d.framework=m?D["next-app"]:D["next-pages"],d.isRSC=m,d):(e?.startsWith("vite.config.")&&(d.framework=D.vite),d)},ee=async t=>{let e=await V.glob("**/{next,vite}.config.*",{cwd:t,deep:3,ignore:B});return e.length?e[0]:null},oe=async t=>{let e=await V.glob("tailwind.config.*",{cwd:t,deep:3,ignore:B});return e.length?e[0]:null},re=async t=>{let e=await V.glob(["**/*.css","**/*.scss"],{cwd:t,deep:5,ignore:B});if(!e.length)return null;for(let o of e){let r=await Y.readFile(b.resolve(t,o),"utf-8");if(r.includes('@import "tailwindcss"')||r.includes("@import 'tailwindcss'"))return o}return null};var ne=async t=>(await V.glob("tsconfig.*",{cwd:t,deep:1,ignore:B})).length>0,ie=async t=>{let e=te(t);if(e.resultType==="failed"||!e.paths)return null;for(let[o,r]of Object.entries(e.paths))if(r.includes("./*")||r.includes("./src/*")||r.includes("./app/*")||r.includes("./resources/js/*/"))return o.at(0)??null;return null},H=(t,e,o)=>{let r;switch(o){case"vite":r=b.join(t,"src","index.css");break;case"next-app":r=e?b.join(t,"src","app","globals.css"):b.join(t,"app","globals.css");break;case"next-pages":r=e?b.join(t,"src","styles","globals.css"):b.join(t,"styles","globals.css");break;default:throw new Error(`Unsupported framework: ${o}`)}return r};import{execa as et}from"execa";import k from"fs-extra";import x from"path";import{Command as Fe}from"commander";import U from"fs-extra";import W from"path";import je from"prompts";import F from"zod";import X from"fs-extra";import gt from"path";var ut=async t=>{if(!X.existsSync(t.cwd)||!X.existsSync(gt.resolve(t.cwd,"package.json")))return{projectInfo:null};let e=await M(t.cwd),o=[],r=u("Preflight checks",{silent:!1}).start();X.existsSync(gt.resolve(t.cwd,"components.json"))?(r.fail(),o.push(`The ${l.info("components.json")} file already exists at ${l.info(t.cwd)}. To start over, remove the ${l.info("components.json")} file and run ${l.info("init")} command again`)):r.succeed("Before init checks completed");let n=u("Detecting framework",{silent:!1}).start();!e||e?.framework.name==="manual"?(n?.fail(),e?.framework.link.installation&&o.push(`We could not detect a supported framework at ${l.info(t.cwd)}. Visit ${l.info(e?.framework.link.installation)} to manually configure your project. Once configured, you can use the cli to add components.`)):n?.succeed(`Detecting framework. Detected ${l.info(e.framework.label)}.`);let i=u("Verifying tailwind configuration",{silent:!1}).start();e.tailwindCssFile?i?.succeed("Verifying tailwind configuration. Found Tailwind configuration."):(i?.fail(),e.framework.name==="vite"?o.push(`We could not find a Tailwind config at ${l.info(t.cwd)}. Make sure you have a Tailwind installed your project. Visit ${l.info("https://tailwindcss.com/docs/installation")} to get started.`):o.push(`We could not find a Tailwind config at ${l.info(t.cwd)}. Make sure you have a Tailwind installed your project. Visit ${l.info("https://tailwindcss.com/docs/installation/framework-guides/nextjs")} to get started.`));let s=u("Validating import alias",{silent:!1}).start();if(e.aliasPrefix?s?.succeed(`Verifying import alias. Found import alias prefix: ${e.aliasPrefix}`):(s?.fail(),o.push(`No import alias found in your tsconfig.json file. Visit ${l.info("https://radianos.com/docs/installation/vite")} to learn how to set an import alias.`)),o.length>0)throw new Error(o.join(` `));return{projectInfo:e}};import P from"prompts";import se from"adm-zip";import{createWriteStream as ae}from"fs";import*as y from"fs";import z from"path";import{pipeline as ce}from"stream/promises";var Z="https://radianos.com",le="https://blocks.radianos.com",ht=`${Z}/api/components`,q=`${le}/api/blocks`,$=async()=>{try{let t=await fetch(ht);if(!t.ok){let n=`Failed to fetch data from ${ht}. Status: ${t.status} - ${t.statusText}`;throw new Error(n)}let e=await fetch(new URL("/api/blocks",q).toString());if(!e.ok){let n=`Failed to fetch data from ${q}. Status: ${e.status} - ${e.statusText}`;throw new Error(n)}let o=await t.json(),r=await e.json();return[...o,...r]}catch(t){return w(t),[]}},pe=async t=>{try{let e=new URL(`/api/assets?assetsDirectory=${t}`,q).toString(),o=await fetch(e);if(!o.ok){let a=`Failed to fetch assets from ${e}. Status: ${o.status} - ${o.statusText}`;throw new Error(a)}let r=o.headers.get("content-type");if(!r?.includes("application/zip"))throw new Error(`Expected zip file but received: ${r}`);let n=z.join(process.cwd(),"temp"),i=z.join(n,`${t}-${Date.now()}.zip`);y.existsSync(n)||y.mkdirSync(n,{recursive:!0});let s=ae(i);await ce(o.body,s);let m=z.join(process.cwd(),"public"),d=z.join(m,t);if(y.existsSync(m)||y.mkdirSync(m,{recursive:!0}),y.existsSync(d)&&y.rmSync(d,{recursive:!0,force:!0}),new se(i).extractAllTo(d,!0),y.unlinkSync(i),y.existsSync(n))try{y.rmSync(n,{recursive:!0,force:!0})}catch(a){console.warn("Failed to cleanup temp directory:",a)}}catch(e){w(e)}},wt=async t=>{for(let e of t){let o=u(`Downloading assets for ${e.componentName}`).start();await pe(e.assetsDirectory),o.succeed()}},yt=async t=>{try{let e=await fetch(`${Z}/r/themes/${t}.json`);if(!e.ok){let r=`Failed to fetch data from ${e.url}. Status: ${e.status} - ${e.statusText}`;throw new Error(r)}return await e.json()}catch(e){throw new Error(`Failed to fetch data from ${t}.json: ${e instanceof Error?e.message:"unknown error"}`)}},xt=async t=>{try{let e=await fetch(`${Z}/r/fonts/${t}.json`);if(!e.ok){let r=`Failed to fetch data from ${e.url}. Status: ${e.status} - ${e.statusText}`;throw new Error(r)}return await e.json()}catch(e){throw new Error(`Failed to fetch data from ${t}.json: ${e instanceof Error?e.message:"unknown error"}`)}};async function Q(t,e,o=new Set){let r=[];for(let n of e){if(o.has(n))continue;o.add(n);let i=t.find(s=>s.name===n);if(i&&(r.push(i),i.registryDependencies?.length)){let s=await Q(t,i.registryDependencies,o);r.push(...s)}}return r.filter((n,i,s)=>s.findIndex(m=>m.name===n.name)===i)}var L=async t=>{if(t.defaultConfigurations)return{projectName:"my-app",useSrcDir:!0,framework:"next-app",brandColor:"amber",font:"inter"};let e=t.projectName||(await P({type:"text",name:"projectName",message:"What would you like to name your project?",initial:"my-app",format:s=>s.trim(),validate:s=>s.length>128?"Name should be less than 128 characters.":!0})).projectName,o=t.next?"next-app":t.vite?"vite":(await P({type:"select",name:"framework",message:"Which framework do you want to use?",choices:[{title:"Next.js",value:"next-app"},{title:"Vite",value:"vite"}],initial:0})).framework,r=o==="next-app"?(await P({type:"confirm",name:"useSrcDir",message:"Would you like to use /src directory?",initial:!0})).useSrcDir:!0,{brandColor:n}=await P({type:"select",name:"brandColor",message:"Which color would you like to use as your brand color?",choices:[{title:"Violet Blue (Default)",value:"violet-blue"},{title:"Light Blue",value:"light-blue"},{title:"Emerald",value:"emerald"},{title:"Red",value:"red"},{title:"Amber",value:"amber"}],initial:0}),{font:i}=await P({type:"select",name:"font",message:"Which font would you like to use for your project?",choices:[{title:"Inter - Inter Display (Default)",value:"inter"},{title:"Roboto",value:"roboto"},{title:"Geist",value:"geist"}],initial:0});return{projectName:e,useSrcDir:r,framework:o,brandColor:n,font:i}};async function kt(t){try{let o=(await $()).filter(n=>n.type==="ui"||n.type==="animated").map(n=>n.name);if(t.all)return o;if(t.components?.length)return t.components;let{components:r}=await P({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:o.map(n=>({title:n,value:n,selected:t.components?.includes(n)}))});return r}catch{throw new Error("Failed to fetch available components.")}}var bt=`import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs.filter(Boolean))); } `,Ct=`{ "$schema": "https://radianos.com/schema.json", "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "animated": "@/components/animated", "lib": "@/lib", "hooks": "@/hooks" }, "hasSrcDir": true }`,vt=`@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"); @import "tailwindcss"; @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @theme { /* primary */ --color-primary: oklch(0.528 0.2539 282.58); --color-primary-accent: oklch(0.94 0.0271 295.05); --color-primary-focus: oklch(0.9169 0.0383 295.46); --color-primary-hover: oklch(0.5768 0.2279 286.25); --color-primary-text: oklch(0.4304 0.202 282.82); /* success */ --color-success: oklch(0.6334 0.171 148.65); --color-success-accent: oklch(0.9685 0.0336 157.66); --color-success-focus: oklch(0.9489 0.0556 156.34); --color-success-hover: oklch(0.6901 0.1748 149.64); --color-success-text: oklch(0.5388 0.1339 149.74); /* error */ --color-error: oklch(0.64 0.22 26.04); --color-error-accent: oklch(0.9465 0.0252 17.61); --color-error-focus: oklch(0.9133 0.0414 17.93); --color-error-hover: oklch(0.6786 0.2095 24.66); --color-error-text: oklch(0.5716 0.2125 27.27); /* warning */ --color-warning: oklch(0.8016 0.1705 73.27); --color-warning-accent: oklch(0.9622 0.0384 83.83); --color-warning-focus: oklch(0.946 0.0574 85.03); --color-warning-hover: oklch(0.8342 0.1594 79.51); --color-warning-text: oklch(0.5461 0.1088 77.73); /* information */ --color-info: oklch(0.6092 0.2041 255.8); --color-info-accent: oklch(0.949 0.0213 245.85); --color-info-focus: oklch(0.9135 0.0358 249.52); --color-info-hover: oklch(0.6722 0.1615 251.56); --color-info-text: oklch(0.4663 0.1065 251.21); /* background */ --color-base: oklch(1 0 0); --color-fill1: oklch(0.9824 0.0013 286.38); --color-fill2: oklch(0.9677 0.0027 286.35); --color-fill3: oklch(0.9349 0.004 286.32); --color-fill4: oklch(0.902 0.0068 286.26); /* foreground */ --color-fg: oklch(0.2314 0.0078 274.6); --color-fg-secondary: oklch(0.4515 0.0243 285.39); --color-fg-tertiary: oklch(0.6261 0.0268 285.6); --color-fg-disabled: oklch(0.8352 0.011 286.16); --color-fg-inverse: oklch(1 0 0); /* border */ --color-border: oklch(0.902 0.0068 286.26); --color-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 88%); --color-soft: oklch(0.9349 0.004 286.32); --color-soft-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 92%); /* background elevation */ --color-elevation-negative: oklch(0.9677 0.0027 286.35); --color-elevation-level1: oklch(1 0 0); --color-elevation-level2: oklch(1 0 0); /* inverse */ --color-white-inverse: oklch(1 0 0); --color-black-inverse: oklch(0.144 0.0028 247.09); /* background fill alpha */ --color-fill1-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 98%); --color-fill2-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 96%); --color-fill3-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 92%); --color-fill4-alpha: color-mix(in srgb, oklch(0.1452 0.0021 286.13), transparent 88%); } .dark { /* primary */ --color-primary: oklch(0.528 0.2539 282.58); --color-primary-accent: oklch(0.2294 0.0753 289.19); --color-primary-focus: oklch(0.2538 0.1064 285.61); --color-primary-hover: oklch(0.5768 0.2279 286.25); --color-primary-text: oklch(0.7757 0.1162 292.43); /* success */ --color-success: oklch(0.6334 0.171 148.65); --color-success-accent: oklch(0.271 0.0537 151.74); --color-success-focus: oklch(0.3887 0.0924 150.55); --color-success-hover: oklch(0.6901 0.1748 149.64); --color-success-text: oklch(0.871 0.1501 153.14); /* error */ --color-error: oklch(0.64 0.22 26.04); --color-error-accent: oklch(0.2567 0.0648 22.77); --color-error-focus: oklch(0.2973 0.0922 24.71); --color-error-hover: oklch(0.6786 0.2095 24.66); --color-error-text: oklch(0.7884 0.1226 20.19); /* warning */ --color-warning: oklch(0.8016 0.1705 73.27); --color-warning-accent: oklch(0.2663 0.0372 84.34); --color-warning-focus: oklch(0.3744 0.0636 81.14); --color-warning-hover: oklch(0.8342 0.1594 79.51); --color-warning-text: oklch(0.8776 0.1255 82.88); /* information */ --color-info: oklch(0.6092 0.2041 255.8); --color-info-accent: oklch(0.2739 0.0462 248.76); --color-info-focus: oklch(0.3147 0.0668 250.78); --color-info-hover: oklch(0.6722 0.1615 251.56); --color-info-text: oklch(0.829 0.0811 248.83); /* background */ --color-base: oklch(0.144 0.0028 247.09); --color-fill1: oklch(0.1652 0.0062 285.7); --color-fill2: oklch(0.1881 0.006 285.81); --color-fill3: oklch(0.2314 0.0078 274.6); --color-fill4: oklch(0.2738 0.0093 276.77); /* foreground */ --color-fg: oklch(1 0 0); --color-fg-secondary: oklch(0.6619 0.0235 285.74); --color-fg-tertiary: oklch(0.5553 0.0292 285.41); --color-fg-disabled: oklch(0.4515 0.0243 285.39); --color-fg-inverse: oklch(0.2314 0.0078 274.6); /* border */ --color-border: oklch(0.2738 0.0093 276.77); --color-alpha: color-mix(in srgb, oklch(1 0 0), transparent 88%); --color-soft: oklch(0.2314 0.0078 274.6); --color-soft-alpha: color-mix(in srgb, oklch(1 0 0), transparent 92%); /* background elevation */ --color-elevation-negative: oklch(0 0 0); --color-elevation-level1: oklch(0.1881 0.006 285.81); --color-elevation-level2: oklch(0.2314 0.0078 274.6); /* inverse */ --color-white-inverse: oklch(0.144 0.0028 247.09); --color-black-inverse: oklch(1 0 0); /* background fill alpha */ --color-fill1-alpha: color-mix(in srgb, oklch(1 0 0), transparent 98%); --color-fill2-alpha: color-mix(in srgb, oklch(1 0 0), transparent 96%); --color-fill3-alpha: color-mix(in srgb, oklch(1 0 0), transparent 92%); --color-fill4-alpha: color-mix(in srgb, oklch(1 0 0), transparent 88%); } /* Base styles */ @layer base { * { border-color: var(--color-border); } body { @apply font-body bg-base text-fg; /* Font families */ --heading-font: "Inter Display", system-ui, sans-serif; --body-font: "Inter", system-ui, sans-serif; } } /* Custom heading font */ @utility font-heading { font-family: var(--heading-font); } /* Custom body font */ @utility font-body { font-family: var(--body-font); } /* Heading 1 */ @utility heading-1 { @apply font-heading text-[2.25rem] font-bold leading-[2.75rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 3rem; line-height: 3.5rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 4rem; line-height: 4.5rem; } } /* Heading 2 */ @utility heading-2 { @apply font-heading text-[2rem] font-bold leading-[2.5rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 2.5rem; line-height: 3rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 3rem; line-height: 3.5rem; } } /* Heading 3 */ @utility heading-3 { @apply font-heading text-[1.875rem] font-bold leading-[2.375rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 2.25rem; line-height: 2.75rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 2.5rem; line-height: 3rem; } } /* Heading 4 */ @utility heading-4 { @apply font-heading text-[1.75rem] font-bold leading-[2.25rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 1.875rem; line-height: 2.375rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 2rem; line-height: 2.5rem; } } /* Heading 5 */ @utility heading-5 { @apply font-heading text-[1.5rem] font-bold leading-[2rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 1.5rem; line-height: 2rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 1.5rem; line-height: 2rem; } } /* Heading 6 */ @utility heading-6 { @apply font-heading text-[1.25rem] font-bold leading-[1.75rem]; @media (width >=theme(--breakpoint-sm)) { font-size: 1.25rem; line-height: 1.75rem; } @media (width >=theme(--breakpoint-lg)) { font-size: 1.25rem; line-height: 1.75rem; } } /* Additional body fonts */ @utility body-15 { @apply font-body text-[0.9375rem] leading-[1.375]; } @utility text-sm-p { @apply font-body text-sm leading-[1.25rem]; } @utility body-13 { @apply font-body text-[0.8125rem] leading-[1.125rem]; } /* Hides scrollbar in multiple browsers*/ @utility no-scrollbar { -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ &::-webkit-scrollbar { display: none; /* Chrome, Safari and Opera */ } } `;import Ft from"postcss";var E={DARK_SELECTOR:".dark",COLOR_PRIMARY_PREFIX:"--color-primary",GOOGLE_FONTS_DOMAIN:"fonts.googleapis.com",HEADING_FONT_PROP:"--heading-font",BODY_FONT_PROP:"--body-font",FALLBACK_FONTS:"system-ui, sans-serif"};function me(t,e){t.walkAtRules("theme",o=>{jt(o,e,"light theme @theme rule")})}function fe(t,e){t.walkRules(o=>{o.selector===E.DARK_SELECTOR&&jt(o,e,"dark theme rule")})}function jt(t,e,o){t.walkDecls(r=>{if(!r.prop.startsWith(E.COLOR_PRIMARY_PREFIX))return;let n=de(r.prop),i=ge(n);e[i]?r.value=e[i]:c.error(`No color found for: ${i} in ${o}`)})}function de(t){return t.replace(E.COLOR_PRIMARY_PREFIX,"")||""}function ge(t){return t?`primary${t}`:"primary"}function ue(t,e){he(e),we(t,e.importURL)||xe(t,e.importURL),ke(t,e)}function he(t){if(!t.importURL||!t.cssVariables)throw new Error("Font data must contain importURL and cssVariables")}function we(t,e){let o=!1;return t.walkAtRules("import",r=>{let n=r.params.replace(/['"]/g,"");ye(n)&&(r.params=`url("${e}")`,o=!0)}),o}function ye(t){return t.startsWith("url(")&&t.includes(E.GOOGLE_FONTS_DOMAIN)}function xe(t,e){let o=Ft.atRule({name:"import",params:`url("${e}")`});t.prepend(o)}function ke(t,e){t.walkAtRules("theme",o=>{o.walkDecls(r=>{be(r,e)})})}function be(t,e){let{cssVariables:o}=e;t.prop===E.HEADING_FONT_PROP&&o["heading-font"]?t.value=Et(o["heading-font"]):t.prop===E.BODY_FONT_PROP&&o["body-font"]&&(t.value=Et(o["body-font"]))}function Et(t){return`"${t}", ${E.FALLBACK_FONTS}`}var St=(t={})=>{let{color:e,font:o}=t;return{postcssPlugin:"theme-update",async Once(r){try{Ce(e,o);let[n,i]=await Promise.all([yt(e),xt(o)]);await Promise.all([ve(r,i,o),Ee(r,n,e)])}catch(n){let i=n instanceof Error?n.message:"Unknown error";throw new Error(`Error updating theme colors: ${i}`)}}}};function Ce(t,e){if(!t||!e)throw new Error("Both color and font options are required for theme updates")}async function ve(t,e,o){if(!e?.importURL||!e?.cssVariables)throw new Error(`Invalid or incomplete font data for font: ${o}`);ue(t,e)}async function Ee(t,e,o){if(!e?.cssVariables)throw new Error(`No theme color data found for theme: ${o}`);let{light:r,dark:n}=e.cssVariables;r&&me(t,r),n&&fe(t,n)}St.postcss=!0;async function Pt(t,e,o){try{let r=await import("fs/promises"),n=await r.readFile(t,"utf-8"),i=await Ft([St({color:e,font:o})]).process(n,{from:t});await r.writeFile(t,i.css)}catch(r){throw new Error(`Error updating CSS file: ${r instanceof Error?r.message:"Unknown error"}`)}}var Rt=["tw-animate-css","class-variance-authority","clsx","tailwind-merge","lucide-react"],Nt=["@tailwindcss/vite"],Se=F.object({cwd:F.string(),skipPrompts:F.boolean().optional(),defaultConfigurations:F.boolean().optional(),next:F.boolean().optional(),vite:F.boolean().optional(),projectName:F.string().optional()}),Tt=new Fe().name("init").description("initializes your project with required dependencies").argument("[project-name]","the name of the project").option("--next","use next.js",!1).option("--vite","use vite",!1).option("-s,--skipPrompts","skip confirmation prompts",!1).option("-d,--defaultConfigurations","use default configurations",!1).option("-c,--cwd <cwd>","current working directory",process.cwd()).action(async(t,e)=>{try{let o=Se.parse({...e,projectName:t});o.next&&o.vite&&(c.break(),c.error("You cannot use both --next and --vite options together. Please pass only one option."),c.break(),process.exit(1)),await Re(o),c.break(),c.info(`${l.success("Success!")} Project initialization completed. You may now add components.`),c.break()}catch(o){w(o)}}),Ot=async(t,e,o)=>{try{let r=H(t,e,o);await U.ensureFile(r),await U.writeFile(r,vt,"utf-8")}catch(r){throw new Error(`Failed to create global CSS: ${r.message}`)}},Pe=async(t,e,o,r,n)=>{let i=u("Updating global CSS variables");try{let s=H(t,e,o);i.start(),await Pt(s,r,n),i.succeed()}catch(s){throw i.fail(),new Error(`Failed to update global CSS variables: ${s}`)}},Dt=async(t,e,o)=>{try{let r=o==="vite"?W.join(t,"src"):e?W.join(t,"src"):t,n=W.join(r,"lib");await U.ensureDir(n),await U.writeFile(W.join(n,"utils.ts"),bt,"utf8")}catch(r){throw new Error(`Failed to create utils.ts: ${r}`)}},Re=async t=>{let{projectInfo:e}=await ut(t);if(!!e)c.warn(`${l.bold("Note:")} This will replace your global CSS file and add Radian OS styles and colors to your project`),await I(t.cwd,e.framework.name,e.hasSrcDir);else{(await je({type:"confirm",name:"confirmNewProject",message:`No package.json found at ${l.bold(l.info(t.cwd))}. Create a new project?`,initial:!1})).confirmNewProject||process.exit();let n=await L(t),{projectPath:i}=await J(t,n);await I(i,n.framework,n.useSrcDir),await Pe(i,n.useSrcDir,n.framework,n.brandColor,n.font)}return e};import{Project as Ne,SyntaxKind as Te}from"ts-morph";async function $t(t){let o=new Ne().addSourceFileAtPath(t);o.getImportDeclarations().forEach(r=>{r.getModuleSpecifierValue().includes("next/font")&&r.remove()}),o.getVariableStatements().forEach(r=>{r.getDeclarations().forEach(i=>{i.getInitializer()?.getText().includes("Geist")&&r.remove()})}),o.getDescendantsOfKind(Te.JsxElement).forEach(r=>{let i=r.getOpeningElement().getAttribute("className");if(i){let s=i.getInitializer()?.getText();if(s?.includes("geist")){let m=s.replace(/[`{}$]/g,"").split(" ").filter(d=>!d.includes("geist")).join(" ");m.trim()?i.setInitializer(`"${m}"`):i.remove()}}}),await o.save()}import R from"fs-extra";import Oe from"json5";import It from"path";var At=async t=>{let e=It.join(t,"tsconfig.json"),o={baseUrl:".",paths:{"@/*":["./src/*"]}};try{if(await R.pathExists(e)){let r=await R.readJson(e);r.compilerOptions={...r.compilerOptions,...o},await R.writeJson(e,r,{spaces:2})}}catch(r){throw new Error(`Failed to update tsconfig.json: ${r}`)}},_t=async(t,e)=>{if(e!=="vite")return;let o=It.join(t,"tsconfig.app.json"),r={baseUrl:".",paths:{"@/*":["./src/*"]}};try{if(await R.pathExists(o)){let n=await R.readFile(o,"utf8"),i=Oe.parse(n);i.compilerOptions={...i.compilerOptions||{},...r,paths:{...i.compilerOptions?.paths||{},...r.paths}},await R.writeJson(o,i,{spaces:2})}else throw new Error(`tsconfig.app.json not found at ${o}`)}catch(n){throw new Error(`Failed to update tsconfig.app.json: ${n}`)}};import N from"fs-extra";import tt from"path";var Vt=async t=>{let e=tt.join(t,"vite.config.ts"),o=`import path from "path" import tailwindcss from "@tailwindcss/vite" import react from "@vitejs/plugin-react" import { defineConfig } from "vite" export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { "@": path.resolve(__dirname, "./src"), }, }, })`;try{await N.pathExists(e)&&await N.writeFile(e,o,"utf8")}catch(r){throw new Error(`Failed to update vite.config.ts: ${r}`)}},Bt=async t=>{try{let e=tt.join(t,"src","App.tsx"),o=tt.join(t,"src","App.css"),r=`import React from 'react' const App = () => { return ( <h1 className="text-4xl font-bold text-center mt-20 text-blue-600"> Welcome to Your Tailwind-powered App! </h1> ) } export default App `;await N.ensureFile(e),await N.writeFile(e,r,"utf8"),await N.pathExists(o)&&await N.remove(o)}catch(e){throw new Error(`Failed to replace App.tsx and remove App.css: ${e.message}`)}};var J=async(t,e)=>{let{projectName:o,useSrcDir:r,framework:n}=e,i=x.join(t.cwd,o);if(await k.access(t.cwd,k.constants.W_OK),k.existsSync(i))throw new Error(`A project named ${o} already exists.`);let s=await O(t.cwd,{withFallback:!0}),m=u(`Creating a new ${n=="next-app"?l.info("Next.js"):l.info("Vite")} project. This might take some time.`).start();return n==="next-app"?await et("npx",["create-next-app","--tailwind","--eslint","--typescript","--app",o,`--use-${s}`,r?"--src-dir":"--no-src-dir","--yes"],{cwd:t.cwd,stdio:"ignore"}):(await et("npm",["create","vite@latest",o,"--","--template","react-ts"],{cwd:t.cwd,stdio:"ignore"}),await et(s,["install"],{cwd:i})),m.succeed(),{projectPath:i}},I=async(t,e,o)=>{let r=u("Writing components.json file").start(),n=x.resolve(t,"components.json");await k.writeFile(n,Ct,"utf8"),r.succeed();let i=u("Setting up project configuration").start();await Dt(t,o,e),await Ot(t,o,e),e.includes("next")?await $e(t,o,e):e==="vite"&&await De(t),i.succeed();let s=[...Rt,"@types/node"],m=e==="vite"?[...s,...Nt]:s;await K(t,m)},De=async t=>{try{let e=x.join(t,"src"),o=x.join(e,"main.tsx"),r=x.join(e,"App.tsx");if(!await k.pathExists(e))throw new Error(`Vite src directory not found at ${e}`);if(!await k.pathExists(o))throw new Error(`Main entry file not found at ${o}`);if(!await k.pathExists(r))throw new Error(`App component not found at ${r}`);await Promise.all([At(t),Vt(t),Bt(t),_t(t,"vite")])}catch(e){throw new Error(`Vite setup failed: ${e.message}`)}},$e=async(t,e,o)=>{try{let r,n;switch(o){case"next-app":r=e?x.join(t,"src","app"):x.join(t,"app"),n=x.join(r,"layout.tsx");break;case"next-pages":r=e?x.join(t,"src","pages"):x.join(t,"pages"),n=x.join(r,"index.tsx");break;default:throw new Error(`Unsupported framework: ${o}`)}if(!await k.pathExists(r))throw new Error(`Directory not found at ${r}`);if(!await k.pathExists(n))throw new Error(`File not found at ${n}`);await $t(n)}catch(r){throw new Error(`Next.js setup failed: ${r.message}`)}};function Mt(t,e){if(![".tsx",".ts",".jsx",".js"].includes(t.getExtension()))return t.getText();let o=t.getImportDeclarations();for(let r of o){let n=Ie(r.getModuleSpecifierValue(),e);r.setModuleSpecifier(n),n==="@/lib/utils"&&r.getNamedImports().find(m=>m.getName()==="cn")&&r.setModuleSpecifier(e.aliases.utils)}return t.getText()}function Ie(t,e){return t.startsWith("@/")?t.match(/^@\/registry\/ui/)?t.replace(/^@\/registry\/ui/,e.aliases.ui??`${e.aliases.components}/ui`):e.aliases.components&&t.match(/^@\/registry\/components/)?t.replace(/^@\/registry\/components/,e.aliases.components):e.aliases.animated&&t.match(/^@\/registry\/animated/)?t.replace(/^@\/registry\/animated/,e.aliases.animated):e.aliases.lib&&t.match(/^@\/registry\/lib/)?t.replace(/^@\/registry\/lib/,e.aliases.lib):e.aliases.hooks&&t.match(/^@\/registry\/(.+)\/hooks/)?t.replace(/^@\/registry\/hooks/,e.aliases.hooks):t.replace(/^@\/app\/registry\/(.+)\/components/,e.aliases.components):t}import{SyntaxKind as j}from"ts-morph";var Ae=/^["']use client["']$/,zt=async({sourceFile:t,config:e})=>{if(e.rsc)return t;let o=t.getFirstChildByKind(j.ExpressionStatement);o&&Ae.test(o.getText())&&o.remove();let r=t.getImportDeclarations();for(let a of r){let p=a.getModuleSpecifierValue();(p==="next/image"||p==="next/link")&&a.remove()}let n=t.getDescendantsOfKind(j.JsxSelfClosingElement);for(let a of n)a.getTagNameNode().getText()==="Image"&&a.replaceWithText(p=>{p.write("<img"),a.getAttributes().forEach(h=>{p.write(" ").write(h.getText())}),p.write(" />")});let i=t.getDescendantsOfKind(j.JsxOpeningElement),s=t.getDescendantsOfKind(j.JsxClosingElement);for(let a of i)a.getTagNameNode().getText()==="Image"&&a.getTagNameNode().replaceWithText("img");for(let a of s)a.getTagNameNode().getText()==="Image"&&a.getTagNameNode().replaceWithText("img");let m=t.getDescendantsOfKind(j.JsxOpeningElement),d=t.getDescendantsOfKind(j.JsxClosingElement),v=t.getDescendantsOfKind(j.JsxSelfClosingElement);for(let a of m)a.getTagNameNode().getText()==="Link"&&a.getTagNameNode().replaceWithText("a");for(let a of d)a.getTagNameNode().getText()==="Link"&&a.getTagNameNode().replaceWithText("a");for(let a of v)a.getTagNameNode().getText()==="Link"&&a.replaceWithText(p=>{p.write("<a"),a.getAttributes().forEach(h=>{p.write(" ").write(h.getText())}),p.write(" />")});return t};import{Project as _e}from"ts-morph";var Ve=new _e({useInMemoryFileSystem:!0}),Lt=async(t,e,o,r)=>{let n=Ve.createSourceFile(e,o),i=Mt(n,r);return t.framework.name==="vite"&&(i=(await zt({sourceFile:n,config:t})).getFullText()),n.delete(),i};var ze=C.object({components:C.array(C.string()).optional(),cwd:C.string(),yes:C.boolean(),all:C.boolean(),overwrite:C.boolean(),silent:C.boolean()}),Wt=new Be().name("add").description("Add components to ui folder inside the components folder in your project").argument("[components...]","The components to add.").option("-y, --yes","Skip confirmation prompts.",!1).option("-a, --all","Install all available components.",!1).option("-c, --cwd <cwd>","The working directory. Defaults to the current directory.",process.cwd()).option("-o, --overwrite","Overwrite existing files if they exist.",!1).option("-s, --silent","Mute output logs.",!1).action(async(t,e)=>{try{let o=ze.parse({components:t,cwd:A.resolve(e.cwd),...e});if(!(await st(o)).config){c.log("The current path does not have a project. You can add components are creating a new project.");let s={cwd:o.cwd,skipPrompts:!1,defaultConfigurations:!1},m=await L(o),{projectPath:d}=await J(s,m);await I(d,m.framework,m.useSrcDir),o.cwd=d}if(!o.components?.length){let s=await kt(o);s.length||(c.warn("No components selected. Exiting."),process.exit(1)),o.components=s}let n=await Le(o.components),i=await Q(await $(),n);await We(i,o,await M(o.cwd))}catch(o){w(o)}}),Le=async t=>{let e=u("Checking registry").start(),o=(await $()).map(n=>n.name),r=t.filter(n=>!o.includes(n));return r.length>0&&(e.fail("Checking registry. Not found:"),r.forEach(n=>c.info(`- ${n}`)),process.exit(1)),e.succeed(),t},ot=async(t,e)=>t=="ui"?e.aliases.ui.replace("@/",""):t=="component"?e.aliases.components.replace("@/",""):t=="animated"?e.aliases.animated?.replace("@/","")??"components/animated":t=="hook"?e.aliases.hooks?.replace("@/","")??"hooks":e.aliases.components.replace("@/","");async function We(t,e,o){let r=o.hasSrcDir;await mt(t,e);let n=[],i=[],s=[],m=[],d=ft(t),v=await _(e.cwd);for(let a of t){for(let p of a.files){let h;switch(o.framework.name){case"next-app":{let S=p.type==="page"?`app/${p.targetDir}`:await ot(p.type,v);h=A.join(e.cwd,r?"src":"",S,p.type==="page"?"page.tsx":p.name);break}case"next-pages":{let S=p.type==="page"?`pages/${p.targetDir}`:await ot(p.type,v);h=A.join(e.cwd,r?"src":"",S,p.type==="page"?"index.tsx":p.name);break}case"vite":{let S=p.type==="page"?`${p.targetDir}`:await ot(p.type,v);h=A.join(e.cwd,r?"src":"",S,p.name);break}default:throw new Error("Framework not supported")}let rt=await G.exists(h);if(rt&&!e.overwrite){if(d.has(a.name)&&a.type!=="block"){s.push(h);continue}let{overwrite:Jt}=await Me({type:"confirm",name:"overwrite",message:`Component ${l.info(p.name)} already exists. Would you like to overwrite?`,initial:!1});if(!Jt){s.push(h);continue}}await Ue(h,o,p,v),rt?i.push(h):n.push(h)}a.assetsDirectory&&m.push({componentName:a.name,assetsDirectory:a.assetsDirectory})}await wt(m),e.silent||(n.length>0&&(c.break(),c.info(`Created ${n.length} file(s):`),n.forEach(a=>c.log(` - ${a}`))),i.length>0&&(c.break(),c.info(`Updated ${i.length} file(s):`),i.forEach(a=>c.log(` - ${a}`))),s.length>0&&(c.break(),c.info(`Skipped ${s.length} file(s):`),s.forEach(a=>c.log(` - ${a}`))))}var Ue=async(t,e,o,r)=>{let n=A.dirname(t);await G.exists(n)||await G.mkdir(n,{recursive:!0});let i=await Lt(e,t,o.content,r);await G.writeFile(t,i)};import{instagram as Je}from"gradient-string";var Ut=t=>{c.break(),c.log(Je(t)),c.break()};process.on("uncaughtException",w);process.on("unhandledRejection",w);process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function Ke(){let t=new Ge().name(T.name).description(T.description).version(T.version,"-v, --version","display the version number");Ut(`RadianOS v${T.version}`),t.addCommand(Tt),t.addCommand(Wt),t.parse()}Ke(); //# sourceMappingURL=index.js.map