@getcoherent/cli 0.6.16 → 0.6.18

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.
@@ -623,36 +623,18 @@ function replaceRawColors(classes, colorMap) {
623
623
  const n = parseInt(shade);
624
624
  const isDestructive = color === "red";
625
625
  if (prefix === "bg") {
626
- if (n >= 500 && n <= 700) {
627
- changed = true;
628
- return statePrefix + (isDestructive ? "bg-destructive" : "bg-primary");
629
- }
630
- if (n >= 100 && n <= 200) {
631
- changed = true;
632
- return statePrefix + (isDestructive ? "bg-destructive/10" : "bg-primary/10");
633
- }
634
- if (n >= 300 && n <= 400) {
635
- changed = true;
636
- return statePrefix + (isDestructive ? "bg-destructive/20" : "bg-primary/20");
637
- }
638
- if (n >= 800) {
639
- changed = true;
640
- return statePrefix + "bg-muted";
641
- }
626
+ changed = true;
627
+ if (n <= 100) return statePrefix + (isDestructive ? "bg-destructive/10" : "bg-primary/10");
628
+ if (n <= 200) return statePrefix + (isDestructive ? "bg-destructive/10" : "bg-primary/10");
629
+ if (n <= 400) return statePrefix + (isDestructive ? "bg-destructive/20" : "bg-primary/20");
630
+ if (n <= 700) return statePrefix + (isDestructive ? "bg-destructive" : "bg-primary");
631
+ return statePrefix + "bg-muted";
642
632
  }
643
633
  if (prefix === "text") {
644
- if (n >= 400 && n <= 600) {
645
- changed = true;
646
- return statePrefix + (isDestructive ? "text-destructive" : "text-primary");
647
- }
648
- if (n >= 100 && n <= 300) {
649
- changed = true;
650
- return statePrefix + "text-foreground";
651
- }
652
- if (n >= 700) {
653
- changed = true;
654
- return statePrefix + "text-foreground";
655
- }
634
+ changed = true;
635
+ if (n <= 300) return statePrefix + "text-foreground";
636
+ if (n <= 600) return statePrefix + (isDestructive ? "text-destructive" : "text-primary");
637
+ return statePrefix + "text-foreground";
656
638
  }
657
639
  if (prefix === "border" || prefix === "ring" || prefix === "outline") {
658
640
  changed = true;
@@ -675,24 +657,16 @@ function replaceRawColors(classes, colorMap) {
675
657
  }
676
658
  const n = parseInt(shade);
677
659
  if (prefix === "bg") {
678
- if (n >= 800) {
679
- changed = true;
680
- return statePrefix + "bg-background";
681
- }
682
- if (n >= 100 && n <= 300) {
683
- changed = true;
684
- return statePrefix + "bg-muted";
685
- }
660
+ changed = true;
661
+ if (n <= 300) return statePrefix + "bg-muted";
662
+ if (n <= 700) return statePrefix + "bg-muted";
663
+ return statePrefix + "bg-background";
686
664
  }
687
665
  if (prefix === "text") {
688
- if (n >= 100 && n <= 300) {
689
- changed = true;
690
- return statePrefix + "text-foreground";
691
- }
692
- if (n >= 400 && n <= 600) {
693
- changed = true;
694
- return statePrefix + "text-muted-foreground";
695
- }
666
+ changed = true;
667
+ if (n <= 300) return statePrefix + "text-foreground";
668
+ if (n <= 600) return statePrefix + "text-muted-foreground";
669
+ return statePrefix + "text-foreground";
696
670
  }
697
671
  if (prefix === "border" || prefix === "ring" || prefix === "outline") {
698
672
  changed = true;
@@ -969,15 +943,47 @@ ${selectImport}`
969
943
  newImport = newImport.replace(new RegExp(`\\b${dup}\\b,?\\s*`), "");
970
944
  fixes.push(`removed ${dup} from lucide import (conflicts with UI component import)`);
971
945
  }
946
+ const ICON_ALIASES = {
947
+ Github: "ExternalLink",
948
+ GitHub: "ExternalLink",
949
+ Twitter: "MessageCircle",
950
+ Linkedin: "Link2",
951
+ LinkedIn: "Link2",
952
+ Slack: "MessageSquare",
953
+ Discord: "MessageCircle",
954
+ Facebook: "Globe",
955
+ Instagram: "Camera",
956
+ YouTube: "Play",
957
+ Youtube: "Play",
958
+ TikTok: "Music",
959
+ Reddit: "MessageSquare",
960
+ Twitch: "Tv",
961
+ Figma: "Pen",
962
+ Dribbble: "Palette",
963
+ Medium: "FileText",
964
+ WhatsApp: "Phone",
965
+ Telegram: "Send",
966
+ Pinterest: "Pin",
967
+ Spotify: "Music"
968
+ };
972
969
  const invalid = iconNames.filter((name) => !lucideExports.has(name) && !nonLucideImports.has(name));
973
970
  if (invalid.length > 0) {
974
- const fallback = "Circle";
971
+ const replacements = [];
975
972
  for (const bad of invalid) {
976
- const re = new RegExp(`\\b${bad}\\b`, "g");
977
- newImport = newImport.replace(re, fallback);
978
- fixed = fixed.replace(re, fallback);
973
+ const replacement = ICON_ALIASES[bad] || "Circle";
974
+ if (lucideExports.has(replacement)) {
975
+ const re = new RegExp(`\\b${bad}\\b`, "g");
976
+ newImport = newImport.replace(re, replacement);
977
+ fixed = fixed.replace(re, replacement);
978
+ replacements.push(`${bad}\u2192${replacement}`);
979
+ } else {
980
+ const re = new RegExp(`\\b${bad}\\b`, "g");
981
+ newImport = newImport.replace(re, "Circle");
982
+ fixed = fixed.replace(re, "Circle");
983
+ replacements.push(`${bad}\u2192Circle`);
984
+ }
979
985
  }
980
- fixes.push(`invalid lucide icons \u2192 ${fallback}: ${invalid.join(", ")}`);
986
+ fixes.push(`invalid lucide icons: ${replacements.join(", ")}`);
981
987
  }
982
988
  if (duplicates.length > 0 || invalid.length > 0) {
983
989
  const importedNames = [
@@ -985,8 +991,10 @@ ${selectImport}`
985
991
  newImport.split(",").map((s) => s.trim()).filter(Boolean)
986
992
  )
987
993
  ];
988
- const originalImportLine = lucideImportMatch[0];
989
- fixed = fixed.replace(originalImportLine, `import { ${importedNames.join(", ")} } from "lucide-react"`);
994
+ const currentLucideImport = fixed.match(/import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/);
995
+ if (currentLucideImport) {
996
+ fixed = fixed.replace(currentLucideImport[0], `import { ${importedNames.join(", ")} } from "lucide-react"`);
997
+ }
990
998
  }
