@fragments-sdk/cli 0.8.1 → 0.9.1

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.
Files changed (128) hide show
  1. package/dist/bin.js +517 -77
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-WI6SLMSO.js → chunk-5GT62FCB.js} +2 -2
  4. package/dist/{chunk-CJEGT3WD.js → chunk-BW3ZATBW.js} +20 -3
  5. package/dist/chunk-BW3ZATBW.js.map +1 -0
  6. package/dist/{chunk-2JIKCJX3.js → chunk-D7372LQX.js} +13 -6
  7. package/dist/chunk-D7372LQX.js.map +1 -0
  8. package/dist/chunk-EZYXYWNF.js +131 -0
  9. package/dist/chunk-EZYXYWNF.js.map +1 -0
  10. package/dist/{chunk-NGIMCIK2.js → chunk-GF6OVPIN.js} +2 -2
  11. package/dist/{chunk-GOVI6COW.js → chunk-NVSPGSKB.js} +12 -4
  12. package/dist/chunk-NVSPGSKB.js.map +1 -0
  13. package/dist/core/index.d.ts +105 -3
  14. package/dist/core/index.js +12 -2
  15. package/dist/{defineFragment-D0UTve-I.d.ts → defineFragment-CBMS7Bab.d.ts} +21 -1
  16. package/dist/generate-LQA2R7FN.js +461 -0
  17. package/dist/generate-LQA2R7FN.js.map +1 -0
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +5 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/{init-KFYN37ZY.js → init-2GEGVIUQ.js} +14 -76
  22. package/dist/init-2GEGVIUQ.js.map +1 -0
  23. package/dist/mcp-bin.js +4 -3
  24. package/dist/mcp-bin.js.map +1 -1
  25. package/dist/{scan-65RH3QMM.js → scan-JGS65S7P.js} +6 -5
  26. package/dist/{service-A5GIGGGK.js → service-XP2EAJXD.js} +4 -3
  27. package/dist/{static-viewer-NSODM5VX.js → static-viewer-XCS7UJTO.js} +4 -3
  28. package/dist/storyFilters-3LUYAFZF.js +15 -0
  29. package/dist/storyFilters-3LUYAFZF.js.map +1 -0
  30. package/dist/{test-RPWZAYSJ.js → test-TD6TJNVY.js} +3 -3
  31. package/dist/{tokens-NIXSZRX7.js → tokens-2EXPCVP3.js} +5 -4
  32. package/dist/{tokens-NIXSZRX7.js.map → tokens-2EXPCVP3.js.map} +1 -1
  33. package/dist/{viewer-HZK4BSDK.js → viewer-RFA2KVBG.js} +249 -22
  34. package/dist/viewer-RFA2KVBG.js.map +1 -0
  35. package/package.json +2 -2
  36. package/src/bin.ts +26 -0
  37. package/src/build.ts +12 -2
  38. package/src/commands/build.ts +16 -2
  39. package/src/commands/doctor.ts +498 -0
  40. package/src/commands/generate.ts +383 -68
  41. package/src/commands/init-framework.ts +1 -1
  42. package/src/commands/init.ts +9 -51
  43. package/src/core/config.ts +15 -2
  44. package/src/core/generators/typescript-extractor.ts +10 -0
  45. package/src/core/index.ts +15 -0
  46. package/src/core/schema.ts +10 -2
  47. package/src/core/storyFilters.test.ts +350 -0
  48. package/src/core/storyFilters.ts +253 -0
  49. package/src/core/types.ts +22 -0
  50. package/src/migrate/converter.ts +9 -1
  51. package/src/migrate/parser.ts +2 -0
  52. package/src/migrate/types.ts +2 -0
  53. package/src/setup.ts +69 -24
  54. package/src/viewer/__tests__/viewer-integration.test.ts +1 -1
  55. package/src/viewer/components/AccessibilityPanel.tsx +305 -312
  56. package/src/viewer/components/ActionsPanel.tsx +31 -29
  57. package/src/viewer/components/AllVariantsPreview.tsx +78 -0
  58. package/src/viewer/components/App.tsx +187 -740
  59. package/src/viewer/components/BottomPanel.tsx +228 -132
  60. package/src/viewer/components/CodePanel.tsx +1 -1
  61. package/src/viewer/components/CommandPalette.tsx +7 -10
  62. package/src/viewer/components/ComponentDocView.tsx +164 -0
  63. package/src/viewer/components/ComponentGraph.tsx +111 -142
  64. package/src/viewer/components/ContractPanel.tsx +6 -6
  65. package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
  66. package/src/viewer/components/FigmaEmbed.tsx +20 -18
  67. package/src/viewer/components/FragmentEditor.tsx +92 -115
  68. package/src/viewer/components/HeaderSearch.tsx +24 -0
  69. package/src/viewer/components/HealthDashboard.tsx +16 -2
  70. package/src/viewer/components/Icons.tsx +9 -0
  71. package/src/viewer/components/InteractionsPanel.tsx +101 -117
  72. package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
  73. package/src/viewer/components/LandingPage.tsx +3 -3
  74. package/src/viewer/components/LeftSidebar.tsx +141 -63
  75. package/src/viewer/components/LoadErrorMessage.tsx +102 -0
  76. package/src/viewer/components/MultiViewportPreview.tsx +61 -142
  77. package/src/viewer/components/NoVariantsMessage.tsx +59 -0
  78. package/src/viewer/components/PanelShell.tsx +161 -0
  79. package/src/viewer/components/PerformancePanel.tsx +31 -28
  80. package/src/viewer/components/PreviewArea.tsx +1 -1
  81. package/src/viewer/components/PreviewAside.tsx +168 -0
  82. package/src/viewer/components/PreviewFrameHost.tsx +3 -3
  83. package/src/viewer/components/PropsEditor.tsx +70 -156
  84. package/src/viewer/components/ResizablePanel.tsx +103 -263
  85. package/src/viewer/components/RightSidebar.tsx +3 -9
  86. package/src/viewer/components/SkeletonLoader.tsx +13 -13
  87. package/src/viewer/components/TokenStylePanel.tsx +182 -209
  88. package/src/viewer/components/TopToolbar.tsx +159 -0
  89. package/src/viewer/components/VariantMatrix.tsx +42 -86
  90. package/src/viewer/components/VariantTabs.tsx +3 -3
  91. package/src/viewer/components/ViewerHeader.tsx +69 -0
  92. package/src/viewer/components/WebMCPDevTools.tsx +17 -23
  93. package/src/viewer/components/viewer-utils.ts +16 -0
  94. package/src/viewer/entry.tsx +5 -0
  95. package/src/viewer/hooks/useAppState.ts +27 -4
  96. package/src/viewer/hooks/usePreviewBridge.ts +2 -2
  97. package/src/viewer/preview-frame.html +6 -12
  98. package/src/viewer/server.ts +184 -6
  99. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
  100. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
  101. package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
  102. package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
  103. package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
  104. package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
  105. package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
  106. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +122 -0
  107. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
  108. package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
  109. package/src/viewer/vendor/shared/src/docs-data/index.ts +32 -0
  110. package/src/viewer/vendor/shared/src/docs-data/mcp-configs.ts +72 -0
  111. package/src/viewer/vendor/shared/src/docs-data/palettes.ts +75 -0
  112. package/src/viewer/vendor/shared/src/docs-data/setup-examples.ts +55 -0
  113. package/src/viewer/vendor/shared/src/index.ts +8 -0
  114. package/src/viewer/vendor/shared/src/types.ts +12 -0
  115. package/src/viewer/vite-plugin.ts +109 -4
  116. package/dist/chunk-2JIKCJX3.js.map +0 -1
  117. package/dist/chunk-CJEGT3WD.js.map +0 -1
  118. package/dist/chunk-GOVI6COW.js.map +0 -1
  119. package/dist/generate-35OIMW4Y.js +0 -252
  120. package/dist/generate-35OIMW4Y.js.map +0 -1
  121. package/dist/init-KFYN37ZY.js.map +0 -1
  122. package/dist/viewer-HZK4BSDK.js.map +0 -1
  123. /package/dist/{chunk-WI6SLMSO.js.map → chunk-5GT62FCB.js.map} +0 -0
  124. /package/dist/{chunk-NGIMCIK2.js.map → chunk-GF6OVPIN.js.map} +0 -0
  125. /package/dist/{scan-65RH3QMM.js.map → scan-JGS65S7P.js.map} +0 -0
  126. /package/dist/{service-A5GIGGGK.js.map → service-XP2EAJXD.js.map} +0 -0
  127. /package/dist/{static-viewer-NSODM5VX.js.map → static-viewer-XCS7UJTO.js.map} +0 -0
  128. /package/dist/{test-RPWZAYSJ.js.map → test-TD6TJNVY.js.map} +0 -0
