galaxy-design 0.2.72 → 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.
- package/README.md +113 -95
- package/dist/bin.js +17 -1
- package/dist/bin.js.map +1 -1
- package/dist/commands/add.js +59 -99
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/init.js +120 -611
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate-tailwind.js +90 -0
- package/dist/commands/migrate-tailwind.js.map +1 -0
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/registries/registry-angular.json +145 -537
- package/dist/registries/registry-react.json +2 -0
- package/dist/registry-angular.json +145 -537
- package/dist/registry-react.json +2 -0
- package/dist/schemas/components-schema.json +66 -11
- package/dist/schemas/registry-framework-schema.json +17 -7
- package/dist/utils/angular-provider-manager.js +1 -1
- package/dist/utils/angular-provider-manager.js.map +1 -1
- package/dist/utils/component-copier.js +102 -62
- package/dist/utils/component-copier.js.map +1 -1
- package/dist/utils/component-transformer.js +86 -16
- package/dist/utils/component-transformer.js.map +1 -1
- package/dist/utils/config-schema.js +160 -9
- package/dist/utils/config-schema.js.map +1 -1
- package/dist/utils/framework-registry-service.js +181 -0
- package/dist/utils/framework-registry-service.js.map +1 -0
- package/dist/utils/framework-registry.js +1 -138
- package/dist/utils/framework-registry.js.map +1 -1
- package/dist/utils/github-fetcher.js +55 -27
- package/dist/utils/github-fetcher.js.map +1 -1
- package/dist/utils/index.js +4 -3
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/init-runtime.js +477 -0
- package/dist/utils/init-runtime.js.map +1 -0
- package/dist/utils/init-scaffold.js +115 -0
- package/dist/utils/init-scaffold.js.map +1 -0
- package/dist/utils/init-workflow.js +189 -0
- package/dist/utils/init-workflow.js.map +1 -0
- package/dist/utils/package-manager.js +77 -2
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/platform-detector.js +12 -8
- package/dist/utils/platform-detector.js.map +1 -1
- package/dist/utils/registry-loader.js +20 -41
- package/dist/utils/registry-loader.js.map +1 -1
- package/dist/utils/tailwind-detector.js +162 -0
- package/dist/utils/tailwind-detector.js.map +1 -0
- package/dist/utils/tailwind-migration.js +401 -0
- package/dist/utils/tailwind-migration.js.map +1 -0
- package/dist/utils/tailwind-scaffold.js +398 -0
- package/dist/utils/tailwind-scaffold.js.map +1 -0
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -1,61 +1,94 @@
|
|
|
1
1
|
# Galaxy UI CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CLI for initializing Galaxy UI and copying framework-specific components into your project.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
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
|
-
##
|
|
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
|
-
|
|
31
|
+
```bash
|
|
24
32
|
npm install -g galaxy-design
|
|
25
33
|
bun add -g galaxy-design
|
|
26
34
|
```
|
|
27
35
|
|
|
28
|
-
##
|
|
36
|
+
## Quick Start
|
|
29
37
|
|
|
30
|
-
### 1. Initialize
|
|
38
|
+
### 1. Initialize
|
|
31
39
|
|
|
32
40
|
```bash
|
|
33
41
|
npx galaxy-design@latest init
|
|
34
42
|
```
|
|
35
43
|
|
|
36
|
-
|
|
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
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
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
|
-
|
|
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
|
|
78
|
+
# Add one component
|
|
49
79
|
npx galaxy-design@latest add button
|
|
50
80
|
|
|
51
|
-
# Add
|
|
81
|
+
# Add several components
|
|
52
82
|
npx galaxy-design@latest add button input card
|
|
53
83
|
|
|
54
|
-
# Interactive
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
259
|
+
Nuxt users should make sure the `@/` alias is available in `nuxt.config.ts`.
|
|
225
260
|
|
|
226
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
237
|
-
"
|
|
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
|
-
|
|
290
|
+
## Configuration Options
|
|
253
291
|
|
|
254
|
-
| Option
|
|
255
|
-
|
|
256
|
-
| `framework`
|
|
257
|
-
| `typescript`
|
|
258
|
-
| `tailwind.
|
|
259
|
-
| `tailwind.
|
|
260
|
-
| `tailwind.
|
|
261
|
-
| `
|
|
262
|
-
| `aliases.
|
|
263
|
-
| `
|
|
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
|
-
##
|
|
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
|
-
|
|
332
|
+
There is currently no `diff` command and no `--overwrite` option on `add`.
|
|
297
333
|
|
|
298
|
-
|
|
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
|
-
##
|
|
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
|
-
##
|
|
365
|
+
## Documentation
|
|
336
366
|
|
|
337
|
-
-
|
|
338
|
-
-
|
|
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
|
-
##
|
|
370
|
+
## Notes
|
|
342
371
|
|
|
343
|
-
|
|
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
|
-
##
|
|
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(
|
|
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(
|
|
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"}
|
package/dist/commands/add.js
CHANGED
|
@@ -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
|
|
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 {
|
|
9
|
-
import {
|
|
10
|
-
import { installDependencies } from '../utils/package-manager.js';
|
|
11
|
-
import {
|
|
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
|
-
|
|
85
|
-
if (allComponents[
|
|
86
|
-
componentsToAdd.push(
|
|
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
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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(`
|
|
195
|
+
console.log(chalk.gray(` ${formatInstallCommand(packageManager, uniqueDependencies)}`));
|
|
256
196
|
}
|
|
257
197
|
if (uniqueDevDependencies.length > 0) {
|
|
258
|
-
console.log(chalk.gray(`
|
|
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
|
-
|
|
301
|
-
|
|
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
|
-
|
|
305
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
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
|
|