23 lines
6.3 KiB
JSON
23 lines
6.3 KiB
JSON
{
|
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
"name": "files",
|
|
"type": "registry:ui",
|
|
"title": "Files",
|
|
"description": "A component that allows you to display a list of files and folders.",
|
|
"dependencies": [
|
|
"motion",
|
|
"lucide-react"
|
|
],
|
|
"registryDependencies": [
|
|
"https://animate-ui.com/r/motion-highlight",
|
|
"https://animate-ui.com/r/radix-accordion"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "registry/components/files/index.tsx",
|
|
"content": "'use client';\n\nimport * as React from 'react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport { FileIcon, FolderIcon, FolderOpenIcon } from 'lucide-react';\n\nimport { cn } from '@/lib/utils';\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionItemProps,\n AccordionTrigger,\n AccordionTriggerProps,\n useAccordionItem,\n} from '@/components/animate-ui/radix/accordion';\nimport {\n MotionHighlight,\n MotionHighlightItem,\n} from '@/components/animate-ui/effects/motion-highlight';\n\ntype FileButtonProps = React.ComponentProps<'div'> & {\n icons?: {\n close: React.ReactNode;\n open: React.ReactNode;\n };\n icon?: React.ReactNode;\n open?: boolean;\n sideComponent?: React.ReactNode;\n};\n\nfunction FileButton({\n children,\n className,\n icons,\n icon,\n open,\n sideComponent,\n ...props\n}: FileButtonProps) {\n return (\n <MotionHighlightItem className=\"size-full\">\n <div\n data-slot=\"file-button\"\n className={cn(\n 'flex items-center truncate gap-2 p-2 h-10 relative z-10 rounded-lg w-full cursor-default',\n className,\n )}\n {...props}\n >\n <span className=\"flex [&_svg]:size-4 [&_svg]:shrink-0 items-center gap-2 shrink-1 truncate\">\n {icon\n ? typeof icon !== 'string'\n ? icon\n : null\n : icons && (\n <AnimatePresence mode=\"wait\">\n <motion.span\n key={open ? 'open' : 'close'}\n initial={{ scale: 0.9 }}\n animate={{ scale: 1 }}\n exit={{ scale: 0.9 }}\n transition={{ duration: 0.15 }}\n >\n {open\n ? typeof icons.open !== 'string'\n ? icons.open\n : null\n : typeof icons.close !== 'string'\n ? icons.close\n : null}\n </motion.span>\n </AnimatePresence>\n )}\n <span className=\"shrink-1 text-sm block truncate break-words\">\n {children}\n </span>\n </span>\n {sideComponent}\n </div>\n </MotionHighlightItem>\n );\n}\n\ntype FilesProps = React.ComponentProps<'div'> & {\n children: React.ReactNode;\n activeClassName?: string;\n defaultOpen?: string[];\n open?: string[];\n onOpenChange?: (open: string[]) => void;\n};\n\nfunction Files({\n children,\n className,\n activeClassName,\n defaultOpen,\n open,\n onOpenChange,\n ...props\n}: FilesProps) {\n return (\n <div\n data-slot=\"files\"\n className={cn(\n 'relative size-full rounded-xl border bg-background overflow-auto',\n className,\n )}\n {...props}\n >\n <MotionHighlight\n controlledItems\n mode=\"parent\"\n hover\n className={cn(\n 'bg-muted rounded-lg pointer-events-none',\n activeClassName,\n )}\n >\n <Accordion\n type=\"multiple\"\n className=\"p-2\"\n defaultValue={defaultOpen}\n value={open}\n onValueChange={onOpenChange}\n >\n {children}\n </Accordion>\n </MotionHighlight>\n </div>\n );\n}\n\ntype FolderTriggerProps = AccordionTriggerProps & {\n sideComponent?: React.ReactNode;\n};\n\nfunction FolderTrigger({\n children,\n className,\n sideComponent,\n ...props\n}: FolderTriggerProps) {\n const { isOpen } = useAccordionItem();\n\n return (\n <AccordionTrigger\n data-slot=\"folder-trigger\"\n className=\"h-auto py-0 hover:no-underline font-normal relative z-10 max-w-full\"\n {...props}\n chevron={false}\n >\n <FileButton\n open={isOpen}\n icons={{ open: <FolderOpenIcon />, close: <FolderIcon /> }}\n className={className}\n sideComponent={sideComponent}\n >\n {children}\n </FileButton>\n </AccordionTrigger>\n );\n}\n\ntype FolderProps = Omit<\n AccordionItemProps,\n 'value' | 'onValueChange' | 'defaultValue' | 'children'\n> & {\n children?: React.ReactNode;\n name: string;\n open?: string[];\n onOpenChange?: (open: string[]) => void;\n defaultOpen?: string[];\n sideComponent?: React.ReactNode;\n};\n\nfunction Folder({\n children,\n className,\n name,\n open,\n defaultOpen,\n onOpenChange,\n sideComponent,\n ...props\n}: FolderProps) {\n return (\n <AccordionItem\n data-slot=\"folder\"\n value={name}\n className=\"relative border-b-0\"\n {...props}\n >\n <FolderTrigger className={className} sideComponent={sideComponent}>\n {name}\n </FolderTrigger>\n {children && (\n <AccordionContent className=\"relative pb-0 !ml-7 before:absolute before:-left-3 before:inset-y-0 before:w-px before:h-full before:bg-border\">\n <Accordion\n type=\"multiple\"\n defaultValue={defaultOpen}\n value={open}\n onValueChange={onOpenChange}\n >\n {children}\n </Accordion>\n </AccordionContent>\n )}\n </AccordionItem>\n );\n}\n\ntype FileProps = Omit<React.ComponentProps<'div'>, 'children'> & {\n name: string;\n sideComponent?: React.ReactNode;\n};\n\nfunction File({ name, className, sideComponent, ...props }: FileProps) {\n return (\n <FileButton\n data-slot=\"file\"\n icon={<FileIcon />}\n className={className}\n sideComponent={sideComponent}\n {...props}\n >\n {name}\n </FileButton>\n );\n}\n\nexport {\n Files,\n Folder,\n File,\n type FilesProps,\n type FolderProps,\n type FileProps,\n};\n",
|
|
"type": "registry:ui",
|
|
"target": "components/animate-ui/components/files.tsx"
|
|
}
|
|
]
|
|
} |