@cyberbloxai/ui-kit 0.2.0 → 0.2.1
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 +13 -2
- package/package.json +1 -1
- package/src/cli.js +324 -24
package/README.md
CHANGED
|
@@ -21,17 +21,28 @@ CyberBlox UI Kit is a modular, themeable component library designed for building
|
|
|
21
21
|
There are two ways to use CyberBlox UI:
|
|
22
22
|
|
|
23
23
|
### 1. shadcn-style (Recommended)
|
|
24
|
-
This copies the component source code directly into your project, allowing you to customize everything.
|
|
24
|
+
This copies the component source code directly into your project, allowing you to customize everything. It also handles dependencies and installs necessary npm packages automatically.
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
# 1. Initialize the project (
|
|
27
|
+
# 1. Initialize the project (creates components.json and lib/utils.ts)
|
|
28
28
|
npx @cyberbloxai/ui-kit init
|
|
29
29
|
|
|
30
30
|
# 2. Add components as needed
|
|
31
31
|
npx @cyberbloxai/ui-kit add button
|
|
32
32
|
npx @cyberbloxai/ui-kit add dialog
|
|
33
|
+
npx @cyberbloxai/ui-kit add alert-dialog # This will also add 'button' automatically!
|
|
33
34
|
```
|
|
34
35
|
|
|
36
|
+
**What happens during `init`?**
|
|
37
|
+
- A `components.json` file is created in your root directory.
|
|
38
|
+
- `lib/utils.ts` is created with the `cn` helper.
|
|
39
|
+
|
|
40
|
+
**What happens during `add`?**
|
|
41
|
+
- The component's `.tsx` file is copied to your `components/ui` folder.
|
|
42
|
+
- Any internal dependencies (like `button` for `alert-dialog`) are also added.
|
|
43
|
+
- Any required npm packages (like `@radix-ui/react-dialog`) are installed automatically.
|
|
44
|
+
|
|
45
|
+
|
|
35
46
|
### 2. Standard Library Style
|
|
36
47
|
Install it as a traditional npm package.
|
|
37
48
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
6
7
|
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
9
|
const __dirname = path.dirname(__filename);
|
|
9
10
|
|
|
10
|
-
// This script will be located in node_modules/@cyberbloxai/ui-kit/src/cli.js
|
|
11
|
-
// We need to find the source components directory relative to this script.
|
|
12
11
|
const packageRoot = path.join(__dirname, '..');
|
|
13
12
|
const componentsSrc = path.join(packageRoot, 'src', 'components', 'ui');
|
|
14
13
|
const utilsSrc = path.join(packageRoot, 'src', 'lib', 'utils.ts');
|
|
@@ -16,9 +15,240 @@ const utilsSrc = path.join(packageRoot, 'src', 'lib', 'utils.ts');
|
|
|
16
15
|
const args = process.argv.slice(2);
|
|
17
16
|
const command = args[0];
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const DEFAULT_CONFIG = {
|
|
19
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
20
|
+
"style": "default",
|
|
21
|
+
"rsc": false,
|
|
22
|
+
"tsx": true,
|
|
23
|
+
"tailwind": {
|
|
24
|
+
"config": "tailwind.config.js",
|
|
25
|
+
"css": "src/index.css",
|
|
26
|
+
"baseColor": "slate",
|
|
27
|
+
"cssVariables": true,
|
|
28
|
+
"prefix": ""
|
|
29
|
+
},
|
|
30
|
+
"aliases": {
|
|
31
|
+
"components": "@/components",
|
|
32
|
+
"utils": "@/lib/utils",
|
|
33
|
+
"ui": "@/components/ui",
|
|
34
|
+
"lib": "@/lib",
|
|
35
|
+
"hooks": "@/hooks"
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Component dependencies map
|
|
40
|
+
const COMPONENT_REGISTRY = {
|
|
41
|
+
"accordion": {
|
|
42
|
+
"dependencies": ["@radix-ui/react-accordion"],
|
|
43
|
+
"registryDependencies": ["lucide-react"]
|
|
44
|
+
},
|
|
45
|
+
"alert-dialog": {
|
|
46
|
+
"dependencies": ["@radix-ui/react-alert-dialog", "button"],
|
|
47
|
+
"registryDependencies": ["lucide-react"]
|
|
48
|
+
},
|
|
49
|
+
"alert": {
|
|
50
|
+
"dependencies": [],
|
|
51
|
+
"registryDependencies": ["lucide-react", "class-variance-authority"]
|
|
52
|
+
},
|
|
53
|
+
"aspect-ratio": {
|
|
54
|
+
"dependencies": ["@radix-ui/react-aspect-ratio"],
|
|
55
|
+
"registryDependencies": []
|
|
56
|
+
},
|
|
57
|
+
"avatar": {
|
|
58
|
+
"dependencies": ["@radix-ui/react-avatar"],
|
|
59
|
+
"registryDependencies": []
|
|
60
|
+
},
|
|
61
|
+
"badge": {
|
|
62
|
+
"dependencies": [],
|
|
63
|
+
"registryDependencies": ["class-variance-authority"]
|
|
64
|
+
},
|
|
65
|
+
"breadcrumb": {
|
|
66
|
+
"dependencies": ["@radix-ui/react-slot"],
|
|
67
|
+
"registryDependencies": ["lucide-react"]
|
|
68
|
+
},
|
|
69
|
+
"button": {
|
|
70
|
+
"dependencies": ["@radix-ui/react-slot"],
|
|
71
|
+
"registryDependencies": ["class-variance-authority", "lucide-react"]
|
|
72
|
+
},
|
|
73
|
+
"calendar": {
|
|
74
|
+
"dependencies": ["react-day-picker", "date-fns", "button"],
|
|
75
|
+
"registryDependencies": ["lucide-react"]
|
|
76
|
+
},
|
|
77
|
+
"card": {
|
|
78
|
+
"dependencies": [],
|
|
79
|
+
"registryDependencies": []
|
|
80
|
+
},
|
|
81
|
+
"carousel": {
|
|
82
|
+
"dependencies": ["embla-carousel-react", "button"],
|
|
83
|
+
"registryDependencies": ["lucide-react"]
|
|
84
|
+
},
|
|
85
|
+
"checkbox": {
|
|
86
|
+
"dependencies": ["@radix-ui/react-checkbox"],
|
|
87
|
+
"registryDependencies": ["lucide-react"]
|
|
88
|
+
},
|
|
89
|
+
"collapsible": {
|
|
90
|
+
"dependencies": ["@radix-ui/react-collapsible"],
|
|
91
|
+
"registryDependencies": []
|
|
92
|
+
},
|
|
93
|
+
"command": {
|
|
94
|
+
"dependencies": ["cmdk", "dialog"],
|
|
95
|
+
"registryDependencies": ["lucide-react"]
|
|
96
|
+
},
|
|
97
|
+
"context-menu": {
|
|
98
|
+
"dependencies": ["@radix-ui/react-context-menu"],
|
|
99
|
+
"registryDependencies": ["lucide-react"]
|
|
100
|
+
},
|
|
101
|
+
"dialog": {
|
|
102
|
+
"dependencies": ["@radix-ui/react-dialog"],
|
|
103
|
+
"registryDependencies": ["lucide-react"]
|
|
104
|
+
},
|
|
105
|
+
"drawer": {
|
|
106
|
+
"dependencies": ["vaul"],
|
|
107
|
+
"registryDependencies": ["lucide-react"]
|
|
108
|
+
},
|
|
109
|
+
"dropdown-menu": {
|
|
110
|
+
"dependencies": ["@radix-ui/react-dropdown-menu"],
|
|
111
|
+
"registryDependencies": ["lucide-react"]
|
|
112
|
+
},
|
|
113
|
+
"form": {
|
|
114
|
+
"dependencies": ["@radix-ui/react-label", "@radix-ui/react-slot", "react-hook-form", "@hookform/resolvers", "zod", "label"],
|
|
115
|
+
"registryDependencies": ["lucide-react"]
|
|
116
|
+
},
|
|
117
|
+
"hover-card": {
|
|
118
|
+
"dependencies": ["@radix-ui/react-hover-card"],
|
|
119
|
+
"registryDependencies": []
|
|
120
|
+
},
|
|
121
|
+
"input-otp": {
|
|
122
|
+
"dependencies": ["input-otp"],
|
|
123
|
+
"registryDependencies": ["lucide-react"]
|
|
124
|
+
},
|
|
125
|
+
"input": {
|
|
126
|
+
"dependencies": [],
|
|
127
|
+
"registryDependencies": []
|
|
128
|
+
},
|
|
129
|
+
"label": {
|
|
130
|
+
"dependencies": ["@radix-ui/react-label"],
|
|
131
|
+
"registryDependencies": ["class-variance-authority"]
|
|
132
|
+
},
|
|
133
|
+
"menubar": {
|
|
134
|
+
"dependencies": ["@radix-ui/react-menubar"],
|
|
135
|
+
"registryDependencies": ["lucide-react"]
|
|
136
|
+
},
|
|
137
|
+
"navigation-menu": {
|
|
138
|
+
"dependencies": ["@radix-ui/react-navigation-menu"],
|
|
139
|
+
"registryDependencies": ["lucide-react", "class-variance-authority"]
|
|
140
|
+
},
|
|
141
|
+
"pagination": {
|
|
142
|
+
"dependencies": ["button"],
|
|
143
|
+
"registryDependencies": ["lucide-react"]
|
|
144
|
+
},
|
|
145
|
+
"popover": {
|
|
146
|
+
"dependencies": ["@radix-ui/react-popover"],
|
|
147
|
+
"registryDependencies": []
|
|
148
|
+
},
|
|
149
|
+
"progress": {
|
|
150
|
+
"dependencies": ["@radix-ui/react-progress"],
|
|
151
|
+
"registryDependencies": []
|
|
152
|
+
},
|
|
153
|
+
"radio-group": {
|
|
154
|
+
"dependencies": ["@radix-ui/react-radio-group"],
|
|
155
|
+
"registryDependencies": ["lucide-react"]
|
|
156
|
+
},
|
|
157
|
+
"resizable": {
|
|
158
|
+
"dependencies": ["react-resizable-panels"],
|
|
159
|
+
"registryDependencies": ["lucide-react"]
|
|
160
|
+
},
|
|
161
|
+
"scroll-area": {
|
|
162
|
+
"dependencies": ["@radix-ui/react-scroll-area"],
|
|
163
|
+
"registryDependencies": []
|
|
164
|
+
},
|
|
165
|
+
"select": {
|
|
166
|
+
"dependencies": ["@radix-ui/react-select"],
|
|
167
|
+
"registryDependencies": ["lucide-react"]
|
|
168
|
+
},
|
|
169
|
+
"separator": {
|
|
170
|
+
"dependencies": ["@radix-ui/react-separator"],
|
|
171
|
+
"registryDependencies": []
|
|
172
|
+
},
|
|
173
|
+
"sheet": {
|
|
174
|
+
"dependencies": ["@radix-ui/react-dialog"],
|
|
175
|
+
"registryDependencies": ["lucide-react", "class-variance-authority"]
|
|
176
|
+
},
|
|
177
|
+
"sidebar": {
|
|
178
|
+
"dependencies": ["@radix-ui/react-slot", "button", "input", "separator", "sheet", "skeleton", "tooltip"],
|
|
179
|
+
"registryDependencies": ["lucide-react", "class-variance-authority"]
|
|
180
|
+
},
|
|
181
|
+
"skeleton": {
|
|
182
|
+
"dependencies": [],
|
|
183
|
+
"registryDependencies": []
|
|
184
|
+
},
|
|
185
|
+
"slider": {
|
|
186
|
+
"dependencies": ["@radix-ui/react-slider"],
|
|
187
|
+
"registryDependencies": []
|
|
188
|
+
},
|
|
189
|
+
"sonner": {
|
|
190
|
+
"dependencies": ["sonner", "next-themes"],
|
|
191
|
+
"registryDependencies": []
|
|
192
|
+
},
|
|
193
|
+
"switch": {
|
|
194
|
+
"dependencies": ["@radix-ui/react-switch"],
|
|
195
|
+
"registryDependencies": []
|
|
196
|
+
},
|
|
197
|
+
"table": {
|
|
198
|
+
"dependencies": [],
|
|
199
|
+
"registryDependencies": []
|
|
200
|
+
},
|
|
201
|
+
"tabs": {
|
|
202
|
+
"dependencies": ["@radix-ui/react-tabs"],
|
|
203
|
+
"registryDependencies": []
|
|
204
|
+
},
|
|
205
|
+
"textarea": {
|
|
206
|
+
"dependencies": [],
|
|
207
|
+
"registryDependencies": []
|
|
208
|
+
},
|
|
209
|
+
"use-toast": {
|
|
210
|
+
"dependencies": [],
|
|
211
|
+
"registryDependencies": []
|
|
212
|
+
},
|
|
213
|
+
"toast": {
|
|
214
|
+
"dependencies": ["@radix-ui/react-toast"],
|
|
215
|
+
"registryDependencies": ["lucide-react", "class-variance-authority"]
|
|
216
|
+
},
|
|
217
|
+
"toaster": {
|
|
218
|
+
"dependencies": ["toast", "use-toast"],
|
|
219
|
+
"registryDependencies": []
|
|
220
|
+
},
|
|
221
|
+
"toggle-group": {
|
|
222
|
+
"dependencies": ["@radix-ui/react-toggle-group", "toggle"],
|
|
223
|
+
"registryDependencies": []
|
|
224
|
+
},
|
|
225
|
+
"toggle": {
|
|
226
|
+
"dependencies": ["@radix-ui/react-toggle"],
|
|
227
|
+
"registryDependencies": ["class-variance-authority"]
|
|
228
|
+
},
|
|
229
|
+
"tooltip": {
|
|
230
|
+
"dependencies": ["@radix-ui/react-tooltip"],
|
|
231
|
+
"registryDependencies": []
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
function getProjectConfig() {
|
|
236
|
+
const configPath = path.join(process.cwd(), 'components.json');
|
|
237
|
+
if (fs.existsSync(configPath)) {
|
|
238
|
+
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function resolveAlias(alias, config) {
|
|
244
|
+
const aliases = config.aliases || {};
|
|
245
|
+
if (alias.startsWith('@/')) {
|
|
246
|
+
// Basic @/ support - assuming it maps to src/ or project root
|
|
247
|
+
const isSrcExists = fs.existsSync(path.join(process.cwd(), 'src'));
|
|
248
|
+
const base = isSrcExists ? 'src' : '';
|
|
249
|
+
return path.join(process.cwd(), base, alias.replace('@/', ''));
|
|
250
|
+
}
|
|
251
|
+
return path.join(process.cwd(), alias);
|
|
22
252
|
}
|
|
23
253
|
|
|
24
254
|
function copyFile(src, dest) {
|
|
@@ -26,41 +256,111 @@ function copyFile(src, dest) {
|
|
|
26
256
|
if (!fs.existsSync(destDir)) {
|
|
27
257
|
fs.mkdirSync(destDir, { recursive: true });
|
|
28
258
|
}
|
|
29
|
-
|
|
259
|
+
|
|
260
|
+
let content = fs.readFileSync(src, 'utf8');
|
|
261
|
+
|
|
262
|
+
// Basic path replacement: replace @/ with project root relative paths if needed
|
|
263
|
+
// In a real shadcn CLI, this is more complex (respecting aliases)
|
|
264
|
+
|
|
265
|
+
fs.writeFileSync(dest, content);
|
|
30
266
|
console.log(` Created ${path.relative(process.cwd(), dest)}`);
|
|
31
267
|
}
|
|
32
268
|
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
269
|
+
function installDependencies(deps) {
|
|
270
|
+
if (!deps || deps.length === 0) return;
|
|
271
|
+
|
|
272
|
+
console.log(` Installing dependencies: ${deps.join(', ')}...`);
|
|
273
|
+
try {
|
|
274
|
+
const command = fs.existsSync(path.join(process.cwd(), 'yarn.lock'))
|
|
275
|
+
? `yarn add ${deps.join(' ')}`
|
|
276
|
+
: `npm install ${deps.join(' ')}`;
|
|
277
|
+
execSync(command, { stdio: 'inherit' });
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.warn(' Failed to install dependencies automatically. Please install them manually.');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function init() {
|
|
284
|
+
console.log('Initializing CyberBlox UI...');
|
|
285
|
+
|
|
286
|
+
const configPath = path.join(process.cwd(), 'components.json');
|
|
287
|
+
if (fs.existsSync(configPath)) {
|
|
288
|
+
console.log(' components.json already exists.');
|
|
289
|
+
} else {
|
|
290
|
+
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
|
|
291
|
+
console.log(' Created components.json');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const config = getProjectConfig() || DEFAULT_CONFIG;
|
|
295
|
+
const utilsDest = resolveAlias(config.aliases.utils + '.ts', config);
|
|
36
296
|
|
|
37
|
-
// Copy utils
|
|
38
|
-
const utilsDest = path.join(targetBase, 'lib', 'utils.ts');
|
|
39
297
|
copyFile(utilsSrc, utilsDest);
|
|
40
298
|
|
|
41
|
-
console.log('\nSuccess!
|
|
42
|
-
console.log('
|
|
299
|
+
console.log('\nSuccess! Project initialized.');
|
|
300
|
+
console.log('Now you can add components using:');
|
|
301
|
+
console.log('npx @cyberbloxai/ui-kit add [component-name]');
|
|
43
302
|
}
|
|
44
303
|
|
|
45
304
|
function addComponent(name) {
|
|
46
305
|
if (!name) {
|
|
47
|
-
console.error('Please specify a component name
|
|
306
|
+
console.error('Please specify a component name.');
|
|
48
307
|
process.exit(1);
|
|
49
308
|
}
|
|
50
309
|
|
|
51
|
-
const
|
|
310
|
+
const config = getProjectConfig();
|
|
311
|
+
if (!config) {
|
|
312
|
+
console.error('Project not initialized. Run "npx @cyberbloxai/ui-kit init" first.');
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const registryItem = COMPONENT_REGISTRY[name];
|
|
317
|
+
|
|
318
|
+
// Recursive add for internal dependencies
|
|
319
|
+
if (registryItem && registryItem.dependencies) {
|
|
320
|
+
registryItem.dependencies.forEach(dep => {
|
|
321
|
+
if (!dep.startsWith('@')) { // It's an internal component
|
|
322
|
+
addComponent(dep);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const fileName = name.endsWith('.tsx') || name.endsWith('.ts') ? name : `${name}.tsx`;
|
|
52
328
|
const srcPath = path.join(componentsSrc, fileName);
|
|
53
329
|
|
|
330
|
+
// Also check in hooks if not found in components
|
|
331
|
+
let finalSrcPath = srcPath;
|
|
332
|
+
let targetDir = resolveAlias(config.aliases.ui, config);
|
|
333
|
+
|
|
54
334
|
if (!fs.existsSync(srcPath)) {
|
|
55
|
-
|
|
56
|
-
|
|
335
|
+
const hookPath = path.join(packageRoot, 'src', 'hooks', fileName);
|
|
336
|
+
const libPath = path.join(packageRoot, 'src', 'lib', fileName);
|
|
337
|
+
|
|
338
|
+
if (fs.existsSync(hookPath)) {
|
|
339
|
+
finalSrcPath = hookPath;
|
|
340
|
+
targetDir = resolveAlias(config.aliases.hooks || '@/hooks', config);
|
|
341
|
+
} else if (fs.existsSync(libPath)) {
|
|
342
|
+
finalSrcPath = libPath;
|
|
343
|
+
targetDir = resolveAlias(config.aliases.lib || '@/lib', config);
|
|
344
|
+
} else {
|
|
345
|
+
console.error(`Component or file "${name}" not found.`);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
57
348
|
}
|
|
58
349
|
|
|
59
|
-
const
|
|
60
|
-
const destPath = path.join(targetBase, 'components', 'ui', fileName);
|
|
350
|
+
const destPath = path.join(targetDir, path.basename(finalSrcPath));
|
|
61
351
|
|
|
62
|
-
|
|
63
|
-
|
|
352
|
+
if (fs.existsSync(destPath)) {
|
|
353
|
+
console.log(` File ${path.basename(finalSrcPath)} already exists. Skipping.`);
|
|
354
|
+
} else {
|
|
355
|
+
copyFile(finalSrcPath, destPath);
|
|
356
|
+
|
|
357
|
+
// Install npm dependencies
|
|
358
|
+
if (registryItem && registryItem.dependencies) {
|
|
359
|
+
const npmDeps = registryItem.dependencies.filter(d => d.startsWith('@') || !COMPONENT_REGISTRY[d]);
|
|
360
|
+
const regDeps = registryItem.registryDependencies || [];
|
|
361
|
+
installDependencies([...new Set([...npmDeps, ...regDeps])]);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
64
364
|
}
|
|
65
365
|
|
|
66
366
|
function listComponents() {
|
|
@@ -86,8 +386,8 @@ switch (command) {
|
|
|
86
386
|
default:
|
|
87
387
|
console.log('CyberBlox UI CLI');
|
|
88
388
|
console.log('\nUsage:');
|
|
89
|
-
console.log(' npx
|
|
90
|
-
console.log(' npx
|
|
91
|
-
console.log(' npx
|
|
389
|
+
console.log(' npx @cyberbloxai/ui-kit init - Setup components.json and utils');
|
|
390
|
+
console.log(' npx @cyberbloxai/ui-kit add [name] - Add a component');
|
|
391
|
+
console.log(' npx @cyberbloxai/ui-kit list - List components');
|
|
92
392
|
break;
|
|
93
393
|
}
|