react-apps-ui 1.0.10 → 1.0.12

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 CHANGED
@@ -44,7 +44,7 @@ Get up and running in a fresh project in seconds.
44
44
 
45
45
  Run the `init` command at the root of your project. This interactive command lets you select your target platform (Web or Mobile) and styling engine, creates your base theme, and sets up your utility files.
46
46
 
47
- ```bash
47
+ ```sh
48
48
  npx react-apps-ui@latest init
49
49
  ```
50
50
 
@@ -52,7 +52,7 @@ npx react-apps-ui@latest init
52
52
 
53
53
  Use the `add` command to pull a component into your project. The CLI will automatically fetch the exact code needed for your specific engine, grab any sub-dependencies, and install necessary NPM packages.
54
54
 
55
- ```bash
55
+ ```sh
56
56
  npx react-apps-ui@latest add action-button
57
57
  ```
58
58
 
@@ -64,11 +64,11 @@ The code is now yours! You will find it beautifully organized in your project fo
64
64
  import { ActionButton } from "@/components/ui/action-button";
65
65
 
66
66
  export default function App() {
67
- return (
68
- <ActionButton onPress="{()"> console.log("Pressed!")}>
69
- Click Me
70
- </ActionButton>
71
- );
67
+ return (
68
+ <ActionButton onPress={() => console.log("Pressed!")}>
69
+ Click Me
70
+ </ActionButton>
71
+ );
72
72
  }
