untitledui 0.1.49 → 0.1.52
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/config/styles/theme.css +4 -0
- package/dist/index.mjs +38 -30
- package/package.json +8 -8
package/config/styles/theme.css
CHANGED
|
@@ -748,6 +748,7 @@
|
|
|
748
748
|
--color-bg-error-primary: var(--color-error-50);
|
|
749
749
|
--color-bg-error-secondary: var(--color-error-100);
|
|
750
750
|
--color-bg-error-solid: var(--color-error-600);
|
|
751
|
+
--color-bg-error-solid_hover: var(--color-error-700);
|
|
751
752
|
--color-bg-warning-primary: var(--color-warning-50);
|
|
752
753
|
--color-bg-warning-secondary: var(--color-warning-100);
|
|
753
754
|
--color-bg-warning-solid: var(--color-warning-600);
|
|
@@ -825,6 +826,7 @@
|
|
|
825
826
|
--background-color-error-primary: var(--color-bg-error-primary);
|
|
826
827
|
--background-color-error-secondary: var(--color-bg-error-secondary);
|
|
827
828
|
--background-color-error-solid: var(--color-bg-error-solid);
|
|
829
|
+
--background-color-error-solid_hover: var(--color-bg-error-solid_hover);
|
|
828
830
|
--background-color-warning-primary: var(--color-bg-warning-primary);
|
|
829
831
|
--background-color-warning-secondary: var(--color-bg-warning-secondary);
|
|
830
832
|
--background-color-warning-solid: var(--color-bg-warning-solid);
|
|
@@ -1170,6 +1172,7 @@
|
|
|
1170
1172
|
--color-bg-error-primary: var(--color-error-950);
|
|
1171
1173
|
--color-bg-error-secondary: var(--color-error-600);
|
|
1172
1174
|
--color-bg-error-solid: var(--color-error-600);
|
|
1175
|
+
--color-bg-error-solid_hover: var(--color-error-500);
|
|
1173
1176
|
--color-bg-warning-primary: var(--color-warning-950);
|
|
1174
1177
|
--color-bg-warning-secondary: var(--color-warning-600);
|
|
1175
1178
|
--color-bg-warning-solid: var(--color-warning-600);
|
|
@@ -1251,6 +1254,7 @@
|
|
|
1251
1254
|
--background-color-error-primary: var(--color-bg-error-primary);
|
|
1252
1255
|
--background-color-error-secondary: var(--color-bg-error-secondary);
|
|
1253
1256
|
--background-color-error-solid: var(--color-bg-error-solid);
|
|
1257
|
+
--background-color-error-solid_hover: var(--color-bg-error-solid_hover);
|
|
1254
1258
|
--background-color-warning-primary: var(--color-bg-warning-primary);
|
|
1255
1259
|
--background-color-warning-secondary: var(--color-bg-warning-secondary);
|
|
1256
1260
|
--background-color-warning-solid: var(--color-bg-warning-solid);
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import{Command as J2}from"commander";import W1 from"async-retry";import _ from"chalk";import{Command as d1}from"commander";import{execa as R0}from"execa";import*as k from"fs";import K0 from"ora";import h1 from"os";import*as C from"path";import p from"prompts";import{Project as f1}from"ts-morph";import r0 from"node-fetch";import{Readable as N1,pipeline as D1}from"stream";import{x as y1}from"tar";import{promisify as A1}from"util";var v1=A1(D1);async function i0(z,B){try{let Q=await _1(B);await v1(Q,y1({cwd:z,strip:1}))}catch(Q){throw new Error(`Failed to download or extract repository from API: ${Q instanceof Error?Q.message:Q}`)}}async function _1(z){let B=`https://www.untitledui.com/react/api/download-repo?template=${z.template}`;try{let Q=await r0(B,{method:"GET",headers:{"Content-Type":"application/json",Accept:"application/octet-stream"}});if(Q.status===403||Q.status===404)throw new Error("Repository not found");if(!Q.ok)throw new Error(`Failed to download from API. Status: ${Q.status} ${Q.statusText}`);if(!Q.body)throw new Error("Response body is empty");return N1.from(Q.body)}catch(Q){throw new Error(`Error downloading tarball: ${Q instanceof Error?Q.message:Q}`)}}async function J0(z){let B=`https://www.untitledui.com/react/api/validate-key?key=${z}`;try{return(await r0(B)).status===200}catch{return!1}}import E1 from"node-fetch";var n0={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function b0(z,B,Q){let Y=B.map((q)=>{if(q.includes("modals/"))if(q.includes("-modal"))return q;else return q+"-modal";return q});try{let q=await E1("https://www.untitledui.com/react/api/components",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:z,components:Y,key:Q})});if(!q.ok)console.log(n0?.[q.statusText]||n0.no_components_found),process.exit(1);return await q.json()}catch(q){return null}}import u0 from"node-fetch";var $0={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function p0(z,B=""){let Q=`https://www.untitledui.com/react/api/components/list?key=${B}&type=${z}`;try{let $=await u0(Q),Y=await $.json();if(!$.ok)console.log($0?.[$.statusText]||$0.no_components_found),process.exit(1);if(!Y?.components?.length)return null;return Y}catch($){return console.error($),null}}async function o0(z,B="",Q){let $=`https://www.untitledui.com/react/api/components/list?key=${B}&type=${z}&subfolders=${Q.join(",")}`;try{let Y=await u0($);if(!Y.ok)console.log($0?.[Y.statusText]||$0.no_components_found),process.exit(1);let q=await Y.json();if(!q?.components?.length)return null;return q}catch(Y){return console.error(Y),null}}async function t0(z=""){let B=`https://www.untitledui.com/react/api/components/list?key=${z}`;try{let Q=await u0(B);if(!Q.ok)console.log($0?.[Q.statusText]||$0.no_components_found),process.exit(1);let $=await Q.json();if(!$?.types?.length)return null;return $}catch(Q){return console.error(Q),null}}import T0 from"fast-glob";import*as j0 from"fs";import*as c from"path";import{Project as P1}from"ts-morph";import{loadConfig as Y1}from"tsconfig-paths";import u1 from"prettier";async function e0(z,B="typescript"){try{return await u1.format(z,{parser:B,printWidth:160,tabWidth:4})}catch(Q){return console.error("Error formatting with Prettier:",Q),z}}import h from"chalk";import r from"fast-glob";import*as m from"fs";import*as f from"path";import{loadConfig as H0}from"tsconfig-paths";import z1 from"fs";import T1 from"path";function B1(z=""){let B=T1.join(z,"package.json");if(!z1.existsSync(B))return null;else return JSON.parse(z1.readFileSync(B,"utf-8"))}import x1 from"path";import{createMatchPath as w1}from"tsconfig-paths";function Q1(z,B){let Q=x1.posix.join(z,"index"),$=w1(B.absoluteBaseUrl,B.paths)(Q,void 0,()=>!0,[".ts",".tsx",".jsx",".js",".css"]);if($)return $.split("/").slice(0,-1).join("/");else return}var g=["**/node_modules/**",".next","public","dist","build"],M0=!1,Z1={"next-app":"Next.js (App)","next-pages":"Next.js (Pages)",vite:"Vite",other:"Other"};async function n(z){let B=m.existsSync(f.resolve(z,"src")),Q=m.existsSync(f.resolve(z,`${B?"src/":""}app`)),[$,Y,q,L,b]=await Promise.all([r.glob("**/{next,vite,astro}.config.*|gatsby-config.*",{cwd:z,deep:2,ignore:g}),S1(z),k1(z),C1(z),B1(z)]),U=m.existsSync(f.resolve(z,"components.json")),V=null;if(U)V=JSON.parse(m.readFileSync(f.resolve(z,"components.json"),"utf-8"));let J=r.sync(["**/**/theme.css"],{cwd:z,absolute:!0,onlyFiles:!0,ignore:g}),H=J?.[0]&&m.readFileSync(J[0],"utf-8").match(/(--color-brand+-\d{1,3}):\s*(rgb\([^)]+\))/g)?.[1]||void 0,I={tailwind:{config:q||void 0,brandColor:H?.replace(/--color-([^-]+(?:-[^-]+)?)-\d+:.*/,"$1")||void 0},examples:V?.examples||void 0,aliases:V?.aliases||L||{},paths:await F1(V?.aliases||{})||{},isTsx:Y,isSrcDir:B,isAppDir:Q,isComponentsJson:!!U,framework:"other"};if($.find((G)=>G.startsWith("next.config."))?.length)return I.framework=Q?"next-app":"next-pages",I;else if($.find((G)=>G.startsWith("vite.config."))?.length)return I.framework="vite",I;else if(Object.keys(b?.dependencies||{}).includes("react"))return I.framework="next-pages",I;else if($?.length||m.existsSync(f.resolve(z,"package.json")))return I.framework="other",I;return null}async function S1(z){return(await r.glob("tsconfig.*",{cwd:z,deep:2,ignore:g})).length>0}async function F1(z){let B={},Q=[],$=Object.entries(z).filter(([,U])=>U);if($.length===0)return null;let Y=process.cwd(),L=H0(Y).resultType==="success",b=await $1(Y);if(!b){if(!M0){if(M0=!0,process.stdout.write("\r\x1B[K"),L)console.log(h.yellow(`
|
|
3
|
+
⚠ Could not resolve path aliases from components.json - no paths configured in tsconfig.json.`));else console.log(h.yellow(`
|
|
4
|
+
⚠ Could not resolve path aliases from components.json - tsconfig.json not found.`));console.log(h.dim(` The following aliases will be used for imports but files will be placed in default locations:
|
|
5
|
+
`)),$.forEach(([U,V])=>{console.log(h.dim(` ${U}: ${V}`))}),console.log(h.dim(`
|
|
6
|
+
To fix this, add matching paths to your tsconfig.json.
|
|
7
|
+
`))}return null}for(let[U,V]of Object.entries(z))if(V){let J=await Q1(V.replace(/\/\*$/,""),b);if(J)B[U]=f.relative(process.cwd(),J);else Q.push(`${U}: ${V}`)}if(Q.length>0&&!M0)M0=!0,process.stdout.write("\r\x1B[K"),console.log(h.yellow(`
|
|
8
|
+
⚠ Could not resolve the following path aliases from tsconfig.json:`)),Q.forEach((U)=>{console.log(h.dim(` ${U}`))}),console.log(h.dim(`
|
|
9
|
+
These aliases will be used for imports but files will be placed in default locations.`)),console.log(h.dim(` To fix this, add matching paths to your tsconfig.json.
|
|
10
|
+
`));return B}async function $1(z){let[B,Q]=await Promise.all([r.glob("next.config.*",{cwd:z,deep:1,ignore:g}),r.glob("vite.config.*",{cwd:z,deep:1,ignore:g})]),$=B.length>0,Y=Q.length>0,q=null;if($)q=H0(z);else if(Y){if(q=H0(z),q?.resultType==="failed"||!Object.keys(q.paths||{}).length){let L=await r.glob(["tsconfig.app.*","*/tsconfig.app.*"],{cwd:z,deep:1,onlyFiles:!0,absolute:!0,ignore:g}),[b]=L;if(b)try{let V=function(I){return I.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"").replace(/,(\s*[}\]])/g,"$1")},U=m.readFileSync(b,"utf-8"),J=V(U),H=JSON.parse(J);if(H.compilerOptions?.paths)q={resultType:"success",paths:H?.compilerOptions?.paths,baseUrl:H.compilerOptions.baseUrl||".",configFileAbsolutePath:b,absoluteBaseUrl:f.resolve(z,H.compilerOptions.baseUrl||".")}}catch{}}}else q=H0(z);if(!q||q?.resultType==="failed"||!Object.keys(q.paths).length)return null;return q}async function k1(z){let B=await r.glob("tailwind.config.*",{cwd:z,deep:2,ignore:g});if(!B.length)return null;return B[0]}async function C1(z){let B=await $1(z);if(!B)return null;let Q={},$={app:/\/?app\/\*$/,components:/\/?components\/\*$/,utils:/\/?utils\/\*$/,styles:/\/?styles\/\*$/,hooks:/\/?hooks\/\*$/,src:/^(\.\/src\/\*|\.\/\*|\/src\/\*|src\/\*|\/\*|\*)$/};for(let[Y,q]of Object.entries(B.paths)){let L=Y.replace(/\/\*$/,"/");for(let[b,U]of Object.entries($))if(q.some((V)=>U.test(V))){Q[b]=L;break}}return Q||null}function Y0(z,B){let Q=Y1(z),$=T0.sync(["tailwind.config.*","**/globals.css","package.json"],{cwd:z,deep:4,absolute:!0,onlyFiles:!0,ignore:g}),Y=T0.sync("**/{layout,_app,main}.tsx",{cwd:B?c.posix.join(z,B):z,deep:4,absolute:!0,onlyFiles:!0,ignore:g});return{tailwindFile:$.find((L)=>L.includes("tailwind.config.")),cssFile:$.find((L)=>L.includes("globals.css")),packageJson:$.find((L)=>L.includes("package.json")),tsConfig:Q?.resultType==="success"?Q?.configFileAbsolutePath:void 0,layoutFile:Y.find((L)=>L.includes("layout")),appFile:Y.find((L)=>L.includes("_app")),mainFile:Y.find((L)=>L.includes("main"))}}function q0(z,B,Q={}){if(z.startsWith("@/components/")){if(Q?.components)return z.replace(/^@\/components\//,c.posix.join(Q.components,"/"));if(B)return z.replace(/^@\/components\//,c.posix.join("@",B,"/"))}if(z.startsWith("@/app/")&&Q?.app)return z.replace(/^@\/app\//,c.posix.join(Q.app,"/"));if(z.startsWith("@/utils/")&&Q?.utils)return z.replace(/^@\/utils\//,c.posix.join(Q.utils,"/"));if(z.startsWith("@/hooks/")&&Q?.hooks)return z.replace(/^@\/hooks\//,c.posix.join(Q.hooks,"/"));if(z.startsWith("@/styles/")&&Q?.styles)return z.replace(/^@\/styles\//,c.posix.join(Q.styles,"/"));if(z.startsWith("@/")&&Q?.src)return z.replace(/^@\//,c.posix.join(Q.src,"/"));return z}async function q1(z,B,Q="@/*"){let $=await Y1(z);if($?.resultType==="failed")return null;let Y={};if(!Object.keys($.paths).length){$.paths={[Q]:[`./${B?"src/":""}*`]},Y.src=Q.replace(/\/\*$/,"");let q=await j0.promises.readFile($.configFileAbsolutePath,"utf-8"),L,b=/(?:\/\/\s*)?"paths":\s*\{(?:[^{}]|\{[^}]*\})*\}/;if(!b.test(q))L=q.replace(/"compilerOptions":\s*{/,`"compilerOptions": {
|
|
11
|
+
"paths": ${JSON.stringify($.paths)},`);else L=q.replace(b,`"paths": ${JSON.stringify($.paths)}`);let V=new P1,J=await e0(L,"json");return V.createSourceFile($.configFileAbsolutePath,J,{overwrite:!0}),await V.save(),Y}return Y||null}function X1(z){let B=T0.sync(["vite.config.*"],{cwd:z,absolute:!0,onlyFiles:!0,ignore:g})?.[0];if(!B)return!1;try{let Q=j0.readFileSync(B,"utf-8");return O1(Q)}catch{return!1}}function O1(z){let B=z.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"");if(!["tailwindcss","@tailwindcss/vite","tailwind("].some((q)=>B.includes(q)))return!1;return["plugins:","postcss:","css:"].some((q)=>B.includes(q))}var g1=["npm","config","user","agent"].join("_");function F(){let z=process.env[g1]||"";if(z.startsWith("yarn"))return"yarn";if(z.startsWith("pnpm"))return"pnpm";if(z.startsWith("bun"))return"bun";return"npm"}function X0(){switch(F()){case"yarn":return"yarn";case"pnpm":return"pnpx";case"bun":return"bunx";default:return"npx"}}function U1(){switch(F()){case"yarn":return"yarn dev";case"pnpm":return"pnpm dev";case"bun":return"bun dev";default:return"npm run dev"}}function G0(z){return z.replace(/^[ \t]*\/\/\s*(TODO:|collapse-(start|end)).*\r?\n?|[ \t]*{\s*\/\*\s*(TODO:|collapse-(start|end)).*?\*\/\s*}\r?\n?/gm,"")}import l from"path";function I0(z,B,Q){let $=z.replace(/^(components|utils|hooks|styles)\//,"");if(z.includes("components")&&B?.components)return l.relative(process.cwd(),l.posix.join(B.components,$));if(z.includes("utils")&&B?.utils)return l.relative(process.cwd(),l.posix.join(B.utils,$));if(z.includes("hooks")&&B?.hooks)return l.relative(process.cwd(),l.posix.join(B.hooks,$));if(z.includes("styles")&&B?.styles)return l.relative(process.cwd(),l.posix.join(B.styles,$));return l.posix.join(Q?"src":"",$)}var m1=C.join(h1.homedir(),".untitledui"),o=C.join(m1,"config.json"),K={components:[],path:"",type:void 0,license:""};if(k.existsSync(o)){let z=JSON.parse(k.readFileSync(o,"utf-8"));K.license=z.license}var U0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
12
|
+
`),process.exit(1)},K1=new d1().name("add").description("add a component to your project").argument("[components...]","the components to add").option("-a, --all","add all available components",!1).option("-o, --overwrite","overwrite existing files.",!1).option("-p, --path <path>","the path to add the component to.").option("-d, --dir <directory>","the directory where the project is located.").option("-t, --type <base|marketing|shared-assets|application|foundations>","the type of the component to add.").action(async(z,B)=>{if(z)K.components=z;if(B)K.all=B.all,K.dir=B.dir,K.path=B.path,K.overwrite=B.overwrite,K.license=B.license||K.license;try{await x0(K)}catch(Q){console.error(_.red(Q))}});async function x0(z){if(z)K={...K,...z};let B=K0().start(),Q=C.posix.join(process.cwd(),K.dir||"");if(!k.existsSync(C.resolve(Q,"package.json")))B.warn("This command should be run in a project directory."),process.exit(1);let Y=await n(Q);if(K.license){if(!await J0(K.license))B.fail("Invalid license key"),process.exit(1);if(!k.existsSync(o)){let M=C.dirname(o);k.mkdirSync(M,{recursive:!0}),k.writeFileSync(o,JSON.stringify({license:K.license},null,2))}if(JSON.parse(k.readFileSync(o,"utf-8")).license!==K.license)k.writeFileSync(o,JSON.stringify({license:K.license},null,2),"utf-8")}B.stop();let q=[];if(K.components.length){let Z=await b0(K.type,K.components,K.license);if(Z&&Z.pro&&Z.pro.length>0){if(console.log(),Z.pro.length===1){let X=Z.pro[0]?.split("/")[1]||Z.pro[0];console.log(_.yellow(`\uD83D\uDD12 The ${_.cyan(X)} component requires PRO access.`))}else console.log(_.yellow("\uD83D\uDD12 The following components require PRO access:")),Z.pro.forEach((X)=>{let M=X?.split("/")[1]||X;console.log(` • ${_.cyan(M)}`)});console.log(),console.log("To access PRO components:"),console.log(` ${_.green("→")} If you've already purchased: ${_.cyan(`${X0()} untitledui@latest login`)}`),console.log(` ${_.green("→")} To purchase PRO components: ${_.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(!Z?.components.length)console.log("No components found"),process.exit(1);q.push(...Z.components)}if(!K?.type&&!K?.components.length){let Z=await t0(K.license);if(!Z)console.log("No component types found"),process.exit(1);let X=await p({type:"select",name:"type",onState:U0,message:`What type of ${_.cyan("component")} are you adding?`,choices:Z?.types.map((M)=>({title:M,value:M}))});K.type=X.type}if(!K?.path&&!Y?.paths?.components){let Z=await p({type:"text",name:"path",onState:U0,message:`Where would you like to add the ${_.cyan("components")}?`,initial:"components"});K.path=Z.path}if(K?.path&&Y&&Y.paths)Y.paths.components=C.posix.join(Y?.isSrcDir?"src":"",K.path);if(Y&&!Object.keys(Y?.aliases).length){let Z=/^[^*"]+\/\*\s*$/,X=await p({type:"text",name:"aliasPrefix",onState:U0,initial:"@/*",message:`What is the ${_.cyan("import alias")} for your project?`,validate:(M)=>Z.test(M)?!0:"Import alias must follow the pattern <prefix>/*"});Y.aliases=await q1(Q,Y?.isSrcDir,X?.aliasPrefix)}if(!K?.components.length){let Z=await p0(K?.type,K.license);if(!Z)console.log("No components found"),process.exit(1);let X=await p({type:"multiselect",name:"components",onState:U0,message:`Which ${_.cyan("components")} would you like to add?`,choices:Z?.components?.map((D)=>({title:D?.name+(D?.count?` (${D?.count} variants)`:"")||"example",value:D||"example",selected:K.components.includes(D.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!X.components||!X.components.length)console.log("No option selected. Exiting..."),process.exit(1);let M=X.components.filter((D)=>D?.type==="file").map((D)=>D.name),x=X.components.filter((D)=>D?.type==="dir").map((D)=>D.name),A=[];if(x.length){let D=await o0(K?.type,K.license,x);if(D&&D.components.length)for(let R of D.components){let[u,E]=Object.entries(R)[0]||[],P=await p({type:"select",name:"component",onState:U0,message:`Which ${_.cyan("variant")} from ${_.cyan(u)} would you like to add?`,choices:E?.map((O)=>({title:O?.name.replace(/-modal/g,"")||"example",value:O?.name||"example",selected:K.components.includes(O.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!P.component)console.log("No variant selected for "+_.cyan(u));A.push(u+"/"+P.component)}else console.log("No variants found")}K.components=[...A,...M]}if(!K.components?.length)B.warn("No components selected. Exiting."),process.exit(1);let L=Y0(Q),b=new Set,U=new Set,V=new Set,J=new f1({tsConfigFilePath:L?.tsConfig});if(B.start(),K.type&&K.components.length){let Z=await b0(K.type,K.components,K.license);if(!Z?.components.length)console.log("No components found"),process.exit(1);q.push(...Z.components)}let H=new Set;if(q.forEach((Z)=>{Z?.components?.forEach((X)=>{H.add({name:X.name,path:X.path})})}),B.stop(),H.size){let Z=Array.from(H).filter((X)=>!k.existsSync(C.posix.join(Q,`${Y?.isSrcDir?"src":""}`,X?.path?.replace(/components\//,K.path+"/"))));if(Z?.length){let X=await p({type:"multiselect",name:"baseComponents",onState:U0,message:"Select which base components you want to add",choices:Z.map((M)=>({title:M?.name,value:M?.name,selected:!0})),instructions:!1,hint:"- Space to select. Return to submit"});if(K.baseComponents=X.baseComponents,!Z.length&&!X.baseComponents?.length)B.warn("No components selected")}}if(B.start(),K?.baseComponents?.length){let Z=await b0("",K.baseComponents,K.license);if(!Z||!Z?.components.length)console.log("No base components found");else q.push(...Z.components)}B.stop();let I=new Set;for(let Z of q){let X=K0(`Adding ${Z.name}...`).start(),M=Z.files;Z?.dependencies?.forEach((A)=>U.add(A)),Z?.devDependencies?.forEach((A)=>V.add(A));let x=!1;try{for(let{path:A,code:D}of M||[]){let R=C.posix.join(Q,I0(A,Y?.paths,Y?.isSrcDir)),u=Y?.framework==="vite"?D.replace(`"use client";
|
|
5
13
|
|
|
6
|
-
`,""):E
|
|
7
|
-
Failed to add the component ${
|
|
8
|
-
Following files already exist in the directory.`),
|
|
14
|
+
`,""):D,E=G0(u),P=C.dirname(R);if(k.existsSync(R)&&!K.overwrite&&!I.has(R)){if(k.readFileSync(R,"utf-8")!==E)b.add({code:E,path:R}),x=!0}else if(!I.has(R)){k.mkdirSync(P,{recursive:!0}),k.writeFileSync(R,E),I.add(R);let O=J.addSourceFileAtPath(C.resolve(R));O.getImportDeclarations().forEach((s)=>{let s0=s.getModuleSpecifierValue();s.setModuleSpecifier(q0(s0,K.path,Y?.aliases))}),await O.save()}}if(x)X.warn(`Some files of ${_.yellow(Z.name)} already exist`);else X.succeed(`${_.green(Z.name)} is added successfully`)}catch(A){X.fail(`
|
|
15
|
+
Failed to add the component ${_.red(Z.name)}`),console.error(_.red(A)),process.exit(1)}}if(b.size&&!K?.overwrite){console.log(`
|
|
16
|
+
Following files already exist in the directory.`),b.forEach((X)=>{console.log(_.green(`- ${C.relative(Q,X.path)}`))});let Z=await p({type:"confirm",name:"overwrite",message:"Do you want to overwrite the existing files?",initial:!0});if(Z.overwrite===void 0)console.log(`
|
|
17
|
+
Use ${_.cyan("--overwrite")} or ${_.cyan("-o")} flag to overwrite existing files, or run with ${_.cyan("node")} instead of ${_.cyan("bun")}.`),process.exit(1);if(Z.overwrite){let X=K0("Overwriting files").start();b.forEach((M)=>{let x=J.addSourceFileAtPath(C.resolve(M.path));x.replaceWithText(M.code),x.getImportDeclarations().forEach((A)=>{let D=A.getModuleSpecifierValue();A.setModuleSpecifier(q0(D,K.path,Y?.aliases))}),x.saveSync()}),X.succeed("Files are overwritten")}}let G=F();if(U?.size){let Z=K0("Installing component dependencies").start();await W1(()=>R0(G,[G==="npm"?"install":"add",...U],{cwd:Q}).catch(async(X)=>{if(X.message.includes("peer"))Z.warn("Component dependencies conflict detected. Retrying with --legacy-peer-deps..."),Z.start("Installing component dependencies with --legacy-peer-deps flag"),await R0(G,[G==="npm"?"install":"add",...U,"--legacy-peer-deps"],{cwd:Q})}),{retries:1}),Z.succeed("Component dependencies are installed")}if(V?.size){let Z=K0("Installing component devDependencies").start();await W1(()=>R0(G,[G==="npm"?"install":"add","-D",...V],{cwd:Q}).catch(async(X)=>{if(X.message.includes("peer"))Z.warn("Component devDependencies conflict detected. Retrying with --legacy-peer-deps..."),Z.start("Installing component devDependencies with --legacy-peer-deps flag"),await R0(G,[G==="npm"?"install":"add","-D",...V,"--legacy-peer-deps"],{cwd:Q})}),{retries:1}),Z.succeed("Component devDependencies are installed")}if(K.message!==void 0){if(K.message)console.log(K.message);return}process.exit(0)}import F0 from"chalk";import{Command as s1}from"commander";import*as a from"fs";import r1 from"http";import i1 from"open";import n1 from"ora";import p1 from"os";import*as C0 from"path";import{URL as o1}from"url";import*as N0 from"fs";import*as t from"path";import{fileURLToPath as c1}from"url";var l1=c1(import.meta.url),w0=t.dirname(l1);function a1(){let z=[t.join(w0,"..","templates","auth-template.html"),t.join(w0,"templates","auth-template.html"),t.join(process.cwd(),"node_modules","untitledui","templates","auth-template.html"),t.join(w0,"..","..","templates","auth-template.html")];for(let B of z)if(N0.existsSync(B))return B;throw new Error("Auth template file not found. Please ensure the CLI package is properly installed.")}function L1(){try{let z=a1();return N0.readFileSync(z,"utf-8")}catch(z){return console.warn("Warning: Using fallback auth template. Some styling may be missing."),`<!doctype html>
|
|
9
18
|
<html lang="en">
|
|
10
19
|
<head>
|
|
11
20
|
<meta charset="UTF-8" />
|
|
@@ -51,31 +60,30 @@ Following files already exist in the directory.`),G.forEach(($)=>{console.log(N.
|
|
|
51
60
|
{{AUTO_CLOSE_SCRIPT}}
|
|
52
61
|
</div>
|
|
53
62
|
</body>
|
|
54
|
-
</html>`}}function
|
|
55
|
-
✨ You can now access PRO components with the CLI!`)),process.exit(0)}catch(
|
|
56
|
-
Failed to open browser automatically: ${
|
|
57
|
-
`))}),z.text="Waiting for authentication in browser..."}),setTimeout(()=>{
|
|
58
|
-
`),process.exit(1)},
|
|
59
|
-
Creating a new project in ${
|
|
63
|
+
</html>`}}function V1(){return L1().replace("{{TITLE}}","Authentication successful").replace("{{HEADING}}","Authentication successful").replace("{{DESCRIPTION}}","You can now close this tab and return to your terminal.").replace("{{AUTO_CLOSE_SCRIPT}}","<script>setTimeout(() => window.close(), 10000);</script>")}function D0(z){return L1().replace("{{TITLE}}","Authentication failed").replace("{{HEADING}}","Authentication failed").replace("{{DESCRIPTION}}",z).replace("{{AUTO_CLOSE_SCRIPT}}","")}var k0=C0.join(p1.homedir(),".untitledui"),S0=C0.join(k0,"config.json"),J1=new s1().name("login").description("authenticate with Untitled UI to access PRO components").action(async()=>{let z=n1("Starting authentication...").start();try{await t1(z),z.succeed("Authentication completed successfully!"),console.log(F0.green(`
|
|
64
|
+
✨ You can now access PRO components with the CLI!`)),process.exit(0)}catch(B){z.fail(`Authentication failed: ${B instanceof Error?B.message:B}`),process.exit(1)}});async function t1(z){return new Promise((B,Q)=>{let $=r1.createServer((Y,q)=>{let L=new o1(Y.url,"http://localhost");if(L.pathname==="/callback"){let b=L.searchParams.get("apiKey"),U=L.searchParams.get("error");if(U){q.writeHead(400,{"Content-Type":"text/html"}),q.end(D0(decodeURIComponent(U))),$.close(),Q(new Error(decodeURIComponent(U)));return}if(!b){q.writeHead(400,{"Content-Type":"text/html"}),q.end(D0("No Access Token received")),$.close(),Q(new Error("No Access Token received"));return}try{e1(b),q.writeHead(200,{"Content-Type":"text/html"}),q.end(V1()),$.close(),B()}catch(V){q.writeHead(500,{"Content-Type":"text/html"}),q.end(D0("Failed to save authentication data")),$.close(),Q(V)}}else q.writeHead(404),q.end("Not found")});$.listen(0,"localhost",()=>{let L=`https://www.untitledui.com/react/api/cli-auth?port=${$.address().port}`;z.text="Opening browser for authentication...",i1(L).catch((b)=>{console.log(F0.yellow(`
|
|
65
|
+
Failed to open browser automatically: ${b.message}`)),console.log(F0.cyan(`Please manually open: ${L}
|
|
66
|
+
`))}),z.text="Waiting for authentication in browser..."}),setTimeout(()=>{$.close(),Q(new Error("Authentication timeout. Please try again."))},300000)})}function e1(z){if(!a.existsSync(k0))a.mkdirSync(k0,{recursive:!0});let B={};if(a.existsSync(S0))try{B=JSON.parse(a.readFileSync(S0,"utf-8"))}catch{B={}}B.license=z,a.writeFileSync(S0,JSON.stringify(B,null,2),"utf-8")}import c0 from"async-retry";import j from"chalk";import{Command as X2}from"commander";import{execa as E0}from"execa";import*as S from"fs";import V0 from"ora";import U2 from"os";import*as y from"path";import B0 from"prompts";import{Project as W2}from"ts-morph";import z2 from"node-fetch";async function y0(z,B){try{let $=await z2("https://www.untitledui.com/react/api/components/example",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({example:z,key:B})});if(!$.ok){if($.status===401||$.status===403)return{type:"error",status:$.status,message:"PRO access required"};return console.error(`API error: ${$.status} - ${$.statusText}`),null}return await $.json()}catch($){return console.error($?.message||"Error fetching example data."),null}}import L0 from"async-retry";import w from"chalk";import{Command as B2}from"commander";import{execa as e}from"execa";import h0 from"fast-glob";import T from"fs";import W0 from"ora";import Q2 from"os";import*as v from"path";import _0 from"prompts";import{Project as Z2}from"ts-morph";import{fileURLToPath as $2}from"url";import*as A0 from"fs";import*as b1 from"path";function P0(z,B){let Q=b1.join(z,"package.json");if(!A0.existsSync(Q))return B;let $=JSON.parse(A0.readFileSync(Q,"utf-8")),Y={...$.dependencies,...$.devDependencies},q=[];for(let L of B){let b=Y[L];if(!b){q.push(L);continue}if(L==="tailwindcss"){let U=b.match(/\d+/);if((U?parseInt(U[0],10):0)<4)q.push(L)}}return q}import O0 from"chalk";import*as i from"fs";import*as v0 from"path";function g0(z){if(!i.existsSync(v0.resolve(z)))console.log(O0.red(`Error: CSS file not found at ${z}`)),process.exit(1);let B=i.readFileSync(v0.resolve(z),"utf-8"),Q=/(--color-[a-zA-Z-]+-\d{1,3}):\s*(rgb\([^)]+\))/g,$={},Y;while((Y=Q.exec(B))!==null)if(Y[1]&&Y[2])$[Y[1]]=Y[2];return $}function d0(z,B,Q){let $=v0.resolve(Q);if(!i.existsSync($)){console.log(O0.red(`Error: CSS file not found at ${$}`));return}let Y=i.readFileSync($,"utf-8"),q=g0(Q),L={},b={};for(let[V,J]of Object.entries(q))if(V.startsWith(`--color-${z}-`)){let H=V.replace(`--color-${z}-`,"");L[H]=V}else if(V.startsWith(`--color-${B}-`)){let H=V.replace(`--color-${B}-`,"");b[H]=J}let U=!1;for(let[V,J]of Object.entries(L))if(b[V]){let H=b[V],I=new RegExp(`(${J}):\\s*rgb\\([^)]*\\);?`,"g");if(I.test(Y))Y=Y.replace(I,`$1: ${H};`),U=!0;else console.log(O0.yellow(`No match found for ${J}`))}if(U)i.writeFileSync($,Y,"utf-8")}var Y2=$2(import.meta.url),M1=v.dirname(Y2),q2=v.join(Q2.homedir(),".untitledui"),z0=v.join(q2,"config.json"),j1="vite",G1="nextjs",H1={[G1]:"Next.js",[j1]:"Vite"},d="",N={color:"",template:"",framework:void 0};if(T.existsSync(z0)){let z=JSON.parse(T.readFileSync(z0,"utf-8"));N.license=z.license}var f0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
67
|
+
`),process.exit(1)},I1=new B2().name("init").description("initialize a new project or adjust an existing one").argument("[directory]").usage("[directory] [options]").helpOption("-h, --help","display this help message.").option("--vite","initialize a Vite project.",!1).option("--nextjs","initialize a Next.js project.",!1).option("-o, --overwrite","overwrite existing files.",!1).option("--colors-list","show the colors list.",!1).option("-c, --color <color-name>","specify a color for the project.").action(async(z,B)=>{if(z)d=z;if(B){if(N.color=B.color,N.template=B.template,N.overwrite=B.overwrite,N.colorsList=B.colorsList,N.license=B.license||N.license,N.vite=B.vite,N.nextjs=B.nextjs,B.vite)N.framework=j1;if(B.nextjs)N.framework=G1}try{await m0(B),process.exit(0)}catch(Q){console.error(w.red(Q)),process.exit(1)}});async function m0(z,B=null){let Q=process.cwd(),$=T.existsSync(v.resolve(Q,"package.json")),Y=v.resolve(v.join(M1,"../config/styles","theme.css")),q=g0(Y??""),L=Array.from(new Set(Object.keys(q).map((J)=>J?.split("--color-")?.[1]?.replace(/-\d{1,3}/,"")))),b=W0().start(),U=await n(Q);if(N.license){if(!T.existsSync(z0)){let H=v.dirname(z0);T.mkdirSync(H,{recursive:!0}),T.writeFileSync(z0,JSON.stringify({license:N.license},null,2))}if(JSON.parse(T.readFileSync(z0,"utf-8")).license!==N.license)T.writeFileSync(z0,JSON.stringify({license:N.license},null,2))}if(!$){if(b.stop(),!d){let H=await _0({onState:f0,type:"text",name:"path",message:"What is your project named?",initial:"untitled-ui"});if(typeof H.path==="string")d=H.path.trim()}if(B)B.projectPath=d;let J=T.existsSync(v.resolve(v.posix.join(Q,d,"package.json")));if(T.existsSync(v.resolve(v.posix.join(Q,d)))&&J)b.fail(w.red("Directory already exists!")),process.exit(1);if(N.vite&&N.nextjs||!N.framework){let H=await _0({type:"select",name:"framework",onState:f0,message:`Which ${w.cyan("framework")} would you like to use?`,choices:Object.entries(H1).map(([I,G])=>({title:G,value:I}))});N.framework=H.framework}b.succeed("Framework is selected: "+w.green(H1[N.framework]))}else if(U?.framework==="other")b.fail("Unsupported project framework"),console.log(`Please refer to the documentation ${w.cyan("https://www.untitled.com/docs")} for supported frameworks or proceed with manual installation.`),process.exit(1);else if(U?.framework.startsWith("next")||U?.framework.startsWith("vite"))if(!B&&!U.tailwind.brandColor)b.succeed(w.yellow(`Detected ${Z1[U.framework]} project, proceeding with the setup...`));else b.stop();if(N.colorsList||!N.color&&!U?.tailwind.brandColor){let J=await _0({type:"select",name:"color",onState:f0,initial:z.color??"",message:`Which ${w.cyan("color")} would you like to use as the ${w.cyanBright("brand")} color?`,choices:L.map((H)=>({title:H,value:H}))});if(N.color=J.color,N.colorsList&&U)U.tailwind.brandColor=J.color}let V=v.posix.join(Q,d||"");if(d&&!$){let J=v.resolve(d);console.log(`
|
|
68
|
+
Creating a new project in ${w.blue(d)}`);let H=W0("Downloading and extracting the repository...").start();try{T.mkdirSync(J,{recursive:!0}),await L0(()=>i0(J,{template:N.framework}),{retries:2}),H.succeed("Files are downloaded and extracted successfully!");let I=W0({text:"Installing dependencies..."}).start(),G=h0.sync(["**/styles/theme.css"],{cwd:J,absolute:!0,onlyFiles:!0})[0];if(d0("brand",N.color||"",G??""),await L0(()=>e(F(),["install"],{cwd:V}).catch(async(Z)=>{if(Z.message.includes("peer"))I.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),I.start("Installing dependencies with --legacy-peer-deps flag"),await e(F(),["install","--legacy-peer-deps"],{cwd:V})}),{retries:1}),await L0(()=>e("git",["init"],{cwd:V}),{retries:1}),I.succeed("Dependencies are installed"),!B)console.log(`
|
|
60
69
|
Your project is ready, to get started run the following commands:
|
|
61
70
|
|
|
62
|
-
cd ${
|
|
63
|
-
${
|
|
64
|
-
Failed to download and extract the repository`)),
|
|
65
|
-
`);
|
|
66
|
-
`),
|
|
71
|
+
cd ${w.cyan(d)}
|
|
72
|
+
${w.cyan(U1())}`)}catch(I){if(H.fail(w.red(`
|
|
73
|
+
Failed to download and extract the repository`)),I instanceof Error)console.error(I.message);else console.error(`
|
|
74
|
+
`);T.rmdirSync(J,{recursive:!0}),process.exit(1)}}else{let J=W0(),H=new Set,I=U?.examples||"",G=Y0(Q,I),Z=v.resolve(v.join(M1,"../config")),X=h0.sync(["**"],{cwd:Z,onlyFiles:!0,ignore:g}),M=P0(Q,["tailwindcss","tailwindcss-animate","@tailwindcss/typography","tailwindcss-react-aria-components"]),x=P0(Q,["@tailwindcss/postcss","postcss"]);if(!B&&!U?.tailwind.brandColor)J.start("Copying files to the project directory");if(X.forEach((R)=>{let u=R.includes("postcss.config"),E=v.posix.join(v.posix.join(Z),R),P=v.posix.join(Q,u?R:I0(R,U?.paths,U?.isSrcDir));if(T.existsSync(P)){if(N?.overwrite)T.copyFileSync(E,P);else{let O=T.readFileSync(P,"utf-8"),s=T.readFileSync(E,"utf-8");if(O!==s){if(R.endsWith("theme.css")&&U?.tailwind.brandColor)return;H.add({targetFile:P,sourceFile:E})}}return}T.mkdirSync(v.dirname(P),{recursive:!0}),T.writeFileSync(P,""),T.copyFileSync(E,P)}),J.stop(),H.size&&!N?.overwrite){if(console.log(`
|
|
75
|
+
`),J.fail("Following files already exist in the directory."),H.forEach((u)=>{console.log(`- ${w.green(u.targetFile)}`)}),(await _0({type:"confirm",name:"overwrite",message:"Do you want to overwrite the existing files?",initial:!0})).overwrite){let u=W0("Overwriting files").start();H.forEach((E)=>{T.copyFileSync(E.sourceFile,E.targetFile)}),u.succeed("Files are overwritten")}}if(G?.tailwindFile)console.log(`
|
|
67
76
|
Tailwind config file exists in the project directory. You can add it to your globals.css as follows:`),console.log(`
|
|
68
|
-
${
|
|
69
|
-
`);if(
|
|
70
|
-
Tailwind CSS is not configured in your Vite project. Please refer to the documentation ${
|
|
71
|
-
`)}let
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`),process.exit(1)},L3=new p3().name("example").description("add an example to the project").argument("[example]","the example to add").option("-o, --overwrite","overwrite existing files.",!1).option("-p, --path <path>","the path to add the component to.").option("-e, --example-path <example-path>","the path to add the example file to.").action(async(z,Q)=>{if(z)U.example=z;if(Q)U.path=Q.path,U.overwrite=Q.overwrite,U.examplePath=Q.examplePath,U.license=Q.license||U.license;try{await g0(Q,d0),await z1()}catch(Y){console.error(v.red(Y))}});async function z1(){let z=K0().start(),Q=y.posix.join(process.cwd(),d0?.projectPath||"");if(!w.existsSync(y.posix.join(y.resolve(Q,"package.json"))))z.warn("This command should be run in a project directory."),process.exit(1);let Z=await s(Q);if(U.license){if(!await J0(U.license))z.fail("Invalid license key"),process.exit(1);if(!w.existsSync(e)){let L=y.dirname(e);w.mkdirSync(L,{recursive:!0}),w.writeFileSync(e,JSON.stringify({license:U.license},null,2))}if(JSON.parse(w.readFileSync(e,"utf-8")).license!==U.license)w.writeFileSync(e,JSON.stringify({license:U.license},null,2),"utf-8")}if(z.stop(),!U.example){let W=await o({type:"select",name:"example",onState:q0,message:"Select which type of example you want to add",choices:[{title:"Application",value:"application"},{title:"Marketing",value:"marketing"}]});U.example=W.example}let B=null;if(U.example){let W=await G0(U.example,U.license);if(W?.type==="error"&&(W.status===401||W.status===403))console.log(),console.log(v.yellow(`\uD83D\uDD12 The ${v.cyan(U.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${v.green("→")} If you've already purchased: ${v.cyan(`${Y0()} untitledui@latest login`)}`),console.log(` ${v.green("→")} To purchase PRO examples: ${v.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1);if(W?.type==="directory"){let $=await o({type:"select",name:"example",onState:q0,message:`Select a folder or file in "${U.example}"`,choices:W.results.map((L)=>({title:L,value:L}))});if(!$.example)return;if(U.example=$.example,W=await G0($.example,U.license),W?.type==="error"&&(W.status===401||W.status===403))console.log(),console.log(v.yellow(`\uD83D\uDD12 The ${v.cyan($.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${v.green("→")} If you've already purchased: ${v.cyan(`${Y0()} untitledui@latest login`)}`),console.log(` ${v.green("→")} To purchase PRO examples: ${v.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(W?.type==="json-files"){let $=await o({type:"select",name:"example",onState:q0,message:`Select which example you want to add from "${U.example}"`,choices:W.results.map((L)=>({title:L,value:`${U.example}/${L}`}))});if(!$.example)return;if(U.example=$.example,W=await G0($.example,U.license),W?.type==="error"&&(W.status===401||W.status===403))console.log(),console.log(v.yellow(`\uD83D\uDD12 The ${v.cyan($.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${v.green("→")} If you've already purchased: ${v.cyan(`${Y0()} untitledui@latest login`)}`),console.log(` ${v.green("→")} To purchase PRO examples: ${v.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(W?.type==="json-file")B=W.content}if(!B)z.fail("No example found"),process.exit(1);let q=Z?.examples||"";if(q){let W=await s(y.posix.join(Q,q));if(W)Z={...W,aliases:Z?.aliases||{}}}if(!U?.examplePath){let W=Z?.isAppDir?"app":"pages",$=Z?.isSrcDir?y.posix.join("src",W):W,L=await o({type:"text",name:"examplePath",onState:q0,message:`Where would you like to add the ${v.cyan(U?.example)} example?`,initial:$});U.examplePath=`${q}/${L.examplePath}`}else if(!w.existsSync(y.posix.join(Q,U.examplePath)))w.mkdirSync(y.posix.join(Q,U.examplePath),{recursive:!0}),console.log(v.green(`Created directory ${U.examplePath}`));if(!U?.path){let W=await o({type:"text",name:"path",onState:q0,message:`Where would you like to add the ${v.cyan("components")}?`,initial:"components"});U.path=W.path}let J=B.components.filter((W)=>!w.existsSync(y.posix.join(Q,`${Z?.isSrcDir?"src":""}`,W?.path?.replace(/components\//,U.path+"/"))));if(J?.length){let W=await o({type:"multiselect",name:"components",onState:q0,message:`Select which components you want to add from ${v.cyan(B.name)} example`,choices:J.map(($)=>({title:$?.name,value:$?.name,selected:!0})),instructions:!1,hint:"- Space to select. Return to submit"});if(U.components=W.components,!J.length&&!W.components?.length)z.warn("No components selected")}let G=Q0(Q),K=new Set,M=new o3({tsConfigFilePath:G?.tsConfig}),b=K0(`Adding ${U?.example}...`).start(),H="";try{if(B.files?.forEach(async({path:W,code:$})=>{let L=y.posix.join(Q,`${Z?.isSrcDir?"src":""}`,W.replace(/components\//,U.path+"/")),R=Z?.framework==="vite"?$.replace(`"use client";
|
|
77
|
+
${w.cyan(`@config "../${U?.isSrcDir?"../":""}${v.relative(Q,G.tailwindFile)}";`)}
|
|
78
|
+
`);if(U?.framework==="vite"){if(!X1(Q))console.log(`
|
|
79
|
+
Tailwind CSS is not configured in your Vite project. Please refer to the documentation ${w.cyan("https://www.untitled.com/react/integrations/vite")} for manual installation.
|
|
80
|
+
`)}let A=G?.layoutFile||G?.appFile||U?.framework==="vite"&&G?.mainFile||"";if(A){let u=new Z2({tsConfigFilePath:v.resolve(G?.tsConfig||"")}).addSourceFileAtPath(v.resolve(A)),E="styles/globals.css";if(!u.getImportDeclarations().some((O)=>{let s=O.getModuleSpecifierValue();return/(?:styles\/)?globals\.css$/.test(s)})){let O=U?.aliases?.styles||U?.aliases?.src||"",s=U?.aliases?.styles?`${O}globals.css`:`${O}styles/globals.css`;u.addImportDeclaration({moduleSpecifier:s})}u.saveSync()}let D=h0.sync(["**/theme.css"],{cwd:Q,absolute:!0,onlyFiles:!0,ignore:g});if(!D?.length)return J.fail(`Failed to copy ${w.cyan("theme.css")} file.
|
|
81
|
+
Ensure that the ${w.cyan("theme.css")} file exists in the project directory under your ${w.yellow("styles")} folder.`);if((N.color||!U?.tailwind.brandColor)&&d0("brand",N.color||"brand",D[0]??""),M.length||x.length){let R=W0().start("Installing dependencies");M.length&&await L0(()=>e(F(),[F()==="npm"?"install":"add",...M],{cwd:V}).catch(async(u)=>{if(u.message.includes("peer"))R.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),R.start("Installing dependencies with --legacy-peer-deps flag"),await e(F(),[F()==="npm"?"install":"add",...M,"--legacy-peer-deps"],{cwd:V})}),{retries:1}),x.length&&await L0(()=>e(F(),[F()==="npm"?"install":"add","-D",...x],{cwd:V}).catch(async(u)=>{if(u.message.includes("peer"))R.warn("DevDependency conflict detected. Retrying with --legacy-peer-deps..."),R.start("Installing dependencies with --legacy-peer-deps flag"),await e(F(),[F()==="npm"?"install":"add","-D",...x,"--legacy-peer-deps"],{cwd:V})}),{retries:1}),R.succeed("Dependencies are installed")}if(!B&&!U?.tailwind.brandColor)J.succeed(w.green("Project setup is completed!"));if(B&&$){b.stop(),J.stop();return}else console.log(`
|
|
82
|
+
Your project is ready, you can now start adding components.`)}}var K2=y.join(U2.homedir(),".untitledui"),Z0=y.join(K2,"config.json"),W={path:"",example:"",license:"",components:[]},l0={};if(S.existsSync(Z0)){let z=JSON.parse(S.readFileSync(Z0,"utf-8"));W.license=z.license}var Q0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
83
|
+
`),process.exit(1)},R1=new X2().name("example").description("add an example to the project").argument("[example]","the example to add").option("-o, --overwrite","overwrite existing files.",!1).option("-p, --path <path>","the path to add the component to.").option("-e, --example-path <example-path>","the path to add the example file to.").action(async(z,B)=>{if(z)W.example=z;if(B)W.path=B.path,W.overwrite=B.overwrite,W.examplePath=B.examplePath,W.license=B.license||W.license;try{await m0(B,l0),await L2()}catch(Q){console.error(j.red(Q))}});async function L2(){let z=V0().start(),B=y.posix.join(process.cwd(),l0?.projectPath||"");if(!S.existsSync(y.posix.join(y.resolve(B,"package.json"))))z.warn("This command should be run in a project directory."),process.exit(1);let $=await n(B);if(W.license){if(!await J0(W.license))z.fail("Invalid license key"),process.exit(1);if(!S.existsSync(Z0)){let M=y.dirname(Z0);S.mkdirSync(M,{recursive:!0}),S.writeFileSync(Z0,JSON.stringify({license:W.license},null,2))}if(JSON.parse(S.readFileSync(Z0,"utf-8")).license!==W.license)S.writeFileSync(Z0,JSON.stringify({license:W.license},null,2),"utf-8")}if(z.stop(),!W.example){let Z=await B0({type:"select",name:"example",onState:Q0,message:"Select which type of example you want to add",choices:[{title:"Application",value:"application"},{title:"Marketing",value:"marketing"}]});W.example=Z.example}let Y=null;if(W.example){let Z=await y0(W.example,W.license);if(Z?.type==="error"&&(Z.status===401||Z.status===403))console.log(),console.log(j.yellow(`\uD83D\uDD12 The ${j.cyan(W.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${j.green("→")} If you've already purchased: ${j.cyan(`${X0()} untitledui@latest login`)}`),console.log(` ${j.green("→")} To purchase PRO examples: ${j.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1);if(Z?.type==="directory"){let X=await B0({type:"select",name:"example",onState:Q0,message:`Select a folder or file in "${W.example}"`,choices:Z.results.map((M)=>({title:M,value:M}))});if(!X.example)return;if(W.example=X.example,Z=await y0(X.example,W.license),Z?.type==="error"&&(Z.status===401||Z.status===403))console.log(),console.log(j.yellow(`\uD83D\uDD12 The ${j.cyan(X.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${j.green("→")} If you've already purchased: ${j.cyan(`${X0()} untitledui@latest login`)}`),console.log(` ${j.green("→")} To purchase PRO examples: ${j.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(Z?.type==="json-files"){let X=await B0({type:"select",name:"example",onState:Q0,message:`Select which example you want to add from "${W.example}"`,choices:Z.results.map((M)=>({title:M,value:`${W.example}/${M}`}))});if(!X.example)return;if(W.example=X.example,Z=await y0(X.example,W.license),Z?.type==="error"&&(Z.status===401||Z.status===403))console.log(),console.log(j.yellow(`\uD83D\uDD12 The ${j.cyan(X.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${j.green("→")} If you've already purchased: ${j.cyan(`${X0()} untitledui@latest login`)}`),console.log(` ${j.green("→")} To purchase PRO examples: ${j.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(Z?.type==="json-file")Y=Z.content}if(!Y)z.fail("No example found"),process.exit(1);let q=$?.examples||"";if(q){let Z=await n(y.posix.join(B,q));if(Z)$={...Z,aliases:$?.aliases||{}};W.examplePath=q}if(!W?.examplePath){let Z=$?.isAppDir?"app":"pages",X=$?.isSrcDir?y.posix.join("src",Z):Z,M=await B0({type:"text",name:"examplePath",onState:Q0,message:`Where would you like to add the ${j.cyan(W?.example)} example?`,initial:X});W.examplePath=M.examplePath}else if(!S.existsSync(y.posix.join(B,W.examplePath)))S.mkdirSync(y.posix.join(B,W.examplePath),{recursive:!0}),console.log(j.green(`Created directory ${W.examplePath}`));if(!W?.path&&!$?.paths?.components){let Z=await B0({type:"text",name:"path",onState:Q0,message:`Where would you like to add the ${j.cyan("components")}?`,initial:"components"});W.path=Z.path}if(W?.path&&$?.paths&&!$.paths.components)$.paths.components=y.posix.join($?.isSrcDir?"src":"",W.path);if(!W?.path&&$?.paths?.components)W.path=$.paths.components.replace(/^src\//,"");let L=Y.components.filter((Z)=>!S.existsSync(y.posix.join(B,`${$?.isSrcDir?"src":""}`,Z?.path?.replace(/components\//,W.path+"/"))));if(L?.length){let Z=await B0({type:"multiselect",name:"components",onState:Q0,message:`Select which components you want to add from ${j.cyan(Y.name)} example`,choices:L.map((X)=>({title:X?.name,value:X?.name,selected:!0})),instructions:!1,hint:"- Space to select. Return to submit"});if(W.components=Z.components,!L.length&&!Z.components?.length)z.warn("No components selected")}let b=Y0(B),U=new Set,V=new W2({tsConfigFilePath:b?.tsConfig}),J=V0(`Adding ${W?.example}...`).start(),H="",I=new Set(Y.components.filter((Z)=>W.components?.includes(Z.name)).map((Z)=>y.dirname(Z.path)));try{for(let{path:Z,code:X}of Y.files||[]){let M=y.dirname(Z);if(Array.from(I).some((E)=>M===E||M.startsWith(E+"/")))continue;let A=y.posix.join(B,`${$?.isSrcDir?"src":""}`,Z.replace(/components\//,W.path+"/")),D=$?.framework==="vite"?X.replace(`"use client";
|
|
76
84
|
|
|
77
|
-
`,"")
|
|
78
|
-
Failed to add the component ${
|
|
79
|
-
Following files already exist in the directory.`),
|
|
80
|
-
|
|
81
|
-
\uD83C\uDF89 Example ${
|
|
85
|
+
`,""):X,R=G0(D);if(Z.includes("examples")){let E=y.basename(Z);A=y.posix.join(B,W?.examplePath??"",E),H=y.posix.join(W?.examplePath??"",E)}let u=y.dirname(A);if(S.existsSync(A)&&!W.overwrite){if(S.readFileSync(A,"utf-8")!==R)U.add({code:R,path:A})}else{S.mkdirSync(u,{recursive:!0}),S.writeFileSync(A,R);let E=V.addSourceFileAtPath(y.resolve(A));E.getImportDeclarations().forEach((P)=>{let O=P.getModuleSpecifierValue();P.setModuleSpecifier(q0(O,W.path,$?.aliases))}),await E.save()}}if(U.size)J.warn(`Some files of ${j.yellow(W?.example)} already exist`);else J.succeed(`${j.green(W?.example)} is added successfully`)}catch(Z){J.fail(`
|
|
86
|
+
Failed to add the component ${j.red(W?.example)}`),console.error(j.red(Z)),process.exit(1)}if(U.size&&!W?.overwrite){console.log(`
|
|
87
|
+
Following files already exist in the directory.`),U.forEach((X)=>{console.log(j.green(`- ${y.relative(B,X.path)}`))});let Z=await B0({type:"confirm",name:"overwrite",onState:Q0,message:"Do you want to overwrite the existing files?",initial:!0});if(Z.overwrite===void 0)console.log(`
|
|
88
|
+
Use ${j.cyan("--overwrite")} or ${j.cyan("-o")} flag to overwrite existing files, or run with ${j.cyan("node")} instead of ${j.cyan("bun")}.`),process.exit(1);if(Z.overwrite){let X=V0("Overwriting files").start();U.forEach((M)=>{let x=V.addSourceFileAtPath(y.resolve(M.path));x.replaceWithText(M.code),x.getImportDeclarations().forEach((A)=>{let D=A.getModuleSpecifierValue();A.setModuleSpecifier(q0(D,W.path,$?.aliases))}),x.saveSync()}),X.succeed("Files are overwritten")}}let G=F();if(Y?.dependencies?.length){let Z=V0("Installing example dependencies").start();await c0(()=>E0(G,[G==="npm"?"install":"add",...Y.dependencies],{cwd:B}).catch(async(X)=>{if(X.message.includes("peer"))Z.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),Z.start("Installing dependencies with --legacy-peer-deps flag"),await E0(G,[G==="npm"?"install":"add",...Y.dependencies,"--legacy-peer-deps"],{cwd:B})}),{retries:1}),Z.succeed("Example dependencies are installed")}if(Y?.devDependencies?.length){let Z=V0("Installing example devDependencies").start();await c0(()=>E0(G,[G==="npm"?"install":"add","-D",...Y.devDependencies],{cwd:B}).catch(async(X)=>{if(X.message.includes("peer"))Z.warn("DevDependency conflict detected. Retrying with --legacy-peer-deps..."),Z.start("Installing devDependencies with --legacy-peer-deps flag"),await E0(G,[G==="npm"?"install":"add","-D",...Y.devDependencies,"--legacy-peer-deps"],{cwd:B})}),{retries:1}),Z.succeed("Example devDependencies are installed")}if(W?.components?.length)await c0(()=>x0({components:W.components,dir:l0?.projectPath||"",path:W.path,message:""}),{retries:1});console.log(`
|
|
89
|
+
\uD83C\uDF89 Example ${j.green(W.example)} has been added to ${j.green(H)}`),process.exit(0)}var a0={name:"untitledui",version:"0.1.52",main:"dist/index.mjs",description:"The Untitled UI CLI tool helps you quickly scaffold projects with Untitled UI React and add components and page examples to your existing projects with an interactive interface in seconds.",type:"module",publishConfig:{access:"public"},scripts:{test:'echo "Error: no test specified" && exit 1',dev:"bun build --entrypoints ./index.ts --entry-naming=[name].mjs --outdir=dist --target=node --minify --packages=external --env=inline --define=process.env.API_URL=http://localhost:3000/react/api --watch",build:"bun build --entrypoints ./index.ts --entry-naming=[name].mjs --outdir=dist --target=node --minify --packages=external --env=inline --define=process.env.API_URL=https://www.untitledui.com/react/api","publish:npm":"bun run build && npm publish --access public",start:"node dist/index.mjs"},bugs:{url:"https://github.com/untitleduico/react/issues"},homepage:"https://github.com/untitleduico/react#readme",keywords:["untitledui","untitled-ui","untitledui","untitledui-cli","untitledui-react","untitledui-components","untitledui-examples","untitledui-vite","untitledui-nextjs","cli","tailwindcss","nextjs","react","components","examples","vite"],files:["dist","config","templates","README.md"],author:{name:"Untitled UI",url:"https://www.untitledui.com/react"},contributors:[{name:"Dilshod Turobov",url:"https://x.com/deebovv"},{name:"Jordan Hughes",url:"https://x.com/jordanphughes"}],license:"MIT",bin:{untitledui:"dist/index.mjs"},exports:"./dist/index.mjs",dependencies:{"async-retry":"^1.3.3",chalk:"^5.6.2",commander:"^13.1.0",execa:"^7.2.0","fast-glob":"^3.3.3","node-fetch":"^3.3.2",open:"^10.2.0",ora:"^8.2.0",prettier:"^3.7.4",prompts:"^2.4.2",tar:"^7.5.2","ts-morph":"^25.0.1","tsconfig-paths":"^4.2.0","update-check":"^1.5.4"},devDependencies:{"@types/async-retry":"^1.4.9","@types/prompts":"^2.4.9","@types/tar":"^6.1.13","type-fest":"^4.41.0",typescript:"^5.9.3"}};process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function b2(){let z=new J2().name(a0.name).version(a0.version);z.addCommand(I1).addCommand(K1).addCommand(R1).addCommand(J1),z.parse()}b2();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "untitledui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"main": "dist/index.mjs",
|
|
5
5
|
"description": "The Untitled UI CLI tool helps you quickly scaffold projects with Untitled UI React and add components and page examples to your existing projects with an interactive interface in seconds.",
|
|
6
6
|
"type": "module",
|
|
@@ -63,16 +63,16 @@
|
|
|
63
63
|
"exports": "./dist/index.mjs",
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"async-retry": "^1.3.3",
|
|
66
|
-
"chalk": "^5.
|
|
66
|
+
"chalk": "^5.6.2",
|
|
67
67
|
"commander": "^13.1.0",
|
|
68
|
-
"execa": "^7.
|
|
68
|
+
"execa": "^7.2.0",
|
|
69
69
|
"fast-glob": "^3.3.3",
|
|
70
70
|
"node-fetch": "^3.3.2",
|
|
71
|
-
"open": "^10.
|
|
71
|
+
"open": "^10.2.0",
|
|
72
72
|
"ora": "^8.2.0",
|
|
73
|
-
"prettier": "^3.
|
|
73
|
+
"prettier": "^3.7.4",
|
|
74
74
|
"prompts": "^2.4.2",
|
|
75
|
-
"tar": "^7.
|
|
75
|
+
"tar": "^7.5.2",
|
|
76
76
|
"ts-morph": "^25.0.1",
|
|
77
77
|
"tsconfig-paths": "^4.2.0",
|
|
78
78
|
"update-check": "^1.5.4"
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@types/async-retry": "^1.4.9",
|
|
82
82
|
"@types/prompts": "^2.4.9",
|
|
83
83
|
"@types/tar": "^6.1.13",
|
|
84
|
-
"type-fest": "^4.
|
|
85
|
-
"typescript": "^5.
|
|
84
|
+
"type-fest": "^4.41.0",
|
|
85
|
+
"typescript": "^5.9.3"
|
|
86
86
|
}
|
|
87
87
|
}
|