@reeverdev/ui-cli 0.1.0
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/dist/index.js +588 -0
- package/package.json +49 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
4
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// ../package.json
|
|
8
|
+
var require_package = __commonJS({
|
|
9
|
+
"../package.json"(exports, module) {
|
|
10
|
+
module.exports = {
|
|
11
|
+
name: "reever",
|
|
12
|
+
version: "0.0.0",
|
|
13
|
+
private: true,
|
|
14
|
+
description: "Reever Design System - Multi-platform UI component library",
|
|
15
|
+
author: "Reever",
|
|
16
|
+
license: "MIT",
|
|
17
|
+
repository: {
|
|
18
|
+
type: "git",
|
|
19
|
+
url: "https://github.com/ReeverApp/Reever.UI.git"
|
|
20
|
+
},
|
|
21
|
+
homepage: "https://reever.dev",
|
|
22
|
+
workspaces: [
|
|
23
|
+
"packages/*",
|
|
24
|
+
"apps/*",
|
|
25
|
+
"tooling/*"
|
|
26
|
+
],
|
|
27
|
+
scripts: {
|
|
28
|
+
build: "turbo build",
|
|
29
|
+
dev: "turbo dev",
|
|
30
|
+
lint: "turbo lint",
|
|
31
|
+
typecheck: "turbo typecheck",
|
|
32
|
+
test: "turbo test",
|
|
33
|
+
clean: "turbo clean && rm -rf node_modules",
|
|
34
|
+
format: 'prettier --write "**/*.{ts,tsx,md,json}"',
|
|
35
|
+
changeset: "changeset",
|
|
36
|
+
"version-packages": "changeset version",
|
|
37
|
+
release: "turbo build --filter=./packages/* && changeset publish"
|
|
38
|
+
},
|
|
39
|
+
devDependencies: {
|
|
40
|
+
"@changesets/cli": "^2.29.8",
|
|
41
|
+
prettier: "^3.7.4",
|
|
42
|
+
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
43
|
+
turbo: "^2.5.4",
|
|
44
|
+
typescript: "^5.9.3"
|
|
45
|
+
},
|
|
46
|
+
packageManager: "pnpm@9.15.0",
|
|
47
|
+
engines: {
|
|
48
|
+
node: ">=18.0.0"
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// index.ts
|
|
55
|
+
import { Command } from "commander";
|
|
56
|
+
|
|
57
|
+
// commands/init.ts
|
|
58
|
+
import * as fs from "fs";
|
|
59
|
+
import * as path from "path";
|
|
60
|
+
import chalk from "chalk";
|
|
61
|
+
import ora from "ora";
|
|
62
|
+
import prompts from "prompts";
|
|
63
|
+
var DEFAULT_CONFIG = {
|
|
64
|
+
$schema: "https://reever-ui.com/schema.json",
|
|
65
|
+
style: "default",
|
|
66
|
+
tailwind: {
|
|
67
|
+
config: "tailwind.config.js",
|
|
68
|
+
css: "src/styles/globals.css",
|
|
69
|
+
baseColor: "slate",
|
|
70
|
+
cssVariables: true
|
|
71
|
+
},
|
|
72
|
+
aliases: {
|
|
73
|
+
components: "@/components",
|
|
74
|
+
utils: "@/lib/utils"
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
async function init(options) {
|
|
78
|
+
const configPath = path.resolve(process.cwd(), "reever-ui.json");
|
|
79
|
+
if (fs.existsSync(configPath) && !options.overwrite) {
|
|
80
|
+
console.log(
|
|
81
|
+
chalk.yellow("Configuration file already exists. Use --overwrite to replace.")
|
|
82
|
+
);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!options.yes) {
|
|
86
|
+
const response = await prompts([
|
|
87
|
+
{
|
|
88
|
+
type: "text",
|
|
89
|
+
name: "componentsDir",
|
|
90
|
+
message: "Where would you like to install components?",
|
|
91
|
+
initial: "src/components/ui"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: "text",
|
|
95
|
+
name: "utilsDir",
|
|
96
|
+
message: "Where is your utils directory?",
|
|
97
|
+
initial: "src/lib"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
name: "tailwindConfig",
|
|
102
|
+
message: "Where is your tailwind.config file?",
|
|
103
|
+
initial: "tailwind.config.js"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: "text",
|
|
107
|
+
name: "globalsCss",
|
|
108
|
+
message: "Where is your global CSS file?",
|
|
109
|
+
initial: "src/styles/globals.css"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: "select",
|
|
113
|
+
name: "baseColor",
|
|
114
|
+
message: "Which base color would you like to use?",
|
|
115
|
+
choices: [
|
|
116
|
+
{ title: "Slate", value: "slate" },
|
|
117
|
+
{ title: "Gray", value: "gray" },
|
|
118
|
+
{ title: "Zinc", value: "zinc" },
|
|
119
|
+
{ title: "Neutral", value: "neutral" },
|
|
120
|
+
{ title: "Stone", value: "stone" }
|
|
121
|
+
],
|
|
122
|
+
initial: 0
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
125
|
+
DEFAULT_CONFIG.aliases.components = `@/${response.componentsDir.replace(/^src\//, "")}`;
|
|
126
|
+
DEFAULT_CONFIG.aliases.utils = `@/${response.utilsDir.replace(/^src\//, "")}`;
|
|
127
|
+
DEFAULT_CONFIG.tailwind.config = response.tailwindConfig;
|
|
128
|
+
DEFAULT_CONFIG.tailwind.css = response.globalsCss;
|
|
129
|
+
DEFAULT_CONFIG.tailwind.baseColor = response.baseColor;
|
|
130
|
+
}
|
|
131
|
+
const spinner = ora("Initializing reever-ui...").start();
|
|
132
|
+
try {
|
|
133
|
+
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
|
|
134
|
+
spinner.succeed("Configuration file created");
|
|
135
|
+
const utilsPath = path.resolve(process.cwd(), "src/lib/utils.ts");
|
|
136
|
+
const utilsDir = path.dirname(utilsPath);
|
|
137
|
+
if (!fs.existsSync(utilsDir)) {
|
|
138
|
+
fs.mkdirSync(utilsDir, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
if (!fs.existsSync(utilsPath)) {
|
|
141
|
+
fs.writeFileSync(
|
|
142
|
+
utilsPath,
|
|
143
|
+
`import { type ClassValue, clsx } from "clsx";
|
|
144
|
+
import { twMerge } from "tailwind-merge";
|
|
145
|
+
|
|
146
|
+
export function cn(...inputs: ClassValue[]) {
|
|
147
|
+
return twMerge(clsx(inputs));
|
|
148
|
+
}
|
|
149
|
+
`
|
|
150
|
+
);
|
|
151
|
+
spinner.succeed("Utils file created");
|
|
152
|
+
}
|
|
153
|
+
console.log();
|
|
154
|
+
console.log(chalk.green("\u2713 reever-ui initialized successfully!"));
|
|
155
|
+
console.log();
|
|
156
|
+
console.log("Next steps:");
|
|
157
|
+
console.log(` ${chalk.cyan("npx reever-ui add button")} - Add your first component`);
|
|
158
|
+
console.log(` ${chalk.cyan("npx reever-ui list")} - See all available components`);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
spinner.fail("Failed to initialize");
|
|
161
|
+
console.error(error);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// commands/add.ts
|
|
167
|
+
import * as fs2 from "fs";
|
|
168
|
+
import * as path2 from "path";
|
|
169
|
+
import chalk2 from "chalk";
|
|
170
|
+
import ora2 from "ora";
|
|
171
|
+
import prompts2 from "prompts";
|
|
172
|
+
|
|
173
|
+
// registry.ts
|
|
174
|
+
var CATEGORIES = [
|
|
175
|
+
"Core",
|
|
176
|
+
"Form",
|
|
177
|
+
"Navigation",
|
|
178
|
+
"Data Display",
|
|
179
|
+
"Overlay",
|
|
180
|
+
"Feedback",
|
|
181
|
+
"Layout",
|
|
182
|
+
"Animation",
|
|
183
|
+
"Mobile"
|
|
184
|
+
];
|
|
185
|
+
var COMPONENTS = {
|
|
186
|
+
button: {
|
|
187
|
+
name: "Button",
|
|
188
|
+
description: "Primary action button with variants",
|
|
189
|
+
category: "Core",
|
|
190
|
+
code: `// Button component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
191
|
+
export { Button, buttonVariants } from "reever-ui";
|
|
192
|
+
`,
|
|
193
|
+
dependencies: ["class-variance-authority"]
|
|
194
|
+
},
|
|
195
|
+
input: {
|
|
196
|
+
name: "Input",
|
|
197
|
+
description: "Text input field",
|
|
198
|
+
category: "Core",
|
|
199
|
+
code: `// Input component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
200
|
+
export { Input } from "reever-ui";
|
|
201
|
+
`
|
|
202
|
+
},
|
|
203
|
+
card: {
|
|
204
|
+
name: "Card",
|
|
205
|
+
description: "Container card component",
|
|
206
|
+
category: "Core",
|
|
207
|
+
code: `// Card component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
208
|
+
export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "reever-ui";
|
|
209
|
+
`
|
|
210
|
+
},
|
|
211
|
+
dialog: {
|
|
212
|
+
name: "Dialog",
|
|
213
|
+
description: "Modal dialog",
|
|
214
|
+
category: "Overlay",
|
|
215
|
+
code: `// Dialog component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
216
|
+
export { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from "reever-ui";
|
|
217
|
+
`,
|
|
218
|
+
dependencies: ["@radix-ui/react-dialog"]
|
|
219
|
+
},
|
|
220
|
+
select: {
|
|
221
|
+
name: "Select",
|
|
222
|
+
description: "Dropdown select",
|
|
223
|
+
category: "Form",
|
|
224
|
+
code: `// Select component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
225
|
+
export { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel } from "reever-ui";
|
|
226
|
+
`,
|
|
227
|
+
dependencies: ["@radix-ui/react-select"]
|
|
228
|
+
},
|
|
229
|
+
tabs: {
|
|
230
|
+
name: "Tabs",
|
|
231
|
+
description: "Tabbed content",
|
|
232
|
+
category: "Navigation",
|
|
233
|
+
code: `// Tabs component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
234
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent } from "reever-ui";
|
|
235
|
+
`,
|
|
236
|
+
dependencies: ["@radix-ui/react-tabs"]
|
|
237
|
+
},
|
|
238
|
+
toast: {
|
|
239
|
+
name: "Toast",
|
|
240
|
+
description: "Toast notifications",
|
|
241
|
+
category: "Feedback",
|
|
242
|
+
code: `// Toast component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
243
|
+
export { toast, Toaster } from "reever-ui";
|
|
244
|
+
`,
|
|
245
|
+
dependencies: ["sonner"]
|
|
246
|
+
},
|
|
247
|
+
table: {
|
|
248
|
+
name: "Table",
|
|
249
|
+
description: "Data table",
|
|
250
|
+
category: "Data Display",
|
|
251
|
+
code: `// Table component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
252
|
+
export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from "reever-ui";
|
|
253
|
+
`
|
|
254
|
+
},
|
|
255
|
+
form: {
|
|
256
|
+
name: "Form",
|
|
257
|
+
description: "Form wrapper with validation",
|
|
258
|
+
category: "Form",
|
|
259
|
+
code: `// Form component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
260
|
+
export { Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage } from "reever-ui";
|
|
261
|
+
`
|
|
262
|
+
},
|
|
263
|
+
avatar: {
|
|
264
|
+
name: "Avatar",
|
|
265
|
+
description: "User avatar",
|
|
266
|
+
category: "Data Display",
|
|
267
|
+
code: `// Avatar component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
268
|
+
export { Avatar, AvatarImage, AvatarFallback } from "reever-ui";
|
|
269
|
+
`,
|
|
270
|
+
dependencies: ["@radix-ui/react-avatar"]
|
|
271
|
+
},
|
|
272
|
+
badge: {
|
|
273
|
+
name: "Badge",
|
|
274
|
+
description: "Status badge",
|
|
275
|
+
category: "Core",
|
|
276
|
+
code: `// Badge component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
277
|
+
export { Badge, badgeVariants } from "reever-ui";
|
|
278
|
+
`,
|
|
279
|
+
dependencies: ["class-variance-authority"]
|
|
280
|
+
},
|
|
281
|
+
checkbox: {
|
|
282
|
+
name: "Checkbox",
|
|
283
|
+
description: "Checkbox input",
|
|
284
|
+
category: "Form",
|
|
285
|
+
code: `// Checkbox component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
286
|
+
export { Checkbox } from "reever-ui";
|
|
287
|
+
`,
|
|
288
|
+
dependencies: ["@radix-ui/react-checkbox"]
|
|
289
|
+
},
|
|
290
|
+
dropdown: {
|
|
291
|
+
name: "DropdownMenu",
|
|
292
|
+
description: "Dropdown menu",
|
|
293
|
+
category: "Overlay",
|
|
294
|
+
code: `// DropdownMenu component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
295
|
+
export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "reever-ui";
|
|
296
|
+
`,
|
|
297
|
+
dependencies: ["@radix-ui/react-dropdown-menu"]
|
|
298
|
+
},
|
|
299
|
+
popover: {
|
|
300
|
+
name: "Popover",
|
|
301
|
+
description: "Popover overlay",
|
|
302
|
+
category: "Overlay",
|
|
303
|
+
code: `// Popover component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
304
|
+
export { Popover, PopoverTrigger, PopoverContent } from "reever-ui";
|
|
305
|
+
`,
|
|
306
|
+
dependencies: ["@radix-ui/react-popover"]
|
|
307
|
+
},
|
|
308
|
+
tooltip: {
|
|
309
|
+
name: "Tooltip",
|
|
310
|
+
description: "Tooltip overlay",
|
|
311
|
+
category: "Overlay",
|
|
312
|
+
code: `// Tooltip component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
313
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "reever-ui";
|
|
314
|
+
`,
|
|
315
|
+
dependencies: ["@radix-ui/react-tooltip"]
|
|
316
|
+
},
|
|
317
|
+
slider: {
|
|
318
|
+
name: "Slider",
|
|
319
|
+
description: "Range slider",
|
|
320
|
+
category: "Form",
|
|
321
|
+
code: `// Slider component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
322
|
+
export { Slider } from "reever-ui";
|
|
323
|
+
`,
|
|
324
|
+
dependencies: ["@radix-ui/react-slider"]
|
|
325
|
+
},
|
|
326
|
+
switch: {
|
|
327
|
+
name: "Switch",
|
|
328
|
+
description: "Toggle switch",
|
|
329
|
+
category: "Form",
|
|
330
|
+
code: `// Switch component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
331
|
+
export { Switch } from "reever-ui";
|
|
332
|
+
`,
|
|
333
|
+
dependencies: ["@radix-ui/react-switch"]
|
|
334
|
+
},
|
|
335
|
+
progress: {
|
|
336
|
+
name: "Progress",
|
|
337
|
+
description: "Progress bar",
|
|
338
|
+
category: "Feedback",
|
|
339
|
+
code: `// Progress component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
340
|
+
export { Progress } from "reever-ui";
|
|
341
|
+
`,
|
|
342
|
+
dependencies: ["@radix-ui/react-progress"]
|
|
343
|
+
},
|
|
344
|
+
skeleton: {
|
|
345
|
+
name: "Skeleton",
|
|
346
|
+
description: "Loading skeleton",
|
|
347
|
+
category: "Feedback",
|
|
348
|
+
code: `// Skeleton component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
349
|
+
export { Skeleton } from "reever-ui";
|
|
350
|
+
`
|
|
351
|
+
},
|
|
352
|
+
separator: {
|
|
353
|
+
name: "Separator",
|
|
354
|
+
description: "Visual separator",
|
|
355
|
+
category: "Core",
|
|
356
|
+
code: `// Separator component - run 'npm install reever-ui' and import from 'reever-ui'
|
|
357
|
+
export { Separator } from "reever-ui";
|
|
358
|
+
`,
|
|
359
|
+
dependencies: ["@radix-ui/react-separator"]
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
function getComponent(name) {
|
|
363
|
+
return COMPONENTS[name];
|
|
364
|
+
}
|
|
365
|
+
function getComponentDependencies(name) {
|
|
366
|
+
const component = COMPONENTS[name];
|
|
367
|
+
if (!component) return [];
|
|
368
|
+
return component.componentDependencies || [];
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// commands/add.ts
|
|
372
|
+
async function add(components, options) {
|
|
373
|
+
var _a, _b;
|
|
374
|
+
const configPath = path2.resolve(process.cwd(), "reever-ui.json");
|
|
375
|
+
if (!fs2.existsSync(configPath)) {
|
|
376
|
+
console.log(chalk2.red("Configuration not found. Run `npx reever-ui init` first."));
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
const _config = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
380
|
+
void _config;
|
|
381
|
+
const componentsDir = options.path || path2.resolve(process.cwd(), "src/components/ui");
|
|
382
|
+
let selectedComponents = components;
|
|
383
|
+
if (options.all) {
|
|
384
|
+
selectedComponents = Object.keys(COMPONENTS);
|
|
385
|
+
}
|
|
386
|
+
if (!selectedComponents.length && !options.all) {
|
|
387
|
+
const response = await prompts2({
|
|
388
|
+
type: "multiselect",
|
|
389
|
+
name: "components",
|
|
390
|
+
message: "Which components would you like to add?",
|
|
391
|
+
choices: Object.entries(COMPONENTS).map(([key, value]) => ({
|
|
392
|
+
title: value.name,
|
|
393
|
+
value: key,
|
|
394
|
+
description: value.description
|
|
395
|
+
})),
|
|
396
|
+
instructions: false,
|
|
397
|
+
hint: "- Space to select. Return to submit"
|
|
398
|
+
});
|
|
399
|
+
if (!((_a = response.components) == null ? void 0 : _a.length)) {
|
|
400
|
+
console.log(chalk2.yellow("No components selected."));
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
selectedComponents = response.components;
|
|
404
|
+
}
|
|
405
|
+
const invalidComponents = selectedComponents.filter((c) => !COMPONENTS[c]);
|
|
406
|
+
if (invalidComponents.length) {
|
|
407
|
+
console.log(
|
|
408
|
+
chalk2.red(`Unknown components: ${invalidComponents.join(", ")}`)
|
|
409
|
+
);
|
|
410
|
+
console.log(`Run ${chalk2.cyan("npx reever-ui list")} to see available components.`);
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
const allDependencies = /* @__PURE__ */ new Set();
|
|
414
|
+
for (const comp of selectedComponents) {
|
|
415
|
+
const deps = getComponentDependencies(comp);
|
|
416
|
+
deps.forEach((d) => allDependencies.add(d));
|
|
417
|
+
allDependencies.add(comp);
|
|
418
|
+
}
|
|
419
|
+
const toInstall = Array.from(allDependencies);
|
|
420
|
+
const existing = toInstall.filter((c) => {
|
|
421
|
+
const componentPath = path2.join(componentsDir, `${c}.tsx`);
|
|
422
|
+
return fs2.existsSync(componentPath);
|
|
423
|
+
});
|
|
424
|
+
if (existing.length && !options.overwrite && !options.yes) {
|
|
425
|
+
const response = await prompts2({
|
|
426
|
+
type: "confirm",
|
|
427
|
+
name: "overwrite",
|
|
428
|
+
message: `The following components already exist: ${existing.join(", ")}. Overwrite?`,
|
|
429
|
+
initial: false
|
|
430
|
+
});
|
|
431
|
+
if (!response.overwrite) {
|
|
432
|
+
const filtered = toInstall.filter((c) => !existing.includes(c));
|
|
433
|
+
if (!filtered.length) {
|
|
434
|
+
console.log(chalk2.yellow("No new components to add."));
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (!fs2.existsSync(componentsDir)) {
|
|
440
|
+
fs2.mkdirSync(componentsDir, { recursive: true });
|
|
441
|
+
}
|
|
442
|
+
const spinner = ora2("Adding components...").start();
|
|
443
|
+
try {
|
|
444
|
+
const added = [];
|
|
445
|
+
const npmDependencies = /* @__PURE__ */ new Set();
|
|
446
|
+
for (const componentName of toInstall) {
|
|
447
|
+
const component = getComponent(componentName);
|
|
448
|
+
if (!component) continue;
|
|
449
|
+
const componentPath = path2.join(componentsDir, `${componentName}.tsx`);
|
|
450
|
+
fs2.writeFileSync(componentPath, component.code);
|
|
451
|
+
added.push(componentName);
|
|
452
|
+
(_b = component.dependencies) == null ? void 0 : _b.forEach((dep) => npmDependencies.add(dep));
|
|
453
|
+
spinner.text = `Added ${componentName}`;
|
|
454
|
+
}
|
|
455
|
+
spinner.succeed(`Added ${added.length} component(s)`);
|
|
456
|
+
if (npmDependencies.size > 0) {
|
|
457
|
+
console.log();
|
|
458
|
+
console.log(chalk2.cyan("Install required dependencies:"));
|
|
459
|
+
console.log(` npm install ${Array.from(npmDependencies).join(" ")}`);
|
|
460
|
+
}
|
|
461
|
+
console.log();
|
|
462
|
+
console.log(chalk2.green("\u2713 Components added successfully!"));
|
|
463
|
+
} catch (error) {
|
|
464
|
+
spinner.fail("Failed to add components");
|
|
465
|
+
console.error(error);
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// commands/list.ts
|
|
471
|
+
import chalk3 from "chalk";
|
|
472
|
+
async function list(options) {
|
|
473
|
+
let componentsList = Object.entries(COMPONENTS);
|
|
474
|
+
if (options.category) {
|
|
475
|
+
componentsList = componentsList.filter(
|
|
476
|
+
([_, value]) => value.category === options.category
|
|
477
|
+
);
|
|
478
|
+
if (!componentsList.length) {
|
|
479
|
+
console.log(chalk3.yellow(`No components found in category: ${options.category}`));
|
|
480
|
+
console.log(`Available categories: ${CATEGORIES.join(", ")}`);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (options.json) {
|
|
485
|
+
const output = componentsList.reduce((acc, [key, value]) => {
|
|
486
|
+
acc[key] = {
|
|
487
|
+
name: value.name,
|
|
488
|
+
description: value.description,
|
|
489
|
+
category: value.category,
|
|
490
|
+
dependencies: value.dependencies
|
|
491
|
+
};
|
|
492
|
+
return acc;
|
|
493
|
+
}, {});
|
|
494
|
+
console.log(JSON.stringify(output, null, 2));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
console.log();
|
|
498
|
+
console.log(chalk3.bold("Available Components"));
|
|
499
|
+
console.log();
|
|
500
|
+
const grouped = componentsList.reduce((acc, [key, value]) => {
|
|
501
|
+
const cat = value.category || "Other";
|
|
502
|
+
if (!acc[cat]) acc[cat] = [];
|
|
503
|
+
acc[cat].push({ key, ...value });
|
|
504
|
+
return acc;
|
|
505
|
+
}, {});
|
|
506
|
+
for (const [category, components] of Object.entries(grouped)) {
|
|
507
|
+
console.log(chalk3.cyan.bold(` ${category}`));
|
|
508
|
+
for (const comp of components) {
|
|
509
|
+
console.log(` ${chalk3.green(comp.key.padEnd(20))} ${chalk3.dim(comp.description)}`);
|
|
510
|
+
}
|
|
511
|
+
console.log();
|
|
512
|
+
}
|
|
513
|
+
console.log(chalk3.dim(`Total: ${componentsList.length} components`));
|
|
514
|
+
console.log();
|
|
515
|
+
console.log(`Run ${chalk3.cyan("npx reever-ui add <component>")} to add a component.`);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// commands/diff.ts
|
|
519
|
+
import * as fs3 from "fs";
|
|
520
|
+
import * as path3 from "path";
|
|
521
|
+
import chalk4 from "chalk";
|
|
522
|
+
import { diffLines } from "diff";
|
|
523
|
+
async function diff(components) {
|
|
524
|
+
const configPath = path3.resolve(process.cwd(), "reever-ui.json");
|
|
525
|
+
if (!fs3.existsSync(configPath)) {
|
|
526
|
+
console.log(chalk4.red("Configuration not found. Run `npx reever-ui init` first."));
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
const componentsDir = path3.resolve(process.cwd(), "src/components/ui");
|
|
530
|
+
let toCheck = components;
|
|
531
|
+
if (!toCheck.length) {
|
|
532
|
+
toCheck = Object.keys(COMPONENTS).filter((c) => {
|
|
533
|
+
const componentPath = path3.join(componentsDir, `${c}.tsx`);
|
|
534
|
+
return fs3.existsSync(componentPath);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
if (!toCheck.length) {
|
|
538
|
+
console.log(chalk4.yellow("No components to compare."));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
console.log();
|
|
542
|
+
console.log(chalk4.bold("Component Differences"));
|
|
543
|
+
console.log();
|
|
544
|
+
let hasChanges = false;
|
|
545
|
+
for (const componentName of toCheck) {
|
|
546
|
+
const component = getComponent(componentName);
|
|
547
|
+
if (!component) {
|
|
548
|
+
console.log(chalk4.yellow(`Unknown component: ${componentName}`));
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
const componentPath = path3.join(componentsDir, `${componentName}.tsx`);
|
|
552
|
+
if (!fs3.existsSync(componentPath)) {
|
|
553
|
+
console.log(chalk4.yellow(`${componentName}: Not installed`));
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
const localCode = fs3.readFileSync(componentPath, "utf-8");
|
|
557
|
+
const upstreamCode = component.code;
|
|
558
|
+
if (localCode === upstreamCode) {
|
|
559
|
+
console.log(chalk4.green(`${componentName}: Up to date`));
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
hasChanges = true;
|
|
563
|
+
console.log(chalk4.yellow(`${componentName}: Modified`));
|
|
564
|
+
const changes = diffLines(upstreamCode, localCode);
|
|
565
|
+
for (const change of changes) {
|
|
566
|
+
if (change.added) {
|
|
567
|
+
process.stdout.write(chalk4.green(`+ ${change.value}`));
|
|
568
|
+
} else if (change.removed) {
|
|
569
|
+
process.stdout.write(chalk4.red(`- ${change.value}`));
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
console.log();
|
|
573
|
+
}
|
|
574
|
+
if (!hasChanges) {
|
|
575
|
+
console.log();
|
|
576
|
+
console.log(chalk4.green("\u2713 All components are up to date!"));
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// index.ts
|
|
581
|
+
var packageJson = require_package();
|
|
582
|
+
var program = new Command();
|
|
583
|
+
program.name("reever-ui").description("CLI tool for reever-ui component library").version(packageJson.version);
|
|
584
|
+
program.command("init").description("Initialize reever-ui in your project").option("-y, --yes", "Skip confirmation prompt").option("--overwrite", "Overwrite existing configuration").action(init);
|
|
585
|
+
program.command("add").description("Add components to your project").argument("[components...]", "Components to add").option("-a, --all", "Add all available components").option("-y, --yes", "Skip confirmation prompt").option("-o, --overwrite", "Overwrite existing components").option("-p, --path <path>", "Custom component path").action(add);
|
|
586
|
+
program.command("list").description("List all available components").option("-c, --category <category>", "Filter by category").option("--json", "Output as JSON").action(list);
|
|
587
|
+
program.command("diff").description("Show differences with upstream components").argument("[components...]", "Components to diff").action(diff);
|
|
588
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reeverdev/ui-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool for Reever UI component library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"reever-ui": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup index.ts --format esm",
|
|
14
|
+
"dev": "tsx index.ts"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@types/diff": "^7.0.2",
|
|
18
|
+
"chalk": "^5.3.0",
|
|
19
|
+
"commander": "^12.1.0",
|
|
20
|
+
"diff": "^8.0.2",
|
|
21
|
+
"fs-extra": "^11.2.0",
|
|
22
|
+
"ora": "^8.0.1",
|
|
23
|
+
"prompts": "^2.4.2"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/fs-extra": "^11.0.4",
|
|
27
|
+
"@types/prompts": "^2.4.9",
|
|
28
|
+
"tsup": "^8.0.0",
|
|
29
|
+
"tsx": "^4.7.0",
|
|
30
|
+
"typescript": "^5.3.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"reever-ui",
|
|
34
|
+
"cli",
|
|
35
|
+
"components",
|
|
36
|
+
"react",
|
|
37
|
+
"tailwindcss"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/reeverdev/ui.git",
|
|
42
|
+
"directory": "cli"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/reeverdev/ui#readme",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"license": "MIT"
|
|
49
|
+
}
|