@machinemetrics/mm-react-components 1.0.0-rc.1 → 1.0.0-rc.3

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * MM React Components - ASCII logo (single source of truth)
3
- * Used by: npx-init.cjs, init.cjs, install-skill.cjs
3
+ * Used by: init.cjs, install-skill.cjs
4
4
  */
5
5
 
6
6
  const ASCII_LOGO = [
@@ -532,19 +532,12 @@ export function transformCompoundComponents(input, compoundSpec) {
532
532
  };
533
533
  }
534
534
 
535
- export function transformJSX(
536
- input,
537
- _jsxSpecifiers,
538
- _usedSpecifiers,
539
- _applyMode,
540
- ) {
535
+ // JSX transform is implemented only in the CLI (bin/chakra-to-shadcn.js). This stub
536
+ // exists for internal use by analyzeImports in this file; do not rely on it for real transformations.
537
+ function transformJSX(input, _jsxSpecifiers, _usedSpecifiers, _applyMode) {
541
538
  if (!input) return { output: input, changed: false, replaced: [] };
542
- let output = input;
543
539
  const replaced = new Set();
544
- let changed = false;
545
- // The JSX transform implementation is identical to the original file; kept intact
546
- // ... For brevity in this refactor, we rely on the identical logic retained above when splitting modules.
547
- // To preserve behavior, import the same implementation from the original file here if needed.
548
- // For now, no-op merge; the actual logic was moved here verbatim above in the original script.
540
+ const changed = false;
541
+ const output = input;
549
542
  return { output, changed, replaced };
550
543
  }
@@ -1,22 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * MM React Components - Zero-Config Init Script
4
+ * MM React Components - Init Script
5
5
  *
6
- * Simple initialization script for the MachineMetrics React Components library
7
- * Uses the zero-config approach with pre-compiled CSS (no build tools needed)
6
+ * Run via: npx @machinemetrics/mm-react-components mm-init
7
+ * (or npx @machinemetrics/mm-react-components)
8
8
  */
9
9
 
10
- /* eslint-disable no-undef */
10
+ /* eslint-disable no-undef, no-unused-vars */
11
11
 
12
12
  const { execSync } = require('child_process');
13
13
  const fs = require('fs');
14
14
  const path = require('path');
15
15
  const readline = require('readline');
16
16
 
17
- const { ASCII_LOGO } = require(path.join(__dirname, 'ascii-logo.cjs'));
17
+ // Read the version from package.json
18
+ // When built, this script is at dist/scripts/init.cjs, so go up two levels
19
+ const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
20
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
21
+ const version = packageJson.version;
18
22
 
19
23
  // Colors for console output
24
+ const { ASCII_LOGO } = require(path.join(__dirname, 'ascii-logo.cjs'));
20
25
 
21
26
  const colors = {
22
27
  reset: '\x1b[0m',
@@ -25,6 +30,7 @@ const colors = {
25
30
  blue: '\x1b[34m',
26
31
  cyan: '\x1b[36m',
27
32
  yellow: '\x1b[33m',
33
+ red: '\x1b[31m',
28
34
  };
29
35
 
30
36
  function logLogo() {
@@ -35,6 +41,10 @@ function log(message, color = 'reset') {
35
41
  console.log(`${colors[color]}${message}${colors.reset}`);
36
42
  }
37
43
 
44
+ function logWarning(message) {
45
+ log(`⚠️ ${message}`, 'yellow');
46
+ }
47
+
38
48
  function detectChakraUI() {
39
49
  const packageJsonPath = path.join(process.cwd(), 'package.json');
40
50
  if (!fs.existsSync(packageJsonPath)) {
@@ -65,29 +75,85 @@ function askQuestion(question) {
65
75
  });
66
76
  }
67
77
 
78
+ function checkReactProject() {
79
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
80
+
81
+ if (!fs.existsSync(packageJsonPath)) {
82
+ log(
83
+ '❌ No package.json found. Please run this script from your React project root.',
84
+ 'red',
85
+ );
86
+ process.exit(1);
87
+ }
88
+
89
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
90
+
91
+ if (!packageJson.dependencies?.react && !packageJson.devDependencies?.react) {
92
+ log(
93
+ "❌ React not found in dependencies. Please ensure you're in a React project.",
94
+ 'red',
95
+ );
96
+ process.exit(1);
97
+ }
98
+
99
+ return packageJson;
100
+ }
101
+
68
102
  async function main() {
69
103
  logLogo();
70
- log('MM React Components - Zero-Config Setup', 'bright');
71
- log(
72
- 'Installing MachineMetrics React Components with pre-compiled CSS...\n',
73
- 'blue',
74
- );
104
+ log('MM React Components init', 'bright');
75
105
 
76
106
  try {
107
+ checkReactProject();
108
+
77
109
  // Check for Chakra UI before installation
78
110
  const hasChakra = detectChakraUI();
79
111
 
80
112
  // Install the component library
81
- log('📦 Installing MM React Components...', 'cyan');
82
- execSync('npm install @machinemetrics/mm-react-components@beta', {
113
+ log(`Installing @machinemetrics/mm-react-components@${version}...`, 'cyan');
114
+ execSync(`npm install @machinemetrics/mm-react-components@${version}`, {
83
115
  stdio: 'inherit',
84
116
  });
85
117
  log('✅ MM React Components installed', 'green');
86
118
 
87
- log('\n💡 Zero-config mode: No build tools needed!', 'yellow');
88
- log(' Using pre-compiled CSS (118 KB, 18 KB gzipped)\n', 'cyan');
119
+ // Check React version compatibility (minimal output)
120
+ try {
121
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
122
+ const reactVersion =
123
+ packageJson.dependencies?.react || packageJson.devDependencies?.react;
124
+
125
+ if (reactVersion && reactVersion.includes('18')) {
126
+ const versionMatch = reactVersion.match(/18\.(\d+)\./);
127
+ if (versionMatch && parseInt(versionMatch[1]) < 2) {
128
+ execSync(
129
+ 'npm install react@^18.2.0 react-dom@^18.2.0',
130
+ { stdio: 'inherit' },
131
+ );
132
+ }
133
+ log('React 18.2+ — compatible', 'green');
134
+ } else if (reactVersion && reactVersion.includes('19')) {
135
+ try {
136
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
137
+ const scriptsVersion = pkg.dependencies?.['react-scripts'];
138
+ if (scriptsVersion && scriptsVersion.includes('5.0')) {
139
+ execSync('npm install react-scripts@^5.0.0', { stdio: 'inherit' });
140
+ }
141
+ } catch (_e) {
142
+ /* ignore */
143
+ }
144
+ log('React 19 — compatible', 'green');
145
+ } else {
146
+ execSync(
147
+ 'npm install react@^18.2.0 react-dom@^18.2.0',
148
+ { stdio: 'inherit' },
149
+ );
150
+ log('React 18.2+ installed — compatible', 'green');
151
+ }
152
+ } catch (_error) {
153
+ log('React version check skipped', 'yellow');
154
+ }
89
155
 
90
- // Create simple CSS import (zero-config approach)
156
+ // Setup CSS (zero-config approach)
91
157
  const srcPath = path.join(process.cwd(), 'src');
92
158
  const indexCssPath = path.join(srcPath, 'index.css');
93
159
 
@@ -97,67 +163,96 @@ async function main() {
97
163
  log('✅ Created src/ directory', 'green');
98
164
  }
99
165
 
100
- if (fs.existsSync(indexCssPath)) {
101
- const cssContent = fs.readFileSync(indexCssPath, 'utf8');
102
- if (!cssContent.includes('@machinemetrics/mm-react-components')) {
103
- const newCssContent = `/* MM React Components - Pre-compiled CSS (zero-config) */
166
+ // Setup CSS with pre-compiled styles
167
+ const cssContent = `/* MM React Components - Pre-compiled CSS (zero-config) */
104
168
  @import '@machinemetrics/mm-react-components/styles';
169
+ `;
105
170
 
106
- ${cssContent}`;
107
- fs.writeFileSync(indexCssPath, newCssContent);
171
+ if (fs.existsSync(indexCssPath)) {
172
+ const existingContent = fs.readFileSync(indexCssPath, 'utf8');
173
+ if (!existingContent.includes('@machinemetrics/mm-react-components')) {
174
+ fs.writeFileSync(indexCssPath, cssContent + '\n' + existingContent);
108
175
  log('✅ Added MM styles import to existing index.css', 'green');
109
176
  } else {
110
177
  log('✅ MM styles import already present in index.css', 'green');
111
178
  }
112
179
  } else {
113
- const cssContent = `/* MM React Components - Pre-compiled CSS (zero-config) */
114
- @import '@machinemetrics/mm-react-components/styles';
115
- `;
116
-
117
180
  fs.writeFileSync(indexCssPath, cssContent);
118
181
  log('✅ Created index.css with MM styles import', 'green');
119
182
  }
120
183
 
121
- // Success message
122
- log('\n🎉 Zero-Config Setup Complete!', 'green');
123
- log('\n📚 Next steps:', 'bright');
124
- log(' 1. Add Carbide class to your root element:');
125
- log(' document.documentElement.classList.add("carbide")', 'cyan');
126
- log(' 2. Import components:');
127
- log(
128
- ' import { Button, Input } from "@machinemetrics/mm-react-components"',
129
- 'cyan',
184
+ // Concise summary for user or AI (examples are in GETTING_STARTED / skill)
185
+ log('\n--- Setup complete ---', 'green');
186
+ log(`Package: @machinemetrics/mm-react-components@${version}`, 'reset');
187
+ log('CSS: pre-compiled (118 KB, 18 KB gzipped); import in index.css. No build tools required.', 'reset');
188
+ log('\nRequired: Add class "carbide" to root:', 'bright');
189
+ log(' document.documentElement.classList.add("carbide")', 'cyan');
190
+ log('Import: import { Button, Input } from "@machinemetrics/mm-react-components"', 'cyan');
191
+ log('\nDocs: GETTING_STARTED.md, CSS_EXPORTS.md, DEPENDENCIES.md', 'reset');
192
+ log('Repo: https://github.com/machinemetrics/mm-react-components', 'reset');
193
+
194
+ // Offer Carbide AI skill installation
195
+ log('\nOptional: mm-carbide AI skill for Carbide-styled UI generation.', 'yellow');
196
+ const installSkillAnswer = await askQuestion(
197
+ ' Install the Carbide skill for your AI editor? (y/N): ',
130
198
  );
131
- log(' 3. Use components - everything is pre-styled and ready!');
132
-
133
- log('\n✅ What you got:', 'bright');
134
- log(' • Pre-compiled CSS with all Tailwind utilities');
135
- log(' • Carbide industrial theme');
136
- log(' Dark mode support');
137
- log(' • All component styles (focus, hover, etc.)');
138
- log(' • Google Fonts included');
139
-
140
- log('\n💡 No build tools needed!', 'yellow');
141
- log(' This is a zero-config setup - everything just works!');
142
-
143
- log('\n📖 Advanced setup (optional):', 'bright');
144
- log(' Want custom Tailwind config? See docs/DEPENDENCIES.md');
145
- log(' For theme-only CSS, see docs/CSS_EXPORTS.md');
199
+ if (
200
+ installSkillAnswer.toLowerCase() === 'y' ||
201
+ installSkillAnswer.toLowerCase() === 'yes'
202
+ ) {
203
+ const aiPrompt =
204
+ ' Which AI do you use? (1) Cursor (2) VS Code / GitHub Copilot (3) Claude Code (4) Gemini CLI: ';
205
+ const aiAnswer = (await askQuestion(aiPrompt)).trim().toLowerCase();
206
+ const targetMap = {
207
+ '1': 'cursor',
208
+ cursor: 'cursor',
209
+ '2': 'copilot',
210
+ copilot: 'copilot',
211
+ '3': 'claude',
212
+ claude: 'claude',
213
+ '4': 'gemini',
214
+ gemini: 'gemini',
215
+ };
216
+ const target = targetMap[aiAnswer] || 'cursor';
217
+ const scopePrompt =
218
+ ' Install for this project only or for your user (all projects)? (1) This project (2) User (global): ';
219
+ const scopeAnswer = (await askQuestion(scopePrompt)).trim().toLowerCase();
220
+ const scopeMap = {
221
+ '1': 'project',
222
+ project: 'project',
223
+ '2': 'user',
224
+ user: 'user',
225
+ global: 'user',
226
+ };
227
+ const scope = scopeMap[scopeAnswer] || 'project';
228
+ const installSkillPath = path.join(__dirname, 'install-skill.cjs');
229
+ if (fs.existsSync(installSkillPath)) {
230
+ try {
231
+ execSync(
232
+ `node "${installSkillPath}" --target=${target} --scope=${scope}`,
233
+ { stdio: 'inherit' },
234
+ );
235
+ } catch (err) {
236
+ log(' Could not run skill installer.', 'yellow');
237
+ log(
238
+ ' You can install later: npx @machinemetrics/mm-react-components mm-install-skill --target=<cursor|copilot|claude|gemini> [--scope=project|user]',
239
+ 'cyan',
240
+ );
241
+ }
242
+ } else {
243
+ log(' Skill installer not found; install later with mm-install-skill.', 'yellow');
244
+ }
245
+ }
146
246
 
147
247
  // Offer Chakra migration if detected
148
248
  if (hasChakra) {
149
- log('\n🔄 Chakra UI Detected!', 'yellow');
150
- log(
151
- ' We can help you migrate from Chakra UI to MM React Components\n',
152
- 'cyan',
153
- );
154
-
249
+ log('\nChakra UI detected. Migrate to MM React Components?', 'yellow');
155
250
  const answer = await askQuestion(
156
- ' Would you like to run the Chakra UI migration now? (y/N): ',
251
+ ' Would you like to run the Chakra UI migration now? (y/N): ',
157
252
  );
158
253
 
159
254
  if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
160
- log('\n🔄 Starting Chakra UI migration...', 'cyan');
255
+ log('\nRunning Chakra UI migration...', 'cyan');
161
256
 
162
257
  const migrationScriptPath = path.join(
163
258
  __dirname,
@@ -179,35 +274,27 @@ ${cssContent}`;
179
274
  stdio: 'inherit',
180
275
  },
181
276
  );
182
- log('\n✅ Chakra UI migration complete!', 'green');
277
+ log('\nChakra UI migration complete.', 'green');
183
278
  } catch (error) {
184
- log('\n⚠️ Migration encountered issues', 'yellow');
185
- log(` ${error.message}`, 'yellow');
279
+ log('\nMigration encountered issues', 'yellow');
280
+ log(` ${error.message}`, 'yellow');
186
281
  log(
187
- ' You can run it manually: node scripts/chakra-to-shadcn-migrator/chakra-to-shadcn.js',
282
+ ' You can run it manually: node scripts/chakra-to-shadcn-migrator/chakra-to-shadcn.js',
188
283
  'cyan',
189
284
  );
190
285
  }
191
286
  } else {
287
+ log('\nMigration script not found at expected location.', 'yellow');
192
288
  log(
193
- '\n⚠️ Migration script not found at expected location',
194
- 'yellow',
195
- );
196
- log(
197
- ' Clone the repo to access migration tools: https://github.com/machinemetrics/mm-react-components',
289
+ ' Clone the repo to access migration tools: https://github.com/machinemetrics/mm-react-components',
198
290
  'cyan',
199
291
  );
200
292
  }
201
293
  } else {
202
- log('\n No problem! You can migrate later with:', 'cyan');
203
- log(
204
- ' node scripts/chakra-to-shadcn-migrator/chakra-to-shadcn.js --apply',
205
- 'cyan',
206
- );
294
+ log(' Migrate later: node scripts/chakra-to-shadcn-migrator/... --apply', 'cyan');
207
295
  }
208
296
  }
209
297
 
210
- log('\n🚀 Happy coding!', 'cyan');
211
298
  } catch (error) {
212
299
  log(`❌ Setup failed: ${error.message}`, 'red');
213
300
  process.exit(1);
@@ -63,8 +63,13 @@ function copyRecursive(src, dest) {
63
63
  for (const item of items) {
64
64
  const srcPath = path.join(src, item);
65
65
  const destPath = path.join(dest, item);
66
+ const stat = fs.lstatSync(srcPath);
66
67
 
67
- if (fs.statSync(srcPath).isDirectory()) {
68
+ if (stat.isSymbolicLink()) {
69
+ // Do not follow symlinks (defense-in-depth)
70
+ continue;
71
+ }
72
+ if (stat.isDirectory()) {
68
73
  if (!fs.existsSync(destPath)) {
69
74
  fs.mkdirSync(destPath, { recursive: true });
70
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@machinemetrics/mm-react-components",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0-rc.3",
4
4
  "description": "Industrial-grade React components for manufacturing applications",
5
5
  "keywords": [
6
6
  "react",
@@ -19,6 +19,9 @@
19
19
  "url": "https://github.com/machinemetrics/mm-react-components/issues"
20
20
  },
21
21
  "license": "MIT",
22
+ "sideEffects": [
23
+ "*.css"
24
+ ],
22
25
  "type": "module",
23
26
  "main": "dist/mm-react-components.umd.js",
24
27
  "module": "dist/mm-react-components.es.js",
@@ -58,8 +61,9 @@
58
61
  }
59
62
  },
60
63
  "bin": {
64
+ "mm-react-components": "dist/scripts/init.cjs",
61
65
  "chakra-to-shadcn": "dist/scripts/chakra-to-shadcn-migrator/bin/chakra-to-shadcn.js",
62
- "mm-init": "dist/scripts/npx-init.cjs",
66
+ "mm-init": "dist/scripts/init.cjs",
63
67
  "mm-install-skill": "dist/scripts/install-skill.cjs"
64
68
  },
65
69
  "scripts": {
@@ -144,12 +148,10 @@
144
148
  "input-otp": "^1.4.2",
145
149
  "lucide-react": "^0.562.0",
146
150
  "next-themes": "^0.4.6",
147
- "prism-react-renderer": "^2.4.1",
148
151
  "react": "^18.2.0 || ^19.0.0",
149
152
  "react-day-picker": "^9.13.0",
150
153
  "react-dom": "^18.2.0 || ^19.0.0",
151
154
  "react-dropzone": "14.3.8",
152
- "react-element-to-jsx-string": "^17.0.1",
153
155
  "react-hook-form": "^7.71.0",
154
156
  "react-resizable-panels": "^4.5.2",
155
157
  "recharts": "^2.15.4",
@@ -183,7 +185,9 @@
183
185
  "eslint-plugin-react-refresh": "^0.4.26",
184
186
  "globals": "^17.0.0",
185
187
  "playwright": "^1.57.0",
188
+ "prism-react-renderer": "^2.4.1",
186
189
  "prettier": "^3.7.4",
190
+ "react-element-to-jsx-string": "^17.0.1",
187
191
  "tailwindcss": "^4.1.18",
188
192
  "terser": "^5.44.1",
189
193
  "tsx": "^4.21.0",