package/dist/bin.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
3
+ import {
4
+ scan
5
+ } from "./chunk-5GT62FCB.js";
3
6
  import {
4
7
  buildFragments,
5
8
  buildFragmentsDir,
@@ -12,14 +15,11 @@ import {
12
15
  validateCoverage,
13
16
  validateSchema,
14
17
  validateSnippets
15
- } from "./chunk-2JIKCJX3.js";
16
- import {
17
- scan
18
- } from "./chunk-WI6SLMSO.js";
18
+ } from "./chunk-D7372LQX.js";
19
19
  import {
20
20
  loadConfig,
21
21
  loadFragmentFile
22
- } from "./chunk-CJEGT3WD.js";
22
+ } from "./chunk-BW3ZATBW.js";
23
23
  import {
24
24
  discoverFragmentFiles
25
25
  } from "./chunk-AWYCDRPG.js";
@@ -44,8 +44,9 @@ import {
44
44
  formatBytes,
45
45
  generateContext,
46
46
  resolvePerformanceConfig
47
- } from "./chunk-NGIMCIK2.js";
48
- import "./chunk-GOVI6COW.js";
47
+ } from "./chunk-GF6OVPIN.js";
48
+ import "./chunk-NVSPGSKB.js";
49
+ import "./chunk-EZYXYWNF.js";
49
50
  import {
50
51
  BRAND
51
52
  } from "./chunk-EKLMXTWU.js";
@@ -53,10 +54,10 @@ import "./chunk-Z7EY4VHE.js";
53
54
 
54
55
  // src/bin.ts
55
56
  import { Command } from "commander";
56
- import pc22 from "picocolors";
57
+ import pc23 from "picocolors";
57
58
  import { readFileSync } from "fs";
58
59
  import { fileURLToPath } from "url";
59
- import { dirname as dirname4, join as join10 } from "path";
60
+ import { dirname as dirname4, join as join11 } from "path";
60
61
 
61
62
  // src/commands/validate.ts
62
63
  import pc from "picocolors";
@@ -176,9 +177,20 @@ ${BRAND.name} Build
176
177
  }
177
178
  fragmentCount = result.fragmentCount;
178
179
  outputPath = result.outputPath;
