@fragments-sdk/cli 0.9.0 → 0.10.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.
Files changed (166) hide show
  1. package/dist/bin.d.ts +1 -0
  2. package/dist/bin.js +502 -84
  3. package/dist/bin.js.map +1 -1
  4. package/dist/{chunk-CJEGT3WD.js → chunk-566BNPQZ.js} +21 -6
  5. package/dist/chunk-566BNPQZ.js.map +1 -0
  6. package/dist/{chunk-WI6SLMSO.js → chunk-CAMXG5HJ.js} +5 -5
  7. package/dist/chunk-D2CDBRNU.js +2 -0
  8. package/dist/{chunk-YMPGYEWK.js → chunk-D5PYOXEI.js} +2 -2
  9. package/dist/{chunk-NGIMCIK2.js → chunk-OQO55NKV.js} +405 -34
  10. package/dist/chunk-OQO55NKV.js.map +1 -0
  11. package/dist/{chunk-TOIE7VXF.js → chunk-PW7QTQA6.js} +2 -2
  12. package/dist/{chunk-AWYCDRPG.js → chunk-WXSR2II7.js} +2 -2
  13. package/dist/chunk-WXSR2II7.js.map +1 -0
  14. package/dist/{chunk-2JIKCJX3.js → chunk-ZDA3PLQ6.js} +17 -14
  15. package/dist/chunk-ZDA3PLQ6.js.map +1 -0
  16. package/dist/core/index.d.ts +1 -2092
  17. package/dist/core/index.js +26 -21
  18. package/dist/{discovery-Z4RDDFVR.js → discovery-NEOY4MPN.js} +3 -3
  19. package/dist/generate-BGKTKO6E.js +459 -0
  20. package/dist/generate-BGKTKO6E.js.map +1 -0
  21. package/dist/index.d.ts +3 -5
  22. package/dist/index.js +7 -8
  23. package/dist/index.js.map +1 -1
  24. package/dist/{init-KSAAS7X3.js → init-Q53R5Q2T.js} +66 -76
  25. package/dist/init-Q53R5Q2T.js.map +1 -0
  26. package/dist/mcp-bin.js +5 -7
  27. package/dist/mcp-bin.js.map +1 -1
  28. package/dist/scan-OQU7M4GH.js +14 -0
  29. package/dist/scan-generate-T5QNUG7N.js +691 -0
  30. package/dist/scan-generate-T5QNUG7N.js.map +1 -0
  31. package/dist/{service-A5GIGGGK.js → service-TQYWY65E.js} +4 -5
  32. package/dist/{static-viewer-NSODM5VX.js → static-viewer-NUBFPKWH.js} +4 -5
  33. package/dist/static-viewer-NUBFPKWH.js.map +1 -0
  34. package/dist/{test-RPWZAYSJ.js → test-2CSOSS3B.js} +4 -5
  35. package/dist/{test-RPWZAYSJ.js.map → test-2CSOSS3B.js.map} +1 -1
  36. package/dist/{tokens-NIXSZRX7.js → tokens-DXEGYTOJ.js} +6 -7
  37. package/dist/{tokens-NIXSZRX7.js.map → tokens-DXEGYTOJ.js.map} +1 -1
  38. package/dist/{viewer-SBTJDMP7.js → viewer-DBEPYM3G.js} +245 -23
  39. package/dist/viewer-DBEPYM3G.js.map +1 -0
  40. package/package.json +2 -1
  41. package/src/bin.ts +33 -1
  42. package/src/build.ts +13 -3
  43. package/src/commands/__tests__/scan-generate.test.ts +308 -0
  44. package/src/commands/build.ts +16 -2
  45. package/src/commands/generate.ts +383 -68
  46. package/src/commands/init.ts +81 -56
  47. package/src/commands/perf.ts +1 -1
  48. package/src/commands/scan-generate.ts +1013 -0
  49. package/src/commands/setup.ts +499 -0
  50. package/src/core/auto-props.ts +1 -1
  51. package/src/core/bundle-measurer.ts +2 -2
  52. package/src/core/config.ts +16 -4
  53. package/src/core/discovery.ts +2 -2
  54. package/src/core/generators/context.ts +1 -1
  55. package/src/core/generators/registry.ts +3 -3
  56. package/src/core/generators/typescript-extractor.ts +11 -1
  57. package/src/core/graph-extractor.ts +1 -1
  58. package/src/core/index.ts +3 -190
  59. package/src/core/loader.ts +2 -2
  60. package/src/core/parser.ts +1 -1
  61. package/src/core/previewLoader.ts +1 -1
  62. package/src/index.ts +2 -2
  63. package/src/migrate/converter.ts +9 -1
  64. package/src/migrate/parser.ts +2 -0
  65. package/src/migrate/types.ts +2 -0
  66. package/src/service/snippet-validation.test.ts +1 -1
  67. package/src/service/snippet-validation.ts +2 -2
  68. package/src/setup.ts +69 -24
  69. package/src/viewer/__tests__/viewer-integration.test.ts +4 -10
  70. package/src/viewer/components/AccessibilityPanel.tsx +305 -312
  71. package/src/viewer/components/ActionsPanel.tsx +31 -29
  72. package/src/viewer/components/AllVariantsPreview.tsx +78 -0
  73. package/src/viewer/components/App.tsx +187 -740
  74. package/src/viewer/components/BottomPanel.tsx +228 -132
  75. package/src/viewer/components/CodePanel.tsx +1 -1
  76. package/src/viewer/components/CommandPalette.tsx +7 -10
  77. package/src/viewer/components/ComponentDocView.tsx +164 -0
  78. package/src/viewer/components/ComponentGraph.tsx +111 -142
  79. package/src/viewer/components/ContractPanel.tsx +6 -6
  80. package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
  81. package/src/viewer/components/FigmaEmbed.tsx +20 -18
  82. package/src/viewer/components/FragmentEditor.tsx +92 -115
  83. package/src/viewer/components/HeaderSearch.tsx +24 -0
  84. package/src/viewer/components/HealthDashboard.tsx +16 -2
  85. package/src/viewer/components/Icons.tsx +9 -0
  86. package/src/viewer/components/InteractionsPanel.tsx +101 -117
  87. package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
  88. package/src/viewer/components/LandingPage.tsx +3 -3
  89. package/src/viewer/components/LeftSidebar.tsx +141 -63
  90. package/src/viewer/components/LoadErrorMessage.tsx +102 -0
  91. package/src/viewer/components/MultiViewportPreview.tsx +61 -142
  92. package/src/viewer/components/NoVariantsMessage.tsx +59 -0
  93. package/src/viewer/components/PanelShell.tsx +161 -0
  94. package/src/viewer/components/PerformancePanel.tsx +31 -28
  95. package/src/viewer/components/PreviewArea.tsx +1 -1
  96. package/src/viewer/components/PreviewAside.tsx +168 -0
  97. package/src/viewer/components/PreviewFrameHost.tsx +3 -3
  98. package/src/viewer/components/PropsEditor.tsx +70 -156
  99. package/src/viewer/components/ResizablePanel.tsx +103 -263
  100. package/src/viewer/components/RightSidebar.tsx +3 -9
  101. package/src/viewer/components/SkeletonLoader.tsx +13 -13
  102. package/src/viewer/components/TokenStylePanel.tsx +182 -209
  103. package/src/viewer/components/TopToolbar.tsx +159 -0
  104. package/src/viewer/components/VariantMatrix.tsx +42 -86
  105. package/src/viewer/components/VariantTabs.tsx +3 -3
  106. package/src/viewer/components/ViewerHeader.tsx +69 -0
  107. package/src/viewer/components/WebMCPDevTools.tsx +17 -23
  108. package/src/viewer/components/viewer-utils.ts +16 -0
  109. package/src/viewer/entry.tsx +5 -0
  110. package/src/viewer/hooks/useAppState.ts +27 -4
  111. package/src/viewer/hooks/usePreviewBridge.ts +2 -2
  112. package/src/viewer/preview-frame.html +6 -12
  113. package/src/viewer/server.ts +169 -2
  114. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
  115. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
  116. package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
  117. package/src/viewer/vendor/shared/src/DocsHeaderBar.tsx +6 -18
  118. package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
  119. package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +5 -16
  120. package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
  121. package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
  122. package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
  123. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +114 -0
  124. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
  125. package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
  126. package/src/viewer/vendor/shared/src/index.ts +8 -0
  127. package/src/viewer/vendor/shared/src/types.ts +12 -0
  128. package/src/viewer/vite-plugin.ts +109 -4
  129. package/dist/chunk-2JIKCJX3.js.map +0 -1
  130. package/dist/chunk-AWYCDRPG.js.map +0 -1
  131. package/dist/chunk-CJEGT3WD.js.map +0 -1
  132. package/dist/chunk-EKLMXTWU.js +0 -80
  133. package/dist/chunk-EKLMXTWU.js.map +0 -1
  134. package/dist/chunk-GOVI6COW.js +0 -195
  135. package/dist/chunk-GOVI6COW.js.map +0 -1
  136. package/dist/chunk-NGIMCIK2.js.map +0 -1
  137. package/dist/defineFragment-D0UTve-I.d.ts +0 -665
  138. package/dist/generate-35OIMW4Y.js +0 -252
  139. package/dist/generate-35OIMW4Y.js.map +0 -1
  140. package/dist/init-KSAAS7X3.js.map +0 -1
  141. package/dist/scan-65RH3QMM.js +0 -15
  142. package/dist/viewer-SBTJDMP7.js.map +0 -1
  143. package/src/core/__tests__/preview-runtime.test.tsx +0 -111
  144. package/src/core/composition.test.ts +0 -262
  145. package/src/core/composition.ts +0 -318
  146. package/src/core/constants.ts +0 -114
  147. package/src/core/context.ts +0 -2
  148. package/src/core/defineFragment.ts +0 -141
  149. package/src/core/figma.ts +0 -263
  150. package/src/core/fragment-types.ts +0 -214
  151. package/src/core/performance-presets.ts +0 -142
  152. package/src/core/preview-runtime.tsx +0 -144
  153. package/src/core/schema.ts +0 -221
  154. package/src/core/storyAdapter.test.ts +0 -571
  155. package/src/core/storyAdapter.ts +0 -761
  156. package/src/core/storybook-csf.ts +0 -11
  157. package/src/core/token-parser.ts +0 -321
  158. package/src/core/token-types.ts +0 -287
  159. package/src/core/types.ts +0 -762
  160. /package/dist/{chunk-WI6SLMSO.js.map → chunk-CAMXG5HJ.js.map} +0 -0
  161. /package/dist/{discovery-Z4RDDFVR.js.map → chunk-D2CDBRNU.js.map} +0 -0
  162. /package/dist/{chunk-YMPGYEWK.js.map → chunk-D5PYOXEI.js.map} +0 -0
  163. /package/dist/{chunk-TOIE7VXF.js.map → chunk-PW7QTQA6.js.map} +0 -0
  164. /package/dist/{scan-65RH3QMM.js.map → discovery-NEOY4MPN.js.map} +0 -0
  165. /package/dist/{service-A5GIGGGK.js.map → scan-OQU7M4GH.js.map} +0 -0
  166. /package/dist/{static-viewer-NSODM5VX.js.map → service-TQYWY65E.js.map} +0 -0
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * fragments init - Smart interactive initialization
3
3
  *
