vibe-design-system 2.8.2 → 2.8.3
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
|
@@ -951,6 +951,17 @@ function writeVdsGeneratedComponents(suggestions) {
|
|
|
951
951
|
|
|
952
952
|
let bodyJsx;
|
|
953
953
|
const tokens = [];
|
|
954
|
+
// Known shadcn/UI component names — not Lucide icons
|
|
955
|
+
const KNOWN_UI_COMPONENTS = new Set([
|
|
956
|
+
"Button", "Card", "CardHeader", "CardTitle", "CardContent", "CardFooter",
|
|
957
|
+
"Input", "Label", "Textarea", "Select", "Checkbox", "Switch", "Badge",
|
|
958
|
+
"Avatar", "Dialog", "Sheet", "Drawer", "Tooltip", "Popover", "Tabs",
|
|
959
|
+
"Table", "Accordion", "Alert", "Toast", "Form", "Skeleton", "Separator",
|
|
960
|
+
"Progress", "Slider", "RadioGroup", "Toggle", "Command", "Calendar",
|
|
961
|
+
"DropdownMenu", "ContextMenu", "NavigationMenu", "Menubar", "HoverCard",
|
|
962
|
+
"Collapsible", "ScrollArea", "AspectRatio", "Carousel", "Resizable",
|
|
963
|
+
"Link", "Nav", "Header", "Footer", "Section", "Container", "Wrapper",
|
|
964
|
+
]);
|
|
954
965
|
if (s.fullJsx && s.fullJsx.trim().length > 0) {
|
|
955
966
|
bodyJsx = flattenJsx(s.fullJsx);
|
|
956
967
|
bodyJsx = convertHtmlStyleToReact(bodyJsx);
|
|
@@ -958,17 +969,28 @@ function writeVdsGeneratedComponents(suggestions) {
|
|
|
958
969
|
const lucideTags = [];
|
|
959
970
|
const uiTags = [];
|
|
960
971
|
for (const tag of componentTags) {
|
|
961
|
-
if (
|
|
962
|
-
|
|
972
|
+
if (KNOWN_UI_COMPONENTS.has(tag)) {
|
|
973
|
+
uiTags.push(tag);
|
|
974
|
+
} else if (/^[A-Z][a-zA-Z0-9]+$/.test(tag) && tag.length > 2) {
|
|
975
|
+
lucideTags.push(tag); // likely a Lucide icon or unknown component
|
|
976
|
+
} else {
|
|
977
|
+
uiTags.push(tag);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
if (lucideTags.length > 0) {
|
|
981
|
+
bodyJsx = applyLucideNamespace(bodyJsx, lucideTags);
|
|
982
|
+
}
|
|
983
|
+
const importLines = ['import React from "react";'];
|
|
984
|
+
if (bodyJsx.includes("motion.") || bodyJsx.includes("<motion")) {
|
|
985
|
+
importLines.push('import { motion } from "framer-motion";');
|
|
986
|
+
}
|
|
987
|
+
if (lucideTags.length > 0) {
|
|
988
|
+
importLines.push('import * as LucideIcons from "lucide-react";');
|
|
989
|
+
}
|
|
990
|
+
for (const tag of uiTags) {
|
|
991
|
+
if (!KNOWN_UI_COMPONENTS.has(tag)) continue;
|
|
992
|
+
importLines.push(`import { ${tag} } from "@/components/ui/${toKebab(tag)}";`);
|
|
963
993
|
}
|
|
964
|
-
bodyJsx = applyLucideNamespace(bodyJsx, lucideTags);
|
|
965
|
-
const standardImports = [
|
|
966
|
-
'import React from "react";',
|
|
967
|
-
'import { motion } from "framer-motion";',
|
|
968
|
-
'import * as LucideIcons from "lucide-react";',
|
|
969
|
-
];
|
|
970
|
-
const uiImportLines = uiTags.map((tag) => `import { ${tag} } from "@/components/ui/${toKebab(tag)}";`);
|
|
971
|
-
const importLines = [...standardImports, ...uiImportLines];
|
|
972
994
|
const content = importLines.join("\n") + "\n\n" +
|
|
973
995
|
`export function ${componentName}() {\n return (\n ` +
|
|
974
996
|
bodyJsx.replace(/\n/g, "\n ") + "\n );\n}\n";
|
|
@@ -978,16 +1000,7 @@ function writeVdsGeneratedComponents(suggestions) {
|
|
|
978
1000
|
const tagName = s.tagName || "div";
|
|
979
1001
|
const className = s.pattern || "";
|
|
980
1002
|
bodyJsx = `<${tagName} className="${className.replace(/"/g, '\\"')}">\n {null}\n </${tagName}>`;
|
|
981
|
-
const content = `import React from "react"
|
|
982
|
-
import { motion } from "framer-motion";
|
|
983
|
-
import * as LucideIcons from "lucide-react";
|
|
984
|
-
|
|
985
|
-
export function ${componentName}() {
|
|
986
|
-
return (
|
|
987
|
-
${bodyJsx}
|
|
988
|
-
);
|
|
989
|
-
}
|
|
990
|
-
`;
|
|
1003
|
+
const content = `import React from "react";\n\nexport function ${componentName}() {\n return (\n ${bodyJsx}\n );\n}\n`;
|
|
991
1004
|
fs.writeFileSync(fullPath, content, "utf-8");
|
|
992
1005
|
tokens.push(...(className || "").split(/\s+/).filter(Boolean));
|
|
993
1006
|
}
|
|
@@ -995,8 +1008,9 @@ export function ${componentName}() {
|
|
|
995
1008
|
entries.push({
|
|
996
1009
|
file: relPath,
|
|
997
1010
|
name: componentName.replace(/([A-Z])/g, " $1").trim(),
|
|
998
|
-
|
|
999
|
-
|
|
1011
|
+
exportName: componentName,
|
|
1012
|
+
group: "Generated",
|
|
1013
|
+
category: "Generated",
|
|
1000
1014
|
description: "Auto-extracted from repeated className patterns.",
|
|
1001
1015
|
tokens: [...new Set(tokens)],
|
|
1002
1016
|
occurrences: s.occurrences ?? 0,
|
|
@@ -1635,6 +1649,7 @@ function scan() {
|
|
|
1635
1649
|
engineer: getGitEngineer(),
|
|
1636
1650
|
scannedAt: new Date().toISOString(),
|
|
1637
1651
|
totalComponents: results.length,
|
|
1652
|
+
componentsRelDir: COMPONENTS_DIR ? path.relative(PROJECT_ROOT, COMPONENTS_DIR).replace(/\\/g, "/") : "src/components",
|
|
1638
1653
|
components: results,
|
|
1639
1654
|
foundations,
|
|
1640
1655
|
componentSuggestions,
|
|
@@ -22,6 +22,8 @@ const STORIES_DIR = path.join(SRC_DIR, "stories");
|
|
|
22
22
|
|
|
23
23
|
// Filled in main() after reading vds-output.json so helpers (buildSpecialStories) can see foundations data (e.g. buttonUsage).
|
|
24
24
|
let FOUNDATIONS_DATA = null;
|
|
25
|
+
// componentsRelDir from vds-output.json — defaults to "src/components"
|
|
26
|
+
let COMPONENTS_REL_DIR = "src/components";
|
|
25
27
|
|
|
26
28
|
// CSS is loaded from .storybook/preview.tsx — never add CSS import to story files.
|
|
27
29
|
|
|
@@ -1052,12 +1054,18 @@ function buildRecipeStoryContent(comp, componentName, importPath, title, source,
|
|
|
1052
1054
|
function buildStoryFileContent(comp) {
|
|
1053
1055
|
const componentName = toSafeComponentName(comp.name, comp.file);
|
|
1054
1056
|
const fileNoExt = comp.file.replace(/\.(tsx|jsx)$/, "");
|
|
1057
|
+
// Compute import path relative to src/stories/ using the actual components directory.
|
|
1055
1058
|
let importPath = "";
|
|
1056
|
-
|
|
1057
|
-
|
|
1059
|
+
const isPageFile = fileNoExt.startsWith("pages/") || fileNoExt.startsWith("src/pages/");
|
|
1060
|
+
if (isPageFile) {
|
|
1061
|
+
const normalized = fileNoExt.replace(/^src\//, "");
|
|
1062
|
+
importPath = path.posix.relative("src/stories", normalized);
|
|
1058
1063
|
} else {
|
|
1059
|
-
|
|
1064
|
+
const targetPath = path.posix.join(COMPONENTS_REL_DIR, fileNoExt);
|
|
1065
|
+
importPath = path.posix.relative("src/stories", targetPath);
|
|
1060
1066
|
}
|
|
1067
|
+
if (!importPath.startsWith(".")) importPath = "./" + importPath;
|
|
1068
|
+
|
|
1061
1069
|
const group = comp.group || "Components";
|
|
1062
1070
|
const category = comp.category || null;
|
|
1063
1071
|
const titleParts = [group, category, componentName].filter(Boolean);
|
|
@@ -1067,9 +1075,9 @@ function buildStoryFileContent(comp) {
|
|
|
1067
1075
|
const variantProp = props.find((p) => p.name === "variant");
|
|
1068
1076
|
let variants = parseUnionLiterals(variantProp && variantProp.type);
|
|
1069
1077
|
|
|
1070
|
-
const srcPath =
|
|
1071
|
-
? path.join(
|
|
1072
|
-
: path.join(
|
|
1078
|
+
const srcPath = isPageFile
|
|
1079
|
+
? path.join(PROJECT_ROOT, fileNoExt.replace(/^src\//, "src/") + ".tsx")
|
|
1080
|
+
: path.join(PROJECT_ROOT, COMPONENTS_REL_DIR, comp.file);
|
|
1073
1081
|
|
|
1074
1082
|
// Fallback: if manifest doesn't have variant metadata yet, parse cva() directly from component file.
|
|
1075
1083
|
if (!variants.length) {
|
|
@@ -1105,7 +1113,7 @@ function buildStoryFileContent(comp) {
|
|
|
1105
1113
|
}
|
|
1106
1114
|
const exportStyle = detectExportStyle(source, componentName);
|
|
1107
1115
|
const omitChildren = componentWrapsVoidElement(source);
|
|
1108
|
-
const isPage =
|
|
1116
|
+
const isPage = isPageFile;
|
|
1109
1117
|
|
|
1110
1118
|
// Props: manifest or parse from source for default args (LucideIcon, array types, ReactNode, contextual placeholders)
|
|
1111
1119
|
const effectiveProps = Array.isArray(comp.props) && comp.props.length > 0 ? comp.props : parsePropsFromSource(source);
|
|
@@ -1499,6 +1507,7 @@ function main() {
|
|
|
1499
1507
|
}
|
|
1500
1508
|
const raw = fs.readFileSync(VDS_OUTPUT, "utf-8");
|
|
1501
1509
|
const data = JSON.parse(raw);
|
|
1510
|
+
COMPONENTS_REL_DIR = data.componentsRelDir || "src/components";
|
|
1502
1511
|
const components = Array.isArray(data.components) ? data.components : [];
|
|
1503
1512
|
const foundations = data.foundations || null;
|
|
1504
1513
|
FOUNDATIONS_DATA = foundations;
|