ionbit-ui 0.1.15 → 0.2.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/dist/index.js CHANGED
@@ -403,6 +403,109 @@ ${label}`));
403
403
  console.log(chalk.dim(`Install with: ionbit-ui add <name>`));
404
404
  console.log("");
405
405
  }
406
+ function mix(color, amount) {
407
+ return `color-mix(in oklab, ${color} ${amount}%, transparent)`;
408
+ }
409
+ const SHADOW_SCALE = {
410
+ subtle: 0.6,
411
+ normal: 1,
412
+ dramatic: 1.5
413
+ };
414
+ function hover(color) {
415
+ return `color-mix(in oklab, ${color} 88%, black)`;
416
+ }
417
+ function colorsToCss(c, s, isLight) {
418
+ const { translucency } = s;
419
+ const k = SHADOW_SCALE[s.shadowIntensity];
420
+ const alpha = (base) => (base * k).toFixed(2);
421
+ const borderBase = isLight ? "0 0 0" : "1 0 0";
422
+ const borderAlpha = translucency.toFixed(2);
423
+ const mutedAmount = Math.round(translucency * 160);
424
+ const subtleAmount = Math.round(translucency * 80);
425
+ return [
426
+ ` --background: ${c.background};`,
427
+ ` --surface: ${c.surface};`,
428
+ ` --surface-elevated: ${c.surfaceElevated};`,
429
+ ` --surface-hover: ${c.surfaceHover};`,
430
+ ` --foreground: ${c.foreground};`,
431
+ ` --foreground-muted: ${c.foregroundMuted};`,
432
+ ` --foreground-subtle: ${c.foregroundSubtle};`,
433
+ ` --accent: ${c.accent};`,
434
+ ` --accent-hover: ${c.accentHover};`,
435
+ ` --accent-foreground: ${c.accentForeground};`,
436
+ ` --accent-muted: ${mix(c.accent, mutedAmount)};`,
437
+ ` --accent-subtle: ${mix(c.accent, subtleAmount)};`,
438
+ ` --success: ${c.success};`,
439
+ ` --success-hover: ${hover(c.success)};`,
440
+ ` --success-muted: ${mix(c.success, mutedAmount)};`,
441
+ ` --success-subtle: ${mix(c.success, subtleAmount)};`,
442
+ ` --success-foreground: ${isLight ? "oklch(0.99 0 0)" : "oklch(0.1 0.03 155)"};`,
443
+ ` --warning: ${c.warning};`,
444
+ ` --warning-hover: ${hover(c.warning)};`,
445
+ ` --warning-muted: ${mix(c.warning, mutedAmount)};`,
446
+ ` --warning-subtle: ${mix(c.warning, subtleAmount)};`,
447
+ ` --warning-foreground: ${isLight ? "oklch(0.99 0 0)" : "oklch(0.1 0.03 80)"};`,
448
+ ` --error: ${c.error};`,
449
+ ` --error-hover: ${hover(c.error)};`,
450
+ ` --error-muted: ${mix(c.error, mutedAmount)};`,
451
+ ` --error-subtle: ${mix(c.error, subtleAmount)};`,
452
+ ` --error-foreground: ${isLight ? "oklch(0.99 0 0)" : "oklch(0.1 0.04 5)"};`,
453
+ ` --info: ${c.info};`,
454
+ ` --info-hover: ${hover(c.info)};`,
455
+ ` --info-muted: ${mix(c.info, mutedAmount)};`,
456
+ ` --info-subtle: ${mix(c.info, subtleAmount)};`,
457
+ ` --info-foreground: ${isLight ? "oklch(0.99 0 0)" : "oklch(0.1 0.03 230)"};`,
458
+ ` --ring: ${c.ring};`,
459
+ ` --border: oklch(${borderBase} / ${borderAlpha});`,
460
+ ` --border-strong: oklch(${borderBase} / ${(translucency * 1.75).toFixed(2)});`,
461
+ ` --border-accent: ${mix(c.accent, 50)};`,
462
+ ` --border-error: ${mix(c.error, 50)};`,
463
+ ` --border-success: ${mix(c.success, 50)};`,
464
+ ` --border-warning: ${mix(c.warning, 50)};`,
465
+ ` --border-info: ${mix(c.info, 50)};`,
466
+ ` --shadow-xs: 0 1px 2px 0 oklch(0 0 0 / ${alpha(isLight ? 0.06 : 0.2)});`,
467
+ ` --shadow-sm: 0 2px 4px -1px oklch(0 0 0 / ${alpha(isLight ? 0.08 : 0.25)}), 0 1px 2px -1px oklch(0 0 0 / ${alpha(isLight ? 0.06 : 0.2)});`,
468
+ ` --shadow-md: 0 4px 8px -2px oklch(0 0 0 / ${alpha(isLight ? 0.1 : 0.3)}), 0 2px 4px -2px oklch(0 0 0 / ${alpha(isLight ? 0.08 : 0.25)});`,
469
+ ` --shadow-lg: 0 12px 24px -8px oklch(0 0 0 / ${alpha(isLight ? 0.12 : 0.4)}), 0 4px 8px -4px oklch(0 0 0 / ${alpha(isLight ? 0.1 : 0.3)});`
470
+ ].join("\n");
471
+ }
472
+ function radiusToCss(r) {
473
+ return [
474
+ ` --radius-sm: ${r.sm};`,
475
+ ` --radius-md: ${r.md};`,
476
+ ` --radius-lg: ${r.lg};`,
477
+ ` --radius-xl: ${r.xl};`
478
+ ].join("\n");
479
+ }
480
+ function settingsToCss(s) {
481
+ return [
482
+ ` --spotlight-intensity: ${s.spotlightIntensity};`,
483
+ ` --magnetic-intensity: ${s.magneticIntensity};`,
484
+ ` --glow-intensity: ${s.glowIntensity};`,
485
+ ` --pulse-intensity: ${s.pulseIntensity};`,
486
+ ` --ripple-intensity: ${s.rippleIntensity};`,
487
+ ` --tilt-intensity: ${s.tiltIntensity};`,
488
+ ` --reflection-intensity: ${s.reflectionIntensity};`,
489
+ ` --scramble-intensity: ${s.scrambleIntensity};`,
490
+ ` --trace-intensity: ${s.traceIntensity};`
491
+ ].join("\n");
492
+ }
493
+ function generateThemeCss(preset) {
494
+ const darkBlock = `:root {
495
+ ${colorsToCss(preset.dark, preset.settings, false)}
496
+ ${radiusToCss(preset.radius)}
497
+ ${settingsToCss(preset.settings)}
498
+ }`;
499
+ const lightBlock = `.light {
500
+ ${colorsToCss(preset.light, preset.settings, true)}
501
+ ${radiusToCss(preset.radius)}
502
+ ${settingsToCss(preset.settings)}
503
+ }`;
504
+ return `/* Ionbit UI — Theme: ${preset.label} */
505
+ ${darkBlock}
506
+
507
+ ${lightBlock}`;
508
+ }
406
509
  async function theme(id, options) {
407
510
  const cwd = process.cwd();
408
511
  const config = loadConfig(cwd);
@@ -432,7 +535,10 @@ async function theme(id, options) {
432
535
  return;
433
536
  }
434
537
  label = "Custom";
435
- css = generateThemeCss(custom, label);
538
+ css = generateThemeCss({
539
+ ...custom,
540
+ label
541
+ });
436
542
  } else {
437
543
  if (!id) {
438
544
  console.log(chalk.red("Provide a theme id or use --custom <json>."));
@@ -490,71 +596,10 @@ ${importLine}
490
596
  `);
491
597
  }
492
598
  }