4
- * Handles three scenarios:
5
- * 1. Stories foundConfigure and load existing stories
6
- * 2. Components found (no stories) Auto-generate documentation
7
- * 3. Fresh project Guided setup with example component
4
+ * Handles four scenarios:
5
+ * 1. --scan <path>Scan external component library, generate fragment files
6
+ * 2. Stories found Configure and load existing stories
7
+ * 3. Components found (no stories) Auto-generate documentation
8
+ * 4. Fresh project → Guided setup with example component
8
9
  */
9
10
 
10
11
  import { readFile, writeFile, mkdir, access } from "node:fs/promises";
@@ -29,12 +30,14 @@ export interface InitOptions {
29
30
  yes?: boolean;
30
31
  /** Explicit framework override */
31
32
  framework?: string;
33
+ /** Path to scan for components (enables scan mode) */
34
+ scan?: string;
32
35
  }
33
36
 
34
37
  export interface InitResult {
35
38
  success: boolean;
36
39
  configPath?: string;
37
- scenario: "stories" | "components" | "fresh";
40
+ scenario: "stories" | "components" | "fresh" | "scan";
38
41
  storiesFound: number;
39
42
  componentsFound: number;
40
43
  errors: string[];
@@ -396,6 +399,70 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
396
399
  const projectRoot = resolve(options.projectRoot || process.cwd());
397
400
  const errors: string[] = [];
398
401
 
402
+ // Early return for scan mode — non-interactive
403
+ if (options.scan) {
404
+ const scanPath = resolve(projectRoot, options.scan);
405
+
406
+ // Verify scan path exists
407
+ try {
408
+ await access(scanPath);
409
+ } catch {
410
+ console.error(pc.red(`\nScan path not found: ${scanPath}\n`));
411
+ return {
412
+ success: false,
413
+ scenario: "scan",
414
+ storiesFound: 0,
415
+ componentsFound: 0,
416
+ errors: [`Scan path not found: ${scanPath}`],
417
+ };
418
+ }
419
+
420
+ // Run scan-generate
421
+ const { scanGenerate } = await import("./scan-generate.js");
422
+ const scanResult = await scanGenerate({
423
+ scanPath,
424
+ force: options.force,
425
+ verbose: true,
426
+ });
427
+
428
+ // Create config pointing at the scanned path
429
+ const relScanPath = relative(projectRoot, scanPath);
430
+ const configPath = join(projectRoot, BRAND.configFile);
431
+ const configContent = generateConfig({
432
+ includePaths: [`${relScanPath}/**/*.fragment.tsx`],
433
+ componentPaths: [`${relScanPath}/**/*.tsx`],
434
+ framework: "react",
435
+ });
436
+
437
+ try {
438
+ await writeFile(configPath, configContent, "utf-8");
439
+ console.log(pc.green(`✓ Created ${BRAND.configFile}`));
440
+ } catch (e) {
441
+ errors.push(`Failed to create config: ${e}`);
442
+ }
443
+
444
+ // Next steps
445
+ if (scanResult.success) {
446
+ console.log(pc.cyan("Next steps:"));
447
+ console.log(` 1. Search generated files for ${pc.bold("TODO:")} markers and fill in human knowledge`);
448
+ console.log(` 2. Run ${pc.bold(`${BRAND.cliCommand} dev`)} to preview your components`);
449
+ console.log(` 3. Run ${pc.bold(`${BRAND.cliCommand} build`)} to compile fragments.json`);
450
+ console.log();
451
+ }
452
+
453
+ return {
454
+ success: scanResult.success && errors.length === 0,
455
+ configPath: errors.length === 0 ? configPath : undefined,
456
+ scenario: "scan",
457
+ storiesFound: 0,
458
+ componentsFound: scanResult.generated.length,
459
+ errors: [
460
+ ...errors,
461
+ ...scanResult.errors.map((e) => `${e.name}: ${e.error}`),
462
+ ],
463
+ };
464
+ }
465
+
399
466
  console.log(pc.cyan(`\n✨ Welcome to ${BRAND.name}!\n`));
400
467
 
401
468
  // Step 1: Detect what exists
@@ -462,9 +529,9 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
462
529
 
463
530
  // Step 3: Gather configuration (interactive unless --yes)
464
531
  let componentPath = detection.suggestedComponentPath;
465
- let runScan = scenario === "components";
532
+ let runScan = scenario === "components" || scenario === "stories";
466
533
  let createExample = scenario === "fresh";
467
- let startServer = true;
534
+ let startServer = false;
468
535
 
469
536
  if (!options.yes) {
470
537
  // Ask about component location
@@ -473,13 +540,7 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
473
540
  default: detection.suggestedComponentPath,
474
541
  });