179
- console.log(pc2.green(`\u2713 Built ${result.fragmentCount} fragment(s)`));
180
- console.log(pc2.dim(` Output: ${result.outputPath}
180
+ if (result.fragmentCount === 0 && result.errors.length === 0) {
181
+ console.log(pc2.dim("No compilable fragment files found. Falling back to source scan...\n"));
182
+ const scanResult = await scan({
183
+ config: options.config,
184
+ output: options.output,
185
+ verbose: options.verbose
186
+ });
187
+ fragmentCount = scanResult.componentCount;
188
+ outputPath = scanResult.outputPath;
189
+ } else {
190
+ console.log(pc2.green(`\u2713 Built ${result.fragmentCount} fragment(s)`));
191
+ console.log(pc2.dim(` Output: ${result.outputPath}
181
192
  `));
193
+ }
182
194
  }
183
195
  if (options.registry || options.registryOnly) {
184
196
  console.log(pc2.dim("Generating registry and context...\n"));
@@ -602,6 +614,7 @@ function parseMeta(content, filePath, warnings) {
602
614
  );
603
615
  if (importMatch) {
604
616
  result.componentImport = importMatch[1];
617
+ result.isDefaultImport = false;
605
618
  } else {
606
619
  const defaultImportMatch = content.match(
607
620
  new RegExp(
@@ -610,6 +623,7 @@ function parseMeta(content, filePath, warnings) {
610
623
  );
611
624
  if (defaultImportMatch) {
612
625
  result.componentImport = defaultImportMatch[1];
626
+ result.isDefaultImport = true;
613
627
  }
614
628
  }
615
629
  }
@@ -1199,6 +1213,7 @@ function convertToFragment(parsed) {
1199
1213
  const code = generateFragmentCode({
1200
1214
  componentName,
1201
1215
  componentImport: parsed.meta.componentImport,
1216
+ isDefaultImport: parsed.meta.isDefaultImport,
1202
1217
  description: parsed.meta.description,
1203
1218
  category,
1204
1219
  tags: parsed.meta.tags,
@@ -1434,6 +1449,7 @@ function generateFragmentCode(options) {
1434
1449
  const {
1435
1450
  componentName,
1436
1451
  componentImport,
1452
+ isDefaultImport,
1437
1453
  description,
1438
1454
  category,
1439
1455
  tags,
@@ -1461,8 +1477,9 @@ ${generated.skippedVariants.map((sv) => ` { name: "${escapeString(sv.name)}
1461
1477
  },
1462
1478
  `;
1463
1479
  }
1480
+ const componentImportStatement = isDefaultImport ? `import ${componentName} from "${componentImport}";` : `import { ${componentName} } from "${componentImport}";`;
1464
1481
  return `import { defineFragment } from "@fragments-sdk/cli/core";
1465
- import { ${componentName} } from "${componentImport}";
1482
+ ${componentImportStatement}
1466
1483
 
1467
1484
  export default defineFragment({
1468
1485
  component: ${componentName},
@@ -1717,27 +1734,48 @@ async function runSetup(options = {}) {
1717
1734
  const sbConfig = await detectStorybookConfig(configDir);
1718
1735
  if (sbConfig) {
1719
1736
  log(pc6.dim(` Found Storybook at ${sbConfig.configPath}`));
1720
- log(pc6.dim(" Converting stories to fragments...\n"));
1721
- const storyFiles = await discoverStoryFiles(configDir, sbConfig.storyPatterns);
1722
- if (storyFiles.length > 0) {
1723
- let converted = 0;
1724
- for (const storyFile of storyFiles) {
1725
- try {
1726
- const parsed = await parseStoryFile(storyFile);
1727
- const fragmentResult = convertToFragment(parsed);
1728
- await fs2.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
1729
- await fs2.writeFile(fragmentResult.outputFile, fragmentResult.code);
1730
- converted++;
1731
- } catch {
1737
+ const hasStoryPatterns = config.include.some((p) => p.includes(".stories."));
1738
+ if (hasStoryPatterns) {
1739
+ log(pc6.dim(" Stories included in config \u2014 viewer will load them directly\n"));
1740
+ fragmentFiles = await discoverFragmentFiles(config, configDir);
1741
+ if (fragmentFiles.length > 0) {
1742
+ log(pc6.green(` Found ${fragmentFiles.length} story/fragment file(s)`));
1743
+ }
1744
+ } else {
1745
+ log(pc6.dim(" Converting stories to fragments...\n"));
1746
+ const storyFiles = await discoverStoryFiles(configDir, sbConfig.storyPatterns);
1747
+ if (storyFiles.length > 0) {
1748
+ let converted = 0;
1749
+ for (const storyFile of storyFiles) {
1750
+ try {
1751
+ const parsed = await parseStoryFile(storyFile);
1752
+ const fragmentResult = convertToFragment(parsed);
1753
+ await fs2.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
1754
+ await fs2.writeFile(fragmentResult.outputFile, fragmentResult.code);
1755
+ converted++;
1756
+ } catch {
1757
+ }
1732
1758
  }
1759
+ result.fragmentFilesCreated = converted;
1760
+ log(pc6.green(` Generated ${converted} fragment file(s)`));
1761
+ fragmentFiles = await discoverFragmentFiles(config, configDir);
1733
1762
  }
1734
- result.fragmentFilesCreated = converted;
1735
- log(pc6.green(` Generated ${converted} fragment file(s)`));
1736
- fragmentFiles = await discoverFragmentFiles(config, configDir);
1737
1763
  }
1738
1764
  } else {
1739
1765
  log(pc6.dim(" No Storybook config found"));
1740
- log(pc6.dim(` Run ${pc6.cyan(`${BRAND.cliCommand} add <ComponentName>`)} to create your first fragment`));
1766
+ log(pc6.dim(" Auto-scanning source code...\n"));
1767
+ try {
1768
+ const scanResult = await scan({
1769
+ config: options.configPath,
1770
+ verbose: false
1771
+ });
1772
+ if (scanResult.componentCount > 0) {
1773
+ result.fragmentsBuilt = scanResult.componentCount;
1774
+ log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
1775
+ }
1776
+ } catch {
1777
+ log(pc6.dim(` Run ${pc6.cyan(`${BRAND.cliCommand} scan`)} to generate documentation from source`));
1778
+ }
1741
1779
  }
1742
1780
  } else if (fragmentFiles.length > 0) {
1743
1781
  log(pc6.green(` Found ${fragmentFiles.length} fragment file(s)`));
@@ -1757,7 +1795,19 @@ ${reason} ${BRAND.outFile}...`));
1757
1795
  result.errors.push(`${err.file}: ${err.error}`);
1758
1796
  }
1759
1797
  }
1760
- log(pc6.green(` Built ${buildResult.fragmentCount} fragment(s)`));
1798
+ if (buildResult.fragmentCount > 0) {
1799
+ log(pc6.green(` Built ${buildResult.fragmentCount} fragment(s)`));
1800
+ } else {
1801
+ log(pc6.dim(" No compilable fragments found, falling back to source scan..."));
1802
+ try {
1803
+ const scanResult = await scan({ verbose: false });
1804
+ if (scanResult.componentCount > 0) {
1805
+ result.fragmentsBuilt = scanResult.componentCount;
1806
+ log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
1807
+ }
1808
+ } catch {
1809
+ }
1810
+ }
1761
1811
  } catch (error) {
1762
1812
  result.errors.push(`Build failed: ${error instanceof Error ? error.message : "Unknown error"}`);
1763
1813
  }
@@ -1811,7 +1861,7 @@ ${BRAND.name} Dev Server
1811
1861
  }
1812
1862
  }
1813
1863
  }
1814
- const { createDevServer } = await import("./viewer-HZK4BSDK.js");
1864
+ const { createDevServer } = await import("./viewer-RFA2KVBG.js");
1815
1865
  console.log(pc7.dim("\nStarting dev server..."));
1816
1866
  const parsedPort = typeof port === "string" ? parseInt(port, 10) : port;
1817
1867
  try {
@@ -5363,9 +5413,384 @@ ${pc21.bold("Summary")}`);
5363
5413
  };
5364
5414
  }
5365
5415
 
5416
+ // src/commands/doctor.ts
5417
+ import { readFile as readFile8, access as access3 } from "fs/promises";
5418
+ import { join as join10, resolve as resolve8 } from "path";
5419
+ import pc22 from "picocolors";
5420
+ var VALID_NEUTRALS = ["stone", "ice", "earth", "sand", "fire"];
5421
+ var VALID_DENSITIES = ["compact", "default", "relaxed"];
5422
+ var VALID_RADII = ["sharp", "subtle", "default", "rounded", "pill"];
5423
+ async function checkPackageInstalled(root) {
5424
+ try {
5425
+ const pkgPath = join10(root, "package.json");
5426
+ const content = await readFile8(pkgPath, "utf-8");
5427
+ const pkg2 = JSON.parse(content);
5428
+ const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
5429
+ if (allDeps["@fragments-sdk/ui"]) {
5430
+ return {
5431
+ name: "Package installed",
5432
+ status: "pass",
5433
+ message: `@fragments-sdk/ui ${allDeps["@fragments-sdk/ui"]} found in dependencies`
5434
+ };
5435
+ }
5436
+ return {
5437
+ name: "Package installed",
5438
+ status: "fail",
5439
+ message: "@fragments-sdk/ui not found in package.json",
5440
+ fix: "npm install @fragments-sdk/ui"
5441
+ };
5442
+ } catch {
5443
+ return {
5444
+ name: "Package installed",
5445
+ status: "fail",
5446
+ message: "No package.json found"
5447
+ };
5448
+ }
5449
+ }
5450
+ async function checkStylesImport(root) {
5451
+ const entryPatterns = [
5452
+ "src/main.tsx",
5453
+ "src/main.ts",
5454
+ "src/index.tsx",
5455
+ "src/index.ts",
5456
+ "src/App.tsx",
5457
+ "src/App.ts",
5458
+ "app/layout.tsx",
5459
+ "app/layout.ts",
5460
+ "src/app/layout.tsx",
5461
+ "src/app/layout.ts",
5462
+ "app/root.tsx",
5463
+ "pages/_app.tsx",
5464
+ "pages/_app.ts"
5465
+ ];
5466
+ for (const pattern of entryPatterns) {
5467
+ try {
5468
+ const content = await readFile8(join10(root, pattern), "utf-8");
5469
+ if (content.includes("@fragments-sdk/ui/styles")) {
5470
+ return {
5471
+ name: "Styles import",
5472
+ status: "pass",
5473
+ message: `Found styles import in ${pattern}`
5474
+ };
5475
+ }
5476
+ if (content.includes("@fragments-sdk/ui/globals")) {
5477
+ return {
5478
+ name: "Styles import",
5479
+ status: "warn",
5480
+ message: `${pattern} uses deprecated '@fragments-sdk/ui/globals'. Use '@fragments-sdk/ui/styles' instead`,
5481
+ fix: `Replace '@fragments-sdk/ui/globals' with '@fragments-sdk/ui/styles' in ${pattern}`
5482
+ };
5483
+ }
5484
+ } catch {
5485
+ }
5486
+ }
5487
+ const scssPatterns = [
5488
+ "src/styles/globals.scss",
5489
+ "src/globals.scss",
5490
+ "styles/globals.scss",
5491
+ "app/globals.scss",
5492
+ "src/app/globals.scss",
5493
+ "app/styles/globals.scss"
5494
+ ];
5495
+ for (const pattern of scssPatterns) {
5496
+ try {
5497
+ const content = await readFile8(join10(root, pattern), "utf-8");
5498
+ if (content.includes("@fragments-sdk/ui/styles")) {
5499
+ return {
5500
+ name: "Styles import",
5501
+ status: "pass",
5502
+ message: `Found SCSS @use import in ${pattern}`
5503
+ };
5504
+ }
5505
+ } catch {
5506
+ }
5507
+ }
5508
+ return {
5509
+ name: "Styles import",
5510
+ status: "fail",
5511
+ message: "No @fragments-sdk/ui/styles import found in entry files",
5512
+ fix: "Add `import '@fragments-sdk/ui/styles'` to your app's entry file"
5513
+ };
5514
+ }
5515
+ async function checkThemeProvider(root) {
5516
+ const providerPatterns = [
5517
+ "src/main.tsx",
5518
+ "src/App.tsx",
5519
+ "src/providers.tsx",
5520
+ "app/layout.tsx",
5521
+ "app/providers.tsx",
5522
+ "src/app/layout.tsx",
5523
+ "src/app/providers.tsx",
5524
+ "app/root.tsx",
5525
+ "pages/_app.tsx"
5526
+ ];
5527
+ for (const pattern of providerPatterns) {
5528
+ try {
5529
+ const content = await readFile8(join10(root, pattern), "utf-8");
5530
+ if (content.includes("ThemeProvider")) {
5531
+ if (content.includes("defaultTheme=") || content.includes("defaultTheme =")) {
5532
+ return {
5533
+ name: "ThemeProvider",
5534
+ status: "warn",
5535
+ message: `${pattern} uses deprecated 'defaultTheme' prop. Use 'defaultMode' instead`,
5536
+ fix: `Replace 'defaultTheme' with 'defaultMode' in ${pattern}`
5537
+ };
5538
+ }
5539
+ return {
5540
+ name: "ThemeProvider",
5541
+ status: "pass",
5542
+ message: `ThemeProvider found in ${pattern}`
5543
+ };
5544
+ }
5545
+ } catch {
5546
+ }
5547
+ }
5548
+ return {
5549
+ name: "ThemeProvider",
5550
+ status: "warn",
5551
+ message: "ThemeProvider not found in common entry files (optional but recommended)",
5552
+ fix: 'Wrap your app with <ThemeProvider defaultMode="system">'
5553
+ };
5554
+ }
5555
+ async function checkScssSeeds(root) {
5556
+ const checks = [];
5557
+ const scssPatterns = [
5558
+ "src/styles/globals.scss",
5559
+ "src/globals.scss",
5560
+ "styles/globals.scss",
5561
+ "app/globals.scss",
5562
+ "src/app/globals.scss",
5563
+ "app/styles/globals.scss"
5564
+ ];
5565
+ for (const pattern of scssPatterns) {
5566
+ try {
5567
+ const content = await readFile8(join10(root, pattern), "utf-8");
5568
+ if (!content.includes("@fragments-sdk/ui/styles")) continue;
5569
+ const standalonePattern = /^\$fui-\w+:\s*.+;$/m;
5570
+ if (standalonePattern.test(content) && !content.includes("@use")) {
5571
+ checks.push({
5572
+ name: "SCSS syntax",
5573
+ status: "fail",
5574
+ message: `${pattern} uses standalone $fui- variables. Must use @use...with() syntax`,
5575
+ fix: "@use '@fragments-sdk/ui/styles' with ($fui-brand: #0066ff);"
5576
+ });
5577
+ }
5578
+ const neutralMatch = content.match(/\$fui-neutral:\s*"([^"]+)"/);
5579
+ if (neutralMatch && !VALID_NEUTRALS.includes(neutralMatch[1])) {
5580
+ checks.push({
5581
+ name: "SCSS seed: neutral",
5582
+ status: "fail",
5583
+ message: `Invalid $fui-neutral: "${neutralMatch[1]}" in ${pattern}`,
5584
+ fix: `Valid neutrals: ${VALID_NEUTRALS.join(", ")}`
5585
+ });
5586
+ }
5587
+ const densityMatch = content.match(/\$fui-density:\s*"([^"]+)"/);
5588
+ if (densityMatch && !VALID_DENSITIES.includes(densityMatch[1])) {
5589
+ checks.push({
5590
+ name: "SCSS seed: density",
5591
+ status: "fail",
5592
+ message: `Invalid $fui-density: "${densityMatch[1]}" in ${pattern}`,
5593
+ fix: `Valid densities: ${VALID_DENSITIES.join(", ")}`
5594
+ });
5595
+ }
5596
+ const radiusMatch = content.match(/\$fui-radius-style:\s*"([^"]+)"/);
5597
+ if (radiusMatch && !VALID_RADII.includes(radiusMatch[1])) {
5598
+ checks.push({
5599
+ name: "SCSS seed: radius-style",
5600
+ status: "fail",
5601
+ message: `Invalid $fui-radius-style: "${radiusMatch[1]}" in ${pattern}`,
5602
+ fix: `Valid radius styles: ${VALID_RADII.join(", ")}`
5603
+ });
5604
+ }
5605
+ const brandMatch = content.match(/\$fui-brand:\s*(#[0-9a-fA-F]+)/);
5606
+ if (brandMatch) {
5607
+ const hex = brandMatch[1];
5608
+ if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(hex)) {
5609
+ checks.push({
5610
+ name: "SCSS seed: brand",
5611
+ status: "fail",
5612
+ message: `Invalid $fui-brand color: "${hex}" in ${pattern}`,
5613
+ fix: "Must be a valid hex color (e.g., #0066ff)"
5614
+ });
5615
+ }
5616
+ }
5617
+ if (checks.length === 0) {
5618
+ checks.push({
5619
+ name: "SCSS seeds",
5620
+ status: "pass",
5621
+ message: `Seed values in ${pattern} are valid`
5622
+ });
5623
+ }
5624
+ return checks;
5625
+ } catch {
5626
+ }
5627
+ }
5628
+ checks.push({
5629
+ name: "SCSS seeds",
5630
+ status: "pass",
5631
+ message: "No custom SCSS seeds configured (using defaults)"
5632
+ });
5633
+ return checks;
5634
+ }
5635
+ async function checkPeerDeps(root) {
5636
+ const checks = [];
5637
+ try {
5638
+ const pkgPath = join10(root, "package.json");
5639
+ const content = await readFile8(pkgPath, "utf-8");
5640
+ const pkg2 = JSON.parse(content);
5641
+ const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
5642
+ if (!allDeps["react"]) {
5643
+ checks.push({
5644
+ name: "Peer dep: react",
5645
+ status: "fail",
5646
+ message: "react not found in dependencies (required)",
5647
+ fix: "npm install react react-dom"
5648
+ });
5649
+ } else {
5650
+ checks.push({
5651
+ name: "Peer dep: react",
5652
+ status: "pass",
5653
+ message: `react ${allDeps["react"]} installed`
5654
+ });
5655
+ }
5656
+ if (!allDeps["sass"]) {
5657
+ checks.push({
5658
+ name: "Peer dep: sass",
5659
+ status: "warn",
5660
+ message: "sass not installed (needed for custom SCSS theming)",
5661
+ fix: "npm install -D sass"
5662
+ });
5663
+ }
5664
+ const optionalPeers = [
5665
+ { pkg: "recharts", components: "Chart" },
5666
+ { pkg: "shiki", components: "CodeBlock" },
5667
+ { pkg: "react-day-picker", components: "DatePicker" },
5668
+ { pkg: "@tanstack/react-table", components: "DataTable" }
5669
+ ];
5670
+ for (const peer of optionalPeers) {
5671
+ if (allDeps[peer.pkg]) {
5672
+ checks.push({
5673
+ name: `Optional dep: ${peer.pkg}`,
5674
+ status: "pass",
5675
+ message: `${peer.pkg} installed (enables ${peer.components})`
5676
+ });
5677
+ }
5678
+ }
5679
+ } catch {
5680
+ checks.push({
5681
+ name: "Peer dependencies",
5682
+ status: "fail",
5683
+ message: "Could not read package.json"
5684
+ });
5685
+ }
5686
+ return checks;
5687
+ }
5688
+ async function checkMcpConfig(root) {
5689
+ const mcpConfigPaths = [
5690
+ ".mcp.json",
5691
+ ".cursor/mcp.json",
5692
+ ".vscode/mcp.json"
5693
+ ];
5694
+ for (const configPath of mcpConfigPaths) {
5695
+ try {
5696
+ const fullPath = join10(root, configPath);
5697
+ const content = await readFile8(fullPath, "utf-8");
5698
+ const config = JSON.parse(content);
5699
+ const servers = config.mcpServers || config.servers || {};
5700
+ const hasFragments = Object.values(servers).some((server) => {
5701
+ const s = server;
5702
+ return s.args?.some((arg) => arg.includes("@fragments-sdk/mcp")) || s.command?.includes("fragments");
5703
+ });
5704
+ if (hasFragments) {
5705
+ return {
5706
+ name: "MCP configuration",
5707
+ status: "pass",
5708
+ message: `Fragments MCP server configured in ${configPath}`
5709
+ };
5710
+ }
5711
+ } catch {
5712
+ }
5713
+ }
5714
+ return {
5715
+ name: "MCP configuration",
5716
+ status: "warn",
5717
+ message: "No Fragments MCP server configuration found (optional)",
5718
+ fix: "Run `fragments init` or add @fragments-sdk/mcp to your MCP config"
5719
+ };
5720
+ }
5721
+ async function checkTypeScript(root) {
5722
+ try {
5723
+ const tsconfigPath = join10(root, "tsconfig.json");
5724
+ await access3(tsconfigPath);
5725
+ return {
5726
+ name: "TypeScript",
5727
+ status: "pass",
5728
+ message: "tsconfig.json found"
5729
+ };
5730
+ } catch {
5731
+ return {
5732
+ name: "TypeScript",
5733
+ status: "warn",
5734
+ message: "No tsconfig.json found (TypeScript recommended but not required)"
5735
+ };
5736
+ }
5737
+ }
5738
+ async function doctor(options = {}) {
5739
+ const root = resolve8(options.root ?? process.cwd());
5740
+ const checks = [];
5741
+ if (!options.json) {
5742
+ console.log(pc22.cyan(`
5743
+ ${BRAND.name} Doctor
5744
+ `));
5745
+ console.log(pc22.dim(`Checking project at ${root}
5746
+ `));
5747
+ }
5748
+ checks.push(await checkPackageInstalled(root));
5749
+ checks.push(await checkStylesImport(root));
5750
+ checks.push(await checkThemeProvider(root));
5751
+ checks.push(...await checkScssSeeds(root));
5752
+ checks.push(...await checkPeerDeps(root));
5753
+ checks.push(await checkMcpConfig(root));
5754
+ checks.push(await checkTypeScript(root));
5755
+ const passed = checks.filter((c) => c.status === "pass").length;
5756
+ const warned = checks.filter((c) => c.status === "warn").length;
5757
+ const failed = checks.filter((c) => c.status === "fail").length;
5758
+ const result = {
5759
+ success: failed === 0,
5760
+ checks,
5761
+ passed,
5762
+ warned,
5763
+ failed
5764
+ };
5765
+ if (options.json) {
5766
+ console.log(JSON.stringify(result, null, 2));
5767
+ } else {
5768
+ for (const check of checks) {
5769
+ const icon = check.status === "pass" ? pc22.green("\u2713") : check.status === "warn" ? pc22.yellow("!") : pc22.red("\u2717");
5770
+ const msg = check.status === "pass" ? check.message : check.status === "warn" ? pc22.yellow(check.message) : pc22.red(check.message);
5771
+ console.log(` ${icon} ${pc22.bold(check.name)}: ${msg}`);
5772
+ if (check.fix && check.status !== "pass") {
5773
+ console.log(pc22.dim(` \u2192 ${check.fix}`));
5774
+ }
5775
+ }
5776
+ console.log();
5777
+ if (failed === 0 && warned === 0) {
5778
+ console.log(pc22.green(`\u2713 All ${passed} checks passed \u2014 your setup looks great!`));
5779
+ } else if (failed === 0) {
5780
+ console.log(pc22.green(`\u2713 ${passed} passed`) + pc22.yellow(`, ${warned} warning(s)`));
5781
+ } else {
5782
+ console.log(
5783
+ pc22.red(`\u2717 ${failed} failed`) + (warned > 0 ? pc22.yellow(`, ${warned} warning(s)`) : "") + pc22.dim(`, ${passed} passed`)
5784
+ );
5785
+ }
5786
+ console.log();
5787
+ }
5788
+ return result;
5789
+ }
5790
+
5366
5791
  // src/bin.ts
5367
5792
  var __dirname = dirname4(fileURLToPath(import.meta.url));
5368
- var pkg = JSON.parse(readFileSync(join10(__dirname, "../package.json"), "utf-8"));
5793
+ var pkg = JSON.parse(readFileSync(join11(__dirname, "../package.json"), "utf-8"));
5369
5794
  var program = new Command();
5370
5795
  program.name(BRAND.cliCommand).description(`${BRAND.name} - Design system documentation and compliance tool`).version(pkg.version);
5371
5796
  program.command("validate").description("Validate fragment files").option("-c, --config <path>", "Path to config file").option("--schema", "Validate fragment schema only").option("--coverage", "Validate coverage only").option("--snippets", "Validate snippet/render policy only").option("--snippet-mode <mode>", "Override snippet policy mode (warn|error)").option("--component-start <name>", "Start component name for alphabetical snippet batch validation").option("--component-limit <n>", "Component count for alphabetical snippet batch validation", (value) => Number.parseInt(value, 10)).action(async (options) => {
@@ -5375,7 +5800,7 @@ program.command("validate").description("Validate fragment files").option("-c, -
5375
5800
  process.exit(1);
5376
5801
  }
5377
5802
  } catch (error) {
5378
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5803
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5379
5804
  process.exit(1);
5380
5805
  }
5381
5806
  });
@@ -5395,7 +5820,7 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
5395
5820
  process.exit(1);
5396
5821
  }
5397
5822
  } catch (error) {
5398
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5823
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5399
5824
  process.exit(1);
5400
5825
  }
