{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "code-block-command", "title": "Code Block Command", "author": "tusharvarshney ", "description": "Display install commands with package manager switcher and copy button.", "dependencies": [ "@base-ui/react", "motion", "jotai" ], "registryDependencies": [ "https://tusharvarshney.com/r/copy-button.json" ], "files": [ { "path": "src/registry/components/code-block-command/code-block-command.tsx", "content": "\"use client\"\n\nimport { ScrollArea } from \"@base-ui/react/scroll-area\"\nimport { useAtom } from \"jotai\"\nimport { atomWithStorage } from \"jotai/utils\"\nimport { useMemo } from \"react\"\n\nimport {\n Tabs,\n TabsContent,\n TabsIndicator,\n TabsList,\n TabsTrigger,\n} from \"@/components/base/ui/tabs\"\nimport { IconPlaceholder } from \"@/components/icon-placeholder\"\nimport { cn } from \"@/lib/utils\"\nimport { CopyButton } from \"@/registry/components/copy-button\"\n\nexport type PackageManager = \"prompt\" | \"pnpm\" | \"yarn\" | \"npm\" | \"bun\"\n\nconst packageManagerAtom = atomWithStorage(\n \"packageManager\",\n \"pnpm\"\n)\n\nexport function usePackageManager() {\n return useAtom(packageManagerAtom)\n}\n\n/**\n * Props for the CodeBlockCommand component.\n */\nexport type CodeBlockCommandProps = {\n /**\n * Natural language instruction for AI agents to install a package or component.\n */\n prompt?: string\n /**\n * Command to execute with pnpm package manager.\n */\n pnpm?: string\n\n /**\n * Command to execute with yarn package manager.\n */\n yarn?: string\n\n /**\n * Command to execute with npm package manager.\n */\n npm?: string\n\n /**\n * Command to execute with bun package manager.\n */\n bun?: string\n\n /**\n * Callback invoked when a command is successfully copied to clipboard.\n *\n * Receives an object containing the selected package manager and the copied command text.\n * Useful for tracking user interactions or showing custom success notifications.\n *\n * @param data - Object containing copy operation details\n * @param data.packageManager - The package manager that was selected when copying\n * @param data.command - The actual command text that was copied\n *\n * @example\n * ```tsx\n * {\n * console.log(`Copied ${command} for ${packageManager}`)\n * }}\n * />\n * ```\n */\n onCopySuccess?: (data: {\n packageManager: PackageManager\n command: string\n }) => void\n\n /**\n * Callback invoked when copying to clipboard fails.\n *\n * Receives the error object for debugging or showing custom error messages.\n *\n * @param error - The error that occurred during the copy operation\n *\n * @example\n * ```tsx\n * {\n * console.error('Copy failed:', error)\n * }}\n * />\n * ```\n */\n onCopyError?: (error: Error) => void\n}\n\nexport function CodeBlockCommand({\n prompt,\n pnpm,\n yarn,\n npm,\n bun,\n onCopySuccess,\n onCopyError,\n}: CodeBlockCommandProps) {\n const [packageManager, setPackageManager] = usePackageManager()\n\n const tabs = useMemo(() => {\n return {\n prompt,\n pnpm,\n yarn,\n npm,\n bun,\n }\n }, [prompt, pnpm, yarn, npm, bun])\n\n const tabsFiltered = useMemo(\n () => Object.entries(tabs).filter(([, value]) => !!value),\n [tabs]\n )\n\n return (\n
\n {\n setPackageManager(value as PackageManager)\n }}\n >\n \n }\n >\n {getIconForPackageManager(packageManager)}\n\n {tabsFiltered.map(([key]) => {\n return (\n \n {key}\n \n )\n })}\n\n \n \n \n\n {tabsFiltered.map(([key, value]) => {\n return (\n \n \n \n \n ${\" \"}\n \n {value}\n \n \n \n )\n })}\n \n\n {\n onCopySuccess?.({\n packageManager,\n command: copiedCommand,\n })\n }}\n onCopyError={onCopyError}\n />\n
\n )\n}\n\nfunction getIconForPackageManager(manager: PackageManager) {\n switch (manager) {\n case \"prompt\":\n return (\n \n )\n case \"pnpm\":\n return (\n \n \n \n )\n case \"yarn\":\n return (\n \n \n \n )\n case \"npm\":\n return (\n \n \n \n )\n case \"bun\":\n return (\n \n \n \n )\n default:\n return (\n \n )\n }\n}\n\n/**\n * Result of converting an npm command to all package managers.\n */\nexport type ConvertNpmCommandResult = {\n /**\n * Command for pnpm package manager.\n */\n pnpm: string\n\n /**\n * Command for yarn package manager.\n */\n yarn: string\n\n /**\n * Command for npm package manager.\n */\n npm: string\n\n /**\n * Command for bun package manager.\n */\n bun: string\n}\n\n/**\n * Converts a standard npm command into equivalent commands for pnpm, yarn, npm,\n * and bun. The result can be spread directly into `CodeBlockCommand` props.\n *\n * Supported command patterns:\n * - `npm install ` -> add commands for each manager\n * - `npx create-` -> create commands for each manager\n * - `npm create ` -> create commands for each manager\n * - `npx ` -> execute commands for each manager\n * - `npm run