73
73
  ```
74
74
 
package/dist/index.js CHANGED
@@ -18,6 +18,22 @@ program
18
18
  .description("Add high-quality components to your React Native app")
19
19
  .version("1.0.0");
20
20
  // --- THE INIT COMMAND ---
21
+ // 1. Define the foundational architecture for each engine
22
+ const BASE_DEPS = {
23
+ "mobile-nativewind": {
24
+ npm: [
25
+ "class-variance-authority",
26
+ "tailwind-merge",
27
+ "clsx",
28
+ "lucide-react-native", // Added for the IconName type
29
+ ],
30
+ registry: ["theme", "utils"], // Pulls your cn() utility and theme
31
+ },
32
+ "mobile-stylesheet": {
33
+ npm: ["lucide-react-native"], // Added for the IconName type
34
+ registry: ["theme", "utils"],
35
+ },
36
+ };
21
37
  program
22
38
  .command("init")
23
39
  .description("Configure your Expo project and install the ThemeProvider")
@@ -43,6 +59,8 @@ program
43
59
  console.log(chalk_1.default.red("Initialization cancelled."));
44
60
  return;
45
61
  }
62
+ const engineKey = response.engine;
63
+ const setup = BASE_DEPS[engineKey];
46
64
  // 2. USE THE REGISTRY_URL to fetch the correct JSON manifest
47
65
  const manifestUrl = `${REGISTRY_URL}/${response.engine}.json`;
48
66
  console.log(chalk_1.default.dim(`\nFetching registry from GitHub...`));
@@ -51,57 +69,71 @@ program
51
69
  if (!res.ok)
52
70
  throw new Error(`Failed to fetch registry: ${res.statusText}`);
53
71
  const registry = await res.json();
54
- // 3. Find the "theme" component inside the giant JSON
55
- const themeComponent = registry.find((item) => item.name === "theme");
56
- if (!themeComponent) {
57
- console.log(chalk_1.default.red("Error: Could not find 'theme' in the registry."));
58
- return;
59
- }
60
- console.log(chalk_1.default.green(`✓ Found theme provider. Installing...`));
61
72
  // Check if the user's project uses a 'src' directory
62
73
  const hasSrcDir = fs_1.default.existsSync(path_1.default.join(process.cwd(), "src"));
63
- // 4. Loop through the files and write them smartly
64
- for (const file of themeComponent.files) {
65
- // A. Force the target to be a string so it can never be undefined
66
- const safeTarget = String(file.target || file.name || "unknown-file");
67
- let finalTargetPath = path_1.default.join(process.cwd(), safeTarget);
68
- //B. Safely check includes on the guaranteed string
69
- const isRootConfig = safeTarget.includes("tailwind") ||
70
- safeTarget.endsWith(".config.js") ||
71
- safeTarget.endsWith(".json");
72
- if (hasSrcDir && !isRootConfig) {
73
- finalTargetPath = path_1.default.join(process.cwd(), "src", safeTarget);
74
+ // 3. Loop through the required BASE REGISTRY components (theme, utils, etc.)
75
+ for (const compName of setup.registry) {
76
+ const componentData = registry.find((item) => item.name === compName);
77
+ if (!componentData) {
78
+ console.log(chalk_1.default.red(`Error: Could not find '${compName}' in the registry.`));
79
+ continue;
74
80
  }
75
- // Ensure the folder exists
76
- fs_1.default.mkdirSync(path_1.default.dirname(finalTargetPath), {
77
- recursive: true,
78
- });
79
- // SAFE WRITE: Check if the file already exists
80
- if (fs_1.default.existsSync(finalTargetPath)) {
81
- if (file.type === "css" ||
82
- finalTargetPath.endsWith(".css")) {
83
- console.log(chalk_1.default.yellow(` ⚠️ ${file.target} already exists. Appending theme variables safely...`));
84
- try {
85
- // C. Read the file and forcefully convert it to a String
86
- const rawContent = fs_1.default.readFileSync(finalTargetPath, "utf-8");
87
- const safeExistingContent = String(rawContent || "");
88
- // D. Safely check includes (This line can no longer crash!)
89
- if (!safeExistingContent.includes("--background:")) {
90
- fs_1.default.appendFileSync(finalTargetPath, `\n/* React Apps UI Theme */\n${file.content || ""}`, "utf-8");
81
+ console.log(chalk_1.default.green(`✓ Found ${compName}. Installing...`));
82
+ // 4. Loop through the files and write them smartly
83
+ for (const file of componentData.files) {
84
+ // A. Force the target to be a string so it can never be undefined
85
+ const safeTarget = String(file.target || file.name || "unknown-file");
86
+ let finalTargetPath = path_1.default.join(process.cwd(), safeTarget);
87
+ //B. Safely check includes on the guaranteed string
88
+ const isRootConfig = safeTarget.includes("tailwind") ||
89
+ safeTarget.endsWith(".config.js") ||
90
+ safeTarget.endsWith(".json");
91
+ if (hasSrcDir && !isRootConfig) {
92
+ finalTargetPath = path_1.default.join(process.cwd(), "src", safeTarget);
93
+ }
94
+ // Ensure the folder exists
95
+ fs_1.default.mkdirSync(path_1.default.dirname(finalTargetPath), {
96
+ recursive: true,
97
+ });
98
+ // SAFE WRITE: Check if the file already exists
99
+ if (fs_1.default.existsSync(finalTargetPath)) {
100
+ if (file.type === "css" ||
101
+ finalTargetPath.endsWith(".css")) {
102
+ console.log(chalk_1.default.yellow(` ⚠️ ${file.target} already exists. Appending theme variables safely...`));
103
+ try {
104
+ // C. Read the file and forcefully convert it to a String
105
+ const rawContent = fs_1.default.readFileSync(finalTargetPath, "utf-8");
106
+ const safeExistingContent = String(rawContent || "");
107
+ // D. Safely check includes (This line can no longer crash!)
108
+ if (!safeExistingContent.includes("--background:")) {
109
+ fs_1.default.appendFileSync(finalTargetPath, `\n/* React Apps UI Theme */\n${file.content || ""}`, "utf-8");
110
+ }
111
+ }
112
+ catch (err) {
113
+ console.log(chalk_1.default.red(` ❌ Error reading or appending to ${safeTarget}`));
91
114
  }
92
115
  }
93
- catch (err) {
94
- console.log(chalk_1.default.red(` Error reading or appending to ${safeTarget}`));
116
+ else {
117
+ console.log(chalk_1.default.yellow(` ⚠️ ${file.target} already exists. Skipping to prevent overwrite.`));
95
118
  }
96
119
  }
97
120
  else {
98
- console.log(chalk_1.default.yellow(` ⚠️ ${file.target} already exists. Skipping to prevent overwrite.`));
121
+ // File doesn't exist, safe to write normally
122
+ fs_1.default.writeFileSync(finalTargetPath, file.content, "utf-8");
123
+ console.log(chalk_1.default.green(` Created ${safeTarget}`));
99
124
  }
100
125
  }
101
- else {
102
- // File doesn't exist, safe to write normally
103
- fs_1.default.writeFileSync(finalTargetPath, file.content, "utf-8");
104
- console.log(chalk_1.default.green(` Created ${safeTarget}`));
126
+ }
127
+ // 5. INSTALL FOUNDATIONAL NPM DEPENDENCIES
128
+ if (setup.npm.length > 0) {
129
+ const depList = setup.npm.join(" ");
130
+ console.log(chalk_1.default.blue(`\n📦 Installing foundational NPM dependencies: ${depList}...`));
131
+ try {
132
+ (0, child_process_1.execSync)(`npm install ${depList}`, { stdio: "inherit" });
133
+ console.log(chalk_1.default.green("✓ Dependencies installed successfully."));
134
+ }
135
+ catch (err) {
136
+ console.log(chalk_1.default.red("❌ Failed to install dependencies. You may need to install them manually."));
105
137
  }
106
138
  }
107
139
  console.log(chalk_1.default.blue("\n🎉 Initialization complete!"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-apps-ui",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "A universal, Shadcn-inspired UI component CLI for Web, React Native, and Expo.",
5
5
  "author": "Anand Vyas",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -18,6 +18,24 @@ program
18
18
  .version("1.0.0");
19
19
 
20
20
  // --- THE INIT COMMAND ---
21
+
22
+ // 1. Define the foundational architecture for each engine
23
+ const BASE_DEPS: Record<string, { npm: string[]; registry: string[] }> = {
24
+ "mobile-nativewind": {
25
+ npm: [
26
+ "class-variance-authority",
27
+ "tailwind-merge",
28
+ "clsx",
29
+ "lucide-react-native", // Added for the IconName type
30
+ ],
31
+ registry: ["theme", "utils"], // Pulls your cn() utility and theme
32
+ },
33
+ "mobile-stylesheet": {
34
+ npm: ["lucide-react-native"], // Added for the IconName type
35
+ registry: ["theme", "utils"],
36
+ },
37
+ };
38
+
21
39
  program
22
40
  .command("init")
23
41
  .description("Configure your Expo project and install the ThemeProvider")
@@ -46,6 +64,9 @@ program
46
64
  return;
47
65
  }
48
66
 
67
+ const engineKey = response.engine as keyof typeof BASE_DEPS;
68
+ const setup = BASE_DEPS[engineKey];
69
+
49
70
  // 2. USE THE REGISTRY_URL to fetch the correct JSON manifest
50
71
  const manifestUrl = `${REGISTRY_URL}/${response.engine}.json`;
51
72
  console.log(chalk.dim(`\nFetching registry from GitHub...`));
@@ -56,101 +77,132 @@ program
56
77
  throw new Error(`Failed to fetch registry: ${res.statusText}`);
57
78
 
58
79
  const registry = await res.json();
59
-
60
- // 3. Find the "theme" component inside the giant JSON
61
- const themeComponent = registry.find(
62
- (item: any) => item.name === "theme",
63
- );
64
-
65
- if (!themeComponent) {
66
- console.log(
67
- chalk.red("Error: Could not find 'theme' in the registry."),
68
- );
69
- return;
70
- }
71
-
72
- console.log(chalk.green(`✓ Found theme provider. Installing...`));
73
-
74
80
  // Check if the user's project uses a 'src' directory
75
81
  const hasSrcDir = fs.existsSync(path.join(process.cwd(), "src"));
76
82
 
77
- // 4. Loop through the files and write them smartly
78
- for (const file of themeComponent.files) {
79
- // A. Force the target to be a string so it can never be undefined
80
- const safeTarget = String(
81
- file.target || file.name || "unknown-file",
83
+ // 3. Loop through the required BASE REGISTRY components (theme, utils, etc.)
84
+ for (const compName of setup.registry) {
85
+ const componentData = registry.find(
86
+ (item: any) => item.name === compName,
82
87
  );
83
- let finalTargetPath = path.join(process.cwd(), safeTarget);
84
-
85
- //B. Safely check includes on the guaranteed string
86
- const isRootConfig =
87
- safeTarget.includes("tailwind") ||
88
- safeTarget.endsWith(".config.js") ||
89
- safeTarget.endsWith(".json");
90
-
91
- if (hasSrcDir && !isRootConfig) {
92
- finalTargetPath = path.join(
93
- process.cwd(),
94
- "src",
95
- safeTarget,
88
+
89
+ if (!componentData) {
90
+ console.log(
91
+ chalk.red(
92
+ `Error: Could not find '${compName}' in the registry.`,
93
+ ),
96
94
  );
95
+ continue;
97
96
  }
98
97
 
99
- // Ensure the folder exists
100
- fs.mkdirSync(path.dirname(finalTargetPath), {
101
- recursive: true,
102
- });
103
-
104
- // SAFE WRITE: Check if the file already exists
105
- if (fs.existsSync(finalTargetPath)) {
106
- if (
107
- file.type === "css" ||
108
- finalTargetPath.endsWith(".css")
109
- ) {
110
- console.log(
111
- chalk.yellow(
112
- ` ⚠️ ${file.target} already exists. Appending theme variables safely...`,
113
- ),
98
+ console.log(chalk.green(`✓ Found ${compName}. Installing...`));
99
+
100
+ // 4. Loop through the files and write them smartly
101
+ for (const file of componentData.files) {
102
+ // A. Force the target to be a string so it can never be undefined
103
+ const safeTarget = String(
104
+ file.target || file.name || "unknown-file",
105
+ );
106
+ let finalTargetPath = path.join(process.cwd(), safeTarget);
107
+
108
+ //B. Safely check includes on the guaranteed string
109
+ const isRootConfig =
110
+ safeTarget.includes("tailwind") ||
111
+ safeTarget.endsWith(".config.js") ||
112
+ safeTarget.endsWith(".json");
113
+
114
+ if (hasSrcDir && !isRootConfig) {
115
+ finalTargetPath = path.join(
116
+ process.cwd(),
117
+ "src",
118
+ safeTarget,
114
119
  );
120
+ }
115
121
 
116
- try {
117
- // C. Read the file and forcefully convert it to a String
118
- const rawContent = fs.readFileSync(
119
- finalTargetPath,
120
- "utf-8",
121
- );
122
- const safeExistingContent = String(
123
- rawContent || "",
122
+ // Ensure the folder exists
123
+ fs.mkdirSync(path.dirname(finalTargetPath), {
124
+ recursive: true,
125
+ });
126
+
127
+ // SAFE WRITE: Check if the file already exists
128
+ if (fs.existsSync(finalTargetPath)) {
129
+ if (
130
+ file.type === "css" ||
131
+ finalTargetPath.endsWith(".css")
132
+ ) {
133
+ console.log(
134
+ chalk.yellow(
135
+ ` ⚠️ ${file.target} already exists. Appending theme variables safely...`,
136
+ ),
124
137
  );
125
138
 
126
- // D. Safely check includes (This line can no longer crash!)
127
- if (
128
- !safeExistingContent.includes("--background:")
129
- ) {
130
- fs.appendFileSync(
139
+ try {
140
+ // C. Read the file and forcefully convert it to a String
141
+ const rawContent = fs.readFileSync(
131
142
  finalTargetPath,
132
- `\n/* React Apps UI Theme */\n${file.content || ""}`,
133
143
  "utf-8",
134
144
  );
145
+ const safeExistingContent = String(
146
+ rawContent || "",
147
+ );
148
+
149
+ // D. Safely check includes (This line can no longer crash!)
150
+ if (
151
+ !safeExistingContent.includes(
152
+ "--background:",
153
+ )
154
+ ) {
155
+ fs.appendFileSync(
156
+ finalTargetPath,
157
+ `\n/* React Apps UI Theme */\n${file.content || ""}`,
158
+ "utf-8",
159
+ );
160
+ }
161
+ } catch (err) {
162
+ console.log(
163
+ chalk.red(
164
+ ` ❌ Error reading or appending to ${safeTarget}`,
165
+ ),
166
+ );
135
167
  }
136
- } catch (err) {
168
+ } else {
137
169
  console.log(
138
- chalk.red(
139
- ` Error reading or appending to ${safeTarget}`,
170
+ chalk.yellow(
171
+ ` ⚠️ ${file.target} already exists. Skipping to prevent overwrite.`,
140
172
  ),
141
173
  );
142
174
  }
143
175
  } else {
144
- console.log(
145
- chalk.yellow(
146
- ` ⚠️ ${file.target} already exists. Skipping to prevent overwrite.`,
147
- ),
176
+ // File doesn't exist, safe to write normally
177
+ fs.writeFileSync(
178
+ finalTargetPath,
179
+ file.content,
180
+ "utf-8",
148
181
  );
182
+ console.log(chalk.green(` Created ${safeTarget}`));
149
183
  }
150
- } else {
151
- // File doesn't exist, safe to write normally
152
- fs.writeFileSync(finalTargetPath, file.content, "utf-8");
153
- console.log(chalk.green(` Created ${safeTarget}`));
184
+ }
185
+ }
186
+
187
+ // 5. INSTALL FOUNDATIONAL NPM DEPENDENCIES
188
+ if (setup.npm.length > 0) {
189
+ const depList = setup.npm.join(" ");
190
+ console.log(
191
+ chalk.blue(
192
+ `\n📦 Installing foundational NPM dependencies: ${depList}...`,
193
+ ),
194
+ );
195
+ try {
196
+ execSync(`npm install ${depList}`, { stdio: "inherit" });
197
+ console.log(
198
+ chalk.green("✓ Dependencies installed successfully."),
199
+ );
200
+ } catch (err) {
201
+ console.log(
202
+ chalk.red(
203
+ "❌ Failed to install dependencies. You may need to install them manually.",
204
+ ),
205
+ );
154
206
  }
155
207
  }
156
208