vibe-design-system 2.2.0 → 2.3.0

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.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -776,6 +776,69 @@ function extractFoundations() {
776
776
  }
777
777
  }
778
778
 
779
+ // ── FALLBACK 1: Arbitrary Tailwind values ──────────────────
780
+ const srcRelFiles = getAllTsxJsxInDir(SRC_DIR);
781
+ const allSourceFiles = [
782
+ ...srcRelFiles.map((f) => path.join(SRC_DIR, f)),
783
+ path.join(PROJECT_ROOT, "index.html"),
784
+ path.join(PROJECT_ROOT, "src", "index.css"),
785
+ path.join(PROJECT_ROOT, "src", "globals.css"),
786
+ path.join(PROJECT_ROOT, "src", "App.css"),
787
+ path.join(PROJECT_ROOT, "app", "globals.css"),
788
+ ].filter((p) => fs.existsSync(p));
789
+
790
+ const ARBITRARY_HEX = /(?:bg|text|border|ring|fill|stroke|from|to|via)-\[#([0-9a-fA-F]{3,8})\]/g;
791
+ const arbitraryColors = new Map();
792
+ for (const file of allSourceFiles) {
793
+ try {
794
+ const content = fs.readFileSync(file, "utf-8");
795
+ for (const match of content.matchAll(ARBITRARY_HEX)) {
796
+ const hex = "#" + match[1].toUpperCase();
797
+ arbitraryColors.set(hex, (arbitraryColors.get(hex) || 0) + 1);
798
+ }
799
+ } catch (_) {}
800
+ }
801
+ const getHex = (v) => {
802
+ const x = typeof v === "string" ? v : v?.hex ?? v?.value;
803
+ return x ? String(x).toUpperCase() : "";
804
+ };
805
+ const existingHexValues = new Set([
806
+ ...Object.values(colors).map((v) => getHex(v)).filter(Boolean),
807
+ ...Object.values(colorsDark).map((v) => getHex(v)).filter(Boolean),
808
+ ]);
809
+ for (const [hex, count] of arbitraryColors) {
810
+ const hexUpper = hex.toUpperCase();
811
+ if (existingHexValues.has(hexUpper)) continue;
812
+ if (count < 1) continue;
813
+ const name = "arbitrary-" + hex.slice(1).toLowerCase();
814
+ colors[name] = { value: hex, source: "arbitrary-tailwind", frequency: count };
815
+ }
816
+
817
+ // ── FALLBACK 2: Google Fonts URL ──────────────────────────
818
+ const GFONTS_PATTERN = /family=([A-Za-z+]+)(?::.*?)?(?:&|$)/g;
819
+ const fontFiles = allSourceFiles.filter(
820
+ (f) =>
821
+ f.endsWith("index.html") ||
822
+ f.includes("layout.") ||
823
+ f.includes("_document.") ||
824
+ f.endsWith("index.css") ||
825
+ f.includes("globals.css")
826
+ );
827
+ for (const file of fontFiles) {
828
+ try {
829
+ const content = fs.readFileSync(file, "utf-8");
830
+ if (!content.includes("fonts.googleapis.com")) continue;
831
+ for (const match of content.matchAll(GFONTS_PATTERN)) {
832
+ const family = match[1].replace(/\+/g, " ");
833
+ const alreadyHas = Object.values(typography).some((v) => String(v).includes(family));
834
+ if (!alreadyHas) {
835
+ const key = "--font-" + family.toLowerCase().replace(/\s+/g, "-");
836
+ typography[key] = { family, source: "google-fonts-url" };
837
+ }
838
+ }
839
+ } catch (_) {}
840
+ }
841
+
779
842
  const twTheme = getTailwindTheme();
780
843
  const normalizeThemeObj = (obj) => {
781
844
  if (!obj || typeof obj !== "object") return {};
@@ -814,56 +814,29 @@ function writeComponentSuggestionsStory(componentSuggestions) {
814
814
  }
815
815
 
816
816
  function writeChangelogStory(changelog) {
817
- if (!Array.isArray(changelog) || changelog.length === 0) return;
818
817
  const foundationsDir = path.join(STORIES_DIR, "foundations");
819
818
  ensureDir(foundationsDir);
820
- const entries = changelog.map((e) => ({
821
- version: e.version,
822
- date: e.date,
823
- changes: e.changes || [],
824
- }));
819
+ const entries = Array.isArray(changelog) ? changelog.map((e) => ({ version: e.version, date: e.date, changes: e.changes || [] })) : [];
825
820
  const content =
826
821
  [
827
822
  "import type { Meta, StoryObj } from \"@storybook/react\";",
828
823
  "",
829
- "const meta = { title: \"Foundations/Changelog\" } satisfies Meta;",
824
+ "const meta = { title: \"Foundations/Changelog\", tags: [\"autodocs\"] } satisfies Meta;",
830
825
  "export default meta;",
831
826
  "type Story = StoryObj;",
832
827
  "",
833
828
  `const changelog = ${JSON.stringify(entries)};`,
834
829
  "",
835
- "function ChangeItem({ c }) {",
836
- " if (c.type === \"color_changed\")",
837
- " return (",
838
- " <div style={{ marginBottom: 8 }}>",
839
- " <strong>{c.name}</strong>: <span style={{ color: \"#888\" }}>{c.from}</span> → <span style={{ color: \"#0f0\" }}>{c.to}</span>",
840
- " <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.from, marginLeft: 8, border: \"1px solid #333\" }} />",
841
- " <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.to, marginLeft: 4, border: \"1px solid #333\" }} />",
842
- " </div>",
843
- " );",
844
- " if (c.type === \"color_added\") return <div style={{ marginBottom: 8 }}><strong>{c.name}</strong> added: <code>{c.to}</code> <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.to, marginLeft: 4, border: \"1px solid #333\" }} /></div>;",
845
- " if (c.type === \"color_removed\") return <div style={{ marginBottom: 8, color: \"#888\" }}><strong>{c.name}</strong> removed</div>;",
846
- " if (c.type === \"typography_changed\") return <div style={{ marginBottom: 8 }}><strong>{c.key}</strong>: {c.from} → {c.to}</div>;",
847
- " if (c.type === \"component_added\") return <div style={{ marginBottom: 8, color: \"#0f0\" }}>+ {c.name}</div>;",
848
- " if (c.type === \"component_removed\") return <div style={{ marginBottom: 8, color: \"#f88\" }}>− {c.name}</div>;",
849
- " return <div style={{ marginBottom: 8 }}>{c.type}: {JSON.stringify(c)}</div>;",
850
- "}",
851
- "",
852
830
  "export const Default: Story = {",
853
831
  " render: () => (",
854
- " <div style={{ padding: 24, fontFamily: \"system-ui, sans-serif\" }}>",
855
- " <h2 style={{ marginBottom: 16 }}>VDS Changelog</h2>",
856
- " <div style={{ display: \"flex\", flexDirection: \"column\", gap: 24 }}>",
857
- " {changelog.map((e, i) => (",
858
- " <div key={i} style={{ border: \"1px solid #333\", borderRadius: 8, padding: 16, background: \"#111\" }}>",
859
- " <div style={{ fontWeight: 600, marginBottom: 4 }}>v{e.version}</div>",
860
- " <div style={{ fontSize: 12, color: \"#888\", marginBottom: 12 }}>{e.date}</div>",
861
- " {e.changes.length === 0 ? <div style={{ color: \"#666\" }}>No changes</div> : (",
862
- " <div>{e.changes.map((c, j) => <ChangeItem key={j} c={c} />)}</div>",
863
- " )}",
864
- " </div>",
865
- " ))}",
866
- " </div>",
832
+ " <div style={{ fontFamily: \"monospace\", padding: 24 }}>",
833
+ " <h2>CHANGELOG</h2>",
834
+ " {changelog.length === 0 ? <p>No changes recorded yet. Run npm run vds again after making changes.</p> : changelog.map((entry) => (",
835
+ " <div key={entry.version}>",
836
+ " <h3>v{entry.version} {entry.date}</h3>",
837
+ " {entry.changes.map((c, i) => <div key={i}>{c.type}: {c.name ?? c.key ?? \"\"}</div>)}",
838
+ " </div>",
839
+ " ))}",
867
840
  " </div>",
868
841
  " ),",
869
842
  "};",
@@ -891,10 +864,7 @@ function main() {
891
864
  if (componentSuggestions?.length) {
892
865
  writeComponentSuggestionsStory(componentSuggestions);
893
866
  }
894
- const changelog = data.changelog;
895
- if (changelog?.length) {
896
- writeChangelogStory(changelog);
897
- }
867
+ writeChangelogStory(data.changelog);
898
868
  try {
899
869
  const fd = path.join(STORIES_DIR, "foundations");
900
870
  if (fs.existsSync(fd)) {
@@ -925,6 +895,7 @@ function main() {
925
895
  }
926
896
 
927
897
  for (const comp of components) {
898
+ if (comp.file && comp.file.startsWith("pages/")) continue;
928
899
  const componentName = toSafeComponentName(comp.name, comp.file);
929
900
  if (onlyName && componentName !== onlyName) continue;
930
901
  if (SKIP_LIST.includes(componentName)) continue;