@tpitre/story-ui 2.0.1 โ†’ 2.1.1

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/dist/cli/index.js CHANGED
@@ -6,7 +6,7 @@ import path from 'path';
6
6
  import { fileURLToPath } from 'url';
7
7
  import { setupProductionGitignore } from '../story-generator/productionGitignoreManager.js';
8
8
  import { createStoryUIConfig } from '../story-ui.config.js';
9
- import { setupCommand } from './setup.js';
9
+ import { setupCommand, cleanupDefaultStorybookComponents } from './setup.js';
10
10
  import net from 'net';
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = path.dirname(__filename);
@@ -249,4 +249,12 @@ function writeConfig(config, type, filename) {
249
249
  fs.writeFileSync(outputFile, jsContent);
250
250
  }
251
251
  }
252
+ program
253
+ .command('cleanup')
254
+ .description('Remove default Storybook template files that conflict with component discovery')
255
+ .action(() => {
256
+ console.log('๐Ÿงน Cleaning up default Storybook template files...');
257
+ cleanupDefaultStorybookComponents();
258
+ console.log('โœ… Cleanup complete! Component discovery should now work properly.');
259
+ });
252
260
  program.parse(process.argv);
package/dist/cli/setup.js CHANGED
@@ -31,40 +31,130 @@ async function findAvailablePort(startPort) {
31
31
  /**
32
32
  * Clean up default Storybook template components that could conflict with design system discovery
33
33
  */
34
- function cleanupDefaultStorybookComponents() {
35
- const storiesDir = path.join(process.cwd(), 'src', 'stories');
36
- // Common default Storybook files that cause conflicts
34
+ export function cleanupDefaultStorybookComponents() {
35
+ const possibleDirs = [
36
+ path.join(process.cwd(), 'src', 'stories'),
37
+ path.join(process.cwd(), 'stories'),
38
+ path.join(process.cwd(), '.storybook', 'stories')
39
+ ];
40
+ // Comprehensive list of default Storybook files that cause conflicts
37
41
  const defaultFiles = [
38
- 'Button.stories.ts',
39
- 'Button.stories.tsx',
40
- 'Header.stories.ts',
41
- 'Header.stories.tsx',
42
- 'Page.stories.ts',
43
- 'Page.stories.tsx',
44
- 'button.css',
45
- 'header.css',
46
- 'page.css',
47
- 'Button.tsx',
48
- 'Header.tsx',
49
- 'Page.tsx'
42
+ // Component files
43
+ 'Button.stories.ts', 'Button.stories.tsx', 'Button.stories.js', 'Button.stories.jsx',
44
+ 'Header.stories.ts', 'Header.stories.tsx', 'Header.stories.js', 'Header.stories.jsx',
45
+ 'Page.stories.ts', 'Page.stories.tsx', 'Page.stories.js', 'Page.stories.jsx',
46
+ 'Introduction.stories.ts', 'Introduction.stories.tsx', 'Introduction.stories.js', 'Introduction.stories.jsx',
47
+ 'Configure.stories.ts', 'Configure.stories.tsx', 'Configure.stories.js', 'Configure.stories.jsx',
48
+ // Component implementation files
49
+ 'Button.tsx', 'Button.ts', 'Button.jsx', 'Button.js',
50
+ 'Header.tsx', 'Header.ts', 'Header.jsx', 'Header.js',
51
+ 'Page.tsx', 'Page.ts', 'Page.jsx', 'Page.js',
52
+ // CSS files
53
+ 'button.css', 'header.css', 'page.css', 'introduction.css',
54
+ // MDX files
55
+ 'Introduction.stories.mdx', 'Configure.stories.mdx'
50
56
  ];
51
57
  let cleanedFiles = 0;
52
- for (const fileName of defaultFiles) {
53
- const filePath = path.join(storiesDir, fileName);
54
- if (fs.existsSync(filePath)) {
55
- try {
56
- fs.unlinkSync(filePath);
57
- cleanedFiles++;
58
- }
59
- catch (error) {
60
- console.warn(`Could not remove ${fileName}: ${error}`);
58
+ for (const storiesDir of possibleDirs) {
59
+ if (!fs.existsSync(storiesDir))
60
+ continue;
61
+ for (const fileName of defaultFiles) {
62
+ const filePath = path.join(storiesDir, fileName);
63
+ if (fs.existsSync(filePath)) {
64
+ try {
65
+ fs.unlinkSync(filePath);
66
+ cleanedFiles++;
67
+ }
68
+ catch (error) {
69
+ console.warn(`Could not remove ${fileName}: ${error}`);
70
+ }
61
71
  }
62
72
  }
63
73
  }
64
74
  if (cleanedFiles > 0) {
65
- console.log(chalk.green(`โœ… Cleaned up ${cleanedFiles} default Storybook template files to prevent conflicts`));
75
+ console.log(chalk.green(`โœ… Cleaned up ${cleanedFiles} default Storybook template files to prevent component discovery conflicts`));
66
76
  }
67
77
  }
78
+ /**
79
+ * Set up Storybook preview file with appropriate providers for design systems
80
+ */
81
+ function setupStorybookPreview(designSystem) {
82
+ const storybookDir = path.join(process.cwd(), '.storybook');
83
+ const previewTsPath = path.join(storybookDir, 'preview.ts');
84
+ const previewTsxPath = path.join(storybookDir, 'preview.tsx');
85
+ if (!fs.existsSync(storybookDir)) {
86
+ console.log(chalk.yellow('โš ๏ธ .storybook directory not found. Please run storybook init first.'));
87
+ return;
88
+ }
89
+ const designSystemConfigs = {
90
+ chakra: {
91
+ imports: [
92
+ "import type { Preview } from '@storybook/react-vite'",
93
+ "import { ChakraProvider, defaultSystem } from '@chakra-ui/react'",
94
+ "import React from 'react'"
95
+ ],
96
+ decorator: `(Story) => (
97
+ <ChakraProvider value={defaultSystem}>
98
+ <Story />
99
+ </ChakraProvider>
100
+ )`
101
+ },
102
+ antd: {
103
+ imports: [
104
+ "import type { Preview } from '@storybook/react-vite'",
105
+ "import { ConfigProvider } from 'antd'",
106
+ "import React from 'react'"
107
+ ],
108
+ decorator: `(Story) => (
109
+ <ConfigProvider>
110
+ <Story />
111
+ </ConfigProvider>
112
+ )`
113
+ },
114
+ mantine: {
115
+ imports: [
116
+ "import type { Preview } from '@storybook/react-vite'",
117
+ "import { MantineProvider } from '@mantine/core'",
118
+ "import '@mantine/core/styles.css'",
119
+ "import React from 'react'"
120
+ ],
121
+ decorator: `(Story) => (
122
+ <MantineProvider>
123
+ <Story />
124
+ </MantineProvider>
125
+ )`
126
+ }
127
+ };
128
+ const config = designSystemConfigs[designSystem];
129
+ if (!config)
130
+ return;
131
+ // Create the preview content
132
+ const previewContent = `${config.imports.join('\n')}
133
+
134
+ const preview: Preview = {
135
+ parameters: {
136
+ controls: {
137
+ matchers: {
138
+ color: /(background|color)$/i,
139
+ date: /Date$/i,
140
+ },
141
+ },
142
+ },
143
+ decorators: [
144
+ ${config.decorator},
145
+ ],
146
+ };
147
+
148
+ export default preview;
149
+ `;
150
+ // Remove existing preview.ts if it exists
151
+ if (fs.existsSync(previewTsPath)) {
152
+ fs.unlinkSync(previewTsPath);
153
+ }
154
+ // Create preview.tsx with JSX support
155
+ fs.writeFileSync(previewTsxPath, previewContent);
156
+ console.log(chalk.green(`โœ… Created .storybook/preview.tsx with ${designSystem} provider setup`));
157
+ }
68
158
  // Design system installation configurations
69
159
  const DESIGN_SYSTEM_CONFIGS = {
70
160
  antd: {
@@ -112,11 +202,56 @@ async function installDesignSystem(systemKey) {
112
202
  try {
113
203
  console.log(chalk.gray(`Running: ${installCommand}`));
114
204
  execSync(installCommand, { stdio: 'inherit' });
205
+ // Verify installation was successful by re-checking package.json
206
+ const updatedPackageJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
207
+ const updatedDeps = { ...updatedPackageJson.dependencies, ...updatedPackageJson.devDependencies };
208
+ const stillMissingPackages = config.packages.filter(pkg => !updatedDeps[pkg]);
209
+ if (stillMissingPackages.length > 0) {
210
+ throw new Error(`Installation failed: packages still missing: ${stillMissingPackages.join(', ')}`);
211
+ }
115
212
  console.log(chalk.green(`โœ… ${config.name} installed successfully!`));
116
213
  if (config.additionalSetup) {
117
- console.log(chalk.blue('\n๐Ÿ“‹ Additional setup required:'));
118
- console.log(chalk.gray(`Add this import to your main CSS/index file:`));
119
- console.log(chalk.cyan(`${config.additionalSetup}`));
214
+ // Try to automatically add CSS import for Mantine
215
+ if (systemKey === 'mantine') {
216
+ const cssFiles = [
217
+ path.join(process.cwd(), 'src', 'index.css'),
218
+ path.join(process.cwd(), 'src', 'main.css'),
219
+ path.join(process.cwd(), 'src', 'App.css')
220
+ ];
221
+ let cssAdded = false;
222
+ for (const cssFile of cssFiles) {
223
+ if (fs.existsSync(cssFile)) {
224
+ try {
225
+ const cssContent = fs.readFileSync(cssFile, 'utf-8');
226
+ if (!cssContent.includes('@mantine/core/styles.css')) {
227
+ const newContent = `@import "@mantine/core/styles.css";\n\n${cssContent}`;
228
+ fs.writeFileSync(cssFile, newContent);
229
+ console.log(chalk.green(`โœ… Added Mantine CSS import to ${path.relative(process.cwd(), cssFile)}`));
230
+ cssAdded = true;
231
+ break;
232
+ }
233
+ else {
234
+ console.log(chalk.blue(`โ„น๏ธ Mantine CSS already imported in ${path.relative(process.cwd(), cssFile)}`));
235
+ cssAdded = true;
236
+ break;
237
+ }
238
+ }
239
+ catch (error) {
240
+ console.warn(chalk.yellow(`โš ๏ธ Could not modify ${cssFile}:`, error));
241
+ }
242
+ }
243
+ }
244
+ if (!cssAdded) {
245
+ console.log(chalk.blue('\n๐Ÿ“‹ Manual setup required:'));
246
+ console.log(chalk.gray(`Add this import to your main CSS file:`));
247
+ console.log(chalk.cyan(`${config.additionalSetup}`));
248
+ }
249
+ }
250
+ else {
251
+ console.log(chalk.blue('\n๐Ÿ“‹ Additional setup required:'));
252
+ console.log(chalk.gray(`Add this import to your main CSS/index file:`));
253
+ console.log(chalk.cyan(`${config.additionalSetup}`));
254
+ }
120
255
  }
121
256
  return true;
122
257
  }
@@ -261,7 +396,27 @@ export async function setupCommand() {
261
396
  if (answers.installDesignSystem && ['antd', 'mantine', 'chakra'].includes(answers.designSystem)) {
262
397
  const installSuccess = await installDesignSystem(answers.designSystem);
263
398
  if (!installSuccess) {
264
- console.log(chalk.yellow('โš ๏ธ Installation failed but continuing with configuration...'));
399
+ console.log(chalk.red('โŒ Installation failed! Cannot continue without required dependencies.'));
400
+ console.log(chalk.yellow('Please install manually and run setup again:'));
401
+ const config = DESIGN_SYSTEM_CONFIGS[answers.designSystem];
402
+ console.log(chalk.cyan(`npm install ${config.packages.join(' ')}`));
403
+ process.exit(1);
404
+ }
405
+ }
406
+ else if (['antd', 'mantine', 'chakra'].includes(answers.designSystem)) {
407
+ // User declined installation - verify dependencies exist
408
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
409
+ if (fs.existsSync(packageJsonPath)) {
410
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
411
+ const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
412
+ const config = DESIGN_SYSTEM_CONFIGS[answers.designSystem];
413
+ const missingDeps = config.packages.filter(pkg => !allDeps[pkg]);
414
+ if (missingDeps.length > 0) {
415
+ console.log(chalk.red('โŒ Required dependencies missing:'), missingDeps.join(', '));
416
+ console.log(chalk.yellow('Please install them manually:'));
417
+ console.log(chalk.cyan(`npm install ${missingDeps.join(' ')}`));
418
+ process.exit(1);
419
+ }
265
420
  }
266
421
  }
267
422
  // Generate configuration
@@ -493,6 +648,10 @@ export async function setupCommand() {
493
648
  }
494
649
  // Clean up default Storybook template components to prevent conflicts
495
650
  cleanupDefaultStorybookComponents();
651
+ // Set up Storybook preview file for design systems that require JSX
652
+ if (['chakra', 'antd', 'mantine'].includes(answers.designSystem)) {
653
+ setupStorybookPreview(answers.designSystem);
654
+ }
496
655
  // Update package.json with convenience scripts
497
656
  if (packageJson) {
498
657
  const scripts = packageJson.scripts || {};
@@ -233,14 +233,24 @@ export class DynamicPackageDiscovery {
233
233
  * Get the type of an export
234
234
  */
235
235
  getExportType(value) {
236
+ // Handle undefined/null values
237
+ if (value === undefined || value === null) {
238
+ return 'unknown';
239
+ }
236
240
  const type = typeof value;
237
241
  if (type === 'function') {
238
- // Try to distinguish between function and class
239
- const fnString = value.toString();
240
- if (fnString.startsWith('class ') || /^function [A-Z]/.test(fnString)) {
241
- return 'class';
242
+ try {
243
+ // Try to distinguish between function and class
244
+ const fnString = value.toString();
245
+ if (fnString.startsWith('class ') || /^function [A-Z]/.test(fnString)) {
246
+ return 'class';
247
+ }
248
+ return 'function';
249
+ }
250
+ catch (error) {
251
+ // Some functions might not have toString() available
252
+ return 'function';
242
253
  }
243
- return 'function';
244
254
  }
245
255
  if (type === 'object' && value !== null) {
246
256
  return 'object';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpitre/story-ui",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "AI-powered Storybook story generator with dynamic component discovery",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",