991
999
  }
992
1000
  }
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  formatIssues,
8
8
  validatePageQuality,
9
9
  verifyIncrementalEdit
10
- } from "./chunk-N6H73ROO.js";
10
+ } from "./chunk-63DJQ2TU.js";
11
11
  import {
12
12
  generateArchitecturePlan,
13
13
  getPageGroup,
@@ -6012,8 +6012,29 @@ function buildTieredComponentsPrompt(manifest, pageType) {
6012
6012
  );
6013
6013
  return sections.join("\n");
6014
6014
  }
6015
- function formatPlanSummary(plan) {
6015
+ function formatPlanSummary(plan, forRoute) {
6016
6016
  if (plan.groups.length === 0) return "";
6017
+ if (forRoute) {
6018
+ const group = plan.groups.find((g) => g.pages.includes(forRoute));
6019
+ if (!group) return "";
6020
+ const groupLine = ` Group "${group.id}" (layout: ${group.layout}): ${group.pages.join(", ")}`;
6021
+ const relevantComps = plan.sharedComponents.filter((c) => c.usedBy.includes(forRoute));
6022
+ const parts2 = [`ARCHITECTURE PLAN:
6023
+ Your group:
6024
+ ${groupLine}`];
6025
+ if (relevantComps.length > 0) {
6026
+ parts2.push(
6027
+ `Shared Components for this page:
6028
+ ${relevantComps.map((c) => ` ${c.name} (${c.type}) \u2014 ${c.description}`).join("\n")}`
6029
+ );
6030
+ }
6031
+ const routeKey = forRoute.replace(/^\//, "");
6032
+ const note = plan.pageNotes?.[routeKey];
6033
+ if (note?.sections && note.sections.length > 0) {
6034
+ parts2.push(`Page Sections: ${note.sections.join(", ")}`);
6035
+ }
6036
+ return parts2.join("\n");
6037
+ }
6017
6038
  const groupLines = plan.groups.map((g) => ` Group "${g.id}" (layout: ${g.layout}): ${g.pages.join(", ")}`);
6018
6039
  const compLines = plan.sharedComponents.map(
6019
6040
  (c) => ` ${c.name} (${c.type}) \u2014 ${c.description}; usedBy: ${c.usedBy.join(", ")}`
@@ -6045,7 +6066,7 @@ function readExistingAppPageForReference(projectRoot, plan) {
6045
6066
  if (existsSync14(filePath)) {
6046
6067
  const code = readFileSync9(filePath, "utf-8");
6047
6068
  const lines = code.split("\n");
6048
- return lines.slice(0, 200).join("\n");
6069
+ return lines.slice(0, 60).join("\n");
6049
6070
  }
6050
6071
  }
6051
6072
  }
@@ -6064,7 +6085,7 @@ function readExistingAppPageForReference(projectRoot, plan) {
6064
6085
  if (existsSync14(pagePath)) {
6065
6086
  const code = readFileSync9(pagePath, "utf-8");
6066
6087
  const lines = code.split("\n");
6067
- return lines.slice(0, 200).join("\n");
6088
+ return lines.slice(0, 60).join("\n");
6068
6089
  }
6069
6090
  }
6070
6091
  }
@@ -6321,7 +6342,6 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
6321
6342
  const currentManifest = projectRoot ? await loadManifest5(projectRoot) : null;
6322
6343
  const routeNote = `EXISTING ROUTES in this project: ${allRoutes}. All internal links MUST point to one of these routes. If a target doesn't exist, use href="#".`;
6323
6344
  const alignmentNote = 'CRITICAL LAYOUT RULE: Every <section> must wrap its content in a container div matching the header width. Use the EXACT same container classes as shown in the style context (e.g. className="container max-w-6xl px-4" or className="max-w-6xl mx-auto px-4"). Inner content can use narrower max-w for text centering, but the outer section container MUST match.';
6324
- const planSummaryNote = plan ? formatPlanSummary(plan) : "";
6325
6345
  const existingAppPageCode = readExistingAppPageForReference(parseOpts?.projectRoot ?? null, plan);
6326
6346
  const existingAppPageNote = existingAppPageCode ? `
6327
6347
  EXISTING APP PAGE (match these UI patterns for consistency):
@@ -6398,7 +6418,7 @@ ${existingAppPageCode}
6398
6418
  routeNote,
6399
6419
  alignmentNote,
6400
6420
  authNote,
6401
- planSummaryNote,
6421
+ plan ? formatPlanSummary(plan, route) : "",
6402
6422
  pageType !== "auth" ? existingAppPageNote : void 0,
6403
6423
  existingPagesContext,
6404
6424
  styleContext
@@ -8472,7 +8492,7 @@ async function chatCommand(message, options) {
8472
8492
  spinner.start(`Creating shared component: ${componentName}...`);
8473
8493
  const { createAIProvider: createAIProvider2 } = await import("./ai-provider-CGSIYFZT.js");
8474
8494
  const { generateSharedComponent: generateSharedComponent7 } = await import("@getcoherent/core");
8475
- const { autoFixCode: autoFixCode2 } = await import("./quality-validator-3K5BMJSR.js");
8495
+ const { autoFixCode: autoFixCode2 } = await import("./quality-validator-GKGPDQ5I.js");
8476
8496
  const { extractPropsInterface, extractDependencies } = await import("./component-extractor-VYJLT5NR.js");
8477
8497
  const aiProvider = await createAIProvider2(provider ?? "auto");
8478
8498
  const prompt = `Generate a React component called "${componentName}". Description: ${message}.
@@ -4,7 +4,7 @@ import {
4
4
  formatIssues,
5
5
  validatePageQuality,
6
6
  verifyIncrementalEdit
7
- } from "./chunk-N6H73ROO.js";
7
+ } from "./chunk-63DJQ2TU.js";
8
8
  import "./chunk-3RG5ZIWI.js";
9
9
  export {
10
10
  autoFixCode,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.16",
6
+ "version": "0.6.18",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
@@ -54,6 +54,8 @@
54
54
  "devDependencies": {
55
55
  "@types/node": "^20.11.0",
56
56
  "@types/prompts": "^2.4.9",
57
+ "lucide-react": "^1.0.1",
58
+ "react": "^19.2.4",
57
59
  "tsup": "^8.0.1",
58
60
  "typescript": "^5.3.3"
59
61
  }