@fr0mpy/component-system 2.2.0 → 3.1.0
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 +86 -27
- package/bin/cli.js +155 -62
- package/bin/validate-compliance.js +447 -0
- package/bin/validate-config.js +175 -0
- package/index.js +15 -0
- package/package.json +6 -4
- package/templates/agents/component-auditor.md +77 -0
- package/templates/agents/design-token-validator.md +72 -0
- package/templates/agents/harness-scaffolder.md +146 -0
- package/templates/agents/playwright-tester.md +437 -0
- package/templates/agents/style-inspector.md +81 -0
- package/templates/commands/component-harness.md +104 -10
- package/templates/commands/retheme.md +142 -0
- package/templates/commands/save-theme.md +50 -0
- package/templates/commands/setup-styling.md +386 -57
- package/templates/component-recipes/accordion.md +9 -9
- package/templates/component-recipes/alert.md +36 -23
- package/templates/component-recipes/avatar.md +14 -12
- package/templates/component-recipes/badge.md +9 -6
- package/templates/component-recipes/breadcrumb.md +4 -4
- package/templates/component-recipes/button.md +2 -2
- package/templates/component-recipes/checkbox.md +5 -5
- package/templates/component-recipes/collapsible.md +13 -13
- package/templates/component-recipes/combobox.md +2 -2
- package/templates/component-recipes/context-menu.md +11 -11
- package/templates/component-recipes/dialog.md +16 -16
- package/templates/component-recipes/drawer.md +18 -18
- package/templates/component-recipes/dropdown-menu.md +12 -12
- package/templates/component-recipes/hover-card.md +11 -11
- package/templates/component-recipes/label.md +4 -4
- package/templates/component-recipes/modal.md +9 -9
- package/templates/component-recipes/navigation-menu.md +19 -19
- package/templates/component-recipes/popover.md +10 -10
- package/templates/component-recipes/progress.md +10 -8
- package/templates/component-recipes/radio.md +6 -6
- package/templates/component-recipes/select.md +5 -5
- package/templates/component-recipes/separator.md +2 -2
- package/templates/component-recipes/slider.md +2 -2
- package/templates/component-recipes/switch.md +6 -6
- package/templates/component-recipes/table.md +1 -1
- package/templates/component-recipes/tabs.md +6 -6
- package/templates/component-recipes/toast.md +56 -42
- package/templates/component-recipes/toggle-group.md +4 -4
- package/templates/component-recipes/tooltip.md +5 -5
- package/templates/mcp/mcp.json +8 -0
- package/templates/playwright/playwright.config.ts +31 -0
- package/templates/playwright/tests/components.spec.ts +104 -0
- package/templates/skills/react-patterns.md +4 -0
- package/templates/skills/styling.md +141 -52
- package/templates/hooks/triggers.d/react-patterns.json +0 -18
- package/templates/hooks/triggers.d/styling.json +0 -23
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @fr0mpy/component-system
|
|
2
2
|
|
|
3
|
-
Claude Code UI styling system with design tokens,
|
|
3
|
+
Claude Code UI styling system with multi-theme support, design tokens, component agents, 40 Base UI recipes, and Playwright testing.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,36 +10,92 @@ npx @fr0mpy/component-system
|
|
|
10
10
|
|
|
11
11
|
## What's Included
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
| Directory | Purpose |
|
|
14
|
+
|-----------|---------|
|
|
15
|
+
| `skills/` | Styling + React patterns skills |
|
|
16
|
+
| `agents/` | 5 component system agents |
|
|
17
|
+
| `component-recipes/` | 40 Base UI component templates |
|
|
18
|
+
| `playwright-templates/` | Playwright test config + component specs |
|
|
19
|
+
| `commands/` | `/setup-styling`, `/component-harness`, `/save-theme`, `/retheme` |
|
|
20
|
+
| `.mcp.json` | Playwright MCP server configuration |
|
|
16
21
|
|
|
17
|
-
##
|
|
22
|
+
## Multi-Theme System
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
Create and switch between multiple themes in real-time:
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
```
|
|
27
|
+
.claude/
|
|
28
|
+
├── styling-config.json # Active theme config
|
|
29
|
+
├── themes/ # Saved themes
|
|
30
|
+
│ ├── stripe-inspired.json
|
|
31
|
+
│ ├── matrix.json
|
|
32
|
+
│ └── vercel-dark.json
|
|
33
|
+
└── component-recipes/ # Component templates
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Workflow
|
|
37
|
+
|
|
38
|
+
1. **Create themes** via `/setup-styling`:
|
|
39
|
+
- Extract from URL (analyzes any website's design system)
|
|
40
|
+
- Manual configuration (answer questions about colors, typography)
|
|
41
|
+
- Saves to both `styling-config.json` and `themes/{name}.json`
|
|
42
|
+
|
|
43
|
+
2. **Switch themes** in the component harness:
|
|
44
|
+
- ThemeSwitcher dropdown loads all `.claude/themes/*.json`
|
|
45
|
+
- Live switching via CSS variable injection
|
|
46
|
+
- No page reload required
|
|
47
|
+
|
|
48
|
+
3. **Quick commands**:
|
|
49
|
+
- `/save-theme [name]` - Save current config as a named theme
|
|
50
|
+
- `/retheme` - Regenerate CSS from current config
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
| Command | Purpose |
|
|
55
|
+
|---------|---------|
|
|
56
|
+
| `/setup-styling` | Configure design tokens, creates theme |
|
|
57
|
+
| `/component-harness` | Launch visual preview with theme switcher |
|
|
58
|
+
| `/save-theme` | Save current config as named theme |
|
|
59
|
+
| `/retheme` | Regenerate harness CSS from config |
|
|
60
|
+
|
|
61
|
+
## Agents (5)
|
|
62
|
+
|
|
63
|
+
| Agent | Purpose |
|
|
64
|
+
|-------|---------|
|
|
65
|
+
| style-inspector | Reverse-engineers website design systems from URLs |
|
|
66
|
+
| design-token-validator | Audits components for token compliance |
|
|
67
|
+
| component-auditor | Validates recipe compliance, a11y, React patterns |
|
|
68
|
+
| harness-scaffolder | Scaffolds Vite preview gallery from recipes |
|
|
69
|
+
| playwright-tester | Tests components via Playwright MCP with Axe a11y |
|
|
70
|
+
|
|
71
|
+
## Skills (2)
|
|
72
|
+
|
|
73
|
+
| Skill | Purpose |
|
|
74
|
+
|-------|---------|
|
|
75
|
+
| styling | Enforces design token usage, mobile-first patterns, recipe compliance |
|
|
76
|
+
| react-patterns | Enforces Rules of Hooks and correct state/effect patterns |
|
|
22
77
|
|
|
23
|
-
|
|
24
|
-
- Border radius
|
|
25
|
-
- Shadows
|
|
26
|
-
- Spacing
|
|
27
|
-
- Typography
|
|
78
|
+
## Component Recipes (40)
|
|
28
79
|
|
|
29
|
-
|
|
80
|
+
| Category | Components |
|
|
81
|
+
|----------|------------|
|
|
82
|
+
| **Form (10)** | button, input, textarea, select, combobox, checkbox, radio, switch, slider, label |
|
|
83
|
+
| **Layout (6)** | card, separator, collapsible, accordion, tabs, table |
|
|
84
|
+
| **Navigation (5)** | navigation-menu, breadcrumb, pagination, dropdown-menu, context-menu |
|
|
85
|
+
| **Overlay (6)** | modal, dialog, drawer, popover, hover-card, tooltip |
|
|
86
|
+
| **Feedback (5)** | alert, toast, progress, skeleton, spinner |
|
|
87
|
+
| **Display (4)** | badge, avatar, carousel, toggle-group |
|
|
30
88
|
|
|
31
|
-
|
|
89
|
+
All recipes use [Base UI](https://base-ui.com) headless primitives for accessibility with Tailwind CSS styling.
|
|
32
90
|
|
|
33
|
-
|
|
34
|
-
- **Layout** (6): card, separator, collapsible, accordion, tabs, table
|
|
35
|
-
- **Navigation** (5): navigation-menu, breadcrumb, pagination, dropdown-menu, context-menu
|
|
36
|
-
- **Overlay** (6): modal, dialog, drawer, popover, hover-card, tooltip
|
|
37
|
-
- **Feedback** (5): alert, toast, progress, skeleton, spinner
|
|
38
|
-
- **Display** (4): badge, avatar, carousel, toggle-group
|
|
91
|
+
## Component Harness
|
|
39
92
|
|
|
40
|
-
|
|
93
|
+
Run `/component-harness` to scaffold a Vite + React preview environment:
|
|
41
94
|
|
|
42
|
-
|
|
95
|
+
- **Theme Switcher** - Dropdown to switch between saved themes
|
|
96
|
+
- **Live Preview** - All 40 components with variants
|
|
97
|
+
- **Instant Updates** - CSS variable injection, no page reload
|
|
98
|
+
- **Playwright Testing** - Visual + accessibility testing via MCP
|
|
43
99
|
|
|
44
100
|
## Usage
|
|
45
101
|
|
|
@@ -47,13 +103,14 @@ Run `/component-harness` to scaffold a Vite + React development environment for
|
|
|
47
103
|
# Initialize
|
|
48
104
|
npx @fr0mpy/component-system
|
|
49
105
|
|
|
50
|
-
#
|
|
106
|
+
# Options
|
|
51
107
|
npx @fr0mpy/component-system --force # Overwrite existing
|
|
52
108
|
npx @fr0mpy/component-system --merge # Add to existing .claude
|
|
53
109
|
npx @fr0mpy/component-system --remove # Remove installation
|
|
54
110
|
|
|
55
111
|
# Selective updates
|
|
56
112
|
npx @fr0mpy/component-system --update-skills
|
|
113
|
+
npx @fr0mpy/component-system --update-agents
|
|
57
114
|
npx @fr0mpy/component-system --update-recipes
|
|
58
115
|
npx @fr0mpy/component-system --update-commands
|
|
59
116
|
```
|
|
@@ -61,18 +118,20 @@ npx @fr0mpy/component-system --update-commands
|
|
|
61
118
|
## Getting Started
|
|
62
119
|
|
|
63
120
|
1. Install: `npx @fr0mpy/component-system`
|
|
64
|
-
2. Configure:
|
|
65
|
-
3. Preview:
|
|
121
|
+
2. Configure: `/setup-styling` to create your first theme
|
|
122
|
+
3. Preview: `/component-harness` to launch visual gallery
|
|
123
|
+
4. Add themes: Run `/setup-styling` again to create more themes
|
|
124
|
+
5. Switch: Use the ThemeSwitcher dropdown in the harness
|
|
66
125
|
|
|
67
126
|
## Integration with Prompt System
|
|
68
127
|
|
|
69
|
-
For
|
|
128
|
+
For additional agents and context management:
|
|
70
129
|
|
|
71
130
|
```bash
|
|
72
131
|
npx @fr0mpy/prompt-system
|
|
73
132
|
```
|
|
74
133
|
|
|
75
|
-
|
|
134
|
+
Skills are automatically discovered via their `USE WHEN` descriptions in YAML frontmatter.
|
|
76
135
|
|
|
77
136
|
## License
|
|
78
137
|
|
package/bin/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
|
|
6
6
|
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
7
7
|
const TARGET_DIR = path.join(process.cwd(), '.claude');
|
|
8
|
+
const PROJECT_ROOT = process.cwd();
|
|
8
9
|
const args = process.argv.slice(2);
|
|
9
10
|
|
|
10
11
|
// Parse flags
|
|
@@ -16,7 +17,8 @@ const helpMode = hasFlag('--help', '-h');
|
|
|
16
17
|
const updateSkills = hasFlag('--update-skills');
|
|
17
18
|
const updateRecipes = hasFlag('--update-recipes');
|
|
18
19
|
const updateCommands = hasFlag('--update-commands');
|
|
19
|
-
const
|
|
20
|
+
const updateAgents = hasFlag('--update-agents');
|
|
21
|
+
const updateMode = updateSkills || updateRecipes || updateCommands || updateAgents;
|
|
20
22
|
|
|
21
23
|
function copyDir(src, dest) {
|
|
22
24
|
fs.mkdirSync(dest, { recursive: true });
|
|
@@ -52,37 +54,20 @@ function copySubdir(subdir) {
|
|
|
52
54
|
return true;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (const trigger of triggers) {
|
|
63
|
-
const src = path.join(TEMPLATES_DIR, 'hooks', 'triggers.d', trigger);
|
|
64
|
-
const dest = path.join(triggersDDir, trigger);
|
|
65
|
-
if (fs.existsSync(src)) {
|
|
66
|
-
fs.copyFileSync(src, dest);
|
|
67
|
-
injected = true;
|
|
68
|
-
}
|
|
57
|
+
function mergeJsonFile(src, dest) {
|
|
58
|
+
if (!fs.existsSync(src)) return false;
|
|
59
|
+
const srcData = JSON.parse(fs.readFileSync(src, 'utf8'));
|
|
60
|
+
let destData = {};
|
|
61
|
+
if (fs.existsSync(dest)) {
|
|
62
|
+
try { destData = JSON.parse(fs.readFileSync(dest, 'utf8')); } catch (e) { /* invalid JSON */ }
|
|
69
63
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const triggersDDir = path.join(TARGET_DIR, 'hooks', 'triggers.d');
|
|
75
|
-
const triggers = ['styling.json', 'react-patterns.json'];
|
|
76
|
-
let removed = false;
|
|
77
|
-
|
|
78
|
-
for (const trigger of triggers) {
|
|
79
|
-
const triggerPath = path.join(triggersDDir, trigger);
|
|
80
|
-
if (fs.existsSync(triggerPath)) {
|
|
81
|
-
fs.unlinkSync(triggerPath);
|
|
82
|
-
removed = true;
|
|
83
|
-
}
|
|
64
|
+
const merged = { ...destData, ...srcData };
|
|
65
|
+
// Deep merge mcpServers if both exist
|
|
66
|
+
if (destData.mcpServers && srcData.mcpServers) {
|
|
67
|
+
merged.mcpServers = { ...destData.mcpServers, ...srcData.mcpServers };
|
|
84
68
|
}
|
|
85
|
-
|
|
69
|
+
fs.writeFileSync(dest, JSON.stringify(merged, null, 2) + '\n');
|
|
70
|
+
return true;
|
|
86
71
|
}
|
|
87
72
|
|
|
88
73
|
async function init() {
|
|
@@ -95,7 +80,7 @@ async function init() {
|
|
|
95
80
|
if (componentSystemExists && !forceMode && !mergeMode) {
|
|
96
81
|
console.log('⚠️ Component system already exists in .claude/');
|
|
97
82
|
console.log(' Use --force to overwrite, --merge to update, or use selective updates:');
|
|
98
|
-
console.log(' --update-skills, --update-recipes, --update-commands\n');
|
|
83
|
+
console.log(' --update-skills, --update-recipes, --update-commands, --update-agents\n');
|
|
99
84
|
process.exit(1);
|
|
100
85
|
}
|
|
101
86
|
|
|
@@ -108,14 +93,39 @@ async function init() {
|
|
|
108
93
|
fs.mkdirSync(TARGET_DIR, { recursive: true });
|
|
109
94
|
|
|
110
95
|
if (forceMode && componentSystemExists) {
|
|
111
|
-
//
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
96
|
+
// Remove component-system specific skill files (preserve prompt-system skills)
|
|
97
|
+
const componentSkills = ['styling.md', 'react-patterns.md', 'style-inspector.md'];
|
|
98
|
+
const skillsDir = path.join(TARGET_DIR, 'skills');
|
|
99
|
+
if (fs.existsSync(skillsDir)) {
|
|
100
|
+
for (const skill of componentSkills) {
|
|
101
|
+
const skillPath = path.join(skillsDir, skill);
|
|
102
|
+
if (fs.existsSync(skillPath)) {
|
|
103
|
+
fs.unlinkSync(skillPath);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Remove component-system specific agent files
|
|
109
|
+
const componentAgents = [
|
|
110
|
+
'style-inspector.md', 'design-token-validator.md',
|
|
111
|
+
'component-auditor.md', 'harness-scaffolder.md', 'playwright-tester.md'
|
|
112
|
+
];
|
|
113
|
+
const agentsDir = path.join(TARGET_DIR, 'agents');
|
|
114
|
+
if (fs.existsSync(agentsDir)) {
|
|
115
|
+
for (const agent of componentAgents) {
|
|
116
|
+
const agentPath = path.join(agentsDir, agent);
|
|
117
|
+
if (fs.existsSync(agentPath)) {
|
|
118
|
+
fs.unlinkSync(agentPath);
|
|
119
|
+
}
|
|
117
120
|
}
|
|
118
121
|
}
|
|
122
|
+
|
|
123
|
+
// Remove component-recipes entirely (owned by component-system)
|
|
124
|
+
const recipesDir = path.join(TARGET_DIR, 'component-recipes');
|
|
125
|
+
if (fs.existsSync(recipesDir)) {
|
|
126
|
+
fs.rmSync(recipesDir, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
|
|
119
129
|
console.log('🗑️ Removed existing component system files.\n');
|
|
120
130
|
}
|
|
121
131
|
|
|
@@ -123,6 +133,20 @@ async function init() {
|
|
|
123
133
|
copyDir(path.join(TEMPLATES_DIR, 'skills'), path.join(TARGET_DIR, 'skills'));
|
|
124
134
|
copyDir(path.join(TEMPLATES_DIR, 'component-recipes'), path.join(TARGET_DIR, 'component-recipes'));
|
|
125
135
|
|
|
136
|
+
// Copy agents (merge into existing agents dir if prompt-system is installed)
|
|
137
|
+
const agentsDir = path.join(TARGET_DIR, 'agents');
|
|
138
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
139
|
+
copyDir(path.join(TEMPLATES_DIR, 'agents'), agentsDir);
|
|
140
|
+
|
|
141
|
+
// Migrate: remove style-inspector from skills if it exists (now an agent)
|
|
142
|
+
const oldStyleInspector = path.join(TARGET_DIR, 'skills', 'style-inspector.md');
|
|
143
|
+
if (fs.existsSync(oldStyleInspector)) {
|
|
144
|
+
fs.unlinkSync(oldStyleInspector);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Copy Playwright templates (staged for harness scaffolding)
|
|
148
|
+
copyDir(path.join(TEMPLATES_DIR, 'playwright'), path.join(TARGET_DIR, 'playwright-templates'));
|
|
149
|
+
|
|
126
150
|
// Copy styling commands
|
|
127
151
|
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
128
152
|
fs.mkdirSync(commandsDir, { recursive: true });
|
|
@@ -135,21 +159,24 @@ async function init() {
|
|
|
135
159
|
path.join(commandsDir, 'component-harness.md')
|
|
136
160
|
);
|
|
137
161
|
|
|
162
|
+
// Merge MCP configuration into project .mcp.json
|
|
163
|
+
const mcpSrc = path.join(TEMPLATES_DIR, 'mcp', 'mcp.json');
|
|
164
|
+
const mcpDest = path.join(PROJECT_ROOT, '.mcp.json');
|
|
165
|
+
if (mergeJsonFile(mcpSrc, mcpDest)) {
|
|
166
|
+
console.log('✅ Configured Playwright MCP server in .mcp.json');
|
|
167
|
+
}
|
|
168
|
+
|
|
138
169
|
console.log('✅ Created component system files:');
|
|
139
|
-
console.log(' 📁 skills/
|
|
140
|
-
console.log(' 📁
|
|
170
|
+
console.log(' 📁 skills/ - Styling + React patterns skills');
|
|
171
|
+
console.log(' 📁 agents/ - 5 component system agents');
|
|
172
|
+
console.log(' 📁 component-recipes/ - 38 component templates');
|
|
173
|
+
console.log(' 📁 playwright-templates/ - Playwright test config + specs');
|
|
141
174
|
console.log(' 📄 commands/setup-styling.md');
|
|
142
175
|
console.log(' 📄 commands/component-harness.md\n');
|
|
143
176
|
|
|
144
|
-
//
|
|
145
|
-
if (promptSystemExists) {
|
|
146
|
-
|
|
147
|
-
console.log('✅ Injected triggers into prompt system.');
|
|
148
|
-
console.log(' Styling and React patterns will auto-trigger on relevant prompts.\n');
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
console.log('ℹ️ Prompt system not detected.');
|
|
152
|
-
console.log(' For auto-triggering styling rules, also install:');
|
|
177
|
+
// Suggest prompt-system if not installed
|
|
178
|
+
if (!promptSystemExists) {
|
|
179
|
+
console.log('💡 For agents and prompt management, also install:');
|
|
153
180
|
console.log(' npx @fr0mpy/prompt-system\n');
|
|
154
181
|
}
|
|
155
182
|
|
|
@@ -166,8 +193,21 @@ async function update() {
|
|
|
166
193
|
|
|
167
194
|
const updates = [];
|
|
168
195
|
|
|
169
|
-
if (updateSkills && copySubdir('skills'))
|
|
196
|
+
if (updateSkills && copySubdir('skills')) {
|
|
197
|
+
// Migrate: remove style-inspector from skills if it exists
|
|
198
|
+
const oldStyleInspector = path.join(TARGET_DIR, 'skills', 'style-inspector.md');
|
|
199
|
+
if (fs.existsSync(oldStyleInspector)) {
|
|
200
|
+
fs.unlinkSync(oldStyleInspector);
|
|
201
|
+
}
|
|
202
|
+
updates.push('skills');
|
|
203
|
+
}
|
|
170
204
|
if (updateRecipes && copySubdir('component-recipes')) updates.push('component-recipes');
|
|
205
|
+
if (updateAgents) {
|
|
206
|
+
const agentsDir = path.join(TARGET_DIR, 'agents');
|
|
207
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
208
|
+
copyDir(path.join(TEMPLATES_DIR, 'agents'), agentsDir);
|
|
209
|
+
updates.push('agents');
|
|
210
|
+
}
|
|
171
211
|
if (updateCommands) {
|
|
172
212
|
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
173
213
|
fs.mkdirSync(commandsDir, { recursive: true });
|
|
@@ -198,16 +238,47 @@ function remove() {
|
|
|
198
238
|
// Check if prompt-system exists - if so, only remove component-system files
|
|
199
239
|
const hasHooks = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
|
|
200
240
|
|
|
201
|
-
const
|
|
241
|
+
const componentSkills = ['styling.md', 'react-patterns.md', 'style-inspector.md'];
|
|
242
|
+
const componentAgents = [
|
|
243
|
+
'style-inspector.md', 'design-token-validator.md',
|
|
244
|
+
'component-auditor.md', 'harness-scaffolder.md', 'playwright-tester.md'
|
|
245
|
+
];
|
|
202
246
|
const componentCommands = ['setup-styling.md', 'component-harness.md'];
|
|
203
247
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
248
|
+
// Remove component-system specific skill files (preserve prompt-system skills)
|
|
249
|
+
const skillsDir = path.join(TARGET_DIR, 'skills');
|
|
250
|
+
if (fs.existsSync(skillsDir)) {
|
|
251
|
+
for (const skill of componentSkills) {
|
|
252
|
+
const skillPath = path.join(skillsDir, skill);
|
|
253
|
+
if (fs.existsSync(skillPath)) {
|
|
254
|
+
fs.unlinkSync(skillPath);
|
|
255
|
+
}
|
|
208
256
|
}
|
|
209
257
|
}
|
|
210
258
|
|
|
259
|
+
// Remove component-system specific agent files (preserve prompt-system agents)
|
|
260
|
+
const agentsDir = path.join(TARGET_DIR, 'agents');
|
|
261
|
+
if (fs.existsSync(agentsDir)) {
|
|
262
|
+
for (const agent of componentAgents) {
|
|
263
|
+
const agentPath = path.join(agentsDir, agent);
|
|
264
|
+
if (fs.existsSync(agentPath)) {
|
|
265
|
+
fs.unlinkSync(agentPath);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Remove component-recipes entirely (owned by component-system)
|
|
271
|
+
const recipesDir = path.join(TARGET_DIR, 'component-recipes');
|
|
272
|
+
if (fs.existsSync(recipesDir)) {
|
|
273
|
+
fs.rmSync(recipesDir, { recursive: true });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Remove playwright-templates (owned by component-system)
|
|
277
|
+
const playwrightDir = path.join(TARGET_DIR, 'playwright-templates');
|
|
278
|
+
if (fs.existsSync(playwrightDir)) {
|
|
279
|
+
fs.rmSync(playwrightDir, { recursive: true });
|
|
280
|
+
}
|
|
281
|
+
|
|
211
282
|
// Remove styling commands
|
|
212
283
|
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
213
284
|
if (fs.existsSync(commandsDir)) {
|
|
@@ -219,15 +290,31 @@ function remove() {
|
|
|
219
290
|
}
|
|
220
291
|
}
|
|
221
292
|
|
|
222
|
-
// Remove triggers
|
|
223
|
-
removeTriggers();
|
|
224
|
-
|
|
225
293
|
// Remove styling-config.json if it exists
|
|
226
294
|
const stylingConfig = path.join(TARGET_DIR, 'styling-config.json');
|
|
227
295
|
if (fs.existsSync(stylingConfig)) {
|
|
228
296
|
fs.unlinkSync(stylingConfig);
|
|
229
297
|
}
|
|
230
298
|
|
|
299
|
+
// Clean up Playwright MCP config from .mcp.json
|
|
300
|
+
const mcpPath = path.join(PROJECT_ROOT, '.mcp.json');
|
|
301
|
+
if (fs.existsSync(mcpPath)) {
|
|
302
|
+
try {
|
|
303
|
+
const mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
|
304
|
+
if (mcpConfig.mcpServers?.playwright) {
|
|
305
|
+
delete mcpConfig.mcpServers.playwright;
|
|
306
|
+
if (Object.keys(mcpConfig.mcpServers).length === 0) {
|
|
307
|
+
delete mcpConfig.mcpServers;
|
|
308
|
+
}
|
|
309
|
+
if (Object.keys(mcpConfig).length === 0) {
|
|
310
|
+
fs.unlinkSync(mcpPath);
|
|
311
|
+
} else {
|
|
312
|
+
fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + '\n');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} catch (e) { /* .mcp.json may not be valid JSON */ }
|
|
316
|
+
}
|
|
317
|
+
|
|
231
318
|
if (hasHooks) {
|
|
232
319
|
console.log('✅ Removed component system files. Prompt system preserved.\n');
|
|
233
320
|
} else {
|
|
@@ -256,6 +343,7 @@ Selective updates:
|
|
|
256
343
|
--update-skills Update only skills/
|
|
257
344
|
--update-recipes Update only component-recipes/
|
|
258
345
|
--update-commands Update only styling commands
|
|
346
|
+
--update-agents Update only agents/
|
|
259
347
|
|
|
260
348
|
Options:
|
|
261
349
|
-h, --help Show this help message
|
|
@@ -264,16 +352,21 @@ Options:
|
|
|
264
352
|
-r, --remove Remove component system (alias: --uninstall)
|
|
265
353
|
|
|
266
354
|
What's included:
|
|
267
|
-
• skills/
|
|
268
|
-
•
|
|
269
|
-
|
|
355
|
+
• skills/ Styling + React patterns skills
|
|
356
|
+
• agents/ 5 component system agents (style-inspector,
|
|
357
|
+
design-token-validator, component-auditor,
|
|
358
|
+
harness-scaffolder, playwright-tester)
|
|
359
|
+
• component-recipes/ 38 pre-built component templates
|
|
360
|
+
• playwright-templates/ Playwright test config + component specs
|
|
361
|
+
• commands/ /setup-styling, /component-harness
|
|
362
|
+
• .mcp.json Playwright MCP server configuration
|
|
270
363
|
|
|
271
364
|
Getting started:
|
|
272
365
|
1. Run: npx @fr0mpy/component-system
|
|
273
366
|
2. Use: /setup-styling to configure your design system
|
|
274
|
-
3. Use: /component-harness to preview components
|
|
367
|
+
3. Use: /component-harness to preview and test components
|
|
275
368
|
|
|
276
|
-
For prompt injection and agents:
|
|
369
|
+
For prompt injection and additional agents:
|
|
277
370
|
npx @fr0mpy/prompt-system
|
|
278
371
|
|
|
279
372
|
Learn more: https://github.com/fr0mpy/claude-base-setup
|