@tpitre/story-ui 4.12.0 → 4.13.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.
Files changed (94) hide show
  1. package/dist/cli/generateRegistry.d.ts +23 -0
  2. package/dist/cli/generateRegistry.d.ts.map +1 -0
  3. package/dist/cli/generateRegistry.js +155 -0
  4. package/dist/cli/index.js +19 -111
  5. package/dist/cli/setup.d.ts.map +1 -1
  6. package/dist/cli/setup.js +115 -4
  7. package/dist/cli/update.d.ts.map +1 -1
  8. package/dist/cli/update.js +26 -0
  9. package/dist/mcp-server/index.js +155 -22
  10. package/dist/mcp-server/routes/canvasGenerate.d.ts +25 -0
  11. package/dist/mcp-server/routes/canvasGenerate.d.ts.map +1 -0
  12. package/dist/mcp-server/routes/canvasGenerate.js +268 -0
  13. package/dist/mcp-server/routes/canvasIntent.d.ts +15 -0
  14. package/dist/mcp-server/routes/canvasIntent.d.ts.map +1 -0
  15. package/dist/mcp-server/routes/canvasIntent.js +553 -0
  16. package/dist/mcp-server/routes/canvasPreview.d.ts +14 -0
  17. package/dist/mcp-server/routes/canvasPreview.d.ts.map +1 -0
  18. package/dist/mcp-server/routes/canvasPreview.js +25 -0
  19. package/dist/mcp-server/routes/canvasSave.d.ts +13 -0
  20. package/dist/mcp-server/routes/canvasSave.d.ts.map +1 -0
  21. package/dist/mcp-server/routes/canvasSave.js +273 -0
  22. package/dist/mcp-server/routes/convertToStory.d.ts +17 -0
  23. package/dist/mcp-server/routes/convertToStory.d.ts.map +1 -0
  24. package/dist/mcp-server/routes/convertToStory.js +730 -0
  25. package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
  26. package/dist/mcp-server/routes/generateStory.js +18 -1
  27. package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
  28. package/dist/mcp-server/routes/generateStoryStream.js +38 -2
  29. package/dist/mcp-server/routes/manifest.d.ts +19 -0
  30. package/dist/mcp-server/routes/manifest.d.ts.map +1 -0
  31. package/dist/mcp-server/routes/manifest.js +100 -0
  32. package/dist/mcp-server/routes/voiceRender.d.ts +19 -0
  33. package/dist/mcp-server/routes/voiceRender.d.ts.map +1 -0
  34. package/dist/mcp-server/routes/voiceRender.js +329 -0
  35. package/dist/story-generator/configLoader.d.ts.map +1 -1
  36. package/dist/story-generator/configLoader.js +3 -3
  37. package/dist/story-generator/llm-providers/gemini-provider.js +1 -1
  38. package/dist/story-generator/llm-providers/openai-provider.js +1 -1
  39. package/dist/story-generator/manifestManager.d.ts +105 -0
  40. package/dist/story-generator/manifestManager.d.ts.map +1 -0
  41. package/dist/story-generator/manifestManager.js +265 -0
  42. package/dist/templates/StoryUI/StoryUIPanel.css +732 -0
  43. package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
  44. package/dist/templates/StoryUI/StoryUIPanel.js +432 -110
  45. package/dist/templates/StoryUI/StoryUIPanel.tsx +2509 -0
  46. package/dist/templates/StoryUI/index.tsx +2 -0
  47. package/dist/templates/StoryUI/voice/VoiceCanvas.d.ts +15 -0
  48. package/dist/templates/StoryUI/voice/VoiceCanvas.d.ts.map +1 -0
  49. package/dist/templates/StoryUI/voice/VoiceCanvas.js +477 -0
  50. package/dist/templates/StoryUI/voice/VoiceCanvas.tsx +702 -0
  51. package/dist/templates/StoryUI/voice/VoiceControls.d.ts +12 -0
  52. package/dist/templates/StoryUI/voice/VoiceControls.d.ts.map +1 -0
  53. package/dist/templates/StoryUI/voice/VoiceControls.js +73 -0
  54. package/dist/templates/StoryUI/voice/VoiceControls.tsx +167 -0
  55. package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.d.ts +14 -0
  56. package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.d.ts.map +1 -0
  57. package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.js +90 -0
  58. package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.tsx +168 -0
  59. package/dist/templates/StoryUI/voice/canvas/componentRegistry.d.ts +21 -0
  60. package/dist/templates/StoryUI/voice/canvas/componentRegistry.d.ts.map +1 -0
  61. package/dist/templates/StoryUI/voice/canvas/componentRegistry.js +24 -0
  62. package/dist/templates/StoryUI/voice/canvas/componentRegistry.ts +30 -0
  63. package/dist/templates/StoryUI/voice/canvas/operations.d.ts +8 -0
  64. package/dist/templates/StoryUI/voice/canvas/operations.d.ts.map +1 -0
  65. package/dist/templates/StoryUI/voice/canvas/operations.js +189 -0
  66. package/dist/templates/StoryUI/voice/canvas/operations.ts +233 -0
  67. package/dist/templates/StoryUI/voice/canvas/types.d.ts +89 -0
  68. package/dist/templates/StoryUI/voice/canvas/types.d.ts.map +1 -0
  69. package/dist/templates/StoryUI/voice/canvas/types.js +2 -0
  70. package/dist/templates/StoryUI/voice/canvas/types.ts +106 -0
  71. package/dist/templates/StoryUI/voice/types.d.ts +83 -0
  72. package/dist/templates/StoryUI/voice/types.d.ts.map +1 -0
  73. package/dist/templates/StoryUI/voice/types.js +2 -0
  74. package/dist/templates/StoryUI/voice/types.ts +114 -0
  75. package/dist/templates/StoryUI/voice/useVoiceInput.d.ts +3 -0
  76. package/dist/templates/StoryUI/voice/useVoiceInput.d.ts.map +1 -0
  77. package/dist/templates/StoryUI/voice/useVoiceInput.js +182 -0
  78. package/dist/templates/StoryUI/voice/useVoiceInput.ts +224 -0
  79. package/dist/templates/StoryUI/voice/voiceCommands.d.ts +8 -0
  80. package/dist/templates/StoryUI/voice/voiceCommands.d.ts.map +1 -0
  81. package/dist/templates/StoryUI/voice/voiceCommands.js +46 -0
  82. package/dist/templates/StoryUI/voice/voiceCommands.ts +54 -0
  83. package/package.json +4 -4
  84. package/templates/StoryUI/StoryUIPanel.css +732 -0
  85. package/templates/StoryUI/StoryUIPanel.tsx +456 -105
  86. package/templates/StoryUI/voice/VoiceCanvas.tsx +702 -0
  87. package/templates/StoryUI/voice/VoiceControls.tsx +167 -0
  88. package/templates/StoryUI/voice/canvas/ComponentRenderer.tsx +168 -0
  89. package/templates/StoryUI/voice/canvas/componentRegistry.ts +30 -0
  90. package/templates/StoryUI/voice/canvas/operations.ts +233 -0
  91. package/templates/StoryUI/voice/canvas/types.ts +106 -0
  92. package/templates/StoryUI/voice/types.ts +114 -0
  93. package/templates/StoryUI/voice/useVoiceInput.ts +224 -0
  94. package/templates/StoryUI/voice/voiceCommands.ts +54 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Component Registry Generator
