galaxy-design 0.2.73 → 0.2.74

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.
Files changed (50) hide show
  1. package/README.md +113 -95
  2. package/dist/bin.js +17 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/add.js +59 -99
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/init.js +120 -611
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/migrate-tailwind.js +90 -0
  9. package/dist/commands/migrate-tailwind.js.map +1 -0
  10. package/dist/index.js +6 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/registries/registry-angular.json +145 -537
  13. package/dist/registry-angular.json +145 -537
  14. package/dist/schemas/components-schema.json +66 -11
  15. package/dist/schemas/registry-framework-schema.json +17 -7
  16. package/dist/utils/angular-provider-manager.js +1 -1
  17. package/dist/utils/angular-provider-manager.js.map +1 -1
  18. package/dist/utils/component-copier.js +102 -62
  19. package/dist/utils/component-copier.js.map +1 -1
  20. package/dist/utils/component-transformer.js +86 -16
  21. package/dist/utils/component-transformer.js.map +1 -1
  22. package/dist/utils/config-schema.js +160 -9
  23. package/dist/utils/config-schema.js.map +1 -1
  24. package/dist/utils/framework-registry-service.js +181 -0
  25. package/dist/utils/framework-registry-service.js.map +1 -0
  26. package/dist/utils/framework-registry.js +1 -138
  27. package/dist/utils/framework-registry.js.map +1 -1
  28. package/dist/utils/github-fetcher.js +55 -27
  29. package/dist/utils/github-fetcher.js.map +1 -1
  30. package/dist/utils/index.js +4 -3
  31. package/dist/utils/index.js.map +1 -1
  32. package/dist/utils/init-runtime.js +477 -0
  33. package/dist/utils/init-runtime.js.map +1 -0
  34. package/dist/utils/init-scaffold.js +115 -0
  35. package/dist/utils/init-scaffold.js.map +1 -0
  36. package/dist/utils/init-workflow.js +189 -0
  37. package/dist/utils/init-workflow.js.map +1 -0
  38. package/dist/utils/package-manager.js +77 -2
  39. package/dist/utils/package-manager.js.map +1 -1
  40. package/dist/utils/platform-detector.js +12 -8
  41. package/dist/utils/platform-detector.js.map +1 -1
  42. package/dist/utils/registry-loader.js +20 -41
  43. package/dist/utils/registry-loader.js.map +1 -1
  44. package/dist/utils/tailwind-detector.js +162 -0
  45. package/dist/utils/tailwind-detector.js.map +1 -0
  46. package/dist/utils/tailwind-migration.js +401 -0
  47. package/dist/utils/tailwind-migration.js.map +1 -0
  48. package/dist/utils/tailwind-scaffold.js +398 -0
  49. package/dist/utils/tailwind-scaffold.js.map +1 -0
  50. package/package.json +20 -2
package/README.md CHANGED
@@ -1,61 +1,94 @@
1
1
  # Galaxy UI CLI
2
2
 
3
- A modern, framework-agnostic CLI tool for adding beautiful, accessible UI components to your projects. Inspired by shadcn/ui, but supporting React, Vue, Angular, Next.js, and Nuxt.js.
3
+ CLI for initializing Galaxy UI and copying framework-specific components into your project.
4
4
 
5
- ## 🌟 Features
5
+ ## Features
6
6
 
7
- - 🚀 **Multi-framework support**: React, Vue, Angular, Next.js, and Nuxt.js
8
- - 📦 **41 production-ready components** across 8 categories
9
- - 🎨 **Built with Radix UI primitives** (radix-ui for React/Next.js, radix-vue for Vue/Nuxt.js, radix-ng for Angular)
10
- - 🌙 **Dark mode support** out of the box
11
- - 📱 **Responsive design** with mobile-first approach
12
- - **Accessibility-focused** (WAI-ARIA compliant)
13
- - 🎯 **TypeScript strict mode** support
14
- - 💅 **Tailwind CSS** for styling
15
- - 📝 **Customizable** - components are copied to your project
7
+ - Supports `init`, `add`, and `migrate tailwind`
8
+ - Detects React, Next.js, Vue, Nuxt.js, and Angular projects
9
+ - Stores project settings in `components.json`
10
+ - Scaffolds Tailwind in v4-first mode while preserving existing v3 projects
11
+ - Copies components into your source tree so they remain editable
12
+ - Fails clearly when remote component files cannot be fetched
16
13
 
17
- ## 📦 Installation
14
+ ## Framework Mapping
15
+
16
+ `nextjs` and `nuxtjs` are CLI target frameworks, not separate published component packages.
17
+
18
+ - `nextjs` reuses the React source registry and adds Next-specific transforms such as `'use client'` when required
19
+ - `nuxtjs` reuses the Vue source registry and keeps Vue/Nuxt-specific file structure intact
20
+
21
+ That means the package/source-of-truth layer is still React for Next.js and Vue for Nuxt.js, while the CLI adapts the copied files for the target app.
22
+
23
+ ## Installation
18
24
 
