inai-react-components 0.1.7 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +80 -0
  2. package/dist/commands/add.d.ts +42 -12
  3. package/dist/commands/add.d.ts.map +1 -1
  4. package/dist/commands/add.js +413 -93
  5. package/dist/commands/diff.d.ts +6 -0
  6. package/dist/commands/diff.d.ts.map +1 -1
  7. package/dist/commands/diff.js +90 -20
  8. package/dist/commands/init.d.ts +17 -5
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +87 -64
  11. package/dist/commands/mcp.d.ts +123 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +289 -0
  14. package/dist/commands/migrate.d.ts +41 -0
  15. package/dist/commands/migrate.d.ts.map +1 -0
  16. package/dist/commands/migrate.js +139 -0
  17. package/dist/commands/registries.d.ts +46 -0
  18. package/dist/commands/registries.d.ts.map +1 -0
  19. package/dist/commands/registries.js +152 -0
  20. package/dist/commands/remove.d.ts +11 -0
  21. package/dist/commands/remove.d.ts.map +1 -0
  22. package/dist/commands/remove.js +171 -0
  23. package/dist/commands/schema.d.ts +16 -0
  24. package/dist/commands/schema.d.ts.map +1 -0
  25. package/dist/commands/schema.js +32 -0
  26. package/dist/commands/status.d.ts +40 -4
  27. package/dist/commands/status.d.ts.map +1 -1
  28. package/dist/commands/status.js +149 -25
  29. package/dist/commands/theme.d.ts.map +1 -1
  30. package/dist/commands/theme.js +3 -37
  31. package/dist/commands/update.d.ts +18 -1
  32. package/dist/commands/update.d.ts.map +1 -1
  33. package/dist/commands/update.js +197 -6
  34. package/dist/index.js +76 -5
  35. package/dist/schemas/registry-config.schema.json +62 -0
  36. package/dist/schemas/registry-item.schema.json +63 -0
  37. package/dist/schemas/registry.schema.json +15 -0
  38. package/dist/types/registry.d.ts +50 -0
  39. package/dist/types/registry.d.ts.map +1 -0
  40. package/dist/types/registry.js +10 -0
  41. package/dist/utils/auto-install.d.ts +11 -0
  42. package/dist/utils/auto-install.d.ts.map +1 -0
  43. package/dist/utils/auto-install.js +29 -0
  44. package/dist/utils/framework-detect.d.ts +20 -0
  45. package/dist/utils/framework-detect.d.ts.map +1 -0
  46. package/dist/utils/framework-detect.js +97 -0
  47. package/dist/utils/fuzzy-search.d.ts +16 -0
  48. package/dist/utils/fuzzy-search.d.ts.map +1 -0
  49. package/dist/utils/fuzzy-search.js +67 -0
  50. package/dist/utils/paths.d.ts +26 -0
  51. package/dist/utils/paths.d.ts.map +1 -0
  52. package/dist/utils/paths.js +35 -0
  53. package/dist/utils/registry-config.d.ts +27 -0
  54. package/dist/utils/registry-config.d.ts.map +1 -0
  55. package/dist/utils/registry-config.js +94 -0
  56. package/dist/utils/registry-resolver.d.ts +26 -0
  57. package/dist/utils/registry-resolver.d.ts.map +1 -1
  58. package/dist/utils/registry-resolver.js +134 -10
  59. package/dist/utils/snapshot.d.ts +20 -0
  60. package/dist/utils/snapshot.d.ts.map +1 -0
  61. package/dist/utils/snapshot.js +32 -0
  62. package/dist/utils/themes.d.ts +17 -0
  63. package/dist/utils/themes.d.ts.map +1 -0
  64. package/dist/utils/themes.js +49 -0
  65. package/dist/utils/tsconfig-detect.d.ts +18 -0
  66. package/dist/utils/tsconfig-detect.d.ts.map +1 -0
  67. package/dist/utils/tsconfig-detect.js +121 -0
  68. package/package.json +9 -3
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Single source of truth for the built-in theme list used by the CLI
3
+ * (init, theme create, add). The registry on disk may expose more themes
4
+ * (discovered from packages/tokens/src/themes/*.css), but this list is the
5
+ * canonical fallback used when no registry is available and for validation.
6
+ */
7
+ export const THEMES = [
8
+ // Brand
9
+ { name: "inai", label: "InAI", category: "brand", description: "Default InAI brand theme — vibrant purple primary on OKLCH." },
10
+ { name: "monday", label: "Monday", category: "brand", description: "Monday.com-inspired vibrant SaaS aesthetic." },
11
+ { name: "linear", label: "Linear", category: "brand", description: "Linear-inspired minimal monochrome theme." },
12
+ { name: "notion", label: "Notion", category: "brand", description: "Notion-inspired soft neutral theme." },
13
+ { name: "vercel", label: "Vercel", category: "brand", description: "Vercel-inspired high-contrast black & white." },
14
+ { name: "anthropic", label: "Anthropic", category: "brand", description: "Anthropic-inspired warm editorial theme." },
15
+ // shadcn palette (17)
16
+ { name: "shadcn-default", label: "shadcn Default", category: "shadcn", description: "shadcn/ui default neutral theme." },
17
+ { name: "shadcn-blue", label: "shadcn Blue", category: "shadcn", description: "shadcn/ui blue primary variant." },
18
+ { name: "shadcn-green", label: "shadcn Green", category: "shadcn", description: "shadcn/ui green primary variant." },
19
+ { name: "shadcn-orange", label: "shadcn Orange", category: "shadcn", description: "shadcn/ui orange primary variant." },
20
+ { name: "shadcn-red", label: "shadcn Red", category: "shadcn", description: "shadcn/ui red primary variant." },
21
+ { name: "shadcn-rose", label: "shadcn Rose", category: "shadcn", description: "shadcn/ui rose primary variant." },
22
+ { name: "shadcn-violet", label: "shadcn Violet", category: "shadcn", description: "shadcn/ui violet primary variant." },
23
+ { name: "shadcn-yellow", label: "shadcn Yellow", category: "shadcn", description: "shadcn/ui yellow primary variant." },
24
+ { name: "shadcn-amber", label: "shadcn Amber", category: "shadcn", description: "shadcn/ui amber primary variant." },
25
+ { name: "shadcn-lime", label: "shadcn Lime", category: "shadcn", description: "shadcn/ui lime primary variant." },
26
+ { name: "shadcn-emerald", label: "shadcn Emerald", category: "shadcn", description: "shadcn/ui emerald primary variant." },
27
+ { name: "shadcn-teal", label: "shadcn Teal", category: "shadcn", description: "shadcn/ui teal primary variant." },
28
+ { name: "shadcn-cyan", label: "shadcn Cyan", category: "shadcn", description: "shadcn/ui cyan primary variant." },
29
+ { name: "shadcn-sky", label: "shadcn Sky", category: "shadcn", description: "shadcn/ui sky primary variant." },
30
+ { name: "shadcn-indigo", label: "shadcn Indigo", category: "shadcn", description: "shadcn/ui indigo primary variant." },
31
+ { name: "shadcn-purple", label: "shadcn Purple", category: "shadcn", description: "shadcn/ui purple primary variant." },
32
+ { name: "shadcn-fuchsia", label: "shadcn Fuchsia", category: "shadcn", description: "shadcn/ui fuchsia primary variant." },
33
+ { name: "shadcn-pink", label: "shadcn Pink", category: "shadcn", description: "shadcn/ui pink primary variant." },
34
+ // Creative (10)
35
+ { name: "cyberpunk", label: "Cyberpunk", category: "creative", description: "Neon pink and electric cyan on deep violet." },
36
+ { name: "aurora", label: "Aurora", category: "creative", description: "Northern-lights greens and teals." },
37
+ { name: "sunset", label: "Sunset", category: "creative", description: "Warm orange-to-pink gradient palette." },
38
+ { name: "midnight", label: "Midnight", category: "creative", description: "Deep-blue near-black editorial theme." },
39
+ { name: "acid", label: "Acid", category: "creative", description: "High-energy acid green and yellow." },
40
+ { name: "sakura", label: "Sakura", category: "creative", description: "Soft cherry-blossom pinks and neutrals." },
41
+ { name: "ocean", label: "Ocean", category: "creative", description: "Deep ocean blues and cyans." },
42
+ { name: "cosmic", label: "Cosmic", category: "creative", description: "Space-inspired violet and nebula hues." },
43
+ { name: "matcha", label: "Matcha", category: "creative", description: "Earthy matcha greens and cream." },
44
+ { name: "volcanic", label: "Volcanic", category: "creative", description: "Charcoal and lava orange contrast." },
45
+ ];
46
+ export const THEME_NAMES = THEMES.map((t) => t.name);
47
+ export function isKnownTheme(name) {
48
+ return THEME_NAMES.includes(name);
49
+ }
@@ -0,0 +1,18 @@
1
+ export interface ProjectLayout {
2
+ /** Directory where source code lives, relative to project root. e.g. "app" | "src". */
3
+ sourceRoot: string;
4
+ /** Import alias prefix including trailing slash. e.g. "~/" | "@/" | "$/". */
5
+ aliasPrefix: string;
6
+ }
7
+ /**
8
+ * Detect the project layout (source root directory and alias prefix) by
9
+ * reading `tsconfig.json` in `cwd`. Falls back to filesystem heuristics
10
+ * (looking for `app/` or `src/`) if tsconfig is missing or doesn't declare
11
+ * path aliases.
12
+ *
13
+ * The returned layout drives where the CLI writes component files, cn.ts,
14
+ * tokens, and the CSS entry point so projects using `app/` (Remix,
15
+ * TanStack Start, Next App Router, custom) work without manual config.
16
+ */
17
+ export declare function detectProjectLayout(cwd: string): ProjectLayout;
18
+ //# sourceMappingURL=tsconfig-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsconfig-detect.d.ts","sourceRoot":"","sources":["../../src/utils/tsconfig-detect.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;CACrB;AA0FD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CA0B9D"}
@@ -0,0 +1,121 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ /**
4
+ * Strip JSONC comments and trailing commas so `JSON.parse` can handle
5
+ * typical `tsconfig.json` files without an extra dependency.
6
+ */
7
+ function parseJsonc(raw) {
8
+ // Remove block comments /* ... */
9
+ let stripped = raw.replace(/\/\*[\s\S]*?\*\//g, "");
10
+ // Remove line comments //
11
+ stripped = stripped.replace(/(^|[^:])\/\/.*$/gm, "$1");
12
+ // Remove trailing commas in objects/arrays
13
+ stripped = stripped.replace(/,(\s*[}\]])/g, "$1");
14
+ return JSON.parse(stripped);
15
+ }
16
+ /**
17
+ * Load a tsconfig file and merge its `extends` chain (up to 3 levels).
18
+ * Only `compilerOptions.paths` and `compilerOptions.baseUrl` are merged —
19
+ * that is the minimum we need to resolve the source root.
20
+ */
21
+ function loadTsconfigChain(tsconfigPath, depth = 0) {
22
+ if (depth > 3)
23
+ return null;
24
+ if (!fs.existsSync(tsconfigPath))
25
+ return null;
26
+ let parsed;
27
+ try {
28
+ const raw = fs.readFileSync(tsconfigPath, "utf-8");
29
+ parsed = parseJsonc(raw);
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ if (parsed.extends) {
35
+ let parentPath = parsed.extends;
36
+ if (!parentPath.endsWith(".json"))
37
+ parentPath += ".json";
38
+ const resolved = path.isAbsolute(parentPath)
39
+ ? parentPath
40
+ : path.resolve(path.dirname(tsconfigPath), parentPath);
41
+ const parent = loadTsconfigChain(resolved, depth + 1);
42
+ if (parent) {
43
+ return {
44
+ compilerOptions: {
45
+ baseUrl: parsed.compilerOptions?.baseUrl ?? parent.compilerOptions?.baseUrl,
46
+ paths: {
47
+ ...(parent.compilerOptions?.paths ?? {}),
48
+ ...(parsed.compilerOptions?.paths ?? {}),
49
+ },
50
+ },
51
+ };
52
+ }
53
+ }
54
+ return parsed;
55
+ }
56
+ /**
57
+ * Parse a tsconfig `paths` entry to extract the alias prefix and target
58
+ * directory. Returns null if the entry is not a simple wildcard-to-directory
59
+ * mapping.
60
+ *
61
+ * Examples:
62
+ * - `"~/*": ["./app/*"]` → { prefix: "~/", sourceRoot: "app" }
63
+ * - `"@/*": ["./src/*"]` → { prefix: "@/", sourceRoot: "src" }
64
+ * - `"@foo/*": ["./libs/foo/*"]` → { prefix: "@foo/", sourceRoot: "libs/foo" }
65
+ */
66
+ function parsePathEntry(key, value) {
67
+ if (!key.endsWith("/*"))
68
+ return null;
69
+ const target = value[0];
70
+ if (!target || !target.endsWith("/*"))
71
+ return null;
72
+ const aliasPrefix = key.slice(0, -1); // "~/*" → "~/"
73
+ let sourceRoot = target.slice(0, -2); // "./app/*" → "./app"
74
+ // Strip leading "./"
75
+ if (sourceRoot.startsWith("./"))
76
+ sourceRoot = sourceRoot.slice(2);
77
+ // Reject absolute paths and paths that escape the project
78
+ if (path.isAbsolute(sourceRoot) || sourceRoot.startsWith(".."))
79
+ return null;
80
+ if (!sourceRoot)
81
+ return null;
82
+ return { sourceRoot, aliasPrefix };
83
+ }
84
+ /**
85
+ * Detect the project layout (source root directory and alias prefix) by
86
+ * reading `tsconfig.json` in `cwd`. Falls back to filesystem heuristics
87
+ * (looking for `app/` or `src/`) if tsconfig is missing or doesn't declare
88
+ * path aliases.
89
+ *
90
+ * The returned layout drives where the CLI writes component files, cn.ts,
91
+ * tokens, and the CSS entry point so projects using `app/` (Remix,
92
+ * TanStack Start, Next App Router, custom) work without manual config.
93
+ */
94
+ export function detectProjectLayout(cwd) {
95
+ const tsconfigPath = path.join(cwd, "tsconfig.json");
96
+ const tsconfig = loadTsconfigChain(tsconfigPath);
97
+ const paths = tsconfig?.compilerOptions?.paths ?? {};
98
+ // Prefer an entry whose source root directory actually exists on disk.
99
+ // This handles tsconfigs that declare multiple aliases.
100
+ let firstParsed = null;
101
+ for (const [key, value] of Object.entries(paths)) {
102
+ const parsed = parsePathEntry(key, value);
103
+ if (!parsed)
104
+ continue;
105
+ if (!firstParsed)
106
+ firstParsed = parsed;
107
+ if (fs.existsSync(path.join(cwd, parsed.sourceRoot))) {
108
+ return parsed;
109
+ }
110
+ }
111
+ if (firstParsed)
112
+ return firstParsed;
113
+ // No usable alias in tsconfig — fall back to directory heuristics.
114
+ if (fs.existsSync(path.join(cwd, "app"))) {
115
+ return { sourceRoot: "app", aliasPrefix: "~/" };
116
+ }
117
+ if (fs.existsSync(path.join(cwd, "src"))) {
118
+ return { sourceRoot: "src", aliasPrefix: "@/" };
119
+ }
120
+ return { sourceRoot: "src", aliasPrefix: "@/" };
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inai-react-components",
3
- "version": "0.1.7",
3
+ "version": "1.4.0",
4
4
  "description": "CLI for InAI UI component library — install components from a private registry into your React project",
5
5
  "private": false,
6
6
  "type": "module",
@@ -29,19 +29,25 @@
29
29
  "dist"
30
30
  ],
31
31
  "scripts": {
32
- "build": "tsc",
32
+ "build": "tsc && pnpm run copy-schemas",
33
+ "copy-schemas": "node -e \"require('fs').cpSync('src/schemas', 'dist/schemas', {recursive: true})\"",
33
34
  "dev": "tsc --watch",
34
35
  "check-types": "tsc --noEmit",
35
- "test": "vitest run"
36
+ "test": "vitest run",
37
+ "prepublishOnly": "pnpm run build && pnpm run test"
36
38
  },
37
39
  "dependencies": {
40
+ "@modelcontextprotocol/sdk": "^1.29.0",
38
41
  "chalk": "^5.6.2",
39
42
  "commander": "^14.0.3",
43
+ "diff": "^8.0.4",
44
+ "diff3": "^0.0.4",
40
45
  "ora": "^9.3.0",
41
46
  "prompts": "^2.4.2"
42
47
  },
43
48
  "devDependencies": {
44
49
  "@repo/typescript-config": "workspace:*",
50
+ "@types/diff": "^8.0.0",
45
51
  "@types/node": "^22.15.3",
46
52
  "typescript": "5.9.2",
47
53
  "vitest": "^4.1.0"