inai-react-components 2.1.0 → 2.2.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;AA0BrB,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAChD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAyCA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE;IAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAAC,SAAS,EAAE,iBAAiB,EAAE,CAAA;CAAE,EAC1G,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,iBAAiB,GAAG,IAAI,CAc1B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,MAAM,GACX,aAAa,GAAG,IAAI,CAGtB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iBAAiB,EAC5B,cAAc,EAAE,kBAAkB,GACjC,MAAM,CAiBR;AAuYD,wBAAsB,MAAM,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CA0NpB;AAqCD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,UAAU,CAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAqIf"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;AA2BrB,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAChD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAyCA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE;IAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAAC,SAAS,EAAE,iBAAiB,EAAE,CAAA;CAAE,EAC1G,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,iBAAiB,GAAG,IAAI,CAc1B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,MAAM,GACX,aAAa,GAAG,IAAI,CAGtB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iBAAiB,EAC5B,cAAc,EAAE,kBAAkB,GACjC,MAAM,CAiBR;AAqXD,wBAAsB,MAAM,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CA0NpB;AAqCD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,UAAU,CAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAqIf"}
@@ -10,7 +10,7 @@ import { saveSnapshot, sha256, } from "../utils/snapshot.js";
10
10
  import { fuzzySearchNames } from "../utils/fuzzy-search.js";
11
11
  import { normalizeThemeCss, getLocalTailwindCssTemplate, getLegacyTailwindCssTemplate, } from "./init.js";
12
12
  import { autoInstallDeps } from "../utils/auto-install.js";