5401
5826
  });
@@ -5414,7 +5839,7 @@ program.command("context").description("Generate AI-ready context for your desig
5414
5839
  process.exit(1);
5415
5840
  }
5416
5841
  } catch (error) {
5417
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5842
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5418
5843
  process.exit(1);
5419
5844
  }
5420
5845
  });
@@ -5441,7 +5866,7 @@ program.command("ai").description("Generate context optimized for AI assistants
5441
5866
  }
5442
5867
  }
5443
5868
  } catch (error) {
5444
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5869
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5445
5870
  process.exit(1);
5446
5871
  }
5447
5872
  });
@@ -5449,7 +5874,7 @@ program.command("list").description("List all discovered fragment files").option
5449
5874
  try {
5450
5875
  await list(options);
5451
5876
  } catch (error) {
5452
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5877
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5453
5878
  process.exit(1);
5454
5879
  }
5455
5880
  });
@@ -5457,7 +5882,7 @@ program.command("reset").description("Reset to initial state (delete all generat
5457
5882
  try {
5458
5883
  await reset(options);
5459
5884
  } catch (error) {
5460
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5885
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5461
5886
  process.exit(1);
5462
5887
  }
5463
5888
  });
@@ -5471,7 +5896,7 @@ linkCommand.command("figma").argument("[figma-url]", "Figma file URL to link com
5471
5896
  variants: options.variants
5472
5897
  });