19
25
  ```bash
20
- # Using npx (recommended - no installation needed)
21
26
  npx galaxy-design@latest init
27
+ ```
28
+
29
+ Or install globally:
22
30
 
23
- # Or install globally
31
+ ```bash
24
32
  npm install -g galaxy-design
25
33
  bun add -g galaxy-design
26
34
  ```
27
35
 
28
- ## 🚀 Quick Start
36
+ ## Quick Start
29
37
 
30
- ### 1. Initialize Galaxy UI in your project
38
+ ### 1. Initialize
31
39
 
32
40
  ```bash
33
41
  npx galaxy-design@latest init
34
42
  ```
35
43
 
36
- This interactive command will:
44
+ `init` currently does the following:
45
+
46
+ - Detects the framework
47
+ - Creates `components.json`
48
+ - Installs core dependencies
49
+ - Creates `components/ui` and the `cn()` utility
50
+ - Detects Tailwind v3/v4 and scaffolds the matching mode
51
+
52
+ Tailwind behavior:
53
+
54
+ - Existing Tailwind v3 project: stays on v3
55
+ - Existing Tailwind v4 project: stays on v4
56
+ - No Tailwind detected: installs/scaffolds v4 by default
57
+
58
+ ### 1.5 Migrate Tailwind v3 To v4
59
+
60
+ ```bash
61
+ npx galaxy-design@latest migrate tailwind --dry-run
62
+ npx galaxy-design@latest migrate tailwind --yes
63
+ ```
64
+
65
+ `migrate tailwind` currently focuses on the safe scaffold layer:
37
66
 
38
- - Detect your framework (React, Vue, Angular, Next.js, or Nuxt.js)
39
- - Detect your package manager (npm, pnpm, yarn, or bun)
40
- - Install required dependencies (lucide icons, clsx, tailwind-merge, radix primitives)
41
- - Create component directory structure
42
- - Setup Tailwind CSS configuration
43
- - ✅ Create utility files (cn helper, etc.)
67
+ - Detects whether the current project still uses Tailwind v3
68
+ - Rewrites the global CSS entry from `@tailwind ...` directives to `@import "tailwindcss";`
69
+ - Rewrites the PostCSS config to use `@tailwindcss/postcss`
70
+ - Updates `components.json` Tailwind version metadata when present
71
+ - Reports utility classes that may need manual review in Tailwind v4
44
72
 
45
- ### 2. Add components
73
+ It does not try to auto-rewrite every potentially breaking utility class.
74
+
75
+ ### 2. Add Components
46
76
 
47
77
  ```bash
48
- # Add single component
78
+ # Add one component
49
79
  npx galaxy-design@latest add button
50
80
 
51
- # Add multiple components
81
+ # Add several components
52
82
  npx galaxy-design@latest add button input card
53
83
 
54
- # Interactive mode (select from list)
84
+ # Interactive selection
55
85
  npx galaxy-design@latest add
86
+
87
+ # Add everything in the current registry
88
+ npx galaxy-design@latest add --all
56
89
  ```
57
90
 
58
- ## 📚 Available Components (41 total)
91
+ ## Available Components
59
92
 
60
93
  ### 🎨 Form Components (9)
61
94
 
@@ -126,13 +159,13 @@ npx galaxy-design@latest add
126
159
  - `toggle` - Toggle buttons
127
160
  - `toggle-group` - Toggle button groups
128
161
 
129
- ## 🎯 Framework-Specific Examples
162
+ ## Framework Examples
130
163
 
131
164
  ### React
132
165
 
133
166
  ```tsx
134
- import {Button} from '@/components/ui/button'
135
- import {Input} from '@/components/ui/input'
167
+ import { Button } from '@/components/ui/button';
168
+ import { Input } from '@/components/ui/input';
136
169
 
137
170
  export function MyComponent() {
138
171
  return (
@@ -142,7 +175,7 @@ export function MyComponent() {
142
175
  </Button>
143
176
  <Input placeholder="Enter text..." />
144
177
  </div>
145
- )
178
+ );
146
179
  }
147
180
  ```
148
181
 
