vibe-design-system 2.5.17 → 2.5.20

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/bin/init.js CHANGED
@@ -49,6 +49,7 @@ export default config;
49
49
  const STORYBOOK_PREVIEW_TS = `import type { Preview } from "@storybook/react";
50
50
  import React from "react";
51
51
  import { MemoryRouter } from "react-router-dom";
52
+ // Uygulamanızla aynı stiller için: index.css + kullandığınız diğer global CSS dosyalarını ekleyin (örn. "../src/App.css").
52
53
  import "../src/index.css";
53
54
 
54
55
  const withRouter = (Story: any) => {
@@ -94,6 +95,8 @@ Geliştirme kuralları:
94
95
  - Variant'lar için cva() kullan
95
96
  - Tailwind CSS kullan
96
97
  - Named export veya default export — ikisi de çalışır
98
+
99
+ Storybook stilleri sayfalardan farklıysa: .storybook/preview.ts içinde uygulamanızın kullandığı tüm global CSS dosyalarını import edin (index.css dışında App.css, globals.css vb.).
97
100
  `;
98
101
 
99
102
  const WATCH_MJS = `#!/usr/bin/env node
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.5.17",
3
+ "version": "2.5.20",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -445,28 +445,120 @@ function parsePropsFromSource(source) {
445
445
  /** Default icon for LucideIcon prop when name is generic (icon, leftIcon, etc.). */
446
446
  const LUCIDE_ICON_DEFAULT = "Star";
447
447
 
448
- /** Build default args lines and lucide-react imports for required props (LucideIcon icon component, X[] → example item). */
449
- function buildDefaultArgsForRequiredProps(props) {
448
+ /** Yaygın required string prop isimleri için fallback (sayfada kullanım bulunamazsa). */
449
+ const DEFAULT_STRINGS_BY_PROP_NAME = {
450
+ eyebrow: "Label",
451
+ title: "Section title",
452
+ description: "Short description for the section.",
453
+ value: "100",
454
+ name: "Example",
455
+ heading: "Heading",
456
+ subtitle: "Subtitle text",
457
+ text: "Sample text",
458
+ label: "Label",
459
+ status: "Active",
460
+ sector: "Technology",
461
+ step: "01",
462
+ role: "Team Member",
463
+ };
464
+
465
+ /** Recursive list of .tsx file paths under dir (relative to dir). */
466
+ function getAllTsxUnderDir(dir) {
467
+ if (!fs.existsSync(dir)) return [];
468
+ const out = [];
469
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
470
+ for (const e of entries) {
471
+ const full = path.join(dir, e.name);
472
+ if (e.isDirectory()) {
473
+ out.push(...getAllTsxUnderDir(full).map((r) => path.join(e.name, r)));
474
+ } else if (e.isFile() && e.name.endsWith(".tsx")) {
475
+ out.push(e.name);
476
+ }
477
+ }
478
+ return out;
479
+ }
480
+
481
+ /** Extract prop="value" and prop='value' and prop={"value"} from JSX tag content. Returns { propName: "value", ... }. */
482
+ function extractPropsFromJsxTagContent(tagContent) {
483
+ const props = {};
484
+ let m;
485
+ const doubleQuoted = /\b(\w+)=["]([^"]*)["]/g;
486
+ while ((m = doubleQuoted.exec(tagContent)) !== null) props[m[1]] = m[2];
487
+ const singleQuoted = /\b(\w+)=[']([^']*)[']/g;
488
+ while ((m = singleQuoted.exec(tagContent)) !== null) if (props[m[1]] === undefined) props[m[1]] = m[2];
489
+ const jsxDouble = /\b(\w+)=\{"([^"]*)"\}/g;
490
+ while ((m = jsxDouble.exec(tagContent)) !== null) if (props[m[1]] === undefined) props[m[1]] = m[2];
491
+ const jsxSingle = /\b(\w+)=\{'([^']*)'\}/g;
492
+ while ((m = jsxSingle.exec(tagContent)) !== null) if (props[m[1]] === undefined) props[m[1]] = m[2];
493
+ return props;
494
+ }
495
+
496
+ /** Find first real usage of component in src/pages or src/app; return { propName: "literalValue", ... } or null. */
497
+ function findComponentUsageInPages(componentName, projectRoot) {
498
+ const srcDir = path.join(projectRoot, "src");
499
+ const pagesDir = path.join(srcDir, "pages");
500
+ const appDir = path.join(srcDir, "app");
501
+ const dirs = [];
502
+ if (fs.existsSync(pagesDir)) dirs.push(pagesDir);
503
+ if (fs.existsSync(appDir)) dirs.push(appDir);
504
+ const escapedName = componentName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
505
+ const tagOpenRe = new RegExp(`<${escapedName}\\s+([\\s\\S]*?)\\s*\\/?>`, "m");
506
+ for (const dir of dirs) {
507
+ const files = getAllTsxUnderDir(dir);
508
+ for (const rel of files) {
509
+ const fullPath = path.join(dir, rel);
510
+ try {
511
+ const content = fs.readFileSync(fullPath, "utf-8");
512
+ const match = content.match(tagOpenRe);
513
+ if (match) {
514
+ const props = extractPropsFromJsxTagContent(match[1]);
515
+ if (Object.keys(props).length > 0) return props;
516
+ }
517
+ } catch (_) {}
518
+ }
519
+ }
520
+ return null;
521
+ }
522
+
523
+ /** Build default args lines and lucide-react imports. usageFromPages: sayfadan çıkarılan gerçek prop değerleri (yoksa fallback). */
524
+ function buildDefaultArgsForRequiredProps(props, usageFromPages = null) {
450
525
  const argLines = [];
451
526
  const lucideImports = new Set();
452
- if (!Array.isArray(props) || props.length === 0) return { argLines, lucideImports: [] };
453
- for (const p of props) {
454
- if (p.required !== true) continue;
455
- const type = String(p.type || "").trim();
456
- const name = p.name;
457
- if (/LucideIcon|lucide-react/.test(type)) {
458
- const iconName = LUCIDE_ICON_DEFAULT;
459
- lucideImports.add(iconName);
460
- argLines.push(` ${name}: ${iconName},`);
461
- } else if (/\[\]/.test(type)) {
462
- if (/string\s*\[\]/.test(type)) {
463
- argLines.push(` ${name}: ["Example"],`);
464
- } else {
465
- // Object arrays ({ label, value } vb.) birçok component'te doğrudan child olarak render edilince hata verir; güvenli varsayılan boş dizi.
466
- argLines.push(` ${name}: [],`);
527
+ const fromPages = usageFromPages && typeof usageFromPages === "object" ? usageFromPages : {};
528
+ const added = new Set();
529
+ if (Array.isArray(props) && props.length > 0) {
530
+ for (const p of props) {
531
+ if (p.required !== true) continue;
532
+ const type = String(p.type || "").trim();
533
+ const name = p.name;
534
+ if (/LucideIcon|lucide-react/.test(type)) {
535
+ const iconName = LUCIDE_ICON_DEFAULT;
536
+ lucideImports.add(iconName);
537
+ argLines.push(` ${name}: ${iconName},`);
538
+ added.add(name);
539
+ } else if (/\[\]/.test(type)) {
540
+ if (/string\s*\[\]/.test(type)) {
541
+ argLines.push(` ${name}: ["Example"],`);
542
+ } else {
543
+ argLines.push(` ${name}: [],`);
544
+ }
545
+ added.add(name);
546
+ } else if (fromPages[name] !== undefined && fromPages[name] !== null) {
547
+ argLines.push(` ${name}: ${JSON.stringify(String(fromPages[name]))},`);
548
+ added.add(name);
549
+ } else if (/string/.test(type) && DEFAULT_STRINGS_BY_PROP_NAME[name] !== undefined) {
550
+ argLines.push(` ${name}: ${JSON.stringify(DEFAULT_STRINGS_BY_PROP_NAME[name])},`);
551
+ added.add(name);
467
552
  }
468
553
  }
469
554
  }
555
+ for (const name of Object.keys(fromPages)) {
556
+ if (added.has(name)) continue;
557
+ const val = fromPages[name];
558
+ if (val !== undefined && val !== null && typeof val === "string") {
559
+ argLines.push(` ${name}: ${JSON.stringify(val)},`);
560
+ }
561
+ }
470
562
  return { argLines, lucideImports: [...lucideImports] };
471
563
  }
472
564
 
@@ -709,7 +801,8 @@ function buildStoryFileContent(comp) {
709
801
 
710
802
  // Props: manifest or parse from source for default args (LucideIcon, array types)
711
803
  const effectiveProps = Array.isArray(comp.props) && comp.props.length > 0 ? comp.props : parsePropsFromSource(source);
712
- const { argLines: defaultArgLines, lucideImports } = buildDefaultArgsForRequiredProps(effectiveProps);
804
+ const usageFromPages = findComponentUsageInPages(componentName, PROJECT_ROOT);
805
+ const { argLines: defaultArgLines, lucideImports } = buildDefaultArgsForRequiredProps(effectiveProps, usageFromPages);
713
806
  const useReactNodeChildrenRender = !omitChildren && hasChildrenPropReactNode(effectiveProps);
714
807
 
715
808
  // Skip story only if not a page and no export found