inai-react-components 0.1.4 → 0.1.6

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.
@@ -30,5 +30,7 @@ export declare function getTargetDir(component: RegistryComponent, aliases: {
30
30
  blocks: string;
31
31
  }): string;
32
32
  export declare function runAdd(componentSpec: string, rootDir: string): Promise<AddResult>;
33
- export declare function addCommand(componentSpec?: string): Promise<void>;
33
+ export declare function addCommand(componentSpec?: string, options?: {
34
+ all?: boolean;
35
+ }): Promise<void>;
34
36
  //# sourceMappingURL=add.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,aAAa,CAAC;AAGrB,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;CACxB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAQA;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;;GAEG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAUR;AAED,wBAAsB,MAAM,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAsHpB;AAuBD,wBAAsB,UAAU,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BtE"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,aAAa,CAAC;AASrB,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;CACxB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAQA;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;;GAEG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAUR;AAED,wBAAsB,MAAM,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAsHpB;AAuBD,wBAAsB,UAAU,CAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
@@ -5,6 +5,7 @@ import ora from "ora";
5
5
  import prompts from "prompts";
6
6
  import { readComponentsJson, readRegistryJson, } from "./status.js";
7
7
  import { resolveRegistryDir } from "../utils/registry-resolver.js";
8
+ import { normalizeThemeCss, getLocalTailwindCssTemplate, getLegacyTailwindCssTemplate, } from "./init.js";
8
9
  /**
9
10
  * Parse a component spec like "button", "block/auth-login", or "template/admin-dashboard"
10
11
  * into its type prefix and name.
@@ -166,7 +167,12 @@ function printAddResult(result) {
166
167
  console.log(chalk.cyan(` pnpm add ${result.npmDeps.join(" ")}`));
167
168
  }
168
169
  }
169
- export async function addCommand(componentSpec) {
170
+ export async function addCommand(componentSpec, options) {
171
+ // If --all flag, install everything
172
+ if (options?.all) {
173
+ await installAll();
174
+ return;
175
+ }
170
176
  // If no component specified, show interactive picker
171
177
  if (!componentSpec) {
172
178
  await interactiveAdd();
@@ -190,6 +196,173 @@ export async function addCommand(componentSpec) {
190
196
  process.exit(1);
191
197
  }
192
198
  }
199
+ /**
200
+ * Discover available themes from the registry's tokens directory.
201
+ */
202
+ function discoverThemes(registryDir) {
203
+ const themesDir = path.join(registryDir, "packages", "tokens", "src", "themes");
204
+ if (fs.existsSync(themesDir)) {
205
+ return fs
206
+ .readdirSync(themesDir)
207
+ .filter((f) => f.endsWith(".css"))
208
+ .map((f) => f.replace(/\.css$/, ""))
209
+ .sort();
210
+ }
211
+ return [];
212
+ }
213
+ /**
214
+ * Switch the project's theme. Copies the new theme CSS (normalized),
215
+ * updates components.json, and regenerates the CSS entry point.
216
+ */
217
+ async function changeTheme(rootDir, registryDir) {
218
+ const componentsJson = readComponentsJson(rootDir);
219
+ const currentTheme = componentsJson.theme ?? "monday";
220
+ const themes = discoverThemes(registryDir);
221
+ if (themes.length === 0) {
222
+ console.log(chalk.red("No themes found in registry."));
223
+ return;
224
+ }
225
+ const currentIdx = themes.indexOf(currentTheme);
226
+ const response = await prompts({
227
+ type: "select",
228
+ name: "theme",
229
+ message: `Select a theme ${chalk.dim(`(current: ${currentTheme})`)}`,
230
+ choices: themes.map((t) => ({
231
+ title: t === currentTheme ? `${t} ${chalk.green("(current)")}` : t,
232
+ value: t,
233
+ })),
234
+ initial: currentIdx >= 0 ? currentIdx : 0,
235
+ });
236
+ if (!response.theme) {
237
+ console.log(chalk.yellow("\nTheme change cancelled."));
238
+ return;
239
+ }
240
+ const newTheme = response.theme;
241
+ if (newTheme === currentTheme) {
242
+ console.log(chalk.dim("\nTheme unchanged."));
243
+ return;
244
+ }
245
+ const spinner = ora(`Switching theme to "${newTheme}"...`).start();
246
+ try {
247
+ const tokensSrc = path.join(registryDir, "packages", "tokens", "src");
248
+ const isRemote = !!componentsJson.registrySource;
249
+ if (isRemote) {
250
+ // Remote mode: copy and normalize theme file
251
+ const themesSrc = path.join(tokensSrc, "themes");
252
+ const themesDest = path.join(rootDir, "src", "styles", "tokens", "themes");
253
+ // Remove old theme file
254
+ const oldThemeFile = path.join(themesDest, `${currentTheme}.css`);
255
+ if (fs.existsSync(oldThemeFile)) {
256
+ fs.unlinkSync(oldThemeFile);
257
+ }
258
+ // Copy and normalize new theme
259
+ const newThemeSrc = path.join(themesSrc, `${newTheme}.css`);
260
+ if (fs.existsSync(newThemeSrc)) {
261
+ fs.mkdirSync(themesDest, { recursive: true });
262
+ const rawCss = fs.readFileSync(newThemeSrc, "utf-8");
263
+ const normalizedCss = normalizeThemeCss(rawCss, newTheme);
264
+ fs.writeFileSync(path.join(themesDest, `${newTheme}.css`), normalizedCss);
265
+ }
266
+ // Regenerate index.css
267
+ const font = componentsJson.font ?? { body: "outfit", heading: "outfit" };
268
+ const radius = componentsJson.radius ?? 0.5;
269
+ const cssPath = path.join(rootDir, "src", "index.css");
270
+ fs.writeFileSync(cssPath, getLocalTailwindCssTemplate(newTheme, font.body, font.heading, radius));
271
+ }
272
+ else {
273
+ // Local mode: just regenerate index.css with new import
274
+ const font = componentsJson.font ?? { body: "outfit", heading: "outfit" };
275
+ const radius = componentsJson.radius ?? 0.5;
276
+ const cssPath = path.join(rootDir, "src", "index.css");
277
+ fs.writeFileSync(cssPath, getLegacyTailwindCssTemplate(newTheme, font.body, font.heading, radius));
278
+ }
279
+ // Update components.json
280
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
281
+ componentsJson.theme = newTheme;
282
+ const componentsJsonPath = path.join(rootDir, "components.json");
283
+ fs.writeFileSync(componentsJsonPath, JSON.stringify(componentsJson, null, 2) + "\n");
284
+ spinner.succeed(`Theme switched to "${newTheme}"`);
285
+ console.log(chalk.green("\nUpdated files:"));
286
+ console.log(chalk.dim(" - components.json"));
287
+ console.log(chalk.dim(" - src/index.css"));
288
+ if (componentsJson.registrySource) {
289
+ console.log(chalk.dim(` - src/styles/tokens/themes/${newTheme}.css`));
290
+ }
291
+ }
292
+ catch (error) {
293
+ spinner.fail("Failed to switch theme.");
294
+ const message = error instanceof Error ? error.message : String(error);
295
+ console.error(chalk.red(`\nError: ${message}`));
296
+ }
297
+ }
298
+ async function installAll() {
299
+ const rootDir = process.cwd();
300
+ const componentsJson = readComponentsJson(rootDir);
301
+ if (!componentsJson) {
302
+ console.log(chalk.red("No components.json found. Run `inai-ui init` first to initialize your project."));
303
+ process.exit(1);
304
+ }
305
+ const registryDir = resolveRegistryDir(rootDir);
306
+ const registryPath = path.join(registryDir, "registry.json");
307
+ const registry = readRegistryJson(registryPath);
308
+ if (!registry) {
309
+ console.log(chalk.red("Registry not found. Ensure your project is initialized correctly."));
310
+ process.exit(1);
311
+ }
312
+ const allItems = [
313
+ ...registry.components,
314
+ ...registry.blocks,
315
+ ...registry.templates,
316
+ ];
317
+ console.log(chalk.bold(`\nInstalling all ${allItems.length} components, blocks, and templates...\n`));
318
+ const installed = componentsJson.installedComponents ?? [];
319
+ const installedNames = new Set(installed.map((c) => c.name));
320
+ const allNpmDeps = new Set();
321
+ let addedCount = 0;
322
+ let updatedCount = 0;
323
+ for (const item of allItems) {
324
+ const isInstalled = installedNames.has(item.name);
325
+ const action = isInstalled ? "Updating" : "Adding";
326
+ const prefix = item.type === "block" ? "block/" : item.type === "template" ? "template/" : "";
327
+ const spinner = ora(`${action} "${prefix}${item.name}"...`).start();
328
+ try {
329
+ const spec = prefix ? `${prefix}${item.name}` : item.name;
330
+ const result = await runAdd(spec, rootDir);
331
+ if (!result.added) {
332
+ spinner.fail(result.message);
333
+ continue;
334
+ }
335
+ if (isInstalled) {
336
+ spinner.succeed(`Updated "${prefix}${item.name}"`);
337
+ updatedCount++;
338
+ }
339
+ else {
340
+ spinner.succeed(`Added "${prefix}${item.name}"`);
341
+ addedCount++;
342
+ }
343
+ for (const dep of result.npmDeps) {
344
+ allNpmDeps.add(dep);
345
+ }
346
+ }
347
+ catch (error) {
348
+ spinner.fail(`Failed to process "${prefix}${item.name}"`);
349
+ const message = error instanceof Error ? error.message : String(error);
350
+ console.error(chalk.red(` Error: ${message}`));
351
+ }
352
+ }
353
+ // Summary
354
+ console.log(chalk.bold("\nSummary:"));
355
+ if (addedCount > 0) {
356
+ console.log(chalk.green(` ${addedCount} component${addedCount > 1 ? "s" : ""} added`));
357
+ }
358
+ if (updatedCount > 0) {
359
+ console.log(chalk.blue(` ${updatedCount} component${updatedCount > 1 ? "s" : ""} updated`));
360
+ }
361
+ if (allNpmDeps.size > 0) {
362
+ console.log(chalk.yellow("\nInstall required npm dependencies:"));
363
+ console.log(chalk.cyan(` pnpm add ${[...allNpmDeps].join(" ")}`));
364
+ }
365
+ }
193
366
  async function interactiveAdd() {
194
367
  const rootDir = process.cwd();
195
368
  const componentsJson = readComponentsJson(rootDir);
@@ -204,6 +377,26 @@ async function interactiveAdd() {
204
377
  console.log(chalk.red("Registry not found. Ensure your project is initialized correctly."));
205
378
  process.exit(1);
206
379
  }
380
+ // First: ask what the user wants to do
381
+ console.log(chalk.bold("\nInAI UI - Interactive Menu\n"));
382
+ const actionResponse = await prompts({
383
+ type: "select",
384
+ name: "action",
385
+ message: "What would you like to do?",
386
+ choices: [
387
+ { title: "Add components", value: "components", description: "Browse and install components, blocks, or templates" },
388
+ { title: "Change theme", value: "theme", description: `Current: ${componentsJson.theme ?? "monday"}` },
389
+ ],
390
+ });
391
+ if (!actionResponse.action) {
392
+ return;
393
+ }
394
+ // Theme change flow
395
+ if (actionResponse.action === "theme") {
396
+ await changeTheme(rootDir, registryDir);
397
+ return;
398
+ }
399
+ // Component picker flow
207
400
  const allItems = [
208
401
  ...registry.components,
209
402
  ...registry.blocks,
@@ -227,8 +420,7 @@ async function interactiveAdd() {
227
420
  selected: false,
228
421
  };
229
422
  });
