@fragments-sdk/cli 0.6.0 → 0.7.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 (178) hide show
  1. package/dist/bin.js +529 -285
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-F7ITZPDJ.js → chunk-32VIEOQY.js} +18 -18
  4. package/dist/chunk-32VIEOQY.js.map +1 -0
  5. package/dist/{chunk-SSLQXHNX.js → chunk-5ITIP3ES.js} +27 -27
  6. package/dist/chunk-5ITIP3ES.js.map +1 -0
  7. package/dist/{chunk-RVRTRESS.js → chunk-DQHWLAUV.js} +29 -29
  8. package/dist/chunk-DQHWLAUV.js.map +1 -0
  9. package/dist/{chunk-Q7GOHVOK.js → chunk-GCZMFLDI.js} +67 -32
  10. package/dist/chunk-GCZMFLDI.js.map +1 -0
  11. package/dist/{chunk-6JBGU74P.js → chunk-GHYYFAQN.js} +23 -23
  12. package/dist/chunk-GHYYFAQN.js.map +1 -0
  13. package/dist/{chunk-NWQ4CJOQ.js → chunk-GKX2HPZ6.js} +40 -40
  14. package/dist/chunk-GKX2HPZ6.js.map +1 -0
  15. package/dist/{chunk-D35RGPAG.js → chunk-U6VTHBNI.js} +499 -83
  16. package/dist/chunk-U6VTHBNI.js.map +1 -0
  17. package/dist/{core-SKRPJQZG.js → core-SFHPYR5H.js} +24 -26
  18. package/dist/{generate-7AF7WRVK.js → generate-54GJAWUY.js} +5 -5
  19. package/dist/generate-54GJAWUY.js.map +1 -0
  20. package/dist/index.d.ts +23 -27
  21. package/dist/index.js +10 -10
  22. package/dist/{init-WKGDPYI4.js → init-EIM5WNMP.js} +5 -5
  23. package/dist/{init-WKGDPYI4.js.map → init-EIM5WNMP.js.map} +1 -1
  24. package/dist/mcp-bin.js +73 -73
  25. package/dist/mcp-bin.js.map +1 -1
  26. package/dist/scan-KQBKUS64.js +12 -0
  27. package/dist/{service-F3E4JJM7.js → service-ED2LNCTU.js} +6 -6
  28. package/dist/{static-viewer-4LQZ5AGA.js → static-viewer-Q4F4QP5M.js} +4 -4
  29. package/dist/{test-CJDNJTPZ.js → test-6VN2DA3S.js} +19 -19
  30. package/dist/test-6VN2DA3S.js.map +1 -0
  31. package/dist/{tokens-JAJABYXP.js → tokens-P2B7ZAM3.js} +5 -5
  32. package/dist/{viewer-R3Q6WAMJ.js → viewer-GM7IQPPB.js} +199 -199
  33. package/dist/viewer-GM7IQPPB.js.map +1 -0
  34. package/package.json +2 -2
  35. package/src/ai.ts +5 -5
  36. package/src/analyze.ts +11 -11
  37. package/src/bin.ts +24 -1
  38. package/src/build.ts +64 -21
  39. package/src/commands/a11y.ts +6 -6
  40. package/src/commands/add.ts +11 -11
  41. package/src/commands/audit.ts +4 -4
  42. package/src/commands/baseline.ts +3 -3
  43. package/src/commands/build.ts +8 -8
  44. package/src/commands/compare.ts +20 -20
  45. package/src/commands/context.ts +16 -16
  46. package/src/commands/enhance.ts +36 -36
  47. package/src/commands/generate.ts +1 -1
  48. package/src/commands/graph.ts +274 -0
  49. package/src/commands/init.ts +1 -1
  50. package/src/commands/link/figma.ts +82 -82
  51. package/src/commands/link/index.ts +3 -3
  52. package/src/commands/link/storybook.ts +9 -9
  53. package/src/commands/list.ts +2 -2
  54. package/src/commands/reset.ts +15 -15
  55. package/src/commands/scan.ts +27 -27
  56. package/src/commands/storygen.ts +24 -24
  57. package/src/commands/validate.ts +2 -2
  58. package/src/commands/verify.ts +8 -8
  59. package/src/core/auto-props.ts +4 -4
  60. package/src/core/composition.test.ts +36 -36
  61. package/src/core/composition.ts +83 -20
  62. package/src/core/config.ts +6 -6
  63. package/src/core/{defineSegment.ts → defineFragment.ts} +16 -22
  64. package/src/core/discovery.ts +6 -6
  65. package/src/core/figma.ts +2 -2
  66. package/src/core/graph-extractor.test.ts +542 -0
  67. package/src/core/graph-extractor.ts +601 -0
  68. package/src/core/importAnalyzer.ts +6 -1
  69. package/src/core/index.ts +22 -23
  70. package/src/core/loader.ts +22 -22
  71. package/src/core/node.ts +5 -5
  72. package/src/core/parser.ts +31 -31
  73. package/src/core/previewLoader.ts +1 -1
  74. package/src/core/schema.ts +16 -16
  75. package/src/core/storyAdapter.test.ts +87 -87
  76. package/src/core/storyAdapter.ts +16 -16
  77. package/src/core/types.ts +21 -26
  78. package/src/diff.ts +22 -22
  79. package/src/index.ts +2 -2
  80. package/src/mcp/server.ts +80 -80
  81. package/src/migrate/__tests__/utils/utils.test.ts +3 -3
  82. package/src/migrate/bin.ts +4 -4
  83. package/src/migrate/converter.ts +16 -16
  84. package/src/migrate/index.ts +3 -3
  85. package/src/migrate/migrate.ts +3 -3
  86. package/src/migrate/parser.ts +8 -8
  87. package/src/migrate/report.ts +2 -2
  88. package/src/migrate/types.ts +4 -4
  89. package/src/screenshot.ts +22 -22
  90. package/src/service/__tests__/props-extractor.test.ts +15 -15
  91. package/src/service/analytics.ts +39 -39
  92. package/src/service/enhance/codebase-scanner.ts +1 -1
  93. package/src/service/enhance/index.ts +1 -1
  94. package/src/service/enhance/props-extractor.ts +2 -2
  95. package/src/service/enhance/types.ts +2 -2
  96. package/src/service/index.ts +2 -2
  97. package/src/service/metrics-store.ts +1 -1
  98. package/src/service/patch-generator.ts +1 -1
  99. package/src/setup.ts +52 -52
  100. package/src/shared/dev-server-client.ts +7 -7
  101. package/src/shared/fragment-loader.ts +59 -0
  102. package/src/shared/index.ts +1 -1
  103. package/src/shared/types.ts +4 -4
  104. package/src/static-viewer.ts +35 -35
  105. package/src/test/discovery.ts +6 -6
  106. package/src/test/index.ts +5 -5
  107. package/src/test/reporters/console.ts +1 -1
  108. package/src/test/reporters/junit.ts +1 -1
  109. package/src/test/runner.ts +7 -7
  110. package/src/test/types.ts +3 -3
  111. package/src/test/watch.ts +9 -9
  112. package/src/validators.ts +26 -26
  113. package/src/viewer/__tests__/render-utils.test.ts +28 -28
  114. package/src/viewer/__tests__/viewer-integration.test.ts +4 -4
  115. package/src/viewer/cli/health.ts +26 -26
  116. package/src/viewer/components/App.tsx +201 -103
  117. package/src/viewer/components/BottomPanel.tsx +17 -17
  118. package/src/viewer/components/CodePanel.tsx +3 -3
  119. package/src/viewer/components/CommandPalette.tsx +11 -11
  120. package/src/viewer/components/ComponentGraph.tsx +28 -28
  121. package/src/viewer/components/ComponentHeader.tsx +2 -2
  122. package/src/viewer/components/ContractPanel.tsx +6 -6
  123. package/src/viewer/components/FigmaEmbed.tsx +9 -9
  124. package/src/viewer/components/HealthDashboard.tsx +17 -17
  125. package/src/viewer/components/Icons.tsx +53 -1
  126. package/src/viewer/components/InteractionsPanel.tsx +2 -2
  127. package/src/viewer/components/IsolatedPreviewFrame.tsx +6 -6
  128. package/src/viewer/components/IsolatedRender.tsx +10 -10
  129. package/src/viewer/components/Layout.tsx +7 -3
  130. package/src/viewer/components/LeftSidebar.tsx +92 -114
  131. package/src/viewer/components/MultiViewportPreview.tsx +14 -14
  132. package/src/viewer/components/PreviewArea.tsx +11 -11
  133. package/src/viewer/components/PreviewFrameHost.tsx +77 -48
  134. package/src/viewer/components/PreviewToolbar.tsx +57 -10
  135. package/src/viewer/components/RightSidebar.tsx +9 -9
  136. package/src/viewer/components/Sidebar.tsx +17 -17
  137. package/src/viewer/components/StoryRenderer.tsx +2 -2
  138. package/src/viewer/components/TokenStylePanel.tsx +1 -1
  139. package/src/viewer/components/UsageSection.tsx +2 -2
  140. package/src/viewer/components/VariantMatrix.tsx +11 -11
  141. package/src/viewer/components/VariantRenderer.tsx +3 -3
  142. package/src/viewer/components/VariantTabs.tsx +2 -2
  143. package/src/viewer/components/ViewportSelector.tsx +56 -45
  144. package/src/viewer/components/_future/CreatePage.tsx +6 -6
  145. package/src/viewer/composition-renderer.ts +11 -11
  146. package/src/viewer/constants/ui.ts +4 -4
  147. package/src/viewer/entry.tsx +40 -40
  148. package/src/viewer/hooks/useFigmaIntegration.ts +1 -1
  149. package/src/viewer/hooks/usePreviewBridge.ts +5 -5
  150. package/src/viewer/hooks/useUrlState.ts +6 -6
  151. package/src/viewer/index.ts +2 -2
  152. package/src/viewer/intelligence/healthReport.ts +17 -17
  153. package/src/viewer/intelligence/styleDrift.ts +1 -1
  154. package/src/viewer/intelligence/usageScanner.ts +1 -1
  155. package/src/viewer/preview-frame.html +22 -13
  156. package/src/viewer/render-template.html +1 -1
  157. package/src/viewer/render-utils.ts +21 -21
  158. package/src/viewer/server.ts +18 -18
  159. package/src/viewer/styles/globals.css +42 -81
  160. package/src/viewer/utils/detectRelationships.ts +22 -22
  161. package/src/viewer/vite-plugin.ts +213 -213
  162. package/dist/chunk-6JBGU74P.js.map +0 -1
  163. package/dist/chunk-D35RGPAG.js.map +0 -1
  164. package/dist/chunk-F7ITZPDJ.js.map +0 -1
  165. package/dist/chunk-NWQ4CJOQ.js.map +0 -1
  166. package/dist/chunk-Q7GOHVOK.js.map +0 -1
  167. package/dist/chunk-RVRTRESS.js.map +0 -1
  168. package/dist/chunk-SSLQXHNX.js.map +0 -1
  169. package/dist/generate-7AF7WRVK.js.map +0 -1
  170. package/dist/scan-K6JNMCGM.js +0 -12
  171. package/dist/test-CJDNJTPZ.js.map +0 -1
  172. package/dist/viewer-R3Q6WAMJ.js.map +0 -1
  173. package/src/shared/segment-loader.ts +0 -59
  174. /package/dist/{core-SKRPJQZG.js.map → core-SFHPYR5H.js.map} +0 -0
  175. /package/dist/{scan-K6JNMCGM.js.map → scan-KQBKUS64.js.map} +0 -0
  176. /package/dist/{service-F3E4JJM7.js.map → service-ED2LNCTU.js.map} +0 -0
  177. /package/dist/{static-viewer-4LQZ5AGA.js.map → static-viewer-Q4F4QP5M.js.map} +0 -0
  178. /package/dist/{tokens-JAJABYXP.js.map → tokens-P2B7ZAM3.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Metrics Store
3
3
  *
4
4
  * Persists compliance metrics over time for trend analysis.
5
- * Stores snapshots in .segments/metrics/ directory.
5
+ * Stores snapshots in .fragments/metrics/ directory.
6
6
  */
7
7
 
8
8
  import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
@@ -47,7 +47,7 @@ export interface PatchGenerationResult {
47
47
  * Options for patch generation
48
48
  */
49
49
  export interface PatchGenerationOptions {
50
- /** Source file path (if known from segment metadata) */
50
+ /** Source file path (if known from fragment metadata) */
51
51
  sourceFile?: string;
52
52
 
53
53
  /** Style type hint */
package/src/setup.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import pc from 'picocolors';
2
2
  import { BRAND } from './core/index.js';
3
- import { loadConfig, discoverSegmentFiles } from './core/node.js';
4
- import { buildSegments } from './build.js';
3
+ import { loadConfig, discoverFragmentFiles } from './core/node.js';
4
+ import { buildFragments } from './build.js';
5
5
  import {
6
6
  detectStorybookConfig,
7
7
  discoverStoryFiles as discoverStorybookFiles,
8
8
  parseStoryFile,
9
- convertToSegment,
9
+ convertToFragment,
10
10
  } from './migrate/index.js';
11
11
 
12
12
  export interface SetupOptions {
@@ -18,68 +18,68 @@ export interface SetupOptions {
18
18
  }
19
19
 
20
20
  export interface SetupResult {
21
- segmentFilesCreated: number;
22
- segmentsBuilt: number;
21
+ fragmentFilesCreated: number;
22
+ fragmentsBuilt: number;
23
23
  figmaLinked: number;
24
24
  errors: string[];
25
25
  }
26
26
 
27
- interface SegmentInfo {
27
+ interface FragmentInfo {
28
28
  name: string;
29
29
  filePath: string;
30
30
  hasFigma: boolean;
31
31
  }
32
32
 
33
33
  /**
34
- * Check if segments.json exists and is newer than all segment files.
34
+ * Check if fragments.json exists and is newer than all fragment files.
35
35
  */
36
- async function isSegmentsJsonStale(configDir: string, outFile: string): Promise<{ stale: boolean; missing: boolean }> {
36
+ async function isFragmentsJsonStale(configDir: string, outFile: string): Promise<{ stale: boolean; missing: boolean }> {
37
37
  const fs = await import('node:fs/promises');
38
38
  const path = await import('node:path');
39
39
  const fg = await import('fast-glob');
40
40
 
41
- const segmentsJsonPath = path.join(configDir, outFile);
41
+ const fragmentsJsonPath = path.join(configDir, outFile);
42
42
 
43
43
  try {
44
- const segmentsJsonStat = await fs.stat(segmentsJsonPath);
44
+ const fragmentsJsonStat = await fs.stat(fragmentsJsonPath);
45
45
 
46
- // Find all segment files
47
- const segmentFiles = await fg.default(`**/*${BRAND.fileExtension}`, {
46
+ // Find all fragment files
47
+ const fragmentFiles = await fg.default(`**/*${BRAND.fileExtension}`, {
48
48
  cwd: configDir,
49
49
  ignore: ['**/node_modules/**'],
50
50
  absolute: true,
51
51
  });
52
52
 
53
- // Check if any segment file is newer than segments.json
54
- for (const file of segmentFiles) {
53
+ // Check if any fragment file is newer than fragments.json
54
+ for (const file of fragmentFiles) {
55
55
  const stat = await fs.stat(file);
56
- if (stat.mtimeMs > segmentsJsonStat.mtimeMs) {
56
+ if (stat.mtimeMs > fragmentsJsonStat.mtimeMs) {
57
57
  return { stale: true, missing: false };
58
58
  }
59
59
  }
60
60
 
61
61
  return { stale: false, missing: false };
62
62
  } catch {
63
- // segments.json doesn't exist
63
+ // fragments.json doesn't exist
64
64
  return { stale: false, missing: true };
65
65
  }
66
66
  }
67
67
 
68
68
  /**
69
- * Load segment files and check which ones have Figma links.
69
+ * Load fragment files and check which ones have Figma links.
70
70
  */
71
- async function loadSegmentInfo(segmentFiles: Array<{ absolutePath: string; relativePath: string }>): Promise<SegmentInfo[]> {
71
+ async function loadFragmentInfo(fragmentFiles: Array<{ absolutePath: string; relativePath: string }>): Promise<FragmentInfo[]> {
72
72
  const fs = await import('node:fs/promises');
73
- const segments: SegmentInfo[] = [];
73
+ const fragments: FragmentInfo[] = [];
74
74
 
75
- for (const file of segmentFiles) {
75
+ for (const file of fragmentFiles) {
76
76
  try {
77
77
  const content = await fs.readFile(file.absolutePath, 'utf-8');
78
78
  const nameMatch = content.match(/name:\s*['"]([^'"]+)['"]/);
79
79
  const hasFigma = /meta:\s*\{[^}]*figma:\s*['"]https?:/.test(content);
80
80
 
81
81
  if (nameMatch) {
82
- segments.push({
82
+ fragments.push({
83
83
  name: nameMatch[1],
84
84
  filePath: file.absolutePath,
85
85
  hasFigma,
@@ -90,24 +90,24 @@ async function loadSegmentInfo(segmentFiles: Array<{ absolutePath: string; relat
90
90
  }
91
91
  }
92
92
 
93
- return segments;
93
+ return fragments;
94
94
  }
95
95
 
96
96
  /**
97
- * Run auto-setup for segments dev server.
97
+ * Run auto-setup for fragments dev server.
98
98
  *
99
99
  * This function:
100
- * 1. Checks for segment files, imports from Storybook if none found
101
- * 2. Builds segments.json if missing or stale
102
- * 3. Links Figma if configured but no segments are linked
100
+ * 1. Checks for fragment files, imports from Storybook if none found
101
+ * 2. Builds fragments.json if missing or stale
102
+ * 3. Links Figma if configured but no fragments are linked
103
103
  */
104
104
  export async function runSetup(options: SetupOptions = {}): Promise<SetupResult> {
105
105
  const fs = await import('node:fs/promises');
106
106
  const path = await import('node:path');
107
107
 
108
108
  const result: SetupResult = {
109
- segmentFilesCreated: 0,
110
- segmentsBuilt: 0,
109
+ fragmentFilesCreated: 0,
110
+ fragmentsBuilt: 0,
111
111
  figmaLinked: 0,
112
112
  errors: [],
113
113
  };
@@ -120,11 +120,11 @@ export async function runSetup(options: SetupOptions = {}): Promise<SetupResult>
120
120
  // Load config
121
121
  const { config, configDir } = await loadConfig(options.configPath);
122
122
 
123
- // Step 1: Check for segment files
123
+ // Step 1: Check for fragment files
124
124
  log(pc.dim('Checking for fragment files...'));
125
- let segmentFiles = await discoverSegmentFiles(config, configDir);
125
+ let fragmentFiles = await discoverFragmentFiles(config, configDir);
126
126
 
127
- if (segmentFiles.length === 0 && !options.skipStorybook) {
127
+ if (fragmentFiles.length === 0 && !options.skipStorybook) {
128
128
  // No fragment files - check for Storybook
129
129
  log(pc.yellow('\n No fragment files found'));
130
130
 
@@ -141,43 +141,43 @@ export async function runSetup(options: SetupOptions = {}): Promise<SetupResult>
141
141
  for (const storyFile of storyFiles) {
142
142
  try {
143
143
  const parsed = await parseStoryFile(storyFile);
144
- const segmentResult = convertToSegment(parsed);
144
+ const fragmentResult = convertToFragment(parsed);
145
145
 
146
146
  // Create directory and write file
147
- await fs.mkdir(path.dirname(segmentResult.outputFile), { recursive: true });
148
- await fs.writeFile(segmentResult.outputFile, segmentResult.code);
147
+ await fs.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
148
+ await fs.writeFile(fragmentResult.outputFile, fragmentResult.code);
149
149
  converted++;
150
150
  } catch {
151
151
  // Skip files that can't be converted
152
152
  }
153
153
  }
154
154
 
155
- result.segmentFilesCreated = converted;
155
+ result.fragmentFilesCreated = converted;
156
156
  log(pc.green(` Generated ${converted} fragment file(s)`));
157
157
 
158
- // Refresh segment files list
159
- segmentFiles = await discoverSegmentFiles(config, configDir);
158
+ // Refresh fragment files list
159
+ fragmentFiles = await discoverFragmentFiles(config, configDir);
160
160
  }
161
161
  } else {
162
162
  log(pc.dim(' No Storybook config found'));
163
163
  log(pc.dim(` Run ${pc.cyan(`${BRAND.cliCommand} add <ComponentName>`)} to create your first fragment`));
164
164
  }
165
- } else if (segmentFiles.length > 0) {
166
- log(pc.green(` Found ${segmentFiles.length} fragment file(s)`));
165
+ } else if (fragmentFiles.length > 0) {
166
+ log(pc.green(` Found ${fragmentFiles.length} fragment file(s)`));
167
167
  }
168
168
 
169
169
  // Step 2: Build fragments.json if needed
170
- if (segmentFiles.length > 0 && !options.skipBuild) {
170
+ if (fragmentFiles.length > 0 && !options.skipBuild) {
171
171
  const outFile = config.outFile || BRAND.outFile;
172
- const { stale, missing } = await isSegmentsJsonStale(configDir, outFile);
172
+ const { stale, missing } = await isFragmentsJsonStale(configDir, outFile);
173
173
 
174
174
  if (missing || stale) {
175
175
  const reason = missing ? 'Building' : 'Rebuilding';
176
176
  log(pc.dim(`\n${reason} ${BRAND.outFile}...`));
177
177
 
178
178
  try {
179
- const buildResult = await buildSegments(config, configDir);
180
- result.segmentsBuilt = buildResult.segmentCount;
179
+ const buildResult = await buildFragments(config, configDir);
180
+ result.fragmentsBuilt = buildResult.fragmentCount;
181
181
 
182
182
  if (buildResult.errors.length > 0) {
183
183
  for (const err of buildResult.errors) {
@@ -185,7 +185,7 @@ export async function runSetup(options: SetupOptions = {}): Promise<SetupResult>
185
185
  }
186
186
  }
187
187
 
188
- log(pc.green(` Built ${buildResult.segmentCount} fragment(s)`));
188
+ log(pc.green(` Built ${buildResult.fragmentCount} fragment(s)`));
189
189
  } catch (error) {
190
190
  result.errors.push(`Build failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
191
191
  }
@@ -196,16 +196,16 @@ export async function runSetup(options: SetupOptions = {}): Promise<SetupResult>
196
196
 
197
197
  // Step 3: Link Figma if configured
198
198
  if (!options.skipFigma && config.figmaFile && process.env.FIGMA_ACCESS_TOKEN) {
199
- const segments = await loadSegmentInfo(segmentFiles);
200
- const linkedCount = segments.filter((s) => s.hasFigma).length;
199
+ const fragments = await loadFragmentInfo(fragmentFiles);
200
+ const linkedCount = fragments.filter((s) => s.hasFigma).length;
201
201
 
202
- if (linkedCount === 0 && segments.length > 0) {
202
+ if (linkedCount === 0 && fragments.length > 0) {
203
203
  log(pc.dim('\n Figma configured but no fragments linked'));
204
204
  log(pc.dim(` Run ${pc.cyan(`${BRAND.cliCommand} link figma --auto`)} to auto-link components`));
205
205
  // Note: We don't auto-link here because it requires API calls and user may want control
206
206
  // But we inform them about the option
207
207
  } else if (linkedCount > 0) {
208
- log(pc.dim(`\n ${linkedCount}/${segments.length} fragment(s) linked to Figma`));
208
+ log(pc.dim(`\n ${linkedCount}/${fragments.length} fragment(s) linked to Figma`));
209
209
  }
210
210
  } else if (!options.skipFigma && config.figmaFile && !process.env.FIGMA_ACCESS_TOKEN) {
211
211
  log(pc.dim('\n Figma file configured but FIGMA_ACCESS_TOKEN not set'));
@@ -224,12 +224,12 @@ export async function runSetup(options: SetupOptions = {}): Promise<SetupResult>
224
224
  export function printSetupSummary(result: SetupResult): void {
225
225
  console.log();
226
226
 
227
- if (result.segmentFilesCreated > 0) {
228
- console.log(pc.green(` Imported ${result.segmentFilesCreated} segments from Storybook`));
227
+ if (result.fragmentFilesCreated > 0) {
228
+ console.log(pc.green(` Imported ${result.fragmentFilesCreated} fragments from Storybook`));
229
229
  }
230
230
 
231
- if (result.segmentsBuilt > 0) {
232
- console.log(pc.green(` Built ${result.segmentsBuilt} segments`));
231
+ if (result.fragmentsBuilt > 0) {
232
+ console.log(pc.green(` Built ${result.fragmentsBuilt} fragments`));
233
233
  }
234
234
 
235
235
  if (result.errors.length > 0) {
@@ -7,7 +7,7 @@
7
7
 
8
8
  import type {
9
9
  ComplianceResult,
10
- SegmentInfo,
10
+ FragmentInfo,
11
11
  ContextData,
12
12
  ViolationItem,
13
13
  A11yResult,
@@ -52,7 +52,7 @@ export class DevServerClient {
52
52
  const controller = new AbortController();
53
53
  const timeoutId = setTimeout(() => controller.abort(), 5000);
54
54
 
55
- const response = await fetch(`${this.baseUrl}/segments/context?format=json`, {
55
+ const response = await fetch(`${this.baseUrl}/fragments/context?format=json`, {
56
56
  signal: controller.signal,
57
57
  });
58
58
 
@@ -64,15 +64,15 @@ export class DevServerClient {
64
64
  }
65
65
 
66
66
  /**
67
- * Get all segments from the context endpoint
67
+ * Get all fragments from the context endpoint
68
68
  */
69
- async getSegments(): Promise<SegmentInfo[]> {
70
- const response = await this.fetch('/segments/context?format=json');
69
+ async getFragments(): Promise<FragmentInfo[]> {
70
+ const response = await this.fetch('/fragments/context?format=json');
71
71
  const data = await response.json() as {
72
72
  components: Record<string, { category?: string; description?: string; status?: string; figma?: string }>;
73
73
  };
74
74
 
75
- // Transform object to array of SegmentInfo
75
+ // Transform object to array of FragmentInfo
76
76
  const components = data.components || {};
77
77
  return Object.entries(components).map(([name, info]) => ({
78
78
  name,
@@ -87,7 +87,7 @@ export class DevServerClient {
87
87
  * Get compliance data for a component
88
88
  */
89
89
  async getCompliance(request: ComplianceRequest): Promise<ComplianceResult> {
90
- const response = await this.fetch('/segments/compliance', {
90
+ const response = await this.fetch('/fragments/compliance', {
91
91
  method: 'POST',
92
92
  headers: { 'Content-Type': 'application/json' },
93
93
  body: JSON.stringify(request),
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Fragment Loader
3
+ *
4
+ * Utilities for loading fragment data from the dev server or fragments.json
5
+ */
6
+
7
+ import type { FragmentInfo } from './types.js';
8
+ import { DevServerClient, createDevServerClient } from './dev-server-client.js';
9
+
10
+ /**
11
+ * Options for loading fragments
12
+ */
13
+ export interface LoadFragmentsOptions {
14
+ /** Dev server port */
15
+ port?: number | string;
16
+ /** Filter by component name */
17
+ component?: string;
18
+ }
19
+
20
+ /**
21
+ * Load fragments from the dev server
22
+ */
23
+ export async function loadFragments(options: LoadFragmentsOptions = {}): Promise<FragmentInfo[]> {
24
+ const { port = 6006, component } = options;
25
+
26
+ const client = createDevServerClient(port);
27
+ let fragments = await client.getFragments();
28
+
29
+ // Filter by component if specified
30
+ if (component) {
31
+ fragments = fragments.filter(
32
+ s => s.name.toLowerCase() === component.toLowerCase()
33
+ );
34
+ }
35
+
36
+ return fragments;
37
+ }
38
+
39
+ /**
40
+ * Load a single fragment by name
41
+ */
42
+ export async function loadFragment(
43
+ name: string,
44
+ options: { port?: number | string } = {}
45
+ ): Promise<FragmentInfo | null> {
46
+ const fragments = await loadFragments({ ...options, component: name });
47
+ return fragments.length > 0 ? fragments[0] : null;
48
+ }
49
+
50
+ /**
51
+ * Check if a fragment exists
52
+ */
53
+ export async function fragmentExists(
54
+ name: string,
55
+ options: { port?: number | string } = {}
56
+ ): Promise<boolean> {
57
+ const fragment = await loadFragment(name, options);
58
+ return fragment !== null;
59
+ }
@@ -5,4 +5,4 @@
5
5
  export * from './types.js';
6
6
  export * from './dev-server-client.js';
7
7
  export * from './command-wrapper.js';
8
- export * from './segment-loader.js';
8
+ export * from './fragment-loader.js';
@@ -81,9 +81,9 @@ export interface ComplianceResult {
81
81
  }
82
82
 
83
83
  /**
84
- * Segment information from context endpoint
84
+ * Fragment information from context endpoint
85
85
  */
86
- export interface SegmentInfo {
86
+ export interface FragmentInfo {
87
87
  /** Component name */
88
88
  name: string;
89
89
  /** Component category */
@@ -107,11 +107,11 @@ export interface CommandResult {
107
107
  }
108
108
 
109
109
  /**
110
- * Context data from the /segments/context endpoint
110
+ * Context data from the /fragments/context endpoint
111
111
  */
112
112
  export interface ContextData {
113
113
  /** List of components */
114
- components: SegmentInfo[];
114
+ components: FragmentInfo[];
115
115
  }
116
116
 
117
117
  /**
@@ -1,23 +1,23 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
- import type { CompiledSegmentsFile } from "./core/index.js";
3
+ import type { CompiledFragmentsFile } from "./core/index.js";
4
4
  import { BRAND } from "./core/index.js";
5
5
 
6
6
  /**
7
- * Generate a static HTML viewer for the segments.json file.
7
+ * Generate a static HTML viewer for the fragments.json file.
8
8
  * This viewer shows component documentation without needing to render actual components.
9
9
  */
10
- export function generateStaticViewer(data: CompiledSegmentsFile): string {
11
- const segments = Object.values(data.segments);
10
+ export function generateStaticViewer(data: CompiledFragmentsFile): string {
11
+ const fragments = Object.values(data.fragments);
12
12
 
13
13
  // Group by category
14
- const categories = new Map<string, typeof segments>();
15
- for (const segment of segments) {
16
- const category = segment.meta.category ?? "Uncategorized";
14
+ const categories = new Map<string, typeof fragments>();
15
+ for (const fragment of fragments) {
16
+ const category = fragment.meta.category ?? "Uncategorized";
17
17
  if (!categories.has(category)) {
18
18
  categories.set(category, []);
19
19
  }
20
- categories.get(category)!.push(segment);
20
+ categories.get(category)!.push(fragment);
21
21
  }
22
22
 
23
23
  // Sort categories and components
@@ -426,11 +426,11 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
426
426
 
427
427
  <div class="sidebar-stats">
428
428
  <div class="stat">
429
- <div class="stat-value">${segments.length}</div>
429
+ <div class="stat-value">${fragments.length}</div>
430
430
  <div class="stat-label">Components</div>
431
431
  </div>
432
432
  <div class="stat">
433
- <div class="stat-value">${segments.reduce(
433
+ <div class="stat-value">${fragments.reduce(
434
434
  (sum, s) => sum + s.variants.length,
435
435
  0
436
436
  )}</div>
@@ -465,34 +465,34 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
465
465
 
466
466
  <main class="main" id="main">
467
467
  ${
468
- segments.length === 0
468
+ fragments.length === 0
469
469
  ? `
470
470
  <div class="empty-state">
471
471
  <h2>No Components Found</h2>
472
- <p>Run <code>segments build</code> to compile your segment files.</p>
472
+ <p>Run <code>fragments build</code> to compile your fragment files.</p>
473
473
  </div>
474
474
  `
475
- : segments
475
+ : fragments
476
476
  .sort((a, b) => a.meta.name.localeCompare(b.meta.name))
477
477
  .map(
478
- (segment) => `
479
- <section class="component-section" id="${segment.meta.name}">
478
+ (fragment) => `
479
+ <section class="component-section" id="${fragment.meta.name}">
480
480
  <div class="component-header">
481
- <h2 class="component-name">${segment.meta.name}</h2>
482
- <p class="component-description">${segment.meta.description}</p>
481
+ <h2 class="component-name">${fragment.meta.name}</h2>
482
+ <p class="component-description">${fragment.meta.description}</p>
483
483
  <div class="component-meta">
484
484
  ${
485
- segment.meta.status
486
- ? `<span class="meta-badge status-${segment.meta.status}">${segment.meta.status}</span>`
485
+ fragment.meta.status
486
+ ? `<span class="meta-badge status-${fragment.meta.status}">${fragment.meta.status}</span>`
487
487
  : ""
488
488
  }
489
489
  ${
490
- segment.meta.category
491
- ? `<span class="meta-badge">${segment.meta.category}</span>`
490
+ fragment.meta.category
491
+ ? `<span class="meta-badge">${fragment.meta.category}</span>`
492
492
  : ""
493
493
  }
494
494
  ${
495
- segment.meta.tags
495
+ fragment.meta.tags
496
496
  ?.map((tag) => `<span class="meta-badge">${tag}</span>`)
497
497
  .join("") ?? ""
498
498
  }
@@ -500,15 +500,15 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
500
500
  </div>
501
501
 
502
502
  ${
503
- segment.usage
503
+ fragment.usage
504
504
  ? `
505
505
  <div class="section">
506
506
  <h3 class="section-title">Usage Guidelines</h3>
507
507
  ${
508
- segment.usage.when?.length
508
+ fragment.usage.when?.length
509
509
  ? `
510
510
  <ul class="usage-list">
511
- ${segment.usage.when
511
+ ${fragment.usage.when
512
512
  .map((item) => `<li class="usage-item when">${item}</li>`)
513
513
  .join("")}
514
514
  </ul>
@@ -516,10 +516,10 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
516
516
  : ""
517
517
  }
518
518
  ${
519
- segment.usage.whenNot?.length
519
+ fragment.usage.whenNot?.length
520
520
  ? `
521
521
  <ul class="usage-list" style="margin-top: 12px;">
522
- ${segment.usage.whenNot
522
+ ${fragment.usage.whenNot
523
523
  .map(
524
524
  (item) => `<li class="usage-item when-not">${item}</li>`
525
525
  )
@@ -534,7 +534,7 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
534
534
  }
535
535
 
536
536
  ${
537
- segment.props && Object.keys(segment.props).length
537
+ fragment.props && Object.keys(fragment.props).length
538
538
  ? `
539
539
  <div class="section">
540
540
  <h3 class="section-title">Props</h3>
@@ -548,7 +548,7 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
548
548
  </tr>
549
549
  </thead>
550
550
  <tbody>
551
- ${Object.entries(segment.props)
551
+ ${Object.entries(fragment.props)
552
552
  .map(
553
553
  ([name, prop]) => `
554
554
  <tr>
@@ -579,12 +579,12 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
579
579
  }
580
580
 
581
581
  ${
582
- segment.variants?.length
582
+ fragment.variants?.length
583
583
  ? `
584
584
  <div class="section">
585
585
  <h3 class="section-title">Variants</h3>
586
586
  <div class="variants-grid">
587
- ${segment.variants
587
+ ${fragment.variants
588
588
  .map(
589
589
  (variant) => `
590
590
  <div class="variant-card">
@@ -612,12 +612,12 @@ export function generateStaticViewer(data: CompiledSegmentsFile): string {
612
612
  }
613
613
 
614
614
  ${
615
- segment.relations?.length
615
+ fragment.relations?.length
616
616
  ? `
617
617
  <div class="section">
618
618
  <h3 class="section-title">Related Components</h3>
619
619
  <div class="relations-list">
620
- ${segment.relations
620
+ ${fragment.relations
621
621
  .map(
622
622
  (rel) =>
623
623
  `<a href="#${
@@ -704,12 +704,12 @@ function escapeHtml(str: string): string {
704
704
  }
705
705
 
706
706
  /**
707
- * Load segments.json and generate static viewer
707
+ * Load fragments.json and generate static viewer
708
708
  */
709
709
  export async function generateViewerFromJson(
710
710
  jsonPath: string
711
711
  ): Promise<string> {
712
712
  const content = await readFile(jsonPath, "utf-8");
713
- const data = JSON.parse(content) as CompiledSegmentsFile;
713
+ const data = JSON.parse(content) as CompiledFragmentsFile;
714
714
  return generateStaticViewer(data);
715
715
  }
@@ -3,12 +3,12 @@
3
3
  */
4
4
 
5
5
  import { readFile } from 'node:fs/promises';
6
- import type { SegmentsConfig } from '../core/index.js';
7
- import { discoverSegmentFiles, parseSegmentFile } from '../core/node.js';
6
+ import type { FragmentsConfig } from '../core/index.js';
7
+ import { discoverFragmentFiles, parseFragmentFile } from '../core/node.js';
8
8
  import type { TestCase, DiscoveryOptions } from './types.js';
9
9
 
10
10
  /**
11
- * Discovered segment with play function metadata
11
+ * Discovered fragment with play function metadata
12
12
  */
13
13
  interface DiscoveredVariant {
14
14
  component: string;
@@ -23,17 +23,17 @@ interface DiscoveredVariant {
23
23
  * Discover all variants with play functions
24
24
  */
25
25
  export async function discoverTests(
26
- config: SegmentsConfig,
26
+ config: FragmentsConfig,
27
27
  configDir: string,
28
28
  options: DiscoveryOptions = {}
29
29
  ): Promise<TestCase[]> {
30
- const files = await discoverSegmentFiles(config, configDir);
30
+ const files = await discoverFragmentFiles(config, configDir);
31
31
  const variants: DiscoveredVariant[] = [];
32
32
 
33
33
  for (const file of files) {
34
34
  try {
35
35
  const content = await readFile(file.absolutePath, 'utf-8');
36
- const parsed = parseSegmentFile(content, file.relativePath);
36
+ const parsed = parseFragmentFile(content, file.relativePath);
37
37
 
38
38
  if (!parsed.meta.name) continue;
39
39