omnira-ui 0.3.0 → 0.3.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/cli/omnira-init.mjs +197 -16
- package/package.json +1 -1
package/cli/omnira-init.mjs
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Omnira UI —
|
|
4
|
+
* Omnira UI — CLI
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* npx omnira-ui init Full project scaffolding
|
|
8
|
+
* npx omnira-ui add <Component> Copy a single component into your project
|
|
9
|
+
* npx omnira-ui add List all available components
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* - Theme provider → lib/theme-context.tsx
|
|
12
|
-
* - Design tokens CSS → app/globals.css
|
|
13
|
-
* - Accent overrides → omnira-overrides.css (if non-default)
|
|
14
|
-
* - Config file → omnira.config.ts
|
|
15
|
-
*
|
|
16
|
-
* Advanced components (Sidebar, Feature Cards, etc.) can be copied
|
|
17
|
-
* from the documentation site: https://ui.omnira.space
|
|
11
|
+
* The `add` command copies only the requested component folder into
|
|
12
|
+
* components/ui/ and ensures required lib utilities (cn.ts, etc.)
|
|
13
|
+
* and globals.css are present. No full scaffolding needed.
|
|
18
14
|
*/
|
|
19
15
|
|
|
20
16
|
import * as readline from "node:readline";
|
|
@@ -362,7 +358,192 @@ async function main() {
|
|
|
362
358
|
blank();
|
|
363
359
|
}
|
|
364
360
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
361
|
+
// ── Add command — copy a single component ───────────────────────────
|
|
362
|
+
|
|
363
|
+
function getAvailableComponents() {
|
|
364
|
+
const componentsDir = path.join(PKG_ROOT, "components", "ui");
|
|
365
|
+
if (!fs.existsSync(componentsDir)) return [];
|
|
366
|
+
return fs.readdirSync(componentsDir, { withFileTypes: true })
|
|
367
|
+
.filter((d) => d.isDirectory())
|
|
368
|
+
.map((d) => d.name)
|
|
369
|
+
.sort();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function listComponents() {
|
|
373
|
+
const components = getAvailableComponents();
|
|
374
|
+
|
|
375
|
+
blank();
|
|
376
|
+
log(` ${BOLD}${GREEN}✦${RESET} ${BOLD}${WHITE}Omnira UI — Available Components${RESET}`);
|
|
377
|
+
log(` ${DIM}Copy individual components into your project${RESET}`);
|
|
378
|
+
blank();
|
|
379
|
+
|
|
380
|
+
if (components.length === 0) {
|
|
381
|
+
log(` ${RED}✗${RESET} No components found. This may happen when running locally.`);
|
|
382
|
+
blank();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const cols = 3;
|
|
387
|
+
const rows = Math.ceil(components.length / cols);
|
|
388
|
+
const colWidth = 22;
|
|
389
|
+
|
|
390
|
+
for (let r = 0; r < rows; r++) {
|
|
391
|
+
let line = " ";
|
|
392
|
+
for (let c = 0; c < cols; c++) {
|
|
393
|
+
const idx = r + c * rows;
|
|
394
|
+
if (idx < components.length) {
|
|
395
|
+
line += components[idx].padEnd(colWidth);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
log(line);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
blank();
|
|
402
|
+
log(` ${DIM}Usage:${RESET} ${CYAN}npx omnira-ui add <Component>${RESET}`);
|
|
403
|
+
log(` ${DIM}Example:${RESET} ${CYAN}npx omnira-ui add Table${RESET}`);
|
|
404
|
+
log(` ${DIM}Multiple:${RESET} ${CYAN}npx omnira-ui add Table Button Badge${RESET}`);
|
|
405
|
+
blank();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function ensureLibDeps(cwd) {
|
|
409
|
+
const libFiles = ["cn.ts", "copy-to-clipboard.ts", "theme-context.tsx"];
|
|
410
|
+
const libDest = path.join(cwd, "lib");
|
|
411
|
+
let copied = 0;
|
|
412
|
+
|
|
413
|
+
for (const file of libFiles) {
|
|
414
|
+
const dest = path.join(libDest, file);
|
|
415
|
+
if (!fs.existsSync(dest)) {
|
|
416
|
+
const src = path.join(PKG_ROOT, "lib", file);
|
|
417
|
+
if (copyFile(src, dest)) {
|
|
418
|
+
log(` ${GREEN}✓${RESET} Copied ${BOLD}lib/${file}${RESET} ${DIM}(dependency)${RESET}`);
|
|
419
|
+
copied++;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Ensure globals.css exists
|
|
425
|
+
const globalsDest = path.join(cwd, "app", "globals.css");
|
|
426
|
+
if (!fs.existsSync(globalsDest)) {
|
|
427
|
+
const globalsSrc = path.join(PKG_ROOT, "app", "globals.css");
|
|
428
|
+
if (copyFile(globalsSrc, globalsDest)) {
|
|
429
|
+
log(` ${GREEN}✓${RESET} Copied ${BOLD}app/globals.css${RESET} ${DIM}(design tokens)${RESET}`);
|
|
430
|
+
copied++;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return copied;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function addComponents(componentNames) {
|
|
438
|
+
const cwd = process.cwd();
|
|
439
|
+
const available = getAvailableComponents();
|
|
440
|
+
const availableLower = available.map((c) => c.toLowerCase());
|
|
441
|
+
|
|
442
|
+
blank();
|
|
443
|
+
log(` ${BOLD}${GREEN}✦${RESET} ${BOLD}${WHITE}Omnira UI — Add Components${RESET}`);
|
|
444
|
+
blank();
|
|
445
|
+
|
|
446
|
+
let totalFiles = 0;
|
|
447
|
+
const added = [];
|
|
448
|
+
const notFound = [];
|
|
449
|
+
|
|
450
|
+
for (const name of componentNames) {
|
|
451
|
+
// Case-insensitive match
|
|
452
|
+
const idx = availableLower.indexOf(name.toLowerCase());
|
|
453
|
+
if (idx === -1) {
|
|
454
|
+
notFound.push(name);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const actualName = available[idx];
|
|
459
|
+
const src = path.join(PKG_ROOT, "components", "ui", actualName);
|
|
460
|
+
const dest = path.join(cwd, "components", "ui", actualName);
|
|
461
|
+
|
|
462
|
+
const count = copyDirRecursive(src, dest);
|
|
463
|
+
log(` ${GREEN}✓${RESET} Copied ${BOLD}${actualName}${RESET} ${DIM}(${count} files)${RESET} → ${DIM}components/ui/${actualName}/${RESET}`);
|
|
464
|
+
totalFiles += count;
|
|
465
|
+
added.push(actualName);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
for (const name of notFound) {
|
|
469
|
+
log(` ${RED}✗${RESET} Component "${name}" not found.`);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Ensure lib dependencies are present
|
|
473
|
+
if (added.length > 0) {
|
|
474
|
+
blank();
|
|
475
|
+
log(` ${DIM}Checking dependencies...${RESET}`);
|
|
476
|
+
ensureLibDeps(cwd);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
blank();
|
|
480
|
+
log(` ${DIM}─────────────────────────────────────${RESET}`);
|
|
481
|
+
blank();
|
|
482
|
+
|
|
483
|
+
if (added.length > 0) {
|
|
484
|
+
log(` ${GREEN}✓${RESET} ${BOLD}${WHITE}Added ${added.length} component${added.length > 1 ? "s" : ""} (${totalFiles} files)${RESET}`);
|
|
485
|
+
blank();
|
|
486
|
+
log(` ${BOLD}${WHITE}Usage:${RESET}`);
|
|
487
|
+
blank();
|
|
488
|
+
for (const name of added) {
|
|
489
|
+
log(` ${MAGENTA}import${RESET} { ${name} } ${MAGENTA}from${RESET} ${WHITE}"@/components/ui/${name}"${RESET};`);
|
|
490
|
+
}
|
|
491
|
+
blank();
|
|
492
|
+
|
|
493
|
+
if (!fs.existsSync(path.join(cwd, "app", "globals.css"))) {
|
|
494
|
+
log(` ${YELLOW}!${RESET} Don't forget to import ${BOLD}globals.css${RESET} in your root layout.`);
|
|
495
|
+
blank();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (notFound.length > 0) {
|
|
500
|
+
log(` ${YELLOW}!${RESET} Run ${CYAN}npx omnira-ui add${RESET} to see all available components.`);
|
|
501
|
+
blank();
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// ── Help ─────────────────────────────────────────────────────────────
|
|
506
|
+
|
|
507
|
+
function showHelp() {
|
|
508
|
+
blank();
|
|
509
|
+
log(` ${BOLD}${GREEN}✦${RESET} ${BOLD}${WHITE}Omnira UI — CLI${RESET}`);
|
|
510
|
+
log(` ${DIM}The premium glassmorphism design system${RESET}`);
|
|
511
|
+
blank();
|
|
512
|
+
log(` ${BOLD}${WHITE}Commands:${RESET}`);
|
|
513
|
+
blank();
|
|
514
|
+
log(` ${CYAN}npx omnira-ui init${RESET} Scaffold the full design system`);
|
|
515
|
+
log(` ${CYAN}npx omnira-ui add <Component>${RESET} Add a single component`);
|
|
516
|
+
log(` ${CYAN}npx omnira-ui add${RESET} List all available components`);
|
|
517
|
+
log(` ${CYAN}npx omnira-ui help${RESET} Show this help message`);
|
|
518
|
+
blank();
|
|
519
|
+
log(` ${BOLD}${WHITE}Examples:${RESET}`);
|
|
520
|
+
blank();
|
|
521
|
+
log(` ${CYAN}npx omnira-ui add Table${RESET}`);
|
|
522
|
+
log(` ${CYAN}npx omnira-ui add Button Badge Input${RESET}`);
|
|
523
|
+
log(` ${CYAN}npx omnira-ui init${RESET}`);
|
|
524
|
+
blank();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// ── Command router ──────────────────────────────────────────────────
|
|
528
|
+
|
|
529
|
+
const args = process.argv.slice(2);
|
|
530
|
+
const command = args[0]?.toLowerCase();
|
|
531
|
+
|
|
532
|
+
if (!command || command === "init") {
|
|
533
|
+
main().catch((err) => {
|
|
534
|
+
console.error(err);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
});
|
|
537
|
+
} else if (command === "add") {
|
|
538
|
+
const componentNames = args.slice(1);
|
|
539
|
+
if (componentNames.length === 0) {
|
|
540
|
+
listComponents();
|
|
541
|
+
} else {
|
|
542
|
+
addComponents(componentNames);
|
|
543
|
+
}
|
|
544
|
+
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
545
|
+
showHelp();
|
|
546
|
+
} else {
|
|
547
|
+
log(`\n ${RED}✗${RESET} Unknown command: "${command}"\n`);
|
|
548
|
+
showHelp();
|
|
549
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnira-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A premium glassmorphism design system — dark-first, glass-forward. 30+ base components, sidebar navigation, feature cards, and a CLI to scaffold your project.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design-system",
|