vibe-design-system 2.8.81 → 2.8.82
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
|
@@ -1429,11 +1429,17 @@ function extractFoundations() {
|
|
|
1429
1429
|
}
|
|
1430
1430
|
}
|
|
1431
1431
|
|
|
1432
|
-
// body { font-family } —
|
|
1433
|
-
|
|
1434
|
-
|
|
1432
|
+
// body { font-family } — Tailwind v4 sets font on html/:host, NOT body
|
|
1433
|
+
// Use [^}]* to stay within block boundaries ([\s\S]*? crosses blocks → mono font false-positive)
|
|
1434
|
+
const bodyMatch =
|
|
1435
|
+
css.match(/\bbody\s*\{[^}]*font-family:\s*([^;]+);/) ||
|
|
1436
|
+
css.match(/html\s*(?:,\s*:host)?\s*\{[^}]*font-family:\s*([^;]+);/); // Tailwind v4
|
|
1435
1437
|
if (bodyMatch) typography.body = bodyMatch[1].trim();
|
|
1436
|
-
|
|
1438
|
+
// Mono: code/kbd/samp/pre block (Tailwind v4 uses code,kbd,samp,pre not code,pre,.font-mono)
|
|
1439
|
+
const monoMatch =
|
|
1440
|
+
css.match(/code,\s*pre,\s*\.font-mono\s*\{[^}]*font-family:\s*([^;]+);/) ||
|
|
1441
|
+
css.match(/code,\s*kbd[^{]*\{[^}]*font-family:\s*([^;]+);/) ||
|
|
1442
|
+
css.match(/\bcode\b[^{,]*\{[^}]*font-family:\s*([^;]+);/);
|
|
1437
1443
|
if (monoMatch) typography.mono = monoMatch[1].trim();
|
|
1438
1444
|
// CSS custom properties for fonts (--font-sans, --font-mono, --font-display, etc.)
|
|
1439
1445
|
const fontVarRe = /--font([\w-]*):\s*([^;\n]+);/g;
|
|
@@ -1444,14 +1450,27 @@ function extractFoundations() {
|
|
|
1444
1450
|
if (!typography[key]) typography[key] = val;
|
|
1445
1451
|
}
|
|
1446
1452
|
// Resolve var(--font-*) references in body/mono to actual font names
|
|
1447
|
-
//
|
|
1453
|
+
// Also handles Tailwind v4 --default-font-family / --default-mono-font-family chain
|
|
1448
1454
|
function resolveTypoVar(val) {
|
|
1449
1455
|
if (!val || !val.startsWith("var(")) return val;
|
|
1456
|
+
// Direct --font-* reference: var(--font-sans) → typography.fontSans
|
|
1450
1457
|
const m = val.match(/var\(--font-([\w-]+)\)/);
|
|
1451
|
-
if (
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1458
|
+
if (m) {
|
|
1459
|
+
const key = `font-${m[1]}`.replace(/-([a-zA-Z])/g, (_, c) => c.toUpperCase());
|
|
1460
|
+
return (typography[key] && !typography[key].startsWith("var(")) ? typography[key] : val;
|
|
1461
|
+
}
|
|
1462
|
+
// Tailwind v4: var(--default-font-family, ...) → resolve via fontSans
|
|
1463
|
+
if (val.includes("--default-font-family") && !val.includes("--default-mono")) {
|
|
1464
|
+
if (typography.fontSans && !typography.fontSans.startsWith("var(")) return typography.fontSans;
|
|
1465
|
+
// Fallback: strip the var() wrapper to get the fallback list
|
|
1466
|
+
return val.replace(/^var\(--default-font-family,\s*/, "").replace(/\)\s*$/, "").trim() || val;
|
|
1467
|
+
}
|
|
1468
|
+
// Tailwind v4: var(--default-mono-font-family, ...) → resolve via fontMono
|
|
1469
|
+
if (val.includes("--default-mono-font-family")) {
|
|
1470
|
+
if (typography.fontMono && !typography.fontMono.startsWith("var(")) return typography.fontMono;
|
|
1471
|
+
return val.replace(/^var\(--default-mono-font-family,\s*/, "").replace(/\)\s*$/, "").trim() || val;
|
|
1472
|
+
}
|
|
1473
|
+
return val;
|
|
1455
1474
|
}
|
|
1456
1475
|
if (typography.body) typography.body = resolveTypoVar(typography.body);
|
|
1457
1476
|
if (typography.mono) typography.mono = resolveTypoVar(typography.mono);
|
|
@@ -1792,6 +1792,96 @@ function buildRecipeStoryContent(comp, componentName, importPath, title, source,
|
|
|
1792
1792
|
}
|
|
1793
1793
|
lines.push(`};`);
|
|
1794
1794
|
}
|
|
1795
|
+
|
|
1796
|
+
// --- Design Tokens story (same block as generateStoryFile) ---
|
|
1797
|
+
{
|
|
1798
|
+
const compTokens = Array.isArray(comp.tokens) ? comp.tokens : [];
|
|
1799
|
+
const foundColors = FOUNDATIONS_DATA?.colors || {};
|
|
1800
|
+
if (compTokens.length >= 3) {
|
|
1801
|
+
const cleanTokens = compTokens.filter(t => !/:/.test(t));
|
|
1802
|
+
const colorRaw = cleanTokens.filter(t =>
|
|
1803
|
+
/^(bg|text|border|ring|from|to|fill|stroke)-/.test(t) &&
|
|
1804
|
+
!/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|\d)/.test(t)
|
|
1805
|
+
);
|
|
1806
|
+
const spacingRaw = cleanTokens.filter(t => /^(p[xylrbt]?-|m[xylrbt]?-|gap|space-[xy]|w-|h-|min-[wh]|max-[wh]|size-)/.test(t));
|
|
1807
|
+
const typographyRaw = cleanTokens.filter(t => /^(text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl)|font-)/.test(t));
|
|
1808
|
+
const radiusRaw = cleanTokens.filter(t => /^rounded/.test(t));
|
|
1809
|
+
const animRaw = cleanTokens.filter(t => /^(transition|duration|animate|ease|delay)-/.test(t));
|
|
1810
|
+
const resolvedColors = colorRaw.map(token => {
|
|
1811
|
+
const m = token.match(/^(?:bg|text|border|ring|from|to|fill|stroke)-(.+)$/);
|
|
1812
|
+
const key = m ? m[1] : null;
|
|
1813
|
+
const baseKey = key ? key.replace(/\/[\d.]+$/, "") : null;
|
|
1814
|
+
const entry = key ? (foundColors[key] || (baseKey !== key ? foundColors[baseKey] : null)) : null;
|
|
1815
|
+
const isValidCssColor = (v) => /^#[0-9a-fA-F]{3,8}$/.test(v) || /^(rgb|rgba|hsl|hsla|oklch|oklab|lch|lab|color)\s*\(/.test(v) || v === 'transparent';
|
|
1816
|
+
const hex = entry?.hex && isValidCssColor(entry.hex) ? entry.hex : null;
|
|
1817
|
+
return { token, hex, label: baseKey || key };
|
|
1818
|
+
});
|
|
1819
|
+
const hasContent = resolvedColors.length > 0 || spacingRaw.length > 0 || typographyRaw.length > 0 || radiusRaw.length > 0 || animRaw.length > 0;
|
|
1820
|
+
if (hasContent) {
|
|
1821
|
+
lines.push("");
|
|
1822
|
+
lines.push(`export const Tokens: Story = {`);
|
|
1823
|
+
lines.push(` name: "Design Tokens",`);
|
|
1824
|
+
lines.push(` parameters: { layout: "fullscreen" },`);
|
|
1825
|
+
lines.push(` render: () => {`);
|
|
1826
|
+
lines.push(` const colorTokens = ${JSON.stringify(resolvedColors)};`);
|
|
1827
|
+
lines.push(` const spacingTokens = ${JSON.stringify(spacingRaw)};`);
|
|
1828
|
+
lines.push(` const typographyTokens = ${JSON.stringify(typographyRaw)};`);
|
|
1829
|
+
lines.push(` const radiusTokens = ${JSON.stringify(radiusRaw)};`);
|
|
1830
|
+
lines.push(` const animationTokens = ${JSON.stringify(animRaw)};`);
|
|
1831
|
+
lines.push(` const chip = (label: string, bg: string, color: string) => (`);
|
|
1832
|
+
lines.push(` <span key={label} style={{ fontFamily: "monospace", fontSize: 11, background: bg, color, padding: "3px 9px", borderRadius: 5, border: \`1px solid \${bg === "#f9fafb" ? "#e5e7eb" : bg}\`, whiteSpace: "nowrap" as any }}>{label}</span>`);
|
|
1833
|
+
lines.push(` );`);
|
|
1834
|
+
lines.push(` const section = (title: string, children: any) => (`);
|
|
1835
|
+
lines.push(` <section style={{ marginBottom: 28 }}>`);
|
|
1836
|
+
lines.push(` <p style={{ margin: "0 0 10px", fontSize: 11, fontWeight: 700, color: "#6b7280", textTransform: "uppercase", letterSpacing: "0.08em" }}>{title}</p>`);
|
|
1837
|
+
lines.push(` {children}`);
|
|
1838
|
+
lines.push(` </section>`);
|
|
1839
|
+
lines.push(` );`);
|
|
1840
|
+
lines.push(` return (`);
|
|
1841
|
+
lines.push(` <div style={{ padding: 40, background: "#fff", fontFamily: "system-ui,sans-serif", color: "#111", minHeight: "100vh", width: "100%" }}>`);
|
|
1842
|
+
lines.push(` <h2 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 6px" }}>Design Tokens</h2>`);
|
|
1843
|
+
lines.push(` <p style={{ fontSize: 13, color: "#6b7280", margin: "0 0 32px" }}>Tailwind utilities used in <code style={{ background: "#f3f4f6", padding: "1px 6px", borderRadius: 4, fontSize: 12 }}>${componentName}</code> — resolved to project values.</p>`);
|
|
1844
|
+
lines.push(` {colorTokens.length > 0 && section("Color", (`);
|
|
1845
|
+
lines.push(` <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>`);
|
|
1846
|
+
lines.push(` {colorTokens.map(({ token, hex, label }) => (`);
|
|
1847
|
+
lines.push(` <div key={token} style={{ display: "flex", alignItems: "center", gap: 7, padding: "7px 12px", border: "1px solid #e5e7eb", borderRadius: 8, background: "#f9fafb" }}>`);
|
|
1848
|
+
lines.push(` {hex && <span style={{ display: "inline-block", width: 16, height: 16, borderRadius: 4, background: hex, border: "1px solid rgba(0,0,0,0.1)", flexShrink: 0 }} />}`);
|
|
1849
|
+
lines.push(` <code style={{ fontSize: 12, color: "#374151", fontWeight: 600 }}>{token}</code>`);
|
|
1850
|
+
lines.push(` {hex && <span style={{ fontSize: 11, color: "#9ca3af" }}>{hex}</span>}`);
|
|
1851
|
+
lines.push(` </div>`);
|
|
1852
|
+
lines.push(` ))}`);
|
|
1853
|
+
lines.push(` </div>`);
|
|
1854
|
+
lines.push(` ))}`);
|
|
1855
|
+
lines.push(` {spacingTokens.length > 0 && section("Spacing", (`);
|
|
1856
|
+
lines.push(` <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{spacingTokens.map(t => chip(t, "#faf5ff", "#6d28d9"))}</div>`);
|
|
1857
|
+
lines.push(` ))}`);
|
|
1858
|
+
lines.push(` {typographyTokens.length > 0 && section("Typography", (`);
|
|
1859
|
+
lines.push(` <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{typographyTokens.map(t => chip(t, "#fffbeb", "#92400e"))}</div>`);
|
|
1860
|
+
lines.push(` ))}`);
|
|
1861
|
+
lines.push(` {radiusTokens.length > 0 && section("Border Radius", (`);
|
|
1862
|
+
lines.push(` <div style={{ display: "flex", gap: 16, flexWrap: "wrap", alignItems: "flex-end" }}>`);
|
|
1863
|
+
lines.push(` {radiusTokens.map(t => {`);
|
|
1864
|
+
lines.push(` const px = t === "rounded-none" ? 0 : t === "rounded-sm" ? 2 : t === "rounded" ? 4 : t === "rounded-md" ? 6 : t === "rounded-lg" ? 8 : t === "rounded-xl" ? 12 : t === "rounded-2xl" ? 16 : t === "rounded-3xl" ? 24 : t === "rounded-full" ? 9999 : 4;`);
|
|
1865
|
+
lines.push(` return (`);
|
|
1866
|
+
lines.push(` <div key={t} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }}>`);
|
|
1867
|
+
lines.push(` <div style={{ width: 44, height: 44, background: "#6366f1", borderRadius: px }} />`);
|
|
1868
|
+
lines.push(` <code style={{ fontSize: 10, color: "#6b7280" }}>{t}</code>`);
|
|
1869
|
+
lines.push(` </div>`);
|
|
1870
|
+
lines.push(` );`);
|
|
1871
|
+
lines.push(` })}`);
|
|
1872
|
+
lines.push(` </div>`);
|
|
1873
|
+
lines.push(` ))}`);
|
|
1874
|
+
lines.push(` {animationTokens.length > 0 && section("Motion", (`);
|
|
1875
|
+
lines.push(` <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{animationTokens.map(t => chip(t, "#f0fdf4", "#166534"))}</div>`);
|
|
1876
|
+
lines.push(` ))}`);
|
|
1877
|
+
lines.push(` </div>`);
|
|
1878
|
+
lines.push(` );`);
|
|
1879
|
+
lines.push(` },`);
|
|
1880
|
+
lines.push(`};`);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1795
1885
|
return lines.join("\n");
|
|
1796
1886
|
}
|
|
1797
1887
|
|
|
@@ -2115,42 +2205,46 @@ function buildStoryFileContent(comp) {
|
|
|
2115
2205
|
// Component-specific stories for non-variant components (Input, Textarea, etc.)
|
|
2116
2206
|
// Skip buildSpecialStories when multi-dimension detection found CVA dimensions —
|
|
2117
2207
|
// generic detection produces better stories than hardcoded ones.
|
|
2208
|
+
let generatedSpecialStories = false;
|
|
2118
2209
|
if (!hasDimensions) {
|
|
2119
2210
|
const specialStories = buildSpecialStories(componentName, variants);
|
|
2120
2211
|
if (specialStories) {
|
|
2121
2212
|
lines.push(specialStories);
|
|
2122
|
-
|
|
2213
|
+
generatedSpecialStories = true;
|
|
2214
|
+
// Do NOT return here — fall through to Tokens + Usage stories below
|
|
2123
2215
|
}
|
|
2124
2216
|
}
|
|
2125
2217
|
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2218
|
+
if (!generatedSpecialStories) {
|
|
2219
|
+
// Profile-driven render + children — single source of truth via getStoryProfile()
|
|
2220
|
+
const useSafeWrapper = profile === "SAFE";
|
|
2221
|
+
const RenderTarget = useSafeWrapper ? "SafeWrapper" : "ComponentRef";
|
|
2222
|
+
const argsFallback = !useSafeWrapper && (componentName && RENDER_ARGS_FALLBACKS[componentName]) || "";
|
|
2223
|
+
const renderLine = buildProfileRenderLine(profile, RenderTarget, argsFallback);
|
|
2224
|
+
const childrenArgLine = buildProfileChildrenArgLine(profile);
|
|
2132
2225
|
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2226
|
+
if (hasDimensions) {
|
|
2227
|
+
const multiStories = buildMultiDimensionStories(
|
|
2228
|
+
variantMap, renderLine, childrenArgLine, defaultArgLines, componentName,
|
|
2229
|
+
comp.variantUsage || null
|
|
2230
|
+
);
|
|
2231
|
+
if (multiStories) {
|
|
2232
|
+
lines.push(multiStories);
|
|
2233
|
+
}
|
|
2234
|
+
} else {
|
|
2235
|
+
// No dimensions detected: single Default story
|
|
2236
|
+
lines.push(`export const Default: Story = {`);
|
|
2237
|
+
lines.push(renderLine);
|
|
2238
|
+
const storyArgLines = [];
|
|
2239
|
+
if (childrenArgLine(componentName)) storyArgLines.push(childrenArgLine(componentName));
|
|
2240
|
+
for (const line of defaultArgLines) storyArgLines.push(line);
|
|
2241
|
+
if (storyArgLines.length > 0) {
|
|
2242
|
+
lines.push(` args: {`);
|
|
2243
|
+
for (const line of storyArgLines) lines.push(line);
|
|
2244
|
+
lines.push(` },`);
|
|
2245
|
+
}
|
|
2246
|
+
lines.push(`};`);
|
|
2152
2247
|
}
|
|
2153
|
-
lines.push(`};`);
|
|
2154
2248
|
}
|
|
2155
2249
|
|
|
2156
2250
|
// --- Project-specific usage stories ---
|
|
@@ -2190,7 +2284,7 @@ function buildStoryFileContent(comp) {
|
|
|
2190
2284
|
/^(bg|text|border|ring|from|to|fill|stroke)-/.test(t) &&
|
|
2191
2285
|
!/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|\d)/.test(t)
|
|
2192
2286
|
);
|
|
2193
|
-
const spacingRaw = cleanTokens.filter(t => /^(p[xylrbt]
|
|
2287
|
+
const spacingRaw = cleanTokens.filter(t => /^(p[xylrbt]?-|m[xylrbt]?-|gap|space-[xy]|w-|h-|min-[wh]|max-[wh]|size-)/.test(t));
|
|
2194
2288
|
const typographyRaw = cleanTokens.filter(t => /^(text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl)|font-)/.test(t));
|
|
2195
2289
|
const radiusRaw = cleanTokens.filter(t => /^rounded/.test(t));
|
|
2196
2290
|
const animRaw = cleanTokens.filter(t => /^(transition|duration|animate|ease|delay)-/.test(t));
|