vibe-design-system 2.8.5 → 2.8.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.8.5",
3
+ "version": "2.8.6",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -271,14 +271,10 @@ function collectProvidersAndWarnings(projectRoot) {
271
271
  providersToAdd.unshift({ name: "MemoryRouter", importPath: routerPackage, props: "{ initialEntries: [\"/\"] }" });
272
272
  console.log("[VDS] React Router tespit edildi → MemoryRouter decorator ekleniyor.");
273
273
  }
274
- if (detectReactDnd(projectRoot) && !providersToAdd.some((p) => p.name === "DndProvider")) {
275
- providersToAdd.unshift({
276
- name: "DndProvider",
277
- importPath: "react-dnd",
278
- props: "{ backend: HTML5Backend }",
279
- extraImport: { name: "HTML5Backend", from: "react-dnd-html5-backend" },
280
- });
281
- }
274
+ // NOTE: DndProvider intentionally NOT injected globally.
275
+ // react-dnd as a global Storybook decorator causes a dual-React-instance crash
276
+ // (Cannot read properties of null (reading 'useEffect')).
277
+ // Components using DnD are handled individually via ErrorBoundary.
282
278
  return { providersToAdd, hooksWithoutProvider, hooksByFile };
283
279
  }
284
280
 
@@ -1454,6 +1454,7 @@ function writeComponentSuggestionsStory(componentSuggestions) {
1454
1454
  const content =
1455
1455
  [
1456
1456
  "import type { Meta, StoryObj } from \"@storybook/react\";",
1457
+ "import { useState } from \"react\";",
1457
1458
  "",
1458
1459
  "const meta = { title: \"Foundations/Component Suggestions\" } satisfies Meta;",
1459
1460
  "export default meta;",
@@ -1461,19 +1462,60 @@ function writeComponentSuggestionsStory(componentSuggestions) {
1461
1462
  "",
1462
1463
  `const suggestions = ${JSON.stringify(suggestions)};`,
1463
1464
  "",
1465
+ "function buildPrompt(s: any) {",
1466
+ " const files = s.foundIn.join(', ');",
1467
+ " return [",
1468
+ " `Extract the repeated JSX pattern below into a new reusable React component named \\`${s.suggestedName}\\`.`,",
1469
+ " ``,",
1470
+ " `This pattern appears ${s.occurrences} time(s) across: ${files}`,",
1471
+ " ``,",
1472
+ " `Pattern:`,",
1473
+ " s.snippet,",
1474
+ " ``,",
1475
+ " `Instructions:`,",
1476
+ " `- Create a new file for ${s.suggestedName} with proper TypeScript props`,",
1477
+ " `- Replace all occurrences in the files above with the new component`,",
1478
+ " `- Keep existing styling and behavior exactly the same`,",
1479
+ " ].join('\\n');",
1480
+ "}",
1481
+ "",
1482
+ "function SuggestionCard({ s }: { s: any }) {",
1483
+ " const [copied, setCopied] = useState(false);",
1484
+ " const copy = () => {",
1485
+ " navigator.clipboard.writeText(buildPrompt(s)).then(() => {",
1486
+ " setCopied(true);",
1487
+ " setTimeout(() => setCopied(false), 2000);",
1488
+ " });",
1489
+ " };",
1490
+ " return (",
1491
+ " <div style={{ border: '1px solid #e2e8f0', borderRadius: 12, padding: 20, background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}>",
1492
+ " <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 12 }}>",
1493
+ " <div>",
1494
+ " <div style={{ fontWeight: 700, fontSize: 16, color: '#1a202c', marginBottom: 4 }}>{s.suggestedName}</div>",
1495
+ " <div style={{ fontSize: 12, color: '#718096' }}>{s.reason}</div>",
1496
+ " </div>",
1497
+ " <button onClick={copy} style={{ flexShrink: 0, marginLeft: 16, padding: '8px 16px', borderRadius: 8, border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: 13, background: copied ? '#48bb78' : '#6366f1', color: '#fff', transition: 'background 0.2s' }}>",
1498
+ " {copied ? '✅ Copied!' : '📋 Copy Prompt'}",
1499
+ " </button>",
1500
+ " </div>",
1501
+ " <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 12 }}>",
1502
+ " {s.foundIn.map((f: string, i: number) => (",
1503
+ " <span key={i} style={{ fontSize: 11, background: '#edf2f7', color: '#4a5568', padding: '2px 8px', borderRadius: 4, fontFamily: 'monospace' }}>{f}</span>",
1504
+ " ))}",
1505
+ " </div>",
1506
+ " <pre style={{ margin: 0, padding: 12, background: '#1a202c', borderRadius: 8, overflow: 'auto', fontSize: 12, color: '#e2e8f0', lineHeight: 1.6 }}><code>{s.snippet}</code></pre>",
1507
+ " <div style={{ marginTop: 10, fontSize: 12, color: '#a0aec0' }}>💡 Copy Prompt'a tıkla → Cursor / Superflex'e yapıştır → component otomatik oluşturulur.</div>",
1508
+ " </div>",
1509
+ " );",
1510
+ "}",
1511
+ "",
1464
1512
  "export const Default: Story = {",
1465
1513
  " render: () => (",
1466
- " <div style={{ padding: 24, fontFamily: \"system-ui, sans-serif\" }}>",
1467
- " <h2 style={{ marginBottom: 16 }}>Visual section candidates (component suggestions)</h2>",
1468
- " <p style={{ color: \"#888\", marginBottom: 24 }}>From src/pages, src/app ve src/components: kendi className kümeleri, 2+ child element, 2+ tekrar. Aynı yapı birden fazla dosyada geçiyorsa ayrı component olarak düşünün.</p>",
1469
- " <div style={{ display: \"flex\", flexDirection: \"column\", gap: 24 }}>",
1470
- " {suggestions.map((s, i) => (",
1471
- " <div key={i} style={{ border: \"1px solid #333\", borderRadius: 8, padding: 16, background: \"#111\" }}>",
1472
- " <div style={{ fontWeight: 600, marginBottom: 8 }}>{s.suggestedName}</div>",
1473
- " <div style={{ fontSize: 12, color: \"#888\", marginBottom: 8 }}>{s.reason} · {s.foundIn.join(\", \")}</div>",
1474
- " <pre style={{ margin: 0, padding: 12, background: \"#000\", borderRadius: 4, overflow: \"auto\", fontSize: 12 }}><code>{s.snippet}</code></pre>",
1475
- " </div>",
1476
- " ))}",
1514
+ " <div style={{ padding: 32, fontFamily: 'system-ui, sans-serif', background: '#f7fafc', minHeight: '100vh' }}>",
1515
+ " <h2 style={{ marginBottom: 8, fontSize: 24, fontWeight: 700, color: '#1a202c' }}>Component Suggestions</h2>",
1516
+ " <p style={{ color: '#718096', marginBottom: 32, fontSize: 14 }}>Bu pattern'ler birden fazla dosyada tekrar ediyor. Her biri ayrı bir component olabilir. <strong>Copy Prompt</strong> butonuna tıklayıp Cursor veya Superflex'e yapıştır.</p>",
1517
+ " <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>",
1518
+ " {suggestions.map((s: any, i: number) => <SuggestionCard key={i} s={s} />)}",
1477
1519
  " </div>",
1478
1520
  " </div>",
1479
1521
  " ),",
@@ -1548,22 +1590,25 @@ function main() {
1548
1590
  // ignore
1549
1591
  }
1550
1592
 
1551
- // Clear existing .stories.* files (except foundations/*.mdx) so only VDS-generated stories remain
1552
- try {
1553
- const existing = fs.readdirSync(STORIES_DIR);
1554
- for (const name of existing) {
1555
- if (name === "foundations") continue;
1556
- if (
1557
- name.endsWith(".stories.tsx") ||
1558
- name.endsWith(".stories.ts") ||
1559
- name.endsWith(".stories.jsx") ||
1560
- name.endsWith(".stories.js")
1561
- ) {
1562
- fs.unlinkSync(path.join(STORIES_DIR, name));
1593
+ // Clear existing .stories.* files only on full regeneration (no filter arg),
1594
+ // so that "node story-generator.mjs SomeName" doesn't wipe other stories.
1595
+ if (!onlyName) {
1596
+ try {
1597
+ const existing = fs.readdirSync(STORIES_DIR);
1598
+ for (const name of existing) {
1599
+ if (name === "foundations") continue;
1600
+ if (
1601
+ name.endsWith(".stories.tsx") ||
1602
+ name.endsWith(".stories.ts") ||
1603
+ name.endsWith(".stories.jsx") ||
1604
+ name.endsWith(".stories.js")
1605
+ ) {
1606
+ fs.unlinkSync(path.join(STORIES_DIR, name));
1607
+ }
1563
1608
  }
1609
+ } catch {
1610
+ // ignore
1564
1611
  }
1565
- } catch {
1566
- // ignore
1567
1612
  }
1568
1613
 
1569
1614
  for (const comp of components) {