untitledui 0.1.23 → 0.1.25
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/README.md +173 -0
- package/dist/index.mjs +26 -26
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Untitled UI CLI
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
To always use the latest version of the CLI, we recommend using `npx`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx untitledui@latest <command>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The Untitled UI CLI provides the following commands:
|
|
14
|
+
|
|
15
|
+
If you run a command without providing further arguments, you'll be presented with an interactive interface to continue.
|
|
16
|
+
|
|
17
|
+
- `init`: Initialize a new project or adjust an existing one.
|
|
18
|
+
- `add`: Add a component to your project.
|
|
19
|
+
- `example`: Add an example page to the project.
|
|
20
|
+
- `login`: Authenticate with Untitled UI to access PRO components.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
### `init`
|
|
25
|
+
|
|
26
|
+
The `init` command is used to initialize a new project or adjust an existing one.
|
|
27
|
+
|
|
28
|
+
If you run the command without any arguments, you will be guided through an interactive setup process.
|
|
29
|
+
|
|
30
|
+
**Usage:**
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx untitledui@latest init [directory] [options]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Arguments:**
|
|
37
|
+
|
|
38
|
+
- `[directory]`: The directory to initialize the project in.
|
|
39
|
+
|
|
40
|
+
**Options:**
|
|
41
|
+
|
|
42
|
+
- `--vite`: Initialize a Vite project.
|
|
43
|
+
- `--next`: Initialize a Next.js project.
|
|
44
|
+
- `-o, --overwrite`: Overwrite existing files.
|
|
45
|
+
- `--colors-list`: Show the colors list.
|
|
46
|
+
- `-c, --color <color-name>`: Specify a color for the project.
|
|
47
|
+
- `-h, --help`: Display the help message.
|
|
48
|
+
|
|
49
|
+
**Examples:**
|
|
50
|
+
|
|
51
|
+
- Initialize a new Next.js project in a directory named `my-app`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx untitledui@latest init my-app --next
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Initialize a new Vite project with a specific color:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx untitledui@latest init my-vite-app --vite --color blue
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `add`
|
|
64
|
+
|
|
65
|
+
The `add` command is used to add a component to your project.
|
|
66
|
+
|
|
67
|
+
If you run the command without any arguments, you will be guided through an interactive process to select components.
|
|
68
|
+
|
|
69
|
+
**Usage:**
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx untitledui@latest add [components...] [options]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Arguments:**
|
|
76
|
+
|
|
77
|
+
- `[components...]`: The components to add.
|
|
78
|
+
|
|
79
|
+
**Options:**
|
|
80
|
+
|
|
81
|
+
- `-a, --all`: Add all available components.
|
|
82
|
+
- `-o, --overwrite`: Overwrite existing files.
|
|
83
|
+
- `-p, --path <path>`: The path to add the component to.
|
|
84
|
+
- `-d, --dir <directory>`: The directory where the project is located.
|
|
85
|
+
- `-t, --type <base|marketing|shared-assets|application|foundations>`: The type of the component to add.
|
|
86
|
+
|
|
87
|
+
**Examples:**
|
|
88
|
+
|
|
89
|
+
- Add a single component:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx untitledui@latest add button
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- Add multiple components:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx untitledui@latest add button toggle avatar
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- Add all marketing components:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx untitledui@latest add --all --type marketing
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `example`
|
|
108
|
+
|
|
109
|
+
The `example` command is used to add an example page to the project.
|
|
110
|
+
|
|
111
|
+
**Usage:**
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx untitledui@latest example [example] [options]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Arguments:**
|
|
118
|
+
|
|
119
|
+
- `[example]`: The example to add. This can be a specific example path copied from the [Untitled UI React website](https://www.untitledui.com/react/components) (e.g., `dashboards-01/05`).
|
|
120
|
+
|
|
121
|
+
**Options:**
|
|
122
|
+
|
|
123
|
+
- `-o, --overwrite`: Overwrite existing files.
|
|
124
|
+
- `-p, --path <path>`: The path to add the component to.
|
|
125
|
+
- `-e, --example-path <example-path>`: The path to add the example file to.
|
|
126
|
+
|
|
127
|
+
**Examples:**
|
|
128
|
+
|
|
129
|
+
- Add application UI examples:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npx untitledui@latest example application
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- Add a specific example by its path:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx untitledui@latest example dashboards-01/05
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `login`
|
|
142
|
+
|
|
143
|
+
The `login` command is used to authenticate with Untitled UI to access PRO components.
|
|
144
|
+
|
|
145
|
+
**Usage:**
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx untitledui@latest login
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This command will open a browser window for you to authenticate with your Untitled UI account.
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
The Untitled UI CLI is licensed under the [MIT License](LICENSE).
|
|
156
|
+
|
|
157
|
+
## Contributing
|
|
158
|
+
|
|
159
|
+
Contributions are welcome! Please open an issue or submit a pull request on our [GitHub repository](https://github.com/untitleduico/cli.git).
|
|
160
|
+
|
|
161
|
+
## Bug Reports
|
|
162
|
+
|
|
163
|
+
If you find a bug, please report it on our [issue tracker](https://github.com/untitleduico/cli/issues).
|
|
164
|
+
|
|
165
|
+
## Keywords
|
|
166
|
+
|
|
167
|
+
- untitledui-cli
|
|
168
|
+
- untitledui
|
|
169
|
+
- cli
|
|
170
|
+
- tailwindcss
|
|
171
|
+
- nextjs
|
|
172
|
+
- react
|
|
173
|
+
- components
|
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
3
|
-
`),process.exit(1)},
|
|
2
|
+
import{Command as l1}from"commander";import s0 from"async-retry";import E from"chalk";import{Command as H1}from"commander";import{execa as B0}from"execa";import*as F from"fs";import W0 from"ora";import R1 from"os";import*as D from"path";import Z0 from"prompts";import{Project as j1}from"ts-morph";import O0 from"node-fetch";import{Readable as $1,pipeline as u1}from"stream";import{x as b1}from"tar";import{promisify as q1}from"util";var X1=q1(u1);async function d0(z,Q){try{let Y=await U1(Q);await X1(Y,b1({cwd:z,strip:1}))}catch(Y){throw new Error(`Failed to download or extract repository from API: ${Y instanceof Error?Y.message:Y}`)}}async function U1(z){let Q=`https://www.untitledui.com/react/api/download-repo?template=${z.template}`;try{let Y=await O0(Q,{method:"GET",headers:{"Content-Type":"application/json",Accept:"application/octet-stream"}});if(Y.status===403||Y.status===404)throw new Error("Repository not found");if(!Y.ok)throw new Error(`Failed to download from API. Status: ${Y.status} ${Y.statusText}`);if(!Y.body)throw new Error("Response body is empty");return $1.from(Y.body)}catch(Y){throw new Error(`Error downloading tarball: ${Y instanceof Error?Y.message:Y}`)}}async function r(z){let Q=`https://www.untitledui.com/react/api/validate-key?key=${z}`;try{return(await O0(Q)).status===200}catch{return!1}}import B1 from"node-fetch";var h0={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function j0(z,Q,Y){try{let Z=await B1("https://www.untitledui.com/react/api/components",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:z,components:Q,key:Y})});if(!Z.ok)console.log(h0?.[Z.statusText]||h0.no_components_found),process.exit(1);return await Z.json()}catch(Z){return null}}import G0 from"node-fetch";var i={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function f0(z,Q=""){let Y=`https://www.untitledui.com/react/api/components/list?key=${Q}&type=${z}`;try{let b=await G0(Y),Z=await b.json();if(!b.ok)console.log(i?.[b.statusText]||i.no_components_found),process.exit(1);if(!Z?.components?.length)return null;return Z}catch(b){return console.error(b),null}}async function m0(z,Q="",Y){let b=`https://www.untitledui.com/react/api/components/list?key=${Q}&type=${z}&subfolders=${Y.join(",")}`;try{let Z=await G0(b);if(!Z.ok)console.log(i?.[Z.statusText]||i.no_components_found),process.exit(1);let U=await Z.json();if(!U?.components?.length)return null;return U}catch(Z){return console.error(Z),null}}async function c0(z=""){let Q=`https://www.untitledui.com/react/api/components/list?key=${z}`;try{let Y=await G0(Q);if(!Y.ok)console.log(i?.[Y.statusText]||i.no_components_found),process.exit(1);let b=await Y.json();if(!b?.types?.length)return null;return b}catch(Y){return console.error(Y),null}}import M1 from"fast-glob";import*as I0 from"path";import{Project as U3}from"ts-morph";import{loadConfig as v1}from"tsconfig-paths";import Q3 from"prettier";import X0 from"fast-glob";import*as b0 from"fs";import*as q0 from"path";import{loadConfig as J1}from"tsconfig-paths";var h=["**/node_modules/**",".next","public","dist","build"],l0={"next-app":"Next.js (App)","next-pages":"Next.js (Pages)",vite:"Vite",other:"Other"};async function t(z){let Q=b0.existsSync(q0.resolve(z,"src")),Y=b0.existsSync(q0.resolve(z,`${Q?"src/":""}app`)),[b,Z,U,L]=await Promise.all([X0.glob("**/{next,vite,astro}.config.*|gatsby-config.*",{cwd:z,deep:2,ignore:h}),K1(z),L1(z),V1(z)]),M={framework:"other",isTsx:Z,tailwindFile:U||null,aliasPrefix:L,isSrcDir:Q,isUsingAppDir:Y};if(b.find((K)=>K.startsWith("next.config."))?.length)return M.framework=Y?"next-app":"next-pages",M;else if(b.find((K)=>K.startsWith("vite.config."))?.length)return M.framework="vite",M;else if(b?.length||b0.existsSync(q0.resolve(z,"package.json")))return M.framework="other",M;return null}async function K1(z){return(await X0.glob("tsconfig.*",{cwd:z,deep:2,ignore:h})).length>0}async function L1(z){let Q=await X0.glob("tailwind.config.*",{cwd:z,deep:2,ignore:h});if(!Q.length)return null;return Q[0]}async function V1(z){let Q=await J1(z);if(Q?.resultType==="failed"||!Object.keys(Q.paths).length)return null;let Y={};for(let[b,Z]of Object.entries(Q.paths)){let U=b.replace(/\/\*$/,"/");if(Z.some((L)=>L.includes("/app/*")))Y.appPrefix=U;else if(Z.some((L)=>L.includes("/components/*")))Y.componentsPrefix=U;else if(Z.some((L)=>L.includes("/utils/*")))Y.utilsPrefix=U;else if(Z.some((L)=>L.includes("/styles/*")))Y.stylesPrefix=U;else if(Z.some((L)=>L.includes("./*")||L.includes("/src/*")))Y.srcPrefix=U}return Y||null}function p(z){let Q=v1(z),Y=M1.sync(["tailwind.config.*","**/globals.css","**/{layout,_app,main}.tsx","package.json"],{cwd:z,deep:4,absolute:!0,onlyFiles:!0,ignore:h}),b={tailwindFile:Y.find((Z)=>Z.includes("tailwind.config.")),cssFile:Y.find((Z)=>Z.includes("globals.css")),layoutFile:Y.find((Z)=>Z.includes("layout")),appFile:Y.find((Z)=>Z.includes("_app")),mainFile:Y.find((Z)=>Z.includes("main")),packageJson:Y.find((Z)=>Z.includes("package.json")),tsConfig:Q?.resultType==="success"?Q?.configFileAbsolutePath:void 0};if(Q.resultType==="failed")throw new Error(`Failed to load tsconfig.json. ${Q.message??""}`.trim());return b}function o(z,Q,Y={},b=""){if(z.includes("components")){if(Y?.componentsPrefix)return z.replace(/@\/components\//,I0.posix.join(Y?.componentsPrefix,Q?Q.replace(/components\//,""):"","/"));if(Q){let Z=Y?.srcPrefix?I0.posix.join(Y?.srcPrefix,Q,"/"):b;return z.replace(/@\/components\//,Z)}}if(z.includes("app")&&Y?.appPrefix)return z.replace(/^@\/app\//,Y?.appPrefix);if(z.includes("utils")&&Y?.utilsPrefix)return z.replace(/^@\/utils\//,Y?.utilsPrefix);if(z.includes("styles")&&Y?.stylesPrefix)return z.replace(/^@\/styles\//,Y?.stylesPrefix);if(Y?.srcPrefix)return z.replace(/^@\//,Y?.srcPrefix);return z}function C(){let z=process.env.npm_config_user_agent||"";if(z.startsWith("yarn"))return"yarn";if(z.startsWith("pnpm"))return"pnpm";if(z.startsWith("bun"))return"bun";return"npm"}function e(){switch(C()){case"yarn":return"yarn";case"pnpm":return"pnpx";case"bun":return"bunx";default:return"npx"}}function a0(){switch(C()){case"yarn":return"yarn dev";case"pnpm":return"pnpm dev";case"bun":return"bun dev";default:return"npm run dev"}}function U0(z){return z.replace(/^[ \t]*\/\/\s*(TODO:|collapse-(start|end)).*\r?\n?|[ \t]*{\s*\/\*\s*(TODO:|collapse-(start|end)).*?\*\/\s*}\r?\n?/gm,"")}var G1=D.join(R1.homedir(),".untitledui"),c=D.join(G1,"config.json"),X={components:[],path:"",type:void 0,license:""};if(F.existsSync(c)){let z=JSON.parse(F.readFileSync(c,"utf-8"));X.license=z.license}var J0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
3
|
+
`),process.exit(1)},n0=new H1().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,Q)=>{if(z)X.components=z;if(Q)X.all=Q.all,X.dir=Q.dir,X.path=Q.path,X.overwrite=Q.overwrite,X.license=Q.license||X.license;try{await E0(X)}catch(Y){console.error(E.red(Y))}});async function E0(z){if(z)X={...X,...z};let Q=W0().start(),Y=D.posix.join(process.cwd(),X.dir||"");if(!F.existsSync(D.resolve(Y,"package.json")))Q.warn("This command should be run in a project directory."),process.exit(1);let Z=await t(Y);if(X.license){if(!await r(X.license))Q.fail("Invalid license key"),process.exit(1);if(!F.existsSync(c)){let u=D.dirname(c);F.mkdirSync(u,{recursive:!0}),F.writeFileSync(c,JSON.stringify({license:X.license},null,2))}if(JSON.parse(F.readFileSync(c,"utf-8")).license!==X.license)F.writeFileSync(c,JSON.stringify({license:X.license},null,2),"utf-8")}Q.stop();let U=[];if(X.components.length){let $=await j0(X.type,X.components,X.license);if($&&$.pro&&$.pro.length>0){if(console.log(),$.pro.length===1){let W=$.pro[0]?.split("/")[1]||$.pro[0];console.log(E.yellow(`\uD83D\uDD12 The ${E.cyan(W)} component requires PRO access.`))}else console.log(E.yellow("\uD83D\uDD12 The following components require PRO access:")),$.pro.forEach((W)=>{let u=W?.split("/")[1]||W;console.log(` • ${E.cyan(u)}`)});console.log(),console.log("To access PRO components:"),console.log(` ${E.green("→")} If you've already purchased: ${E.cyan(`${e()} untitledui@latest login`)}`),console.log(` ${E.green("→")} To purchase PRO components: ${E.cyan("https://www.untitledui.com/buy/react")}`),console.log()}if(!$?.components.length)console.log("No components found"),process.exit(1);U.push(...$.components)}if(!X?.type&&!X?.components.length){let $=await c0(X.license);if(!$)console.log("No component types found"),process.exit(1);let W=await Z0({type:"select",name:"type",onState:J0,message:`What type of ${E.cyan("component")} are you adding?`,choices:$?.types.map((u)=>({title:u,value:u}))});X.type=W.type}if(!X?.path){let $=await Z0({type:"text",name:"path",onState:J0,message:`Where would you like to add the ${E.cyan("components")}?`,initial:"components"});X.path=$.path}if(!X?.components.length){let $=await f0(X?.type,X.license);if(!$)console.log("No components found"),process.exit(1);let W=await Z0({type:"multiselect",name:"components",onState:J0,message:`Which ${E.cyan("components")} would you like to add?`,choices:$?.components?.map((J)=>({title:J?.name+(J?.count?` (${J?.count} variants)`:"")||"example",value:J||"example",selected:X.components.includes(J.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!W.components||!W.components.length)console.log("No option selected. Exiting..."),process.exit(1);let u=W.components.filter((J)=>J?.type==="file").map((J)=>J.name),B=W.components.filter((J)=>J?.type==="dir").map((J)=>J.name),S=[];if(B.length){let J=await m0(X?.type,X.license,B);if(J&&J.components.length)for(let x of J.components){let[I,g]=Object.entries(x)[0]||[],G=await Z0({type:"select",name:"component",onState:J0,message:`Which ${E.cyan("variant")} from ${E.cyan(I)} would you like to add?`,choices:g?.map((_)=>({title:_?.name||"example",value:_?.name||"example",selected:X.components.includes(_.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!G.component)console.log("No variant selected for "+E.cyan(I));S.push(I+"/"+G.component)}else console.log("No variants found")}X.components=[...S,...u]}if(!X.components?.length)Q.warn("No components selected. Exiting."),process.exit(1);let L=p(Y),M=new Set,K=new Set,A=new Set,w=new j1({tsConfigFilePath:L?.tsConfig});if(X.type&&X.components.length){let $=await j0(X.type,X.components,X.license);if(!$?.components.length)console.log("No components found"),process.exit(1);U.push(...$.components)}if(U.forEach(($)=>{let W=W0(`Adding ${$.name}...`).start(),u=$.files;$.dependencies.forEach((B)=>K.add(B)),$.devDependencies.forEach((B)=>A.add(B));try{if(u?.forEach(async({path:B,code:S})=>{let J=D.posix.join(Y,`${Z?.isSrcDir&&"src"}`,B.replace(/components\//,X.path+"/")),x=Z?.framework==="vite"?S.replace(`"use client";
|
|
4
4
|
|
|
5
|
-
`,""):S,
|
|
6
|
-
Failed to add the component ${
|
|
7
|
-
Following files already exist in the directory.`),
|
|
8
|
-
✨ You can now access PRO components with the CLI!`)),process.exit(0)}catch(
|
|
9
|
-
Failed to open browser automatically: ${
|
|
10
|
-
`))}),
|
|
11
|
-
`),process.exit(1)},
|
|
12
|
-
Creating a new project in ${
|
|
5
|
+
`,""):S,I=U0(x),g=D.dirname(J);if(F.existsSync(J)&&!X.overwrite){if(F.readFileSync(J,"utf-8")!==I)M.add({code:I,path:J})}else{F.mkdirSync(g,{recursive:!0}),F.writeFileSync(J,I);let G=D.relative(D.resolve(Y,`${Z?.isSrcDir&&"src"}`,X.path),J).split("/").length,_=G===1?"./":"../".repeat(G-1),k=w.addSourceFileAtPath(D.resolve(J));k.getImportDeclarations().forEach((P)=>{let Q0=P.getModuleSpecifierValue();P.setModuleSpecifier(o(Q0,X.path,Z?.aliasPrefix,_))}),await k.save()}}),M.size)W.warn(`Some files of ${E.yellow($.name)} already exist`);else W.succeed(`${E.green($.name)} is added successfully`)}catch(B){W.fail(`
|
|
6
|
+
Failed to add the component ${E.red($.name)}`),console.error(E.red(B)),process.exit(1)}}),M.size&&!X?.overwrite)if(console.log(`
|
|
7
|
+
Following files already exist in the directory.`),M.forEach((W)=>{console.log(E.green(`- ${D.relative(Y,W.path)}`))}),(await Z0({type:"confirm",name:"overwrite",message:"Do you want to overwrite the existing files?",initial:!0})).overwrite){let W=W0("Overwriting files").start();M.forEach((u)=>{let B=D.relative(D.resolve(Y,`${Z?.isSrcDir&&"src"}`,X.path),u.path).split("/").length,S=B===1?"./":"../".repeat(B-1),J=w.addSourceFileAtPath(D.resolve(u.path));J.replaceWithText(u.code),J.getImportDeclarations().forEach((x)=>{let I=x.getModuleSpecifierValue();x.setModuleSpecifier(o(I,X.path,Z?.aliasPrefix,S))}),J.saveSync()}),W.succeed("Files are overwritten")}else console.log(`Use ${E.cyan("--overwrite")} or ${E.cyan("-o")} to overwrite existing files, or refer to the documentation ${E.cyan("https://www.untitled.com/docs")} for manual installation. The rest of the files are added.`),process.exit(1);let j=C();if(K?.size){let $=W0("Installing component dependencies").start();await s0(()=>B0(j,[j==="npm"?"install":"add",...K],{cwd:Y}).catch(async(W)=>{if(W.message.includes("peer"))$.warn("Component dependencies conflict detected. Retrying with --legacy-peer-deps..."),$.start("Installing component dependencies with --legacy-peer-deps flag"),await B0(j,[j==="npm"?"install":"add",...K,"--legacy-peer-deps"],{cwd:Y})}),{retries:1}),$.succeed("Component dependencies are installed")}if(A?.size){let $=W0("Installing component devDependencies").start();await s0(()=>B0(j,[j==="npm"?"install":"add","-D",...A],{cwd:Y}).catch(async(W)=>{if(W.message.includes("peer"))$.warn("Component devDependencies conflict detected. Retrying with --legacy-peer-deps..."),$.start("Installing component devDependencies with --legacy-peer-deps flag"),await B0(j,[j==="npm"?"install":"add","-D",...A,"--legacy-peer-deps"],{cwd:Y})}),{retries:1}),$.succeed("Component devDependencies are installed")}if(X.message)console.log(X.message);process.exit(0)}import N0 from"chalk";import{Command as E1}from"commander";import*as f from"fs";import A1 from"http";import _1 from"open";import N1 from"ora";import T1 from"os";import*as D0 from"path";import{URL as D1}from"url";import*as r0 from"fs";import*as A0 from"path";var __dirname="/Users/xelopsys/Desktop/Projects/untitled-ui/untitledui-tailwind/cli/utils",I1=A0.join(__dirname,"..","templates");function i0(){let z=A0.join(I1,"auth-template.html");return r0.readFileSync(z,"utf-8")}function t0(){return i0().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 K0(z){return i0().replace("{{TITLE}}","Authentication failed").replace("{{HEADING}}","Authentication failed").replace("{{DESCRIPTION}}",z).replace("{{AUTO_CLOSE_SCRIPT}}","")}var T0=D0.join(T1.homedir(),".untitledui"),_0=D0.join(T0,"config.json"),p0=new E1().name("login").description("authenticate with Untitled UI to access PRO components").action(async()=>{let z=N1("Starting authentication...").start();try{await y1(z),z.succeed("Authentication completed successfully!"),console.log(N0.green(`
|
|
8
|
+
✨ You can now access PRO components with the CLI!`)),process.exit(0)}catch(Q){z.fail(`Authentication failed: ${Q instanceof Error?Q.message:Q}`),process.exit(1)}});async function y1(z){return new Promise((Q,Y)=>{let b=A1.createServer((Z,U)=>{let L=new D1(Z.url,"http://localhost");if(L.pathname==="/callback"){let M=L.searchParams.get("apiKey"),K=L.searchParams.get("error");if(K){U.writeHead(400,{"Content-Type":"text/html"}),U.end(K0(decodeURIComponent(K))),b.close(),Y(new Error(decodeURIComponent(K)));return}if(!M){U.writeHead(400,{"Content-Type":"text/html"}),U.end(K0("No Access Token received")),b.close(),Y(new Error("No Access Token received"));return}try{w1(M),U.writeHead(200,{"Content-Type":"text/html"}),U.end(t0()),b.close(),Q()}catch(A){U.writeHead(500,{"Content-Type":"text/html"}),U.end(K0("Failed to save authentication data")),b.close(),Y(A)}}else U.writeHead(404),U.end("Not found")});b.listen(0,"localhost",()=>{let L=`https://www.untitledui.com/react/api/cli-auth?port=${b.address().port}`;z.text="Opening browser for authentication...",_1(L).catch((M)=>{console.log(N0.yellow(`
|
|
9
|
+
Failed to open browser automatically: ${M.message}`)),console.log(N0.cyan(`Please manually open: ${L}
|
|
10
|
+
`))}),z.text="Waiting for authentication in browser..."}),setTimeout(()=>{b.close(),Y(new Error("Authentication timeout. Please try again."))},300000)})}function w1(z){if(!f.existsSync(T0))f.mkdirSync(T0,{recursive:!0});let Q={};if(f.existsSync(_0))try{Q=JSON.parse(f.readFileSync(_0,"utf-8"))}catch{Q={}}Q.license=z,f.writeFileSync(_0,JSON.stringify(Q,null,2),"utf-8")}import k0 from"async-retry";import V from"chalk";import{Command as O1}from"commander";import{execa as R0}from"execa";import*as y from"fs";import u0 from"ora";import d1 from"os";import*as H from"path";import s from"prompts";import{Project as h1}from"ts-morph";import S1 from"node-fetch";async function L0(z,Q){try{let b=await S1("https://www.untitledui.com/react/api/components/example",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({example:z,key:Q})});if(!b.ok){if(b.status===401||b.status===403)return{type:"error",status:b.status,message:"PRO access required"};return console.error(`API error: ${b.status} - ${b.statusText}`),null}return await b.json()}catch(b){return console.error(b?.message||"Error fetching example data."),null}}import $0 from"async-retry";import N from"chalk";import{Command as x1}from"commander";import{execa as l}from"execa";import v0 from"fast-glob";import T from"fs";import Y0 from"ora";import C1 from"os";import*as R from"path";import H0 from"prompts";import{Project as F1}from"ts-morph";import{fileURLToPath as k1}from"url";import*as V0 from"fs";import*as o0 from"path";function y0(z,Q){let Y=o0.join(z,"package.json");if(!V0.existsSync(Y))return Q;let b=JSON.parse(V0.readFileSync(Y,"utf-8")),Z={...b.dependencies,...b.devDependencies},U=[];for(let L of Q){let M=Z[L];if(!M){U.push(L);continue}if(L==="tailwindcss"){let K=M.match(/\d+/);if((K?parseInt(K[0],10):0)<4)U.push(L)}}return U}import w0 from"chalk";import*as m from"fs";import*as M0 from"path";function S0(z){if(!m.existsSync(M0.resolve(z)))console.log(w0.red(`Error: CSS file not found at ${z}`)),process.exit(1);let Q=m.readFileSync(M0.resolve(z),"utf-8"),Y=/(--color-[a-zA-Z-]+-\d{1,3}):\s*(rgb\([^)]+\))/g,b={},Z;while((Z=Y.exec(Q))!==null)if(Z[1]&&Z[2])b[Z[1]]=Z[2];return b}function x0(z,Q,Y){let b=M0.resolve(Y);if(!m.existsSync(b)){console.log(w0.red(`Error: CSS file not found at ${b}`));return}let Z=m.readFileSync(b,"utf-8"),U=S0(Y),L={},M={};for(let[A,w]of Object.entries(U))if(A.startsWith(`--color-${z}-`)){let j=A.replace(`--color-${z}-`,"");L[j]=A}else if(A.startsWith(`--color-${Q}-`)){let j=A.replace(`--color-${Q}-`,"");M[j]=w}let K=!1;for(let[A,w]of Object.entries(L))if(M[A]){let j=M[A],$=new RegExp(`(${w}):\\s*rgb\\([^)]*\\);?`,"g");if($.test(Z))Z=Z.replace($,`$1: ${j};`),K=!0;else console.log(w0.yellow(`No match found for ${w}`))}if(K)m.writeFileSync(b,Z,"utf-8")}var P1=k1(import.meta.url),e0=R.dirname(P1),g1=R.join(C1.homedir(),".untitledui"),a=R.join(g1,"config.json"),z1="vite",Q1="nextjs",Y1={[Q1]:"Next.js",[z1]:"Vite"},d="",v={color:"",template:"",framework:void 0};if(T.existsSync(a)){let z=JSON.parse(T.readFileSync(a,"utf-8"));v.license=z.license}var C0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
11
|
+
`),process.exit(1)},W1=new x1().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("--next","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,Q)=>{if(z)d=z;if(Q){if(v.color=Q.color,v.template=Q.template,v.overwrite=Q.overwrite,v.colorsList=Q.colorsList,v.license=Q.license||v.license,v.vite=Q.vite,v.next=Q.next,Q.vite)v.framework=z1;if(Q.next)v.framework=Q1}try{await F0(Q),process.exit(0)}catch(Y){console.error(N.red(Y)),process.exit(1)}});async function F0(z,Q=null){let Y=process.cwd(),b=T.existsSync(R.resolve(Y,"package.json")),Z=R.resolve(R.join(e0,"../config/styles","theme.css")),U=S0(Z??""),L=Array.from(new Set(Object.keys(U).map(($)=>$?.split("--color-")?.[1]?.replace(/-\d{1,3}/,"")))),M=Y0().start(),K=await t(Y),A=b?v0.sync(["**/**/theme.css"],{cwd:Y,absolute:!0,onlyFiles:!0,ignore:h}):[],w=A?.[0]&&T.readFileSync(A[0],"utf-8").match(/(--color-brand+-\d{1,3}):\s*(rgb\([^)]+\))/g)?.[1]||void 0;if(v.license){if(!await r(v.license))M.fail("Invalid license key"),process.exit(1);if(!T.existsSync(a)){let u=R.dirname(a);T.mkdirSync(u,{recursive:!0}),T.writeFileSync(a,JSON.stringify({license:v.license},null,2))}if(JSON.parse(T.readFileSync(a,"utf-8")).license!==v.license)T.writeFileSync(a,JSON.stringify({license:v.license},null,2))}if(!b){if(M.stop(),!d){let $=await H0({onState:C0,type:"text",name:"path",message:"What is your project named?",initial:"untitled-ui"});if(typeof $.path==="string")d=$.path.trim()}if(Q)Q.projectPath=d;if(T.existsSync(R.resolve(R.posix.join(Y,d))))M.fail(N.red("Directory already exists!")),process.exit(1);if(v.vite&&v.next||!v.framework){let $=await H0({type:"select",name:"framework",onState:C0,message:`Which ${N.cyan("framework")} would you like to use?`,choices:Object.entries(Y1).map(([W,u])=>({title:u,value:W}))});v.framework=$.framework}M.succeed("Framework is selected: "+N.green(Y1[v.framework]))}else if(K?.framework==="other")M.fail("Unsupported project framework"),console.log(`Please refer to the documentation ${N.cyan("https://www.untitled.com/docs")} for supported frameworks or proceed with manual installation.`),process.exit(1);else if(K?.framework.startsWith("next")||K?.framework.startsWith("vite"))if(!Q&&!w)M.succeed(N.yellow(`Detected ${l0[K.framework]} project, proceeding with the setup...`));else M.stop();if(v.colorsList||!v.color&&!w){let $=await H0({type:"select",name:"color",onState:C0,initial:z.color??"",message:`Which ${N.cyan("color")} would you like to use as the ${N.cyanBright("brand")} color?`,choices:L.map((W)=>({title:W,value:W}))});v.color=$.color}let j=R.posix.join(Y,d||"");if(d&&!b){let $=R.resolve(d);console.log(`
|
|
12
|
+
Creating a new project in ${N.blue(d)}`);let W=Y0("Downloading and extracting the repository...").start();try{T.mkdirSync($,{recursive:!0}),await $0(()=>d0($,{template:v.framework}),{retries:2}),W.succeed("Files are downloaded and extracted successfully!");let u=Y0({text:"Installing dependencies..."}).start(),B=v0.sync(["**/styles/theme.css"],{cwd:$,absolute:!0,onlyFiles:!0})[0];if(x0("brand",v.color||"",B??""),await $0(()=>l(C(),["install"],{cwd:j}).catch(async(S)=>{if(S.message.includes("peer"))u.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),u.start("Installing dependencies with --legacy-peer-deps flag"),await l(C(),["install","--legacy-peer-deps"],{cwd:j})}),{retries:1}),await $0(()=>l("git",["init"],{cwd:j}),{retries:1}),u.succeed("Dependencies are installed"),!Q)console.log(`
|
|
13
13
|
Your project is ready, to get started run the following commands:
|
|
14
14
|
|
|
15
|
-
cd ${
|
|
16
|
-
${
|
|
17
|
-
Failed to download and extract the repository`)),
|
|
18
|
-
`);
|
|
19
|
-
`),$.fail("Following files already exist in the directory."),W.forEach((
|
|
15
|
+
cd ${N.cyan(d)}
|
|
16
|
+
${N.cyan(a0())}`)}catch(u){if(W.fail(N.red(`
|
|
17
|
+
Failed to download and extract the repository`)),u instanceof Error)console.error(u.message);else console.error(`
|
|
18
|
+
`);T.rmdirSync($,{recursive:!0}),process.exit(1)}}else{let $=Y0(),W=new Set,u=p(Y),B=R.resolve(R.join(e0,"../config")),S=v0.sync(["**"],{cwd:B,onlyFiles:!0,ignore:h}),J=y0(Y,["tailwindcss","tailwindcss-animate","@tailwindcss/typography","tailwindcss-react-aria-components"]),x=y0(Y,["@tailwindcss/postcss","postcss"]);if(!Q&&!w)$.start("Copying files to the project directory");if(S.forEach((G)=>{let _=G.includes("postcss.config"),k=R.resolve(R.posix.join(B),G),P=R.resolve(Y,_?G:`${K?.isSrcDir?"src":""}/${G}`);if(T.existsSync(P)){if(v?.overwrite)T.copyFileSync(k,P);else{let Q0=T.readFileSync(P,"utf-8"),O=T.readFileSync(k,"utf-8");if(Q0!==O){if(G.endsWith("theme.css")&&w)return;W.add({targetFile:P,sourceFile:k})}}return}T.mkdirSync(R.dirname(P),{recursive:!0}),T.writeFileSync(P,""),T.copyFileSync(k,P)}),$.stop(),W.size&&!v?.overwrite)if(console.log(`
|
|
19
|
+
`),$.fail("Following files already exist in the directory."),W.forEach((_)=>{console.log(`- ${N.green(_.targetFile)}`)}),(await H0({type:"confirm",name:"overwrite",message:"Do you want to overwrite the existing files?",initial:!0})).overwrite){let _=Y0("Overwriting files").start();W.forEach((k)=>{T.copyFileSync(k.sourceFile,k.targetFile)}),_.succeed("Files are overwritten")}else console.log(`Use ${N.cyan("--overwrite")} or ${N.cyan("-o")} to overwrite existing files, or refer to the documentation ${N.cyan("https://www.untitled.com/docs")} for manual installation. The rest of the files are added.`);if(u?.tailwindFile)console.log(`
|
|
20
20
|
Tailwind config file exists in the project directory. You can add it to your globals.css as follows:`),console.log(`
|
|
21
|
-
${
|
|
22
|
-
`);let
|
|
23
|
-
`),S.forEach((G)=>{console.log(
|
|
24
|
-
Ensure that the ${
|
|
25
|
-
Your project is ready, you can now start adding components.`)}}var
|
|
26
|
-
`),process.exit(1)},
|
|
21
|
+
${N.cyan(`@config "../${K?.isSrcDir&&"../"}${R.relative(Y,u.tailwindFile)}";`)}
|
|
22
|
+
`);let I=u?.layoutFile||u?.appFile||K?.framework==="vite"&&u?.mainFile||"";if(!I)console.log(`Import following files to your main file:
|
|
23
|
+
`),S.forEach((G)=>{console.log(N.cyan(G))});else{let _=new F1({tsConfigFilePath:R.resolve(u?.tsConfig||"")}).addSourceFileAtPath(R.resolve(I)),k="globals.css";_.getImportDeclarations().filter((O)=>O.getModuleSpecifierValue().includes("globals.css")).forEach((O)=>O.remove());let P=R.relative(R.resolve(Y,`${K?.isSrcDir&&"src"}`),I).split("/").length,Q0=K?.aliasPrefix?.stylesPrefix||K?.aliasPrefix?.srcPrefix||(P===1?"./":"../".repeat(P-1));_.addImportDeclarations(S.filter((O)=>O.includes("globals.css")).map((O)=>({moduleSpecifier:`${Q0}${K?.aliasPrefix?.stylesPrefix?O?.split("styles/")[1]:O}`}))),_.saveSync()}let g=v0.sync(["**/styles/theme.css"],{cwd:Y,absolute:!0,onlyFiles:!0,ignore:h});if(!g?.length)return $.fail(`Failed to copy ${N.cyan("theme.css")} file.
|
|
24
|
+
Ensure that the ${N.cyan("theme.css")} file exists in the project directory under ${N.yellow("styles/")} folder.`);if((v.color||!w)&&x0("brand",v.color||"brand",g[0]??""),J.length||x.length){let G=Y0().start("Installing dependencies");J.length&&await $0(()=>l(C(),[C()==="npm"?"install":"add",...J],{cwd:j}).catch(async(_)=>{if(_.message.includes("peer"))G.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),G.start("Installing dependencies with --legacy-peer-deps flag"),await l(C(),[C()==="npm"?"install":"add",...J,"--legacy-peer-deps"],{cwd:j})}),{retries:1}),x.length&&await $0(()=>l(C(),[C()==="npm"?"install":"add","-D",...x],{cwd:j}).catch(async(_)=>{if(_.message.includes("peer"))G.warn("DevDependency conflict detected. Retrying with --legacy-peer-deps..."),G.start("Installing dependencies with --legacy-peer-deps flag"),await l(C(),[C()==="npm"?"install":"add","-D",...x,"--legacy-peer-deps"],{cwd:j})}),{retries:1}),G.succeed("Dependencies are installed")}if(!Q&&!w)$.succeed(N.green("Project setup is completed!"));if(Q&&b)return;else console.log(`
|
|
25
|
+
Your project is ready, you can now start adding components.`)}}var f1=H.join(d1.homedir(),".untitledui"),n=H.join(f1,"config.json"),q={path:"",example:"",license:"",components:[]},P0={};if(y.existsSync(n)){let z=JSON.parse(y.readFileSync(n,"utf-8"));q.license=z.license}var z0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
|
|
26
|
+
`),process.exit(1)},Z1=new O1().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)q.example=z;if(Q)q.path=Q.path,q.overwrite=Q.overwrite,q.examplePath=Q.examplePath,q.license=Q.license||q.license;try{await F0(Q,P0),await m1(q)}catch(Y){console.error(V.red(Y))}});async function m1(z){let Q=u0().start(),Y=H.posix.join(process.cwd(),P0?.projectPath||"");if(!y.existsSync(H.posix.join(H.resolve(Y,"package.json"))))Q.warn("This command should be run in a project directory."),process.exit(1);let Z=await t(Y);if(q.license){if(!await r(q.license))Q.fail("Invalid license key"),process.exit(1);if(!y.existsSync(n)){let B=H.dirname(n);y.mkdirSync(B,{recursive:!0}),y.writeFileSync(n,JSON.stringify({license:q.license},null,2))}if(JSON.parse(y.readFileSync(n,"utf-8")).license!==q.license)y.writeFileSync(n,JSON.stringify({license:q.license},null,2),"utf-8")}if(Q.stop(),!q.example){let W=await s({type:"select",name:"example",onState:z0,message:"Select which type of example you want to add",choices:[{title:"Application",value:"application"},{title:"Marketing",value:"marketing"}]});q.example=W.example}let U=null;if(q.example){let W=await L0(q.example,q.license);if(W?.type==="error"&&(W.status===401||W.status===403))console.log(),console.log(V.yellow(`\uD83D\uDD12 The ${V.cyan(q.example)} example requires PRO access.`)),console.log(),console.log("To access PRO examples:"),console.log(` ${V.green("→")} If you've already purchased: ${V.cyan(`${e()} 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 u=await s({type:"select",name:"example",onState:z0,message:`Select a folder or file in "${q.example}"`,choices:W.results.map((B)=>({title:B,value:B}))});if(!u.example)return;if(q.example=u.example,W=await L0(u.example,q.license),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(`${e()} 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 u=await s({type:"select",name:"example",onState:z0,message:`Select which example you want to add from "${q.example}"`,choices:W.results.map((B)=>({title:B,value:`${q.example}/${B}`}))});if(!u.example)return;if(q.example=u.example,W=await L0(u.example,q.license),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(`${e()} 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")U=W.content}if(!U)Q.fail("No example found"),process.exit(1);if(!q?.examplePath){let W=Z?.isUsingAppDir?"app":"pages",u=Z?.isSrcDir?H.posix.join("src",W):W,B=await s({type:"text",name:"examplePath",onState:z0,message:`Where would you like to add the ${V.cyan(q?.example)} example?`,initial:u});q.examplePath=B.examplePath}else if(!y.existsSync(H.posix.join(Y,q.examplePath)))y.mkdirSync(H.posix.join(Y,q.examplePath),{recursive:!0}),console.log(V.green(`Created directory ${q.examplePath}`));if(!q?.path){let W=await s({type:"text",name:"path",onState:z0,message:`Where would you like to add the ${V.cyan("components")}?`,initial:"components"});q.path=W.path}let L=U.components.filter((W)=>!y.existsSync(H.posix.join(Y,`${Z?.isSrcDir&&"src"}`,W?.path?.replace(/components\//,q.path+"/"))));if(L?.length){let W=await s({type:"multiselect",name:"components",onState:z0,message:`Select which components you want to add from ${V.cyan(U.name)} example`,choices:L.map((u)=>({title:u?.name,value:u?.name,selected:!0})),instructions:!1,hint:"- Space to select. Return to submit"});if(q.components=W.components,!L.length&&!W.components?.length)Q.warn("No components selected")}let M=p(Y),K=new Set,A=new h1({tsConfigFilePath:M?.tsConfig}),w=u0(`Adding ${q?.example}...`).start(),j="";try{if(U.files?.forEach(async({path:W,code:u})=>{let B=H.posix.join(Y,`${Z?.isSrcDir&&"src"}`,W.replace(/components\//,q.path+"/")),S=Z?.framework==="vite"?u.replace(`"use client";
|
|
27
27
|
|
|
28
|
-
`,""):
|
|
29
|
-
Failed to add the component ${
|
|
30
|
-
Following files already exist in the directory.`),
|
|
31
|
-
\uD83C\uDF89 Example ${
|
|
32
|
-
\uD83C\uDF89 Example ${
|
|
28
|
+
`,""):u,J=U0(S);if(W.includes("examples")){let I=H.basename(W);B=H.posix.join(Y,q?.examplePath??"",I),j=H.posix.join(q?.examplePath??"",I)}let x=H.dirname(B);if(y.existsSync(B)&&!q.overwrite){if(y.readFileSync(B,"utf-8")!==J)K.add({code:J,path:B})}else{y.mkdirSync(x,{recursive:!0}),y.writeFileSync(B,J);let I=H.relative(H.resolve(Y,`${Z?.isSrcDir&&"src"}`,q.path),B).split("/").length,g=I===1?"./":"../".repeat(I-1),G=A.addSourceFileAtPath(H.resolve(B));G.getImportDeclarations().forEach((_)=>{let k=_.getModuleSpecifierValue();_.setModuleSpecifier(o(k,q.path,Z?.aliasPrefix,g))}),await G.save()}}),K.size)w.warn(`Some files of ${V.yellow(q?.example)} already exist`);else w.succeed(`${V.green(q?.example)} is added successfully`)}catch(W){w.fail(`
|
|
29
|
+
Failed to add the component ${V.red(q?.example)}`),console.error(V.red(W)),process.exit(1)}if(K.size&&!q?.overwrite)if(console.log(`
|
|
30
|
+
Following files already exist in the directory.`),K.forEach((u)=>{console.log(V.green(`- ${H.relative(Y,u.path)}`))}),(await s({type:"confirm",name:"overwrite",message:"Do you want to overwrite the existing files?",initial:!0})).overwrite){let u=u0("Overwriting files").start();K.forEach((B)=>{let S=H.relative(H.resolve(Y,`${Z?.isSrcDir&&"src"}`,q.path),B.path).split("/").length,J=S===1?"./":"../".repeat(S-1),x=A.addSourceFileAtPath(H.resolve(B.path));x.replaceWithText(B.code),x.getImportDeclarations().forEach((I)=>{let g=I.getModuleSpecifierValue();I.setModuleSpecifier(o(g,q.path,Z?.aliasPrefix,J))}),x.saveSync()}),u.succeed("Files are overwritten")}else console.log(`Use ${V.cyan("--overwrite")} or ${V.cyan("-o")} to overwrite existing files, or refer to the documentation ${V.cyan("https://www.untitled.com/docs")} for manual installation. The rest of the files are added.`),process.exit(1);let $=C();if(U?.dependencies?.length){let W=u0("Installing example dependencies").start();await k0(()=>R0($,[$==="npm"?"install":"add",...U.dependencies],{cwd:Y}).catch(async(u)=>{if(u.message.includes("peer"))W.warn("Dependency conflict detected. Retrying with --legacy-peer-deps..."),W.start("Installing dependencies with --legacy-peer-deps flag"),await R0($,[$==="npm"?"install":"add",...U.dependencies,"--legacy-peer-deps"],{cwd:Y})}),{retries:1}),W.succeed("Example dependencies are installed")}if(U?.devDependencies?.length){let W=u0("Installing example devDependencies").start();await k0(()=>R0($,[$==="npm"?"install":"add","-D",...U.devDependencies],{cwd:Y}).catch(async(u)=>{if(u.message.includes("peer"))W.warn("DevDependency conflict detected. Retrying with --legacy-peer-deps..."),W.start("Installing devDependencies with --legacy-peer-deps flag"),await R0($,[$==="npm"?"install":"add","-D",...U.devDependencies,"--legacy-peer-deps"],{cwd:Y})}),{retries:1}),W.succeed("Example devDependencies are installed")}if(q?.components?.length)await k0(()=>E0({components:q.components,dir:P0?.projectPath||"",path:q.path,message:`
|
|
31
|
+
\uD83C\uDF89 Example ${V.green(q.example)} has been added to ${V.green(j)}`}),{retries:1});console.log(`
|
|
32
|
+
\uD83C\uDF89 Example ${V.green(q.example)} has been added to ${V.green(j)}`),process.exit(0)}var g0={name:"untitledui",version:"0.1.25",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"},repository:{type:"git",url:"https://github.com/untitledui/cli.git"},bugs:{url:"https://github.com/untitledui/cli/issues"},homepage:"https://github.com/untitledui/cli#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","README.md"],author:{name:"Untitled UI",url:"https://www.untitledui.com/react"},contributors:[{name:"Dilshod Turobov",email:"dilshod@untitledui.com",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.4.1",commander:"^13.1.0",execa:"^7.0.0","fast-glob":"^3.3.3","node-fetch":"^3.3.2",open:"^10.1.0",ora:"^8.2.0",prettier:"^3.5.3",prompts:"^2.4.2",tar:"^7.4.3","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.37.0",typescript:"^5.8.2"}};process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function a1(){let z=new l1().name(g0.name).version(g0.version);z.addCommand(W1).addCommand(n0).addCommand(Z1).addCommand(p0),z.parse()}a1();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "untitledui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
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",
|