13
- import { resolveLocalDir, getSourceRoot, rewriteCompanyUiImports, rewriteLibImports, stripRelativeJsExtensions, } from "../utils/paths.js";
13
+ import { resolveLocalDir, getSourceRoot, rewriteCompanyUiImports, rewriteLibImports, stripRelativeJsExtensions, computeDestRel, } from "../utils/paths.js";
14
14
  /**
15
15
  * Parse a component spec into its registry namespace, type prefix and name.
16
16
  *
@@ -121,19 +121,6 @@ async function installOne(component, registry, componentsJson, registryDir, root
121
121
  const baseTargetDir = getTargetDir(component, componentsJson);
122
122
  const isMultiFile = component.type === "block" || component.type === "template";
123
123
  const targetDir = isMultiFile ? path.join(baseTargetDir, name) : baseTargetDir;
124
- // Prefixes used by source files. Stripping them preserves each
125
- // component/block's internal subdirectory structure.
126
- //
127
- // Components: `packages/ui/src/<name>.tsx` and
128
- // `packages/ui/src/<name>/sub.tsx` → strip `packages/ui/src/`
129
- // so compound subdirs (`data-table/`) land as-is under
130
- // `<componentDir>/`.
131
- //
132
- // Blocks/templates: `apps/docs/src/registry/blocks/<name>/**` → strip
133
- // `apps/docs/src/registry/blocks/<name>/` so nested `parts/`
134
- // subfolders are preserved under `<blocksDir>/<name>/`.
135
- const UI_PREFIX = "packages/ui/src/";
136
- const BLOCK_PREFIX = `apps/docs/src/registry/blocks/${name}/`;
137
124
  const copiedFiles = [];
138
125
  const skippedFiles = [];
139
126
  // Track captured content for the snapshot (only for files that were
@@ -141,21 +128,11 @@ async function installOne(component, registry, componentsJson, registryDir, root
141
128
  const capturedFiles = {};
142
129
  for (const filePath of component.files) {
143
130
  const registryFilePath = path.join(registryDir, filePath);
144
- // Destination path relative to `targetDir`. The prefix stripping
145
- // preserves intra-component directory structure (compound subdirs,
146
- // blocks' `parts/` folders, etc.). Flattening to basename here was
147
- // the cause of broken `./parts/*` and `../data` imports in templates.
148
- let destRel;
149
- if (isMultiFile && filePath.startsWith(BLOCK_PREFIX)) {
150
- destRel = filePath.slice(BLOCK_PREFIX.length);
151
- }
152
- else if (!isMultiFile && filePath.startsWith(UI_PREFIX)) {
153
- destRel = filePath.slice(UI_PREFIX.length);
154
- }
155
- else {
156
- // Fallback for legacy registry entries without the expected prefix.
157
- destRel = path.basename(filePath);
158
- }
131
+ // Destination path relative to `targetDir`. Prefix stripping preserves
132
+ // intra-component directory structure (compound subdirs, blocks'
133
+ // `parts/` folders, etc.). `computeDestRel` throws on registry drift
134
+ // instead of silently flattening to basename.
135
+ const destRel = computeDestRel(filePath, name, isMultiFile);
159
136
  const localFilePath = path.join(rootDir, targetDir, destRel);
160
137
  const displayName = isMultiFile ? `${name}/${destRel}` : destRel;
161
138
  if (!fs.existsSync(registryFilePath)) {
@@ -326,6 +303,10 @@ async function installOne(component, registry, componentsJson, registryDir, root
326
303
  name,
327
304
  version: registryVersion,
328
305
  installedAt: new Date().toISOString().split("T")[0],
306
+ // `targetDir` is already relative to rootDir (returned by getTargetDir
307
+ // → resolveLocalDir which never emits absolute paths). Persist it so
308
+ // `update` can re-target the same dir even if aliases later change.
309
+ installDir: targetDir,
329
310
  };
330
311
  if (existingIdx >= 0) {
331
312
  installed[existingIdx] = entry;
@@ -425,6 +406,7 @@ async function installTheme(theme, componentsJson, registryDir, rootDir, options
425
406
  name: `theme/${name}`,
426
407
  version: "2.0.0",
427
408
  installedAt: new Date().toISOString().split("T")[0],
409
+ installDir: themesDir,
428
410
  };
429
411
  if (existingIdx >= 0) {
430
412
  installed[existingIdx] = entry;
@@ -218,6 +218,7 @@ type FontPreset = (typeof FONT_PRESETS)[number]["name"];
218
218
  export interface InitConfig {
219
219
  componentPath: string;
220
220
  blockPath: string;
221
+ templatePath: string;
221
222
  theme: Theme;
222
223
  fontBody: FontPreset;
223
224
  fontHeading: FontPreset;
@@ -244,6 +245,7 @@ export interface ComponentsJson {
244
245
  aliases: {
245
246
  components: string;
246
247
  blocks: string;
248
+ templates: string;
247
249
  utils: string;
248
250
  lib?: string;
249
251
  };
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -136,6 +136,9 @@ export function loadInitConfigFromFile(configPath, framework, layout) {
136
136
  const blockPath = typeof raw.blockPath === "string"
137
137
  ? assertSafeRelativePath(raw.blockPath, "blockPath")
138
138
  : `${sourceRoot}/components/blocks`;
139
+ const templatePath = typeof raw.templatePath === "string"
140
+ ? assertSafeRelativePath(raw.templatePath, "templatePath")
141
+ : `${sourceRoot}/templates`;
139
142
  const theme = typeof raw.theme === "string" ? raw.theme : AVAILABLE_THEMES[0] ?? "inai";
140
143
  if (!AVAILABLE_THEMES.includes(theme)) {
141
144
  throw new Error(`Unknown theme "${theme}". Allowed: ${AVAILABLE_THEMES.join(", ")}`);
@@ -161,6 +164,7 @@ export function loadInitConfigFromFile(configPath, framework, layout) {
161
164
  return {
162
165
  componentPath,
163
166
  blockPath,
167
+ templatePath,
164
168
  theme,
165
169
  fontBody,
166
170
  fontHeading,
@@ -180,18 +184,50 @@ export async function promptInitConfig(registryDir, framework, layout) {
180
184
  const defaultCssEntry = framework
181
185
  ? getCssEntryPoint(framework, sourceRoot)
182
186
  : `${sourceRoot}/index.css`;
187
+ // Warn (non-blocking) when the user types a path that doesn't start with
188
+ // `${sourceRoot}/` but `${sourceRoot}` exists on disk. This catches the
189
+ // classic "I dropped the `src/` prefix and now files end up at the repo
190
+ // root" mistake without forcing the layout for non-standard projects.
191
+ const validateProjectPath = (value) => {
192
+ if (typeof value !== "string")
193
+ return "Path must be a string";
194
+ const trimmed = value.trim();
195
+ if (!trimmed)
196
+ return "Path must not be empty";
197
+ if (path.isAbsolute(trimmed))
198
+ return "Path must be relative to the project root";
199
+ if (trimmed.split(/[\\/]/).includes(".."))
200
+ return "Path must not contain '..' segments";
201
+ const expectsSourceRoot = fs.existsSync(path.join(process.cwd(), sourceRoot));
202
+ if (expectsSourceRoot &&
203
+ sourceRoot !== "." &&
204
+ !trimmed.startsWith(`${sourceRoot}/`) &&
205
+ trimmed !== sourceRoot) {
206
+ return `Project uses '${sourceRoot}/' as the source root — did you mean '${sourceRoot}/${trimmed}'?`;
207
+ }
208
+ return true;
209
+ };
183
210
  const response = await prompts([
184
211
  {
185
212
  type: "text",
186
213
  name: "componentPath",
187
214
  message: "Where would you like to install components?",
188
215
  initial: `${sourceRoot}/components/ui`,
216
+ validate: validateProjectPath,
189
217
  },
190
218
  {
191
219
  type: "text",
192
220
  name: "blockPath",
193
221
  message: "Where would you like to install blocks?",
194
222
  initial: `${sourceRoot}/components/blocks`,
223
+ validate: validateProjectPath,
224
+ },
225
+ {
226
+ type: "text",
227
+ name: "templatePath",
228
+ message: "Where would you like to install templates?",
229
+ initial: `${sourceRoot}/templates`,
230
+ validate: validateProjectPath,
195
231
  },
196
232
  {
197
233
  type: "select",
@@ -282,6 +318,7 @@ export function buildComponentsJson(config, repoUrl) {
282
318
  aliases: {
283
319
  components: config.componentPath,
284
320
  blocks: config.blockPath,
321
+ templates: config.templatePath,
285
322
  utils: utilsAlias,
286
323
  lib: libAlias,
287
324
  },
@@ -47,6 +47,18 @@ export interface InstalledComponent {
47
47
  name: string;
48
48
  version: string;
49
49
  installedAt: string;
50
+ /**
51
+ * Directory (relative to the project root) where this component's files
52
+ * were copied during `add`. Used by `update` to keep writing to the same
53
+ * location even if the user later edits `aliases.components` / `blocks` /
54
+ * `templates` in `components.json` — that change would otherwise produce
55
+ * silent duplicates (old files in the old dir, new ones in the new dir).
56
+ *
57
+ * Optional for back-compat: components installed by a pre-2.2 CLI won't
58
+ * have this field, and `update` falls back to re-resolving via
59
+ * `getTargetDir` in that case.
60
+ */
61
+ installDir?: string;
50
62
  }