475
542
 
476
- if (scenario === "components") {
477
- // For component-only projects, ask about scanning
478
- runScan = await confirm({
479
- message: "Auto-generate documentation from TypeScript?",
480
- default: true,
481
- });
482
- } else {
543
+ if (scenario === "fresh") {
483
544
  // Fresh project - ask about example
484
545
  createExample = await confirm({
485
546
  message: "Create an example Button component to get started?",
@@ -502,7 +563,7 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
502
563
  `${componentPath}/**/*.fragment.tsx`,
503
564
  ];
504
565
 
505
- // Include story files when Storybook is detected
566
+ // If Storybook stories detected, also include them for direct rendering
506
567
  if (scenario === 'stories') {
507
568
  includePaths.push(`${componentPath}/**/*.stories.tsx`);
508
569
  includePaths.push(`${componentPath}/**/*.stories.ts`);
@@ -557,39 +618,9 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
557
618
  }
558
619
  }
559
620
 
560
- if (scenario === "components" && runScan) {
561
- // Generate .fragment.tsx stubs for discovered components
562
- let stubsCreated = 0;
563
- for (const compFile of detection.componentFiles) {
564
- const absPath = join(projectRoot, compFile);
565
- const dir = dirname(absPath);
566
- const fileName = basename(compFile, ".tsx");
567
- const componentName = toPascalCase(fileName);
568
- const fragmentPath = join(dir, `${fileName}.fragment.tsx`);
569
-
570
- // Skip if fragment already exists
571
- try {
572
- await access(fragmentPath);
573
- continue; // already exists
574
- } catch {
575
- // doesn't exist, create it
576
- }
577
-
578
- try {
579
- const stub = generateFragmentStub(componentName, `./${fileName}`);
580
- await writeFile(fragmentPath, stub, "utf-8");
581
- stubsCreated++;
582
- } catch {
583
- // skip files we can't write to
584
- }
585
- }
586
-
587
- if (stubsCreated > 0) {
588
- console.log(pc.green(`✓ Generated ${stubsCreated} fragment stub(s)`));
589
- }
590
-
591
- // Run scan to generate fragments.json
592
- console.log(pc.dim("\nGenerating documentation from source code...\n"));
621
+ if (runScan) {
622
+ // Run scan to generate fragments.json from source code
623
+ console.log(pc.dim("\nScanning source code for documentation...\n"));
593
624
  try {
594
625
  const { scan } = await import("./scan.js");
595
626
  await scan({
@@ -641,14 +672,7 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
641
672
  console.log(pc.green("\n✓ Setup complete!\n"));
642
673
 
643
674
  if (startServer) {
644
- const serverMessage =
645
- scenario === "stories"
646
- ? `Your ${detection.storyFiles.length} stories are loading...`
647
- : scenario === "components"
648
- ? `Your ${detection.componentFiles.length} components are being documented...`
649
- : `Your first component is ready!`;
650
-
651
- console.log(pc.cyan(serverMessage));
675
+ console.log(pc.cyan("Starting viewer...\n"));
652
676
  startDevServer(projectRoot);
653
677
  } else {
654
678
  console.log(pc.cyan("Next steps:"));
@@ -656,6 +680,7 @@ export async function init(options: InitOptions = {}): Promise<InitResult> {
656
680
  if (scenario === "fresh") {
657
681
  console.log(` 2. Edit ${pc.bold(`${componentPath}/Button/Button.fragment.tsx`)}`);
658
682
  }
683
+ console.log(` 3. Run ${pc.bold(`${BRAND.cliCommand} generate`)} to create fragment files for your components`);
659
684
  console.log();
660
685
  }
661
686
  }
@@ -16,7 +16,7 @@ import {
16
16
  budgetBar,
17
17
  type PerformanceConfig,
18
18
  type ComplexityTier,
19
- } from '../core/performance-presets.js';
19
+ } from '../core/index.js';
20
20
  import {
21
21
  measureBundleSizes,
22
22
  toPerformanceData,