@fragments-sdk/cli 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +712 -39
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ICAIQ57V.js → chunk-6JBGU74P.js} +5 -3
- package/dist/chunk-6JBGU74P.js.map +1 -0
- package/dist/{chunk-U4GQ2JTD.js → chunk-D35RGPAG.js} +412 -35
- package/dist/chunk-D35RGPAG.js.map +1 -0
- package/dist/{chunk-XNWDI6UT.js → chunk-F7ITZPDJ.js} +5 -5
- package/dist/{chunk-IOJE35DZ.js → chunk-NWQ4CJOQ.js} +3 -3
- package/dist/{chunk-V7YLRR4C.js → chunk-Q7GOHVOK.js} +3 -3
- package/dist/{chunk-2DJH4F4P.js → chunk-RVRTRESS.js} +3 -3
- package/dist/{chunk-2H2JAA3U.js → chunk-SSLQXHNX.js} +3 -3
- package/dist/{core-DKHB7FYV.js → core-SKRPJQZG.js} +4 -4
- package/dist/{generate-KL24VZVD.js → generate-7AF7WRVK.js} +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/{init-NZB55B5O.js → init-WKGDPYI4.js} +7 -7
- package/dist/init-WKGDPYI4.js.map +1 -0
- package/dist/mcp-bin.js +8 -220
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-K6JNMCGM.js +12 -0
- package/dist/{service-RWUMZ3EW.js → service-F3E4JJM7.js} +5 -5
- package/dist/static-viewer-4LQZ5AGA.js +12 -0
- package/dist/{test-ECPEXFDN.js → test-CJDNJTPZ.js} +4 -4
- package/dist/{tokens-ITADYVPF.js → tokens-JAJABYXP.js} +6 -6
- package/dist/viewer-R3Q6WAMJ.js +1822 -0
- package/dist/viewer-R3Q6WAMJ.js.map +1 -0
- package/package.json +5 -4
- package/src/bin.ts +8 -0
- package/src/build.ts +104 -13
- package/src/cli-commands.ts +18 -0
- package/src/commands/__tests__/a11y-scoring.test.ts +278 -0
- package/src/commands/a11y-report.ts +625 -0
- package/src/commands/a11y.ts +168 -14
- package/src/commands/build.ts +16 -0
- package/src/commands/init.ts +2 -2
- package/src/core/auto-props.ts +464 -0
- package/src/core/schema.ts +2 -0
- package/src/core/types.ts +3 -1
- package/src/index.ts +4 -0
- package/src/mcp/server.ts +13 -220
- package/src/theme/__tests__/component-contrast.test.ts +338 -0
- package/src/theme/__tests__/contrast-validation.test.ts +326 -0
- package/src/theme/contrast.test.ts +331 -0
- package/src/theme/contrast.ts +246 -0
- package/src/theme/generator.ts +213 -1
- package/src/theme/index.ts +16 -0
- package/src/theme/types.ts +51 -0
- package/src/viewer/__tests__/a11y-fixes.test.ts +358 -0
- package/src/viewer/__tests__/viewer-integration.test.ts +2 -7
- package/src/viewer/components/AccessibilityPanel.tsx +493 -433
- package/src/viewer/components/ActionCapture.tsx +1 -1
- package/src/viewer/components/ActionsPanel.tsx +142 -183
- package/src/viewer/components/App.tsx +159 -164
- package/src/viewer/components/BottomPanel.tsx +40 -80
- package/src/viewer/components/CodePanel.tsx +9 -87
- package/src/viewer/components/CommandPalette.tsx +117 -74
- package/src/viewer/components/ComponentGraph.tsx +143 -126
- package/src/viewer/components/ComponentHeader.tsx +46 -43
- package/src/viewer/components/ContractPanel.tsx +124 -117
- package/src/viewer/components/ErrorBoundary.tsx +47 -35
- package/src/viewer/components/FigmaEmbed.tsx +18 -13
- package/src/viewer/components/FragmentEditor.tsx +126 -63
- package/src/viewer/components/HealthDashboard.tsx +146 -171
- package/src/viewer/components/HmrStatusIndicator.tsx +31 -41
- package/src/viewer/components/Icons.tsx +99 -98
- package/src/viewer/components/InteractionsPanel.tsx +317 -264
- package/src/viewer/components/IsolatedPreviewFrame.tsx +52 -27
- package/src/viewer/components/IsolatedRender.tsx +12 -6
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +34 -70
- package/src/viewer/components/LandingPage.tsx +285 -305
- package/src/viewer/components/Layout.tsx +7 -9
- package/src/viewer/components/LeftSidebar.tsx +78 -108
- package/src/viewer/components/MultiViewportPreview.tsx +254 -63
- package/src/viewer/components/PreviewArea.tsx +113 -44
- package/src/viewer/components/PreviewFrameHost.tsx +6 -5
- package/src/viewer/components/PreviewPane.tsx +2 -3
- package/src/viewer/components/PreviewToolbar.tsx +61 -104
- package/src/viewer/components/PropsEditor.tsx +154 -74
- package/src/viewer/components/PropsTable.tsx +95 -82
- package/src/viewer/components/RelationsSection.tsx +71 -40
- package/src/viewer/components/ResizablePanel.tsx +158 -55
- package/src/viewer/components/RightSidebar.tsx +46 -56
- package/src/viewer/components/ScreenshotButton.tsx +12 -12
- package/src/viewer/components/SkeletonLoader.tsx +99 -83
- package/src/viewer/components/StoryRenderer.tsx +4 -11
- package/src/viewer/components/Toast.tsx +3 -67
- package/src/viewer/components/TokenStylePanel.tsx +136 -118
- package/src/viewer/components/UsageSection.tsx +26 -26
- package/src/viewer/components/VariantMatrix.tsx +140 -47
- package/src/viewer/components/VariantTabs.tsx +24 -68
- package/src/viewer/components/ViewportSelector.tsx +106 -110
- package/src/viewer/constants/ui.ts +19 -18
- package/src/viewer/entry.tsx +8 -3
- package/src/viewer/index.ts +3 -6
- package/src/viewer/preview-frame.html +21 -5
- package/src/viewer/server.ts +7 -16
- package/src/viewer/styles/globals.css +4 -4
- package/src/viewer/utils/a11y-fixes.ts +53 -30
- package/dist/chunk-ICAIQ57V.js.map +0 -1
- package/dist/chunk-U4GQ2JTD.js.map +0 -1
- package/dist/init-NZB55B5O.js.map +0 -1
- package/dist/scan-ESEXV7LF.js +0 -12
- package/dist/static-viewer-O37MJ5B6.js +0 -12
- package/dist/viewer-YDGFDTK5.js +0 -11104
- package/dist/viewer-YDGFDTK5.js.map +0 -1
- package/src/viewer/postcss.config.js +0 -6
- package/src/viewer/tailwind.config.js +0 -37
- /package/dist/{chunk-XNWDI6UT.js.map → chunk-F7ITZPDJ.js.map} +0 -0
- /package/dist/{chunk-IOJE35DZ.js.map → chunk-NWQ4CJOQ.js.map} +0 -0
- /package/dist/{chunk-V7YLRR4C.js.map → chunk-Q7GOHVOK.js.map} +0 -0
- /package/dist/{chunk-2DJH4F4P.js.map → chunk-RVRTRESS.js.map} +0 -0
- /package/dist/{chunk-2H2JAA3U.js.map → chunk-SSLQXHNX.js.map} +0 -0
- /package/dist/{core-DKHB7FYV.js.map → core-SKRPJQZG.js.map} +0 -0
- /package/dist/{generate-KL24VZVD.js.map → generate-7AF7WRVK.js.map} +0 -0
- /package/dist/{scan-ESEXV7LF.js.map → scan-K6JNMCGM.js.map} +0 -0
- /package/dist/{service-RWUMZ3EW.js.map → service-F3E4JJM7.js.map} +0 -0
- /package/dist/{static-viewer-O37MJ5B6.js.map → static-viewer-4LQZ5AGA.js.map} +0 -0
- /package/dist/{test-ECPEXFDN.js.map → test-CJDNJTPZ.js.map} +0 -0
- /package/dist/{tokens-ITADYVPF.js.map → tokens-JAJABYXP.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/validators.ts","../src/build.ts","../src/screenshot.ts","../src/diff.ts","../src/analyze.ts"],"sourcesContent":["import { segmentDefinitionSchema, BRAND, type SegmentsConfig } from './core/index.js';\nimport {\n discoverSegmentFiles,\n discoverComponentFiles,\n extractComponentName,\n loadSegmentFile,\n type DiscoveredFile,\n} from './core/node.js';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\nexport interface ValidationError {\n file: string;\n message: string;\n details?: string;\n}\n\nexport interface ValidationWarning {\n file: string;\n message: string;\n}\n\n/**\n * Validate segment file schema\n */\nexport async function validateSchema(\n config: SegmentsConfig,\n configDir: string\n): Promise<ValidationResult> {\n const files = await discoverSegmentFiles(config, configDir);\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n for (const file of files) {\n try {\n const segment = await loadSegmentFile(file.absolutePath);\n\n if (!segment) {\n errors.push({\n file: file.relativePath,\n message: 'No default export found',\n details: `Segment files must have a default export from defineSegment()`,\n });\n continue;\n }\n\n const result = segmentDefinitionSchema.safeParse(segment);\n\n if (!result.success) {\n const details = result.error.errors\n .map((e) => `${e.path.join('.')}: ${e.message}`)\n .join('; ');\n\n errors.push({\n file: file.relativePath,\n message: 'Invalid segment schema',\n details,\n });\n }\n } catch (error) {\n errors.push({\n file: file.relativePath,\n message: 'Failed to load segment file',\n details: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validate coverage - ensure all components have segments\n */\nexport async function validateCoverage(\n config: SegmentsConfig,\n configDir: string\n): Promise<ValidationResult> {\n const segmentFiles = await discoverSegmentFiles(config, configDir);\n const componentFiles = await discoverComponentFiles(config, configDir);\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n // Build set of documented component names\n const documentedComponents = new Set<string>();\n\n for (const file of segmentFiles) {\n try {\n const segment = await loadSegmentFile(file.absolutePath);\n\n if (segment?.meta?.name) {\n documentedComponents.add(segment.meta.name);\n }\n } catch {\n // Skip files that fail to load - schema validation will catch these\n }\n }\n\n // Check each component file\n for (const file of componentFiles) {\n const componentName = extractComponentName(file.relativePath);\n\n // Check if there's a corresponding segment file\n const segmentPath = file.relativePath.replace(\n /\\.(tsx?|jsx?)$/,\n BRAND.fileExtension\n );\n const hasSegmentFile = segmentFiles.some(\n (s) => s.relativePath === segmentPath\n );\n\n if (!hasSegmentFile && !documentedComponents.has(componentName)) {\n warnings.push({\n file: file.relativePath,\n message: `Component \"${componentName}\" has no segment documentation`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Run all validations\n */\nexport async function validateAll(\n config: SegmentsConfig,\n configDir: string\n): Promise<ValidationResult> {\n const [schemaResult, coverageResult] = await Promise.all([\n validateSchema(config, configDir),\n validateCoverage(config, configDir),\n ]);\n\n return {\n valid: schemaResult.valid && coverageResult.valid,\n errors: [...schemaResult.errors, ...coverageResult.errors],\n warnings: [...schemaResult.warnings, ...coverageResult.warnings],\n };\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type {\n SegmentsConfig,\n CompiledSegmentsFile,\n CompiledSegment,\n CompiledBlock,\n CompiledTokenData,\n} from \"./core/index.js\";\nimport { BRAND, compileBlock, parseTokenFile } from \"./core/index.js\";\nimport type { BlockDefinition } from \"./core/index.js\";\nimport {\n discoverSegmentFiles,\n discoverBlockFiles,\n discoverTokenFiles,\n parseSegmentFile,\n loadSegmentFile,\n generateRegistry,\n generateContextMd,\n} from \"./core/node.js\";\n\nexport interface BuildResult {\n success: boolean;\n outputPath: string;\n segmentCount: number;\n errors: Array<{ file: string; error: string }>;\n warnings: Array<{ file: string; warning: string }>;\n}\n\n/**\n * Build compiled fragments.json file for AI consumption.\n *\n * Uses AST parsing to extract metadata WITHOUT executing fragment files.\n * This means the build works without any project dependencies installed.\n */\nexport async function buildSegments(\n config: SegmentsConfig,\n configDir: string\n): Promise<BuildResult> {\n const files = await discoverSegmentFiles(config, configDir);\n const errors: Array<{ file: string; error: string }> = [];\n const warnings: Array<{ file: string; warning: string }> = [];\n const segments: CompiledSegmentsFile[\"segments\"] = {};\n\n for (const file of files) {\n try {\n // Read file content as text\n const content = await readFile(file.absolutePath, \"utf-8\");\n\n // Parse using AST (no execution)\n const parsed = parseSegmentFile(content, file.relativePath);\n\n // Collect warnings\n for (const warning of parsed.warnings) {\n warnings.push({ file: file.relativePath, warning });\n }\n\n // Check for required fields\n if (!parsed.meta.name) {\n errors.push({\n file: file.relativePath,\n error: \"Missing meta.name in fragment definition\",\n });\n continue;\n }\n\n // Build compiled fragment from parsed metadata\n const compiled: CompiledSegment = {\n filePath: file.relativePath,\n meta: {\n name: parsed.meta.name,\n description: parsed.meta.description ?? \"\",\n category: parsed.meta.category ?? \"Uncategorized\",\n status: parsed.meta.status,\n tags: parsed.meta.tags,\n since: parsed.meta.since,\n figma: parsed.meta.figma,\n },\n usage: {\n when: parsed.usage.when ?? [],\n whenNot: parsed.usage.whenNot ?? [],\n guidelines: parsed.usage.guidelines,\n accessibility: parsed.usage.accessibility,\n },\n props: Object.fromEntries(\n Object.entries(parsed.props).map(([name, prop]) => [\n name,\n {\n type: prop.type ?? \"custom\",\n description: prop.description ?? \"\",\n default: prop.default,\n required: prop.required,\n values: prop.values,\n constraints: prop.constraints,\n },\n ])\n ),\n relations: parsed.relations.map((rel) => ({\n component: rel.component,\n relationship: rel.relationship as\n | \"alternative\"\n | \"sibling\"\n | \"parent\"\n | \"child\"\n | \"composition\",\n note: rel.note,\n })),\n variants: parsed.variants.map((v) => ({\n name: v.name,\n description: v.description,\n ...(v.code && { code: v.code }),\n ...(v.figma && { figma: v.figma }),\n ...(v.args && { args: v.args }),\n })),\n // Include AI metadata if present\n ...(parsed.ai && { ai: parsed.ai }),\n };\n\n segments[parsed.meta.name] = compiled;\n } catch (error) {\n errors.push({\n file: file.relativePath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Discover and compile block files\n const blocks: Record<string, CompiledBlock> = {};\n try {\n const blockFiles = await discoverBlockFiles(configDir, config.exclude);\n for (const file of blockFiles) {\n try {\n // loadSegmentFile uses esbuild to bundle+evaluate, returns default export\n // CJS/ESM interop may double-wrap the default export\n let raw = await loadSegmentFile(file.absolutePath) as unknown as Record<string, unknown> | null;\n // Unwrap double-default from CJS interop\n if (raw && 'default' in raw && typeof raw.default === 'object') {\n raw = raw.default as Record<string, unknown>;\n }\n const def = raw;\n if (def && typeof def === 'object' && 'name' in def && 'code' in def && 'components' in def) {\n const compiled = compileBlock(def as unknown as BlockDefinition, file.relativePath);\n blocks[compiled.name] = compiled;\n }\n } catch (error) {\n warnings.push({\n file: file.relativePath,\n warning: `Failed to load block: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n } catch {\n // Block discovery failure is non-fatal\n }\n\n // Discover and extract design tokens from SCSS/CSS files\n let tokens: CompiledTokenData | undefined;\n try {\n const tokenPatterns = config.tokens?.include;\n const tokenFiles = await discoverTokenFiles(configDir, tokenPatterns, config.exclude);\n if (tokenFiles.length > 0) {\n // Merge tokens from all discovered files\n const mergedCategories: Record<string, Array<{ name: string; description?: string }>> = {};\n let prefix = '--';\n let total = 0;\n\n for (const file of tokenFiles) {\n const content = await readFile(file.absolutePath, 'utf-8');\n const parsed = parseTokenFile(content, file.relativePath);\n prefix = parsed.prefix; // Use last file's prefix (usually consistent)\n total += parsed.total;\n for (const [cat, catTokens] of Object.entries(parsed.categories)) {\n if (!mergedCategories[cat]) {\n mergedCategories[cat] = [];\n }\n for (const t of catTokens) {\n // Deduplicate by name\n if (!mergedCategories[cat].some((e) => e.name === t.name)) {\n mergedCategories[cat].push({ name: t.name, description: t.description });\n }\n }\n }\n }\n\n if (total > 0) {\n tokens = { prefix, total, categories: mergedCategories };\n }\n }\n } catch {\n // Token extraction failure is non-fatal\n }\n\n // Read package name for import statements\n let packageName: string | undefined;\n const pkgJsonPath = resolve(configDir, \"package.json\");\n if (existsSync(pkgJsonPath)) {\n try {\n const pkg = JSON.parse(await readFile(pkgJsonPath, \"utf-8\"));\n if (pkg.name) packageName = pkg.name;\n } catch {\n // Non-fatal\n }\n }\n\n const output: CompiledSegmentsFile = {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n ...(packageName && { packageName }),\n segments,\n ...(Object.keys(blocks).length > 0 && { blocks }),\n ...(tokens && { tokens }),\n };\n\n const outputPath = resolve(configDir, config.outFile ?? BRAND.outFile);\n await writeFile(outputPath, JSON.stringify(output));\n\n return {\n success: errors.length === 0,\n outputPath,\n segmentCount: Object.keys(segments).length,\n errors,\n warnings,\n };\n}\n\n/**\n * Result of building the .fragments directory\n */\nexport interface FragmentsBuildResult {\n success: boolean;\n indexPath: string;\n registryPath: string;\n contextPath: string;\n componentCount: number;\n errors: Array<{ file: string; error: string }>;\n warnings: Array<{ file: string; warning: string }>;\n}\n\n/**\n * Build the .fragments/ directory with index.json, registry.json, and context.md\n *\n * This generates:\n * - .fragments/index.json - Minimal name → path mapping (tiny, for quick lookups)\n * - .fragments/registry.json - Component index with paths and enrichment references\n * - .fragments/context.md - AI-ready consolidated context file\n */\nexport async function buildFragmentsDir(\n config: SegmentsConfig,\n configDir: string\n): Promise<FragmentsBuildResult> {\n const fragmentsDir = join(configDir, BRAND.dataDir);\n const componentsDir = join(fragmentsDir, BRAND.componentsDir);\n\n // Create directories\n await mkdir(fragmentsDir, { recursive: true });\n await mkdir(componentsDir, { recursive: true });\n\n // Generate registry with config options\n const registryResult = await generateRegistry({\n projectRoot: configDir,\n componentPatterns: config.components || [\"src/**/*.tsx\", \"src/**/*.ts\"],\n storyPatterns: config.include || [\"src/**/*.stories.tsx\"],\n fragmentsDir,\n registryOptions: config.registry || {},\n });\n\n const errors = [...registryResult.errors];\n const warnings = [...registryResult.warnings];\n\n // Write index.json (minimal name → path)\n const indexPath = join(fragmentsDir, \"index.json\");\n await writeFile(indexPath, JSON.stringify(registryResult.index, null, 2));\n\n // Write registry.json (full metadata)\n const registryPath = join(fragmentsDir, BRAND.registryFile);\n await writeFile(registryPath, JSON.stringify(registryResult.registry, null, 2));\n\n // Generate context.md - focus on semantic knowledge, skip props (AI can read source)\n const contextResult = generateContextMd(registryResult.registry, {\n format: \"markdown\",\n compact: false,\n include: {\n props: false, // AI can read TypeScript directly\n relations: true,\n code: false,\n },\n });\n\n // Write context.md\n const contextPath = join(fragmentsDir, BRAND.contextFile);\n await writeFile(contextPath, contextResult.content);\n\n return {\n success: errors.length === 0,\n indexPath,\n registryPath,\n contextPath,\n componentCount: registryResult.registry.componentCount,\n errors,\n warnings,\n };\n}\n","import pc from 'picocolors';\nimport {\n BRAND,\n DEFAULTS,\n type SegmentsConfig,\n type SegmentDefinition,\n type Theme,\n} from './core/index.js';\nimport { discoverSegmentFiles, loadSegmentFile } from './core/node.js';\nimport {\n BrowserPool,\n CaptureEngine,\n StorageManager,\n formatMs,\n type CaptureOptions,\n} from './service/index.js';\n\n/**\n * Options for the screenshot command\n */\nexport interface ScreenshotCommandOptions {\n /** Specific component to capture */\n component?: string;\n\n /** Specific variant to capture */\n variant?: string;\n\n /** Theme to capture */\n theme?: Theme;\n\n /** Update existing baselines */\n update?: boolean;\n\n /** CI mode - no interactive prompts */\n ci?: boolean;\n\n /** Viewport width */\n width?: number;\n\n /** Viewport height */\n height?: number;\n}\n\n/**\n * Result of the screenshot command\n */\nexport interface ScreenshotResult {\n success: boolean;\n captured: number;\n skipped: number;\n errors: Array<{ component: string; variant: string; error: string }>;\n totalTimeMs: number;\n}\n\n/**\n * Execute the screenshot command\n */\nexport async function runScreenshotCommand(\n config: SegmentsConfig,\n configDir: string,\n options: ScreenshotCommandOptions = {}\n): Promise<ScreenshotResult> {\n const startTime = Date.now();\n const errors: ScreenshotResult['errors'] = [];\n\n // Initialize storage\n const storage = new StorageManager({\n projectRoot: configDir,\n viewport: options.width && options.height\n ? { width: options.width, height: options.height }\n : config.screenshots?.viewport,\n });\n await storage.initialize();\n\n // Discover segments\n const segmentFiles = await discoverSegmentFiles(config, configDir);\n\n if (segmentFiles.length === 0) {\n console.log(pc.yellow('No segment files found.'));\n return {\n success: true,\n captured: 0,\n skipped: 0,\n errors: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Load all segments\n const segments: Array<{ path: string; segment: SegmentDefinition }> = [];\n\n for (const file of segmentFiles) {\n try {\n const segment = await loadSegmentFile(file.absolutePath);\n if (segment) {\n segments.push({ path: file.relativePath, segment });\n }\n } catch (error) {\n errors.push({\n component: file.relativePath,\n variant: '',\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Filter by component if specified\n const filteredSegments = options.component\n ? segments.filter((s) => s.segment.meta.name === options.component)\n : segments;\n\n if (options.component && filteredSegments.length === 0) {\n console.log(pc.yellow(`Component \"${options.component}\" not found.`));\n return {\n success: false,\n captured: 0,\n skipped: 0,\n errors: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Build list of variants to capture\n const variantsToCapture: Array<{\n component: string;\n variant: string;\n render: () => unknown;\n }> = [];\n\n for (const { segment } of filteredSegments) {\n const variants = options.variant\n ? segment.variants.filter((v) => v.name === options.variant)\n : segment.variants;\n\n for (const variant of variants) {\n variantsToCapture.push({\n component: segment.meta.name,\n variant: variant.name,\n render: variant.render,\n });\n }\n }\n\n if (variantsToCapture.length === 0) {\n console.log(pc.yellow('No variants to capture.'));\n return {\n success: true,\n captured: 0,\n skipped: 0,\n errors: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Determine theme\n const theme: Theme = options.theme ?? DEFAULTS.theme;\n const viewport = {\n width: options.width ?? config.screenshots?.viewport?.width ?? DEFAULTS.viewport.width,\n height: options.height ?? config.screenshots?.viewport?.height ?? DEFAULTS.viewport.height,\n };\n\n console.log(pc.cyan(`\\n${BRAND.name} Screenshot\\n`));\n console.log(pc.dim(`Capturing variants (theme: ${theme}, viewport: ${viewport.width}x${viewport.height}):\\n`));\n\n // Initialize browser pool\n const pool = new BrowserPool({\n viewport,\n });\n\n // Create capture engine - use the viewer URL\n const viewerPort = DEFAULTS.port;\n const baseUrl = `http://localhost:${viewerPort}`;\n const captureEngine = new CaptureEngine(pool, baseUrl);\n\n let captured = 0;\n let skipped = 0;\n\n const captureOptions: CaptureOptions = {\n theme,\n viewport,\n delay: config.screenshots?.delay ?? DEFAULTS.captureDelayMs,\n };\n\n try {\n // Warm up the pool\n console.log(pc.dim('Starting browser...'));\n await pool.warmup();\n console.log(pc.dim('Browser ready.\\n'));\n\n // Capture each variant\n for (const { component, variant } of variantsToCapture) {\n const hasExisting = storage.hasBaseline(component, variant, theme);\n\n // Skip if exists and not updating\n if (hasExisting && !options.update) {\n console.log(` ${pc.dim('○')} ${component}/${variant} ${pc.dim('(skipped)')}`);\n skipped++;\n continue;\n }\n\n try {\n const screenshot = await captureEngine.captureVariant(\n component,\n variant,\n captureOptions\n );\n\n await storage.saveBaseline(screenshot);\n\n const totalTime = screenshot.metadata.renderTimeMs + screenshot.metadata.captureTimeMs;\n console.log(\n ` ${pc.green('✓')} ${component}/${variant} ${pc.dim(formatMs(totalTime))}`\n );\n captured++;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.log(` ${pc.red('✗')} ${component}/${variant} ${pc.dim(errorMsg)}`);\n errors.push({ component, variant, error: errorMsg });\n }\n }\n } finally {\n // Shutdown browser pool\n await pool.shutdown();\n }\n\n const totalTimeMs = Date.now() - startTime;\n\n // Print summary\n console.log();\n if (errors.length === 0) {\n console.log(pc.green(`✓ Captured ${captured} screenshot(s) in ${formatMs(totalTimeMs)}`));\n } else {\n console.log(pc.yellow(`⚠ Captured ${captured} screenshot(s) with ${errors.length} error(s)`));\n }\n\n if (skipped > 0) {\n console.log(pc.dim(` ${skipped} skipped (use --update to recapture)`));\n }\n\n console.log(pc.dim(` Stored in ${storage.screenshotsDirPath}\\n`));\n\n return {\n success: errors.length === 0,\n captured,\n skipped,\n errors,\n totalTimeMs,\n };\n}\n","import pc from 'picocolors';\nimport {\n BRAND,\n DEFAULTS,\n type SegmentsConfig,\n type SegmentDefinition,\n type Theme,\n} from './core/index.js';\nimport { discoverSegmentFiles, loadSegmentFile } from './core/node.js';\nimport {\n BrowserPool,\n CaptureEngine,\n StorageManager,\n DiffEngine,\n formatMs,\n type CaptureOptions,\n type DiffResult,\n} from './service/index.js';\n\n/**\n * Options for the diff command\n */\nexport interface DiffCommandOptions {\n /** Specific component to diff */\n component?: string;\n\n /** Specific variant to diff */\n variant?: string;\n\n /** Theme to compare */\n theme?: Theme;\n\n /** CI mode - exit 1 on differences */\n ci?: boolean;\n\n /** Diff threshold percentage */\n threshold?: number;\n\n /** Open diff images */\n open?: boolean;\n}\n\n/**\n * Single diff result with metadata\n */\nexport interface VariantDiffResult {\n component: string;\n variant: string;\n theme: Theme;\n result: DiffResult;\n diffImagePath?: string;\n}\n\n/**\n * Result of the diff command\n */\nexport interface DiffCommandResult {\n success: boolean;\n total: number;\n passed: number;\n failed: number;\n missing: number;\n results: VariantDiffResult[];\n totalTimeMs: number;\n}\n\n/**\n * Execute the diff command\n */\nexport async function runDiffCommand(\n config: SegmentsConfig,\n configDir: string,\n options: DiffCommandOptions = {}\n): Promise<DiffCommandResult> {\n const startTime = Date.now();\n const results: VariantDiffResult[] = [];\n\n // Initialize storage\n const storage = new StorageManager({\n projectRoot: configDir,\n viewport: config.screenshots?.viewport,\n });\n await storage.initialize();\n\n // Initialize diff engine\n const threshold = options.threshold ?? config.screenshots?.threshold ?? DEFAULTS.diffThreshold;\n const diffEngine = new DiffEngine(threshold);\n\n // Discover segments\n const segmentFiles = await discoverSegmentFiles(config, configDir);\n\n if (segmentFiles.length === 0) {\n console.log(pc.yellow('No segment files found.'));\n return {\n success: true,\n total: 0,\n passed: 0,\n failed: 0,\n missing: 0,\n results: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Load all segments\n const segments: Array<{ path: string; segment: SegmentDefinition }> = [];\n\n for (const file of segmentFiles) {\n try {\n const segment = await loadSegmentFile(file.absolutePath);\n if (segment) {\n segments.push({ path: file.relativePath, segment });\n }\n } catch {\n // Skip failed loads\n }\n }\n\n // Filter by component if specified\n const filteredSegments = options.component\n ? segments.filter((s) => s.segment.meta.name === options.component)\n : segments;\n\n if (options.component && filteredSegments.length === 0) {\n console.log(pc.yellow(`Component \"${options.component}\" not found.`));\n return {\n success: false,\n total: 0,\n passed: 0,\n failed: 0,\n missing: 0,\n results: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Build list of variants to diff\n const variantsToDiff: Array<{\n component: string;\n variant: string;\n }> = [];\n\n for (const { segment } of filteredSegments) {\n const variants = options.variant\n ? segment.variants.filter((v) => v.name === options.variant)\n : segment.variants;\n\n for (const variant of variants) {\n variantsToDiff.push({\n component: segment.meta.name,\n variant: variant.name,\n });\n }\n }\n\n if (variantsToDiff.length === 0) {\n console.log(pc.yellow('No variants to compare.'));\n return {\n success: true,\n total: 0,\n passed: 0,\n failed: 0,\n missing: 0,\n results: [],\n totalTimeMs: Date.now() - startTime,\n };\n }\n\n // Determine theme\n const theme: Theme = options.theme ?? DEFAULTS.theme;\n const viewport = config.screenshots?.viewport ?? DEFAULTS.viewport;\n\n console.log(pc.cyan(`\\n${BRAND.name} Diff\\n`));\n console.log(pc.dim(`Comparing against baselines (theme: ${theme}, threshold: ${threshold}%):\\n`));\n\n // Initialize browser pool\n const pool = new BrowserPool({\n viewport,\n });\n\n // Create capture engine\n const viewerPort = DEFAULTS.port;\n const baseUrl = `http://localhost:${viewerPort}`;\n const captureEngine = new CaptureEngine(pool, baseUrl);\n\n let passed = 0;\n let failed = 0;\n let missing = 0;\n\n const captureOptions: CaptureOptions = {\n theme,\n viewport,\n delay: config.screenshots?.delay ?? DEFAULTS.captureDelayMs,\n };\n\n try {\n // Warm up the pool\n await pool.warmup();\n\n // Compare each variant\n for (const { component, variant } of variantsToDiff) {\n // Load baseline\n const baseline = await storage.loadBaseline(component, variant, theme);\n\n if (!baseline) {\n console.log(\n ` ${pc.yellow('?')} ${component}/${variant} ${pc.dim('(no baseline)')}`\n );\n missing++;\n continue;\n }\n\n try {\n // Capture current\n const current = await captureEngine.captureVariant(\n component,\n variant,\n captureOptions\n );\n\n // Quick hash check\n if (diffEngine.areIdentical(current, baseline)) {\n console.log(` ${pc.green('✓')} ${component}/${variant} ${pc.dim('0.0%')}`);\n results.push({\n component,\n variant,\n theme,\n result: {\n matches: true,\n diffPercentage: 0,\n diffPixelCount: 0,\n totalPixels: current.viewport.width * current.viewport.height,\n changedRegions: [],\n diffTimeMs: 0,\n },\n });\n passed++;\n continue;\n }\n\n // Full diff\n const diffResult = diffEngine.compare(current, baseline, { threshold });\n\n if (diffResult.matches) {\n console.log(\n ` ${pc.green('✓')} ${component}/${variant} ${pc.dim(`${diffResult.diffPercentage}%`)}`\n );\n passed++;\n } else {\n // Save diff image\n let diffImagePath: string | undefined;\n if (diffResult.diffImage) {\n diffImagePath = await storage.saveDiff(\n component,\n variant,\n theme,\n diffResult.diffImage\n );\n }\n\n console.log(\n ` ${pc.red('✗')} ${component}/${variant} ${pc.yellow(`${diffResult.diffPercentage}%`)}` +\n (diffImagePath ? pc.dim(` → ${diffImagePath}`) : '')\n );\n failed++;\n\n results.push({\n component,\n variant,\n theme,\n result: diffResult,\n diffImagePath,\n });\n continue;\n }\n\n results.push({\n component,\n variant,\n theme,\n result: diffResult,\n });\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.log(` ${pc.red('!')} ${component}/${variant} ${pc.dim(errorMsg)}`);\n failed++;\n }\n }\n } finally {\n // Shutdown browser pool\n await pool.shutdown();\n }\n\n const totalTimeMs = Date.now() - startTime;\n const total = passed + failed + missing;\n\n // Print summary\n console.log();\n if (failed === 0 && missing === 0) {\n console.log(pc.green(`✓ All ${passed} variant(s) match baselines`));\n } else if (failed > 0) {\n console.log(pc.red(`✗ ${failed} variant(s) differ from baselines`));\n }\n\n if (missing > 0) {\n console.log(pc.yellow(` ${missing} variant(s) have no baseline (run \\`${BRAND.cliCommand} screenshot\\`)`));\n }\n\n console.log(pc.dim(` Completed in ${formatMs(totalTimeMs)}\\n`));\n\n // In CI mode, exit with error if any failed\n const success = failed === 0;\n\n return {\n success,\n total,\n passed,\n failed,\n missing,\n results,\n totalTimeMs,\n };\n}\n","/**\n * CLI command: segments analyze\n *\n * Analyzes the design system and generates an HTML report with:\n * - Component inventory\n * - Documentation coverage\n * - Quality insights\n * - Actionable recommendations\n */\n\nimport { existsSync } from \"node:fs\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport pc from \"picocolors\";\nimport type { SegmentsConfig, CompiledSegmentsFile } from \"./core/index.js\";\nimport { BRAND, DEFAULTS } from \"./core/index.js\";\nimport {\n analyzeDesignSystem,\n generateHtmlReport,\n getGrade,\n getScoreColor,\n type DesignSystemAnalytics,\n} from \"./service/index.js\";\n\nexport interface AnalyzeOptions {\n /** Output format */\n format?: \"html\" | \"json\" | \"console\";\n /** Output file path (default: segments-report.html) */\n output?: string;\n /** Open report in browser after generation */\n open?: boolean;\n /** CI mode - exit with appropriate code */\n ci?: boolean;\n /** Minimum score to pass in CI mode */\n minScore?: number;\n}\n\nexport interface AnalyzeResult {\n success: boolean;\n analytics: DesignSystemAnalytics;\n outputPath?: string;\n}\n\n/**\n * Run the analyze command\n */\nexport async function runAnalyzeCommand(\n config: SegmentsConfig,\n configDir: string,\n options: AnalyzeOptions = {}\n): Promise<AnalyzeResult> {\n const format = options.format ?? \"html\";\n const minScore = options.minScore ?? 0;\n\n console.log(pc.cyan(`\\n${BRAND.name} Analyzer\\n`));\n\n // Load compiled segments\n const segmentsPath = join(configDir, config.outFile ?? \"segments.json\");\n\n if (!existsSync(segmentsPath)) {\n console.log(pc.red(`✗ No segments.json found. Run \\`${BRAND.cliCommand} build\\` first.\\n`));\n return {\n success: false,\n analytics: createEmptyAnalytics(),\n };\n }\n\n console.log(pc.dim(\"Analyzing design system...\\n\"));\n\n const content = await readFile(segmentsPath, \"utf-8\");\n const data: CompiledSegmentsFile = JSON.parse(content);\n\n // Run analysis\n const analytics = analyzeDesignSystem(data);\n\n // Print summary to console\n printConsoleSummary(analytics);\n\n // Generate output based on format\n let outputPath: string | undefined;\n\n if (format === \"html\" || format === \"json\") {\n outputPath = options.output ?? getDefaultOutputPath(format, configDir);\n\n // Ensure output directory exists\n await mkdir(dirname(outputPath), { recursive: true });\n\n if (format === \"html\") {\n const html = generateHtmlReport(analytics);\n await writeFile(outputPath, html);\n console.log(pc.green(`✓ Report generated: ${outputPath}\\n`));\n } else {\n await writeFile(outputPath, JSON.stringify(analytics, null, 2));\n console.log(pc.green(`✓ JSON report generated: ${outputPath}\\n`));\n }\n\n // Open in browser if requested\n if (options.open && format === \"html\") {\n await openInBrowser(outputPath);\n }\n }\n\n // CI mode - check score\n const passedCi = analytics.summary.overallScore >= minScore;\n\n if (options.ci) {\n if (passedCi) {\n console.log(\n pc.green(`✓ Score ${analytics.summary.overallScore} meets minimum threshold ${minScore}\\n`)\n );\n } else {\n console.log(\n pc.red(\n `✗ Score ${analytics.summary.overallScore} below minimum threshold ${minScore}\\n`\n )\n );\n }\n }\n\n return {\n success: !options.ci || passedCi,\n analytics,\n outputPath,\n };\n}\n\n/**\n * Print a summary to the console\n */\nfunction printConsoleSummary(analytics: DesignSystemAnalytics): void {\n const { summary, coverage, recommendations } = analytics;\n const grade = getGrade(summary.overallScore);\n\n // Score header\n console.log(\n pc.bold(\n `Overall Score: ${colorizeScore(summary.overallScore)} (${grade})\\n`\n )\n );\n\n // Summary stats\n console.log(pc.dim(\"Summary\"));\n console.log(` Components: ${pc.white(summary.totalComponents.toString())}`);\n console.log(` Variants: ${pc.white(summary.totalVariants.toString())}`);\n console.log(` Props: ${pc.white(summary.totalProps.toString())}`);\n console.log(` Categories: ${pc.white(summary.categories.join(\", \"))}`);\n console.log();\n\n // Coverage\n console.log(pc.dim(\"Coverage\"));\n console.log(` Description: ${formatCoverage(coverage.fields.description)}`);\n console.log(` Usage when: ${formatCoverage(coverage.fields.usageWhen)}`);\n console.log(` Usage whenNot:${formatCoverage(coverage.fields.usageWhenNot)}`);\n console.log(` Guidelines: ${formatCoverage(coverage.fields.guidelines)}`);\n console.log(` Relations: ${formatCoverage(coverage.fields.relations)}`);\n console.log();\n\n // Top recommendations\n if (recommendations.length > 0) {\n console.log(pc.dim(\"Top Recommendations\"));\n for (const rec of recommendations.slice(0, 3)) {\n const priority = rec.priority === \"high\"\n ? pc.red(`[${rec.priority}]`)\n : rec.priority === \"medium\"\n ? pc.yellow(`[${rec.priority}]`)\n : pc.dim(`[${rec.priority}]`);\n console.log(` ${priority} ${rec.title}`);\n }\n console.log();\n }\n}\n\n/**\n * Format coverage percentage with color\n */\nfunction formatCoverage(field: { percentage: number; covered: number; total: number }): string {\n const pct = colorizeScore(field.percentage);\n return `${pct} (${field.covered}/${field.total})`;\n}\n\n/**\n * Colorize a score\n */\nfunction colorizeScore(score: number): string {\n if (score >= 80) return pc.green(`${score}%`);\n if (score >= 60) return pc.yellow(`${score}%`);\n return pc.red(`${score}%`);\n}\n\n/**\n * Get default output path\n */\nfunction getDefaultOutputPath(format: \"html\" | \"json\", configDir: string): string {\n const filename = format === \"html\" ? \"segments-report.html\" : \"segments-report.json\";\n return join(configDir, filename);\n}\n\n/**\n * Open file in default browser\n */\nasync function openInBrowser(path: string): Promise<void> {\n const { platform } = await import(\"node:os\");\n const { exec } = await import(\"node:child_process\");\n\n const os = platform();\n const cmd = os === \"darwin\"\n ? `open \"${path}\"`\n : os === \"win32\"\n ? `start \"\" \"${path}\"`\n : `xdg-open \"${path}\"`;\n\n exec(cmd);\n}\n\n/**\n * Create empty analytics for error cases\n */\nfunction createEmptyAnalytics(): DesignSystemAnalytics {\n return {\n analyzedAt: new Date(),\n summary: {\n totalComponents: 0,\n totalVariants: 0,\n totalProps: 0,\n categories: [],\n overallScore: 0,\n },\n inventory: {\n byCategory: {},\n byStatus: {},\n byVariantCount: [],\n byPropCount: [],\n },\n coverage: {\n overall: 0,\n fields: {\n description: { covered: 0, total: 0, percentage: 0 },\n usageWhen: { covered: 0, total: 0, percentage: 0 },\n usageWhenNot: { covered: 0, total: 0, percentage: 0 },\n guidelines: { covered: 0, total: 0, percentage: 0 },\n accessibility: { covered: 0, total: 0, percentage: 0 },\n relations: { covered: 0, total: 0, percentage: 0 },\n propDescriptions: { covered: 0, total: 0, percentage: 0 },\n propConstraints: { covered: 0, total: 0, percentage: 0 },\n },\n incomplete: [],\n },\n quality: {\n missingWhenNot: [],\n isolated: [],\n deprecated: [],\n fewVariants: [],\n undocumentedProps: [],\n unconstrainedProps: [],\n },\n distribution: {\n variantsPerComponent: [],\n propsPerComponent: [],\n componentsPerCategory: [],\n statusDistribution: [],\n tagFrequency: [],\n },\n recommendations: [],\n };\n}\n"],"mappings":"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","names":["pc","pc","existsSync","readFile","writeFile","mkdir","join","pc","pc","join","existsSync","readFile","mkdir","writeFile"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["/**\n * fragments init - Smart interactive initialization\n *\n * Handles three scenarios:\n * 1. Stories found → Configure and load existing stories\n * 2. Components found (no stories) → Auto-generate documentation\n * 3. Fresh project → Guided setup with example component\n */\n\nimport { readFile, writeFile, mkdir, access } from \"node:fs/promises\";\nimport { resolve, join, relative } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport pc from \"picocolors\";\nimport { BRAND } from \"../core/index.js\";\nimport fg from \"fast-glob\";\nimport { input, confirm, select } from \"@inquirer/prompts\";\n\nexport interface InitOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Force overwrite existing config */\n force?: boolean;\n /** Non-interactive mode - auto-detect and use defaults */\n yes?: boolean;\n}\n\nexport interface InitResult {\n success: boolean;\n configPath?: string;\n scenario: \"stories\" | \"components\" | \"fresh\";\n storiesFound: number;\n componentsFound: number;\n errors: string[];\n}\n\ninterface DetectionResult {\n storyFiles: string[];\n componentFiles: string[];\n hasConfig: boolean;\n configPath: string | null;\n suggestedComponentPath: string;\n}\n\n/**\n * Detect what exists in the project\n */\nasync function detectProject(projectRoot: string): Promise<DetectionResult> {\n console.log(pc.dim(\"\\nScanning project...\\n\"));\n\n // Check for existing config\n const configPath = join(projectRoot, BRAND.configFile);\n const legacyConfigPath = join(projectRoot, BRAND.legacyConfigFile);\n let hasConfig = false;\n let foundConfigPath: string | null = null;\n\n try {\n await access(configPath);\n hasConfig = true;\n foundConfigPath = configPath;\n } catch {\n try {\n await access(legacyConfigPath);\n hasConfig = true;\n foundConfigPath = legacyConfigPath;\n } catch {\n // No config\n }\n }\n\n // Scan for story files\n const storyFiles = await fg(\n [\"**/*.stories.tsx\", \"**/*.stories.ts\", \"**/*.stories.jsx\", \"**/*.stories.js\"],\n {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.storybook/**\"],\n }\n );\n\n // Scan for component files (React components)\n const componentFiles = await fg(\n [\"**/components/**/*.tsx\", \"**/Components/**/*.tsx\", \"src/**/*.tsx\"],\n {\n cwd: projectRoot,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.stories.*\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*.d.ts\",\n \"**/index.tsx\", // Skip barrel files\n ],\n }\n );\n\n // Filter to likely component files (capitalized names, not utility files)\n const likelyComponents = componentFiles.filter((f) => {\n const fileName = f.split(\"/\").pop() || \"\";\n return /^[A-Z]/.test(fileName) && !fileName.includes(\".styles\");\n });\n\n // Suggest component path based on what we found\n let suggestedComponentPath = \"src/components\";\n if (likelyComponents.length > 0) {\n const firstComponent = likelyComponents[0];\n const parts = firstComponent.split(\"/\");\n const componentsIndex = parts.findIndex(\n (p) => p.toLowerCase() === \"components\"\n );\n if (componentsIndex !== -1) {\n suggestedComponentPath = parts.slice(0, componentsIndex + 1).join(\"/\");\n }\n }\n\n return {\n storyFiles,\n componentFiles: likelyComponents,\n hasConfig,\n configPath: foundConfigPath,\n suggestedComponentPath,\n };\n}\n\n/**\n * Generate config file content\n */\nfunction generateConfig(options: {\n includePaths: string[];\n componentPaths: string[];\n framework: string;\n}): string {\n const includeStr = options.includePaths.map((p) => ` '${p}'`).join(\",\\n\");\n const componentStr = options.componentPaths.map((p) => ` '${p}'`).join(\",\\n\");\n\n return `import type { FragmentsConfig } from '@fragments/core';\n\nconst config: FragmentsConfig = {\n // Glob patterns for finding fragment/story files\n include: [\n${includeStr}\n ],\n\n // Glob patterns to exclude\n exclude: ['**/node_modules/**'],\n\n // Glob patterns for finding component files (for auto-documentation)\n components: [\n${componentStr}\n ],\n\n // Framework (react, vue, svelte)\n framework: '${options.framework}',\n};\n\nexport default config;\n`;\n}\n\n/**\n * Generate example Button component\n */\nfunction generateExampleComponent(): string {\n return `import React from 'react';\n\nexport interface ButtonProps {\n /** Button label */\n children: React.ReactNode;\n /** Visual style variant */\n variant?: 'primary' | 'secondary' | 'ghost';\n /** Button size */\n size?: 'sm' | 'md' | 'lg';\n /** Disabled state */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport function Button({\n children,\n variant = 'primary',\n size = 'md',\n disabled = false,\n onClick,\n}: ButtonProps) {\n const baseStyles = 'inline-flex items-center justify-center font-medium rounded-md transition-colors';\n\n const variantStyles = {\n primary: 'bg-blue-600 text-white hover:bg-blue-700',\n secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',\n ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',\n };\n\n const sizeStyles = {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n };\n\n return (\n <button\n className={\\`\\${baseStyles} \\${variantStyles[variant]} \\${sizeStyles[size]}\\`}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n`;\n}\n\n/**\n * Generate example Button fragment file\n */\nfunction generateExampleFragment(): string {\n return `import React from 'react';\nimport { defineFragment } from '@fragments/core';\nimport { Button } from './Button';\n\nexport default defineFragment({\n component: Button,\n\n meta: {\n name: 'Button',\n description: 'Interactive button for triggering actions',\n category: 'Actions',\n status: 'stable',\n },\n\n usage: {\n when: [\n 'Triggering an action (save, submit, delete)',\n 'Form submission',\n 'Opening dialogs or menus',\n ],\n whenNot: [\n 'Simple navigation (use Link)',\n 'Toggling state (use Switch)',\n ],\n guidelines: [\n 'Use Primary for the main action in a context',\n 'Only one Primary button per section',\n ],\n },\n\n props: {\n children: {\n type: 'node',\n required: true,\n description: 'Button label content',\n },\n variant: {\n type: 'enum',\n values: ['primary', 'secondary', 'ghost'],\n default: 'primary',\n description: 'Visual style variant',\n },\n size: {\n type: 'enum',\n values: ['sm', 'md', 'lg'],\n default: 'md',\n description: 'Button size',\n },\n },\n\n variants: [\n {\n name: 'Primary',\n description: 'Default action button',\n render: () => <Button variant=\"primary\">Save Changes</Button>,\n },\n {\n name: 'Secondary',\n description: 'Less prominent action',\n render: () => <Button variant=\"secondary\">Cancel</Button>,\n },\n {\n name: 'Ghost',\n description: 'Minimal visual weight',\n render: () => <Button variant=\"ghost\">Learn More</Button>,\n },\n {\n name: 'Sizes',\n description: 'Available size options',\n render: () => (\n <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n </div>\n ),\n },\n ],\n});\n`;\n}\n\n/**\n * Start the dev server\n */\nfunction startDevServer(projectRoot: string): void {\n console.log(pc.dim(\"\\nStarting development server...\\n\"));\n\n // Use process.platform to determine the correct command\n const isWindows = process.platform === \"win32\";\n const cmd = isWindows ? \"npx.cmd\" : \"npx\";\n\n const child = spawn(cmd, [BRAND.cliCommand, \"dev\"], {\n cwd: projectRoot,\n stdio: \"inherit\",\n });\n\n child.on(\"error\", (err) => {\n console.error(pc.red(\"Failed to start dev server:\"), err.message);\n });\n}\n\n/**\n * Main init function - smart and interactive by default\n */\nexport async function init(options: InitOptions = {}): Promise<InitResult> {\n const projectRoot = resolve(options.projectRoot || process.cwd());\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n✨ Welcome to ${BRAND.name}!\\n`));\n\n // Step 1: Detect what exists\n const detection = await detectProject(projectRoot);\n\n // Check for existing config\n if (detection.hasConfig && !options.force) {\n console.log(pc.yellow(`⚠ Config already exists: ${BRAND.configFile}`));\n\n if (!options.yes) {\n const overwrite = await confirm({\n message: \"Do you want to reinitialize? (This will overwrite your config)\",\n default: false,\n });\n\n if (!overwrite) {\n console.log(pc.dim(`\\nKeeping existing configuration. Run \\`${BRAND.cliCommand} dev\\` to start.\\n`));\n return {\n success: true,\n scenario: \"stories\",\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors: [],\n };\n }\n }\n }\n\n // Step 2: Determine scenario and show what we found\n let scenario: \"stories\" | \"components\" | \"fresh\";\n\n if (detection.storyFiles.length > 0) {\n scenario = \"stories\";\n console.log(pc.green(`✓ Found ${detection.storyFiles.length} Storybook story file(s)`));\n console.log(pc.dim(` ${detection.storyFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.storyFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.storyFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"Great news! \") +\n \"Fragments can load your existing stories automatically.\"\n );\n } else if (detection.componentFiles.length > 0) {\n scenario = \"components\";\n console.log(pc.green(`✓ Found ${detection.componentFiles.length} component file(s)`));\n console.log(pc.dim(` ${detection.componentFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.componentFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.componentFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"No stories found, but that's fine! \") +\n \"Fragments can auto-generate documentation from your TypeScript.\"\n );\n } else {\n scenario = \"fresh\";\n console.log(pc.yellow(\"No components or stories found.\"));\n console.log();\n console.log(pc.cyan(\"Let's create your first fragment!\"));\n }\n\n console.log();\n\n // Step 3: Gather configuration (interactive unless --yes)\n let componentPath = detection.suggestedComponentPath;\n let runScan = scenario === \"components\";\n let createExample = scenario === \"fresh\";\n let startServer = true;\n\n if (!options.yes) {\n // Ask about component location\n componentPath = await input({\n message: \"Where are your components located?\",\n default: detection.suggestedComponentPath,\n });\n\n if (scenario === \"components\") {\n // For component-only projects, ask about scanning\n runScan = await confirm({\n message: \"Auto-generate documentation from TypeScript?\",\n default: true,\n });\n } else {\n // Fresh project - ask about example\n createExample = await confirm({\n message: \"Create an example Button component to get started?\",\n default: true,\n });\n }\n\n // Ask about starting the server\n startServer = await confirm({\n message: \"Start the viewer now?\",\n default: true,\n });\n }\n\n // Step 4: Create configuration\n console.log(pc.dim(\"\\nCreating configuration...\\n\"));\n\n // Build include patterns\n // Note: Stories are loaded separately by the viewer, not via include patterns\n const includePaths: string[] = [\n `${componentPath}/**/*.fragment.tsx`,\n `${componentPath}/**/*.segment.tsx`, // Legacy support\n ];\n\n // Create config file\n const configPath = join(projectRoot, BRAND.configFile);\n const configContent = generateConfig({\n includePaths,\n componentPaths: [`${componentPath}/**/*.tsx`],\n framework: \"react\",\n });\n\n try {\n await writeFile(configPath, configContent, \"utf-8\");\n console.log(pc.green(`✓ Created ${BRAND.configFile}`));\n } catch (e) {\n errors.push(`Failed to create config: ${e}`);\n }\n\n // Step 5: Handle scenario-specific setup\n if (scenario === \"fresh\" && createExample) {\n // Create example component\n const exampleDir = join(projectRoot, componentPath, \"Button\");\n\n try {\n await mkdir(exampleDir, { recursive: true });\n\n // Write Button.tsx\n await writeFile(\n join(exampleDir, \"Button.tsx\"),\n generateExampleComponent(),\n \"utf-8\"\n );\n console.log(\n pc.green(`✓ Created ${relative(projectRoot, join(exampleDir, \"Button.tsx\"))}`)\n );\n\n // Write Button.fragment.tsx\n await writeFile(\n join(exampleDir, \"Button.fragment.tsx\"),\n generateExampleFragment(),\n \"utf-8\"\n );\n console.log(\n pc.green(\n `✓ Created ${relative(projectRoot, join(exampleDir, \"Button.fragment.tsx\"))}`\n )\n );\n } catch (e) {\n errors.push(`Failed to create example component: ${e}`);\n }\n }\n\n if (scenario === \"components\" && runScan) {\n // Run scan to generate fragments.json\n console.log(pc.dim(\"\\nGenerating documentation from source code...\\n\"));\n try {\n const { scan } = await import(\"./scan.js\");\n await scan({\n config: configPath,\n verbose: false,\n });\n } catch (e) {\n console.log(\n pc.yellow(`Note: Auto-documentation will run when you start the dev server.`)\n );\n }\n }\n\n // Step 6: Show next steps or start server\n if (errors.length === 0) {\n console.log(pc.green(\"\\n✓ Setup complete!\\n\"));\n\n if (startServer) {\n const serverMessage =\n scenario === \"stories\"\n ? `Your ${detection.storyFiles.length} stories are loading...`\n : scenario === \"components\"\n ? `Your ${detection.componentFiles.length} components are being documented...`\n : `Your first component is ready!`;\n\n console.log(pc.cyan(serverMessage));\n startDevServer(projectRoot);\n } else {\n console.log(pc.cyan(\"Next steps:\"));\n console.log(` 1. Run ${pc.bold(`${BRAND.cliCommand} dev`)} to start the viewer`);\n if (scenario === \"fresh\") {\n console.log(` 2. Edit ${pc.bold(`${componentPath}/Button/Button.fragment.tsx`)}`);\n }\n console.log();\n }\n }\n\n return {\n success: errors.length === 0,\n configPath: errors.length === 0 ? configPath : undefined,\n scenario,\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors,\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/scan-ESEXV7LF.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
scan
|
|
4
|
-
} from "./chunk-XNWDI6UT.js";
|
|
5
|
-
import "./chunk-IOJE35DZ.js";
|
|
6
|
-
import "./chunk-2H2JAA3U.js";
|
|
7
|
-
import "./chunk-V7YLRR4C.js";
|
|
8
|
-
import "./chunk-ICAIQ57V.js";
|
|
9
|
-
export {
|
|
10
|
-
scan
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=scan-ESEXV7LF.js.map
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
generateStaticViewer,
|
|
4
|
-
generateViewerFromJson
|
|
5
|
-
} from "./chunk-2DJH4F4P.js";
|
|
6
|
-
import "./chunk-V7YLRR4C.js";
|
|
7
|
-
import "./chunk-ICAIQ57V.js";
|
|
8
|
-
export {
|
|
9
|
-
generateStaticViewer,
|
|
10
|
-
generateViewerFromJson
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=static-viewer-O37MJ5B6.js.map
|