51
63
  export interface RegistryJson {
52
64
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,YAAY,CA4Cd;AAED,wBAAsB,SAAS,CAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,UAAQ,GAClB,OAAO,CAAC,YAAY,CAAC,CAqSvB;AAED,wBAAsB,aAAa,CACjC,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAiDf"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,YAAY,CA4Cd;AAED,wBAAsB,SAAS,CAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,UAAQ,GAClB,OAAO,CAAC,YAAY,CAAC,CAwSvB;AAED,wBAAsB,aAAa,CACjC,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -8,7 +8,7 @@ import { readComponentsJson, readRegistryJson, } from "./status.js";
8
8
  import { findComponentInRegistry, computeDiff } from "./diff.js";
9
9
  import { getTargetDir } from "./add.js";
10
10
  import { resolveRegistryDir } from "../utils/registry-resolver.js";
11
- import { rewriteCompanyUiImports, rewriteLibImports, stripRelativeJsExtensions, resolveLocalDir, getSourceRoot, } from "../utils/paths.js";
11
+ import { rewriteCompanyUiImports, rewriteLibImports, stripRelativeJsExtensions, resolveLocalDir, getSourceRoot, computeDestRel, } from "../utils/paths.js";
12
12
  import { loadSnapshot, saveSnapshot, sha256, } from "../utils/snapshot.js";
13
13
  /**
14
14
  * Run a 3-way line merge between base (snapshot), mine (local) and theirs
@@ -81,18 +81,25 @@ export async function runUpdate(componentName, rootDir, skipPrompts = false) {
81
81
  // Mirror add.ts targetDir resolution so blocks/templates land in their own
82
82
  // subdirectories and components in `aliases.components` directly. Without
83
83
  // this, `update` for a block would write its files into the components dir.
84
+ //
85
+ // Drift guard: if `add` recorded an `installDir` for this component, use
86
+ // that path verbatim instead of re-resolving from current aliases. This
87
+ // keeps update writing to the same directory where the files actually
88
+ // live even when the user has since edited `components.json` aliases —
89
+ // otherwise update would create silent duplicates in the new location
90
+ // while leaving the originals untouched.
84
91
  const isMultiFile = registryComponent.type === "block" || registryComponent.type === "template";
85
- const baseTargetDir = getTargetDir(registryComponent, componentsJson);
86
- const targetDir = isMultiFile
87
- ? path.join(baseTargetDir, componentName)
88
- : baseTargetDir;
89
- // Prefix stripping identical to add.ts so compound components (data-table,
90
- // tabs, etc.) preserve their internal subdirectory structure. Previously
91
- // update collapsed every path with `basename`, which caused both
92
- // `packages/ui/src/tabs.tsx` (barrel root) and `packages/ui/src/tabs/tabs.tsx`
93
- // (inner component) to land at `tabs.tsx`, overwriting each other.
94
- const UI_PREFIX = "packages/ui/src/";
95
- const BLOCK_PREFIX = `apps/docs/src/registry/blocks/${componentName}/`;
92
+ const installedEntry = (componentsJson.installedComponents ?? []).find((c) => c.name === componentName);
93
+ let targetDir;
94
+ if (installedEntry?.installDir) {
95
+ targetDir = installedEntry.installDir;
96
+ }
97
+ else {
98
+ const baseTargetDir = getTargetDir(registryComponent, componentsJson);
99
+ targetDir = isMultiFile
100
+ ? path.join(baseTargetDir, componentName)
101
+ : baseTargetDir;
102
+ }
96
103
  const updatedFiles = [];
97
104
  const cleanMerges = [];
98
105
  const conflictedFiles = [];
@@ -102,16 +109,10 @@ export async function runUpdate(componentName, rootDir, skipPrompts = false) {
102
109
  for (const filePath of registryComponent.files) {
103
110
  const registryFilePath = path.join(registryDir, filePath);
104
111
  // Compute destination path that preserves subdirectory structure.
105
- let destRel;
106
- if (isMultiFile && filePath.startsWith(BLOCK_PREFIX)) {
107
- destRel = filePath.slice(BLOCK_PREFIX.length);
108
- }
109
- else if (!isMultiFile && filePath.startsWith(UI_PREFIX)) {
110
- destRel = filePath.slice(UI_PREFIX.length);
111
- }
112
- else {
113
- destRel = path.basename(filePath);
114
- }
112
+ // Shared with add.ts via `computeDestRel` so a future divergence
113
+ // can't reintroduce the v2.0.4 bug where compound paths collapsed
114
+ // to basename and overwrote sibling files.
115
+ const destRel = computeDestRel(filePath, componentName, isMultiFile);
115
116
  const fileName = destRel;
116
117
  const localFilePath = path.join(rootDir, targetDir, destRel);
117
118
  if (!fs.existsSync(registryFilePath)) {
@@ -0,0 +1,2 @@
1
+ export declare function Button(): null;
2
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/ui/button.tsx"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,SAA4B"}
@@ -0,0 +1 @@
1
+ export function Button() { return null; /* v2 */ }
package/dist/index.js CHANGED
File without changes
@@ -16,6 +16,11 @@
16
16
  "description": "Where to install blocks. Defaults to `<sourceRoot>/components/blocks`.",