3
+ *
4
+ * Generates a `componentRegistry.ts` file that maps component names to
5
+ * actual React/Vue/etc imports for use by the Voice Canvas ComponentRenderer.
6
+ *
7
+ * Design-system agnostic — uses existing component discovery to find
8
+ * components from npm packages, local directories, and custom elements.
9
+ *
10
+ * Called during `npx story-ui init` and can be re-run with `npx story-ui registry`.
11
+ */
12
+ export interface RegistryGeneratorOptions {
13
+ /** Working directory (defaults to cwd) */
14
+ cwd?: string;
15
+ /** Output path relative to cwd (defaults to src/stories/StoryUI/voice/canvas/) */
16
+ outputDir?: string;
17
+ }
18
+ /**
19
+ * Generate the component registry file using project's discovered components.
20
+ * Returns the path to the generated file.
21
+ */
22
+ export declare function generateComponentRegistry(options?: RegistryGeneratorOptions): Promise<string>;
23
+ //# sourceMappingURL=generateRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateRegistry.d.ts","sourceRoot":"","sources":["../../cli/generateRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDvG"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Component Registry Generator
3
+ *
4
+ * Generates a `componentRegistry.ts` file that maps component names to
5
+ * actual React/Vue/etc imports for use by the Voice Canvas ComponentRenderer.
6
+ *
7
+ * Design-system agnostic — uses existing component discovery to find
8
+ * components from npm packages, local directories, and custom elements.
9
+ *
10
+ * Called during `npx story-ui init` and can be re-run with `npx story-ui registry`.
11
+ */
12
+ import path from 'path';
13
+ import fs from 'fs';
14
+ import { loadUserConfig } from '../story-generator/configLoader.js';
15
+ import { EnhancedComponentDiscovery } from '../story-generator/enhancedComponentDiscovery.js';
16
+ /**
17
+ * Generate the component registry file using project's discovered components.
18
+ * Returns the path to the generated file.
19
+ */
20
+ export async function generateComponentRegistry(options = {}) {
21
+ const cwd = options.cwd || process.cwd();
22
+ // loadUserConfig reads from cwd — ensure we're in the right directory
23
+ const originalCwd = process.cwd();
24
+ if (cwd !== originalCwd)
25
+ process.chdir(cwd);
26
+ const config = loadUserConfig();
27
+ if (cwd !== originalCwd)
28
+ process.chdir(originalCwd);
29
+ // Discover components using the existing discovery system
30
+ const discovery = new EnhancedComponentDiscovery(config);
31
+ const components = await discovery.discoverAll();
32
+ const componentNames = components.map(c => c.name).sort();
33
+ if (componentNames.length === 0) {
34
+ console.warn('āš ļø No components discovered — registry will be empty');
35
+ }
36
+ const importPath = config.importPath || '@mantine/core';
37
+ const framework = config.componentFramework || 'react';
38
+ const importStyle = config.importStyle || 'barrel';
39
+ // Determine output directory
40
+ const outputDir = options.outputDir
41
+ ? path.resolve(cwd, options.outputDir)
42
+ : path.resolve(cwd, 'src/stories/StoryUI/voice/canvas');
43
+ if (!fs.existsSync(outputDir)) {
44
+ fs.mkdirSync(outputDir, { recursive: true });
45
+ }
46
+ const outputPath = path.join(outputDir, 'componentRegistry.ts');
47
+ // Generate the file content
48
+ let code;
49
+ if (framework === 'react') {
50
+ code = generateReactRegistry(componentNames, importPath, importStyle);
51
+ }
52
+ else if (framework === 'vue') {
53
+ code = generateVueRegistry(componentNames, importPath, importStyle);
54
+ }
55
+ else {
56
+ // Fallback: generic registry with dynamic imports note
57
+ code = generateGenericRegistry(componentNames, importPath, framework);
58
+ }
59
+ fs.writeFileSync(outputPath, code, 'utf-8');
60
+ console.log(`āœ… Component registry generated: ${path.relative(cwd, outputPath)} (${componentNames.length} components)`);
61
+ return outputPath;
62
+ }
63
+ // ── React registry generator ────────────────────────────────
64
+ function generateReactRegistry(names, importPath, importStyle) {
65
+ // Separate parent components from sub-components (e.g., "Card.Section")
66
+ const topLevel = names.filter(n => !n.includes('.'));
67
+ const subComponents = names.filter(n => n.includes('.'));
68
+ // For barrel imports, import all top-level from one path
69
+ // For individual imports, import each from its own path
70
+ let imports;
71
+ if (importStyle === 'individual') {
72
+ imports = topLevel.map(name => `import { ${name} } from '${importPath}/${name}';`).join('\n');
73
+ }
74
+ else {
75
+ // Barrel import — single line
76
+ imports = `import {\n${topLevel.map(n => ` ${n},`).join('\n')}\n} from '${importPath}';`;
77
+ }
78
+ // Build registry entries
79
+ const entries = topLevel.map(name => ` '${name}': ${name},`);
80
+ // Sub-components map automatically via dot-notation in ComponentRenderer
81
+ // e.g., "Card.Section" resolves to Card.Section at runtime
82
+ // But we still add them for explicit lookup
83
+ for (const sub of subComponents) {
84
+ const [parent, child] = sub.split('.');
85
+ entries.push(` '${sub}': (${parent} as any).${child},`);
86
+ }
87
+ return `/**
88
+ * Auto-generated component registry for Voice Canvas
89
+ * Source: ${importPath}
90
+ * Components: ${names.length}
91
+ *
92
+ * DO NOT EDIT — regenerate with: npx story-ui registry
93
+ */
94
+
95
+ ${imports}
96
+ import type { ComponentRegistry } from './ComponentRenderer';
97
+
98
+ export const registry: ComponentRegistry = {
99
+ ${entries.join('\n')}
100
+ };
101
+
102
+ export default registry;
103
+ `;
104
+ }
105
+ // ── Vue registry generator ──────────────────────────────────
106
+ function generateVueRegistry(names, importPath, importStyle) {
107
+ const topLevel = names.filter(n => !n.includes('.'));
108
+ let imports;
109
+ if (importStyle === 'individual') {
110
+ imports = topLevel.map(name => `import { ${name} } from '${importPath}/${name}';`).join('\n');
111
+ }
112
+ else {
113
+ imports = `import {\n${topLevel.map(n => ` ${n},`).join('\n')}\n} from '${importPath}';`;
114
+ }
115
+ const entries = topLevel.map(name => ` '${name}': ${name},`);
116
+ return `/**
117
+ * Auto-generated component registry for Voice Canvas (Vue)
118
+ * Source: ${importPath}
119
+ * Components: ${names.length}
120
+ *
121
+ * DO NOT EDIT — regenerate with: npx story-ui registry
122
+ */
123
+
124
+ ${imports}
125
+
126
+ export const registry: Record<string, any> = {
127
+ ${entries.join('\n')}
128
+ };
129
+
130
+ export default registry;
131
+ `;
132
+ }
133
+ // ── Generic fallback ────────────────────────────────────────
134
+ function generateGenericRegistry(names, importPath, framework) {
135
+ return `/**
136
+ * Auto-generated component registry for Voice Canvas (${framework})
137
+ * Source: ${importPath}
138
+ * Components: ${names.length}
139
+ *
140
+ * NOTE: This is a placeholder registry for ${framework}.
141
+ * You may need to customize imports for your framework.
142
+ *
143
+ * DO NOT EDIT — regenerate with: npx story-ui registry
144
+ */
145
+
146
+ // TODO: Add imports for ${framework} components from '${importPath}'
147
+ // ${names.map(n => `// import { ${n} } from '${importPath}';`).join('\n')}
148
+
149
+ export const registry: Record<string, any> = {
150
+ ${names.map(n => ` // '${n}': ${n},`).join('\n')}
151
+ };
152
+
153
+ export default registry;
154
+ `;
155
+ }
package/dist/cli/index.js CHANGED
@@ -10,11 +10,29 @@ import { updateCommand, statusCommand } from './update.js';
10
10
  import net from 'net';
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = path.dirname(__filename);
13
+ // Read version from package.json (try both src/cli and dist/cli paths)
14
+ const packageJsonPaths = [
15
+ path.resolve(__dirname, '..', 'package.json'), // From src/cli
16
+ path.resolve(__dirname, '..', '..', 'package.json'), // From dist/cli
17
+ ];
18
+ let packageVersion = 'unknown';
19
+ for (const p of packageJsonPaths) {
20
+ if (fs.existsSync(p)) {
21
+ try {
22
+ const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
23
+ if (pkg.version) {
24
+ packageVersion = pkg.version;
25
+ break;
26
+ }
27
+ }
28
+ catch { /* skip */ }
29
+ }
30
+ }
13
31
  const program = new Command();
14
32
  program
15
33
  .name('story-ui')
16
34
  .description('AI-powered Storybook story generator for React component libraries')
17
- .version('1.0.0');
35
+ .version(packageVersion);
18
36
  program
19
37
  .command('init')
20
38
  .description('Initialize Story UI configuration with interactive setup')
@@ -130,116 +148,6 @@ program
130
148
  console.log(`āœ… Sample configuration generated: ${filename}`);
131
149
  }
132
150
  });
133
- async function autoDetectAndCreateConfig() {
134
- const cwd = process.cwd();
135
- const config = {
136
- generatedStoriesPath: './src/stories/generated',
137
- storyPrefix: 'Generated/',
138
- defaultAuthor: 'Story UI AI',
139
- componentPrefix: '',
140
- layoutRules: {
141
- multiColumnWrapper: 'div',
142
- columnComponent: 'div',
143
- layoutExamples: {
144
- twoColumn: `<div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem'}}>
145
- <div>Column 1 content</div>
146
- <div>Column 2 content</div>
147
- </div>`
148
- },
149
- prohibitedElements: []
150
- }
151
- };
152
- // Try to detect package.json
153
- const packageJsonPath = path.join(cwd, 'package.json');
154
- if (fs.existsSync(packageJsonPath)) {
155
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
156
- config.importPath = packageJson.name || 'your-component-library';
157
- }
158
- // Try to detect components directory
159
- const possibleComponentPaths = [
160
- './src/components',
161
- './lib/components',
162
- './components',
163
- './src'
164
- ];
165
- for (const possiblePath of possibleComponentPaths) {
166
- if (fs.existsSync(path.join(cwd, possiblePath))) {
167
- config.componentsPath = possiblePath;
168
- break;
169
- }
170
- }
171
- writeConfig(config, 'js');
172
- }
173
- async function createTemplateConfig(template) {
174
- let config;
175
- switch (template) {
176
- case 'chakra-ui':
177
- config = {
178
- importPath: '@chakra-ui/react',
179
- componentPrefix: '',
180
- layoutRules: {
181
- multiColumnWrapper: 'SimpleGrid',
182
- columnComponent: 'Box',
183
- layoutExamples: {
184
- twoColumn: `<SimpleGrid columns={2} spacing={4}>
185
- <Box><Card>Left content</Card></Box>
186
- <Box><Card>Right content</Card></Box>
187
- </SimpleGrid>`
188
- }
189
- }
190
- };
191
- break;
192
- case 'ant-design':
193
- config = {
194
- importPath: 'antd',
195
- componentPrefix: '',
196
- layoutRules: {
197
- multiColumnWrapper: 'Row',
198
- columnComponent: 'Col',
199
- layoutExamples: {
200
- twoColumn: `<Row gutter={16}>
201
- <Col span={12}><Card>Left content</Card></Col>
202
- <Col span={12}><Card>Right content</Card></Col>
203
- </Row>`
204
- }
205
- }
206
- };
207
- break;
208
- default:
209
- throw new Error(`Unknown template: ${template}`);
210
- }
211
- // Add common defaults
212
- config = {
213
- generatedStoriesPath: './src/stories/generated',
214
- componentsPath: './src/components',
215
- storyPrefix: 'Generated/',
216
- defaultAuthor: 'Story UI AI',
217
- ...config
218
- };
219
- writeConfig(config, 'js');
220
- }
221
- async function createBasicConfig() {
222
- const config = {
223
- generatedStoriesPath: './src/stories/generated',
224
- componentsPath: './src/components',
225
- storyPrefix: 'Generated/',
226
- defaultAuthor: 'Story UI AI',
227
- importPath: 'your-component-library',
228
- componentPrefix: '',
229
- layoutRules: {
230
- multiColumnWrapper: 'div',
231
- columnComponent: 'div',
232
- layoutExamples: {
233
- twoColumn: `<div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem'}}>
234
- <div>Column 1 content</div>
235
- <div>Column 2 content</div>
236
- </div>`
237
- },
238
- prohibitedElements: []
239
- }
240
- };
241
- writeConfig(config, 'js');
242
- }
243
151
  function generateSampleConfig(filename, type) {
244
152
  const config = {
245
153
  generatedStoriesPath: './src/stories/generated',
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAmDA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;AAiWD,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,iBA85B5D"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAmDA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;AAoXD,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,iBA6/B5D"}
package/dist/cli/setup.js CHANGED
@@ -128,10 +128,19 @@ function setupStorybookPreview(designSystem) {
128
128
  const designSystemConfigs = {
129
129
  chakra: {
130
130
  imports: [
131
+ "import React from 'react'",
131
132
  "import type { Preview } from '@storybook/react-vite'",
132
- "import { ChakraProvider, defaultSystem } from '@chakra-ui/react'",
133
- "import React from 'react'"
133
+ "import * as ChakraUI from '@chakra-ui/react'",
134
134
  ],
135
+ globals: `
136
+ const { ChakraProvider, defaultSystem } = ChakraUI;
137
+
138
+ // Expose all Chakra components for Voice Canvas live preview.
139
+ // Voice Canvas uses these globals to render components without import statements.
140
+ (window as any).__STORY_UI_DESIGN_SYSTEM__ = ChakraUI;
141
+ (window as any).__STORY_UI_CANVAS_PROVIDER__ = ({ children }: { children: React.ReactNode }) => (
142
+ <ChakraProvider value={defaultSystem}>{children}</ChakraProvider>
143
+ );`,
135
144
  decorator: `(Story) => (
136
145
  <ChakraProvider value={defaultSystem}>
137
146
  <Story />
@@ -140,11 +149,20 @@ function setupStorybookPreview(designSystem) {
140
149
  },
141
150
  mantine: {
142
151
  imports: [
152
+ "import React from 'react'",
143
153
  "import type { Preview } from '@storybook/react-vite'",
144
- "import { MantineProvider } from '@mantine/core'",
154
+ "import * as MantineCore from '@mantine/core'",
145
155
  "import '@mantine/core/styles.css'",
146
- "import React from 'react'"
147
156
  ],
157
+ globals: `
158
+ const { MantineProvider } = MantineCore;
159
+
160
+ // Expose all Mantine components for Voice Canvas live preview.
161
+ // Voice Canvas uses these globals to render components without import statements.
162
+ (window as any).__STORY_UI_DESIGN_SYSTEM__ = MantineCore;
163
+ (window as any).__STORY_UI_CANVAS_PROVIDER__ = ({ children }: { children: React.ReactNode }) => (
164
+ <MantineProvider>{children}</MantineProvider>
165
+ );`,
148
166
  decorator: `(Story) => (
149
167
  <MantineProvider>
150
168
  <Story />
@@ -157,6 +175,7 @@ function setupStorybookPreview(designSystem) {
157
175
  return;
158
176
  // Create the preview content
159
177
  const previewContent = `${config.imports.join('\n')}
178
+ ${config.globals || ''}
160
179
 
161
180
  const preview: Preview = {
162
181
  parameters: {
@@ -917,6 +936,8 @@ Material UI (MUI) is a React component library implementing Material Design.
917
936
  // Copy component files
918
937
  const templatesDir = path.resolve(__dirname, '../../templates/StoryUI');
919
938
  const componentFiles = ['StoryUIPanel.tsx', 'StoryUIPanel.mdx', 'StoryUIPanel.css'];
939
+ // Voice Canvas files (subdirectory)
940
+ const voiceFiles = ['VoiceCanvas.tsx', 'VoiceControls.tsx', 'useVoiceInput.ts', 'voiceCommands.ts', 'types.ts'];
920
941
  console.log(chalk.blue('\nšŸ“¦ Installing Story UI component...'));
921
942
  for (const file of componentFiles) {
922
943
  const sourcePath = path.join(templatesDir, file);
@@ -934,6 +955,96 @@ Material UI (MUI) is a React component library implementing Material Design.
934
955
  console.warn(chalk.yellow(`āš ļø Template file not found: ${file}`));
935
956
  }
936
957
  }
958
+ // Copy Voice Canvas files
959
+ const voiceSourceDir = path.join(templatesDir, 'voice');
960
+ const voiceTargetDir = path.join(storyUITargetDir, 'voice');
961
+ if (fs.existsSync(voiceSourceDir)) {
962
+ if (!fs.existsSync(voiceTargetDir)) {
963
+ fs.mkdirSync(voiceTargetDir, { recursive: true });
964
+ }
965
+ for (const file of voiceFiles) {
966
+ const sourcePath = path.join(voiceSourceDir, file);
967
+ const targetPath = path.join(voiceTargetDir, file);
968
+ if (fs.existsSync(sourcePath)) {
969
+ fs.copyFileSync(sourcePath, targetPath);
970
+ console.log(chalk.green(`āœ… Copied voice/${file}`));
971
+ }
972
+ }
973
+ }
974
+ // Generate component registry for Voice Canvas with static design system import
975
+ // Vite requires static imports — bare specifiers can't be resolved at runtime
976
+ const canvasTargetDir = path.join(voiceTargetDir, 'canvas');
977
+ if (!fs.existsSync(canvasTargetDir)) {
978
+ fs.mkdirSync(canvasTargetDir, { recursive: true });
979
+ }
980
+ // Copy canvas template files (types.ts, operations.ts, ComponentRenderer.tsx)
981
+ const canvasSourceDir = path.join(voiceSourceDir, 'canvas');
982
+ if (fs.existsSync(canvasSourceDir)) {
983
+ for (const file of fs.readdirSync(canvasSourceDir)) {
984
+ if (file === 'componentRegistry.ts')
985
+ continue; // generated below
986
+ const src = path.join(canvasSourceDir, file);
987
+ const dst = path.join(canvasTargetDir, file);
988
+ if (fs.statSync(src).isFile()) {
989
+ fs.copyFileSync(src, dst);
990
+ console.log(chalk.green(`āœ… Copied voice/canvas/${file}`));
991
+ }
992
+ }
993
+ }
994
+ // Generate the registry with a lazy async import of the design system.
995
+ // Uses a literal string in import() so Vite resolves it at build time,
996
+ // but execution is deferred until loadRegistry() is called — avoiding
997
+ // module-level side effects that can crash the docs page.
998
+ if (config.importPath && config.importStyle !== 'individual') {
999
+ const registryContent = `/**
1000
+ * Component registry for Voice Canvas — lazy-loaded from design system.
1001
+ *
1002
+ * Uses dynamic import('${config.importPath}') with a literal string so Vite
1003
+ * resolves it at build time, but the import only executes when loadRegistry()
1004
+ * is called (not at module evaluation time). This prevents crashes from
1005
+ * module-level side effects.
1006
+ *
1007
+ * Generated by story-ui init. Regenerate with: npx story-ui registry
1008
+ */
1009
+
1010
+ export const registry: Record<string, any> = {};
1011
+
1012
+ let _loaded = false;
1013
+
1014
+ export async function loadRegistry(): Promise<Record<string, any>> {
1015
+ if (_loaded) return registry;
1016
+
1017
+ try {
1018
+ const mod = await import('${config.importPath}');
1019
+
1020
+ for (const [key, value] of Object.entries(mod)) {
1021
+ if (/^[A-Z]/.test(key) && (typeof value === 'function' || typeof value === 'object')) {
1022
+ registry[key] = value;
1023
+ }
1024
+ }
1025
+
1026
+ _loaded = true;
1027
+ console.log(\\\`[componentRegistry] Loaded \\\${Object.keys(registry).length} components from ${config.importPath}\\\`);
1028
+ } catch (err) {
1029
+ console.error('[componentRegistry] Failed to load design system:', err);
1030
+ }
1031
+
1032
+ return registry;
1033
+ }
1034
+
1035
+ export default registry;
1036
+ `;
1037
+ fs.writeFileSync(path.join(canvasTargetDir, 'componentRegistry.ts'), registryContent);
1038
+ console.log(chalk.green(`āœ… Generated voice/canvas/componentRegistry.ts with ${config.importPath} imports`));
1039
+ }
1040
+ else {
1041
+ // For individual import style or unknown, copy the placeholder
1042
+ const placeholderSrc = path.join(canvasSourceDir, 'componentRegistry.ts');
1043
+ if (fs.existsSync(placeholderSrc)) {
1044
+ fs.copyFileSync(placeholderSrc, path.join(canvasTargetDir, 'componentRegistry.ts'));
1045
+ }
1046
+ console.log(chalk.yellow(`āš ļø Voice Canvas registry is empty — populate voice/canvas/componentRegistry.ts manually`));
1047
+ }
937
1048
  // Configure Storybook bundler for StoryUIPanel requirements
938
1049
  console.log(chalk.blue('\nšŸ”§ Configuring Storybook for Story UI...'));
939
1050
  const mainConfigPath = path.join(process.cwd(), '.storybook', 'main.ts');
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../cli/update.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAgTD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkItF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CA+BpC"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../cli/update.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0UD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkItF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CA+BpC"}
@@ -26,6 +26,32 @@ const MANAGED_FILES = [
26
26
  source: 'templates/StoryUI/index.tsx',
27
27
  target: 'src/stories/StoryUI/index.tsx',
28
28
  description: 'Panel registration'
29
+ },
30
+ // Voice Canvas files
31
+ {
32
+ source: 'templates/StoryUI/voice/VoiceCanvas.tsx',
33
+ target: 'src/stories/StoryUI/voice/VoiceCanvas.tsx',
34
+ description: 'Voice Canvas component'
35
+ },
36
+ {
37
+ source: 'templates/StoryUI/voice/VoiceControls.tsx',
38
+ target: 'src/stories/StoryUI/voice/VoiceControls.tsx',
39
+ description: 'Voice control UI components'
40
+ },
41
+ {
42
+ source: 'templates/StoryUI/voice/useVoiceInput.ts',
43
+ target: 'src/stories/StoryUI/voice/useVoiceInput.ts',
44
+ description: 'Voice input hook'
45
+ },
46
+ {
47
+ source: 'templates/StoryUI/voice/voiceCommands.ts',
48
+ target: 'src/stories/StoryUI/voice/voiceCommands.ts',
49
+ description: 'Voice command definitions'
50
+ },
51
+ {
52
+ source: 'templates/StoryUI/voice/types.ts',
53
+ target: 'src/stories/StoryUI/voice/types.ts',
54
+ description: 'Voice module type definitions'
29
55
  }
30
56
  ];
31
57
  // Files that should NEVER be modified by update