5473
5898
  } catch (error) {
5474
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5899
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5475
5900
  process.exit(1);
5476
5901
  }
5477
5902
  });
@@ -5486,7 +5911,7 @@ linkCommand.command("storybook").description("Bootstrap fragments from existing
5486
5911
  exclude: options.exclude
5487
5912
  });
5488
5913
  } catch (error) {
5489
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5914
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5490
5915
  process.exit(1);
5491
5916
  }
5492
5917
  });
@@ -5501,9 +5926,9 @@ program.command("dev").description("Start the development server with live compo
5501
5926
  skipBuild: options.skipBuild
5502
5927
  });
5503
5928
  } catch (error) {
5504
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5929
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5505
5930
  if (error instanceof Error && error.stack) {
5506
- console.error(pc22.dim(error.stack));
5931
+ console.error(pc23.dim(error.stack));
5507
5932
  }
5508
5933
  process.exit(1);
5509
5934
  }
@@ -5524,7 +5949,7 @@ program.command("screenshot").description("Capture screenshots of component vari
5524
5949
  process.exit(1);
5525
5950
  }
5526
5951
  } catch (error) {
5527
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5952
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5528
5953
  process.exit(1);
5529
5954
  }
5530
5955
  });
@@ -5543,7 +5968,7 @@ program.command("diff").argument("[component]", "Component name to diff (optiona
5543
5968
  process.exit(1);
5544
5969
  }