230
- console.log(chalk.bold("\nInAI UI - Component Picker\n"));
231
- console.log(chalk.dim("Select components to add or update. Already installed components will be updated.\n"));
423
+ console.log(chalk.dim("\nSelect components to add or update. Already installed components will be updated.\n"));
232
424
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
233
425
  const response = await prompts({
234
426
  type: "multiselect",
@@ -259,6 +259,13 @@ export declare function buildComponentsJson(config: InitConfig, repoUrl?: string
259
259
  export declare function getCnTemplate(): string;
260
260
  export declare function getLocalTailwindCssTemplate(theme: Theme, fontBody: FontPreset, fontHeading: FontPreset, radius: number): string;
261
261
  export declare function getLegacyTailwindCssTemplate(theme: Theme, fontBody: FontPreset, fontHeading: FontPreset, radius: number): string;
262
+ /**
263
+ * Strip the `[data-theme="<name>"]` selector from theme CSS so it applies
264
+ * directly on `:root` / `.dark`. This is used when copying a single theme
265
+ * for a project — the theme becomes the default without needing a
266
+ * `data-theme` attribute on the HTML element.
267
+ */
268
+ export declare function normalizeThemeCss(css: string, theme: string): string;
262
269
  export declare function runInit(config: InitConfig, targetDir: string, repoUrl?: string): Promise<{
263
270
  success: boolean;
264
271
  filesCreated: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,gBAAgB,yMAeZ,CAAC;AACX,KAAK,KAAK,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DR,CAAC;AACX,KAAK,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAUxD,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,WAAW,EAAE,UAAU,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU,CAAC;QACjB,OAAO,EAAE,UAAU,CAAC;KACrB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAgBD,wBAAsB,gBAAgB,CACpC,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA8F5B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,cAAc,CAkChB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAOD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAa/H;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAahI;AA2ED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA4CvD;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DjE"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -264,6 +264,24 @@ export function getLegacyTailwindCssTemplate(theme, fontBody, fontHeading, radiu
264
264
  }
265
265
  `;
266
266
  }
267
+ /**
268
+ * Strip the `[data-theme="<name>"]` selector from theme CSS so it applies
269
+ * directly on `:root` / `.dark`. This is used when copying a single theme
270
+ * for a project — the theme becomes the default without needing a
271
+ * `data-theme` attribute on the HTML element.
272
+ */
273
+ export function normalizeThemeCss(css, theme) {
274
+ // Replace `:root[data-theme="<name>"],\n[data-theme="<name>"]` → `:root`
275
+ const rootSelector = new RegExp(`:root\\[data-theme="${theme}"\\],?\\s*\\n?\\[data-theme="${theme}"\\]`, "g");
276
+ let normalized = css.replace(rootSelector, ":root");
277
+ // Replace `.dark[data-theme="<name>"],\n[data-theme="<name>"].dark` → `.dark`
278
+ const darkSelector = new RegExp(`\\.dark\\[data-theme="${theme}"\\],?\\s*\\n?\\[data-theme="${theme}"\\]\\.dark`, "g");
279
+ normalized = normalized.replace(darkSelector, ".dark");
280
+ // Catch any remaining standalone `[data-theme="<name>"]` selectors
281
+ const standaloneSelector = new RegExp(`\\[data-theme="${theme}"\\]`, "g");
282
+ normalized = normalized.replace(standaloneSelector, "");
283
+ return normalized;
284
+ }
267
285
  function copyDirRecursive(src, dest) {
268
286
  const copied = [];
269
287
  if (!fs.existsSync(src))
@@ -297,7 +315,7 @@ function copyTokensToProject(registryDir, targetDir, theme) {
297
315
  copied.push(`src/styles/tokens/${file}`);
298
316
  }
299
317
  }
300
- // Copy selected theme
318
+ // Copy selected theme (normalized so it applies without data-theme attribute)
301
319
  const themesSrc = path.join(tokensSrc, "themes");
302
320
  const themesDest = path.join(tokensDest, "themes");
303
321
  if (fs.existsSync(themesSrc)) {
@@ -305,7 +323,9 @@ function copyTokensToProject(registryDir, targetDir, theme) {
305
323
  const themeFile = `${theme}.css`;
306
324
  const themeSrc = path.join(themesSrc, themeFile);
307
325
  if (fs.existsSync(themeSrc)) {
308
- fs.copyFileSync(themeSrc, path.join(themesDest, themeFile));
326
+ const rawCss = fs.readFileSync(themeSrc, "utf-8");
327
+ const normalizedCss = normalizeThemeCss(rawCss, theme);
328
+ fs.writeFileSync(path.join(themesDest, themeFile), normalizedCss);
309
329
  copied.push(`src/styles/tokens/themes/${themeFile}`);
310
330
  }
311
331
  }
@@ -12,6 +12,11 @@ export interface ComponentsJsonFile {
12
12
  };
13
13
  registrySource?: string;
14
14
  theme: string;
15
+ font?: {
16
+ body: string;
17
+ heading: string;
18
+ };
19
+ radius?: number;
15
20
  tanstack: {
16
21
  router: boolean;
17
22
  query: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAO7E;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAM1E;AAED,wBAAgB,iBAAiB,CAC/B,mBAAmB,EAAE,kBAAkB,EAAE,EACzC,eAAe,EAAE,MAAM,GACtB,MAAM,CAuBR;AAOD,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBhE;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnD"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAO7E;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAM1E;AAED,wBAAgB,iBAAiB,CAC/B,mBAAmB,EAAE,kBAAkB,EAAE,EACzC,eAAe,EAAE,MAAM,GACtB,MAAM,CAuBR;AAOD,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBhE;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnD"}
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program
13
13
  .name("inai-ui")
14
14
  .description("CLI for InAI UI component library")
15
- .version("0.1.0");
15
+ .version("0.1.6");
16
16
  program
17
17
  .command("init [repo-url]")
18
18
  .description("Initialize InAI UI in your project. Optionally pass a Git repo URL to fetch components remotely.")
@@ -20,7 +20,8 @@ program
20
20
  program
21
21
  .command("add [component]")
22
22
  .description("Add a component to your project. Without arguments, opens an interactive picker to select multiple components.")
23
- .action((component) => addCommand(component));
23
+ .option("-a, --all", "Install all available components, blocks, and templates")
24
+ .action((component, options) => addCommand(component, options));
24
25
  program
25
26
  .command("sync")
26
27
  .description("Update the local registry cache from the remote repository")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inai-react-components",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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",
@@ -34,7 +34,6 @@
34
34
  "dependencies": {
35
35
  "chalk": "^5.6.2",
36
36
  "commander": "^14.0.3",
37
- "fast-glob": "^3.3.3",
38
37
  "ora": "^9.3.0",
39
38
  "prompts": "^2.4.2"
40
39
  },