493
- function colorMix(color, amount) {
494
- return `color-mix(in oklab, ${color} ${amount}%, transparent)`;
495
- }
496
- function hoverColor(color) {
497
- return `color-mix(in oklab, ${color} 88%, black)`;
498
- }
499
- function colorsToCss(colors, translucency, light) {
500
- const muted = Math.round(translucency * 160);
501
- const subtle = Math.round(translucency * 80);
502
- const borderBase = light ? "0 0 0" : "1 0 0";
503
- return [
504
- ` --background: ${colors.background};`,
505
- ` --surface: ${colors.surface};`,
506
- ` --surface-elevated: ${colors.surfaceElevated};`,
507
- ` --surface-hover: ${colors.surfaceHover};`,
508
- ` --foreground: ${colors.foreground};`,
509
- ` --foreground-muted: ${colors.foregroundMuted};`,
510
- ` --foreground-subtle: ${colors.foregroundSubtle};`,
511
- ` --accent: ${colors.accent};`,
512
- ` --accent-hover: ${colors.accentHover};`,
513
- ` --accent-foreground: ${colors.accentForeground};`,
514
- ` --accent-muted: ${colorMix(colors.accent, muted)};`,
515
- ` --accent-subtle: ${colorMix(colors.accent, subtle)};`,
516
- ...statusCss("success", colors.success, muted, subtle, light, "155"),
517
- ...statusCss("warning", colors.warning, muted, subtle, light, "80"),
518
- ...statusCss("error", colors.error, muted, subtle, light, "5"),
519
- ...statusCss("info", colors.info, muted, subtle, light, "230"),
520
- ` --ring: ${colors.ring};`,
521
- ` --border: oklch(${borderBase} / ${translucency.toFixed(2)});`,
522
- ` --border-strong: oklch(${borderBase} / ${(translucency * 1.75).toFixed(2)});`,
523
- ` --border-accent: ${colorMix(colors.accent, 50)};`,
524
- ` --border-error: ${colorMix(colors.error, 50)};`,
525
- ` --border-success: ${colorMix(colors.success, 50)};`,
526
- ` --border-warning: ${colorMix(colors.warning, 50)};`,
527
- ` --border-info: ${colorMix(colors.info, 50)};`
528
- ].join("\n");
529
- }
530
- function statusCss(name, color, muted, subtle, light, hue) {
531
- return [
532
- ` --${name}: ${color};`,
533
- ` --${name}-hover: ${hoverColor(color)};`,
534
- ` --${name}-muted: ${colorMix(color, muted)};`,
535
- ` --${name}-subtle: ${colorMix(color, subtle)};`,
536
- ` --${name}-foreground: ${light ? "oklch(0.99 0 0)" : `oklch(0.1 0.03 ${hue})`};`
537
- ];
538
- }
539
- function generateThemeCss(theme2, label) {
540
- const radius = Object.entries(theme2.radius).map(([key, value]) => ` --radius-${key}: ${value};`).join("\n");
541
- const settings = Object.entries(theme2.settings).filter(([key]) => key.endsWith("Intensity")).map(
542
- ([key, value]) => ` --${key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}: ${value};`
543
- ).join("\n");
544
- const block = (colors, light) => `${light ? ".light" : ":root"} {
545
- ${colorsToCss(colors, Number(theme2.settings.translucency), light)}
546
- ${radius}
547
- ${settings}
548
- }`;
549
- return `/* Ionbit UI — Theme: ${label} */
550
- ${block(theme2.dark, false)}
551
-
552
- ${block(theme2.light, true)}`;
553
- }
554
599
  const program = new Command();
