grg-kit-cli 0.6.6 ā 0.6.9
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 +2 -2
- package/bin/grg.js +11 -1
- package/commands/add.js +97 -1
- package/commands/init.js +33 -9
- package/commands/list.js +28 -7
- package/commands/llm-setup.js +324 -27
- package/config/resources.js +0 -17
- package/package.json +7 -6
- package/scripts/README.md +6 -8
- package/scripts/generate-resources.js +1 -1
- package/config/.catalog-cache.json +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ CLI tool for initializing Angular projects with GRG Kit and adding blocks.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install -g grg-kit-cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
@@ -140,7 +140,7 @@ For AI assistants to automatically discover and use GRG Kit resources:
|
|
|
140
140
|
### 1. Install the MCP Server
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
|
-
|
|
143
|
+
npm install -g grg-kit-mcp-server
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
### 2. Configure Your AI Assistant
|
package/bin/grg.js
CHANGED
|
@@ -21,7 +21,7 @@ program
|
|
|
21
21
|
.option('-t, --theme <name>', 'Theme to install (grg-theme, claude, clean-slate, modern-minimal, amber-minimal, mocks)', 'grg-theme')
|
|
22
22
|
.action(init);
|
|
23
23
|
|
|
24
|
-
// Add command with block
|
|
24
|
+
// Add command with block and component subcommands
|
|
25
25
|
const addCommand = program.command('add').description('Add resources to your project');
|
|
26
26
|
|
|
27
27
|
addCommand
|
|
@@ -31,6 +31,16 @@ addCommand
|
|
|
31
31
|
.option('-o, --output <path>', 'Custom output directory')
|
|
32
32
|
.action(add);
|
|
33
33
|
|
|
34
|
+
addCommand
|
|
35
|
+
.command('component [componentName]')
|
|
36
|
+
.description('Add GRG components to your project (e.g., grg add component file-upload)')
|
|
37
|
+
.option('--all', 'Add all components')
|
|
38
|
+
.option('-o, --output <path>', 'Custom output directory')
|
|
39
|
+
.action(async (componentName, options) => {
|
|
40
|
+
const { addComponent } = require('../commands/add');
|
|
41
|
+
await addComponent(componentName, options);
|
|
42
|
+
});
|
|
43
|
+
|
|
34
44
|
// List command
|
|
35
45
|
program
|
|
36
46
|
.command('list [category]')
|
package/commands/add.js
CHANGED
|
@@ -196,4 +196,100 @@ function showUsage(RESOURCES) {
|
|
|
196
196
|
console.log(chalk.gray('\nRun'), chalk.cyan('grg list blocks'), chalk.gray('for more details'));
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Add component command - downloads GRG components
|
|
201
|
+
* Format: grg add component <componentName>
|
|
202
|
+
* Examples:
|
|
203
|
+
* grg add component file-upload # Download file-upload component
|
|
204
|
+
* grg add component --all # All components
|
|
205
|
+
*/
|
|
206
|
+
async function addComponent(componentName, options) {
|
|
207
|
+
// Fetch catalog dynamically (with caching)
|
|
208
|
+
const spinner = ora('Fetching catalog...').start();
|
|
209
|
+
const RESOURCES = await fetchCatalog({ silent: true });
|
|
210
|
+
spinner.stop();
|
|
211
|
+
|
|
212
|
+
// Handle --all flag (download all components)
|
|
213
|
+
if (options.all) {
|
|
214
|
+
console.log(chalk.bold.cyan(`\nš¦ Adding all components\n`));
|
|
215
|
+
|
|
216
|
+
for (const component of RESOURCES.components) {
|
|
217
|
+
await downloadComponent(component, options.output);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
console.log(chalk.bold.green('⨠Done!'));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Validate component name
|
|
225
|
+
if (!componentName) {
|
|
226
|
+
showComponentUsage(RESOURCES);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const component = RESOURCES.components.find(c => c.name === componentName);
|
|
231
|
+
if (!component) {
|
|
232
|
+
console.error(chalk.red(`\nError: Component "${componentName}" not found`));
|
|
233
|
+
console.log(chalk.yellow('\nAvailable components:'));
|
|
234
|
+
RESOURCES.components.forEach(c => {
|
|
235
|
+
console.log(chalk.cyan(` ${c.name}`), chalk.gray(`- ${c.description}`));
|
|
236
|
+
});
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await downloadComponent(component, options.output);
|
|
241
|
+
console.log(chalk.bold.green('⨠Done!'));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Download a component
|
|
246
|
+
*/
|
|
247
|
+
async function downloadComponent(component, customOutput) {
|
|
248
|
+
const downloadSpinner = ora();
|
|
249
|
+
const outputPath = customOutput
|
|
250
|
+
? `${customOutput}/${component.name}`
|
|
251
|
+
: component.defaultOutput;
|
|
252
|
+
|
|
253
|
+
downloadSpinner.start(`Downloading ${component.title}...`);
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
const emitter = degit(`${REPO}/${component.path}`, {
|
|
257
|
+
cache: false,
|
|
258
|
+
force: true,
|
|
259
|
+
verbose: false,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
await emitter.clone(outputPath);
|
|
263
|
+
|
|
264
|
+
downloadSpinner.succeed(chalk.green(`ā ${component.title} added`));
|
|
265
|
+
console.log(chalk.gray(` Location: ${outputPath}`));
|
|
266
|
+
|
|
267
|
+
if (component.dependencies && component.dependencies.length > 0) {
|
|
268
|
+
console.log(chalk.gray(` Dependencies: ${component.dependencies.join(', ')}`));
|
|
269
|
+
}
|
|
270
|
+
console.log();
|
|
271
|
+
|
|
272
|
+
} catch (error) {
|
|
273
|
+
downloadSpinner.fail(chalk.red(`Failed to download ${component.title}`));
|
|
274
|
+
console.error(chalk.red(error.message));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Show component usage help
|
|
280
|
+
*/
|
|
281
|
+
function showComponentUsage(RESOURCES) {
|
|
282
|
+
console.log(chalk.yellow('\nUsage: grg add component <componentName>\n'));
|
|
283
|
+
console.log(chalk.bold('Examples:'));
|
|
284
|
+
console.log(chalk.cyan(' grg add component file-upload'), chalk.gray(' # Download file-upload'));
|
|
285
|
+
console.log(chalk.cyan(' grg add component --all'), chalk.gray(' # All components'));
|
|
286
|
+
|
|
287
|
+
console.log(chalk.bold('\nAvailable components:'));
|
|
288
|
+
RESOURCES.components.forEach(c => {
|
|
289
|
+
console.log(chalk.cyan(` ${c.name}`), chalk.gray(`- ${c.description}`));
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
console.log(chalk.gray('\nRun'), chalk.cyan('grg list components'), chalk.gray('for more details'));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
module.exports = { add, addComponent };
|
package/commands/init.js
CHANGED
|
@@ -48,10 +48,12 @@ async function init(options) {
|
|
|
48
48
|
// Step 1: Install Tailwind CSS v4
|
|
49
49
|
spinner.start('Installing Tailwind CSS v4...');
|
|
50
50
|
try {
|
|
51
|
-
await execAsync('
|
|
51
|
+
await execAsync('npm install tailwindcss @tailwindcss/postcss postcss');
|
|
52
52
|
spinner.succeed(chalk.green('ā Tailwind CSS v4 installed'));
|
|
53
53
|
} catch (error) {
|
|
54
|
-
spinner.
|
|
54
|
+
spinner.fail(chalk.red('Failed to install Tailwind CSS v4'));
|
|
55
|
+
console.error(chalk.gray(error.message));
|
|
56
|
+
process.exit(1);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
// Step 3: Create .postcssrc.json
|
|
@@ -71,10 +73,12 @@ async function init(options) {
|
|
|
71
73
|
// Step 4: Install Spartan-NG CLI
|
|
72
74
|
spinner.start('Installing Spartan-NG CLI...');
|
|
73
75
|
try {
|
|
74
|
-
await execAsync('
|
|
76
|
+
await execAsync('npm install -D @spartan-ng/cli');
|
|
75
77
|
spinner.succeed(chalk.green('ā Spartan-NG CLI installed'));
|
|
76
78
|
} catch (error) {
|
|
77
|
-
spinner.
|
|
79
|
+
spinner.fail(chalk.red('Failed to install Spartan-NG CLI'));
|
|
80
|
+
console.error(chalk.gray(error.message));
|
|
81
|
+
process.exit(1);
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
// Step 5: Create components.json config file
|
|
@@ -97,9 +101,14 @@ async function init(options) {
|
|
|
97
101
|
let tsconfigContent = await fs.readFile(tsconfigPath, 'utf-8');
|
|
98
102
|
|
|
99
103
|
// Strip comments from tsconfig (Angular generates tsconfig with comments)
|
|
104
|
+
// Be careful not to strip // inside strings (like URLs)
|
|
100
105
|
tsconfigContent = tsconfigContent
|
|
101
106
|
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments
|
|
102
|
-
.replace(
|
|
107
|
+
.replace(/^\s*\/\/.*/gm, ''); // Remove line comments (only at start of line after whitespace)
|
|
108
|
+
|
|
109
|
+
// Remove trailing commas (common in tsconfig files)
|
|
110
|
+
tsconfigContent = tsconfigContent
|
|
111
|
+
.replace(/,(\s*[}\]])/g, '$1');
|
|
103
112
|
|
|
104
113
|
const tsconfig = JSON.parse(tsconfigContent);
|
|
105
114
|
|
|
@@ -123,9 +132,12 @@ async function init(options) {
|
|
|
123
132
|
try {
|
|
124
133
|
const { spawn } = require('child_process');
|
|
125
134
|
await new Promise((resolve, reject) => {
|
|
126
|
-
|
|
135
|
+
// Use 'ng' directly (works with global @angular/cli) instead of 'npx ng'
|
|
136
|
+
// Exit code 127 occurs when npx can't find the command
|
|
137
|
+
const child = spawn('ng', ['g', '@spartan-ng/cli:ui'], {
|
|
127
138
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
128
|
-
shell: true
|
|
139
|
+
shell: true,
|
|
140
|
+
env: { ...process.env } // Inherit PATH to find global ng
|
|
129
141
|
});
|
|
130
142
|
|
|
131
143
|
let output = '';
|
|
@@ -156,7 +168,9 @@ async function init(options) {
|
|
|
156
168
|
}
|
|
157
169
|
});
|
|
158
170
|
|
|
171
|
+
let stderrOutput = '';
|
|
159
172
|
child.stderr.on('data', (data) => {
|
|
173
|
+
stderrOutput += data.toString();
|
|
160
174
|
// Spartan CLI outputs progress to stderr
|
|
161
175
|
const text = data.toString();
|
|
162
176
|
if (text.includes('CREATE') || text.includes('UPDATE')) {
|
|
@@ -168,14 +182,24 @@ async function init(options) {
|
|
|
168
182
|
child.on('close', (code) => {
|
|
169
183
|
console.log(); // New line after progress dots
|
|
170
184
|
if (code === 0) resolve();
|
|
171
|
-
else reject(new Error(`Process exited with code ${code}`));
|
|
185
|
+
else reject(new Error(`Process exited with code ${code}${stderrOutput ? '\n' + stderrOutput : ''}`));
|
|
186
|
+
});
|
|
187
|
+
child.on('error', (err) => {
|
|
188
|
+
if (err.code === 'ENOENT') {
|
|
189
|
+
reject(new Error('Angular CLI (ng) not found. Please install it: npm install -g @angular/cli'));
|
|
190
|
+
} else {
|
|
191
|
+
reject(err);
|
|
192
|
+
}
|
|
172
193
|
});
|
|
173
|
-
child.on('error', reject);
|
|
174
194
|
});
|
|
175
195
|
spinner.succeed(chalk.green('ā All Spartan-NG UI components installed'));
|
|
176
196
|
} catch (error) {
|
|
177
197
|
spinner.fail(chalk.red('Failed to run Spartan-NG UI generator'));
|
|
178
198
|
console.error(chalk.red(error.message));
|
|
199
|
+
console.log(chalk.yellow('\nTroubleshooting:'));
|
|
200
|
+
console.log(chalk.gray(' 1. Ensure Angular CLI is installed:'), chalk.cyan('npm install -g @angular/cli'));
|
|
201
|
+
console.log(chalk.gray(' 2. Ensure @spartan-ng/cli is installed:'), chalk.cyan('npm install -D @spartan-ng/cli'));
|
|
202
|
+
console.log(chalk.gray(' 3. Try running manually:'), chalk.cyan('ng g @spartan-ng/cli:ui'));
|
|
179
203
|
process.exit(1);
|
|
180
204
|
}
|
|
181
205
|
|
package/commands/list.js
CHANGED
|
@@ -3,7 +3,7 @@ const ora = require('ora');
|
|
|
3
3
|
const { fetchCatalog } = require('../config/catalog-fetcher');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* List command - displays available blocks and themes
|
|
6
|
+
* List command - displays available blocks, components, and themes
|
|
7
7
|
* Usage: grg list [category]
|
|
8
8
|
*/
|
|
9
9
|
async function list(category) {
|
|
@@ -17,16 +17,17 @@ async function list(category) {
|
|
|
17
17
|
console.log(chalk.bold.cyan('\nš¦ GRG Kit Resources\n'));
|
|
18
18
|
|
|
19
19
|
console.log(chalk.bold('Blocks') + chalk.gray(` (${RESOURCES.blocks.length} available)`));
|
|
20
|
-
console.log(chalk.gray(' Add with: grg add block
|
|
20
|
+
console.log(chalk.gray(' Add with: grg add block <name>'));
|
|
21
21
|
console.log(chalk.gray(' Run: grg list blocks\n'));
|
|
22
22
|
|
|
23
|
+
console.log(chalk.bold('Components') + chalk.gray(` (${RESOURCES.components.length} available)`));
|
|
24
|
+
console.log(chalk.gray(' Add with: grg add component <name>'));
|
|
25
|
+
console.log(chalk.gray(' Run: grg list components\n'));
|
|
26
|
+
|
|
23
27
|
console.log(chalk.bold('Themes') + chalk.gray(` (${RESOURCES.themes.length} available)`));
|
|
24
28
|
console.log(chalk.gray(' Set with: grg init --theme <name>'));
|
|
25
29
|
console.log(chalk.gray(' Run: grg list themes\n'));
|
|
26
30
|
|
|
27
|
-
console.log(chalk.gray('Components and spartan-ng examples are installed automatically with'), chalk.cyan('grg init'));
|
|
28
|
-
console.log();
|
|
29
|
-
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -36,7 +37,10 @@ async function list(category) {
|
|
|
36
37
|
RESOURCES.blocks.forEach(block => {
|
|
37
38
|
console.log(chalk.bold(` ${block.name}`));
|
|
38
39
|
console.log(chalk.gray(` ${block.description}`));
|
|
39
|
-
console.log(chalk.yellow(` grg add block
|
|
40
|
+
console.log(chalk.yellow(` grg add block ${block.name}`));
|
|
41
|
+
if (block.files && block.files.length > 0) {
|
|
42
|
+
console.log(chalk.gray(` Files: ${block.files.map(f => f.id).join(', ')}`));
|
|
43
|
+
}
|
|
40
44
|
if (block.tags && block.tags.length > 0) {
|
|
41
45
|
console.log(chalk.gray(` Tags: ${block.tags.join(', ')}`));
|
|
42
46
|
}
|
|
@@ -44,6 +48,23 @@ async function list(category) {
|
|
|
44
48
|
});
|
|
45
49
|
break;
|
|
46
50
|
|
|
51
|
+
case 'components':
|
|
52
|
+
console.log(chalk.bold.cyan('\nš§© Available Components\n'));
|
|
53
|
+
console.log(chalk.gray(' Use with: grg add component <name>\n'));
|
|
54
|
+
RESOURCES.components.forEach(component => {
|
|
55
|
+
console.log(chalk.bold(` ${component.name}`));
|
|
56
|
+
console.log(chalk.gray(` ${component.description}`));
|
|
57
|
+
console.log(chalk.yellow(` grg add component ${component.name}`));
|
|
58
|
+
if (component.dependencies && component.dependencies.length > 0) {
|
|
59
|
+
console.log(chalk.gray(` Dependencies: ${component.dependencies.join(', ')}`));
|
|
60
|
+
}
|
|
61
|
+
if (component.tags && component.tags.length > 0) {
|
|
62
|
+
console.log(chalk.gray(` Tags: ${component.tags.join(', ')}`));
|
|
63
|
+
}
|
|
64
|
+
console.log();
|
|
65
|
+
});
|
|
66
|
+
break;
|
|
67
|
+
|
|
47
68
|
case 'themes':
|
|
48
69
|
console.log(chalk.bold.cyan('\nšØ Available Themes\n'));
|
|
49
70
|
console.log(chalk.gray(' Use with: grg init --theme <name>\n'));
|
|
@@ -60,7 +81,7 @@ async function list(category) {
|
|
|
60
81
|
|
|
61
82
|
default:
|
|
62
83
|
console.error(chalk.red(`Error: Unknown category "${category}"`));
|
|
63
|
-
console.log(chalk.yellow('Valid categories: blocks, themes'));
|
|
84
|
+
console.log(chalk.yellow('Valid categories: blocks, components, themes'));
|
|
64
85
|
process.exit(1);
|
|
65
86
|
}
|
|
66
87
|
}
|
package/commands/llm-setup.js
CHANGED
|
@@ -183,7 +183,7 @@ This project uses **GRG Kit**, a comprehensive Angular UI toolkit built on top o
|
|
|
183
183
|
**GRG Kit Components** (in \`libs/grg-ui/\`):
|
|
184
184
|
- Use \`grg-\` prefix for selectors
|
|
185
185
|
- Import via \`GrgComponentImports\`
|
|
186
|
-
- Example: \`
|
|
186
|
+
- Example: \`GrgFileUploadImports\`
|
|
187
187
|
- Path alias: \`@grg-kit/ui/component-name\`
|
|
188
188
|
|
|
189
189
|
### 3. Import Patterns
|
|
@@ -213,14 +213,14 @@ import { HlmDialogImports } from '@spartan-ng/helm/dialog';
|
|
|
213
213
|
|
|
214
214
|
#### GRG Kit Components
|
|
215
215
|
\`\`\`typescript
|
|
216
|
-
import {
|
|
216
|
+
import { GrgFileUploadImports } from '@grg-kit/ui/file-upload';
|
|
217
217
|
|
|
218
218
|
@Component({
|
|
219
|
-
imports: [
|
|
219
|
+
imports: [GrgFileUploadImports],
|
|
220
220
|
template: \`
|
|
221
|
-
<grg-
|
|
222
|
-
<grg-
|
|
223
|
-
</grg-
|
|
221
|
+
<grg-file-upload>
|
|
222
|
+
<grg-file-upload-trigger>Drop files here</grg-file-upload-trigger>
|
|
223
|
+
</grg-file-upload>
|
|
224
224
|
\`
|
|
225
225
|
})
|
|
226
226
|
\`\`\`
|
|
@@ -343,6 +343,178 @@ class="flex flex-col justify-between gap-4 py-4 sm:flex-row sm:items-center"
|
|
|
343
343
|
[attr.data-state]="row.getIsSelected() && 'selected'"
|
|
344
344
|
\`\`\`
|
|
345
345
|
|
|
346
|
+
## TailwindCSS Best Practices (CRITICAL)
|
|
347
|
+
|
|
348
|
+
### NEVER Use Raw Color Classes
|
|
349
|
+
|
|
350
|
+
**FORBIDDEN - Do NOT use these patterns:**
|
|
351
|
+
\`\`\`typescript
|
|
352
|
+
// ā WRONG - Raw Tailwind colors
|
|
353
|
+
class="text-green-600 bg-green-100" // No raw green
|
|
354
|
+
class="text-red-500 bg-red-50" // No raw red
|
|
355
|
+
class="text-yellow-600 bg-yellow-100" // No raw yellow
|
|
356
|
+
class="text-blue-500 bg-blue-100" // No raw blue
|
|
357
|
+
class="border-gray-200" // No raw gray
|
|
358
|
+
class="text-slate-700" // No raw slate
|
|
359
|
+
\`\`\`
|
|
360
|
+
|
|
361
|
+
**REQUIRED - Use semantic color tokens:**
|
|
362
|
+
\`\`\`typescript
|
|
363
|
+
// ā
CORRECT - Semantic colors from design system
|
|
364
|
+
class="text-foreground" // Primary text
|
|
365
|
+
class="text-muted-foreground" // Secondary/muted text
|
|
366
|
+
class="bg-background" // Page background
|
|
367
|
+
class="bg-card" // Card background
|
|
368
|
+
class="bg-muted" // Muted/subtle background
|
|
369
|
+
class="bg-primary text-primary-foreground" // Primary actions
|
|
370
|
+
class="bg-secondary text-secondary-foreground" // Secondary elements
|
|
371
|
+
class="bg-destructive text-destructive-foreground" // Errors/danger
|
|
372
|
+
class="bg-accent text-accent-foreground" // Accents/highlights
|
|
373
|
+
class="border-border" // Standard borders
|
|
374
|
+
class="border-input" // Input borders
|
|
375
|
+
\`\`\`
|
|
376
|
+
|
|
377
|
+
### Available Semantic Colors
|
|
378
|
+
|
|
379
|
+
These are the ONLY colors you should use (defined in \`styles.css\` and theme files):
|
|
380
|
+
|
|
381
|
+
| Token | Usage |
|
|
382
|
+
|-------|-------|
|
|
383
|
+
| \`background\` / \`foreground\` | Page background and primary text |
|
|
384
|
+
| \`card\` / \`card-foreground\` | Card containers |
|
|
385
|
+
| \`popover\` / \`popover-foreground\` | Popovers, dropdowns |
|
|
386
|
+
| \`primary\` / \`primary-foreground\` | Primary buttons, links |
|
|
387
|
+
| \`secondary\` / \`secondary-foreground\` | Secondary actions |
|
|
388
|
+
| \`muted\` / \`muted-foreground\` | Subtle backgrounds, secondary text |
|
|
389
|
+
| \`accent\` / \`accent-foreground\` | Highlights, hover states |
|
|
390
|
+
| \`destructive\` / \`destructive-foreground\` | Errors, delete actions |
|
|
391
|
+
| \`border\` | Standard borders |
|
|
392
|
+
| \`input\` | Form input borders |
|
|
393
|
+
| \`ring\` | Focus rings |
|
|
394
|
+
| \`chart-1\` through \`chart-5\` | Chart/data visualization colors |
|
|
395
|
+
| \`sidebar-*\` | Sidebar-specific colors |
|
|
396
|
+
|
|
397
|
+
### Adding New Semantic Colors
|
|
398
|
+
|
|
399
|
+
If you need a color that doesn't exist (e.g., success, warning, info):
|
|
400
|
+
|
|
401
|
+
**Step 1: Add CSS variables to \`src/styles.css\`:**
|
|
402
|
+
\`\`\`css
|
|
403
|
+
:root {
|
|
404
|
+
/* Existing variables... */
|
|
405
|
+
|
|
406
|
+
/* Add new semantic color with BOTH light and dark values */
|
|
407
|
+
--success: oklch(0.72 0.19 142); /* Green for light mode */
|
|
408
|
+
--success-foreground: oklch(1 0 0); /* White text */
|
|
409
|
+
|
|
410
|
+
--warning: oklch(0.75 0.18 85); /* Amber for light mode */
|
|
411
|
+
--warning-foreground: oklch(0.2 0 0); /* Dark text */
|
|
412
|
+
|
|
413
|
+
--info: oklch(0.65 0.15 250); /* Blue for light mode */
|
|
414
|
+
--info-foreground: oklch(1 0 0); /* White text */
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.dark {
|
|
418
|
+
/* Dark mode equivalents */
|
|
419
|
+
--success: oklch(0.65 0.17 142);
|
|
420
|
+
--success-foreground: oklch(1 0 0);
|
|
421
|
+
|
|
422
|
+
--warning: oklch(0.70 0.16 85);
|
|
423
|
+
--warning-foreground: oklch(0.15 0 0);
|
|
424
|
+
|
|
425
|
+
--info: oklch(0.60 0.14 250);
|
|
426
|
+
--info-foreground: oklch(1 0 0);
|
|
427
|
+
}
|
|
428
|
+
\`\`\`
|
|
429
|
+
|
|
430
|
+
**Step 2: Register in \`@theme inline\` block (in theme file):**
|
|
431
|
+
\`\`\`css
|
|
432
|
+
@theme inline {
|
|
433
|
+
--color-success: var(--success);
|
|
434
|
+
--color-success-foreground: var(--success-foreground);
|
|
435
|
+
--color-warning: var(--warning);
|
|
436
|
+
--color-warning-foreground: var(--warning-foreground);
|
|
437
|
+
--color-info: var(--info);
|
|
438
|
+
--color-info-foreground: var(--info-foreground);
|
|
439
|
+
}
|
|
440
|
+
\`\`\`
|
|
441
|
+
|
|
442
|
+
**Step 3: Now use in templates:**
|
|
443
|
+
\`\`\`typescript
|
|
444
|
+
class="bg-success text-success-foreground" // Success states
|
|
445
|
+
class="bg-warning text-warning-foreground" // Warning states
|
|
446
|
+
class="bg-info text-info-foreground" // Info states
|
|
447
|
+
\`\`\`
|
|
448
|
+
|
|
449
|
+
### Typography Best Practices
|
|
450
|
+
|
|
451
|
+
**NEVER use arbitrary font sizes:**
|
|
452
|
+
\`\`\`typescript
|
|
453
|
+
// ā WRONG - Arbitrary sizes
|
|
454
|
+
class="text-[13px]" // No arbitrary values
|
|
455
|
+
class="text-[1.1rem]" // No arbitrary values
|
|
456
|
+
\`\`\`
|
|
457
|
+
|
|
458
|
+
**USE the Tailwind typography scale:**
|
|
459
|
+
\`\`\`typescript
|
|
460
|
+
// ā
CORRECT - Standard typography scale
|
|
461
|
+
class="text-xs" // 0.75rem (12px)
|
|
462
|
+
class="text-sm" // 0.875rem (14px)
|
|
463
|
+
class="text-base" // 1rem (16px) - default body
|
|
464
|
+
class="text-lg" // 1.125rem (18px)
|
|
465
|
+
class="text-xl" // 1.25rem (20px)
|
|
466
|
+
class="text-2xl" // 1.5rem (24px)
|
|
467
|
+
class="text-3xl" // 1.875rem (30px)
|
|
468
|
+
class="text-4xl" // 2.25rem (36px)
|
|
469
|
+
\`\`\`
|
|
470
|
+
|
|
471
|
+
**Font weights:**
|
|
472
|
+
\`\`\`typescript
|
|
473
|
+
class="font-normal" // 400
|
|
474
|
+
class="font-medium" // 500
|
|
475
|
+
class="font-semibold" // 600
|
|
476
|
+
class="font-bold" // 700
|
|
477
|
+
\`\`\`
|
|
478
|
+
|
|
479
|
+
**Font families (from theme):**
|
|
480
|
+
\`\`\`typescript
|
|
481
|
+
class="font-sans" // System UI font stack
|
|
482
|
+
class="font-mono" // Monospace for code
|
|
483
|
+
class="font-serif" // Serif for special cases
|
|
484
|
+
\`\`\`
|
|
485
|
+
|
|
486
|
+
### Spacing Best Practices
|
|
487
|
+
|
|
488
|
+
**USE the standard spacing scale:**
|
|
489
|
+
\`\`\`typescript
|
|
490
|
+
// ā
CORRECT - Standard spacing
|
|
491
|
+
class="p-4" // 1rem
|
|
492
|
+
class="gap-2" // 0.5rem
|
|
493
|
+
class="mt-6" // 1.5rem
|
|
494
|
+
class="space-y-4" // 1rem between children
|
|
495
|
+
\`\`\`
|
|
496
|
+
|
|
497
|
+
**AVOID arbitrary spacing unless absolutely necessary:**
|
|
498
|
+
\`\`\`typescript
|
|
499
|
+
// ā AVOID - Arbitrary spacing
|
|
500
|
+
class="p-[13px]" // Use p-3 or p-4 instead
|
|
501
|
+
\`\`\`
|
|
502
|
+
|
|
503
|
+
### Dark Mode Support
|
|
504
|
+
|
|
505
|
+
All semantic colors automatically support dark mode. The theme system handles this via:
|
|
506
|
+
- \`:root\` for light mode values
|
|
507
|
+
- \`.dark\` or \`[data-theme="theme-name"].dark\` for dark mode values
|
|
508
|
+
|
|
509
|
+
**You do NOT need to add \`dark:\` prefixes** when using semantic colors:
|
|
510
|
+
\`\`\`typescript
|
|
511
|
+
// ā
CORRECT - Semantic colors auto-adapt
|
|
512
|
+
class="bg-background text-foreground" // Works in both light and dark
|
|
513
|
+
|
|
514
|
+
// ā WRONG - Manual dark mode with raw colors
|
|
515
|
+
class="bg-white dark:bg-gray-900" // Don't do this
|
|
516
|
+
\`\`\`
|
|
517
|
+
|
|
346
518
|
### Component Variants
|
|
347
519
|
Components support multiple variants through the \`variant\` attribute:
|
|
348
520
|
|
|
@@ -504,14 +676,14 @@ export class FormComponent {
|
|
|
504
676
|
- **Slider**: Range input controls
|
|
505
677
|
|
|
506
678
|
### GRG Kit Custom Components
|
|
507
|
-
- **
|
|
679
|
+
- **File Upload**: Drag and drop file upload component
|
|
508
680
|
|
|
509
681
|
## Package Manager
|
|
510
682
|
|
|
511
|
-
|
|
512
|
-
- \`
|
|
513
|
-
- \`
|
|
514
|
-
- \`
|
|
683
|
+
Use npm for package management operations:
|
|
684
|
+
- \`npm install\` for installing dependencies
|
|
685
|
+
- \`npm install <package>\` for adding packages
|
|
686
|
+
- \`npm uninstall\` for removing packages
|
|
515
687
|
|
|
516
688
|
This design system provides a comprehensive foundation for building consistent, accessible, and maintainable Angular applications using modern UI patterns and best practices.
|
|
517
689
|
`;
|
|
@@ -548,8 +720,7 @@ Add the grg-kit MCP server to your AI assistant configuration:
|
|
|
548
720
|
{
|
|
549
721
|
"mcpServers": {
|
|
550
722
|
"grg-kit": {
|
|
551
|
-
"command": "
|
|
552
|
-
"args": ["-y", "@grg-kit/mcp-server"]
|
|
723
|
+
"command": "grg-mcp-server"
|
|
553
724
|
}
|
|
554
725
|
}
|
|
555
726
|
}
|
|
@@ -569,7 +740,7 @@ After adding, restart your IDE for the MCP server to be available.
|
|
|
569
740
|
Use the MCP server for:
|
|
570
741
|
1. **Themes** - Install different color themes
|
|
571
742
|
2. **Blocks** - Pre-built page layouts (auth, shell, settings)
|
|
572
|
-
3. **GRG Kit Components** - Custom components like
|
|
743
|
+
3. **GRG Kit Components** - Custom components like file-upload
|
|
573
744
|
|
|
574
745
|
**Do NOT use MCP for:**
|
|
575
746
|
- Spartan-NG components (button, card, dialog, etc.) - already installed
|
|
@@ -593,7 +764,7 @@ mcp2_search_ui_resources({
|
|
|
593
764
|
**When to use:**
|
|
594
765
|
- User needs a page layout or block
|
|
595
766
|
- Looking for a theme
|
|
596
|
-
- Need a GRG Kit component (
|
|
767
|
+
- Need a GRG Kit component (file-upload)
|
|
597
768
|
|
|
598
769
|
### 2. mcp2_suggest_resources
|
|
599
770
|
|
|
@@ -699,14 +870,14 @@ AI Workflow:
|
|
|
699
870
|
### Example 4: User Wants a Form Component
|
|
700
871
|
|
|
701
872
|
\`\`\`
|
|
702
|
-
User: "I need a
|
|
873
|
+
User: "I need a file upload"
|
|
703
874
|
|
|
704
875
|
AI Workflow:
|
|
705
|
-
1. mcp2_search_ui_resources({ query: "
|
|
706
|
-
ā Finds: component:
|
|
876
|
+
1. mcp2_search_ui_resources({ query: "file upload" })
|
|
877
|
+
ā Finds: component:file-upload
|
|
707
878
|
|
|
708
879
|
2. Components are included automatically with grg init
|
|
709
|
-
ā Just import and use: import {
|
|
880
|
+
ā Just import and use: import { GrgFileUploadImports } from '@grg-kit/ui/file-upload';
|
|
710
881
|
|
|
711
882
|
3. Use with Spartan-NG form components (from design-system.md)
|
|
712
883
|
\`\`\`
|
|
@@ -736,7 +907,7 @@ User request:
|
|
|
736
907
|
āā Need a theme?
|
|
737
908
|
ā āā Use MCP: mcp2_list_available_resources({ category: "themes" })
|
|
738
909
|
ā
|
|
739
|
-
āā Need
|
|
910
|
+
āā Need file-upload or other GRG Kit component?
|
|
740
911
|
āā Use MCP: mcp2_search_ui_resources({ query: "..." })
|
|
741
912
|
\`\`\`
|
|
742
913
|
|
|
@@ -790,7 +961,7 @@ import { HlmDialogImports } from '@spartan-ng/helm/dialog';
|
|
|
790
961
|
|
|
791
962
|
**GRG Kit (grg- prefix):**
|
|
792
963
|
\`\`\`typescript
|
|
793
|
-
import {
|
|
964
|
+
import { GrgFileUploadImports } from '@grg-kit/ui/file-upload';
|
|
794
965
|
\`\`\`
|
|
795
966
|
|
|
796
967
|
### Common Patterns
|
|
@@ -850,15 +1021,56 @@ import { lucideCheck, lucideX } from '@ng-icons/lucide';
|
|
|
850
1021
|
Use MCP only for:
|
|
851
1022
|
- **Blocks** (auth, shell, settings) - \`mcp2_search_ui_resources({ query: "auth" })\`
|
|
852
1023
|
- **Themes** - \`mcp2_list_available_resources({ category: "themes" })\`
|
|
853
|
-
- **GRG Kit components** (
|
|
1024
|
+
- **GRG Kit components** (file-upload) - \`mcp2_search_ui_resources({ query: "file-upload" })\`
|
|
854
1025
|
|
|
855
1026
|
**Do NOT use MCP for Spartan-NG components** - they are already installed!
|
|
856
1027
|
|
|
1028
|
+
## TailwindCSS Rules (CRITICAL)
|
|
1029
|
+
|
|
1030
|
+
### NEVER use raw Tailwind colors:
|
|
1031
|
+
\`\`\`html
|
|
1032
|
+
<!-- ā FORBIDDEN -->
|
|
1033
|
+
<div class="text-green-600 bg-green-100">Success</div>
|
|
1034
|
+
<div class="text-red-500">Error</div>
|
|
1035
|
+
<div class="bg-yellow-50 border-yellow-200">Warning</div>
|
|
1036
|
+
\`\`\`
|
|
1037
|
+
|
|
1038
|
+
### ALWAYS use semantic color tokens:
|
|
1039
|
+
\`\`\`html
|
|
1040
|
+
<!-- ā
CORRECT -->
|
|
1041
|
+
<div class="bg-primary text-primary-foreground">Primary</div>
|
|
1042
|
+
<div class="bg-destructive text-destructive-foreground">Error</div>
|
|
1043
|
+
<div class="text-muted-foreground">Secondary text</div>
|
|
1044
|
+
<div class="bg-muted">Subtle background</div>
|
|
1045
|
+
<div class="border-border">Standard border</div>
|
|
1046
|
+
\`\`\`
|
|
1047
|
+
|
|
1048
|
+
### Available semantic colors:
|
|
1049
|
+
\`background\`, \`foreground\`, \`card\`, \`card-foreground\`, \`popover\`, \`popover-foreground\`,
|
|
1050
|
+
\`primary\`, \`primary-foreground\`, \`secondary\`, \`secondary-foreground\`, \`muted\`, \`muted-foreground\`,
|
|
1051
|
+
\`accent\`, \`accent-foreground\`, \`destructive\`, \`destructive-foreground\`, \`border\`, \`input\`, \`ring\`
|
|
1052
|
+
|
|
1053
|
+
### Need a new color (e.g., success, warning)?
|
|
1054
|
+
1. Add CSS variable to \`src/styles.css\` with light AND dark mode values
|
|
1055
|
+
2. Register in \`@theme inline\` block
|
|
1056
|
+
3. Then use: \`bg-success text-success-foreground\`
|
|
1057
|
+
|
|
1058
|
+
### Typography - use standard scale:
|
|
1059
|
+
\`\`\`html
|
|
1060
|
+
<!-- ā
CORRECT -->
|
|
1061
|
+
<p class="text-sm">Small</p>
|
|
1062
|
+
<p class="text-base">Body</p>
|
|
1063
|
+
<h2 class="text-xl font-semibold">Heading</h2>
|
|
1064
|
+
|
|
1065
|
+
<!-- ā WRONG - arbitrary sizes -->
|
|
1066
|
+
<p class="text-[13px]">Don't do this</p>
|
|
1067
|
+
\`\`\`
|
|
1068
|
+
|
|
857
1069
|
## Remember
|
|
858
1070
|
- Spartan-NG components are pre-installed - just import and use
|
|
859
1071
|
- Follow existing patterns in the codebase
|
|
860
|
-
- Use TailwindCSS v4 for styling
|
|
861
|
-
-
|
|
1072
|
+
- Use TailwindCSS v4 for styling with SEMANTIC colors only
|
|
1073
|
+
- NEVER use raw colors like text-green-600, bg-yellow-100, etc.
|
|
862
1074
|
`;
|
|
863
1075
|
}
|
|
864
1076
|
|
|
@@ -901,7 +1113,7 @@ import { HlmDialogImports } from '@spartan-ng/helm/dialog';
|
|
|
901
1113
|
|
|
902
1114
|
**GRG Kit:**
|
|
903
1115
|
\`\`\`typescript
|
|
904
|
-
import {
|
|
1116
|
+
import { GrgFileUploadImports } from '@grg-kit/ui/file-upload';
|
|
905
1117
|
\`\`\`
|
|
906
1118
|
|
|
907
1119
|
## Common Components
|
|
@@ -983,15 +1195,100 @@ ${blocksList}
|
|
|
983
1195
|
- Need button, card, dialog, form field, table? ā Use Spartan-NG (already installed)
|
|
984
1196
|
- Need page layout (dashboard, auth, settings)? ā Use MCP: \`mcp2_search_ui_resources\`
|
|
985
1197
|
- Need theme? ā Use MCP: \`mcp2_list_available_resources({ category: "themes" })\`
|
|
986
|
-
- Need
|
|
1198
|
+
- Need file-upload? ā Use MCP: \`mcp2_search_ui_resources\`
|
|
987
1199
|
|
|
988
1200
|
## Package Manager
|
|
989
1201
|
|
|
990
|
-
|
|
1202
|
+
Use npm for package management.
|
|
991
1203
|
|
|
992
1204
|
## Styling
|
|
993
1205
|
|
|
994
1206
|
Use TailwindCSS v4 for all styling. Prefer signals for state management.
|
|
1207
|
+
|
|
1208
|
+
## TailwindCSS Best Practices (CRITICAL)
|
|
1209
|
+
|
|
1210
|
+
### NEVER use raw Tailwind colors:
|
|
1211
|
+
\`\`\`html
|
|
1212
|
+
<!-- ā FORBIDDEN - These break theming and dark mode -->
|
|
1213
|
+
<div class="text-green-600 bg-green-100">Success</div>
|
|
1214
|
+
<div class="text-red-500">Error</div>
|
|
1215
|
+
<div class="bg-yellow-50">Warning</div>
|
|
1216
|
+
<div class="border-gray-200">Border</div>
|
|
1217
|
+
\`\`\`
|
|
1218
|
+
|
|
1219
|
+
### ALWAYS use semantic color tokens:
|
|
1220
|
+
\`\`\`html
|
|
1221
|
+
<!-- ā
CORRECT - These respect theming and dark mode -->
|
|
1222
|
+
<div class="bg-primary text-primary-foreground">Primary action</div>
|
|
1223
|
+
<div class="bg-destructive text-destructive-foreground">Error/Delete</div>
|
|
1224
|
+
<div class="text-muted-foreground">Secondary text</div>
|
|
1225
|
+
<div class="bg-muted">Subtle background</div>
|
|
1226
|
+
<div class="bg-accent text-accent-foreground">Highlighted</div>
|
|
1227
|
+
<div class="border-border">Standard border</div>
|
|
1228
|
+
\`\`\`
|
|
1229
|
+
|
|
1230
|
+
### Available semantic colors:
|
|
1231
|
+
| Token | Usage |
|
|
1232
|
+
|-------|-------|
|
|
1233
|
+
| \`background\` / \`foreground\` | Page background, primary text |
|
|
1234
|
+
| \`card\` / \`card-foreground\` | Card containers |
|
|
1235
|
+
| \`primary\` / \`primary-foreground\` | Primary buttons, CTAs |
|
|
1236
|
+
| \`secondary\` / \`secondary-foreground\` | Secondary actions |
|
|
1237
|
+
| \`muted\` / \`muted-foreground\` | Subtle backgrounds, secondary text |
|
|
1238
|
+
| \`accent\` / \`accent-foreground\` | Highlights, hover states |
|
|
1239
|
+
| \`destructive\` / \`destructive-foreground\` | Errors, delete actions |
|
|
1240
|
+
| \`border\` | Standard borders |
|
|
1241
|
+
| \`input\` | Form input borders |
|
|
1242
|
+
|
|
1243
|
+
### Adding new semantic colors (e.g., success, warning, info):
|
|
1244
|
+
|
|
1245
|
+
**Step 1:** Add to \`src/styles.css\` with BOTH light and dark values:
|
|
1246
|
+
\`\`\`css
|
|
1247
|
+
:root {
|
|
1248
|
+
--success: oklch(0.72 0.19 142);
|
|
1249
|
+
--success-foreground: oklch(1 0 0);
|
|
1250
|
+
}
|
|
1251
|
+
.dark {
|
|
1252
|
+
--success: oklch(0.65 0.17 142);
|
|
1253
|
+
--success-foreground: oklch(1 0 0);
|
|
1254
|
+
}
|
|
1255
|
+
\`\`\`
|
|
1256
|
+
|
|
1257
|
+
**Step 2:** Register in \`@theme inline\` block in theme file:
|
|
1258
|
+
\`\`\`css
|
|
1259
|
+
@theme inline {
|
|
1260
|
+
--color-success: var(--success);
|
|
1261
|
+
--color-success-foreground: var(--success-foreground);
|
|
1262
|
+
}
|
|
1263
|
+
\`\`\`
|
|
1264
|
+
|
|
1265
|
+
**Step 3:** Use in templates:
|
|
1266
|
+
\`\`\`html
|
|
1267
|
+
<div class="bg-success text-success-foreground">Success!</div>
|
|
1268
|
+
\`\`\`
|
|
1269
|
+
|
|
1270
|
+
### Typography - use standard scale only:
|
|
1271
|
+
\`\`\`html
|
|
1272
|
+
<!-- ā
CORRECT -->
|
|
1273
|
+
<p class="text-sm">Small (14px)</p>
|
|
1274
|
+
<p class="text-base">Body (16px)</p>
|
|
1275
|
+
<h2 class="text-xl font-semibold">Heading</h2>
|
|
1276
|
+
|
|
1277
|
+
<!-- ā WRONG - arbitrary sizes -->
|
|
1278
|
+
<p class="text-[13px]">Avoid arbitrary values</p>
|
|
1279
|
+
\`\`\`
|
|
1280
|
+
|
|
1281
|
+
Standard scale: \`text-xs\` (12px), \`text-sm\` (14px), \`text-base\` (16px), \`text-lg\` (18px), \`text-xl\` (20px), \`text-2xl\` (24px), \`text-3xl\` (30px), \`text-4xl\` (36px)
|
|
1282
|
+
|
|
1283
|
+
### Dark mode is automatic:
|
|
1284
|
+
Semantic colors automatically adapt to dark mode. Do NOT use \`dark:\` prefix with raw colors.
|
|
1285
|
+
\`\`\`html
|
|
1286
|
+
<!-- ā
Auto-adapts to dark mode -->
|
|
1287
|
+
<div class="bg-background text-foreground">Content</div>
|
|
1288
|
+
|
|
1289
|
+
<!-- ā Don't do this -->
|
|
1290
|
+
<div class="bg-white dark:bg-gray-900">Content</div>
|
|
1291
|
+
\`\`\`
|
|
995
1292
|
`;
|
|
996
1293
|
}
|
|
997
1294
|
|
package/config/resources.js
CHANGED
|
@@ -145,23 +145,6 @@ const RESOURCES = {
|
|
|
145
145
|
"dependencies": [
|
|
146
146
|
"@spartan-ng/helm/button"
|
|
147
147
|
]
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
"name": "stepper",
|
|
151
|
-
"title": "Stepper Component",
|
|
152
|
-
"description": "Multi-step form component with progress indicator",
|
|
153
|
-
"path": "templates/ui/components/stepper",
|
|
154
|
-
"defaultOutput": "src/app/components/stepper",
|
|
155
|
-
"tags": [
|
|
156
|
-
"form",
|
|
157
|
-
"wizard",
|
|
158
|
-
"multi-step",
|
|
159
|
-
"progress"
|
|
160
|
-
],
|
|
161
|
-
"dependencies": [
|
|
162
|
-
"@spartan-ng/helm/button",
|
|
163
|
-
"@spartan-ng/helm/card"
|
|
164
|
-
]
|
|
165
148
|
}
|
|
166
149
|
],
|
|
167
150
|
"blocks": [
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grg-kit-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "CLI tool for pulling GRG Kit resources into your Angular project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"grg": "./bin/grg.js"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"catalog": "node scripts/generate-resources.js",
|
|
11
|
+
"prepublishOnly": "npm run catalog",
|
|
12
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
13
|
+
},
|
|
9
14
|
"keywords": [
|
|
10
15
|
"angular",
|
|
11
16
|
"ui",
|
|
@@ -30,9 +35,5 @@
|
|
|
30
35
|
},
|
|
31
36
|
"engines": {
|
|
32
37
|
"node": ">=16.0.0"
|
|
33
|
-
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"catalog": "node scripts/generate-resources.js",
|
|
36
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
|
+
}
|
package/scripts/README.md
CHANGED
|
@@ -15,7 +15,7 @@ GRG Kit uses a **two-stage generation pipeline** to ensure CLI and MCP server al
|
|
|
15
15
|
ā
|
|
16
16
|
ā¼
|
|
17
17
|
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
18
|
-
ā STAGE 1:
|
|
18
|
+
ā STAGE 1: npm generate:sources (in app/) ā
|
|
19
19
|
ā ā
|
|
20
20
|
ā ⢠Transforms source components ā template files ā
|
|
21
21
|
ā ⢠Copies meta.json files ā templates/ directory ā
|
|
@@ -79,7 +79,7 @@ app/src/app/blocks/my-block/meta.json
|
|
|
79
79
|
# 3. Update generate-sources.js CONFIG.blocks.sources array
|
|
80
80
|
|
|
81
81
|
# 4. Run generation
|
|
82
|
-
cd app &&
|
|
82
|
+
cd app && npm generate:sources
|
|
83
83
|
cd ../cli && node scripts/generate-resources.js
|
|
84
84
|
|
|
85
85
|
# 5. Commit and push - CLI/MCP pick up changes automatically
|
|
@@ -124,7 +124,7 @@ Generates template files and copies metadata.
|
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
126
|
cd app
|
|
127
|
-
|
|
127
|
+
npm generate:sources
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
**What it does:**
|
|
@@ -187,7 +187,6 @@ grg-kit/
|
|
|
187
187
|
ā ā āāā meta.json ā All themes metadata
|
|
188
188
|
ā ā āāā *.css
|
|
189
189
|
ā āāā libs/grg-ui/
|
|
190
|
-
ā ā āāā stepper/meta.json
|
|
191
190
|
ā ā āāā file-upload/meta.json
|
|
192
191
|
ā āāā scripts/
|
|
193
192
|
ā āāā generate-sources.js ā Stage 1
|
|
@@ -216,8 +215,7 @@ grg-kit/
|
|
|
216
215
|
ā āāā meta.json ā Copied from app
|
|
217
216
|
ā āāā *.css
|
|
218
217
|
āāā components/
|
|
219
|
-
|
|
220
|
-
āāā file-upload/meta.json
|
|
218
|
+
āāā file-upload/meta.json ā Copied from app
|
|
221
219
|
```
|
|
222
220
|
|
|
223
221
|
---
|
|
@@ -226,8 +224,8 @@ grg-kit/
|
|
|
226
224
|
|
|
227
225
|
| Task | Command |
|
|
228
226
|
|------|---------|
|
|
229
|
-
| Generate templates + copy meta | `cd app &&
|
|
227
|
+
| Generate templates + copy meta | `cd app && npm generate:sources` |
|
|
230
228
|
| Generate resources + catalog | `cd cli && node scripts/generate-resources.js` |
|
|
231
229
|
| Full regeneration | Run both above |
|
|
232
230
|
| Test CLI | `cd cli && node bin/grg.js list` |
|
|
233
|
-
| Build MCP | `cd mcp-server &&
|
|
231
|
+
| Build MCP | `cd mcp-server && npm build` |
|
|
@@ -302,7 +302,7 @@ module.exports = { RESOURCES, REPO };
|
|
|
302
302
|
const cliPackage = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
|
|
303
303
|
|
|
304
304
|
const catalog = {
|
|
305
|
-
_generated: 'AUTO-GENERATED FILE - DO NOT EDIT MANUALLY. Run:
|
|
305
|
+
_generated: 'AUTO-GENERATED FILE - DO NOT EDIT MANUALLY. Run: npm catalog',
|
|
306
306
|
version: '1.0.1',
|
|
307
307
|
lastUpdated: new Date().toISOString().split('T')[0],
|
|
308
308
|
cli: {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"timestamp":1765202627293,"data":{"themes":[{"name":"amber-minimal","title":"Amber Minimal","description":"Warm amber accents","file":"amber-minimal.css","tags":["minimal","warm","amber","orange"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/amber-minimal.css","defaultOutput":"src/themes/amber-minimal.css"},{"name":"claude","title":"Claude","description":"Claude-inspired warm tones","file":"claude.css","tags":["warm","orange","brown","claude"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/claude.css","defaultOutput":"src/themes/claude.css"},{"name":"clean-slate","title":"Clean Slate","description":"Minimal grayscale palette","file":"clean-slate.css","tags":["minimal","grayscale","neutral","clean"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/clean-slate.css","defaultOutput":"src/themes/clean-slate.css"},{"name":"grg-theme","title":"Grg Theme","description":"Default theme with purple/orange accents","file":"grg-theme.css","tags":["default","purple","orange","colorful"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/grg-theme.css","defaultOutput":"src/themes/grg-theme.css"},{"name":"mocks","title":"Mocks","description":"Theme for mockups and prototypes","file":"mocks.css","tags":["mockup","prototype","design"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/mocks.css","defaultOutput":"src/themes/mocks.css"},{"name":"modern-minimal","title":"Modern Minimal","description":"Contemporary minimal design","file":"modern-minimal.css","tags":["minimal","modern","contemporary","clean"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/modern-minimal.css","defaultOutput":"src/themes/modern-minimal.css"}],"components":[{"name":"file-upload","title":"File Upload","description":"Drag and drop file upload component","tags":["file","upload","form","drag-drop"],"dependencies":["@spartan-ng/helm/button"],"path":"templates/ui/components/file-upload","defaultOutput":"src/app/components/file-upload"},{"name":"stepper","title":"Stepper","description":"Multi-step form component with progress indicator","tags":["form","wizard","multi-step","progress"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card"],"path":"templates/ui/components/stepper","defaultOutput":"src/app/components/stepper"}],"blocks":[{"name":"auth","title":"Auth","description":"Authentication pages (login, signup, forgot password)","tags":["auth","login","signup","authentication","form"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card","@spartan-ng/helm/form-field"],"files":[{"id":"forgot-password","file":"forgot-password.component.ts","title":"Forgot Password","description":"Forgot Password"},{"id":"login","file":"login.component.ts","title":"Login","description":"Login"},{"id":"register","file":"register.component.ts","title":"Register","description":"Register"}],"path":"templates/ui/blocks/auth","defaultOutput":"src/app/blocks/auth"},{"name":"settings","title":"Settings","description":"Settings pages: profile, notifications, security, danger zone","tags":["settings","preferences","account","profile","security"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card","@spartan-ng/helm/form-field","@spartan-ng/helm/switch"],"files":[{"id":"danger-zone","file":"danger-zone.component.ts","title":"Danger Zone","description":"Danger Zone"},{"id":"notification","file":"notification-settings.component.ts","title":"Notification Settings","description":"Notification Settings"},{"id":"profile","file":"profile-settings.component.ts","title":"Profile Settings","description":"Profile Settings"},{"id":"security","file":"security-settings.component.ts","title":"Security Settings","description":"Security Settings"}],"path":"templates/ui/blocks/settings","defaultOutput":"src/app/blocks/settings"},{"name":"shell","title":"Shell","description":"Application shell layouts: sidebar, topnav, collapsible - each with optional footer variant","tags":["shell","layout","sidebar","header","footer","navigation","topnav","collapsible"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/icon","@spartan-ng/helm/dropdown-menu"],"files":[{"id":"collapsible-footer","file":"collapsible-shell-footer.component.ts","title":"Collapsible Shell Footer","description":"Collapsible Shell Footer"},{"id":"collapsible","file":"collapsible-shell.component.ts","title":"Collapsible Shell","description":"Collapsible Shell"},{"id":"sidebar-footer","file":"sidebar-shell-footer.component.ts","title":"Sidebar Shell Footer","description":"Sidebar Shell Footer"},{"id":"sidebar","file":"sidebar-shell.component.ts","title":"Sidebar Shell","description":"Sidebar Shell"},{"id":"topnav-footer","file":"topnav-shell-footer.component.ts","title":"Topnav Shell Footer","description":"Topnav Shell Footer"},{"id":"topnav","file":"topnav-shell.component.ts","title":"Topnav Shell","description":"Topnav Shell"}],"path":"templates/ui/blocks/shell","defaultOutput":"src/app/blocks/shell"}]}}
|