diff --git a/apps/ui-library/components.json b/apps/ui-library/components.json new file mode 100644 index 00000000000..80d94f1fc9c --- /dev/null +++ b/apps/ui-library/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "app/globals.css", + "baseColor": "gray", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/registry/default/components", + "utils": "@/lib/utils", + "ui": "@/registry/default/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/apps/ui-library/components/block-item-code.tsx b/apps/ui-library/components/block-item-code.tsx new file mode 100644 index 00000000000..05007873138 --- /dev/null +++ b/apps/ui-library/components/block-item-code.tsx @@ -0,0 +1,119 @@ +'use client' + +import { RegistryNode } from '@/lib/process-registry' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@ui/components/shadcn/ui/tabs' +import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock' +import { File, Folder } from 'fumadocs-ui/components/files' +import { useState } from 'react' +import { BlockItemPreview } from './block-item' + +interface BlockItemCodeProps { + files: RegistryNode[] +} + +const demoUrls: Record = { + 'src/registry/blocks/password-based-auth-nextjs/app/login/page.tsx': + '/blocks/password-based-auth-nextjs/login', + 'src/registry/blocks/password-based-auth-nextjs/app/sign-up/page.tsx': + '/blocks/password-based-auth-nextjs/sign-up', + 'src/registry/blocks/password-based-auth-nextjs/app/sign-up-success/page.tsx': + '/blocks/password-based-auth-nextjs/sign-up-success', + 'src/registry/blocks/password-based-auth-nextjs/app/forgot-password/page.tsx': + '/blocks/password-based-auth-nextjs/forgot-password', + 'src/registry/blocks/password-based-auth-nextjs/app/update-password/page.tsx': + '/blocks/password-based-auth-nextjs/update-password', +} + +function FileTree({ + items, + onFileSelect, +}: { + items: RegistryNode[] + onFileSelect: (file: RegistryNode) => void +}) { + if (items.length === 0) { + return null + } + + return ( + <> + {items.map((item, index) => { + if (item.type === 'directory') { + return ( + + + + ) + } + return ( + onFileSelect(item)} + className="cursor-pointer" + /> + ) + })} + + ) +} + +export function BlockItemCode({ files }: BlockItemCodeProps) { + const initialFile = files.find((file) => file.type === 'file') || null + const [selectedFile, setSelectedFile] = useState(initialFile) + + const selectedFilePath = selectedFile?.path.startsWith('/') + ? selectedFile?.path.slice(1) + : selectedFile?.path + const selectedFileExtension = (selectedFile?.name.split('.').pop() ?? 'ts') as 'ts' | 'tsx' + + const selectedFileDemoUrl = selectedFile?.originalPath + ? demoUrls[selectedFile?.originalPath] + : null + + return ( +
+ {/* File browser sidebar */} +
+
+

Files

+
+
+ +
+
+ + {/* Code display area */} +
+ {selectedFile?.content ? ( +
+ +
+ {selectedFilePath} + {selectedFileDemoUrl && ( + + Preview + Code + + )} +
+ + + + + {selectedFileDemoUrl && } + +
+
+ ) : ( +
+ No file selected or file content unavailable +
+ )} +
+
+ ) +} diff --git a/apps/ui-library/components/block-item.tsx b/apps/ui-library/components/block-item.tsx new file mode 100644 index 00000000000..d6efed06122 --- /dev/null +++ b/apps/ui-library/components/block-item.tsx @@ -0,0 +1,29 @@ +import { Command } from '@/components/command' +import { OpenInV0Button } from '@/components/open-in-v0-button' + +interface BlockItemProps { + name: string + title: string + description: string + src: string +} + +export const BlockItem = ({ name, description }: BlockItemProps) => { + return ( +
+ +
+

{description}

+ +
+
+ ) +} + +export const BlockItemPreview = ({ title, src }: { title: string; src: string }) => { + return ( +
+