vibe-design-system 2.5.18 → 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/package.json
CHANGED
|
@@ -445,7 +445,7 @@ 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
|
-
/** Yaygın required string prop isimleri için
|
|
448
|
+
/** Yaygın required string prop isimleri için fallback (sayfada kullanım bulunamazsa). */
|
|
449
449
|
const DEFAULT_STRINGS_BY_PROP_NAME = {
|
|
450
450
|
eyebrow: "Label",
|
|
451
451
|
title: "Section title",
|
|
@@ -456,29 +456,107 @@ const DEFAULT_STRINGS_BY_PROP_NAME = {
|
|
|
456
456
|
subtitle: "Subtitle text",
|
|
457
457
|
text: "Sample text",
|
|
458
458
|
label: "Label",
|
|
459
|
+
status: "Active",
|
|
460
|
+
sector: "Technology",
|
|
461
|
+
step: "01",
|
|
462
|
+
role: "Team Member",
|
|
459
463
|
};
|
|
460
464
|
|
|
461
|
-
/**
|
|
462
|
-
function
|
|
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) {
|
|
463
525
|
const argLines = [];
|
|
464
526
|
const lucideImports = new Set();
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
} else {
|
|
478
|
-
|
|
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);
|
|
479
552
|
}
|
|
480
|
-
}
|
|
481
|
-
|
|
553
|
+
}
|
|
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)},`);
|
|
482
560
|
}
|
|
483
561
|
}
|
|
484
562
|
return { argLines, lucideImports: [...lucideImports] };
|
|
@@ -723,7 +801,8 @@ function buildStoryFileContent(comp) {
|
|
|
723
801
|
|
|
724
802
|
// Props: manifest or parse from source for default args (LucideIcon, array types)
|
|
725
803
|
const effectiveProps = Array.isArray(comp.props) && comp.props.length > 0 ? comp.props : parsePropsFromSource(source);
|
|
726
|
-
const
|
|
804
|
+
const usageFromPages = findComponentUsageInPages(componentName, PROJECT_ROOT);
|
|
805
|
+
const { argLines: defaultArgLines, lucideImports } = buildDefaultArgsForRequiredProps(effectiveProps, usageFromPages);
|
|
727
806
|
const useReactNodeChildrenRender = !omitChildren && hasChildrenPropReactNode(effectiveProps);
|
|
728
807
|
|
|
729
808
|
// Skip story only if not a page and no export found
|