weloop-kosign 1.0.2 → 1.0.4

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 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
- First, make sure you have the base dependencies installed:
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
- To install the base CSS styles:
13
+ This will automatically:
20
14
 
21
- ```bash
22
- npx weloop-kosign@latest css
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 will automatically install any required dependencies for each component. If something's missing, it'll let you know.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weloop-kosign",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "CLI tool for installing Weloop UI components",
5
5
  "keywords": [
6
6
  "weloop",
@@ -164,13 +164,48 @@ async function installPackages(packages) {
164
164
  // FILE OPERATIONS
165
165
  // ============================================================================
166
166
 
167
+ function createDefaultComponentsConfig() {
168
+ const configPath = path.join(process.cwd(), 'components.json');
169
+
170
+ // Detect if it's a Next.js app (app directory) or pages directory
171
+ const hasAppDir = fs.existsSync(path.join(process.cwd(), 'app'));
172
+ const cssPath = hasAppDir ? 'app/globals.css' : 'styles/globals.css';
173
+
174
+ const defaultConfig = {
175
+ style: 'blue',
176
+ rsc: true,
177
+ tsx: true,
178
+ tailwind: {
179
+ config: 'tailwind.config.ts',
180
+ css: cssPath,
181
+ baseColor: 'neutral',
182
+ cssVariables: true,
183
+ prefix: ''
184
+ },
185
+ iconLibrary: 'lucide',
186
+ aliases: {
187
+ components: '@/components',
188
+ utils: '@/lib/utils',
189
+ ui: '@/components/ui',
190
+ lib: '@/lib',
191
+ hooks: '@/hooks'
192
+ },
193
+ registry: 'https://gitlab.com/Sophanithchrek/weloop-shadcn-next-app/-/raw/main/registry/index.json'
194
+ };
195
+
196
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
197
+ success(`Created components.json`);
198
+ info(` You can customize this file to match your project setup`);
199
+
200
+ return defaultConfig;
201
+ }
202
+
167
203
  function loadComponentsConfig() {
168
204
  const configPath = path.join(process.cwd(), 'components.json');
169
205
 
170
206
  if (!fs.existsSync(configPath)) {
171
- error('components.json not found. Please initialize your project first.');
172
- info('Create a components.json file with your project configuration.');
173
- process.exit(1);
207
+ info('components.json not found. Creating default configuration...');
208
+ return createDefaultComponentsConfig();
174
209
  }
175
210
 
176
211
  const content = fs.readFileSync(configPath, 'utf-8');
@@ -370,6 +405,28 @@ function hasWeloopStyles(content) {
370
405
  content.includes('--system-200');
371
406
  }
372
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
+
373
430
  function processTwAnimateImport(cssContent, hasTwAnimate, forceUpdate = false) {
374
431
  const twAnimatePattern = /@import\s+["']tw-animate-css["'];?\s*\n?/g;
375
432
  let processed = cssContent;
@@ -388,7 +445,10 @@ function processTwAnimateImport(cssContent, hasTwAnimate, forceUpdate = false) {
388
445
  }
389
446
  }
390
447
  } else {
391
- // Ensure import exists if package is installed
448
+ // Remove any duplicates first
449
+ processed = removeDuplicateTwAnimateImports(processed);
450
+
451
+ // Ensure import exists if package is installed (only if not already present)
392
452
  if (!processed.match(/@import\s+["']tw-animate-css["'];?\s*\n?/)) {
393
453
  if (processed.includes('@import "tailwindcss"') || processed.includes("@import 'tailwindcss'")) {
394
454
  processed = processed.replace(
@@ -409,10 +469,27 @@ function removeTailwindImport(cssContent) {
409
469
  }
410
470
 
411
471
  function ensureTwAnimateImport(cssContent, hasTwAnimate) {
412
- if (!hasTwAnimate || cssContent.includes('@import "tw-animate-css"')) {
472
+ if (!hasTwAnimate) {
413
473
  return cssContent;
414
474
  }
415
- return '@import "tw-animate-css";\n' + cssContent;
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;
416
493
  }
417
494
 
418
495
  function mergeCSSWithTailwind(existing, weloopStyles, hasTwAnimate) {
@@ -424,8 +501,12 @@ function mergeCSSWithTailwind(existing, weloopStyles, hasTwAnimate) {
424
501
  const beforeTailwind = existing.substring(0, existing.indexOf(tailwindMatch[0]));
425
502
  const afterTailwind = existing.substring(existing.indexOf(tailwindMatch[0]) + tailwindMatch[0].length);
426
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
+
427
508
  let importsToAdd = '';
428
- if (hasTwAnimate && !existing.includes('@import "tw-animate-css"')) {
509
+ if (hasTwAnimate && !hasTwAnimateInExisting && !hasTwAnimateInWeloop) {
429
510
  importsToAdd = '@import "tw-animate-css";\n';
430
511
  }
431
512
 
@@ -527,8 +608,11 @@ async function installCSSStyles(config, registryUrl, forceUpdate = false) {
527
608
  info(` Your existing styles are preserved`);
528
609
  } else {
529
610
  // No Tailwind imports, prepend everything
530
- let finalCssContent = processedCssContent;
531
- if (hasTwAnimate && !finalCssContent.includes('@import "tw-animate-css"')) {
611
+ // Remove duplicates from processedCssContent first
612
+ let finalCssContent = removeDuplicateTwAnimateImports(processedCssContent);
613
+
614
+ // Only add if not already present
615
+ if (hasTwAnimate && !finalCssContent.match(/@import\s+["']tw-animate-css["'];?\s*\n?/)) {
532
616
  if (finalCssContent.includes('@import "tailwindcss"')) {
533
617
  finalCssContent = finalCssContent.replace(
534
618
  /(@import\s+["']tailwindcss["'];?\s*\n?)/,
@@ -580,18 +664,33 @@ export function cn(...inputs: ClassValue[]) {
580
664
  `;
581
665
  fs.writeFileSync(utilsPath, utilsContent);
582
666
  success(`Created ${path.relative(process.cwd(), utilsPath)}`);
583
-
584
- // Check if required packages are installed
585
- if (!checkPackageInstalled('clsx') || !checkPackageInstalled('tailwind-merge')) {
586
- warn('utils.ts requires: clsx and tailwind-merge');
587
- info(' Install with: npm install clsx tailwind-merge');
588
- }
589
667
  }
590
668
 
591
669
  async function installComponent(componentName, options = {}) {
592
670
  const { overwrite = false, registryUrl = DEFAULT_REGISTRY_URL } = options;
671
+
672
+ // Install base dependencies first (required for utils.ts)
673
+ const baseDeps = [];
674
+ if (!checkPackageInstalled('clsx')) {
675
+ baseDeps.push('clsx');
676
+ }
677
+ if (!checkPackageInstalled('tailwind-merge')) {
678
+ baseDeps.push('tailwind-merge');
679
+ }
680
+ if (baseDeps.length > 0) {
681
+ info(`Installing base dependencies: ${baseDeps.join(', ')}...`);
682
+ await installPackages(baseDeps);
683
+ }
684
+
685
+ // Load or create components.json (after base deps are installed)
593
686
  const config = loadComponentsConfig();
594
687
 
688
+ // Install tw-animate-css automatically (required for animations)
689
+ if (!checkPackageInstalled('tw-animate-css')) {
690
+ info('Installing tw-animate-css for animations...');
691
+ await installPackages(['tw-animate-css']);
692
+ }
693
+
595
694
  // Install CSS styles early (before component installation)
596
695
  await installCSSStyles(config, registryUrl);
597
696