555
600
  program.name("ionbit-ui").description(
556
601
  "Ionbit UI CLI — install source-owned components from the Ionbit UI registry."
557
- ).version("0.1.15");
602
+ ).version("0.2.0");
558
603
  program.command("init").description(
559
604
  "Initialize Ionbit UI in your project. Creates a ionbit-ui.config.json and installs design tokens."
560
605
  ).option("-y, --yes", "Skip confirmation prompts and use defaults").option("-f, --force", "Force overwrite of existing configuration").option(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/config.ts","../src/utils/fs.ts","../src/utils/npm.ts","../src/utils/registry.ts","../src/commands/add.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/theme.ts","../src/index.ts"],"sourcesContent":["export const REGISTRY_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry.json\";\n\nexport const REGISTRY_ITEM_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry/items\";\nexport const THEME_REGISTRY_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry/themes.json\";\n\nexport interface RegistryItem {\n name: string;\n type: string;\n title: string;\n description: string;\n dependencies?: string[];\n devDependencies?: string[];\n registryDependencies?: string[];\n files: RegistryFile[];\n}\n\nexport interface RegistryFile {\n path: string;\n type: string;\n content: string;\n}\n\nexport interface Registry {\n $schema: string;\n name: string;\n homepage: string;\n items: RegistryItem[];\n}\n\nexport interface ThemeEntry {\n id: string;\n label: string;\n description: string;\n css: string;\n}\n\nexport interface ThemeRegistry {\n themes: ThemeEntry[];\n}\n\nexport interface Config {\n $schema: string;\n style: string;\n tailwind: {\n css: string;\n cssVariables: boolean;\n };\n aliases: {\n components: string;\n motion: string;\n lib: string;\n styles: string;\n };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n $schema: \"https://ui.shadcn.com/schema/registry.json\",\n style: \"digital\",\n tailwind: {\n css: \"src/index.css\",\n cssVariables: true,\n },\n aliases: {\n components: \"src/components/ui\",\n motion: \"src/components/motion\",\n lib: \"src/lib\",\n styles: \"src/styles\",\n },\n};\n\nexport const CONFIG_FILE = \"ionbit-ui.config.json\";\n","import type { Config } from \"../config\";\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { CONFIG_FILE } from \"../config\";\n\nexport function loadConfig(cwd = process.cwd()): Config | null {\n const configPath = resolve(cwd, CONFIG_FILE);\n if (!existsSync(configPath)) return null;\n return JSON.parse(readFileSync(configPath, \"utf-8\")) as Config;\n}\n\nexport function saveConfig(config: Config, cwd = process.cwd()): void {\n const configPath = resolve(cwd, CONFIG_FILE);\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function ensureDir(filePath: string): void {\n const dir = dirname(filePath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nexport function writeFile(filePath: string, content: string): void {\n ensureDir(filePath);\n writeFileSync(filePath, content);\n}\n\nexport function resolveTargetPath(\n target: string,\n config: Config,\n cwd = process.cwd(),\n): string {\n // Map registry target paths to the user's configured aliases.\n // e.g. \"components/ui/button.tsx\" -> \"{cwd}/components/ui/button.tsx\"\n // \"components/motion/spotlight.tsx\" -> \"{cwd}/components/motion/spotlight.tsx\"\n // \"lib/utils.ts\" -> \"{cwd}/lib/utils.ts\"\n // \"styles/tokens.css\" -> \"{cwd}/styles/tokens.css\"\n let resolved = target;\n\n if (target.startsWith(\"components/ui/\")) {\n resolved = target.replace(\n \"components/ui/\",\n config.aliases.components + \"/\",\n );\n } else if (target.startsWith(\"components/motion/\")) {\n resolved = target.replace(\n \"components/motion/\",\n config.aliases.motion + \"/\",\n );\n } else if (target.startsWith(\"lib/\")) {\n resolved = target.replace(\"lib/\", config.aliases.lib + \"/\");\n } else if (target.startsWith(\"styles/\")) {\n resolved = target.replace(\"styles/\", config.aliases.styles + \"/\");\n }\n\n return resolve(cwd, resolved);\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport function detectPackageManager(cwd: string): PackageManager {\n if (existsSync(resolve(cwd, \"bun.lockb\"))) return \"bun\";\n if (existsSync(resolve(cwd, \"bun.lock\"))) return \"bun\";\n if (existsSync(resolve(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(resolve(cwd, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function installNpmDeps(deps: string[], cwd: string): void {\n if (deps.length === 0) return;\n const pm = detectPackageManager(cwd);\n const cmd =\n pm === \"pnpm\"\n ? `pnpm add ${deps.join(\" \")}`\n : pm === \"yarn\"\n ? `yarn add ${deps.join(\" \")}`\n : pm === \"bun\"\n ? `bun add ${deps.join(\" \")}`\n : `npm install ${deps.join(\" \")}`;\n execSync(cmd, { cwd, stdio: \"inherit\" });\n}\n","import type { Registry, RegistryItem, ThemeRegistry } from \"../config\";\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { REGISTRY_ITEM_URL, REGISTRY_URL, THEME_REGISTRY_URL } from \"../config\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Find the registry.json — checks local paths first, then falls back to the\n * remote GitHub URL. This allows development/testing without pushing to GitHub.\n */\nfunction findLocalRegistry(): string | null {\n const candidates = [\n // Relative to cwd (user's project)\n resolve(process.cwd(), \"registry.json\"),\n // Relative to CLI dist (packages/cli/dist -> ../../../registry.json)\n resolve(__dirname, \"../../../registry.json\"),\n // Relative to CLI src/utils (packages/cli/src/utils -> ../../../../registry.json)\n resolve(__dirname, \"../../../../registry.json\"),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction findLocalRegistryItem(name: string): string | null {\n const candidates = [\n resolve(process.cwd(), \"registry/items\", `${name}.json`),\n resolve(__dirname, \"../../../registry/items\", `${name}.json`),\n resolve(__dirname, \"../../../../registry/items\", `${name}.json`),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction findLocalThemes(): string | null {\n const candidates = [\n resolve(process.cwd(), \"registry/themes.json\"),\n resolve(__dirname, \"../../../registry/themes.json\"),\n resolve(__dirname, \"../../../../registry/themes.json\"),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nexport async function fetchRegistry(): Promise<Registry> {\n const localPath = findLocalRegistry();\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as Registry;\n }\n\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch registry: ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as Registry;\n}\n\nexport async function fetchRegistryItem(name: string): Promise<RegistryItem> {\n const localPath = findLocalRegistryItem(name);\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as RegistryItem;\n }\n\n const res = await fetch(`${REGISTRY_ITEM_URL}/${name}.json`);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch registry item \"${name}\": ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as RegistryItem;\n}\n\nexport async function fetchRegistryItems(\n names: string[],\n): Promise<RegistryItem[]> {\n return Promise.all(names.map(fetchRegistryItem));\n}\n\nexport async function fetchThemeRegistry(): Promise<ThemeRegistry> {\n const localPath = findLocalThemes();\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as ThemeRegistry;\n }\n\n const res = await fetch(THEME_REGISTRY_URL);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch theme registry: ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as ThemeRegistry;\n}\n","import type { Config, RegistryItem } from \"../config\";\n\nimport chalk from \"chalk\";\nimport { existsSync } from \"node:fs\";\n\nimport { loadConfig, resolveTargetPath, writeFile } from \"../utils/fs\";\nimport { installNpmDeps } from \"../utils/npm\";\nimport { fetchRegistry, fetchRegistryItems } from \"../utils/registry\";\n\nexport async function add(\n components: string[],\n options: { overwrite?: boolean },\n): Promise<void> {\n const cwd = process.cwd();\n const config = loadConfig(cwd);\n\n if (!config) {\n console.log(\n chalk.red(\"No ionbit-ui.config.json found. Run `ionbit-ui init` first.\"),\n );\n process.exit(1);\n }\n\n // Fetch the full registry to resolve names and dependencies\n const registry = await fetchRegistry();\n const allNames = new Set(registry.items.map((i) => i.name));\n\n // Validate requested components\n for (const name of components) {\n if (!allNames.has(name)) {\n console.log(\n chalk.red(\n `Component \"${name}\" not found in registry. Run \\`ionbit-ui list\\` to see available components.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Resolve transitive registry dependencies\n const toInstall = resolveDependencies(components, registry.items);\n\n console.log(chalk.dim(`Installing ${toInstall.length} item(s)...`));\n console.log(\"\");\n\n // Fetch all items with embedded content\n const items = await fetchRegistryItems(toInstall);\n\n for (const item of items) {\n await installItem(item, config, cwd, options.overwrite ?? false);\n }\n\n // Collect and install npm dependencies\n const npmDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies ?? []) {\n npmDeps.add(dep);\n }\n }\n\n if (npmDeps.size > 0) {\n console.log(\"\");\n installNpmDeps([...npmDeps], cwd);\n }\n\n console.log(\"\");\n console.log(chalk.green(`✓ Added ${items.length} component(s).`));\n}\n\nfunction resolveDependencies(\n names: string[],\n allItems: { name: string; registryDependencies?: string[] }[],\n): string[] {\n const resolved = new Set<string>();\n const queue = [...names];\n\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (resolved.has(name)) continue;\n resolved.add(name);\n\n const item = allItems.find((i) => i.name === name);\n if (item?.registryDependencies) {\n for (const dep of item.registryDependencies) {\n if (!resolved.has(dep)) queue.push(dep);\n }\n }\n }\n\n return [...resolved];\n}\n\nasync function installItem(\n item: RegistryItem,\n config: Config,\n cwd: string,\n overwrite: boolean,\n): Promise<void> {\n for (const file of item.files) {\n const targetPath = resolveTargetPath(file.path, config, cwd);\n\n if (existsSync(targetPath) && !overwrite) {\n console.log(\n chalk.yellow(\n ` ⚠ ${file.path} already exists — skipping (use --overwrite)`,\n ),\n );\n continue;\n }\n\n writeFile(targetPath, file.content);\n console.log(chalk.green(` ✓ ${file.path}`));\n }\n}\n","import type { Config, RegistryItem } from \"../config\";\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\n\nimport { CONFIG_FILE, DEFAULT_CONFIG } from \"../config\";\nimport { resolveTargetPath, saveConfig, writeFile } from \"../utils/fs\";\nimport { installNpmDeps } from \"../utils/npm\";\nimport { fetchRegistryItems } from \"../utils/registry\";\n\nconst CURSOR_CSS = `@layer base {\n button:not(:disabled),\n [role=\"button\"]:not(:disabled) {\n cursor: pointer;\n }\n}`;\n\n/** Items that every project needs — installed automatically during init. */\nconst BASE_ITEMS = [\"cn\", \"tokens\"];\n\nexport async function init(options: {\n yes?: boolean;\n force?: boolean;\n pointer?: boolean;\n}): Promise<void> {\n const cwd = process.cwd();\n const configPath = resolve(cwd, CONFIG_FILE);\n\n if (existsSync(configPath) && !options.force) {\n console.log(\n chalk.yellow(\n `${CONFIG_FILE} already exists. Use --force to reinitialize.`,\n ),\n );\n return;\n }\n\n const config: Config = { ...DEFAULT_CONFIG };\n\n saveConfig(config, cwd);\n console.log(chalk.green(`✓ Created ${CONFIG_FILE}`));\n\n // Create directory structure\n const dirs = [\n config.aliases.components,\n config.aliases.motion,\n config.aliases.lib,\n config.aliases.styles,\n ];\n\n for (const dir of dirs) {\n const dirPath = resolve(cwd, dir);\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n console.log(chalk.dim(` Created ${dir}/`));\n }\n }\n\n // Install base items (cn utility + design tokens)\n console.log(chalk.dim(\"Installing base items (cn, tokens)...\"));\n const items = await fetchRegistryItems(BASE_ITEMS);\n for (const item of items) {\n installBaseItem(item, config, cwd);\n }\n\n // Add token CSS imports to the user's stylesheet\n setupCssImports(config, cwd);\n\n // Collect and install npm dependencies for base items\n const npmDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies ?? []) {\n npmDeps.add(dep);\n }\n }\n installNpmDeps([...npmDeps], cwd);\n\n // Optionally add cursor: pointer CSS\n if (options.pointer) {\n const cssPath = resolve(cwd, config.tailwind.css);\n if (existsSync(cssPath)) {\n const existing = readFileSync(cssPath, \"utf-8\");\n if (!existing.includes(\"cursor: pointer\")) {\n writeFileSync(cssPath, existing + \"\\n\" + CURSOR_CSS);\n console.log(\n chalk.green(`✓ Added cursor: pointer to ${config.tailwind.css}`),\n );\n } else {\n console.log(\n chalk.dim(\n ` ${config.tailwind.css} already has cursor: pointer — skipping`,\n ),\n );\n }\n } else {\n writeFileSync(cssPath, CURSOR_CSS);\n console.log(\n chalk.green(`✓ Created ${config.tailwind.css} with cursor: pointer`),\n );\n }\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Ionbit UI initialized!\"));\n console.log(\"\");\n console.log(chalk.dim(\"Next steps:\"));\n console.log(` ${chalk.cyan(\"ionbit-ui add button\")} — add a component`);\n console.log(\n ` ${chalk.cyan(\"ionbit-ui list\")} — browse available components`,\n );\n console.log(\"\");\n}\n\nfunction installBaseItem(\n item: RegistryItem,\n config: Config,\n cwd: string,\n): void {\n for (const file of item.files) {\n const targetPath = resolveTargetPath(file.path, config, cwd);\n if (existsSync(targetPath)) {\n console.log(chalk.dim(` ⚠ ${file.path} already exists — skipping`));\n continue;\n }\n writeFile(targetPath, file.content);\n console.log(chalk.green(` ✓ ${file.path}`));\n }\n}\n\nfunction setupCssImports(config: Config, cwd: string): void {\n const cssPath = resolve(cwd, config.tailwind.css);\n const stylesDir = config.aliases.styles;\n\n // Build the import lines relative to the CSS file's directory\n const tokensImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"tokens.css\"))}\";`;\n const baseImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"base.css\"))}\";`;\n const utilitiesImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"utilities.css\"))}\";`;\n\n if (!existsSync(cssPath)) {\n // Create the CSS file with token imports\n const content = `@import \"tailwindcss\";\\n\\n${tokensImport}\\n${baseImport}\\n${utilitiesImport}\\n`;\n writeFileSync(cssPath, content);\n console.log(\n chalk.green(`✓ Created ${config.tailwind.css} with token imports`),\n );\n return;\n }\n\n const existing = readFileSync(cssPath, \"utf-8\");\n const lines: string[] = [];\n\n if (!existing.includes(\"tokens.css\")) {\n lines.push(tokensImport);\n }\n if (!existing.includes(\"base.css\")) {\n lines.push(baseImport);\n }\n if (!existing.includes(\"utilities.css\")) {\n lines.push(utilitiesImport);\n }\n\n if (lines.length > 0) {\n // Add imports after @import \"tailwindcss\" if present, otherwise at the top\n let updated: string;\n if (existing.includes('@import \"tailwindcss\"')) {\n updated = existing.replace(\n /(@import\\s+\"tailwindcss\"[^\\n]*)/,\n `$1\\n${lines.join(\"\\n\")}`,\n );\n } else {\n updated = lines.join(\"\\n\") + \"\\n\" + existing;\n }\n writeFileSync(cssPath, updated);\n console.log(chalk.green(`✓ Added token imports to ${config.tailwind.css}`));\n } else {\n console.log(\n chalk.dim(\n ` ${config.tailwind.css} already has token imports — skipping`,\n ),\n );\n }\n}\n\nfunction relativePath(from: string, to: string): string {\n let rel = relative(from, to).replace(/\\\\/g, \"/\");\n // Remove the leading \"../\" if the CSS file is in the same or parent directory\n if (rel.startsWith(\"../\")) rel = rel.slice(3);\n return rel;\n}\n","import chalk from \"chalk\";\n\nimport { fetchRegistry } from \"../utils/registry\";\n\nexport async function list(): Promise<void> {\n const registry = await fetchRegistry();\n\n const groups: Record<string, typeof registry.items> = {};\n\n for (const item of registry.items) {\n const category = item.type.replace(\"registry:\", \"\");\n if (!groups[category]) groups[category] = [];\n groups[category].push(item);\n }\n\n const categoryOrder = [\"lib\", \"base\", \"ui\"];\n const sortedCategories = Object.keys(groups).sort((a, b) => {\n const ai = categoryOrder.indexOf(a);\n const bi = categoryOrder.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const category of sortedCategories) {\n const items = groups[category];\n if (!items) continue;\n const label =\n category === \"lib\"\n ? \"Libraries\"\n : category === \"base\"\n ? \"Foundation\"\n : \"Components\";\n\n console.log(chalk.bold(`\\n${label}`));\n\n for (const item of items) {\n const deps = item.dependencies?.length\n ? chalk.dim(` (${item.dependencies.length} deps)`)\n : \"\";\n console.log(` ${chalk.cyan(item.name.padEnd(18))} ${item.title}${deps}`);\n }\n }\n\n console.log(\"\");\n console.log(chalk.dim(`Total: ${registry.items.length} items`));\n console.log(chalk.dim(`Install with: ionbit-ui add <name>`));\n console.log(\"\");\n}\n","import type { Config, ThemeEntry } from \"../config\";\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\n\nimport { ensureDir, loadConfig } from \"../utils/fs\";\nimport { fetchThemeRegistry } from \"../utils/registry\";\n\ninterface CustomTheme {\n dark: Record<string, string>;\n light: Record<string, string>;\n radius: Record<string, string>;\n settings: Record<string, string | number>;\n}\n\nexport async function theme(\n id: string | undefined,\n options: { custom?: string; overwrite?: boolean },\n): Promise<void> {\n const cwd = process.cwd();\n const config = loadConfig(cwd);\n\n if (!config) {\n console.log(\n chalk.red(\"No ionbit-ui.config.json found. Run `ionbit-ui init` first.\"),\n );\n process.exitCode = 1;\n return;\n }\n\n if (id && options.custom) {\n console.log(chalk.red(\"Choose a preset theme or --custom, not both.\"));\n process.exitCode = 1;\n return;\n }\n\n let css: string;\n let label: string;\n if (options.custom) {\n let custom: CustomTheme;\n try {\n custom = JSON.parse(options.custom) as CustomTheme;\n validateCustomTheme(custom);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"invalid JSON\";\n console.log(chalk.red(`Invalid custom theme: ${message}`));\n process.exitCode = 1;\n return;\n }\n label = \"Custom\";\n css = generateThemeCss(custom, label);\n } else {\n if (!id) {\n console.log(chalk.red(\"Provide a theme id or use --custom <json>.\"));\n process.exitCode = 1;\n return;\n }\n const registry = await fetchThemeRegistry();\n const preset = registry.themes.find((entry) => entry.id === id);\n if (!preset) {\n printThemeError(id, registry.themes);\n process.exitCode = 1;\n return;\n }\n label = preset.label;\n css = preset.css;\n }\n\n const themePath = resolve(cwd, config.aliases.styles, \"theme.css\");\n if (existsSync(themePath) && !options.overwrite) {\n console.log(\n chalk.yellow(\n `${config.aliases.styles}/theme.css already exists. Use --overwrite to replace it.`,\n ),\n );\n process.exitCode = 1;\n return;\n }\n\n ensureDir(themePath);\n writeFileSync(themePath, css + \"\\n\");\n addThemeImport(config, cwd, themePath);\n console.log(chalk.green(`✓ Installed ${label} theme`));\n console.log(chalk.dim(` ${config.aliases.styles}/theme.css`));\n}\n\nfunction printThemeError(id: string, themes: ThemeEntry[]): void {\n console.log(chalk.red(`Theme \"${id}\" not found. Available themes:`));\n console.log(themes.map((entry) => ` ${entry.id}`).join(\"\\n\"));\n}\n\nfunction validateCustomTheme(themeConfig: CustomTheme): void {\n for (const mode of [\"dark\", \"light\"] as const) {\n if (!themeConfig[mode] || typeof themeConfig[mode] !== \"object\") {\n throw new Error(`missing ${mode} colors`);\n }\n }\n if (!themeConfig.radius || !themeConfig.settings) {\n throw new Error(\"missing radius or settings\");\n }\n}\n\nfunction addThemeImport(config: Config, cwd: string, themePath: string): void {\n const cssPath = resolve(cwd, config.tailwind.css);\n const importPath = relative(dirname(cssPath), themePath).replace(/\\\\/g, \"/\");\n const importLine = `@import \"./${importPath}\";`;\n const existing = existsSync(cssPath) ? readFileSync(cssPath, \"utf-8\") : \"\";\n\n if (!existing.includes(importLine)) {\n writeFileSync(cssPath, `${existing.trimEnd()}\\n${importLine}\\n`);\n }\n}\n\nfunction colorMix(color: string, amount: number): string {\n return `color-mix(in oklab, ${color} ${amount}%, transparent)`;\n}\n\nfunction hoverColor(color: string): string {\n return `color-mix(in oklab, ${color} 88%, black)`;\n}\n\nfunction colorsToCss(\n colors: Record<string, string>,\n translucency: number,\n light: boolean,\n): string {\n const muted = Math.round(translucency * 160);\n const subtle = Math.round(translucency * 80);\n const borderBase = light ? \"0 0 0\" : \"1 0 0\";\n return [\n ` --background: ${colors.background};`,\n ` --surface: ${colors.surface};`,\n ` --surface-elevated: ${colors.surfaceElevated};`,\n ` --surface-hover: ${colors.surfaceHover};`,\n ` --foreground: ${colors.foreground};`,\n ` --foreground-muted: ${colors.foregroundMuted};`,\n ` --foreground-subtle: ${colors.foregroundSubtle};`,\n ` --accent: ${colors.accent};`,\n ` --accent-hover: ${colors.accentHover};`,\n ` --accent-foreground: ${colors.accentForeground};`,\n ` --accent-muted: ${colorMix(colors.accent!, muted)};`,\n ` --accent-subtle: ${colorMix(colors.accent!, subtle)};`,\n ...statusCss(\"success\", colors.success!, muted, subtle, light, \"155\"),\n ...statusCss(\"warning\", colors.warning!, muted, subtle, light, \"80\"),\n ...statusCss(\"error\", colors.error!, muted, subtle, light, \"5\"),\n ...statusCss(\"info\", colors.info!, muted, subtle, light, \"230\"),\n ` --ring: ${colors.ring};`,\n ` --border: oklch(${borderBase} / ${translucency.toFixed(2)});`,\n ` --border-strong: oklch(${borderBase} / ${(translucency * 1.75).toFixed(2)});`,\n ` --border-accent: ${colorMix(colors.accent!, 50)};`,\n ` --border-error: ${colorMix(colors.error!, 50)};`,\n ` --border-success: ${colorMix(colors.success!, 50)};`,\n ` --border-warning: ${colorMix(colors.warning!, 50)};`,\n ` --border-info: ${colorMix(colors.info!, 50)};`,\n ].join(\"\\n\");\n}\n\nfunction statusCss(\n name: string,\n color: string,\n muted: number,\n subtle: number,\n light: boolean,\n hue: string,\n): string[] {\n return [\n ` --${name}: ${color};`,\n ` --${name}-hover: ${hoverColor(color)};`,\n ` --${name}-muted: ${colorMix(color, muted)};`,\n ` --${name}-subtle: ${colorMix(color, subtle)};`,\n ` --${name}-foreground: ${light ? \"oklch(0.99 0 0)\" : `oklch(0.1 0.03 ${hue})`};`,\n ];\n}\n\nfunction generateThemeCss(theme: CustomTheme, label: string): string {\n const radius = Object.entries(theme.radius)\n .map(([key, value]) => ` --radius-${key}: ${value};`)\n .join(\"\\n\");\n const settings = Object.entries(theme.settings)\n .filter(([key]) => key.endsWith(\"Intensity\"))\n .map(\n ([key, value]) =>\n ` --${key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}: ${value};`,\n )\n .join(\"\\n\");\n const block = (colors: Record<string, string>, light: boolean) =>\n `${light ? \".light\" : \":root\"} {\\n${colorsToCss(colors, Number(theme.settings.translucency), light)}\\n${radius}\\n${settings}\\n}`;\n return `/* Ionbit UI — Theme: ${label} */\\n${block(theme.dark, false)}\\n\\n${block(theme.light, true)}`;\n}\n","import { Command } from \"commander\";\n\nimport { add } from \"./commands/add\";\nimport { init } from \"./commands/init\";\nimport { list } from \"./commands/list\";\nimport { theme } from \"./commands/theme\";\n\nconst program = new Command();\n\nprogram\n .name(\"ionbit-ui\")\n .description(\n \"Ionbit UI CLI — install source-owned components from the Ionbit UI registry.\",\n )\n .version(\"0.1.15\");\n\nprogram\n .command(\"init\")\n .description(\n \"Initialize Ionbit UI in your project. Creates a ionbit-ui.config.json and installs design tokens.\",\n )\n .option(\"-y, --yes\", \"Skip confirmation prompts and use defaults\")\n .option(\"-f, --force\", \"Force overwrite of existing configuration\")\n .option(\n \"--pointer\",\n \"Add cursor: pointer CSS for buttons (Tailwind v4 defaults to cursor: default)\",\n )\n .action(init);\n\nprogram\n .command(\"add <components...>\")\n .description(\n \"Add components to your project. e.g. ionbit-ui add button card accordion\",\n )\n .option(\"-o, --overwrite\", \"Overwrite existing files\")\n .action(add);\n\nprogram\n .command(\"list\")\n .description(\"List all available components in the registry.\")\n .action(list);\n\nprogram\n .command(\"theme [id]\")\n .description(\"Install a preset or custom theme.\")\n .option(\"--custom <json>\", \"Install a custom theme from JSON\")\n .option(\"-o, --overwrite\", \"Overwrite the existing theme.css\")\n .action(theme);\n\nprogram.parse();\n"],"names":["__dirname","theme"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/config.ts","../src/utils/fs.ts","../src/utils/npm.ts","../src/utils/registry.ts","../src/commands/add.ts","../src/commands/init.ts","../src/commands/list.ts","../../tokens/src/theme-css.ts","../src/commands/theme.ts","../src/index.ts"],"sourcesContent":["export const REGISTRY_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry.json\";\n\nexport const REGISTRY_ITEM_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry/items\";\nexport const THEME_REGISTRY_URL =\n \"https://raw.githubusercontent.com/rostislaw9/ionbit-ui/main/registry/themes.json\";\n\nexport interface RegistryItem {\n name: string;\n type: string;\n title: string;\n description: string;\n dependencies?: string[];\n devDependencies?: string[];\n registryDependencies?: string[];\n files: RegistryFile[];\n}\n\nexport interface RegistryFile {\n path: string;\n type: string;\n content: string;\n}\n\nexport interface Registry {\n $schema: string;\n name: string;\n homepage: string;\n items: RegistryItem[];\n}\n\nexport interface ThemeEntry {\n id: string;\n label: string;\n description: string;\n css: string;\n}\n\nexport interface ThemeRegistry {\n themes: ThemeEntry[];\n}\n\nexport interface Config {\n $schema: string;\n style: string;\n tailwind: {\n css: string;\n cssVariables: boolean;\n };\n aliases: {\n components: string;\n motion: string;\n lib: string;\n styles: string;\n };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n $schema: \"https://ui.shadcn.com/schema/registry.json\",\n style: \"digital\",\n tailwind: {\n css: \"src/index.css\",\n cssVariables: true,\n },\n aliases: {\n components: \"src/components/ui\",\n motion: \"src/components/motion\",\n lib: \"src/lib\",\n styles: \"src/styles\",\n },\n};\n\nexport const CONFIG_FILE = \"ionbit-ui.config.json\";\n","import type { Config } from \"../config\";\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { CONFIG_FILE } from \"../config\";\n\nexport function loadConfig(cwd = process.cwd()): Config | null {\n const configPath = resolve(cwd, CONFIG_FILE);\n if (!existsSync(configPath)) return null;\n return JSON.parse(readFileSync(configPath, \"utf-8\")) as Config;\n}\n\nexport function saveConfig(config: Config, cwd = process.cwd()): void {\n const configPath = resolve(cwd, CONFIG_FILE);\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function ensureDir(filePath: string): void {\n const dir = dirname(filePath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nexport function writeFile(filePath: string, content: string): void {\n ensureDir(filePath);\n writeFileSync(filePath, content);\n}\n\nexport function resolveTargetPath(\n target: string,\n config: Config,\n cwd = process.cwd(),\n): string {\n // Map registry target paths to the user's configured aliases.\n // e.g. \"components/ui/button.tsx\" -> \"{cwd}/components/ui/button.tsx\"\n // \"components/motion/spotlight.tsx\" -> \"{cwd}/components/motion/spotlight.tsx\"\n // \"lib/utils.ts\" -> \"{cwd}/lib/utils.ts\"\n // \"styles/tokens.css\" -> \"{cwd}/styles/tokens.css\"\n let resolved = target;\n\n if (target.startsWith(\"components/ui/\")) {\n resolved = target.replace(\n \"components/ui/\",\n config.aliases.components + \"/\",\n );\n } else if (target.startsWith(\"components/motion/\")) {\n resolved = target.replace(\n \"components/motion/\",\n config.aliases.motion + \"/\",\n );\n } else if (target.startsWith(\"lib/\")) {\n resolved = target.replace(\"lib/\", config.aliases.lib + \"/\");\n } else if (target.startsWith(\"styles/\")) {\n resolved = target.replace(\"styles/\", config.aliases.styles + \"/\");\n }\n\n return resolve(cwd, resolved);\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport function detectPackageManager(cwd: string): PackageManager {\n if (existsSync(resolve(cwd, \"bun.lockb\"))) return \"bun\";\n if (existsSync(resolve(cwd, \"bun.lock\"))) return \"bun\";\n if (existsSync(resolve(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(resolve(cwd, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function installNpmDeps(deps: string[], cwd: string): void {\n if (deps.length === 0) return;\n const pm = detectPackageManager(cwd);\n const cmd =\n pm === \"pnpm\"\n ? `pnpm add ${deps.join(\" \")}`\n : pm === \"yarn\"\n ? `yarn add ${deps.join(\" \")}`\n : pm === \"bun\"\n ? `bun add ${deps.join(\" \")}`\n : `npm install ${deps.join(\" \")}`;\n execSync(cmd, { cwd, stdio: \"inherit\" });\n}\n","import type { Registry, RegistryItem, ThemeRegistry } from \"../config\";\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { REGISTRY_ITEM_URL, REGISTRY_URL, THEME_REGISTRY_URL } from \"../config\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Find the registry.json — checks local paths first, then falls back to the\n * remote GitHub URL. This allows development/testing without pushing to GitHub.\n */\nfunction findLocalRegistry(): string | null {\n const candidates = [\n // Relative to cwd (user's project)\n resolve(process.cwd(), \"registry.json\"),\n // Relative to CLI dist (packages/cli/dist -> ../../../registry.json)\n resolve(__dirname, \"../../../registry.json\"),\n // Relative to CLI src/utils (packages/cli/src/utils -> ../../../../registry.json)\n resolve(__dirname, \"../../../../registry.json\"),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction findLocalRegistryItem(name: string): string | null {\n const candidates = [\n resolve(process.cwd(), \"registry/items\", `${name}.json`),\n resolve(__dirname, \"../../../registry/items\", `${name}.json`),\n resolve(__dirname, \"../../../../registry/items\", `${name}.json`),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction findLocalThemes(): string | null {\n const candidates = [\n resolve(process.cwd(), \"registry/themes.json\"),\n resolve(__dirname, \"../../../registry/themes.json\"),\n resolve(__dirname, \"../../../../registry/themes.json\"),\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nexport async function fetchRegistry(): Promise<Registry> {\n const localPath = findLocalRegistry();\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as Registry;\n }\n\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch registry: ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as Registry;\n}\n\nexport async function fetchRegistryItem(name: string): Promise<RegistryItem> {\n const localPath = findLocalRegistryItem(name);\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as RegistryItem;\n }\n\n const res = await fetch(`${REGISTRY_ITEM_URL}/${name}.json`);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch registry item \"${name}\": ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as RegistryItem;\n}\n\nexport async function fetchRegistryItems(\n names: string[],\n): Promise<RegistryItem[]> {\n return Promise.all(names.map(fetchRegistryItem));\n}\n\nexport async function fetchThemeRegistry(): Promise<ThemeRegistry> {\n const localPath = findLocalThemes();\n if (localPath) {\n return JSON.parse(readFileSync(localPath, \"utf-8\")) as ThemeRegistry;\n }\n\n const res = await fetch(THEME_REGISTRY_URL);\n if (!res.ok) {\n throw new Error(\n `Failed to fetch theme registry: ${res.status} ${res.statusText}`,\n );\n }\n return (await res.json()) as ThemeRegistry;\n}\n","import type { Config, RegistryItem } from \"../config\";\n\nimport chalk from \"chalk\";\nimport { existsSync } from \"node:fs\";\n\nimport { loadConfig, resolveTargetPath, writeFile } from \"../utils/fs\";\nimport { installNpmDeps } from \"../utils/npm\";\nimport { fetchRegistry, fetchRegistryItems } from \"../utils/registry\";\n\nexport async function add(\n components: string[],\n options: { overwrite?: boolean },\n): Promise<void> {\n const cwd = process.cwd();\n const config = loadConfig(cwd);\n\n if (!config) {\n console.log(\n chalk.red(\"No ionbit-ui.config.json found. Run `ionbit-ui init` first.\"),\n );\n process.exit(1);\n }\n\n // Fetch the full registry to resolve names and dependencies\n const registry = await fetchRegistry();\n const allNames = new Set(registry.items.map((i) => i.name));\n\n // Validate requested components\n for (const name of components) {\n if (!allNames.has(name)) {\n console.log(\n chalk.red(\n `Component \"${name}\" not found in registry. Run \\`ionbit-ui list\\` to see available components.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Resolve transitive registry dependencies\n const toInstall = resolveDependencies(components, registry.items);\n\n console.log(chalk.dim(`Installing ${toInstall.length} item(s)...`));\n console.log(\"\");\n\n // Fetch all items with embedded content\n const items = await fetchRegistryItems(toInstall);\n\n for (const item of items) {\n await installItem(item, config, cwd, options.overwrite ?? false);\n }\n\n // Collect and install npm dependencies\n const npmDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies ?? []) {\n npmDeps.add(dep);\n }\n }\n\n if (npmDeps.size > 0) {\n console.log(\"\");\n installNpmDeps([...npmDeps], cwd);\n }\n\n console.log(\"\");\n console.log(chalk.green(`✓ Added ${items.length} component(s).`));\n}\n\nfunction resolveDependencies(\n names: string[],\n allItems: { name: string; registryDependencies?: string[] }[],\n): string[] {\n const resolved = new Set<string>();\n const queue = [...names];\n\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (resolved.has(name)) continue;\n resolved.add(name);\n\n const item = allItems.find((i) => i.name === name);\n if (item?.registryDependencies) {\n for (const dep of item.registryDependencies) {\n if (!resolved.has(dep)) queue.push(dep);\n }\n }\n }\n\n return [...resolved];\n}\n\nasync function installItem(\n item: RegistryItem,\n config: Config,\n cwd: string,\n overwrite: boolean,\n): Promise<void> {\n for (const file of item.files) {\n const targetPath = resolveTargetPath(file.path, config, cwd);\n\n if (existsSync(targetPath) && !overwrite) {\n console.log(\n chalk.yellow(\n ` ⚠ ${file.path} already exists — skipping (use --overwrite)`,\n ),\n );\n continue;\n }\n\n writeFile(targetPath, file.content);\n console.log(chalk.green(` ✓ ${file.path}`));\n }\n}\n","import type { Config, RegistryItem } from \"../config\";\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\n\nimport { CONFIG_FILE, DEFAULT_CONFIG } from \"../config\";\nimport { resolveTargetPath, saveConfig, writeFile } from \"../utils/fs\";\nimport { installNpmDeps } from \"../utils/npm\";\nimport { fetchRegistryItems } from \"../utils/registry\";\n\nconst CURSOR_CSS = `@layer base {\n button:not(:disabled),\n [role=\"button\"]:not(:disabled) {\n cursor: pointer;\n }\n}`;\n\n/** Items that every project needs — installed automatically during init. */\nconst BASE_ITEMS = [\"cn\", \"tokens\"];\n\nexport async function init(options: {\n yes?: boolean;\n force?: boolean;\n pointer?: boolean;\n}): Promise<void> {\n const cwd = process.cwd();\n const configPath = resolve(cwd, CONFIG_FILE);\n\n if (existsSync(configPath) && !options.force) {\n console.log(\n chalk.yellow(\n `${CONFIG_FILE} already exists. Use --force to reinitialize.`,\n ),\n );\n return;\n }\n\n const config: Config = { ...DEFAULT_CONFIG };\n\n saveConfig(config, cwd);\n console.log(chalk.green(`✓ Created ${CONFIG_FILE}`));\n\n // Create directory structure\n const dirs = [\n config.aliases.components,\n config.aliases.motion,\n config.aliases.lib,\n config.aliases.styles,\n ];\n\n for (const dir of dirs) {\n const dirPath = resolve(cwd, dir);\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n console.log(chalk.dim(` Created ${dir}/`));\n }\n }\n\n // Install base items (cn utility + design tokens)\n console.log(chalk.dim(\"Installing base items (cn, tokens)...\"));\n const items = await fetchRegistryItems(BASE_ITEMS);\n for (const item of items) {\n installBaseItem(item, config, cwd);\n }\n\n // Add token CSS imports to the user's stylesheet\n setupCssImports(config, cwd);\n\n // Collect and install npm dependencies for base items\n const npmDeps = new Set<string>();\n for (const item of items) {\n for (const dep of item.dependencies ?? []) {\n npmDeps.add(dep);\n }\n }\n installNpmDeps([...npmDeps], cwd);\n\n // Optionally add cursor: pointer CSS\n if (options.pointer) {\n const cssPath = resolve(cwd, config.tailwind.css);\n if (existsSync(cssPath)) {\n const existing = readFileSync(cssPath, \"utf-8\");\n if (!existing.includes(\"cursor: pointer\")) {\n writeFileSync(cssPath, existing + \"\\n\" + CURSOR_CSS);\n console.log(\n chalk.green(`✓ Added cursor: pointer to ${config.tailwind.css}`),\n );\n } else {\n console.log(\n chalk.dim(\n ` ${config.tailwind.css} already has cursor: pointer — skipping`,\n ),\n );\n }\n } else {\n writeFileSync(cssPath, CURSOR_CSS);\n console.log(\n chalk.green(`✓ Created ${config.tailwind.css} with cursor: pointer`),\n );\n }\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Ionbit UI initialized!\"));\n console.log(\"\");\n console.log(chalk.dim(\"Next steps:\"));\n console.log(` ${chalk.cyan(\"ionbit-ui add button\")} — add a component`);\n console.log(\n ` ${chalk.cyan(\"ionbit-ui list\")} — browse available components`,\n );\n console.log(\"\");\n}\n\nfunction installBaseItem(\n item: RegistryItem,\n config: Config,\n cwd: string,\n): void {\n for (const file of item.files) {\n const targetPath = resolveTargetPath(file.path, config, cwd);\n if (existsSync(targetPath)) {\n console.log(chalk.dim(` ⚠ ${file.path} already exists — skipping`));\n continue;\n }\n writeFile(targetPath, file.content);\n console.log(chalk.green(` ✓ ${file.path}`));\n }\n}\n\nfunction setupCssImports(config: Config, cwd: string): void {\n const cssPath = resolve(cwd, config.tailwind.css);\n const stylesDir = config.aliases.styles;\n\n // Build the import lines relative to the CSS file's directory\n const tokensImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"tokens.css\"))}\";`;\n const baseImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"base.css\"))}\";`;\n const utilitiesImport = `@import \"./${relativePath(cssPath, resolve(cwd, stylesDir, \"utilities.css\"))}\";`;\n\n if (!existsSync(cssPath)) {\n // Create the CSS file with token imports\n const content = `@import \"tailwindcss\";\\n\\n${tokensImport}\\n${baseImport}\\n${utilitiesImport}\\n`;\n writeFileSync(cssPath, content);\n console.log(\n chalk.green(`✓ Created ${config.tailwind.css} with token imports`),\n );\n return;\n }\n\n const existing = readFileSync(cssPath, \"utf-8\");\n const lines: string[] = [];\n\n if (!existing.includes(\"tokens.css\")) {\n lines.push(tokensImport);\n }\n if (!existing.includes(\"base.css\")) {\n lines.push(baseImport);\n }\n if (!existing.includes(\"utilities.css\")) {\n lines.push(utilitiesImport);\n }\n\n if (lines.length > 0) {\n // Add imports after @import \"tailwindcss\" if present, otherwise at the top\n let updated: string;\n if (existing.includes('@import \"tailwindcss\"')) {\n updated = existing.replace(\n /(@import\\s+\"tailwindcss\"[^\\n]*)/,\n `$1\\n${lines.join(\"\\n\")}`,\n );\n } else {\n updated = lines.join(\"\\n\") + \"\\n\" + existing;\n }\n writeFileSync(cssPath, updated);\n console.log(chalk.green(`✓ Added token imports to ${config.tailwind.css}`));\n } else {\n console.log(\n chalk.dim(\n ` ${config.tailwind.css} already has token imports — skipping`,\n ),\n );\n }\n}\n\nfunction relativePath(from: string, to: string): string {\n let rel = relative(from, to).replace(/\\\\/g, \"/\");\n // Remove the leading \"../\" if the CSS file is in the same or parent directory\n if (rel.startsWith(\"../\")) rel = rel.slice(3);\n return rel;\n}\n","import chalk from \"chalk\";\n\nimport { fetchRegistry } from \"../utils/registry\";\n\nexport async function list(): Promise<void> {\n const registry = await fetchRegistry();\n\n const groups: Record<string, typeof registry.items> = {};\n\n for (const item of registry.items) {\n const category = item.type.replace(\"registry:\", \"\");\n if (!groups[category]) groups[category] = [];\n groups[category].push(item);\n }\n\n const categoryOrder = [\"lib\", \"base\", \"ui\"];\n const sortedCategories = Object.keys(groups).sort((a, b) => {\n const ai = categoryOrder.indexOf(a);\n const bi = categoryOrder.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const category of sortedCategories) {\n const items = groups[category];\n if (!items) continue;\n const label =\n category === \"lib\"\n ? \"Libraries\"\n : category === \"base\"\n ? \"Foundation\"\n : \"Components\";\n\n console.log(chalk.bold(`\\n${label}`));\n\n for (const item of items) {\n const deps = item.dependencies?.length\n ? chalk.dim(` (${item.dependencies.length} deps)`)\n : \"\";\n console.log(` ${chalk.cyan(item.name.padEnd(18))} ${item.title}${deps}`);\n }\n }\n\n console.log(\"\");\n console.log(chalk.dim(`Total: ${registry.items.length} items`));\n console.log(chalk.dim(`Install with: ionbit-ui add <name>`));\n console.log(\"\");\n}\n","import type {\n ShadowIntensity,\n ThemeColors,\n ThemePreset,\n ThemeRadius,\n ThemeSettings,\n} from \"./theme-types\";\n\nfunction mix(color: string, amount: number): string {\n return `color-mix(in oklab, ${color} ${amount}%, transparent)`;\n}\n\n/** Multiplier applied to the mode-specific shadow alphas per tier. */\nconst SHADOW_SCALE: Record<ShadowIntensity, number> = {\n subtle: 0.6,\n normal: 1,\n dramatic: 1.5,\n};\n\nfunction hover(color: string): string {\n return `color-mix(in oklab, ${color} 88%, black)`;\n}\n\nexport function colorsToCss(\n c: ThemeColors,\n s: ThemeSettings,\n isLight: boolean,\n): string {\n const { translucency } = s;\n const k = SHADOW_SCALE[s.shadowIntensity];\n const alpha = (base: number) => (base * k).toFixed(2);\n const borderBase = isLight ? \"0 0 0\" : \"1 0 0\";\n const borderAlpha = translucency.toFixed(2);\n const mutedAmount = Math.round(translucency * 160);\n const subtleAmount = Math.round(translucency * 80);\n\n return [\n ` --background: ${c.background};`,\n ` --surface: ${c.surface};`,\n ` --surface-elevated: ${c.surfaceElevated};`,\n ` --surface-hover: ${c.surfaceHover};`,\n ` --foreground: ${c.foreground};`,\n ` --foreground-muted: ${c.foregroundMuted};`,\n ` --foreground-subtle: ${c.foregroundSubtle};`,\n ` --accent: ${c.accent};`,\n ` --accent-hover: ${c.accentHover};`,\n ` --accent-foreground: ${c.accentForeground};`,\n ` --accent-muted: ${mix(c.accent, mutedAmount)};`,\n ` --accent-subtle: ${mix(c.accent, subtleAmount)};`,\n ` --success: ${c.success};`,\n ` --success-hover: ${hover(c.success)};`,\n ` --success-muted: ${mix(c.success, mutedAmount)};`,\n ` --success-subtle: ${mix(c.success, subtleAmount)};`,\n ` --success-foreground: ${isLight ? \"oklch(0.99 0 0)\" : \"oklch(0.1 0.03 155)\"};`,\n ` --warning: ${c.warning};`,\n ` --warning-hover: ${hover(c.warning)};`,\n ` --warning-muted: ${mix(c.warning, mutedAmount)};`,\n ` --warning-subtle: ${mix(c.warning, subtleAmount)};`,\n ` --warning-foreground: ${isLight ? \"oklch(0.99 0 0)\" : \"oklch(0.1 0.03 80)\"};`,\n ` --error: ${c.error};`,\n ` --error-hover: ${hover(c.error)};`,\n ` --error-muted: ${mix(c.error, mutedAmount)};`,\n ` --error-subtle: ${mix(c.error, subtleAmount)};`,\n ` --error-foreground: ${isLight ? \"oklch(0.99 0 0)\" : \"oklch(0.1 0.04 5)\"};`,\n ` --info: ${c.info};`,\n ` --info-hover: ${hover(c.info)};`,\n ` --info-muted: ${mix(c.info, mutedAmount)};`,\n ` --info-subtle: ${mix(c.info, subtleAmount)};`,\n ` --info-foreground: ${isLight ? \"oklch(0.99 0 0)\" : \"oklch(0.1 0.03 230)\"};`,\n ` --ring: ${c.ring};`,\n ` --border: oklch(${borderBase} / ${borderAlpha});`,\n ` --border-strong: oklch(${borderBase} / ${(translucency * 1.75).toFixed(2)});`,\n ` --border-accent: ${mix(c.accent, 50)};`,\n ` --border-error: ${mix(c.error, 50)};`,\n ` --border-success: ${mix(c.success, 50)};`,\n ` --border-warning: ${mix(c.warning, 50)};`,\n ` --border-info: ${mix(c.info, 50)};`,\n ` --shadow-xs: 0 1px 2px 0 oklch(0 0 0 / ${alpha(isLight ? 0.06 : 0.2)});`,\n ` --shadow-sm: 0 2px 4px -1px oklch(0 0 0 / ${alpha(isLight ? 0.08 : 0.25)}), 0 1px 2px -1px oklch(0 0 0 / ${alpha(isLight ? 0.06 : 0.2)});`,\n ` --shadow-md: 0 4px 8px -2px oklch(0 0 0 / ${alpha(isLight ? 0.1 : 0.3)}), 0 2px 4px -2px oklch(0 0 0 / ${alpha(isLight ? 0.08 : 0.25)});`,\n ` --shadow-lg: 0 12px 24px -8px oklch(0 0 0 / ${alpha(isLight ? 0.12 : 0.4)}), 0 4px 8px -4px oklch(0 0 0 / ${alpha(isLight ? 0.1 : 0.3)});`,\n ].join(\"\\n\");\n}\n\nexport function radiusToCss(r: ThemeRadius): string {\n return [\n ` --radius-sm: ${r.sm};`,\n ` --radius-md: ${r.md};`,\n ` --radius-lg: ${r.lg};`,\n ` --radius-xl: ${r.xl};`,\n ].join(\"\\n\");\n}\n\nexport function settingsToCss(s: ThemeSettings): string {\n return [\n ` --spotlight-intensity: ${s.spotlightIntensity};`,\n ` --magnetic-intensity: ${s.magneticIntensity};`,\n ` --glow-intensity: ${s.glowIntensity};`,\n ` --pulse-intensity: ${s.pulseIntensity};`,\n ` --ripple-intensity: ${s.rippleIntensity};`,\n ` --tilt-intensity: ${s.tiltIntensity};`,\n ` --reflection-intensity: ${s.reflectionIntensity};`,\n ` --scramble-intensity: ${s.scrambleIntensity};`,\n ` --trace-intensity: ${s.traceIntensity};`,\n ].join(\"\\n\");\n}\n\nexport function generateThemeCss(preset: ThemePreset): string {\n const darkBlock = `:root {\\n${colorsToCss(preset.dark, preset.settings, false)}\\n${radiusToCss(preset.radius)}\\n${settingsToCss(preset.settings)}\\n}`;\n const lightBlock = `.light {\\n${colorsToCss(preset.light, preset.settings, true)}\\n${radiusToCss(preset.radius)}\\n${settingsToCss(preset.settings)}\\n}`;\n\n return `/* Ionbit UI — Theme: ${preset.label} */\\n${darkBlock}\\n\\n${lightBlock}`;\n}\n","import type { Config, ThemeEntry } from \"../config\";\nimport type { ThemePreset } from \"@ionbit-ui/tokens/theme-types\";\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\n\nimport { generateThemeCss } from \"@ionbit-ui/tokens/theme-css\";\n\nimport { ensureDir, loadConfig } from \"../utils/fs\";\nimport { fetchThemeRegistry } from \"../utils/registry\";\n\ninterface CustomTheme {\n dark: Record<string, string>;\n light: Record<string, string>;\n radius: Record<string, string>;\n settings: Record<string, string | number>;\n}\n\nexport async function theme(\n id: string | undefined,\n options: { custom?: string; overwrite?: boolean },\n): Promise<void> {\n const cwd = process.cwd();\n const config = loadConfig(cwd);\n\n if (!config) {\n console.log(\n chalk.red(\"No ionbit-ui.config.json found. Run `ionbit-ui init` first.\"),\n );\n process.exitCode = 1;\n return;\n }\n\n if (id && options.custom) {\n console.log(chalk.red(\"Choose a preset theme or --custom, not both.\"));\n process.exitCode = 1;\n return;\n }\n\n let css: string;\n let label: string;\n if (options.custom) {\n let custom: CustomTheme;\n try {\n custom = JSON.parse(options.custom) as CustomTheme;\n validateCustomTheme(custom);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"invalid JSON\";\n console.log(chalk.red(`Invalid custom theme: ${message}`));\n process.exitCode = 1;\n return;\n }\n label = \"Custom\";\n css = generateThemeCss({\n ...custom,\n id: \"custom\",\n label,\n description: \"\",\n } as unknown as ThemePreset);\n } else {\n if (!id) {\n console.log(chalk.red(\"Provide a theme id or use --custom <json>.\"));\n process.exitCode = 1;\n return;\n }\n const registry = await fetchThemeRegistry();\n const preset = registry.themes.find((entry) => entry.id === id);\n if (!preset) {\n printThemeError(id, registry.themes);\n process.exitCode = 1;\n return;\n }\n label = preset.label;\n css = preset.css;\n }\n\n const themePath = resolve(cwd, config.aliases.styles, \"theme.css\");\n if (existsSync(themePath) && !options.overwrite) {\n console.log(\n chalk.yellow(\n `${config.aliases.styles}/theme.css already exists. Use --overwrite to replace it.`,\n ),\n );\n process.exitCode = 1;\n return;\n }\n\n ensureDir(themePath);\n writeFileSync(themePath, css + \"\\n\");\n addThemeImport(config, cwd, themePath);\n console.log(chalk.green(`✓ Installed ${label} theme`));\n console.log(chalk.dim(` ${config.aliases.styles}/theme.css`));\n}\n\nfunction printThemeError(id: string, themes: ThemeEntry[]): void {\n console.log(chalk.red(`Theme \"${id}\" not found. Available themes:`));\n console.log(themes.map((entry) => ` ${entry.id}`).join(\"\\n\"));\n}\n\nfunction validateCustomTheme(themeConfig: CustomTheme): void {\n for (const mode of [\"dark\", \"light\"] as const) {\n if (!themeConfig[mode] || typeof themeConfig[mode] !== \"object\") {\n throw new Error(`missing ${mode} colors`);\n }\n }\n if (!themeConfig.radius || !themeConfig.settings) {\n throw new Error(\"missing radius or settings\");\n }\n}\n\nfunction addThemeImport(config: Config, cwd: string, themePath: string): void {\n const cssPath = resolve(cwd, config.tailwind.css);\n const importPath = relative(dirname(cssPath), themePath).replace(/\\\\/g, \"/\");\n const importLine = `@import \"./${importPath}\";`;\n const existing = existsSync(cssPath) ? readFileSync(cssPath, \"utf-8\") : \"\";\n\n if (!existing.includes(importLine)) {\n writeFileSync(cssPath, `${existing.trimEnd()}\\n${importLine}\\n`);\n }\n}\n","import { Command } from \"commander\";\n\nimport { add } from \"./commands/add\";\nimport { init } from \"./commands/init\";\nimport { list } from \"./commands/list\";\nimport { theme } from \"./commands/theme\";\n\nconst program = new Command();\n\nprogram\n .name(\"ionbit-ui\")\n .description(\n \"Ionbit UI CLI — install source-owned components from the Ionbit UI registry.\",\n )\n .version(\"0.2.0\");\n\nprogram\n .command(\"init\")\n .description(\n \"Initialize Ionbit UI in your project. Creates a ionbit-ui.config.json and installs design tokens.\",\n )\n .option(\"-y, --yes\", \"Skip confirmation prompts and use defaults\")\n .option(\"-f, --force\", \"Force overwrite of existing configuration\")\n .option(\n \"--pointer\",\n \"Add cursor: pointer CSS for buttons (Tailwind v4 defaults to cursor: default)\",\n )\n .action(init);\n\nprogram\n .command(\"add <components...>\")\n .description(\n \"Add components to your project. e.g. ionbit-ui add button card accordion\",\n )\n .option(\"-o, --overwrite\", \"Overwrite existing files\")\n .action(add);\n\nprogram\n .command(\"list\")\n .description(\"List all available components in the registry.\")\n .action(list);\n\nprogram\n .command(\"theme [id]\")\n .description(\"Install a preset or custom theme.\")\n .option(\"--custom <json>\", \"Install a custom theme from JSON\")\n .option(\"-o, --overwrite\", \"Overwrite the existing theme.css\")\n .action(theme);\n\nprogram.parse();\n"],"names":["__dirname"],"mappings":"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"}
