weloop-kosign 1.0.3 → 1.0.5
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 +8 -13
- package/package.json +1 -1
- package/scripts/cli-remote.js +117 -41
package/README.md
CHANGED
|
@@ -4,23 +4,18 @@ A modular component library built with Next.js, similar to shadcn/ui. Install on
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install clsx tailwind-merge
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Then install components using the CLI:
|
|
7
|
+
Install components directly - the CLI handles everything automatically:
|
|
14
8
|
|
|
15
9
|
```bash
|
|
16
10
|
npx weloop-kosign@latest add button
|
|
17
11
|
```
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
This will automatically:
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
- Install base dependencies (`clsx`, `tailwind-merge`, `tw-animate-css`)
|
|
16
|
+
- Create `components.json` configuration file
|
|
17
|
+
- Install CSS styles with animations
|
|
18
|
+
- Install the component and its dependencies
|
|
24
19
|
|
|
25
20
|
## Usage
|
|
26
21
|
|
|
@@ -34,7 +29,7 @@ export function MyComponent() {
|
|
|
34
29
|
}
|
|
35
30
|
```
|
|
36
31
|
|
|
37
|
-
The CLI
|
|
32
|
+
The CLI automatically handles all dependencies, configuration, and CSS setup. No manual setup required.
|
|
38
33
|
|
|
39
34
|
## Available Commands
|
|
40
35
|
|
|
@@ -50,7 +45,7 @@ See all available components:
|
|
|
50
45
|
npx weloop-kosign@latest list
|
|
51
46
|
```
|
|
52
47
|
|
|
53
|
-
Install or update CSS styles:
|
|
48
|
+
Install or update CSS styles (optional - CSS is auto-installed with components):
|
|
54
49
|
|
|
55
50
|
```bash
|
|
56
51
|
npx weloop-kosign@latest css
|
package/package.json
CHANGED
package/scripts/cli-remote.js
CHANGED
|
@@ -405,6 +405,28 @@ function hasWeloopStyles(content) {
|
|
|
405
405
|
content.includes('--system-200');
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
+
function removeDuplicateTwAnimateImports(cssContent) {
|
|
409
|
+
const twAnimatePattern = /@import\s+["']tw-animate-css["'];?\s*\n?/g;
|
|
410
|
+
const matches = cssContent.match(twAnimatePattern);
|
|
411
|
+
|
|
412
|
+
if (matches && matches.length > 1) {
|
|
413
|
+
// Remove all occurrences
|
|
414
|
+
let cleaned = cssContent.replace(twAnimatePattern, '');
|
|
415
|
+
// Add it back once after tailwindcss import
|
|
416
|
+
if (cleaned.includes('@import "tailwindcss"') || cleaned.includes("@import 'tailwindcss'")) {
|
|
417
|
+
cleaned = cleaned.replace(
|
|
418
|
+
/(@import\s+["']tailwindcss["'];?\s*\n?)/,
|
|
419
|
+
'$1@import "tw-animate-css";\n'
|
|
420
|
+
);
|
|
421
|
+
} else {
|
|
422
|
+
cleaned = '@import "tw-animate-css";\n' + cleaned;
|
|
423
|
+
}
|
|
424
|
+
return cleaned;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return cssContent;
|
|
428
|
+
}
|
|
429
|
+
|
|
408
430
|
function processTwAnimateImport(cssContent, hasTwAnimate, forceUpdate = false) {
|
|
409
431
|
const twAnimatePattern = /@import\s+["']tw-animate-css["'];?\s*\n?/g;
|
|
410
432
|
let processed = cssContent;
|
|
@@ -423,7 +445,10 @@ function processTwAnimateImport(cssContent, hasTwAnimate, forceUpdate = false) {
|
|
|
423
445
|
}
|
|
424
446
|
}
|
|
425
447
|
} else {
|
|
426
|
-
//
|
|
448
|
+
// Remove any duplicates first
|
|
449
|
+
processed = removeDuplicateTwAnimateImports(processed);
|
|
450
|
+
|
|
451
|
+
// Ensure import exists if package is installed (only if not already present)
|
|
427
452
|
if (!processed.match(/@import\s+["']tw-animate-css["'];?\s*\n?/)) {
|
|
428
453
|
if (processed.includes('@import "tailwindcss"') || processed.includes("@import 'tailwindcss'")) {
|
|
429
454
|
processed = processed.replace(
|
|
@@ -444,10 +469,27 @@ function removeTailwindImport(cssContent) {
|
|
|
444
469
|
}
|
|
445
470
|
|
|
446
471
|
function ensureTwAnimateImport(cssContent, hasTwAnimate) {
|
|
447
|
-
if (!hasTwAnimate
|
|
472
|
+
if (!hasTwAnimate) {
|
|
448
473
|
return cssContent;
|
|
449
474
|
}
|
|
450
|
-
|
|
475
|
+
|
|
476
|
+
// Remove duplicates first
|
|
477
|
+
let cleaned = removeDuplicateTwAnimateImports(cssContent);
|
|
478
|
+
|
|
479
|
+
// Check if import already exists
|
|
480
|
+
if (cleaned.match(/@import\s+["']tw-animate-css["'];?\s*\n?/)) {
|
|
481
|
+
return cleaned;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Add import after tailwindcss if it exists
|
|
485
|
+
if (cleaned.includes('@import "tailwindcss"') || cleaned.includes("@import 'tailwindcss'")) {
|
|
486
|
+
return cleaned.replace(
|
|
487
|
+
/(@import\s+["']tailwindcss["'];?\s*\n?)/,
|
|
488
|
+
'$1@import "tw-animate-css";\n'
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return '@import "tw-animate-css";\n' + cleaned;
|
|
451
493
|
}
|
|
452
494
|
|
|
453
495
|
function mergeCSSWithTailwind(existing, weloopStyles, hasTwAnimate) {
|
|
@@ -459,8 +501,12 @@ function mergeCSSWithTailwind(existing, weloopStyles, hasTwAnimate) {
|
|
|
459
501
|
const beforeTailwind = existing.substring(0, existing.indexOf(tailwindMatch[0]));
|
|
460
502
|
const afterTailwind = existing.substring(existing.indexOf(tailwindMatch[0]) + tailwindMatch[0].length);
|
|
461
503
|
|
|
504
|
+
// Check if tw-animate-css import already exists in existing or weloopStyles
|
|
505
|
+
const hasTwAnimateInExisting = existing.match(/@import\s+["']tw-animate-css["'];?\s*\n?/);
|
|
506
|
+
const hasTwAnimateInWeloop = weloopStyles.match(/@import\s+["']tw-animate-css["'];?\s*\n?/);
|
|
507
|
+
|
|
462
508
|
let importsToAdd = '';
|
|
463
|
-
if (hasTwAnimate && !
|
|
509
|
+
if (hasTwAnimate && !hasTwAnimateInExisting && !hasTwAnimateInWeloop) {
|
|
464
510
|
importsToAdd = '@import "tw-animate-css";\n';
|
|
465
511
|
}
|
|
466
512
|
|
|
@@ -504,7 +550,7 @@ async function fetchCSSFromRegistry(registryUrl) {
|
|
|
504
550
|
return await fetchText(sourceCssPath);
|
|
505
551
|
}
|
|
506
552
|
|
|
507
|
-
async function installCSSStyles(config, registryUrl, forceUpdate = false) {
|
|
553
|
+
async function installCSSStyles(config, registryUrl, forceUpdate = false, silent = false) {
|
|
508
554
|
const cssPath = config.tailwind?.css || 'app/globals.css';
|
|
509
555
|
const fullCssPath = path.join(process.cwd(), cssPath);
|
|
510
556
|
|
|
@@ -514,13 +560,17 @@ async function installCSSStyles(config, registryUrl, forceUpdate = false) {
|
|
|
514
560
|
const existingContent = fs.readFileSync(fullCssPath, 'utf-8');
|
|
515
561
|
hasWeloopStylesInFile = hasWeloopStyles(existingContent);
|
|
516
562
|
|
|
517
|
-
|
|
518
|
-
|
|
563
|
+
// If styles already exist and not forcing update, skip silently
|
|
564
|
+
if (hasWeloopStylesInFile && !forceUpdate && silent) {
|
|
565
|
+
return;
|
|
519
566
|
}
|
|
520
567
|
}
|
|
521
568
|
|
|
522
569
|
try {
|
|
523
|
-
|
|
570
|
+
if (!silent) {
|
|
571
|
+
info('Installing CSS styles...');
|
|
572
|
+
}
|
|
573
|
+
|
|
524
574
|
const cssContent = await fetchCSSFromRegistry(registryUrl);
|
|
525
575
|
ensureDirectoryExists(path.dirname(fullCssPath));
|
|
526
576
|
|
|
@@ -531,9 +581,11 @@ async function installCSSStyles(config, registryUrl, forceUpdate = false) {
|
|
|
531
581
|
if (forceUpdate && fs.existsSync(fullCssPath)) {
|
|
532
582
|
// --overwrite: Replace entire file
|
|
533
583
|
fs.writeFileSync(fullCssPath, processedCssContent);
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
584
|
+
if (!silent) {
|
|
585
|
+
success(`Overwritten ${cssPath} with Weloop styles`);
|
|
586
|
+
if (hasTwAnimate) {
|
|
587
|
+
info(` tw-animate-css import included`);
|
|
588
|
+
}
|
|
537
589
|
}
|
|
538
590
|
} else if (fs.existsSync(fullCssPath)) {
|
|
539
591
|
// Normal mode: Merge intelligently
|
|
@@ -542,28 +594,37 @@ async function installCSSStyles(config, registryUrl, forceUpdate = false) {
|
|
|
542
594
|
existing.includes('@tailwind base');
|
|
543
595
|
|
|
544
596
|
if (hasWeloopStylesInFile) {
|
|
545
|
-
// Replace existing Weloop styles
|
|
597
|
+
// Replace existing Weloop styles (only if different)
|
|
546
598
|
let weloopStyles = removeTailwindImport(processedCssContent);
|
|
547
599
|
weloopStyles = ensureTwAnimateImport(weloopStyles, hasTwAnimate);
|
|
548
600
|
const finalContent = replaceWeloopStyles(existing, weloopStyles, hasTwAnimate);
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
601
|
+
|
|
602
|
+
// Only update if content actually changed
|
|
603
|
+
if (finalContent !== existing) {
|
|
604
|
+
fs.writeFileSync(fullCssPath, finalContent);
|
|
605
|
+
if (!silent) {
|
|
606
|
+
success(`Updated ${cssPath} with Weloop styles`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// If no changes, silently skip
|
|
552
610
|
} else if (hasTailwindImport) {
|
|
553
611
|
// Merge after Tailwind imports
|
|
554
612
|
let weloopStyles = removeTailwindImport(processedCssContent);
|
|
555
613
|
weloopStyles = ensureTwAnimateImport(weloopStyles, hasTwAnimate);
|
|
556
614
|
const merged = mergeCSSWithTailwind(existing, weloopStyles, hasTwAnimate);
|
|
557
615
|
fs.writeFileSync(fullCssPath, merged);
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
616
|
+
if (!silent) {
|
|
617
|
+
success(`Updated ${cssPath} with Weloop styles`);
|
|
618
|
+
if (hasTwAnimate) {
|
|
619
|
+
info(` tw-animate-css import included`);
|
|
620
|
+
}
|
|
621
|
+
info(` Your existing styles are preserved`);
|
|
561
622
|
}
|
|
562
|
-
info(` Your existing styles are preserved`);
|
|
563
623
|
} else {
|
|
564
624
|
// No Tailwind imports, prepend everything
|
|
565
|
-
let finalCssContent = processedCssContent;
|
|
566
|
-
|
|
625
|
+
let finalCssContent = removeDuplicateTwAnimateImports(processedCssContent);
|
|
626
|
+
|
|
627
|
+
if (hasTwAnimate && !finalCssContent.match(/@import\s+["']tw-animate-css["'];?\s*\n?/)) {
|
|
567
628
|
if (finalCssContent.includes('@import "tailwindcss"')) {
|
|
568
629
|
finalCssContent = finalCssContent.replace(
|
|
569
630
|
/(@import\s+["']tailwindcss["'];?\s*\n?)/,
|
|
@@ -574,25 +635,31 @@ async function installCSSStyles(config, registryUrl, forceUpdate = false) {
|
|
|
574
635
|
}
|
|
575
636
|
}
|
|
576
637
|
fs.writeFileSync(fullCssPath, finalCssContent + '\n\n' + existing);
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
638
|
+
if (!silent) {
|
|
639
|
+
success(`Updated ${cssPath} with Weloop styles`);
|
|
640
|
+
if (hasTwAnimate) {
|
|
641
|
+
info(` tw-animate-css import included`);
|
|
642
|
+
}
|
|
580
643
|
}
|
|
581
644
|
}
|
|
582
645
|
} else {
|
|
583
646
|
// Create new file
|
|
584
647
|
fs.writeFileSync(fullCssPath, processedCssContent);
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
648
|
+
if (!silent) {
|
|
649
|
+
success(`Created ${cssPath} with Weloop styles`);
|
|
650
|
+
if (hasTwAnimate) {
|
|
651
|
+
info(` tw-animate-css import included`);
|
|
652
|
+
}
|
|
588
653
|
}
|
|
589
654
|
}
|
|
590
655
|
} catch (err) {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
656
|
+
if (!silent) {
|
|
657
|
+
warn(`Could not automatically install CSS styles: ${err.message}`);
|
|
658
|
+
info(`\n To add styles manually:`);
|
|
659
|
+
info(` 1. Download: ${registryUrl.replace('/registry', '/app/globals.css')}`);
|
|
660
|
+
info(` 2. Add the CSS variables to your ${cssPath} file`);
|
|
661
|
+
info(` 3. Or copy from: https://gitlab.com/Sophanithchrek/weloop-shadcn-next-app/-/raw/main/app/globals.css\n`);
|
|
662
|
+
}
|
|
596
663
|
}
|
|
597
664
|
}
|
|
598
665
|
|
|
@@ -615,16 +682,25 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
615
682
|
`;
|
|
616
683
|
fs.writeFileSync(utilsPath, utilsContent);
|
|
617
684
|
success(`Created ${path.relative(process.cwd(), utilsPath)}`);
|
|
618
|
-
|
|
619
|
-
// Check if required packages are installed
|
|
620
|
-
if (!checkPackageInstalled('clsx') || !checkPackageInstalled('tailwind-merge')) {
|
|
621
|
-
warn('utils.ts requires: clsx and tailwind-merge');
|
|
622
|
-
info(' Install with: npm install clsx tailwind-merge');
|
|
623
|
-
}
|
|
624
685
|
}
|
|
625
686
|
|
|
626
687
|
async function installComponent(componentName, options = {}) {
|
|
627
688
|
const { overwrite = false, registryUrl = DEFAULT_REGISTRY_URL } = options;
|
|
689
|
+
|
|
690
|
+
// Install base dependencies first (required for utils.ts)
|
|
691
|
+
const baseDeps = [];
|
|
692
|
+
if (!checkPackageInstalled('clsx')) {
|
|
693
|
+
baseDeps.push('clsx');
|
|
694
|
+
}
|
|
695
|
+
if (!checkPackageInstalled('tailwind-merge')) {
|
|
696
|
+
baseDeps.push('tailwind-merge');
|
|
697
|
+
}
|
|
698
|
+
if (baseDeps.length > 0) {
|
|
699
|
+
info(`Installing base dependencies: ${baseDeps.join(', ')}...`);
|
|
700
|
+
await installPackages(baseDeps);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Load or create components.json (after base deps are installed)
|
|
628
704
|
const config = loadComponentsConfig();
|
|
629
705
|
|
|
630
706
|
// Install tw-animate-css automatically (required for animations)
|
|
@@ -633,8 +709,8 @@ async function installComponent(componentName, options = {}) {
|
|
|
633
709
|
await installPackages(['tw-animate-css']);
|
|
634
710
|
}
|
|
635
711
|
|
|
636
|
-
// Install CSS styles early (before component installation)
|
|
637
|
-
await installCSSStyles(config, registryUrl);
|
|
712
|
+
// Install CSS styles early (before component installation) - silent if already installed
|
|
713
|
+
await installCSSStyles(config, registryUrl, false, true);
|
|
638
714
|
|
|
639
715
|
// Get paths from components.json
|
|
640
716
|
const uiAlias = config.aliases?.ui || '@/components/ui';
|
|
@@ -782,7 +858,7 @@ Examples:
|
|
|
782
858
|
case 'css':
|
|
783
859
|
case 'styles':
|
|
784
860
|
const config = loadComponentsConfig();
|
|
785
|
-
await installCSSStyles(config, registryUrl, options.overwrite);
|
|
861
|
+
await installCSSStyles(config, registryUrl, options.overwrite, false);
|
|
786
862
|
break;
|
|
787
863
|
|
|
788
864
|
default:
|