17
17
  "default": "src/components/blocks"
18
18
  },
19
+ "templatePath": {
20
+ "type": "string",
21
+ "description": "Where to install templates. Defaults to `<sourceRoot>/templates`.",
22
+ "default": "src/templates"
23
+ },
19
24
  "theme": {
20
25
  "type": "string",
21
26
  "description": "Base theme. Must be one of the values returned by `inai-ui list themes`.",
@@ -1,4 +1,27 @@
1
1
  import type { ComponentsJsonFile } from "../commands/status.js";
2
+ /**
3
+ * Source layout prefix for component files in the registry. Every component
4
+ * path emitted by `scripts/generate-registry.mjs` lives under this prefix.
5
+ * Stripping it preserves intra-component subdirectory structure (e.g.
6
+ * `data-table/data-table-body.tsx`) when copying to the consumer project.
7
+ */
8
+ export declare const UI_PREFIX = "packages/ui/src/";
9
+ /**
10
+ * Source layout prefix for a block/template's files. Each block/template
11
+ * owns a directory under `apps/docs/src/registry/blocks/`, and the prefix
12
+ * is parameterised by the block/template name.
13
+ */
14
+ export declare function blockPrefix(name: string): string;
15
+ /**
16
+ * Compute the destination path of a registry file relative to its target
17
+ * component/block directory. The prefix stripping preserves nested folder
18
+ * structure (compound component subdirs, block `parts/` folders, etc.).
19
+ *
20
+ * Throws if `filePath` doesn't match either prefix — this catches
21
+ * registry drift early instead of silently flattening compound paths to
22
+ * their basename (which used to overwrite sibling files; see v2.0.4 fix).
23
+ */
24
+ export declare function computeDestRel(filePath: string, componentName: string, isMultiFile: boolean): string;
2
25
  /**
3
26
  * Resolve an alias stored in `components.json` (e.g. "@/components/ui" or
4
27
  * "app/components/ui") to an actual directory relative to the project root.
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAYR;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAiBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAqBR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAaR"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE;;;;;GAKG;AACH,eAAO,MAAM,SAAS,qBAAqB,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,OAAO,GACnB,MAAM,CAYR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAYR;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAiBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAqBR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAaR"}
@@ -1,4 +1,41 @@
1
1
  const KNOWN_PREFIXES = ["@/", "~/", "$/"];
2
+ /**
3
+ * Source layout prefix for component files in the registry. Every component
4
+ * path emitted by `scripts/generate-registry.mjs` lives under this prefix.
5
+ * Stripping it preserves intra-component subdirectory structure (e.g.
6
+ * `data-table/data-table-body.tsx`) when copying to the consumer project.
7
+ */
8
+ export const UI_PREFIX = "packages/ui/src/";
9
+ /**
10
+ * Source layout prefix for a block/template's files. Each block/template
11
+ * owns a directory under `apps/docs/src/registry/blocks/`, and the prefix
12
+ * is parameterised by the block/template name.
13
+ */
14
+ export function blockPrefix(name) {
15
+ return `apps/docs/src/registry/blocks/${name}/`;
16
+ }
17
+ /**
18
+ * Compute the destination path of a registry file relative to its target
19
+ * component/block directory. The prefix stripping preserves nested folder
20
+ * structure (compound component subdirs, block `parts/` folders, etc.).
21
+ *
22
+ * Throws if `filePath` doesn't match either prefix — this catches
23
+ * registry drift early instead of silently flattening compound paths to
24
+ * their basename (which used to overwrite sibling files; see v2.0.4 fix).
25
+ */
26
+ export function computeDestRel(filePath, componentName, isMultiFile) {
27
+ if (isMultiFile) {
28
+ const prefix = blockPrefix(componentName);
29
+ if (filePath.startsWith(prefix))
30
+ return filePath.slice(prefix.length);
31
+ }
32
+ else if (filePath.startsWith(UI_PREFIX)) {
33
+ return filePath.slice(UI_PREFIX.length);
34
+ }
35
+ throw new Error(`Registry path "${filePath}" does not match the expected prefix for "${componentName}" (` +
36
+ `${isMultiFile ? blockPrefix(componentName) : UI_PREFIX}). ` +
37
+ "This usually means registry.json is out of sync — run `pnpm sync-registry` from the registry repo and commit the result.");
38
+ }
2
39
  /**
3
40
  * Resolve an alias stored in `components.json` (e.g. "@/components/ui" or
4
41
  * "app/components/ui") to an actual directory relative to the project root.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inai-react-components",
3
- "version": "2.1.0",
3
+ "version": "2.2.9",
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",
@@ -28,14 +28,6 @@
28
28
  "files": [
29
29
  "dist"
30
30
  ],
31
- "scripts": {
32
- "build": "tsc && pnpm run copy-schemas",
33
- "copy-schemas": "node -e \"require('fs').cpSync('src/schemas', 'dist/schemas', {recursive: true})\"",
34
- "dev": "tsc --watch",
35
- "check-types": "tsc --noEmit",
36
- "test": "vitest run",
37
- "prepublishOnly": "pnpm run build && pnpm run test"
38
- },
39
31
  "dependencies": {
40
32
  "@modelcontextprotocol/sdk": "^1.29.0",
41
33
  "chalk": "^5.6.2",
@@ -46,10 +38,17 @@
46
38
  "prompts": "^2.4.2"
47
39
  },
48
40
  "devDependencies": {
49
- "@repo/typescript-config": "workspace:*",
50
41
  "@types/diff": "^8.0.0",
51
42
  "@types/node": "^22.15.3",
52
43
  "typescript": "5.9.2",
53
- "vitest": "^4.1.0"
44
+ "vitest": "^4.1.0",
45
+ "@repo/typescript-config": "0.0.0"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc && pnpm run copy-schemas",
49
+ "copy-schemas": "node -e \"require('fs').cpSync('src/schemas', 'dist/schemas', {recursive: true})\"",
50
+ "dev": "tsc --watch",
51
+ "check-types": "tsc --noEmit",
52
+ "test": "vitest run"
54
53
  }
55
- }
54
+ }