@@ -150,8 +183,8 @@ export function MyComponent() {
150
183
 
151
184
  ```vue
152
185
  <script setup lang="ts">
153
- import {Button} from '@/components/ui/button'
154
- import {Input} from '@/components/ui/input'
186
+ import { Button } from '@/components/ui/button';
187
+ import { Input } from '@/components/ui/input';
155
188
  </script>
156
189
 
157
190
  <template>
@@ -165,9 +198,9 @@ import {Input} from '@/components/ui/input'
165
198
  ### Angular
166
199
 
167
200
  ```typescript
168
- import {Component} from '@angular/core';
169
- import {ButtonDirective} from '@/components/ui/button';
170
- import {InputComponent} from '@/components/ui/input';
201
+ import { Component } from '@angular/core';
202
+ import { ButtonDirective } from '@/components/ui/button';
203
+ import { InputComponent } from '@/components/ui/input';
171
204
 
172
205
  @Component({
173
206
  selector: 'app-my-component',
@@ -186,10 +219,10 @@ export class MyComponent {}
186
219
  ### Next.js
187
220
 
188
221
  ```tsx
189
- 'use client'
222
+ 'use client';
190
223
 
191
- import {Button} from '@/components/ui/button'
192
- import {Input} from '@/components/ui/input'
224
+ import { Button } from '@/components/ui/button';
225
+ import { Input } from '@/components/ui/input';
193
226
 
194
227
  export default function MyComponent() {
195
228
  return (
@@ -199,18 +232,20 @@ export default function MyComponent() {
199
232
  </Button>
200
233
  <Input placeholder="Enter text..." />
201
234
  </div>
202
- )
235
+ );
203
236
  }
204
237
  ```
205
238
 
206
- **Note:** Galaxy UI CLI automatically adds the `'use client'` directive to components that use client-side features (hooks, event handlers, browser APIs). Server-compatible components won't have this directive added.
239
+ `add` automatically preserves framework-specific transformations such as `'use client'` for Next.js components when needed.
240
+
241
+ Next.js support is implemented as a React-source target inside the CLI, not as a separate `@galaxy-ui/nextjs` package.
207
242
 
208
243
  ### Nuxt.js
209
244
 
210
245
  ```vue
211
246
  <script setup lang="ts">
212
- import {Button} from '@/components/ui/button'
213
- import {Input} from '@/components/ui/input'
247
+ import { Button } from '@/components/ui/button';
248
+ import { Input } from '@/components/ui/input';
214
249
  </script>
215
250
 
216
251
  <template>
@@ -221,11 +256,13 @@ import {Input} from '@/components/ui/input'
221
256
  </template>
222
257
  ```
223
258
 
224
- **Note:** Components work seamlessly with Nuxt 3's auto-import feature. Make sure to configure the `@/` alias in your `nuxt.config.ts`.
259
+ Nuxt users should make sure the `@/` alias is available in `nuxt.config.ts`.
225
260
 
226
- ## ⚙️ Configuration
261
+ Nuxt.js support is implemented as a Vue-source target inside the CLI, not as a separate `@galaxy-ui/nuxtjs` package.
227
262
 
228
- Galaxy UI stores configuration in `components.json` at your project root:
263
+ ## Configuration
264
+
265
+ Galaxy UI stores project settings in `components.json`:
229
266
 
230
267
  ```json
231
268
  {
@@ -233,8 +270,9 @@ Galaxy UI stores configuration in `components.json` at your project root:
233
270
  "framework": "react",
234
271
  "typescript": true,
235
272
  "tailwind": {
236
- "config": "tailwind.config.js",
237
- "css": "src/app/globals.css",
273
+ "version": 4,
274
+ "config": "",
275
+ "css": "src/index.css",
238
276
  "baseColor": "slate",
239
277
  "cssVariables": true,
240
278
  "prefix": ""
@@ -249,24 +287,25 @@ Galaxy UI stores configuration in `components.json` at your project root:
249
287
  }
250
288
  ```
251
289
 
252
- ### Configuration Options
290
+ ## Configuration Options
253
291
 
254
- | Option | Description | Default |
255
- |--------|-------------|---------|
256
- | `framework` | Your framework (react/vue/angular) | Auto-detected |
257
- | `typescript` | Use TypeScript | `true` |
258
- | `tailwind.config` | Tailwind config path | `tailwind.config.js` |
259
- | `tailwind.css` | Global CSS file | Framework-specific |
260
- | `tailwind.baseColor` | Base color scheme | `slate` |
261
- | `aliases.components` | Components alias | `@/components` |
262
- | `aliases.utils` | Utils alias | `@/lib/utils` |
263
- | `iconLibrary` | Icon library to use | `lucide` |
292
+ | Option | Description | Default |
293
+ | -------------------- | ---------------------- | ------------------ |
294
+ | `framework` | Your framework | Auto-detected |
295
+ | `typescript` | Use TypeScript | `true` |
296
+ | `tailwind.version` | Tailwind major version | Auto-detected |
297
+ | `tailwind.config` | Tailwind config path | Framework-specific |
298
+ | `tailwind.css` | Global CSS file | Framework-specific |
299
+ | `tailwind.baseColor` | Base color scheme | `slate` |
300
+ | `aliases.components` | Components alias | `@/components` |
301
+ | `aliases.utils` | Utils alias | `@/lib/utils` |
302
+ | `iconLibrary` | Icon library to use | `lucide` |
264
303
 
265
- ## 🔧 CLI Commands
304
+ ## CLI Commands
266
305
 
267
306
  ### `init`
268
307
 
269
- Initialize Galaxy UI in your project.
308
+ Initialize Galaxy UI in your project and scaffold `components.json`.
270
309
 
271
310
  ```bash
272
311
  npx galaxy-design@latest init
@@ -277,7 +316,7 @@ npx galaxy-design@latest init --yes
277
316
 
278
317
  ### `add`
279
318
 
280
- Add components to your project.
319
+ Add registry components to your project.
281
320
 
282
321
  ```bash
283
322
  # Interactive mode
@@ -288,20 +327,11 @@ npx galaxy-design@latest add button input
288
327
 
289
328
  # Add all components
290
329
  npx galaxy-design@latest add --all
291
-
292
- # Overwrite existing components
293
- npx galaxy-design@latest add button --overwrite
294
330
  ```
295
331
 
296
- ### `diff`
332
+ There is currently no `diff` command and no `--overwrite` option on `add`.
297
333
 
298
- Check which components have updates available.
299
-
300
- ```bash
301
- npx galaxy-design@latest diff button
302
- ```
303
-
304
- ## 🌈 Styling & Theming
334
+ ## Styling And Theming
305
335
 
306
336
  Galaxy UI uses Tailwind CSS with CSS variables for theming. After running `init`, you can customize colors in your CSS file:
307
337
 
@@ -323,7 +353,7 @@ Galaxy UI uses Tailwind CSS with CSS variables for theming. After running `init`
323
353
  }
324
354
  ```
325
355
 
326
- ## 🎨 Customization
356
+ ## Customization
327
357
 
328
358
  Components are copied to your project, so you have full control:
329
359
 
@@ -332,29 +362,17 @@ Components are copied to your project, so you have full control:
332
362
  3. **Add features** - Extend components with your own functionality
333
363
  4. **No lock-in** - Components are yours to modify
334
364
 
335
- ## 📖 Documentation & Examples
365
+ ## Documentation
336
366
 
337
- - **Live Examples**: Check `examples/` folder for complete React, Vue, and Angular apps
338
- - **Docs Website**: <https://galaxy-design.vercel.app>
339
- - **GitHub**: <https://github.com/buikevin/galaxy-design-cli>
367
+ - Docs Website: <https://galaxy-design.vercel.app>
368
+ - Repository: <https://github.com/buikevin/galaxy-design>
340
369
 
341
- ## 🤝 Contributing
370
+ ## Notes
342
371
 
343
- Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md).
372
+ - `add` currently fetches component source files from GitHub at runtime.
373
+ - The CLI now fails explicitly if required files cannot be fetched.
374
+ - `components.json` is the active configuration system. Legacy `galaxy.config.*` flow has been removed from source.
344
375
 
345
- ## 📝 License
376
+ ## License
346
377
 
347
378
  MIT License - see [LICENSE](../../LICENSE) for details
348
-
349
- ## 🙏 Credits
350
-
351
- - Inspired by [shadcn/ui](<https://ui.shadcn.com>)
352
- - Built with [Radix UI](<https://radix-ui.com>), [Radix Vue](<https://radix-vue.com>), and [Spartan NG](<https://spartan.ng>)
353
- - Icons from [Lucide](<https://lucide.dev>)
354
- - Styling with [Tailwind CSS](<https://tailwindcss.com>)
355
-
356
- ---
357
-
358
- **Made with ❤️ by the Galaxy UI team**
359
-
360
- For issues and feature requests, please visit our [GitHub Issues](<https://github.com/buikevin/galaxy-design-cli/issues>)
package/dist/bin.js CHANGED
@@ -1,11 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from 'fs';
3
+ import { dirname, resolve } from 'path';
2
4
  import { Command } from 'commander';
5
+ import { fileURLToPath } from 'url';
3
6
  import { initCommand } from './commands/init.js';
4
7
  import { addCommand } from './commands/add.js';
8
+ import { migrateTailwindCommand } from './commands/migrate-tailwind.js';
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ function getCliVersion() {
12
+ try {
13
+ const packageJsonPath = resolve(__dirname, '../package.json');
14
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
15
+ return packageJson.version || '0.0.0';
16
+ } catch (e) {
17
+ return '0.0.0';
18
+ }
19
+ }
5
20
  const program = new Command();
6
- program.name('galaxy-design').description('CLI tool for Galaxy UI component library').version('0.2.2');
21
+ program.name('galaxy-design').description('CLI tool for Galaxy UI component library').version(getCliVersion());
7
22
  program.command('init').description('Initialize Galaxy UI in your project').option('-y, --yes', 'Skip prompts and use defaults').option('-c, --cwd <path>', 'Current working directory', process.cwd()).action(initCommand);
8
23
  program.command('add').description('Add components to your project').argument('[components...]', 'Component names to add').option('-a, --all', 'Add all components').option('-c, --cwd <path>', 'Current working directory', process.cwd()).action(addCommand);
24
+ program.command('migrate').description('Run Galaxy UI migration helpers').command('tailwind').description('Migrate a Tailwind v3 project to the Galaxy UI v4 scaffold').option('-c, --cwd <path>', 'Current working directory', process.cwd()).option('--dry-run', 'Preview the migration without writing files').option('-y, --yes', 'Skip confirmation prompts').action(migrateTailwindCommand);
9
25
  program.parse();
10
26
 
11
27
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { addCommand } from './commands/add.js';\n\nconst program = new Command();\n\nprogram\n .name('galaxy-design')\n .description('CLI tool for Galaxy UI component library')\n .version('0.2.2');\n\nprogram\n .command('init')\n .description('Initialize Galaxy UI in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .option('-c, --cwd <path>', 'Current working directory', process.cwd())\n .action(initCommand);\n\nprogram\n .command('add')\n .description('Add components to your project')\n .argument('[components...]', 'Component names to add')\n .option('-a, --all', 'Add all components')\n .option('-c, --cwd <path>', 'Current working directory', process.cwd())\n .action(addCommand);\n\nprogram.parse();\n"],"names":["Command","initCommand","addCommand","program","name","description","version","command","option","process","cwd","action","argument","parse"],"mappings":";AACA,SAASA,OAAO,QAAQ,YAAY;AACpC,SAASC,WAAW,QAAQ,qBAAqB;AACjD,SAASC,UAAU,QAAQ,oBAAoB;AAE/C,MAAMC,UAAU,IAAIH;AAEpBG,QACGC,IAAI,CAAC,iBACLC,WAAW,CAAC,4CACZC,OAAO,CAAC;AAEXH,QACGI,OAAO,CAAC,QACRF,WAAW,CAAC,wCACZG,MAAM,CAAC,aAAa,iCACpBA,MAAM,CAAC,oBAAoB,6BAA6BC,QAAQC,GAAG,IACnEC,MAAM,CAACV;AAEVE,QACGI,OAAO,CAAC,OACRF,WAAW,CAAC,kCACZO,QAAQ,CAAC,mBAAmB,0BAC5BJ,MAAM,CAAC,aAAa,sBACpBA,MAAM,CAAC,oBAAoB,6BAA6BC,QAAQC,GAAG,IACnEC,MAAM,CAACT;AAEVC,QAAQU,KAAK"}
1
+ {"version":3,"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFileSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport { Command } from 'commander';\nimport { fileURLToPath } from 'url';\nimport { initCommand } from './commands/init.js';\nimport { addCommand } from './commands/add.js';\nimport { migrateTailwindCommand } from './commands/migrate-tailwind.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nfunction getCliVersion(): string {\n try {\n const packageJsonPath = resolve(__dirname, '../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as {\n version?: string;\n };\n return packageJson.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nconst program = new Command();\n\nprogram\n .name('galaxy-design')\n .description('CLI tool for Galaxy UI component library')\n .version(getCliVersion());\n\nprogram\n .command('init')\n .description('Initialize Galaxy UI in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .option('-c, --cwd <path>', 'Current working directory', process.cwd())\n .action(initCommand);\n\nprogram\n .command('add')\n .description('Add components to your project')\n .argument('[components...]', 'Component names to add')\n .option('-a, --all', 'Add all components')\n .option('-c, --cwd <path>', 'Current working directory', process.cwd())\n .action(addCommand);\n\nprogram\n .command('migrate')\n .description('Run Galaxy UI migration helpers')\n .command('tailwind')\n .description('Migrate a Tailwind v3 project to the Galaxy UI v4 scaffold')\n .option('-c, --cwd <path>', 'Current working directory', process.cwd())\n .option('--dry-run', 'Preview the migration without writing files')\n .option('-y, --yes', 'Skip confirmation prompts')\n .action(migrateTailwindCommand);\n\nprogram.parse();\n"],"names":["readFileSync","dirname","resolve","Command","fileURLToPath","initCommand","addCommand","migrateTailwindCommand","__filename","url","__dirname","getCliVersion","packageJsonPath","packageJson","JSON","parse","version","program","name","description","command","option","process","cwd","action","argument"],"mappings":";AACA,SAASA,YAAY,QAAQ,KAAK;AAClC,SAASC,OAAO,EAAEC,OAAO,QAAQ,OAAO;AACxC,SAASC,OAAO,QAAQ,YAAY;AACpC,SAASC,aAAa,QAAQ,MAAM;AACpC,SAASC,WAAW,QAAQ,qBAAqB;AACjD,SAASC,UAAU,QAAQ,oBAAoB;AAC/C,SAASC,sBAAsB,QAAQ,iCAAiC;AAExE,MAAMC,aAAaJ,cAAc,YAAYK,GAAG;AAChD,MAAMC,YAAYT,QAAQO;AAE1B,SAASG;IACP,IAAI;QACF,MAAMC,kBAAkBV,QAAQQ,WAAW;QAC3C,MAAMG,cAAcC,KAAKC,KAAK,CAACf,aAAaY,iBAAiB;QAG7D,OAAOC,YAAYG,OAAO,IAAI;IAChC,EAAE,UAAM;QACN,OAAO;IACT;AACF;AAEA,MAAMC,UAAU,IAAId;AAEpBc,QACGC,IAAI,CAAC,iBACLC,WAAW,CAAC,4CACZH,OAAO,CAACL;AAEXM,QACGG,OAAO,CAAC,QACRD,WAAW,CAAC,wCACZE,MAAM,CAAC,aAAa,iCACpBA,MAAM,CAAC,oBAAoB,6BAA6BC,QAAQC,GAAG,IACnEC,MAAM,CAACnB;AAEVY,QACGG,OAAO,CAAC,OACRD,WAAW,CAAC,kCACZM,QAAQ,CAAC,mBAAmB,0BAC5BJ,MAAM,CAAC,aAAa,sBACpBA,MAAM,CAAC,oBAAoB,6BAA6BC,QAAQC,GAAG,IACnEC,MAAM,CAAClB;AAEVW,QACGG,OAAO,CAAC,WACRD,WAAW,CAAC,mCACZC,OAAO,CAAC,YACRD,WAAW,CAAC,8DACZE,MAAM,CAAC,oBAAoB,6BAA6BC,QAAQC,GAAG,IACnEF,MAAM,CAAC,aAAa,+CACpBA,MAAM,CAAC,aAAa,6BACpBG,MAAM,CAACjB;AAEVU,QAAQF,KAAK"}
@@ -1,18 +1,14 @@
1
1
  import prompts from 'prompts';
2
2
  import chalk from 'chalk';
3
3
  import ora from 'ora';
4
- import { resolve, join, dirname } from 'path';
5
- import { fileURLToPath } from 'url';
4
+ import { resolve, join } from 'path';
6
5
  import { loadComponentsConfig, hasComponentsConfig } from '../utils/components-config.js';
7
6
  import { hasSrcDirectory } from '../utils/detect.js';
8
- import { loadFrameworkRegistry, getFrameworkComponent, getFrameworkComponentDependencies, getAllFrameworkComponents } from '../utils/framework-registry.js';
9
- import { writeFile, fileExists, ensureDir } from '../utils/files.js';
10
- import { installDependencies } from '../utils/package-manager.js';
11
- import { fetchFileFromGitHub } from '../utils/github-fetcher.js';
12
- import { transformComponent } from '../utils/component-transformer.js';
7
+ import { getFrameworkComponent, getFrameworkComponentDependencies, getAllFrameworkComponents, resolveFrameworkComponentGraph, resolveFrameworkComponentName } from '../utils/framework-registry-service.js';
8
+ import { ensureDir } from '../utils/files.js';
9
+ import { detectPackageManager, formatInstallCommand, installDependencies } from '../utils/package-manager.js';
10
+ import { copyComponentFilesToDirectory } from '../utils/component-copier.js';
13
11
  import { generateAngularProvidersIndex } from '../utils/angular-provider-manager.js';
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = dirname(__filename);
16
12
  export async function addCommand(components, options) {
17
13
  const cwd = options.cwd;
18
14
  // Check if components.json exists (new config system)
@@ -29,8 +25,6 @@ export async function addCommand(components, options) {
29
25
  }
30
26
  const framework = componentsConfig.framework;
31
27
  console.log(chalk.gray(`Framework detected: ${chalk.cyan(framework)}\n`));
32
- // Load framework-specific registry
33
- const registry = loadFrameworkRegistry(framework);
34
28
  const allComponents = getAllFrameworkComponents(framework);
35
29
  // Determine which components to add
36
30
  let componentsToAdd = [];
@@ -81,9 +75,9 @@ export async function addCommand(components, options) {
81
75
  } else {
82
76
  // Add specified components
83
77
  for (const input of components){
84
- // Check if component exists in registry
85
- if (allComponents[input]) {
86
- componentsToAdd.push(input);
78
+ const resolvedName = resolveFrameworkComponentName(framework, input);
79
+ if (resolvedName && allComponents[resolvedName]) {
80
+ componentsToAdd.push(resolvedName);
87
81
  } else {
88
82
  console.log(chalk.yellow(`⚠ Component "${input}" not found. Skipping.`));
89
83
  }
@@ -97,24 +91,7 @@ export async function addCommand(components, options) {
97
91
  componentsToAdd = [
98
92
  ...new Set(componentsToAdd)
99
93
  ];
100
- // Resolve registry dependencies
101
- const resolvedComponents = new Set(componentsToAdd);
102
- const toProcess = [
103
- ...componentsToAdd
104
- ];
105
- while(toProcess.length > 0){
106
- const componentKey = toProcess.pop();
107
- const component = getFrameworkComponent(framework, componentKey);
108
- if (component && component.registryDependencies && component.registryDependencies.length > 0) {
109
- for (const depKey of component.registryDependencies){
110
- if (!resolvedComponents.has(depKey)) {
111
- resolvedComponents.add(depKey);
112
- toProcess.push(depKey);
113
- }
114
- }
115
- }
116
- }
117
- componentsToAdd = Array.from(resolvedComponents);
94
+ componentsToAdd = resolveFrameworkComponentGraph(framework, componentsToAdd);
118
95
  console.log(chalk.bold.cyan(`\n📦 Adding ${componentsToAdd.length} component(s)...\n`));
119
96
  // Collect all dependencies
120
97
  const allDependencies = [];
@@ -123,6 +100,7 @@ export async function addCommand(components, options) {
123
100
  const results = [];
124
101
  for (const componentKey of componentsToAdd){
125
102
  const component = getFrameworkComponent(framework, componentKey);
103
+ let componentFileErrors = [];
126
104
  if (!component) {
127
105
  results.push({
128
106
  name: componentKey,
@@ -141,67 +119,27 @@ export async function addCommand(components, options) {
141
119
  const baseDir = usesSrcDir ? 'src/' : '';
142
120
  const fullDestPath = resolve(cwd, baseDir + destPath, 'ui');
143
121
  ensureDir(fullDestPath);
144
- // Get file extension based on framework
145
- const fileExtensions = {
146
- vue: '.vue',
147
- react: '.tsx',
148
- angular: '.component.ts',
149
- 'react-native': '.tsx',
150
- flutter: '.dart'
151
- };
152
- const ext = fileExtensions[framework];
153
122
  // Create component folder
154
123
  const componentFolderPath = join(fullDestPath, componentKey);
155
124
  ensureDir(componentFolderPath);
156
- // Map framework to actual package framework for GitHub path
157
- // Next.js uses React components, Nuxt.js uses Vue components
158
- let packageFramework = framework;
159
- if (framework === 'nextjs') packageFramework = 'react';
160
- if (framework === 'nuxtjs') packageFramework = 'vue';
161
- // Copy component files from GitHub
162
- for (const file of component.files){
163
- const fileName = file.includes('/') ? file.split('/').pop() : file;
164
- const destFilePath = join(componentFolderPath, fileName);
165
- // Check if file already exists
166
- if (fileExists(destFilePath)) {
125
+ const copyResult = await copyComponentFilesToDirectory({
126
+ componentName: componentKey,
127
+ componentFiles: component.files,
128
+ componentType: component.type,
129
+ sourcePlatform: framework,
130
+ targetPlatform: framework,
131
+ targetDirectory: componentFolderPath,
132
+ relativeTo: cwd,
133
+ overwrite: false,
134
+ onSkippedFile: (fileName)=>{
167
135
  spinner.warn(`${chalk.cyan(component.name)} - File already exists: ${fileName}`);
168
- continue;
169
- }
170
- try {
171
- // Fetch file from GitHub (use packageFramework for correct path)
172
- const sourceFolder = component.type === 'block' ? 'blocks' : 'components';
173
- const githubPath = `packages/${packageFramework}/src/${sourceFolder}/${componentKey}/${file}`;
174
- let content = await fetchFileFromGitHub(githubPath);
175
- // Apply transformations (import path fixes, 'use client' for Next.js, etc.)
176
- const transformResult = transformComponent(content, {
177
- platform: framework,
178
- componentName: componentKey,
179
- filePath: destFilePath
180
- });
181
- content = transformResult.content;
182
- writeFile(destFilePath, content);
183
- } catch (error) {
184
- // Try with capitalized file name
185
- try {
186
- const capitalizedFile = file.charAt(0).toUpperCase() + file.slice(1);
187
- const sourceFolder = component.type === 'block' ? 'blocks' : 'components';
188
- const githubPath = `packages/${packageFramework}/src/${sourceFolder}/${componentKey}/${capitalizedFile}`;
189
- let content = await fetchFileFromGitHub(githubPath);
190
- // Apply transformations (import path fixes, 'use client' for Next.js, etc.)
191
- const transformResult = transformComponent(content, {
192
- platform: framework,
193
- componentName: componentKey,
194
- filePath: destFilePath
195
- });
196
- content = transformResult.content;
197
- writeFile(destFilePath, content);
198
- } catch (capitalizedError) {
199
- // If both attempts fail, write a placeholder
200
- const placeholderContent = `// ${component.name} component for ${framework}\n// TODO: Failed to fetch component from GitHub: ${error instanceof Error ? error.message : 'Unknown error'}\n`;
201
- writeFile(destFilePath, placeholderContent);
202
- spinner.warn(`${chalk.yellow('⚠')} Failed to fetch ${file} from GitHub, created placeholder`);
203
- }
204
136
  }
137
+ });
138
+ if (!copyResult.success) {
139
+ componentFileErrors = [
140
+ ...copyResult.errors
141
+ ];
142
+ throw new Error(`Missing or invalid files: ${copyResult.errors.length}`);
205
143
  }
206
144
  spinner.succeed(`${chalk.green('✓')} Added ${chalk.cyan(component.name)} to ${chalk.gray(destPath + '/ui/' + componentKey + '/')}`);
207
145
  results.push({
@@ -218,7 +156,8 @@ export async function addCommand(components, options) {
218
156
  results.push({
219
157
  name: component.name,
220
158
  success: false,
221
- error: error instanceof Error ? error.message : 'Unknown error'
159
+ error: error instanceof Error ? error.message : 'Unknown error',
160
+ details: componentFileErrors
222
161
  });
223
162
  }
224
163
  }
@@ -251,11 +190,12 @@ export async function addCommand(components, options) {
251
190
  } catch (error) {
252
191
  installSpinner.fail('Failed to install dependencies');
253
192
  console.log(chalk.yellow('Please install them manually:'));
193
+ const packageManager = detectPackageManager(cwd);
254
194
  if (uniqueDependencies.length > 0) {
255
- console.log(chalk.gray(` npm install ${uniqueDependencies.join(' ')}`));
195
+ console.log(chalk.gray(` ${formatInstallCommand(packageManager, uniqueDependencies)}`));
256
196
  }
257
197
  if (uniqueDevDependencies.length > 0) {
258
- console.log(chalk.gray(` npm install -D ${uniqueDevDependencies.join(' ')}`));
198
+ console.log(chalk.gray(` ${formatInstallCommand(packageManager, uniqueDevDependencies, true)}`));
259
199
  }
260
200
  }
261
201
  }
@@ -270,6 +210,11 @@ export async function addCommand(components, options) {
270
210
  console.log(chalk.red.bold(`✗ Failed to add ${failed} component(s)`));
271
211
  for (const result of results.filter((r)=>!r.success)){
272
212
  console.log(chalk.red(` - ${result.name}: ${result.error}`));
213
+ if (result.details && result.details.length > 0) {
214
+ for (const detail of result.details){
215
+ console.log(chalk.gray(` ${detail}`));
216
+ }
217
+ }
273
218
  }
274
219
  }
275
220
  // For Angular, generate/update the components/ui/index.ts file with providers
@@ -295,22 +240,37 @@ export async function addCommand(components, options) {
295
240
  // Next steps
296
241
  if (successful > 0) {
297
242
  console.log('\n' + chalk.gray('Next steps:'));
243
+ const nextSteps = [];
298
244
  switch(framework){
299
245
  case 'vue':
300
- console.log(chalk.gray(' 1. Import the components in your Vue component'));
301
- console.log(chalk.gray(' 2. Use them in your template'));
246
+ case 'nuxtjs':
247
+ nextSteps.push('Import the components in your Vue component');
248
+ nextSteps.push('Use them in your template');
302
249
  break;
303
250
  case 'react':
304
- console.log(chalk.gray(' 1. Import the components in your React component'));
305
- console.log(chalk.gray(' 2. Use them in your JSX'));
251
+ case 'nextjs':
252
+ nextSteps.push('Import the components in your React component');
253
+ nextSteps.push('Use them in your JSX');
306
254
  break;
307
255
  case 'angular':
308
- console.log(chalk.gray(' 1. Import provideGalaxyComponents() in your app.config.ts providers array'));
309
- console.log(chalk.gray(' 2. Import the components in your Angular component'));
310
- console.log(chalk.gray(' 3. Use them in your templates'));
256
+ nextSteps.push('Import provideGalaxyComponents() in your app.config.ts providers array');
257
+ nextSteps.push('Import the components in your Angular component');
258
+ nextSteps.push('Use them in your templates');
259
+ break;
260
+ case 'react-native':
261
+ nextSteps.push('Import the components in your React Native screen or component');
262
+ nextSteps.push('Ensure your NativeWind and alias configuration resolves `@/*` imports');
263
+ break;
264
+ case 'flutter':
265
+ nextSteps.push('Import the generated widgets in your Dart files');
266
+ nextSteps.push('Run `flutter pub get` if new Dart dependencies were added');
311
267
  break;
312
268
  }
313
- console.log(chalk.gray(' 4. Enjoy building with Galaxy UI! 🚀\n'));
269
+ nextSteps.push('Enjoy building with Galaxy UI!');
270
+ nextSteps.forEach((step, index)=>{
271
+ console.log(chalk.gray(` ${index + 1}. ${step}`));
272
+ });
273
+ console.log('');
314
274
  }
315
275
  }
316
276