oh-my-design-cli 0.1.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/LICENSE +21 -0
- package/README.ja.md +145 -0
- package/README.ko.md +245 -0
- package/README.md +245 -0
- package/README.zh-TW.md +145 -0
- package/data/reference-tags.md +104 -0
- package/data/synonyms.json +79 -0
- package/data/vocabulary.json +516 -0
- package/dist/bin/oh-my-design.js +858 -0
- package/dist/bin/oh-my-design.js.map +1 -0
- package/dist/chunk-6YNSV3VY.js +35 -0
- package/dist/chunk-6YNSV3VY.js.map +1 -0
- package/dist/chunk-MHFYGZSO.js +337 -0
- package/dist/chunk-MHFYGZSO.js.map +1 -0
- package/dist/chunk-N2JG6N4Q.js +264 -0
- package/dist/chunk-N2JG6N4Q.js.map +1 -0
- package/dist/chunk-OOQQEUGX.js +46 -0
- package/dist/chunk-OOQQEUGX.js.map +1 -0
- package/dist/chunk-OR5DHENY.js +250 -0
- package/dist/chunk-OR5DHENY.js.map +1 -0
- package/dist/customizer-CM76752R.js +8 -0
- package/dist/customizer-CM76752R.js.map +1 -0
- package/dist/index.d.ts +559 -0
- package/dist/index.js +3113 -0
- package/dist/index.js.map +1 -0
- package/dist/init-STACB7E5.js +635 -0
- package/dist/init-STACB7E5.js.map +1 -0
- package/dist/install-skills-CM6VXFZJ.js +152 -0
- package/dist/install-skills-CM6VXFZJ.js.map +1 -0
- package/dist/learn-33LHKEJA.js +140 -0
- package/dist/learn-33LHKEJA.js.map +1 -0
- package/dist/reference-YMNAOXJQ.js +47 -0
- package/dist/reference-YMNAOXJQ.js.map +1 -0
- package/dist/reference-parser-TM3CJPNE.js +10 -0
- package/dist/reference-parser-TM3CJPNE.js.map +1 -0
- package/dist/remember-UAFA5B2O.js +78 -0
- package/dist/remember-UAFA5B2O.js.map +1 -0
- package/dist/sync-P7X4S2DK.js +404 -0
- package/dist/sync-P7X4S2DK.js.map +1 -0
- package/dist/templates/templates/design-md.hbs +44 -0
- package/dist/templates/templates/partials/agent-prompt-guide.hbs +28 -0
- package/dist/templates/templates/partials/color-palette.hbs +49 -0
- package/dist/templates/templates/partials/component-stylings.hbs +28 -0
- package/dist/templates/templates/partials/depth-elevation.hbs +31 -0
- package/dist/templates/templates/partials/dos-donts.hbs +13 -0
- package/dist/templates/templates/partials/layout.hbs +30 -0
- package/dist/templates/templates/partials/responsive.hbs +25 -0
- package/dist/templates/templates/partials/shadcn-tokens.hbs +64 -0
- package/dist/templates/templates/partials/typography.hbs +43 -0
- package/dist/templates/templates/partials/visual-theme.hbs +26 -0
- package/package.json +68 -0
- package/references/Claude-Design-Sys-Prompt.txt +421 -0
- package/references/airbnb/DESIGN.md +427 -0
- package/references/airbnb/README.md +23 -0
- package/references/airbnb/preview-dark.html +234 -0
- package/references/airbnb/preview.html +233 -0
- package/references/airtable/DESIGN.md +107 -0
- package/references/airtable/README.md +23 -0
- package/references/airtable/preview-dark.html +165 -0
- package/references/airtable/preview.html +164 -0
- package/references/apple/DESIGN.md +496 -0
- package/references/apple/README.md +24 -0
- package/references/apple/preview-dark.html +420 -0
- package/references/apple/preview.html +414 -0
- package/references/baemin/DESIGN.md +260 -0
- package/references/baemin/README.md +19 -0
- package/references/bmw/DESIGN.md +180 -0
- package/references/bmw/README.md +23 -0
- package/references/bmw/preview-dark.html +211 -0
- package/references/bmw/preview.html +210 -0
- package/references/cal/DESIGN.md +259 -0
- package/references/cal/README.md +23 -0
- package/references/cal/preview-dark.html +449 -0
- package/references/cal/preview.html +575 -0
- package/references/claude/DESIGN.md +455 -0
- package/references/claude/README.md +24 -0
- package/references/claude/preview-dark.html +803 -0
- package/references/claude/preview.html +826 -0
- package/references/clay/DESIGN.md +304 -0
- package/references/clay/README.md +23 -0
- package/references/clay/preview-dark.html +316 -0
- package/references/clay/preview.html +315 -0
- package/references/clickhouse/DESIGN.md +281 -0
- package/references/clickhouse/README.md +24 -0
- package/references/clickhouse/preview-dark.html +834 -0
- package/references/clickhouse/preview.html +786 -0
- package/references/cohere/DESIGN.md +266 -0
- package/references/cohere/README.md +24 -0
- package/references/cohere/preview-dark.html +803 -0
- package/references/cohere/preview.html +807 -0
- package/references/coinbase/DESIGN.md +129 -0
- package/references/coinbase/README.md +23 -0
- package/references/coinbase/preview-dark.html +164 -0
- package/references/coinbase/preview.html +163 -0
- package/references/composio/DESIGN.md +307 -0
- package/references/composio/README.md +24 -0
- package/references/composio/preview-dark.html +958 -0
- package/references/composio/preview.html +933 -0
- package/references/cursor/DESIGN.md +322 -0
- package/references/cursor/README.md +24 -0
- package/references/cursor/preview-dark.html +393 -0
- package/references/cursor/preview.html +383 -0
- package/references/dcard/DESIGN.md +302 -0
- package/references/dcard/README.md +12 -0
- package/references/dcard/_research/forum-1440px.png +0 -0
- package/references/dcard/_research.md +77 -0
- package/references/elevenlabs/DESIGN.md +265 -0
- package/references/elevenlabs/README.md +23 -0
- package/references/elevenlabs/preview-dark.html +252 -0
- package/references/elevenlabs/preview.html +251 -0
- package/references/expo/DESIGN.md +281 -0
- package/references/expo/README.md +24 -0
- package/references/expo/preview-dark.html +533 -0
- package/references/expo/preview.html +533 -0
- package/references/ferrari/DESIGN.md +314 -0
- package/references/ferrari/README.md +23 -0
- package/references/ferrari/preview-dark.html +1162 -0
- package/references/ferrari/preview.html +1122 -0
- package/references/figma/DESIGN.md +399 -0
- package/references/figma/README.md +24 -0
- package/references/figma/preview-dark.html +822 -0
- package/references/figma/preview.html +832 -0
- package/references/framer/DESIGN.md +246 -0
- package/references/framer/README.md +23 -0
- package/references/framer/preview-dark.html +902 -0
- package/references/framer/preview.html +883 -0
- package/references/freee/DESIGN.md +308 -0
- package/references/freee/README.md +12 -0
- package/references/freee/_research/vibes-storybook-1440px.png +0 -0
- package/references/freee/_research.md +77 -0
- package/references/hashicorp/DESIGN.md +278 -0
- package/references/hashicorp/README.md +24 -0
- package/references/hashicorp/preview-dark.html +1202 -0
- package/references/hashicorp/preview.html +1193 -0
- package/references/ibm/DESIGN.md +332 -0
- package/references/ibm/README.md +24 -0
- package/references/ibm/preview-dark.html +443 -0
- package/references/ibm/preview.html +428 -0
- package/references/intercom/DESIGN.md +146 -0
- package/references/intercom/README.md +23 -0
- package/references/intercom/preview-dark.html +185 -0
- package/references/intercom/preview.html +184 -0
- package/references/kakao/DESIGN.md +261 -0
- package/references/kakao/README.md +18 -0
- package/references/karrot/DESIGN.md +252 -0
- package/references/karrot/README.md +18 -0
- package/references/kraken/DESIGN.md +146 -0
- package/references/kraken/README.md +23 -0
- package/references/kraken/preview-dark.html +169 -0
- package/references/kraken/preview.html +168 -0
- package/references/lamborghini/DESIGN.md +288 -0
- package/references/lamborghini/README.md +23 -0
- package/references/lamborghini/preview-dark.html +303 -0
- package/references/lamborghini/preview.html +381 -0
- package/references/line/DESIGN.md +375 -0
- package/references/line/README.md +12 -0
- package/references/line/_research/home-1440px.png +0 -0
- package/references/line/_research.md +65 -0
- package/references/linear.app/DESIGN.md +526 -0
- package/references/linear.app/README.md +24 -0
- package/references/linear.app/preview-dark.html +383 -0
- package/references/linear.app/preview.html +373 -0
- package/references/lovable/DESIGN.md +298 -0
- package/references/lovable/README.md +24 -0
- package/references/lovable/preview-dark.html +349 -0
- package/references/lovable/preview.html +348 -0
- package/references/mercari/DESIGN.md +294 -0
- package/references/mercari/README.md +12 -0
- package/references/mercari/_research/home-1440px.png +0 -0
- package/references/mercari/_research.md +77 -0
- package/references/minimax/DESIGN.md +257 -0
- package/references/minimax/README.md +24 -0
- package/references/minimax/preview-dark.html +1262 -0
- package/references/minimax/preview.html +1248 -0
- package/references/mintlify/DESIGN.md +341 -0
- package/references/mintlify/README.md +24 -0
- package/references/mintlify/preview-dark.html +409 -0
- package/references/mintlify/preview.html +398 -0
- package/references/miro/DESIGN.md +108 -0
- package/references/miro/README.md +23 -0
- package/references/miro/preview-dark.html +174 -0
- package/references/miro/preview.html +173 -0
- package/references/mistral.ai/DESIGN.md +261 -0
- package/references/mistral.ai/README.md +24 -0
- package/references/mistral.ai/preview-dark.html +806 -0
- package/references/mistral.ai/preview.html +805 -0
- package/references/mongodb/DESIGN.md +266 -0
- package/references/mongodb/README.md +23 -0
- package/references/mongodb/preview-dark.html +260 -0
- package/references/mongodb/preview.html +259 -0
- package/references/notion/DESIGN.md +492 -0
- package/references/notion/README.md +24 -0
- package/references/notion/preview-dark.html +372 -0
- package/references/notion/preview.html +364 -0
- package/references/nvidia/DESIGN.md +308 -0
- package/references/nvidia/README.md +24 -0
- package/references/nvidia/preview-dark.html +374 -0
- package/references/nvidia/preview.html +366 -0
- package/references/ollama/DESIGN.md +267 -0
- package/references/ollama/README.md +24 -0
- package/references/ollama/preview-dark.html +678 -0
- package/references/ollama/preview.html +678 -0
- package/references/opencode.ai/DESIGN.md +295 -0
- package/references/opencode.ai/README.md +24 -0
- package/references/opencode.ai/preview-dark.html +366 -0
- package/references/opencode.ai/preview.html +357 -0
- package/references/pinkoi/DESIGN.md +309 -0
- package/references/pinkoi/README.md +12 -0
- package/references/pinkoi/_research/browse-1440px.png +0 -0
- package/references/pinkoi/_research.md +115 -0
- package/references/pinterest/DESIGN.md +230 -0
- package/references/pinterest/README.md +23 -0
- package/references/pinterest/preview-dark.html +233 -0
- package/references/pinterest/preview.html +232 -0
- package/references/posthog/DESIGN.md +256 -0
- package/references/posthog/README.md +23 -0
- package/references/posthog/preview-dark.html +699 -0
- package/references/posthog/preview.html +749 -0
- package/references/raycast/DESIGN.md +268 -0
- package/references/raycast/README.md +23 -0
- package/references/raycast/preview-dark.html +606 -0
- package/references/raycast/preview.html +688 -0
- package/references/renault/DESIGN.md +311 -0
- package/references/renault/README.md +23 -0
- package/references/renault/preview-dark.html +406 -0
- package/references/renault/preview.html +606 -0
- package/references/replicate/DESIGN.md +261 -0
- package/references/replicate/README.md +24 -0
- package/references/replicate/preview-dark.html +828 -0
- package/references/replicate/preview.html +831 -0
- package/references/resend/DESIGN.md +303 -0
- package/references/resend/README.md +23 -0
- package/references/resend/preview-dark.html +355 -0
- package/references/resend/preview.html +354 -0
- package/references/revolut/DESIGN.md +185 -0
- package/references/revolut/README.md +23 -0
- package/references/revolut/preview-dark.html +234 -0
- package/references/revolut/preview.html +233 -0
- package/references/runwayml/DESIGN.md +244 -0
- package/references/runwayml/README.md +24 -0
- package/references/runwayml/preview-dark.html +664 -0
- package/references/runwayml/preview.html +665 -0
- package/references/sanity/DESIGN.md +357 -0
- package/references/sanity/README.md +24 -0
- package/references/sanity/preview-dark.html +990 -0
- package/references/sanity/preview.html +1135 -0
- package/references/sentry/DESIGN.md +262 -0
- package/references/sentry/README.md +24 -0
- package/references/sentry/preview-dark.html +626 -0
- package/references/sentry/preview.html +951 -0
- package/references/spacex/DESIGN.md +205 -0
- package/references/spacex/README.md +23 -0
- package/references/spacex/preview-dark.html +221 -0
- package/references/spacex/preview.html +220 -0
- package/references/spotify/DESIGN.md +246 -0
- package/references/spotify/README.md +23 -0
- package/references/spotify/preview-dark.html +231 -0
- package/references/spotify/preview.html +230 -0
- package/references/stripe/DESIGN.md +473 -0
- package/references/stripe/README.md +24 -0
- package/references/stripe/preview-dark.html +428 -0
- package/references/stripe/preview.html +419 -0
- package/references/supabase/DESIGN.md +255 -0
- package/references/supabase/README.md +24 -0
- package/references/supabase/preview-dark.html +977 -0
- package/references/supabase/preview.html +955 -0
- package/references/superhuman/DESIGN.md +252 -0
- package/references/superhuman/README.md +23 -0
- package/references/superhuman/preview-dark.html +973 -0
- package/references/superhuman/preview.html +951 -0
- package/references/tesla/DESIGN.md +286 -0
- package/references/tesla/README.md +23 -0
- package/references/tesla/preview-dark.html +947 -0
- package/references/tesla/preview.html +925 -0
- package/references/together.ai/DESIGN.md +263 -0
- package/references/together.ai/README.md +24 -0
- package/references/together.ai/preview-dark.html +892 -0
- package/references/together.ai/preview.html +897 -0
- package/references/toss/DESIGN.md +387 -0
- package/references/toss/README.md +19 -0
- package/references/uber/DESIGN.md +295 -0
- package/references/uber/README.md +24 -0
- package/references/uber/preview-dark.html +1120 -0
- package/references/uber/preview.html +1119 -0
- package/references/vercel/DESIGN.md +456 -0
- package/references/vercel/README.md +24 -0
- package/references/vercel/preview-dark.html +368 -0
- package/references/vercel/preview.html +367 -0
- package/references/voltagent/DESIGN.md +323 -0
- package/references/voltagent/README.md +24 -0
- package/references/voltagent/preview-dark.html +487 -0
- package/references/voltagent/preview.html +766 -0
- package/references/warp/DESIGN.md +253 -0
- package/references/warp/README.md +23 -0
- package/references/warp/preview-dark.html +500 -0
- package/references/warp/preview.html +533 -0
- package/references/webflow/DESIGN.md +109 -0
- package/references/webflow/README.md +23 -0
- package/references/webflow/preview-dark.html +147 -0
- package/references/webflow/preview.html +146 -0
- package/references/wise/DESIGN.md +173 -0
- package/references/wise/README.md +23 -0
- package/references/wise/preview-dark.html +230 -0
- package/references/wise/preview.html +229 -0
- package/references/x.ai/DESIGN.md +267 -0
- package/references/x.ai/README.md +24 -0
- package/references/x.ai/preview-dark.html +356 -0
- package/references/x.ai/preview.html +407 -0
- package/references/zapier/DESIGN.md +328 -0
- package/references/zapier/README.md +24 -0
- package/references/zapier/preview-dark.html +380 -0
- package/references/zapier/preview.html +372 -0
- package/skills/omd-apply/SKILL.md +85 -0
- package/skills/omd-init/SKILL.md +167 -0
- package/skills/omd-learn/SKILL.md +81 -0
- package/skills/omd-remember/SKILL.md +44 -0
- package/skills/omd-sync/SKILL.md +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../bin/oh-my-design.ts","../../src/cli/index.ts","../../src/cli/prompts.ts","../../src/core/preview-generator.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { run } from '../src/cli/index.js';\n\nfunction readPackageVersion(): string {\n let cur = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n const pkg = join(cur, 'package.json');\n if (existsSync(pkg)) {\n try {\n return JSON.parse(readFileSync(pkg, 'utf8')).version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n }\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return '0.0.0';\n}\n\nconst program = new Command();\n\nprogram\n .name('oh-my-design')\n .description('Interactive CLI to generate DESIGN.md files for AI coding agents')\n .version(readPackageVersion());\n\nprogram\n .command('generate', { isDefault: true })\n .description('Generate DESIGN.md and interactive preview')\n .option('--config <hash>', 'Apply a config hash from the web builder')\n .action(async (opts: { config?: string }) => {\n if (opts.config) {\n // Decode config hash and generate directly without prompts\n const { writeFileSync } = await import('fs');\n const { resolve } = await import('path');\n\n // Decode the hash — format: refId|primary|font|weight|radius|dark|components|stylePrefs\n // parts[7] (stylePrefs) was added in v2. Old hashes lack it and still decode.\n let b64 = opts.config.replace(/-/g, '+').replace(/_/g, '/');\n while (b64.length % 4) b64 += '=';\n const decoded = Buffer.from(b64, 'base64').toString('utf-8');\n const parts = decoded.split('|');\n\n const refId = parts[0] || 'vercel';\n const overrides = {\n primaryColor: parts[1] || undefined,\n fontFamily: parts[2] || undefined,\n headingWeight: parts[3] || undefined,\n borderRadius: parts[4] || undefined,\n darkMode: parts[5] === '1',\n };\n const components = parts[6] ? parts[6].split(',').filter(Boolean) : [];\n // stylePreferences are decoded but not yet applied here — the CLI's\n // customizer (src/core/customizer.ts) does not mirror the web's\n // stylePreferences inline-rewrite logic yet. Parsed here so old and\n // new hashes coexist without error; CLI integration is a follow-up.\n const stylePrefs: Record<string, string> = {};\n if (parts[7]) {\n for (const pair of parts[7].split(';')) {\n const [k, v] = pair.split('=');\n if (k && v) stylePrefs[k] = v;\n }\n }\n\n // Load reference and apply\n const { loadReference } = await import('../src/core/reference-parser.js');\n const { applyOverrides } = await import('../src/core/customizer.js');\n\n const ref = loadReference(refId);\n const mode = (overrides.primaryColor || overrides.fontFamily) ? 'customized' as const : 'as-is' as const;\n const { designMd, shadcnCss, previewData } = applyOverrides(ref, {\n primaryColor: overrides.primaryColor,\n fontFamily: overrides.fontFamily,\n headingWeight: overrides.headingWeight,\n borderRadius: overrides.borderRadius,\n darkMode: overrides.darkMode,\n }, mode, components);\n\n previewData.shadcnCss = shadcnCss;\n previewData.designMd = designMd;\n\n const outputDir = process.cwd();\n const mdPath = resolve(outputDir, 'DESIGN.md');\n writeFileSync(mdPath, designMd, 'utf-8');\n\n console.log(`\\x1b[32m✓\\x1b[0m DESIGN.md generated at ${mdPath}`);\n console.log(` Based on: ${ref.name}`);\n if (overrides.primaryColor) console.log(` Primary: ${overrides.primaryColor}`);\n if (overrides.fontFamily) console.log(` Font: ${overrides.fontFamily}`);\n if (overrides.headingWeight) console.log(` Weight: ${overrides.headingWeight}`);\n if (overrides.borderRadius) console.log(` Radius: ${overrides.borderRadius}`);\n if (overrides.darkMode) console.log(` Dark mode: included`);\n } else {\n await run();\n }\n });\n\nprogram\n .command('install-skills')\n .description('Install omd:* skill files into agent directories (.claude/, .codex/, .opencode/)')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--agent <name...>', 'Restrict to specific agents (claude-code | codex | opencode)')\n .option('--force', 'Overwrite existing files even without the omd marker')\n .action(\n async (opts: { dir?: string; agent?: string[]; force?: boolean }) => {\n const { runInstallSkills } = await import('../src/cli/install-skills.js');\n const validAgents = ['claude-code', 'codex', 'opencode'] as const;\n type Agent = (typeof validAgents)[number];\n const agents = opts.agent\n ? (opts.agent.filter((a): a is Agent =>\n (validAgents as readonly string[]).includes(a)\n ) as Agent[])\n : undefined;\n const code = await runInstallSkills({\n dir: opts.dir,\n agents,\n force: opts.force,\n });\n if (code !== 0) process.exit(code);\n }\n );\n\nconst referenceCmd = program\n .command('reference')\n .description('Inspect bundled design references');\n\nreferenceCmd\n .command('list')\n .description('List all bundled reference ids')\n .action(async () => {\n const { runReferenceList } = await import('../src/cli/reference.js');\n process.exit(runReferenceList());\n });\n\nreferenceCmd\n .command('show <id>')\n .description('Print the full reference DESIGN.md to stdout')\n .action(async (id: string) => {\n const { runReferenceShow } = await import('../src/cli/reference.js');\n process.exit(runReferenceShow(id));\n });\n\nconst initCmd = program\n .command('init')\n .description('Bootstrap DESIGN.md from a reference + project description');\n\ninitCmd\n .command('recommend <description...>')\n .description('Recommend references matching a project description')\n .option('--top <n>', 'Number of recommendations', '5')\n .option('--json', 'Emit machine-readable JSON')\n .action(\n async (descParts: string[], opts: { top?: string; json?: boolean }) => {\n const { runInitRecommend } = await import('../src/cli/init.js');\n const code = runInitRecommend({\n description: descParts.join(' '),\n topK: opts.top ? Number(opts.top) : 5,\n json: opts.json,\n });\n if (code !== 0) process.exit(code);\n }\n );\n\ninitCmd\n .command('prepare')\n .description('Stage init context: rename existing DESIGN.md, compute delta_set, write .omd/init-context.json')\n .requiredOption('--ref <id>', 'Reference id (e.g. vercel, linear.app)')\n .requiredOption('--description <text>', 'Project description')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--reason <text>', 'Reason for deprecation header', 'user-initiated omd init')\n .option('--json', 'Emit machine-readable JSON')\n .action(async (opts: { ref: string; description: string; dir?: string; reason?: string; json?: boolean }) => {\n const { runInitPrepare } = await import('../src/cli/init.js');\n const code = runInitPrepare(opts);\n if (code !== 0) process.exit(code);\n });\n\nprogram\n .command('learn')\n .description('List preferences and flip status (applied/rejected)')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--all', 'Include all statuses (default: pending only)')\n .option('--status <s>', 'Filter by status: pending|applied|rejected|superseded')\n .option('--scope <s>', 'Filter by scope')\n .option('--mark-applied <id>', 'Mark entry as applied')\n .option('--mark-rejected <id>', 'Mark entry as rejected (requires --reason)')\n .option('--reason <text>', 'Reason for rejection')\n .option('--hash <value>', 'DESIGN.md hash to stamp on applied entry (defaults to current file)')\n .action(async (opts: Record<string, string | boolean>) => {\n const { runLearn } = await import('../src/cli/learn.js');\n const code = await runLearn(opts as never);\n if (code !== 0) process.exit(code);\n });\n\nprogram\n .command('remember <note...>')\n .description('Append a design preference/correction to .omd/preferences.md')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--scope <scope>', 'Explicit scope (e.g. color, components.button)')\n .option('--agent <name>', 'Source agent (e.g. claude-code, codex)')\n .option('--context <text>', 'Source file/line context')\n .action(\n async (\n noteParts: string[],\n opts: {\n dir?: string;\n scope?: string;\n agent?: string;\n context?: string;\n }\n ) => {\n const { runRemember } = await import('../src/cli/remember.js');\n const code = await runRemember(noteParts.join(' '), opts as never);\n if (code !== 0) process.exit(code);\n }\n );\n\nprogram\n .command('sync')\n .description('Sync DESIGN.md shim files (CLAUDE.md, AGENTS.md, .cursor/rules/omd-design.mdc)')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--force', 'Overwrite drift without prompting')\n .option('--check', 'Exit non-zero if any shim has drift; do not write')\n .action(async (opts: { dir?: string; force?: boolean; check?: boolean }) => {\n const { runSync } = await import('../src/cli/sync.js');\n const code = await runSync(opts);\n if (code !== 0) process.exit(code);\n });\n\nprogram\n .command('preview')\n .description('Open the preview HTML in the default browser')\n .action(async () => {\n const { existsSync } = await import('fs');\n const { resolve } = await import('path');\n const previewPath = resolve(process.cwd(), 'DESIGN.preview.html');\n\n if (!existsSync(previewPath)) {\n console.error('No DESIGN.preview.html found. Run `oh-my-design generate` first.');\n process.exit(1);\n }\n\n const { exec } = await import('child_process');\n const platform = process.platform;\n const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';\n exec(`${cmd} \"${previewPath}\"`);\n console.log(`Opening ${previewPath}...`);\n });\n\nprogram.parse();\n","import * as p from '@clack/prompts';\nimport { writeFileSync } from 'fs';\nimport { resolve } from 'path';\nimport { runPrompts } from './prompts.js';\nimport { applyOverrides } from '../core/customizer.js';\nimport { generatePreviewHtml } from '../core/preview-generator.js';\n\nexport async function run() {\n const { reference, overrides, outputMode } = await runPrompts();\n\n const s = p.spinner();\n s.start(`Building design system based on ${reference.name}...`);\n\n // Apply overrides to reference DESIGN.md\n const { designMd, shadcnCss, previewData } = applyOverrides(reference, overrides, outputMode);\n\n // Fill in the preview data with generated content\n previewData.shadcnCss = shadcnCss;\n previewData.designMd = designMd;\n\n // Generate preview HTML\n const html = generatePreviewHtml(previewData);\n\n // Write files\n const outputDir = process.cwd();\n const mdPath = resolve(outputDir, 'DESIGN.md');\n const htmlPath = resolve(outputDir, 'DESIGN.preview.html');\n\n writeFileSync(mdPath, designMd, 'utf-8');\n writeFileSync(htmlPath, html, 'utf-8');\n\n s.stop('Done!');\n\n p.log.success(`DESIGN.md → ${mdPath}`);\n p.log.success(`Preview HTML → ${htmlPath}`);\n p.outro('Open DESIGN.preview.html in your browser to explore your design system.');\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport { listReferences, loadReference } from '../core/reference-parser.js';\nimport type { ReferenceEntry } from '../core/reference-parser.js';\n\n// ── Types ────────────────────────────────────────────────────────\n\nexport interface CustomOverrides {\n primaryColor?: string; // override primary color hex\n headingWeight?: string; // override heading weight\n borderRadius?: string; // override base radius\n fontFamily?: string; // override primary font\n darkMode: boolean;\n additionalNotes?: string;\n}\n\nexport interface PromptResult {\n reference: ReferenceEntry;\n overrides: CustomOverrides;\n outputMode: 'as-is' | 'customized';\n}\n\n// ── Main ─────────────────────────────────────────────────────────\n\nexport async function runPrompts(): Promise<PromptResult> {\n p.intro(`${pc.bold('oh-my-design')} — Generate your DESIGN.md from real design systems`);\n\n // Step 1: List all references grouped by category\n const refs = listReferences();\n const categories = [...new Set(refs.map((r) => r.category))];\n\n // Step 1a: Pick category\n const category = await p.select({\n message: 'Pick a category:',\n options: categories.map((cat) => {\n const count = refs.filter((r) => r.category === cat).length;\n return { value: cat, label: `${cat}`, hint: `${count} references` };\n }),\n });\n if (p.isCancel(category)) { p.cancel('Cancelled.'); process.exit(0); }\n\n // Step 1b: Pick reference within category\n const categoryRefs = refs.filter((r) => r.category === category);\n const refId = await p.select({\n message: `Select a design system reference:`,\n options: categoryRefs.map((r) => ({\n value: r.id,\n label: `${r.name}`,\n hint: `${r.primaryColor}`,\n })),\n });\n if (p.isCancel(refId)) { p.cancel('Cancelled.'); process.exit(0); }\n\n const reference = loadReference(refId as string);\n\n p.log.info(`${pc.bold(reference.name)} loaded`);\n p.log.info(` Primary: ${pc.bold(reference.colors.primary)} ${reference.colors.primaryName}`);\n p.log.info(` Font: ${reference.typography.primary}`);\n p.log.info(` Radius: ${reference.radius}`);\n if (reference.mood) {\n p.log.info(` Mood: ${reference.mood.slice(0, 120)}...`);\n }\n\n // Step 2: Use as-is or customize?\n const mode = await p.select({\n message: 'How do you want to use this design system?',\n options: [\n { value: 'as-is', label: 'Use as-is', hint: 'Copy the reference DESIGN.md directly' },\n { value: 'customized', label: 'Customize', hint: 'Modify colors, fonts, radius, etc.' },\n ],\n });\n if (p.isCancel(mode)) { p.cancel('Cancelled.'); process.exit(0); }\n\n if (mode === 'as-is') {\n const darkMode = await p.confirm({\n message: 'Include dark mode notes?',\n initialValue: false,\n });\n if (p.isCancel(darkMode)) { p.cancel('Cancelled.'); process.exit(0); }\n\n return {\n reference,\n overrides: { darkMode },\n outputMode: 'as-is',\n };\n }\n\n // Step 3: Customization prompts\n const overrides = await p.group(\n {\n primaryColor: () =>\n p.text({\n message: `Primary color (current: ${reference.colors.primary}):`,\n placeholder: 'Press enter to keep, or type a hex like #6366f1',\n validate: (val) => {\n if (val && !/^#[0-9a-fA-F]{6}$/.test(val)) return 'Invalid hex color';\n },\n }),\n\n fontFamily: () =>\n p.select({\n message: `Primary font (current: ${reference.typography.primary}):`,\n options: [\n { value: '', label: `Keep \"${reference.typography.primary}\"`, hint: 'No change' },\n { value: 'Inter', label: 'Inter', hint: 'Clean, geometric sans-serif' },\n { value: 'system-ui', label: 'System UI', hint: 'Native OS fonts' },\n { value: 'JetBrains Mono', label: 'JetBrains Mono', hint: 'Monospace, technical' },\n { value: 'Geist', label: 'Geist', hint: 'Vercel\\'s modern sans' },\n ],\n }),\n\n headingWeight: () =>\n p.select({\n message: `Heading weight (current: ${reference.typography.headingWeight}):`,\n options: [\n { value: '', label: `Keep ${reference.typography.headingWeight}`, hint: 'No change' },\n { value: '300', label: '300 — Light', hint: 'Whisper authority (Stripe style)' },\n { value: '400', label: '400 — Regular' },\n { value: '500', label: '500 — Medium', hint: 'Balanced emphasis' },\n { value: '600', label: '600 — Semibold', hint: 'Strong headings' },\n { value: '700', label: '700 — Bold', hint: 'Maximum impact' },\n ],\n }),\n\n borderRadius: () =>\n p.select({\n message: `Border radius (current: ${reference.radius}):`,\n options: [\n { value: '', label: `Keep \"${reference.radius}\"`, hint: 'No change' },\n { value: '2px', label: 'Sharp (2px)', hint: 'Technical, precise' },\n { value: '4px', label: 'Tight (4px)', hint: 'Conservative' },\n { value: '6px', label: 'Moderate (6px)', hint: 'Balanced' },\n { value: '8px', label: 'Comfortable (8px)', hint: 'Friendly' },\n { value: '12px', label: 'Rounded (12px)', hint: 'Soft, approachable' },\n { value: '9999px', label: 'Pill', hint: 'Fully rounded' },\n ],\n }),\n\n darkMode: () =>\n p.confirm({\n message: 'Generate dark mode variant?',\n initialValue: false,\n }),\n\n additionalNotes: () =>\n p.text({\n message: 'Any additional customization notes? (optional)',\n placeholder: 'e.g. \"Use more warm tones\" or press enter to skip',\n }),\n },\n {\n onCancel: () => { p.cancel('Cancelled.'); process.exit(0); },\n },\n );\n\n return {\n reference,\n overrides: {\n primaryColor: overrides.primaryColor || undefined,\n fontFamily: overrides.fontFamily || undefined,\n headingWeight: overrides.headingWeight || undefined,\n borderRadius: overrides.borderRadius || undefined,\n darkMode: overrides.darkMode,\n additionalNotes: overrides.additionalNotes || undefined,\n },\n outputMode: 'customized',\n };\n}\n","import type { PreviewData } from './customizer.js';\nimport {\n generateColorScale,\n contrastForeground,\n hslString,\n hexToHsl,\n hslToHex,\n lighten,\n darken,\n generateChartColors,\n} from '../utils/color.js';\n\nexport function generatePreviewHtml(data: PreviewData): string {\n const {\n name, basedOn, primary, background, foreground, font, headingWeight,\n radius, colors, darkMode, shadcnCss,\n } = data;\n\n const isLightBg = isLight(background);\n const scale = generateColorScale(primary);\n const radiusPx = radius === '9999px' ? '24px' : radius;\n const borderColor = colors.border;\n const accent = colors.accent;\n const muted = colors.muted;\n const chart = colors.chart;\n\n // Generate dark mode vars for CSS\n const darkBg = hslToHex(hexToHsl(primary)[0], 15, 7);\n const darkFg = '#fafafa';\n const darkBorder = hslToHex(hexToHsl(primary)[0], 10, 18);\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>${esc(name)} — Design System Preview</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n :root {\n --bg: ${background};\n --fg: ${foreground};\n --primary: ${primary};\n --primary-fg: ${contrastForeground(primary)};\n --accent: ${accent};\n --muted: ${muted};\n --muted-fg: ${lighten(foreground, 40)};\n --border: ${borderColor};\n --destructive: #ef4444;\n --card: ${isLightBg ? '#ffffff' : lighten(background, 3)};\n --radius: ${radiusPx};\n }\n\n .dark {\n --bg: ${darkBg};\n --fg: ${darkFg};\n --card: ${lighten(darkBg, 3)};\n --muted: ${hslToHex(hexToHsl(primary)[0], 10, 15)};\n --muted-fg: ${darken(darkFg, 35)};\n --border: ${darkBorder};\n }\n\n body {\n font-family: \"${font}\", \"Inter\", system-ui, sans-serif;\n background: var(--bg);\n color: var(--fg);\n line-height: 1.5;\n transition: background 0.25s, color 0.25s;\n }\n\n .shell { max-width: 1100px; margin: 0 auto; padding: 40px 24px 80px; }\n\n /* ── Header ─────── */\n .header {\n display: flex; justify-content: space-between; align-items: center;\n padding-bottom: 24px; margin-bottom: 40px;\n border-bottom: 1px solid var(--border);\n }\n .header h1 {\n font-size: 2rem; font-weight: ${headingWeight};\n letter-spacing: -0.02em;\n }\n .header .sub {\n font-size: 0.875rem; color: var(--muted-fg); margin-top: 4px;\n }\n .controls { display: flex; gap: 8px; }\n .ctrl-btn {\n padding: 8px 16px; border-radius: var(--radius);\n font-size: 0.8125rem; font-family: inherit; cursor: pointer;\n transition: all 0.15s; border: 1px solid var(--border);\n background: var(--card); color: var(--fg);\n }\n .ctrl-btn:hover { opacity: 0.85; }\n .ctrl-btn.primary { background: var(--primary); color: var(--primary-fg); border-color: transparent; }\n\n /* ── Sections ───── */\n .section { margin-bottom: 48px; }\n .section-title {\n font-size: 1.375rem; font-weight: ${headingWeight};\n letter-spacing: -0.01em; margin-bottom: 16px;\n }\n .section-sub { font-size: 0.8125rem; color: var(--muted-fg); margin-bottom: 16px; }\n\n /* ── Color Scale ── */\n .scale-row {\n display: flex; border-radius: var(--radius); overflow: hidden;\n border: 1px solid var(--border); margin-bottom: 24px;\n }\n .scale-stop {\n flex: 1; padding: 28px 4px 8px; text-align: center;\n font-size: 10px; font-family: monospace; cursor: pointer;\n transition: transform 0.1s; position: relative;\n }\n .scale-stop:hover { z-index: 1; transform: scaleY(1.12); }\n .scale-stop .lbl { display: block; opacity: 0.7; margin-bottom: 2px; }\n .scale-stop .hex {\n background: rgba(0,0,0,0.2); color: #fff;\n padding: 1px 4px; border-radius: 3px; font-size: 9px;\n }\n\n /* ── Color Chips ── */\n .chip-grid {\n display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px;\n }\n .chip {\n border-radius: var(--radius); overflow: hidden;\n border: 1px solid var(--border); cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n }\n .chip:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }\n .chip .sw { height: 64px; display: flex; align-items: end; padding: 6px; }\n .chip .sw span {\n font-size: 10px; font-family: monospace;\n background: rgba(0,0,0,0.25); color: #fff;\n padding: 1px 5px; border-radius: 3px;\n }\n .chip .inf { padding: 8px; background: var(--card); }\n .chip .inf .n { font-size: 0.75rem; font-weight: 500; }\n .chip .inf .v { font-size: 10px; color: var(--muted-fg); font-family: monospace; }\n\n /* ── Typography ── */\n .type-rows { display: flex; flex-direction: column; gap: 8px; }\n .type-row {\n display: flex; align-items: baseline; gap: 16px;\n padding: 12px 16px; border-radius: var(--radius);\n background: var(--card); border: 1px solid var(--border);\n }\n .type-row .lbl {\n min-width: 48px; font-size: 0.75rem; color: var(--muted-fg);\n font-family: monospace; flex-shrink: 0;\n }\n .type-row .sample { flex: 1; }\n\n /* ── Components ── */\n .comp-card {\n padding: 24px; border-radius: var(--radius);\n background: var(--card); border: 1px solid var(--border);\n margin-bottom: 16px;\n }\n .comp-card h3 { font-size: 1rem; font-weight: 600; margin-bottom: 16px; }\n .comp-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 12px; }\n\n .btn {\n display: inline-flex; align-items: center; justify-content: center;\n font-family: inherit; font-weight: 500; cursor: pointer;\n transition: all 0.15s; border: none; font-size: 0.8125rem;\n padding: 8px 16px; height: 36px; border-radius: var(--radius);\n }\n .btn-primary { background: var(--primary); color: var(--primary-fg); }\n .btn-secondary { background: var(--muted); color: var(--fg); }\n .btn-outline { background: transparent; color: var(--fg); border: 1px solid var(--border); }\n .btn-ghost { background: transparent; color: var(--fg); }\n .btn-destructive { background: var(--destructive); color: #fff; }\n .btn:hover { opacity: 0.9; }\n\n .badge {\n display: inline-flex; font-size: 0.6875rem; font-weight: 500;\n padding: 2px 10px; border-radius: 9999px;\n }\n .badge-primary { background: var(--primary); color: var(--primary-fg); }\n .badge-secondary { background: var(--muted); color: var(--fg); }\n .badge-outline { background: transparent; color: var(--fg); border: 1px solid var(--border); }\n\n .input-demo {\n width: 100%; max-width: 320px; font-family: inherit;\n background: var(--bg); color: var(--fg);\n border: 1px solid var(--border); border-radius: var(--radius);\n padding: 8px 12px; font-size: 0.8125rem; outline: none;\n transition: border-color 0.15s;\n }\n .input-demo:focus {\n border-color: var(--primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 20%, transparent);\n }\n\n .demo-table {\n width: 100%; border-collapse: collapse; font-size: 0.8125rem;\n }\n .demo-table th, .demo-table td {\n padding: 10px 12px; text-align: left;\n border-bottom: 1px solid var(--border);\n }\n .demo-table th {\n font-weight: 500; color: var(--muted-fg);\n font-size: 0.75rem; text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n .demo-table tr:hover td { background: var(--muted); }\n\n .demo-card {\n padding: 20px; border-radius: var(--radius);\n background: var(--card); border: 1px solid var(--border);\n max-width: 340px; box-shadow: 0 1px 3px rgba(0,0,0,0.06);\n }\n .demo-card h4 { font-weight: 600; margin-bottom: 6px; }\n .demo-card p { font-size: 0.8125rem; color: var(--muted-fg); margin-bottom: 14px; }\n\n .demo-dialog {\n padding: 24px; border-radius: var(--radius);\n background: var(--card); box-shadow: 0 20px 40px rgba(0,0,0,0.15);\n max-width: 400px; border: 1px solid var(--border);\n }\n .demo-dialog h4 { font-weight: 600; margin-bottom: 8px; }\n .demo-dialog p { font-size: 0.8125rem; color: var(--muted-fg); margin-bottom: 16px; }\n .demo-dialog .acts { display: flex; justify-content: flex-end; gap: 8px; }\n\n .tabs {\n display: flex; background: var(--muted); border-radius: var(--radius); padding: 4px; gap: 2px;\n }\n .tab {\n padding: 6px 14px; border-radius: calc(var(--radius) - 2px);\n font-size: 0.8125rem; font-family: inherit; font-weight: 500;\n border: none; cursor: pointer; background: transparent;\n color: var(--muted-fg); transition: all 0.15s;\n }\n .tab.active {\n background: var(--bg); color: var(--fg);\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n }\n .tab:hover:not(.active) { color: var(--fg); }\n\n /* ── CSS Block ──── */\n .css-block {\n position: relative; background: var(--card);\n border: 1px solid var(--border); border-radius: var(--radius);\n overflow: hidden;\n }\n .css-block pre {\n padding: 20px; overflow-x: auto; font-family: monospace;\n font-size: 11px; line-height: 1.6; color: var(--fg);\n }\n .css-block .copy-css { position: absolute; top: 8px; right: 8px; }\n\n /* ── Spacing ────── */\n .spacing-vis {\n display: flex; align-items: end; gap: 8px; padding: 24px;\n background: var(--card); border: 1px solid var(--border);\n border-radius: var(--radius);\n }\n .sp-bar { display: flex; flex-direction: column; align-items: center; gap: 4px; }\n .sp-bar .bar { background: var(--primary); border-radius: 2px; width: 28px; }\n .sp-bar .val { font-size: 10px; font-family: monospace; color: var(--muted-fg); }\n\n /* ── Radius ─────── */\n .radius-grid { display: flex; gap: 16px; flex-wrap: wrap; }\n .radius-demo {\n width: 72px; height: 72px; background: var(--primary);\n display: flex; align-items: center; justify-content: center;\n color: var(--primary-fg); font-size: 0.6875rem; font-family: monospace;\n }\n\n /* ── Toast ──────── */\n .toast-popup {\n position: fixed; bottom: 24px; right: 24px;\n padding: 10px 20px; background: var(--fg); color: var(--bg);\n border-radius: var(--radius); font-size: 0.8125rem;\n box-shadow: 0 8px 20px rgba(0,0,0,0.15);\n transform: translateY(100px); opacity: 0;\n transition: all 0.3s; z-index: 100;\n }\n .toast-popup.show { transform: translateY(0); opacity: 1; }\n\n @media (max-width: 768px) {\n .shell { padding: 16px 12px 48px; }\n .header { flex-direction: column; gap: 12px; align-items: flex-start; }\n .chip-grid { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); }\n }\n</style>\n</head>\n<body>\n<div class=\"shell\">\n\n <div class=\"header\">\n <div>\n <h1>${esc(name)}</h1>\n <div class=\"sub\">Based on ${esc(basedOn)} · Generated by oh-my-design</div>\n </div>\n <div class=\"controls\">\n ${darkMode ? '<button class=\"ctrl-btn\" onclick=\"toggleTheme()\" id=\"theme-btn\">🌙 Dark</button>' : ''}\n <button class=\"ctrl-btn primary\" onclick=\"copyCss()\">Copy CSS</button>\n </div>\n </div>\n\n <!-- Primary Scale -->\n <div class=\"section\">\n <h2 class=\"section-title\">Primary Color Scale</h2>\n <div class=\"section-sub\">Click to copy hex value</div>\n <div class=\"scale-row\">\n${Object.entries(scale).map(([stop, hex]) =>\n ` <div class=\"scale-stop\" style=\"background:${hex};color:${isLight(hex) ? '#000' : '#fff'}\" onclick=\"copy('${hex}')\">\n <span class=\"lbl\">${stop}</span><span class=\"hex\">${hex}</span>\n </div>`).join('\\n')}\n </div>\n </div>\n\n <!-- Semantic Colors -->\n <div class=\"section\">\n <h2 class=\"section-title\">Semantic Colors</h2>\n <div class=\"chip-grid\">\n${[\n { n: 'Primary', bg: primary, v: '--primary' },\n { n: 'Accent', bg: accent, v: '--accent' },\n { n: 'Muted', bg: muted, v: '--muted' },\n { n: 'Destructive', bg: '#ef4444', v: '--destructive' },\n { n: 'Background', bg: background, v: '--background' },\n { n: 'Foreground', bg: foreground, v: '--foreground' },\n { n: 'Border', bg: borderColor, v: '--border' },\n { n: 'Card', bg: isLightBg ? '#ffffff' : lighten(background, 3), v: '--card' },\n].map((c) => ` <div class=\"chip\" onclick=\"copy('${c.bg}')\">\n <div class=\"sw\" style=\"background:${c.bg}\"><span>${c.bg}</span></div>\n <div class=\"inf\"><div class=\"n\">${c.n}</div><div class=\"v\">${c.v}</div></div>\n </div>`).join('\\n')}\n </div>\n </div>\n\n <!-- Chart Colors -->\n <div class=\"section\">\n <h2 class=\"section-title\">Chart Colors</h2>\n <div style=\"display:flex;gap:8px;\">\n${chart.map((c, i) => ` <div style=\"width:48px;height:48px;border-radius:var(--radius);background:${c};cursor:pointer;\" onclick=\"copy('${c}')\" title=\"Chart ${i + 1}: ${c}\"></div>`).join('\\n')}\n </div>\n </div>\n\n <!-- Typography -->\n <div class=\"section\">\n <h2 class=\"section-title\">Typography</h2>\n <div class=\"type-rows\">\n <div class=\"type-row\">\n <span class=\"lbl\">H1</span>\n <span class=\"sample\" style=\"font-size:2.25rem;font-weight:${headingWeight};letter-spacing:-0.02em;line-height:1.2\">Page Title Heading</span>\n </div>\n <div class=\"type-row\">\n <span class=\"lbl\">H2</span>\n <span class=\"sample\" style=\"font-size:1.875rem;font-weight:${headingWeight};letter-spacing:-0.01em;line-height:1.25\">Section Heading</span>\n </div>\n <div class=\"type-row\">\n <span class=\"lbl\">H3</span>\n <span class=\"sample\" style=\"font-size:1.5rem;font-weight:${headingWeight};line-height:1.3\">Subsection</span>\n </div>\n <div class=\"type-row\">\n <span class=\"lbl\">body</span>\n <span class=\"sample\" style=\"font-size:1rem;\">The quick brown fox jumps over the lazy dog. 다람쥐 헌 쳇바퀴에 타고파.</span>\n </div>\n <div class=\"type-row\">\n <span class=\"lbl\">sm</span>\n <span class=\"sample\" style=\"font-size:0.875rem;color:var(--muted-fg)\">Secondary text, labels, and metadata</span>\n </div>\n <div class=\"type-row\">\n <span class=\"lbl\">mono</span>\n <span class=\"sample\" style=\"font-family:monospace;font-size:0.875rem\">const theme = generateDesignSystem();</span>\n </div>\n </div>\n </div>\n\n <!-- Radius -->\n <div class=\"section\">\n <h2 class=\"section-title\">Border Radius</h2>\n <div class=\"radius-grid\">\n <div style=\"text-align:center\"><div class=\"radius-demo\" style=\"border-radius:0\">0</div><div style=\"font-size:10px;margin-top:4px;color:var(--muted-fg)\">none</div></div>\n <div style=\"text-align:center\"><div class=\"radius-demo\" style=\"border-radius:${radiusPx}\">${radiusPx}</div><div style=\"font-size:10px;margin-top:4px;color:var(--muted-fg)\">base</div></div>\n <div style=\"text-align:center\"><div class=\"radius-demo\" style=\"border-radius:${parseInt(radiusPx) * 2}px\">${parseInt(radiusPx) * 2}px</div><div style=\"font-size:10px;margin-top:4px;color:var(--muted-fg)\">lg</div></div>\n <div style=\"text-align:center\"><div class=\"radius-demo\" style=\"border-radius:9999px\">pill</div><div style=\"font-size:10px;margin-top:4px;color:var(--muted-fg)\">full</div></div>\n </div>\n </div>\n\n <!-- Components -->\n <div class=\"section\">\n <h2 class=\"section-title\">Components</h2>\n\n <!-- Buttons -->\n <div class=\"comp-card\">\n <h3>Buttons</h3>\n <div class=\"comp-row\">\n <button class=\"btn btn-primary\">Primary</button>\n <button class=\"btn btn-secondary\">Secondary</button>\n <button class=\"btn btn-outline\">Outline</button>\n <button class=\"btn btn-ghost\">Ghost</button>\n <button class=\"btn btn-destructive\">Delete</button>\n </div>\n </div>\n\n <!-- Badges -->\n <div class=\"comp-card\">\n <h3>Badges</h3>\n <div class=\"comp-row\">\n <span class=\"badge badge-primary\">Active</span>\n <span class=\"badge badge-secondary\">Draft</span>\n <span class=\"badge badge-outline\">Archived</span>\n </div>\n </div>\n\n <!-- Input -->\n <div class=\"comp-card\">\n <h3>Input</h3>\n <div style=\"display:flex;flex-direction:column;gap:12px;max-width:400px;\">\n <div>\n <label style=\"font-size:0.8125rem;font-weight:500;display:block;margin-bottom:4px;\">Email</label>\n <input class=\"input-demo\" type=\"email\" placeholder=\"you@example.com\">\n </div>\n <div>\n <label style=\"font-size:0.8125rem;font-weight:500;display:block;margin-bottom:4px;\">Password</label>\n <input class=\"input-demo\" type=\"password\" placeholder=\"••••••••\">\n </div>\n </div>\n </div>\n\n <!-- Card -->\n <div class=\"comp-card\">\n <h3>Card</h3>\n <div class=\"comp-row\" style=\"align-items:stretch;\">\n <div class=\"demo-card\">\n <h4>Project Overview</h4>\n <p>A summary card showing key metrics and status for your project.</p>\n <button class=\"btn btn-primary\" style=\"height:32px;font-size:0.75rem;\">View Details</button>\n </div>\n </div>\n </div>\n\n <!-- Table -->\n <div class=\"comp-card\">\n <h3>Table</h3>\n <div style=\"overflow-x:auto;\">\n <table class=\"demo-table\">\n <thead><tr><th>Name</th><th>Status</th><th>Role</th><th>Email</th></tr></thead>\n <tbody>\n <tr><td>Kim Minjae</td><td><span class=\"badge badge-primary\" style=\"font-size:10px;\">Active</span></td><td>Developer</td><td>minjae@example.com</td></tr>\n <tr><td>Lee Soyeon</td><td><span class=\"badge badge-secondary\" style=\"font-size:10px;\">Pending</span></td><td>Designer</td><td>soyeon@example.com</td></tr>\n <tr><td>Park Jiwoo</td><td><span class=\"badge badge-outline\" style=\"font-size:10px;\">Inactive</span></td><td>PM</td><td>jiwoo@example.com</td></tr>\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Dialog -->\n <div class=\"comp-card\">\n <h3>Dialog</h3>\n <div class=\"demo-dialog\">\n <h4>Delete item?</h4>\n <p>This action cannot be undone.</p>\n <div class=\"acts\">\n <button class=\"btn btn-outline\" style=\"height:32px;\">Cancel</button>\n <button class=\"btn btn-destructive\" style=\"height:32px;\">Delete</button>\n </div>\n </div>\n </div>\n\n <!-- Tabs -->\n <div class=\"comp-card\">\n <h3>Tabs</h3>\n <div class=\"tabs\">\n <button class=\"tab active\">Overview</button>\n <button class=\"tab\">Analytics</button>\n <button class=\"tab\">Settings</button>\n </div>\n </div>\n </div>\n\n <!-- shadcn CSS -->\n <div class=\"section\">\n <h2 class=\"section-title\">shadcn/ui CSS Variables</h2>\n <div class=\"section-sub\">Ready to paste into globals.css</div>\n <div class=\"css-block\">\n <button class=\"ctrl-btn copy-css\" onclick=\"copyCss()\" style=\"position:absolute;top:8px;right:8px;\">Copy</button>\n <pre id=\"css-output\">${escHtml(shadcnCss)}</pre>\n </div>\n </div>\n\n</div>\n\n<div class=\"toast-popup\" id=\"toast\">Copied!</div>\n\n<script>\nlet isDark = false;\nfunction toggleTheme() {\n isDark = !isDark;\n document.body.classList.toggle('dark', isDark);\n const btn = document.getElementById('theme-btn');\n if (btn) btn.textContent = isDark ? '☀️ Light' : '🌙 Dark';\n}\nfunction showToast(msg) {\n const el = document.getElementById('toast');\n el.textContent = msg;\n el.classList.add('show');\n setTimeout(() => el.classList.remove('show'), 1800);\n}\nfunction copy(val) {\n navigator.clipboard.writeText(val).then(() => showToast('Copied: ' + val));\n}\nfunction copyCss() {\n const css = document.getElementById('css-output').textContent;\n navigator.clipboard.writeText(css).then(() => showToast('CSS variables copied!'));\n}\ndocument.querySelectorAll('.tab').forEach(t => {\n t.addEventListener('click', () => {\n t.parentElement.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));\n t.classList.add('active');\n });\n});\n</script>\n</body>\n</html>`;\n}\n\nfunction isLight(hex: string): boolean {\n const h = hex.replace('#', '');\n const r = parseInt(h.slice(0, 2), 16);\n const g = parseInt(h.slice(2, 4), 16);\n const b = parseInt(h.slice(4, 6), 16);\n return (r * 299 + g * 587 + b * 114) / 1000 > 140;\n}\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction escHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n"],"mappings":"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","names":["p","writeFileSync","resolve","loadReference","applyOverrides","existsSync"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/agent-detect.ts
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
function detectCallingAgent() {
|
|
7
|
+
const env = process.env;
|
|
8
|
+
if (env.CLAUDECODE === "1" || env.CLAUDE_CODE === "1" || env.CLAUDE_CODE_TASK_ID) {
|
|
9
|
+
return "claude-code";
|
|
10
|
+
}
|
|
11
|
+
if (env.CODEX_SESSION_ID || env.CODEX || env.OPENAI_CODEX) {
|
|
12
|
+
return "codex";
|
|
13
|
+
}
|
|
14
|
+
if (env.OPENCODE || env.OPENCODE_SESSION) {
|
|
15
|
+
return "opencode";
|
|
16
|
+
}
|
|
17
|
+
if (env.CURSOR_SESSION_ID || env.CURSOR_AGENT) {
|
|
18
|
+
return "cursor";
|
|
19
|
+
}
|
|
20
|
+
return "unknown";
|
|
21
|
+
}
|
|
22
|
+
function detectInstalledAgents(projectRoot) {
|
|
23
|
+
return {
|
|
24
|
+
claudeCode: existsSync(join(projectRoot, ".claude")) || existsSync(join(projectRoot, "CLAUDE.md")),
|
|
25
|
+
codex: existsSync(join(projectRoot, ".codex")) || existsSync(join(projectRoot, "AGENTS.md")) || existsSync(join(projectRoot, "AGENTS.override.md")),
|
|
26
|
+
opencode: existsSync(join(projectRoot, ".opencode")) || existsSync(join(projectRoot, "opencode.json")) || existsSync(join(projectRoot, "opencode.jsonc")),
|
|
27
|
+
cursor: existsSync(join(projectRoot, ".cursor")) || existsSync(join(projectRoot, ".cursorrules"))
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
detectCallingAgent,
|
|
33
|
+
detectInstalledAgents
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=chunk-6YNSV3VY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/agent-detect.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type AgentId = 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'unknown';\n\nexport function detectCallingAgent(): AgentId {\n const env = process.env;\n\n if (env.CLAUDECODE === '1' || env.CLAUDE_CODE === '1' || env.CLAUDE_CODE_TASK_ID) {\n return 'claude-code';\n }\n if (env.CODEX_SESSION_ID || env.CODEX || env.OPENAI_CODEX) {\n return 'codex';\n }\n if (env.OPENCODE || env.OPENCODE_SESSION) {\n return 'opencode';\n }\n if (env.CURSOR_SESSION_ID || env.CURSOR_AGENT) {\n return 'cursor';\n }\n\n return 'unknown';\n}\n\nexport interface AgentPresence {\n claudeCode: boolean;\n codex: boolean;\n opencode: boolean;\n cursor: boolean;\n}\n\nexport function detectInstalledAgents(projectRoot: string): AgentPresence {\n return {\n claudeCode:\n existsSync(join(projectRoot, '.claude')) ||\n existsSync(join(projectRoot, 'CLAUDE.md')),\n codex:\n existsSync(join(projectRoot, '.codex')) ||\n existsSync(join(projectRoot, 'AGENTS.md')) ||\n existsSync(join(projectRoot, 'AGENTS.override.md')),\n opencode:\n existsSync(join(projectRoot, '.opencode')) ||\n existsSync(join(projectRoot, 'opencode.json')) ||\n existsSync(join(projectRoot, 'opencode.jsonc')),\n cursor:\n existsSync(join(projectRoot, '.cursor')) ||\n existsSync(join(projectRoot, '.cursorrules')),\n };\n}\n"],"mappings":";;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAId,SAAS,qBAA8B;AAC5C,QAAM,MAAM,QAAQ;AAEpB,MAAI,IAAI,eAAe,OAAO,IAAI,gBAAgB,OAAO,IAAI,qBAAqB;AAChF,WAAO;AAAA,EACT;AACA,MAAI,IAAI,oBAAoB,IAAI,SAAS,IAAI,cAAc;AACzD,WAAO;AAAA,EACT;AACA,MAAI,IAAI,YAAY,IAAI,kBAAkB;AACxC,WAAO;AAAA,EACT;AACA,MAAI,IAAI,qBAAqB,IAAI,cAAc;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AASO,SAAS,sBAAsB,aAAoC;AACxE,SAAO;AAAA,IACL,YACE,WAAW,KAAK,aAAa,SAAS,CAAC,KACvC,WAAW,KAAK,aAAa,WAAW,CAAC;AAAA,IAC3C,OACE,WAAW,KAAK,aAAa,QAAQ,CAAC,KACtC,WAAW,KAAK,aAAa,WAAW,CAAC,KACzC,WAAW,KAAK,aAAa,oBAAoB,CAAC;AAAA,IACpD,UACE,WAAW,KAAK,aAAa,WAAW,CAAC,KACzC,WAAW,KAAK,aAAa,eAAe,CAAC,KAC7C,WAAW,KAAK,aAAa,gBAAgB,CAAC;AAAA,IAChD,QACE,WAAW,KAAK,aAAa,SAAS,CAAC,KACvC,WAAW,KAAK,aAAa,cAAc,CAAC;AAAA,EAChD;AACF;","names":[]}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/color.ts
|
|
4
|
+
function hexToRgb(hex) {
|
|
5
|
+
const h = hex.replace("#", "");
|
|
6
|
+
return [
|
|
7
|
+
parseInt(h.slice(0, 2), 16),
|
|
8
|
+
parseInt(h.slice(2, 4), 16),
|
|
9
|
+
parseInt(h.slice(4, 6), 16)
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
function rgbToHex(r, g, b) {
|
|
13
|
+
return "#" + [r, g, b].map((v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0")).join("");
|
|
14
|
+
}
|
|
15
|
+
function hexToHsl(hex) {
|
|
16
|
+
const [r, g, b] = hexToRgb(hex).map((v) => v / 255);
|
|
17
|
+
const max = Math.max(r, g, b);
|
|
18
|
+
const min = Math.min(r, g, b);
|
|
19
|
+
const l = (max + min) / 2;
|
|
20
|
+
let h = 0;
|
|
21
|
+
let s = 0;
|
|
22
|
+
if (max !== min) {
|
|
23
|
+
const d = max - min;
|
|
24
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
25
|
+
switch (max) {
|
|
26
|
+
case r:
|
|
27
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
28
|
+
break;
|
|
29
|
+
case g:
|
|
30
|
+
h = ((b - r) / d + 2) / 6;
|
|
31
|
+
break;
|
|
32
|
+
case b:
|
|
33
|
+
h = ((r - g) / d + 4) / 6;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
|
|
38
|
+
}
|
|
39
|
+
function hslToHex(h, s, l) {
|
|
40
|
+
const sn = s / 100;
|
|
41
|
+
const ln = l / 100;
|
|
42
|
+
const a = sn * Math.min(ln, 1 - ln);
|
|
43
|
+
const f = (n) => {
|
|
44
|
+
const k = (n + h / 30) % 12;
|
|
45
|
+
const color = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
46
|
+
return Math.round(255 * color);
|
|
47
|
+
};
|
|
48
|
+
return rgbToHex(f(0), f(8), f(4));
|
|
49
|
+
}
|
|
50
|
+
function hslString(hex) {
|
|
51
|
+
const [h, s, l] = hexToHsl(hex);
|
|
52
|
+
return `${h} ${s}% ${l}%`;
|
|
53
|
+
}
|
|
54
|
+
function generateColorScale(hex) {
|
|
55
|
+
const [h, s] = hexToHsl(hex);
|
|
56
|
+
const lightnesses = {
|
|
57
|
+
50: 97,
|
|
58
|
+
100: 94,
|
|
59
|
+
200: 86,
|
|
60
|
+
300: 77,
|
|
61
|
+
400: 66,
|
|
62
|
+
500: 55,
|
|
63
|
+
600: 47,
|
|
64
|
+
700: 39,
|
|
65
|
+
800: 32,
|
|
66
|
+
900: 24,
|
|
67
|
+
950: 14
|
|
68
|
+
};
|
|
69
|
+
const scale = {};
|
|
70
|
+
for (const [key, l] of Object.entries(lightnesses)) {
|
|
71
|
+
scale[key] = hslToHex(h, s, l);
|
|
72
|
+
}
|
|
73
|
+
return scale;
|
|
74
|
+
}
|
|
75
|
+
function isLight(hex) {
|
|
76
|
+
const [, , l] = hexToHsl(hex);
|
|
77
|
+
return l > 55;
|
|
78
|
+
}
|
|
79
|
+
function contrastForeground(bgHex) {
|
|
80
|
+
return isLight(bgHex) ? "#09090b" : "#fafafa";
|
|
81
|
+
}
|
|
82
|
+
function lighten(hex, amount) {
|
|
83
|
+
const [h, s, l] = hexToHsl(hex);
|
|
84
|
+
return hslToHex(h, s, Math.min(100, l + amount));
|
|
85
|
+
}
|
|
86
|
+
function darken(hex, amount) {
|
|
87
|
+
const [h, s, l] = hexToHsl(hex);
|
|
88
|
+
return hslToHex(h, s, Math.max(0, l - amount));
|
|
89
|
+
}
|
|
90
|
+
function generateChartColors(primaryHex) {
|
|
91
|
+
const [h, s, l] = hexToHsl(primaryHex);
|
|
92
|
+
return [
|
|
93
|
+
primaryHex,
|
|
94
|
+
hslToHex((h + 40) % 360, s, l),
|
|
95
|
+
hslToHex((h + 80) % 360, s, l),
|
|
96
|
+
hslToHex((h + 160) % 360, s, l),
|
|
97
|
+
hslToHex((h + 220) % 360, s, l)
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/core/customizer.ts
|
|
102
|
+
function applyOverrides(ref, overrides, mode, components) {
|
|
103
|
+
let md = ref.designMd;
|
|
104
|
+
const effectivePrimary = overrides.primaryColor || ref.colors.primary;
|
|
105
|
+
const effectiveFont = overrides.fontFamily || ref.typography.primary;
|
|
106
|
+
const effectiveWeight = overrides.headingWeight || ref.typography.headingWeight;
|
|
107
|
+
const effectiveRadius = overrides.borderRadius || ref.radius.replace(/[-–].*/, "").trim();
|
|
108
|
+
const effectiveBg = ref.colors.background;
|
|
109
|
+
const effectiveFg = ref.colors.foreground;
|
|
110
|
+
md = md.replace(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1FA00}-\u{1FAFF}\u{200D}\u{20E3}\u{E0020}-\u{E007F}]/gu, "");
|
|
111
|
+
if (mode === "customized") {
|
|
112
|
+
md = md.replace(/^# .+$/m, `# Custom Design System (based on ${ref.name})`);
|
|
113
|
+
if (overrides.primaryColor && overrides.primaryColor !== ref.colors.primary) {
|
|
114
|
+
const re = new RegExp(ref.colors.primary.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
115
|
+
md = re[Symbol.replace](md, overrides.primaryColor);
|
|
116
|
+
}
|
|
117
|
+
if (overrides.fontFamily && overrides.fontFamily !== ref.typography.primary) {
|
|
118
|
+
md = md.replaceAll(ref.typography.primary, overrides.fontFamily);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (components && components.length > 0) {
|
|
122
|
+
md += `
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Included Components
|
|
127
|
+
|
|
128
|
+
The following components are part of this design system:
|
|
129
|
+
|
|
130
|
+
`;
|
|
131
|
+
md += components.map((c) => `- ${c.charAt(0).toUpperCase() + c.slice(1).replace(/-/g, " ")}`).join("\n");
|
|
132
|
+
md += "\n";
|
|
133
|
+
}
|
|
134
|
+
md += buildIconographySection();
|
|
135
|
+
const shadcnCss = generateShadcnCss(effectivePrimary, effectiveBg, effectiveFg, effectiveRadius, ref, overrides);
|
|
136
|
+
md += buildDocumentPolicies();
|
|
137
|
+
const previewData = buildPreviewData(ref, overrides, effectivePrimary, effectiveBg, effectiveFg, effectiveFont, effectiveWeight, effectiveRadius);
|
|
138
|
+
return { designMd: md, shadcnCss, previewData };
|
|
139
|
+
}
|
|
140
|
+
function generateShadcnCss(primary, background, foreground, radius, ref, overrides) {
|
|
141
|
+
const scale = generateColorScale(primary);
|
|
142
|
+
const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);
|
|
143
|
+
const border = ref.colors.border || lighten(foreground, 75);
|
|
144
|
+
const muted = lighten(background === "#ffffff" ? "#f5f5f5" : background, 5);
|
|
145
|
+
const destructive = "#ef4444";
|
|
146
|
+
const chart = generateChartColors(primary);
|
|
147
|
+
const radiusRem = radius === "9999px" ? "9999px" : `${parseInt(radius) / 16}rem`;
|
|
148
|
+
const vars = {
|
|
149
|
+
"--background": hslString(background),
|
|
150
|
+
"--foreground": hslString(foreground),
|
|
151
|
+
"--card": hslString(background === "#ffffff" ? "#ffffff" : lighten(background, 3)),
|
|
152
|
+
"--card-foreground": hslString(foreground),
|
|
153
|
+
"--popover": hslString(background === "#ffffff" ? "#ffffff" : lighten(background, 5)),
|
|
154
|
+
"--popover-foreground": hslString(foreground),
|
|
155
|
+
"--primary": hslString(primary),
|
|
156
|
+
"--primary-foreground": hslString(contrastForeground(primary)),
|
|
157
|
+
"--secondary": hslString(scale[100]),
|
|
158
|
+
"--secondary-foreground": hslString(foreground),
|
|
159
|
+
"--muted": hslString(muted),
|
|
160
|
+
"--muted-foreground": hslString(lighten(foreground, 40)),
|
|
161
|
+
"--accent": hslString(accent),
|
|
162
|
+
"--accent-foreground": hslString(contrastForeground(accent)),
|
|
163
|
+
"--destructive": hslString(destructive),
|
|
164
|
+
"--destructive-foreground": hslString(contrastForeground(destructive)),
|
|
165
|
+
"--border": hslString(border),
|
|
166
|
+
"--input": hslString(border),
|
|
167
|
+
"--ring": hslString(primary),
|
|
168
|
+
"--radius": radiusRem,
|
|
169
|
+
"--chart-1": hslString(chart[0]),
|
|
170
|
+
"--chart-2": hslString(chart[1]),
|
|
171
|
+
"--chart-3": hslString(chart[2]),
|
|
172
|
+
"--chart-4": hslString(chart[3]),
|
|
173
|
+
"--chart-5": hslString(chart[4])
|
|
174
|
+
};
|
|
175
|
+
const lines = ["@layer base {", " :root {"];
|
|
176
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
177
|
+
lines.push(` ${k}: ${v};`);
|
|
178
|
+
}
|
|
179
|
+
lines.push(" }");
|
|
180
|
+
if (overrides.darkMode) {
|
|
181
|
+
const darkBg = hslToHex(hexToHsl(primary)[0], 15, 7);
|
|
182
|
+
const darkFg = "#fafafa";
|
|
183
|
+
const darkBorder = hslToHex(hexToHsl(primary)[0], 10, 18);
|
|
184
|
+
const darkMuted = hslToHex(hexToHsl(primary)[0], 10, 15);
|
|
185
|
+
lines.push("", " .dark {");
|
|
186
|
+
const darkVars = {
|
|
187
|
+
"--background": hslString(darkBg),
|
|
188
|
+
"--foreground": hslString(darkFg),
|
|
189
|
+
"--card": hslString(lighten(darkBg, 3)),
|
|
190
|
+
"--card-foreground": hslString(darkFg),
|
|
191
|
+
"--popover": hslString(lighten(darkBg, 5)),
|
|
192
|
+
"--popover-foreground": hslString(darkFg),
|
|
193
|
+
"--primary": hslString(primary),
|
|
194
|
+
"--primary-foreground": hslString(contrastForeground(primary)),
|
|
195
|
+
"--secondary": hslString(hslToHex(hexToHsl(primary)[0], 15, 20)),
|
|
196
|
+
"--secondary-foreground": hslString(darkFg),
|
|
197
|
+
"--muted": hslString(darkMuted),
|
|
198
|
+
"--muted-foreground": hslString(darken(darkFg, 35)),
|
|
199
|
+
"--accent": hslString(accent),
|
|
200
|
+
"--accent-foreground": hslString(contrastForeground(accent)),
|
|
201
|
+
"--destructive": hslString(destructive),
|
|
202
|
+
"--destructive-foreground": hslString(contrastForeground(destructive)),
|
|
203
|
+
"--border": hslString(darkBorder),
|
|
204
|
+
"--input": hslString(lighten(darkBorder, 5)),
|
|
205
|
+
"--ring": hslString(primary),
|
|
206
|
+
"--chart-1": hslString(chart[0]),
|
|
207
|
+
"--chart-2": hslString(chart[1]),
|
|
208
|
+
"--chart-3": hslString(chart[2]),
|
|
209
|
+
"--chart-4": hslString(chart[3]),
|
|
210
|
+
"--chart-5": hslString(chart[4])
|
|
211
|
+
};
|
|
212
|
+
for (const [k, v] of Object.entries(darkVars)) {
|
|
213
|
+
lines.push(` ${k}: ${v};`);
|
|
214
|
+
}
|
|
215
|
+
lines.push(" }");
|
|
216
|
+
}
|
|
217
|
+
lines.push("}");
|
|
218
|
+
return lines.join("\n");
|
|
219
|
+
}
|
|
220
|
+
function buildPreviewData(ref, overrides, primary, background, foreground, font, headingWeight, radius) {
|
|
221
|
+
const scale = generateColorScale(primary);
|
|
222
|
+
const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);
|
|
223
|
+
const border = ref.colors.border || lighten(foreground, 75);
|
|
224
|
+
const chart = generateChartColors(primary);
|
|
225
|
+
return {
|
|
226
|
+
name: overrides.primaryColor || overrides.fontFamily ? `Custom (based on ${ref.name})` : ref.name,
|
|
227
|
+
basedOn: ref.name,
|
|
228
|
+
primary,
|
|
229
|
+
background,
|
|
230
|
+
foreground,
|
|
231
|
+
font,
|
|
232
|
+
headingWeight,
|
|
233
|
+
radius,
|
|
234
|
+
shadcnCss: "",
|
|
235
|
+
// filled later
|
|
236
|
+
designMd: "",
|
|
237
|
+
// filled later
|
|
238
|
+
colors: {
|
|
239
|
+
primary,
|
|
240
|
+
accent,
|
|
241
|
+
muted: lighten(background === "#ffffff" ? "#f5f5f5" : background, 5),
|
|
242
|
+
destructive: "#ef4444",
|
|
243
|
+
border,
|
|
244
|
+
scale,
|
|
245
|
+
chart
|
|
246
|
+
},
|
|
247
|
+
darkMode: overrides.darkMode
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function buildIconographySection() {
|
|
251
|
+
return `
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Iconography & SVG Guidelines
|
|
256
|
+
|
|
257
|
+
### Icon Library
|
|
258
|
+
|
|
259
|
+
Use a single, consistent icon library throughout the project. Recommended options:
|
|
260
|
+
|
|
261
|
+
- **Lucide React** (\`lucide-react\`): Default for shadcn/ui projects. 1,400+ icons, tree-shakeable, consistent 24x24 grid.
|
|
262
|
+
- **Radix Icons** (\`@radix-ui/react-icons\`): 300+ icons, 15x15 grid, minimal and geometric.
|
|
263
|
+
- **Heroicons** (\`@heroicons/react\`): 300+ icons by Tailwind team, outline and solid variants.
|
|
264
|
+
|
|
265
|
+
Pick ONE library and use it everywhere. Do not mix icon libraries within the same project.
|
|
266
|
+
|
|
267
|
+
### SVG Usage Rules
|
|
268
|
+
|
|
269
|
+
- All icons must be inline SVG components (not \`<img>\` tags) for color and size control.
|
|
270
|
+
- Icon size follows the type scale: 16px (inline), 20px (buttons), 24px (standalone).
|
|
271
|
+
- Icon color inherits from \`currentColor\` -- never hard-code fill/stroke colors.
|
|
272
|
+
- For custom/brand icons, export as SVG components with \`currentColor\` fills.
|
|
273
|
+
- Stroke width: 1.5px-2px for outline icons. Keep consistent across the project.
|
|
274
|
+
|
|
275
|
+
### Icon Sizing Scale
|
|
276
|
+
|
|
277
|
+
| Context | Size | Usage |
|
|
278
|
+
|---------|------|-------|
|
|
279
|
+
| Inline text | 16px (1rem) | Badges, labels, breadcrumbs |
|
|
280
|
+
| Button icon | 18px (1.125rem) | Icon buttons, CTA icons |
|
|
281
|
+
| Standalone | 24px (1.5rem) | Navigation, card icons |
|
|
282
|
+
| Feature | 32-48px | Hero sections, empty states |
|
|
283
|
+
|
|
284
|
+
### SVG Optimization
|
|
285
|
+
|
|
286
|
+
- Run all custom SVGs through SVGO before committing.
|
|
287
|
+
- Remove unnecessary attributes: \`xmlns\`, \`xml:space\`, editor metadata.
|
|
288
|
+
- Use \`viewBox\` instead of fixed \`width\`/\`height\` for scalability.
|
|
289
|
+
`;
|
|
290
|
+
}
|
|
291
|
+
function buildDocumentPolicies() {
|
|
292
|
+
return `
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Document Policies
|
|
297
|
+
|
|
298
|
+
### No Emojis
|
|
299
|
+
|
|
300
|
+
This design system must not use emojis in any UI element, component, label, status indicator, or documentation.
|
|
301
|
+
Use SVG icons from the chosen icon library instead. Emojis render inconsistently across platforms and break visual coherence.
|
|
302
|
+
|
|
303
|
+
- Status indicators: use colored dots or icon components, not emoji.
|
|
304
|
+
- Section markers: use text prefixes ("DO:" / "DON'T:") or icons, not checkmark/cross emojis.
|
|
305
|
+
- Navigation: use icon components, not emoji.
|
|
306
|
+
|
|
307
|
+
### Format Compliance
|
|
308
|
+
|
|
309
|
+
This document follows the Google Stitch DESIGN.md 9-section format:
|
|
310
|
+
1. Visual Theme & Atmosphere
|
|
311
|
+
2. Color Palette & Roles
|
|
312
|
+
3. Typography Rules
|
|
313
|
+
4. Component Stylings
|
|
314
|
+
5. Layout Principles
|
|
315
|
+
6. Depth & Elevation
|
|
316
|
+
7. Do's and Don'ts
|
|
317
|
+
8. Responsive Behavior
|
|
318
|
+
9. Agent Prompt Guide
|
|
319
|
+
|
|
320
|
+
Extended with:
|
|
321
|
+
- Iconography & SVG Guidelines
|
|
322
|
+
- Document Policies
|
|
323
|
+
|
|
324
|
+
Total target length: 250-400 lines. Keep sections concise and actionable.
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export {
|
|
329
|
+
hexToHsl,
|
|
330
|
+
hslToHex,
|
|
331
|
+
generateColorScale,
|
|
332
|
+
contrastForeground,
|
|
333
|
+
lighten,
|
|
334
|
+
darken,
|
|
335
|
+
applyOverrides
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=chunk-MHFYGZSO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/color.ts","../src/core/customizer.ts"],"sourcesContent":["import type { ColorScale, SemanticColor } from '../core/types.js';\n\n// ── Hex ↔ HSL conversions ────────────────────────────────────────\n\nexport function hexToRgb(hex: string): [number, number, number] {\n const h = hex.replace('#', '');\n return [\n parseInt(h.slice(0, 2), 16),\n parseInt(h.slice(2, 4), 16),\n parseInt(h.slice(4, 6), 16),\n ];\n}\n\nexport function rgbToHex(r: number, g: number, b: number): string {\n return (\n '#' +\n [r, g, b]\n .map((v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nexport function hexToHsl(hex: string): [number, number, number] {\n const [r, g, b] = hexToRgb(hex).map((v) => v / 255);\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h = 0;\n let s = 0;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;\n case g: h = ((b - r) / d + 2) / 6; break;\n case b: h = ((r - g) / d + 4) / 6; break;\n }\n }\n\n return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];\n}\n\nexport function hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100;\n const ln = l / 100;\n const a = sn * Math.min(ln, 1 - ln);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n const color = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n return Math.round(255 * color);\n };\n return rgbToHex(f(0), f(8), f(4));\n}\n\n/** Format HSL for shadcn CSS variables: \"210 40% 98%\" */\nexport function hslString(hex: string): string {\n const [h, s, l] = hexToHsl(hex);\n return `${h} ${s}% ${l}%`;\n}\n\n// ── Palette generation ───────────────────────────────────────────\n\n/** Generate a full 11-stop color scale from a single hex */\nexport function generateColorScale(hex: string): ColorScale {\n const [h, s] = hexToHsl(hex);\n\n const lightnesses: Record<keyof ColorScale, number> = {\n 50: 97, 100: 94, 200: 86, 300: 77,\n 400: 66, 500: 55, 600: 47, 700: 39,\n 800: 32, 900: 24, 950: 14,\n };\n\n const scale = {} as ColorScale;\n for (const [key, l] of Object.entries(lightnesses)) {\n (scale as unknown as Record<string, string>)[key] = hslToHex(h, s, l);\n }\n return scale;\n}\n\n/** Determine if a color is \"light\" (needs dark foreground) */\nexport function isLight(hex: string): boolean {\n const [, , l] = hexToHsl(hex);\n return l > 55;\n}\n\n/** Pick a contrasting foreground for a given background */\nexport function contrastForeground(bgHex: string): string {\n return isLight(bgHex) ? '#09090b' : '#fafafa';\n}\n\n/** Create a semantic color pair (base + auto-contrast foreground) */\nexport function semanticColor(base: string): SemanticColor {\n return { base, foreground: contrastForeground(base) };\n}\n\n/** Lighten a hex color by a percentage (0-100) */\nexport function lighten(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, s, Math.min(100, l + amount));\n}\n\n/** Darken a hex color by a percentage (0-100) */\nexport function darken(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, s, Math.max(0, l - amount));\n}\n\n/** Desaturate a color */\nexport function desaturate(hex: string, amount: number): string {\n const [h, s, l] = hexToHsl(hex);\n return hslToHex(h, Math.max(0, s - amount), l);\n}\n\n/** Generate chart colors from primary by rotating hue */\nexport function generateChartColors(primaryHex: string): [string, string, string, string, string] {\n const [h, s, l] = hexToHsl(primaryHex);\n return [\n primaryHex,\n hslToHex((h + 40) % 360, s, l),\n hslToHex((h + 80) % 360, s, l),\n hslToHex((h + 160) % 360, s, l),\n hslToHex((h + 220) % 360, s, l),\n ];\n}\n","import type { ReferenceEntry } from './reference-parser.js';\nimport type { CustomOverrides } from '../cli/prompts.js';\nimport {\n generateColorScale,\n contrastForeground,\n hslString,\n hexToHsl,\n hslToHex,\n lighten,\n darken,\n generateChartColors,\n} from '../utils/color.js';\n\n/**\n * Apply user overrides to a reference DESIGN.md.\n *\n * Strategy:\n * - \"as-is\": return the original DESIGN.md content with minimal additions\n * - \"customized\": perform text-level replacements for color/font/radius/weight\n * and append a customization summary + shadcn CSS variables block\n *\n * This is intentionally NOT an AI call. It's deterministic string transformation.\n */\nexport function applyOverrides(\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n mode: 'as-is' | 'customized',\n components?: string[],\n): { designMd: string; shadcnCss: string; previewData: PreviewData } {\n let md = ref.designMd;\n\n const effectivePrimary = overrides.primaryColor || ref.colors.primary;\n const effectiveFont = overrides.fontFamily || ref.typography.primary;\n const effectiveWeight = overrides.headingWeight || ref.typography.headingWeight;\n const effectiveRadius = overrides.borderRadius || ref.radius.replace(/[-–].*/, '').trim();\n const effectiveBg = ref.colors.background;\n const effectiveFg = ref.colors.foreground;\n\n // Strip emojis. The unicode range covers ✅ (U+2705) and ❌ (U+274C) too,\n // so any DO:/DON'T: prefix conversion would never match — references use\n // explicit \"**DO**\" / \"**DON'T**\" markdown instead.\n md = md.replace(/[\\u{1F300}-\\u{1F9FF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}\\u{FE00}-\\u{FE0F}\\u{1FA00}-\\u{1FAFF}\\u{200D}\\u{20E3}\\u{E0020}-\\u{E007F}]/gu, '');\n\n if (mode === 'customized') {\n // Direct replacement — one source of truth for AI agents\n md = md.replace(/^# .+$/m, `# Custom Design System (based on ${ref.name})`);\n\n if (overrides.primaryColor && overrides.primaryColor !== ref.colors.primary) {\n const re = new RegExp(ref.colors.primary.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi');\n md = re[Symbol.replace](md, overrides.primaryColor);\n }\n if (overrides.fontFamily && overrides.fontFamily !== ref.typography.primary) {\n md = md.replaceAll(ref.typography.primary, overrides.fontFamily);\n }\n }\n\n // Append component list\n if (components && components.length > 0) {\n md += `\\n\\n---\\n\\n## Included Components\\n\\nThe following components are part of this design system:\\n\\n`;\n md += components.map(c => `- ${c.charAt(0).toUpperCase() + c.slice(1).replace(/-/g, ' ')}`).join('\\n');\n md += '\\n';\n }\n\n // Append iconography section\n md += buildIconographySection();\n\n // Generate shadcn CSS for preview data only (no longer appended to DESIGN.md)\n const shadcnCss = generateShadcnCss(effectivePrimary, effectiveBg, effectiveFg, effectiveRadius, ref, overrides);\n\n // Append document policies\n md += buildDocumentPolicies();\n\n // Build preview data\n const previewData = buildPreviewData(ref, overrides, effectivePrimary, effectiveBg, effectiveFg, effectiveFont, effectiveWeight, effectiveRadius);\n\n return { designMd: md, shadcnCss, previewData };\n}\n\n// ── Text replacements ────────────────────────────────────────────\n\nfunction replaceColor(md: string, oldHex: string, newHex: string): string {\n // Replace the exact hex (case-insensitive)\n const regex = new RegExp(escapeRegex(oldHex), 'gi');\n return md.replace(regex, newHex);\n}\n\nfunction replaceFont(md: string, oldFont: string, newFont: string): string {\n const regex = new RegExp(escapeRegex(oldFont), 'g');\n return md.replace(regex, newFont);\n}\n\nfunction replaceWeight(md: string, oldWeight: string, newWeight: string): string {\n // Only replace weight in Display/Heading rows and key characteristics\n // Be careful not to replace all numbers\n const regex = new RegExp(`(Display.*?\\\\|\\\\s*)${oldWeight}(\\\\s*\\\\|)`, 'g');\n let result = md.replace(regex, `$1${newWeight}$2`);\n // Also replace \"weight X\" patterns\n result = result.replace(\n new RegExp(`weight ${oldWeight}`, 'g'),\n `weight ${newWeight}`,\n );\n return result;\n}\n\nfunction replaceRadius(md: string, oldRadius: string, newRadius: string): string {\n // Replace \"Xpx\" radius patterns\n const oldBase = oldRadius.replace(/[-–].*/, '').trim();\n if (oldBase === newRadius) return md;\n const regex = new RegExp(`${escapeRegex(oldBase)}`, 'g');\n return md.replace(regex, newRadius);\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ── Customization summary section ────────────────────────────────\n\nfunction buildCustomizationSummary(ref: ReferenceEntry, overrides: CustomOverrides): string {\n const changes: string[] = [];\n if (overrides.primaryColor) {\n changes.push(`- **Primary color**: ${ref.colors.primary} → ${overrides.primaryColor}`);\n }\n if (overrides.fontFamily) {\n changes.push(`- **Font**: ${ref.typography.primary} → ${overrides.fontFamily}`);\n }\n if (overrides.headingWeight) {\n changes.push(`- **Heading weight**: ${ref.typography.headingWeight} → ${overrides.headingWeight}`);\n }\n if (overrides.borderRadius) {\n changes.push(`- **Border radius**: ${ref.radius} → ${overrides.borderRadius}`);\n }\n if (overrides.additionalNotes) {\n changes.push(`- **Additional notes**: ${overrides.additionalNotes}`);\n }\n\n if (changes.length === 0) return '';\n\n return `\n\n---\n\n## Customization Applied\n\n> Based on **${ref.name}** design system with the following modifications:\n\n${changes.join('\\n')}\n`;\n}\n\n// ── shadcn CSS generation ────────────────────────────────────────\n\nfunction generateShadcnCss(\n primary: string,\n background: string,\n foreground: string,\n radius: string,\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n): string {\n const scale = generateColorScale(primary);\n const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);\n const border = ref.colors.border || lighten(foreground, 75);\n const muted = lighten(background === '#ffffff' ? '#f5f5f5' : background, 5);\n const destructive = '#ef4444';\n const chart = generateChartColors(primary);\n\n const radiusRem = radius === '9999px' ? '9999px' : `${parseInt(radius) / 16}rem`;\n\n const vars: Record<string, string> = {\n '--background': hslString(background),\n '--foreground': hslString(foreground),\n '--card': hslString(background === '#ffffff' ? '#ffffff' : lighten(background, 3)),\n '--card-foreground': hslString(foreground),\n '--popover': hslString(background === '#ffffff' ? '#ffffff' : lighten(background, 5)),\n '--popover-foreground': hslString(foreground),\n '--primary': hslString(primary),\n '--primary-foreground': hslString(contrastForeground(primary)),\n '--secondary': hslString(scale[100]),\n '--secondary-foreground': hslString(foreground),\n '--muted': hslString(muted),\n '--muted-foreground': hslString(lighten(foreground, 40)),\n '--accent': hslString(accent),\n '--accent-foreground': hslString(contrastForeground(accent)),\n '--destructive': hslString(destructive),\n '--destructive-foreground': hslString(contrastForeground(destructive)),\n '--border': hslString(border),\n '--input': hslString(border),\n '--ring': hslString(primary),\n '--radius': radiusRem,\n '--chart-1': hslString(chart[0]),\n '--chart-2': hslString(chart[1]),\n '--chart-3': hslString(chart[2]),\n '--chart-4': hslString(chart[3]),\n '--chart-5': hslString(chart[4]),\n };\n\n const lines = ['@layer base {', ' :root {'];\n for (const [k, v] of Object.entries(vars)) {\n lines.push(` ${k}: ${v};`);\n }\n lines.push(' }');\n\n // Dark mode\n if (overrides.darkMode) {\n const darkBg = hslToHex(hexToHsl(primary)[0], 15, 7);\n const darkFg = '#fafafa';\n const darkBorder = hslToHex(hexToHsl(primary)[0], 10, 18);\n const darkMuted = hslToHex(hexToHsl(primary)[0], 10, 15);\n\n lines.push('', ' .dark {');\n const darkVars: Record<string, string> = {\n '--background': hslString(darkBg),\n '--foreground': hslString(darkFg),\n '--card': hslString(lighten(darkBg, 3)),\n '--card-foreground': hslString(darkFg),\n '--popover': hslString(lighten(darkBg, 5)),\n '--popover-foreground': hslString(darkFg),\n '--primary': hslString(primary),\n '--primary-foreground': hslString(contrastForeground(primary)),\n '--secondary': hslString(hslToHex(hexToHsl(primary)[0], 15, 20)),\n '--secondary-foreground': hslString(darkFg),\n '--muted': hslString(darkMuted),\n '--muted-foreground': hslString(darken(darkFg, 35)),\n '--accent': hslString(accent),\n '--accent-foreground': hslString(contrastForeground(accent)),\n '--destructive': hslString(destructive),\n '--destructive-foreground': hslString(contrastForeground(destructive)),\n '--border': hslString(darkBorder),\n '--input': hslString(lighten(darkBorder, 5)),\n '--ring': hslString(primary),\n '--chart-1': hslString(chart[0]),\n '--chart-2': hslString(chart[1]),\n '--chart-3': hslString(chart[2]),\n '--chart-4': hslString(chart[3]),\n '--chart-5': hslString(chart[4]),\n };\n for (const [k, v] of Object.entries(darkVars)) {\n lines.push(` ${k}: ${v};`);\n }\n lines.push(' }');\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\nfunction buildShadcnSection(css: string): string {\n return `\n\n---\n\n## 10. shadcn/ui Theme\n\nCopy this CSS block into your \\`globals.css\\` to apply this design system to shadcn/ui components.\n\n\\`\\`\\`css\n${css}\n\\`\\`\\`\n`;\n}\n\n// ── Preview Data ─────────────────────────────────────────────────\n\nexport interface PreviewData {\n name: string;\n basedOn: string;\n primary: string;\n background: string;\n foreground: string;\n font: string;\n headingWeight: string;\n radius: string;\n shadcnCss: string;\n designMd: string;\n colors: {\n primary: string;\n accent: string;\n muted: string;\n destructive: string;\n border: string;\n scale: Record<string, string>;\n chart: string[];\n };\n darkMode: boolean;\n}\n\nfunction buildPreviewData(\n ref: ReferenceEntry,\n overrides: CustomOverrides,\n primary: string,\n background: string,\n foreground: string,\n font: string,\n headingWeight: string,\n radius: string,\n): PreviewData {\n const scale = generateColorScale(primary);\n const accent = ref.colors.accent || hslToHex((hexToHsl(primary)[0] + 30) % 360, 60, 55);\n const border = ref.colors.border || lighten(foreground, 75);\n const chart = generateChartColors(primary);\n\n return {\n name: overrides.primaryColor || overrides.fontFamily ? `Custom (based on ${ref.name})` : ref.name,\n basedOn: ref.name,\n primary,\n background,\n foreground,\n font,\n headingWeight,\n radius,\n shadcnCss: '', // filled later\n designMd: '', // filled later\n colors: {\n primary,\n accent,\n muted: lighten(background === '#ffffff' ? '#f5f5f5' : background, 5),\n destructive: '#ef4444',\n border,\n scale: scale as unknown as Record<string, string>,\n chart,\n },\n darkMode: overrides.darkMode,\n };\n}\n\n// ── Iconography section ──────────────────────────────────────────\n\nfunction buildIconographySection(): string {\n return `\n\n---\n\n## Iconography & SVG Guidelines\n\n### Icon Library\n\nUse a single, consistent icon library throughout the project. Recommended options:\n\n- **Lucide React** (\\`lucide-react\\`): Default for shadcn/ui projects. 1,400+ icons, tree-shakeable, consistent 24x24 grid.\n- **Radix Icons** (\\`@radix-ui/react-icons\\`): 300+ icons, 15x15 grid, minimal and geometric.\n- **Heroicons** (\\`@heroicons/react\\`): 300+ icons by Tailwind team, outline and solid variants.\n\nPick ONE library and use it everywhere. Do not mix icon libraries within the same project.\n\n### SVG Usage Rules\n\n- All icons must be inline SVG components (not \\`<img>\\` tags) for color and size control.\n- Icon size follows the type scale: 16px (inline), 20px (buttons), 24px (standalone).\n- Icon color inherits from \\`currentColor\\` -- never hard-code fill/stroke colors.\n- For custom/brand icons, export as SVG components with \\`currentColor\\` fills.\n- Stroke width: 1.5px-2px for outline icons. Keep consistent across the project.\n\n### Icon Sizing Scale\n\n| Context | Size | Usage |\n|---------|------|-------|\n| Inline text | 16px (1rem) | Badges, labels, breadcrumbs |\n| Button icon | 18px (1.125rem) | Icon buttons, CTA icons |\n| Standalone | 24px (1.5rem) | Navigation, card icons |\n| Feature | 32-48px | Hero sections, empty states |\n\n### SVG Optimization\n\n- Run all custom SVGs through SVGO before committing.\n- Remove unnecessary attributes: \\`xmlns\\`, \\`xml:space\\`, editor metadata.\n- Use \\`viewBox\\` instead of fixed \\`width\\`/\\`height\\` for scalability.\n`;\n}\n\n// ── Document policies ────────────────────────────────────────────\n\nfunction buildDocumentPolicies(): string {\n return `\n\n---\n\n## Document Policies\n\n### No Emojis\n\nThis design system must not use emojis in any UI element, component, label, status indicator, or documentation.\nUse SVG icons from the chosen icon library instead. Emojis render inconsistently across platforms and break visual coherence.\n\n- Status indicators: use colored dots or icon components, not emoji.\n- Section markers: use text prefixes (\"DO:\" / \"DON'T:\") or icons, not checkmark/cross emojis.\n- Navigation: use icon components, not emoji.\n\n### Format Compliance\n\nThis document follows the Google Stitch DESIGN.md 9-section format:\n1. Visual Theme & Atmosphere\n2. Color Palette & Roles\n3. Typography Rules\n4. Component Stylings\n5. Layout Principles\n6. Depth & Elevation\n7. Do's and Don'ts\n8. Responsive Behavior\n9. Agent Prompt Guide\n\nExtended with:\n- Iconography & SVG Guidelines\n- Document Policies\n\nTotal target length: 250-400 lines. Keep sections concise and actionable.\n`;\n}\n"],"mappings":"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","names":[]}
|