5545
5970
  } catch (error) {
5546
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5971
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5547
5972
  process.exit(1);
5548
5973
  }
5549
5974
  });
@@ -5562,8 +5987,8 @@ program.command("compare").argument("[component]", "Component name to compare").
5562
5987
  process.exit(1);
5563
5988
  }
5564
5989
  } catch (error) {
5565
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
5566
- console.log(pc22.dim(`
5990
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5991
+ console.log(pc23.dim(`
5567
5992
  Make sure the dev server is running: ${BRAND.cliCommand} dev`));
5568
5993
  process.exit(1);
5569
5994
  }
@@ -5582,7 +6007,7 @@ program.command("analyze").description("Analyze design system and generate repor
5582
6007
  process.exit(1);
5583
6008
  }
5584
6009
  } catch (error) {
5585
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6010
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5586
6011
  process.exit(1);
5587
6012
  }
5588
6013
  });
@@ -5601,7 +6026,7 @@ program.command("verify").argument("[component]", "Component name to verify (opt
5601
6026
  if (options.ci) {
5602
6027
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Verification failed" }));
5603
6028
  } else {
5604
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6029
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5605
6030
  }
5606
6031
  process.exit(1);
5607
6032
  }
@@ -5618,7 +6043,7 @@ program.command("audit").description("Scan all fragments and show compliance met
5618
6043
  if (options.json) {
5619
6044
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Audit failed" }));
5620
6045
  } else {
5621
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6046
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5622
6047
  }
5623
6048
  process.exit(1);
5624
6049
  }
@@ -5640,7 +6065,7 @@ program.command("a11y").description("Run accessibility checks on all component v
5640
6065
  if (options.json) {
5641
6066
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "A11y check failed" }));
5642
6067
  } else {
5643
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6068
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5644
6069
  }
5645
6070
  process.exit(1);
5646
6071
  }
@@ -5663,7 +6088,7 @@ program.command("enhance").description("AI-powered documentation generation from
5663
6088
  if (options.format === "json") {
5664
6089
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Enhance failed" }));
5665
6090
  } else {
5666
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6091
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5667
6092
  }
5668
6093
  process.exit(1);
5669
6094
  }
@@ -5684,7 +6109,7 @@ program.command("scan").description(`Zero-config ${BRAND.outFile} generation fro
5684
6109
  process.exit(1);
5685
6110
  }
5686
6111
  } catch (error) {
5687
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6112
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5688
6113
  process.exit(1);
5689
6114
  }
5690
6115
  });