package/dist/tokens.css CHANGED
@@ -145,9 +145,17 @@
145
145
  --ease-emphasized: cubic-bezier(0.3, 0, 0, 1);
146
146
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
147
147
 
148
- /* Effect intensities — 0..1 multipliers. */
148
+ /* Effect intensities — 0..1 multipliers. Mirrors motionTokens.intensity
149
+ in @ionbit-ui/motion; these vars override the JS fallbacks. */
150
+ --glow-intensity: 0.7;
151
+ --magnetic-intensity: 0.2;
152
+ --pulse-intensity: 0.65;
153
+ --ripple-intensity: 0.3;
154
+ --scramble-intensity: 0.6;
149
155
  --spotlight-intensity: 0.4;
150
- --magnetic-intensity: 0.25;
156
+ --tilt-intensity: 0.5;
157
+ --reflection-intensity: 0.35;
158
+ --trace-intensity: 0.6;
151
159
  }
152
160
 
153
161
  /* ---------------------------------------------------------------------------
@@ -298,7 +306,7 @@
298
306
  --ease-emphasized: var(--ease-emphasized);
299
307
  --ease-exit: var(--ease-exit);
300
308
 
301
- /* Accordion expand/collapse — syncs with Radix's --radix-accordion-content-height */
309
+ /* Accordion expand/collapse — syncs with Base UI's --accordion-panel-height */
302
310
  --animate-accordion-down: accordion-down var(--duration-normal)
303
311
  var(--ease-standard);
304
312
  --animate-accordion-up: accordion-up var(--duration-normal)
@@ -309,13 +317,13 @@
309
317
  height: 0;
310
318
  }
311
319
  to {
312
- height: var(--radix-accordion-content-height);
320
+ height: var(--accordion-panel-height);
313
321
  }
314
322
  }
315
323
 
316
324
  @keyframes accordion-up {
317
325
  from {
318
- height: var(--radix-accordion-content-height);
326
+ height: var(--accordion-panel-height);
319
327
  }
320
328
  to {
321
329
  height: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ionbit-ui",
3
- "version": "0.1.15",
3
+ "version": "0.2.0",
4
4
  "description": "Ionbit UI CLI — install source-owned components from the Ionbit UI registry.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,6 +47,7 @@
47
47
  "commander": "^15.0.0"
48
48
  },
49
49
  "devDependencies": {
50
+ "@ionbit-ui/tokens": "workspace:^",
50
51
  "typescript": "^5.6.0",
51
52
  "vite": "^5.4.0"
52
53
  },