pejay-ui 1.3.4 ā 1.4.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/README.md +59 -1
- package/bin/cli.js +294 -22
- package/package.json +2 -2
- package/registry/buttons.json +9 -0
- package/registry/dropdowns.json +28 -0
- package/registry/forms.json +322 -0
- package/registry/layouts.json +18 -0
- package/registry/overlays.json +8 -0
- package/registry/scaffolds.json +83 -0
- package/registry/toast.json +10 -0
- package/templates/overlays/index.ts +1 -0
- package/templates/overlays/portal.tsx +26 -0
- package/templates/toast/README.md +183 -0
- package/templates/toast/container.tsx +320 -0
- package/templates/toast/index.ts +4 -0
- package/templates/toast/store.ts +35 -0
- package/templates/toast/toast.ts +54 -0
- package/templates/toast/types.ts +15 -0
- package/registry.json +0 -256
package/README.md
CHANGED
|
@@ -11,14 +11,55 @@ npx pejay-ui init
|
|
|
11
11
|
|
|
12
12
|
### 2. Add Component
|
|
13
13
|
```bash
|
|
14
|
-
npx pejay-ui add <component-name>
|
|
14
|
+
npx pejay-ui add <component-name-or-category> [options]
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
**Options:**
|
|
18
|
+
- `--all`: Install all components in the specified category.
|
|
19
|
+
- `--select`: Interactively select which components to install from the specified category.
|
|
20
|
+
|
|
21
|
+
**Examples:**
|
|
22
|
+
- Install a single component directly:
|
|
23
|
+
```bash
|
|
24
|
+
npx pejay-ui add form/input
|
|
25
|
+
```
|
|
26
|
+
- Install all components in a category (e.g., `form`):
|
|
27
|
+
```bash
|
|
28
|
+
npx pejay-ui add form --all
|
|
29
|
+
```
|
|
30
|
+
- Select specific components to install from a category (e.g., `form`):
|
|
31
|
+
```bash
|
|
32
|
+
npx pejay-ui add form --select
|
|
33
|
+
```
|
|
34
|
+
*(Note: Running `npx pejay-ui add <category>` without options will default to the interactive selection prompt).*
|
|
35
|
+
|
|
36
|
+
**Automatic Exports (Auto-Indexing):**
|
|
37
|
+
Installing components automatically generates or updates `index.ts` (or `index.js`) files at:
|
|
38
|
+
1. The category level (e.g., `src/pejay-ui/components/form/index.ts`)
|
|
39
|
+
2. The global components level (`src/pejay-ui/components/index.ts`)
|
|
40
|
+
|
|
41
|
+
This allows you to easily import multiple components:
|
|
42
|
+
```typescript
|
|
43
|
+
import { Input, Checkbox, AmountInput } from "@/pejay-ui/components";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Component-Specific Documentation (READMEs):**
|
|
47
|
+
Certain components (like `toast`) ship with localized `README.md` guides. When you install them, the CLI automatically copies their detailed usage documentation directly into the component's folder (e.g., `src/pejay-ui/components/toast/README.md`) so you have helper docs right next to the code.
|
|
48
|
+
|
|
17
49
|
### 3. Remove Component
|
|
18
50
|
```bash
|
|
19
51
|
npx pejay-ui remove <component-name>
|
|
20
52
|
```
|
|
21
53
|
|
|
54
|
+
### 4. Check Components Status
|
|
55
|
+
```bash
|
|
56
|
+
npx pejay-ui status
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Lists all available components categorized, showing their local installation status:
|
|
60
|
+
- Installed components are marked with a green `[ā]`.
|
|
61
|
+
- Uninstalled components are marked with `[ ]`.
|
|
62
|
+
|
|
22
63
|
---
|
|
23
64
|
|
|
24
65
|
## Available Components & Scaffolds
|
|
@@ -46,6 +87,7 @@ npx pejay-ui add form/switch
|
|
|
46
87
|
npx pejay-ui add form/textarea
|
|
47
88
|
npx pejay-ui add form/url-input
|
|
48
89
|
```
|
|
90
|
+
*(Supports category-wide commands: `npx pejay-ui add form --all` or `npx pejay-ui add form --select`)*
|
|
49
91
|
|
|
50
92
|
### Date & Time Pickers
|
|
51
93
|
```bash
|
|
@@ -54,17 +96,32 @@ npx pejay-ui add form/date-range-picker
|
|
|
54
96
|
npx pejay-ui add form/time-picker
|
|
55
97
|
npx pejay-ui add form/time-range-picker
|
|
56
98
|
```
|
|
99
|
+
*(Supports category-wide commands: `npx pejay-ui add form --all` or `npx pejay-ui add form --select`)*
|
|
57
100
|
|
|
58
101
|
### Dropdowns & Selects
|
|
59
102
|
```bash
|
|
60
103
|
npx pejay-ui add dropdown/select-input
|
|
61
104
|
npx pejay-ui add dropdown/multiselect-input
|
|
62
105
|
```
|
|
106
|
+
*(Supports category-wide commands: `npx pejay-ui add dropdown --all` or `npx pejay-ui add dropdown --select`)*
|
|
63
107
|
|
|
64
108
|
### Layouts
|
|
65
109
|
```bash
|
|
66
110
|
npx pejay-ui add layouts/lv1
|
|
67
111
|
```
|
|
112
|
+
*(Supports category-wide commands: `npx pejay-ui add layouts --all` or `npx pejay-ui add layouts --select`)*
|
|
113
|
+
|
|
114
|
+
### Toast
|
|
115
|
+
```bash
|
|
116
|
+
npx pejay-ui add toast
|
|
117
|
+
```
|
|
118
|
+
*(Includes a localized `README.md` guide copied directly into your components folder).*
|
|
119
|
+
|
|
120
|
+
### Overlays
|
|
121
|
+
```bash
|
|
122
|
+
npx pejay-ui add overlays/portal
|
|
123
|
+
```
|
|
124
|
+
*(Supports category-wide commands: `npx pejay-ui add overlays --all` or `npx pejay-ui add overlays --select`)*
|
|
68
125
|
|
|
69
126
|
### Scaffolds & Templates
|
|
70
127
|
```bash
|
|
@@ -75,3 +132,4 @@ npx pejay-ui add axios-client
|
|
|
75
132
|
npx pejay-ui add redux-store-client
|
|
76
133
|
npx pejay-ui add rtk-query-client
|
|
77
134
|
```
|
|
135
|
+
*(Supports category-wide commands: `npx pejay-ui add scaffold --all` or `npx pejay-ui add scaffold --select`)*
|
package/bin/cli.js
CHANGED
|
@@ -38,14 +38,37 @@ const getFilesRecursively = async (dir) => {
|
|
|
38
38
|
return results;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
const loadRegistry = async () => {
|
|
42
|
+
const registryDir = path.join(packageRoot, "registry");
|
|
43
|
+
if (!await fs.pathExists(registryDir)) {
|
|
44
|
+
console.error(`Error: Registry directory not found at ${registryDir}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const files = await fs.readdir(registryDir);
|
|
48
|
+
const registry = {};
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
if (file.endsWith(".json")) {
|
|
51
|
+
const filePath = path.join(registryDir, file);
|
|
52
|
+
try {
|
|
53
|
+
const data = await fs.readJSON(filePath);
|
|
54
|
+
Object.assign(registry, data);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.error(`Error reading registry file: ${file}`, e);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return registry;
|
|
61
|
+
};
|
|
62
|
+
const pkg = await fs.readJSON(path.join(packageRoot, "package.json"));
|
|
63
|
+
|
|
41
64
|
program
|
|
42
65
|
.name("pejay-ui")
|
|
43
66
|
.description("CLI to initialize, add, and remove React UI components")
|
|
44
|
-
.version(
|
|
67
|
+
.version(pkg.version);
|
|
45
68
|
|
|
46
69
|
/* =============================
|
|
47
70
|
INIT COMMAND
|
|
48
|
-
============================= */
|
|
71
|
+
============================= */
|
|
49
72
|
program
|
|
50
73
|
.command("init")
|
|
51
74
|
.description("Initialize pejay-ui configuration in your project")
|
|
@@ -70,11 +93,13 @@ program
|
|
|
70
93
|
|
|
71
94
|
/* =============================
|
|
72
95
|
ADD COMMAND
|
|
73
|
-
============================= */
|
|
96
|
+
============================= */
|
|
74
97
|
program
|
|
75
98
|
.command("add <component>")
|
|
76
99
|
.description("Add a component to your project")
|
|
77
|
-
.
|
|
100
|
+
.option("--all", "Add all components in the category")
|
|
101
|
+
.option("--select", "Select specific components from the category to add")
|
|
102
|
+
.action(async (component, options) => {
|
|
78
103
|
try {
|
|
79
104
|
const cwd = process.cwd();
|
|
80
105
|
const configPath = path.join(cwd, "pejay-ui.json");
|
|
@@ -85,15 +110,75 @@ program
|
|
|
85
110
|
}
|
|
86
111
|
|
|
87
112
|
const config = await fs.readJSON(configPath);
|
|
88
|
-
const
|
|
113
|
+
const registry = await loadRegistry();
|
|
114
|
+
const isTsProject = await fs.pathExists(path.join(cwd, "tsconfig.json"));
|
|
89
115
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
116
|
+
// Determine which components to install
|
|
117
|
+
let selectedComponents = [];
|
|
118
|
+
|
|
119
|
+
// Determine if the input refers to a category that supports category-wide operations
|
|
120
|
+
const categorySupportMap = {};
|
|
121
|
+
for (const [key, compData] of Object.entries(registry)) {
|
|
122
|
+
if (compData.category && compData.supportsCategory) {
|
|
123
|
+
categorySupportMap[compData.category.toLowerCase()] = compData.category;
|
|
124
|
+
}
|
|
93
125
|
}
|
|
94
126
|
|
|
95
|
-
const
|
|
96
|
-
|
|
127
|
+
const getCategoryFromInput = (input, supportMap) => {
|
|
128
|
+
const normInput = input.toLowerCase().trim().replace(/s$/, "");
|
|
129
|
+
for (const [normCat, originalCat] of Object.entries(supportMap)) {
|
|
130
|
+
const normCatSingular = normCat.replace(/s$/, "");
|
|
131
|
+
if (normInput === normCatSingular || (normInput === "dropdown" && normCatSingular === "select-dropdown")) {
|
|
132
|
+
return originalCat;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const targetCategory = getCategoryFromInput(component, categorySupportMap);
|
|
139
|
+
const isExactComponent = !!registry[component];
|
|
140
|
+
|
|
141
|
+
if (targetCategory && (!isExactComponent || options.all || options.select)) {
|
|
142
|
+
// Treat as category installation
|
|
143
|
+
const categoryComponents = Object.keys(registry).filter(
|
|
144
|
+
(key) => registry[key].category === targetCategory
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (categoryComponents.length === 0) {
|
|
148
|
+
console.error(`Error: Category '${component}' has no components in the registry.`);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (options.all) {
|
|
153
|
+
selectedComponents = categoryComponents;
|
|
154
|
+
} else {
|
|
155
|
+
// Dynamic prompt using inquirer checkbox for --select or when no flag is specified for category
|
|
156
|
+
const answers = await prompt([
|
|
157
|
+
{
|
|
158
|
+
type: "checkbox",
|
|
159
|
+
name: "components",
|
|
160
|
+
message: `Select components from category "${targetCategory}" to add:`,
|
|
161
|
+
choices: categoryComponents.map((key) => ({
|
|
162
|
+
name: `${registry[key].name} (${key})`,
|
|
163
|
+
value: key,
|
|
164
|
+
})),
|
|
165
|
+
},
|
|
166
|
+
]);
|
|
167
|
+
selectedComponents = answers.components;
|
|
168
|
+
if (selectedComponents.length === 0) {
|
|
169
|
+
console.log("No components selected. Exiting.");
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// Not a category (or exact component targeted without category flags), treat as a single component key
|
|
175
|
+
if (!isExactComponent) {
|
|
176
|
+
console.error(`Error: Component or Category '${component}' not found in registry.`);
|
|
177
|
+
console.log(`Available categories/components: ${Array.from(new Set(Object.values(registry).map(c => c.category).filter(Boolean))).join(", ")} or ${Object.keys(registry).join(", ")}`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
selectedComponents = [component];
|
|
181
|
+
}
|
|
97
182
|
|
|
98
183
|
// Track all components to install (including dependencies) in topological/order of dependencies
|
|
99
184
|
const installQueue = [];
|
|
@@ -106,7 +191,6 @@ program
|
|
|
106
191
|
const compData = registry[compName];
|
|
107
192
|
if (!compData) {
|
|
108
193
|
console.error(`Error: Component '${compName}' not found in registry.`);
|
|
109
|
-
console.log(`Available components: ${Object.keys(registry).join(", ")}`);
|
|
110
194
|
process.exit(1);
|
|
111
195
|
}
|
|
112
196
|
|
|
@@ -120,13 +204,15 @@ program
|
|
|
120
204
|
installQueue.push(compName);
|
|
121
205
|
};
|
|
122
206
|
|
|
123
|
-
|
|
207
|
+
for (const comp of selectedComponents) {
|
|
208
|
+
resolveDependencies(comp);
|
|
209
|
+
}
|
|
124
210
|
|
|
125
211
|
console.log("\nš Starting installation...\n");
|
|
126
212
|
|
|
127
213
|
for (const compToInstall of installQueue) {
|
|
128
|
-
// Skip if already marked as installed in config (unless it is the
|
|
129
|
-
if (config.installed?.[compToInstall] && compToInstall
|
|
214
|
+
// Skip if already marked as installed in config (unless it is one of the explicitly requested components)
|
|
215
|
+
if (config.installed?.[compToInstall] && !selectedComponents.includes(compToInstall)) {
|
|
130
216
|
console.log(`Component '${compToInstall}' is already installed. Skipping dependency installation.`);
|
|
131
217
|
continue;
|
|
132
218
|
}
|
|
@@ -293,6 +379,56 @@ program
|
|
|
293
379
|
}
|
|
294
380
|
}
|
|
295
381
|
|
|
382
|
+
// 3.5 Automatically generate/update category-level and global index.ts/index.js files
|
|
383
|
+
if (componentData.category && !["scaffold", "scaffolds", "script", "scripts"].includes(componentData.category.toLowerCase())) {
|
|
384
|
+
const indexExt = isTsProject ? "ts" : "js";
|
|
385
|
+
const filesInDir = await fs.readdir(targetDir);
|
|
386
|
+
const exportableFiles = [];
|
|
387
|
+
|
|
388
|
+
for (const file of filesInDir) {
|
|
389
|
+
const filePath = path.join(targetDir, file);
|
|
390
|
+
const stat = await fs.stat(filePath);
|
|
391
|
+
if (stat.isFile()) {
|
|
392
|
+
const ext = path.extname(file);
|
|
393
|
+
const name = path.basename(file, ext);
|
|
394
|
+
if ((ext === ".tsx" || ext === ".ts" || ext === ".jsx" || ext === ".js") && name !== "index") {
|
|
395
|
+
exportableFiles.push(name);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (exportableFiles.length > 0) {
|
|
401
|
+
exportableFiles.sort();
|
|
402
|
+
const indexFilePath = path.join(targetDir, `index.${indexExt}`);
|
|
403
|
+
const exportLines = exportableFiles.map(name => `export * from "./${name}";`);
|
|
404
|
+
await fs.writeFile(indexFilePath, exportLines.join("\n") + "\n", "utf-8");
|
|
405
|
+
console.log(`ā
Updated index.${indexExt} in ${path.relative(cwd, targetDir)}`);
|
|
406
|
+
|
|
407
|
+
// Also update the global components index file
|
|
408
|
+
const componentsDir = path.dirname(targetDir); // src/pejay-ui/components
|
|
409
|
+
if (await fs.pathExists(componentsDir)) {
|
|
410
|
+
const categories = await fs.readdir(componentsDir);
|
|
411
|
+
const validCategories = [];
|
|
412
|
+
for (const cat of categories) {
|
|
413
|
+
const catDir = path.join(componentsDir, cat);
|
|
414
|
+
const catStat = await fs.stat(catDir);
|
|
415
|
+
if (catStat.isDirectory()) {
|
|
416
|
+
if (await fs.pathExists(path.join(catDir, `index.ts`)) || await fs.pathExists(path.join(catDir, `index.js`))) {
|
|
417
|
+
validCategories.push(cat);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (validCategories.length > 0) {
|
|
422
|
+
validCategories.sort();
|
|
423
|
+
const globalIndexFile = path.join(componentsDir, `index.${indexExt}`);
|
|
424
|
+
const globalExportLines = validCategories.map(cat => `export * from "./${cat}";`);
|
|
425
|
+
await fs.writeFile(globalIndexFile, globalExportLines.join("\n") + "\n", "utf-8");
|
|
426
|
+
console.log(`ā
Updated global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
296
432
|
// 4. Update State tracking in config
|
|
297
433
|
config.installed = config.installed || {};
|
|
298
434
|
config.installed[compToInstall] = {
|
|
@@ -326,14 +462,7 @@ program
|
|
|
326
462
|
}
|
|
327
463
|
|
|
328
464
|
const config = await fs.readJSON(configPath);
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
if (!await fs.pathExists(registryPath)) {
|
|
332
|
-
console.error("Error: Registry configuration not found.");
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const registry = await fs.readJSON(registryPath);
|
|
465
|
+
const registry = await loadRegistry();
|
|
337
466
|
const componentData = registry[component];
|
|
338
467
|
|
|
339
468
|
if (!componentData) {
|
|
@@ -358,6 +487,73 @@ program
|
|
|
358
487
|
}
|
|
359
488
|
}
|
|
360
489
|
|
|
490
|
+
// 1.5 Update index files
|
|
491
|
+
if (componentData.category && !["scaffold", "scaffolds", "script", "scripts"].includes(componentData.category.toLowerCase())) {
|
|
492
|
+
const isTsProject = await fs.pathExists(path.join(cwd, "tsconfig.json"));
|
|
493
|
+
const targetDir = path.join(cwd, config.baseDir, "components", componentData.category);
|
|
494
|
+
const indexExt = isTsProject ? "ts" : "js";
|
|
495
|
+
|
|
496
|
+
if (await fs.pathExists(targetDir)) {
|
|
497
|
+
const filesInDir = await fs.readdir(targetDir);
|
|
498
|
+
const exportableFiles = [];
|
|
499
|
+
|
|
500
|
+
for (const file of filesInDir) {
|
|
501
|
+
const filePath = path.join(targetDir, file);
|
|
502
|
+
const stat = await fs.stat(filePath);
|
|
503
|
+
if (stat.isFile()) {
|
|
504
|
+
const ext = path.extname(file);
|
|
505
|
+
const name = path.basename(file, ext);
|
|
506
|
+
if ((ext === ".tsx" || ext === ".ts" || ext === ".jsx" || ext === ".js") && name !== "index") {
|
|
507
|
+
exportableFiles.push(name);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const indexFilePath = path.join(targetDir, `index.${indexExt}`);
|
|
513
|
+
if (exportableFiles.length > 0) {
|
|
514
|
+
exportableFiles.sort();
|
|
515
|
+
const exportLines = exportableFiles.map(name => `export * from "./${name}";`);
|
|
516
|
+
await fs.writeFile(indexFilePath, exportLines.join("\n") + "\n", "utf-8");
|
|
517
|
+
console.log(`ā
Updated index.${indexExt} in ${path.relative(cwd, targetDir)}`);
|
|
518
|
+
} else {
|
|
519
|
+
// No files left, delete the category index file
|
|
520
|
+
if (await fs.pathExists(indexFilePath)) {
|
|
521
|
+
await fs.remove(indexFilePath);
|
|
522
|
+
console.log(`šļø Removed empty index.${indexExt} in ${path.relative(cwd, targetDir)}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Also update the global components index file
|
|
527
|
+
const componentsDir = path.dirname(targetDir);
|
|
528
|
+
if (await fs.pathExists(componentsDir)) {
|
|
529
|
+
const categories = await fs.readdir(componentsDir);
|
|
530
|
+
const validCategories = [];
|
|
531
|
+
for (const cat of categories) {
|
|
532
|
+
const catDir = path.join(componentsDir, cat);
|
|
533
|
+
const catStat = await fs.stat(catDir);
|
|
534
|
+
if (catStat.isDirectory()) {
|
|
535
|
+
if (await fs.pathExists(path.join(catDir, `index.ts`)) || await fs.pathExists(path.join(catDir, `index.js`))) {
|
|
536
|
+
validCategories.push(cat);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const globalIndexFile = path.join(componentsDir, `index.${indexExt}`);
|
|
541
|
+
if (validCategories.length > 0) {
|
|
542
|
+
validCategories.sort();
|
|
543
|
+
const globalExportLines = validCategories.map(cat => `export * from "./${cat}";`);
|
|
544
|
+
await fs.writeFile(globalIndexFile, globalExportLines.join("\n") + "\n", "utf-8");
|
|
545
|
+
console.log(`ā
Updated global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
|
|
546
|
+
} else {
|
|
547
|
+
// No categories left with index files, remove the global index
|
|
548
|
+
if (await fs.pathExists(globalIndexFile)) {
|
|
549
|
+
await fs.remove(globalIndexFile);
|
|
550
|
+
console.log(`šļø Removed empty global index.${indexExt} in ${path.relative(cwd, componentsDir)}`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
361
557
|
// 2. Build Utility Usage Map
|
|
362
558
|
const utilityUsage = {};
|
|
363
559
|
for (const [compName, compInfo] of Object.entries(config.installed)) {
|
|
@@ -452,4 +648,80 @@ program
|
|
|
452
648
|
}
|
|
453
649
|
});
|
|
454
650
|
|
|
651
|
+
/* =============================
|
|
652
|
+
STATUS COMMAND
|
|
653
|
+
============================= */
|
|
654
|
+
program
|
|
655
|
+
.command("status")
|
|
656
|
+
.description("List all available components and check their installation status")
|
|
657
|
+
.action(async () => {
|
|
658
|
+
try {
|
|
659
|
+
const cwd = process.cwd();
|
|
660
|
+
const configPath = path.join(cwd, "pejay-ui.json");
|
|
661
|
+
|
|
662
|
+
let config = { installed: {} };
|
|
663
|
+
let hasConfig = true;
|
|
664
|
+
|
|
665
|
+
if (!await fs.pathExists(configPath)) {
|
|
666
|
+
hasConfig = false;
|
|
667
|
+
} else {
|
|
668
|
+
try {
|
|
669
|
+
config = await fs.readJSON(configPath);
|
|
670
|
+
} catch (e) {
|
|
671
|
+
hasConfig = false;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
const registry = await loadRegistry();
|
|
676
|
+
|
|
677
|
+
// Terminal styling colors
|
|
678
|
+
const GREEN = "\x1b[32m";
|
|
679
|
+
const CYAN = "\x1b[36m";
|
|
680
|
+
const DIM = "\x1b[2m";
|
|
681
|
+
const RESET = "\x1b[0m";
|
|
682
|
+
const YELLOW = "\x1b[33m";
|
|
683
|
+
|
|
684
|
+
console.log(`\nš ${CYAN}pejay-ui Components Status:${RESET}\n`);
|
|
685
|
+
|
|
686
|
+
if (!hasConfig) {
|
|
687
|
+
console.log(`${YELLOW}Note: pejay-ui.json not found. Initialize first via 'npx pejay-ui init'.${RESET}`);
|
|
688
|
+
console.log(`${YELLOW}Showing all components as uninstalled.${RESET}\n`);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Group registry items by category
|
|
692
|
+
const categories = {};
|
|
693
|
+
for (const [key, compData] of Object.entries(registry)) {
|
|
694
|
+
const category = compData.category || "other";
|
|
695
|
+
if (!categories[category]) {
|
|
696
|
+
categories[category] = [];
|
|
697
|
+
}
|
|
698
|
+
categories[category].push({
|
|
699
|
+
key,
|
|
700
|
+
name: compData.name,
|
|
701
|
+
installed: !!config.installed?.[key]
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Print categories and components sorted alphabetically
|
|
706
|
+
const sortedCategoryNames = Object.keys(categories).sort();
|
|
707
|
+
for (const cat of sortedCategoryNames) {
|
|
708
|
+
console.log(`${CYAN}Category: ${cat}${RESET}`);
|
|
709
|
+
const comps = categories[cat];
|
|
710
|
+
comps.sort((a, b) => a.name.localeCompare(b.name));
|
|
711
|
+
|
|
712
|
+
for (const comp of comps) {
|
|
713
|
+
if (comp.installed) {
|
|
714
|
+
console.log(` ${GREEN}[ā] ${comp.name}${RESET} ${DIM}(${comp.key})${RESET}`);
|
|
715
|
+
} else {
|
|
716
|
+
console.log(` [ ] ${comp.name} ${DIM}(${comp.key})${RESET}`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
console.log(); // blank line between categories
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
} catch (err) {
|
|
723
|
+
console.error("\nā Status display failed\n", err);
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
|
|
455
727
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pejay-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "react ui components",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"templates/",
|
|
12
12
|
"utils/",
|
|
13
|
-
"registry
|
|
13
|
+
"registry/"
|
|
14
14
|
],
|
|
15
15
|
"keywords": [
|
|
16
16
|
"react",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dropdown/select-input": {
|
|
3
|
+
"name": "SelectInput",
|
|
4
|
+
"category": "select-dropdown",
|
|
5
|
+
"files": ["templates/select-dropdown/select-input.tsx"],
|
|
6
|
+
"utils": ["cn.ts"],
|
|
7
|
+
"peerDependencies": [
|
|
8
|
+
"clsx",
|
|
9
|
+
"tailwind-merge",
|
|
10
|
+
"lucide-react",
|
|
11
|
+
"@floating-ui/react"
|
|
12
|
+
],
|
|
13
|
+
"supportsCategory": true
|
|
14
|
+
},
|
|
15
|
+
"dropdown/multiselect-input": {
|
|
16
|
+
"name": "MultiselectInput",
|
|
17
|
+
"category": "select-dropdown",
|
|
18
|
+
"files": ["templates/select-dropdown/multiselect-input.tsx"],
|
|
19
|
+
"utils": ["cn.ts"],
|
|
20
|
+
"peerDependencies": [
|
|
21
|
+
"clsx",
|
|
22
|
+
"tailwind-merge",
|
|
23
|
+
"lucide-react",
|
|
24
|
+
"@floating-ui/react"
|
|
25
|
+
],
|
|
26
|
+
"supportsCategory": true
|
|
27
|
+
}
|
|
28
|
+
}
|