@@ -5697,7 +6122,7 @@ program.command("storygen").description("Generate Storybook stories from fragmen
5697
6122
  format: options.format
5698
6123
  });
5699
6124
  } catch (error) {
5700
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6125
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5701
6126
  process.exit(1);
5702
6127
  }
5703
6128
  });
@@ -5709,7 +6134,7 @@ program.command("metrics").argument("[component]", "Component name (optional, sh
5709
6134
  json: options.json
5710
6135
  });
5711
6136
  } catch (error) {
5712
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6137
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5713
6138
  process.exit(1);
5714
6139
  }
5715
6140
  });
@@ -5723,9 +6148,9 @@ program.command("baseline").description("Manage visual regression baselines").ar
5723
6148
  port: options.port
5724
6149
  });
5725
6150
  } catch (error) {
5726
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6151
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5727
6152
  if (action === "update") {
5728
- console.log(pc22.dim(`
6153
+ console.log(pc23.dim(`
5729
6154
  Make sure the dev server is running: ${BRAND.cliCommand} dev`));
5730
6155
  }
5731
6156
  process.exit(1);
@@ -5733,27 +6158,27 @@ Make sure the dev server is running: ${BRAND.cliCommand} dev`));
5733
6158
  });
5734
6159
  program.command("view").description(`Generate a static HTML viewer for ${BRAND.outFile}`).option("-i, --input <path>", `Path to ${BRAND.outFile}`, BRAND.outFile).option("-o, --output <path>", "Output HTML file path", BRAND.viewerHtmlFile).option("--open", "Open in browser after generation").action(async (options) => {
5735
6160
  try {
5736
- const { generateViewerFromJson } = await import("./static-viewer-NSODM5VX.js");
6161
+ const { generateViewerFromJson } = await import("./static-viewer-XCS7UJTO.js");
5737
6162
  const fs2 = await import("fs/promises");
5738
6163
  const path = await import("path");
5739
6164
  const inputPath = path.resolve(process.cwd(), options.input);
5740
6165
  const outputPath = path.resolve(process.cwd(), options.output);
5741
- console.log(pc22.cyan(`
6166
+ console.log(pc23.cyan(`
5742
6167
  ${BRAND.name} Viewer Generator
5743
6168
  `));
5744
6169
  try {
5745
6170
  await fs2.access(inputPath);
5746
6171
  } catch {
5747
- console.log(pc22.red(`Error: ${options.input} not found.`));
5748
- console.log(pc22.dim(`
5749
- Run ${pc22.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
6172
+ console.log(pc23.red(`Error: ${options.input} not found.`));
6173
+ console.log(pc23.dim(`
6174
+ Run ${pc23.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
5750
6175
  `));
5751
6176
  process.exit(1);
5752
6177
  }
5753
- console.log(pc22.dim(`Reading: ${options.input}`));
6178
+ console.log(pc23.dim(`Reading: ${options.input}`));
5754
6179
  const html = await generateViewerFromJson(inputPath);
5755
6180
  await fs2.writeFile(outputPath, html);
5756
- console.log(pc22.green(`
6181
+ console.log(pc23.green(`
5757
6182
  \u2713 Generated: ${options.output}
5758
6183
  `));
5759
6184
  if (options.open) {
@@ -5762,7 +6187,7 @@ Run ${pc22.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
5762
6187
  exec(`${openCmd} "${outputPath}"`);
5763
6188
  }
5764
6189
  } catch (error) {
5765
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6190
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5766
6191
  process.exit(1);
5767
6192
  }
5768
6193
  });
@@ -5775,33 +6200,33 @@ program.command("add").argument("[name]", 'Component name (e.g., "Button", "Text
5775
6200
  component: options.component
5776
6201
  });
5777
6202
  } catch (error) {
5778
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6203
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5779
6204
  process.exit(1);
5780
6205
  }
5781
6206
  });
5782
6207
  program.command("init").description("Initialize fragments in a project (interactive by default)").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive mode - auto-detect and use defaults").action(async (options) => {
5783
6208
  try {
5784
- const { init } = await import("./init-KFYN37ZY.js");
6209
+ const { init } = await import("./init-2GEGVIUQ.js");
5785
6210
  const result = await init({
5786
6211
  projectRoot: process.cwd(),
5787
6212
  force: options.force,
5788
6213
  yes: options.yes
5789
6214
  });
5790
6215
  if (!result.success) {
5791
- console.error(pc22.red("\nInit failed with errors:"));
6216
+ console.error(pc23.red("\nInit failed with errors:"));
5792
6217
  for (const error of result.errors) {
5793
- console.error(pc22.red(` - ${error}`));
6218
+ console.error(pc23.red(` - ${error}`));
5794
6219
  }
5795
6220
  process.exit(1);
5796
6221
  }
5797
6222
  } catch (error) {
5798
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6223
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5799
6224
  process.exit(1);
5800
6225
  }
5801
6226
  });
5802
6227
  program.command("tokens").description("Discover and list design tokens from CSS/SCSS files").option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--categories", "Group tokens by category").option("--theme <theme>", "Filter by theme name").option("--category <category>", "Filter by category (color, spacing, typography, etc.)").option("--verbose", "Show all tokens (no truncation)").action(async (options) => {
5803
6228
  try {
5804
- const { tokens } = await import("./tokens-NIXSZRX7.js");
6229
+ const { tokens } = await import("./tokens-2EXPCVP3.js");
5805
6230
  const result = await tokens({
5806
6231
  config: options.config,
5807
6232
  json: options.json,
@@ -5814,13 +6239,13 @@ program.command("tokens").description("Discover and list design tokens from CSS/
5814
6239
  process.exit(1);
5815
6240
  }
5816
6241
  } catch (error) {
5817
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6242
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5818
6243
  process.exit(1);
5819
6244
  }
5820
6245
  });
5821
6246
  program.command("generate").description("Generate fragment files from component source code").argument("[component]", "Specific component name to generate (optional)").option("--force", "Overwrite existing fragment files").option("--pattern <glob>", "Pattern for component files", "src/components/**/*.tsx").action(async (component, options) => {
5822
6247
  try {
5823
- const { generate } = await import("./generate-35OIMW4Y.js");
6248
+ const { generate } = await import("./generate-LQA2R7FN.js");
5824
6249
  const result = await generate({
5825
6250
  projectRoot: process.cwd(),
5826
6251
  component,
@@ -5828,11 +6253,11 @@ program.command("generate").description("Generate fragment files from component
5828
6253
  componentPattern: options.pattern
5829
6254
  });
5830
6255
  if (!result.success) {
5831
- console.error(pc22.red("\nGenerate completed with errors"));
6256
+ console.error(pc23.red("\nGenerate completed with errors"));
5832
6257
  process.exit(1);
5833
6258
  }
5834
6259
  } catch (error) {
5835
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6260
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5836
6261
  process.exit(1);
5837
6262
  }
5838
6263
  });
@@ -5840,7 +6265,7 @@ program.command("graph").description("Query the component relationship graph").a
5840
6265
  try {
5841
6266
  await graph(component, options);
5842
6267
  } catch (error) {
5843
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6268
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5844
6269
  process.exit(1);
5845
6270
  }
5846
6271
  });
@@ -5858,14 +6283,14 @@ program.command("perf").description("Profile component bundle sizes and performa
5858
6283
  process.exit(1);
5859
6284
  }
5860
6285
  } catch (error) {
5861
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6286
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5862
6287
  process.exit(1);
5863
6288
  }
5864
6289
  });
5865
6290
  program.command("test").description("Run interaction tests for fragments with play functions").option("-c, --config <path>", "Path to config file").option("--component <name>", "Filter by component name").option("--tags <tags>", "Filter by tags (comma-separated)").option("--grep <pattern>", "Filter by variant name pattern").option("--exclude <pattern>", "Exclude tests matching pattern").option("--parallel <count>", "Number of parallel browser contexts", parseInt, 4).option("--timeout <ms>", "Timeout per test in milliseconds", parseInt, 3e4).option("--retries <count>", "Number of retries for failed tests", parseInt, 0).option("--bail", "Stop on first failure").option("--browser <name>", "Browser to use (chromium, firefox, webkit)", "chromium").option("--headed", "Run in headed mode (show browser)").option("--a11y", "Run accessibility checks with axe-core").option("--visual", "Capture screenshots for visual regression").option("--update-snapshots", "Update visual snapshots").option("--watch", "Watch mode - re-run on file changes").option("--reporters <names>", "Reporters to use (console, junit, json)", "console").option("-o, --output <dir>", "Output directory for results", "./test-results").option("--server-url <url>", "URL of running dev server (skips starting server)").option("-p, --port <port>", "Port for dev server", parseInt, 6006).option("--ci", "CI mode - non-interactive, exit with code 1 on failure").option("--list", "List available tests without running them").action(async (options) => {
5866
6291
  try {
5867
6292
  const { config, configDir } = await loadConfig(options.config);
5868
- const { runTestCommand, listTests } = await import("./test-RPWZAYSJ.js");
6293
+ const { runTestCommand, listTests } = await import("./test-TD6TJNVY.js");
5869
6294
  if (options.list) {
5870
6295
  await listTests(config, configDir, {
5871
6296
  component: options.component,
@@ -5898,7 +6323,22 @@ program.command("test").description("Run interaction tests for fragments with pl
5898
6323
  });
5899
6324
  process.exit(exitCode);
5900
6325
  } catch (error) {
5901
- console.error(pc22.red("Error:"), error instanceof Error ? error.message : error);
6326
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6327
+ process.exit(1);
6328
+ }
6329
+ });
6330
+ program.command("doctor").description("Diagnose design system configuration issues").option("--root <dir>", "Project root directory", process.cwd()).option("--json", "Output results as JSON").option("--fix", "Auto-fix issues where possible").action(async (options) => {
6331
+ try {
6332
+ const result = await doctor({
6333
+ root: options.root,
6334
+ json: options.json,
6335
+ fix: options.fix
6336
+ });
6337
+ if (!result.success) {
6338
+ process.exit(1);
6339
+ }
6340
+ } catch (error) {
6341
+ console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5902
6342
  process.exit(1);
5903
6343
  }
5904
6344
  });