{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table",
  "type": "registry:ui",
  "title": "Table",
  "description": "Powerful responsive data table with sticky headers, smooth scrolling, sorting, and pagination.",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": ["@scrollxui/button", "@scrollxui/dropdown-menu"],
  "dependencies": [
    "motion",
    "@tanstack/react-table",
    "lucide-react",
    "@radix-ui/react-dropdown-menu",
    "@radix-ui/react-slot",
    "class-variance-authority",
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/table.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport {\n  ColumnDef,\n  ColumnFiltersState,\n  SortingState,\n  VisibilityState,\n  flexRender,\n  getCoreRowModel,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  useReactTable,\n  PaginationState,\n  Column,\n  Row,\n} from '@tanstack/react-table';\nimport { motion, AnimatePresence } from 'motion/react';\nimport {\n  ChevronDown,\n  ChevronUp,\n  Search,\n  Eye,\n  Filter,\n  ArrowLeft,\n  ArrowRight,\n} from 'lucide-react';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuCheckboxItem,\n  DropdownMenuContent,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n  ({ className, type, ...props }, ref) => {\n    return (\n      <input\n        type={type}\n        className={cn(\n          'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n          className,\n        )}\n        ref={ref}\n        {...props}\n      />\n    );\n  },\n);\nInput.displayName = 'Input';\n\nconst Select = React.forwardRef<\n  HTMLSelectElement,\n  React.ComponentProps<'select'>\n>(({ className, ...props }, ref) => {\n  return (\n    <select\n      className={cn(\n        'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n        className,\n      )}\n      ref={ref}\n      {...props}\n    />\n  );\n});\nSelect.displayName = 'Select';\n\nfunction Table({ className, ...props }: React.ComponentProps<'table'>) {\n  return (\n    <div\n      data-slot='table-container'\n      className='relative w-full overflow-x-auto'\n    >\n      <table\n        data-slot='table'\n        className={cn('w-full caption-bottom text-sm', className)}\n        {...props}\n      />\n    </div>\n  );\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n  return (\n    <thead\n      data-slot='table-header'\n      className={cn('[&_tr]:border-b', className)}\n      {...props}\n    />\n  );\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n  return (\n    <tbody\n      data-slot='table-body'\n      className={cn('[&_tr:last-child]:border-0', className)}\n      {...props}\n    />\n  );\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n  return (\n    <tfoot\n      data-slot='table-footer'\n      className={cn(\n        'bg-muted/50 border-t font-medium last:[&>tr]:border-b-0',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<'tr'>) {\n  return (\n    <tr\n      data-slot='table-row'\n      className={cn(\n        'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<'th'>) {\n  return (\n    <th\n      data-slot='table-head'\n      className={cn(\n        'text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-0.5',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<'td'>) {\n  return (\n    <td\n      data-slot='table-cell'\n      className={cn(\n        'p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-0.5',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction TableCaption({\n  className,\n  ...props\n}: React.ComponentProps<'caption'>) {\n  return (\n    <caption\n      data-slot='table-caption'\n      className={cn('text-muted-foreground mt-4 text-sm', className)}\n      {...props}\n    />\n  );\n}\n\ninterface DataTableProps<TData, TValue> {\n  columns: ColumnDef<TData, TValue>[];\n  data: TData[];\n  searchable?: boolean;\n  searchPlaceholder?: string;\n  searchColumnKey?: string;\n  globalSearch?: boolean;\n  pagination?: boolean;\n  pageSize?: number;\n  pageSizeOptions?: number[];\n  columnVisibility?: boolean;\n  enableAnimations?: boolean;\n  staggerDelay?: number;\n  className?: string;\n  tableClassName?: string;\n  headerClassName?: string;\n  rowClassName?: string;\n  cellClassName?: string;\n  showToolbar?: boolean;\n  toolbarClassName?: string;\n  customToolbar?: React.ReactNode;\n  emptyMessage?: string;\n  onRowClick?: (row: TData) => void;\n  onRowSelect?: (selectedRows: TData[]) => void;\n  initialSorting?: SortingState;\n  initialColumnFilters?: ColumnFiltersState;\n  initialColumnVisibility?: VisibilityState;\n  initialGlobalFilter?: string;\n  initialPagination?: PaginationState;\n  enableScroll?: boolean;\n  scrollHeight?: string | number;\n  stickyHeader?: boolean;\n  showFilters?: boolean;\n  showPageSizeSelector?: boolean;\n}\n\nfunction DataTable<TData, TValue>({\n  columns,\n  data,\n  searchable = true,\n  searchPlaceholder = 'Search...',\n  globalSearch = true,\n  pagination = true,\n  pageSize = 5,\n  pageSizeOptions = [5, 10, 20, 30, 40, 50],\n  columnVisibility = true,\n  enableAnimations = true,\n  staggerDelay = 0.05,\n  className,\n  tableClassName,\n  rowClassName,\n  cellClassName,\n  showToolbar = true,\n  toolbarClassName,\n  customToolbar,\n  emptyMessage = 'No results found.',\n  onRowClick,\n  onRowSelect,\n  initialSorting = [],\n  initialColumnFilters = [],\n  initialColumnVisibility = {},\n  initialGlobalFilter = '',\n  initialPagination = { pageIndex: 0, pageSize },\n  enableScroll = false,\n  scrollHeight = '400px',\n  showFilters = false,\n  showPageSizeSelector = true,\n}: DataTableProps<TData, TValue>) {\n  const [sorting, setSorting] = React.useState<SortingState>(initialSorting);\n  const [columnFilters, setColumnFilters] =\n    React.useState<ColumnFiltersState>(initialColumnFilters);\n  const [columnVisibilityState, setColumnVisibilityState] =\n    React.useState<VisibilityState>(initialColumnVisibility);\n  const [globalFilter, setGlobalFilter] = React.useState(initialGlobalFilter);\n  const [paginationState, setPaginationState] =\n    React.useState<PaginationState>(initialPagination);\n  const [rowSelection, setRowSelection] = React.useState({});\n  const [showFiltersPanel, setShowFiltersPanel] = React.useState(false);\n\n  // eslint-disable-next-line react-hooks/incompatible-library\n  const table = useReactTable({\n    data,\n    columns,\n    onSortingChange: setSorting,\n    onColumnFiltersChange: setColumnFilters,\n    getCoreRowModel: getCoreRowModel(),\n    getPaginationRowModel:\n      pagination && !enableScroll ? getPaginationRowModel() : undefined,\n    getSortedRowModel: getSortedRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    onColumnVisibilityChange: setColumnVisibilityState,\n    onGlobalFilterChange: globalSearch ? setGlobalFilter : undefined,\n    onPaginationChange:\n      pagination && !enableScroll ? setPaginationState : undefined,\n    onRowSelectionChange: setRowSelection,\n    globalFilterFn: 'includesString',\n    state: {\n      sorting,\n      columnFilters,\n      columnVisibility: columnVisibilityState,\n      globalFilter: globalSearch ? globalFilter : undefined,\n      pagination: pagination && !enableScroll ? paginationState : undefined,\n      rowSelection,\n    },\n    initialState: {\n      pagination: pagination && !enableScroll ? initialPagination : undefined,\n    },\n  });\n\n  React.useEffect(() => {\n    if (onRowSelect) {\n      const selectedRows = table\n        .getFilteredSelectedRowModel()\n        .rows.map((row) => row.original);\n      onRowSelect(selectedRows);\n    }\n  }, [rowSelection, onRowSelect, table]);\n\n  const TableWrapper = enableAnimations ? motion.div : 'div';\n  const ToolbarWrapper = enableAnimations ? motion.div : 'div';\n  const TableContainerWrapper = enableAnimations ? motion.div : 'div';\n  const PaginationWrapper = enableAnimations ? motion.div : 'div';\n  const RowWrapper = enableAnimations ? motion.tr : 'tr';\n  const FilterPanelWrapper = enableAnimations ? motion.div : 'div';\n\n  const animationProps = enableAnimations\n    ? {\n        initial: { opacity: 0, y: 20 },\n        animate: { opacity: 1, y: 0 },\n        transition: { duration: 0.5 },\n      }\n    : {};\n\n  const toolbarAnimationProps = enableAnimations\n    ? {\n        initial: { opacity: 0, y: -10 },\n        animate: { opacity: 1, y: 0 },\n        transition: { duration: 0.4, delay: 0.1 },\n      }\n    : {};\n\n  const tableAnimationProps = enableAnimations\n    ? {\n        initial: { opacity: 0, scale: 0.95 },\n        animate: { opacity: 1, scale: 1 },\n        transition: { duration: 0.4, delay: 0.2 },\n      }\n    : {};\n\n  const paginationAnimationProps = enableAnimations\n    ? {\n        initial: { opacity: 0, y: 10 },\n        animate: { opacity: 1, y: 0 },\n        transition: { duration: 0.4, delay: 0.3 },\n      }\n    : {};\n\n  const filterPanelAnimationProps = enableAnimations\n    ? {\n        initial: { opacity: 0, height: 0 },\n        animate: { opacity: 1, height: 'auto' },\n        exit: { opacity: 0, height: 0 },\n        transition: { duration: 0.3 },\n      }\n    : {};\n\n  return (\n    <TableWrapper\n      className={cn('w-full space-y-4', className)}\n      {...animationProps}\n    >\n      {showToolbar && (\n        <ToolbarWrapper\n          className={cn('flex flex-col gap-4', toolbarClassName)}\n          {...toolbarAnimationProps}\n        >\n          {customToolbar ? (\n            customToolbar\n          ) : (\n            <>\n              <div className='flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4'>\n                <div className='flex flex-col sm:flex-row items-start sm:items-center gap-2 w-full sm:w-auto'>\n                  {searchable && globalSearch && (\n                    <div className='relative w-full sm:w-80'>\n                      <Search className='absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground' />\n                      <Input\n                        placeholder={searchPlaceholder}\n                        value={globalFilter ?? ''}\n                        onChange={(event) =>\n                          setGlobalFilter(event.target.value)\n                        }\n                        className='pl-10'\n                      />\n                    </div>\n                  )}\n                </div>\n\n                <div className='flex items-center gap-2'>\n                  {showFilters && (\n                    <Button\n                      variant='outline'\n                      onClick={() => setShowFiltersPanel(!showFiltersPanel)}\n                      className='gap-2'\n                    >\n                      <Filter className='h-4 w-4' />\n                      Filters\n                      <ChevronDown\n                        className={cn(\n                          'h-4 w-4 transition-transform',\n                          showFiltersPanel && 'rotate-180',\n                        )}\n                      />\n                    </Button>\n                  )}\n\n                  {columnVisibility && (\n                    <DropdownMenu>\n                      <DropdownMenuTrigger asChild>\n                        <Button variant='outline' className='gap-2'>\n                          <Eye className='h-4 w-4' />\n                          View\n                          <ChevronDown className='h-4 w-4' />\n                        </Button>\n                      </DropdownMenuTrigger>\n                      <DropdownMenuContent className='w-48'>\n                        {table\n                          .getAllColumns()\n                          .filter((column) => column.getCanHide())\n                          .map((column) => {\n                            return (\n                              <DropdownMenuCheckboxItem\n                                key={column.id}\n                                className='capitalize'\n                                checked={column.getIsVisible()}\n                                onCheckedChange={(value: boolean) =>\n                                  column.toggleVisibility(!!value)\n                                }\n                              >\n                                {column.id}\n                              </DropdownMenuCheckboxItem>\n                            );\n                          })}\n                      </DropdownMenuContent>\n                    </DropdownMenu>\n                  )}\n                </div>\n              </div>\n\n              {showFilters && enableAnimations && (\n                <AnimatePresence>\n                  {showFiltersPanel && (\n                    <FilterPanelWrapper\n                      className='border rounded-lg p-4 bg-muted/10'\n                      {...filterPanelAnimationProps}\n                    >\n                      <div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4'>\n                        {table\n                          .getAllColumns()\n                          .filter((column) => column.getCanFilter())\n                          .map((column) => (\n                            <div key={column.id} className='space-y-2'>\n                              <label className='text-sm font-medium capitalize'>\n                                {column.id}\n                              </label>\n                              <Input\n                                placeholder={`Filter ${column.id}...`}\n                                value={\n                                  (column.getFilterValue() as string) ?? ''\n                                }\n                                onChange={(event) =>\n                                  column.setFilterValue(event.target.value)\n                                }\n                              />\n                            </div>\n                          ))}\n                      </div>\n                    </FilterPanelWrapper>\n                  )}\n                </AnimatePresence>\n              )}\n\n              {showFilters && !enableAnimations && showFiltersPanel && (\n                <div className='border rounded-lg p-4 bg-muted/10'>\n                  <div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4'>\n                    {table\n                      .getAllColumns()\n                      .filter((column) => column.getCanFilter())\n                      .map((column) => (\n                        <div key={column.id} className='space-y-2'>\n                          <label className='text-sm font-medium capitalize'>\n                            {column.id}\n                          </label>\n                          <Input\n                            placeholder={`Filter ${column.id}...`}\n                            value={(column.getFilterValue() as string) ?? ''}\n                            onChange={(event) =>\n                              column.setFilterValue(event.target.value)\n                            }\n                          />\n                        </div>\n                      ))}\n                  </div>\n                </div>\n              )}\n            </>\n          )}\n        </ToolbarWrapper>\n      )}\n\n      <TableContainerWrapper\n        className='rounded-lg border bg-card shadow-xs overflow-hidden'\n        {...tableAnimationProps}\n      >\n        <div className='overflow-x-auto'>\n          <div className='min-w-max'>\n            <Table className={tableClassName}>\n              <TableHeader>\n                {table.getHeaderGroups().map((headerGroup) => (\n                  <TableRow key={headerGroup.id}>\n                    {headerGroup.headers.map((header) => (\n                      <TableHead\n                        key={header.id}\n                        className='sticky top-0 z-20 bg-card border-b shadow-xs whitespace-nowrap'\n                      >\n                        {header.isPlaceholder\n                          ? null\n                          : flexRender(\n                              header.column.columnDef.header,\n                              header.getContext(),\n                            )}\n                      </TableHead>\n                    ))}\n                  </TableRow>\n                ))}\n              </TableHeader>\n            </Table>\n            <div\n              className='overflow-y-auto'\n              style={{\n                maxHeight: enableScroll ? scrollHeight : 'auto',\n              }}\n            >\n              <Table className={tableClassName}>\n                <TableBody>\n                  {enableAnimations ? (\n                    <AnimatePresence mode='popLayout'>\n                      {table.getRowModel().rows?.length ? (\n                        table.getRowModel().rows.map((row, index) => (\n                          <RowWrapper\n                            key={row.id}\n                            layout\n                            initial={{ opacity: 0, y: 20 }}\n                            animate={{ opacity: 1, y: 0 }}\n                            exit={{ opacity: 0, y: -20 }}\n                            transition={{\n                              duration: 0.3,\n                              delay: index * staggerDelay,\n                            }}\n                            data-state={row.getIsSelected() && 'selected'}\n                            className={cn(\n                              'border-b transition-colors hover:bg-muted/50 group cursor-pointer',\n                              rowClassName,\n                            )}\n                            onClick={() => onRowClick?.(row.original)}\n                          >\n                            {row.getVisibleCells().map((cell) => (\n                              <TableCell\n                                key={cell.id}\n                                className={cn(\n                                  'group-hover:bg-transparent whitespace-nowrap',\n                                  cellClassName,\n                                )}\n                              >\n                                {flexRender(\n                                  cell.column.columnDef.cell,\n                                  cell.getContext(),\n                                )}\n                              </TableCell>\n                            ))}\n                          </RowWrapper>\n                        ))\n                      ) : (\n                        <motion.tr\n                          initial={{ opacity: 0 }}\n                          animate={{ opacity: 1 }}\n                          transition={{ duration: 0.3 }}\n                        >\n                          <TableCell\n                            colSpan={columns.length}\n                            className='h-24 text-center'\n                          >\n                            {emptyMessage}\n                          </TableCell>\n                        </motion.tr>\n                      )}\n                    </AnimatePresence>\n                  ) : (\n                    <>\n                      {table.getRowModel().rows?.length ? (\n                        table.getRowModel().rows.map((row) => (\n                          <TableRow\n                            key={row.id}\n                            data-state={row.getIsSelected() && 'selected'}\n                            className={cn('cursor-pointer', rowClassName)}\n                            onClick={() => onRowClick?.(row.original)}\n                          >\n                            {row.getVisibleCells().map((cell) => (\n                              <TableCell\n                                key={cell.id}\n                                className='whitespace-nowrap'\n                              >\n                                {flexRender(\n                                  cell.column.columnDef.cell,\n                                  cell.getContext(),\n                                )}\n                              </TableCell>\n                            ))}\n                          </TableRow>\n                        ))\n                      ) : (\n                        <TableRow>\n                          <TableCell\n                            colSpan={columns.length}\n                            className='h-24 text-center'\n                          >\n                            {emptyMessage}\n                          </TableCell>\n                        </TableRow>\n                      )}\n                    </>\n                  )}\n                </TableBody>\n              </Table>\n            </div>\n          </div>\n        </div>\n      </TableContainerWrapper>\n\n      {pagination && !enableScroll && (\n        <PaginationWrapper\n          className='flex flex-col sm:flex-row items-center justify-between gap-4'\n          {...paginationAnimationProps}\n        >\n          <div className='flex items-center gap-4'>\n            <div className='text-sm text-muted-foreground'>\n              {table.getFilteredSelectedRowModel().rows.length} of{' '}\n              {table.getFilteredRowModel().rows.length} row(s) selected.\n            </div>\n\n            {showPageSizeSelector && (\n              <div className='flex items-center gap-2'>\n                <span className='text-sm text-muted-foreground'>\n                  Rows per page:\n                </span>\n                <DropdownMenu>\n                  <DropdownMenuTrigger asChild>\n                    <Button variant='outline' className='w-20 justify-between'>\n                      {table.getState().pagination.pageSize}\n                      <ChevronDown className='ml-2 h-4 w-4' />\n                    </Button>\n                  </DropdownMenuTrigger>\n\n                  <DropdownMenuContent className='w-28'>\n                    {pageSizeOptions.map((size) => (\n                      <DropdownMenuCheckboxItem\n                        key={size}\n                        checked={table.getState().pagination.pageSize === size}\n                        onCheckedChange={() => table.setPageSize(size)}\n                      >\n                        {size}\n                      </DropdownMenuCheckboxItem>\n                    ))}\n                  </DropdownMenuContent>\n                </DropdownMenu>\n              </div>\n            )}\n          </div>\n\n          <div className='flex items-center space-x-2'>\n            <p className='text-sm text-muted-foreground'>\n              Page {table.getState().pagination.pageIndex + 1} of{' '}\n              {table.getPageCount()}\n            </p>\n            <div className='flex items-center space-x-2'>\n              <Button\n                variant='outline'\n                size='sm'\n                onClick={() => table.previousPage()}\n                disabled={!table.getCanPreviousPage()}\n                className='h-8 w-8 p-0'\n              >\n                <ArrowLeft className='h-4 w-4' />\n              </Button>\n              <Button\n                variant='outline'\n                size='sm'\n                onClick={() => table.nextPage()}\n                disabled={!table.getCanNextPage()}\n                className='h-8 w-8 p-0'\n              >\n                <ArrowRight className='h-4 w-4' />\n              </Button>\n            </div>\n          </div>\n        </PaginationWrapper>\n      )}\n    </TableWrapper>\n  );\n}\n\nconst createSortableHeader = <TData, TValue = unknown>(\n  title: string,\n  enableAnimations: boolean = true,\n) => {\n  const SortableHeader: React.FC<{ column: Column<TData, TValue> }> = ({\n    column,\n  }) => {\n    const SortButton = enableAnimations ? motion.div : 'div';\n\n    return (\n      <Button\n        variant='ghost'\n        onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}\n        className='hover:bg-transparent p-0 h-auto'\n      >\n        {title}\n        {enableAnimations ? (\n          <SortButton\n            animate={{ rotate: column.getIsSorted() === 'desc' ? 180 : 0 }}\n            transition={{ duration: 0.2 }}\n          >\n            {column.getIsSorted() ? (\n              <ChevronUp className='ml-2 h-4 w-4' />\n            ) : (\n              <ChevronDown className='ml-2 h-4 w-4' />\n            )}\n          </SortButton>\n        ) : (\n          <>\n            {column.getIsSorted() ? (\n              <ChevronUp className='ml-2 h-4 w-4' />\n            ) : (\n              <ChevronDown className='ml-2 h-4 w-4' />\n            )}\n          </>\n        )}\n      </Button>\n    );\n  };\n\n  SortableHeader.displayName = 'SortableHeader';\n  return SortableHeader;\n};\n\ninterface AnimatedCellProps {\n  row: Row<unknown>;\n  getValue: () => unknown;\n}\n\nconst createAnimatedCell = (\n  enableAnimations: boolean = true,\n  delay: number = 0,\n  className?: string,\n) => {\n  const AnimatedCell: React.FC<AnimatedCellProps> = ({ row, getValue }) => {\n    const CellWrapper = enableAnimations ? motion.div : 'div';\n    const animationProps = enableAnimations\n      ? {\n          initial: { opacity: 0, x: -20 },\n          animate: { opacity: 1, x: 0 },\n          transition: { duration: 0.3, delay: row.index * 0.05 + delay },\n        }\n      : {};\n\n    return (\n      <CellWrapper className={className} {...animationProps}>\n        {getValue() as React.ReactNode}\n      </CellWrapper>\n    );\n  };\n\n  AnimatedCell.displayName = 'AnimatedCell';\n  return AnimatedCell;\n};\n\nexport {\n  Table,\n  TableHeader,\n  TableBody,\n  TableFooter,\n  TableHead,\n  TableRow,\n  TableCell,\n  TableCaption,\n  DataTable,\n  createSortableHeader,\n  createAnimatedCell,\n};\n\nexport type { ColumnDef } from '@tanstack/react-table';\n"
    },
    {
      "type": "registry:ui",
      "path": "components/ui/button.tsx",
      "content": "import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n  {\n    variants: {\n      variant: {\n        default:\n          'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',\n        destructive:\n          'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',\n        outline:\n          'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',\n        secondary:\n          'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',\n        ghost: 'hover:bg-accent hover:text-accent-foreground',\n        link: 'text-primary underline-offset-4 hover:underline',\n        success: 'bg-green-600 text-white hover:bg-green-700',\n        warning: 'bg-yellow-500 text-black hover:bg-yellow-600',\n        info: 'bg-blue-500 text-white hover:bg-blue-600',\n        dark: 'bg-gray-800 text-white hover:bg-gray-700',\n        light: 'bg-gray-100 text-gray-800 hover:bg-gray-200',\n        gradient:\n          'bg-linear-to-r from-indigo-500 via-purple-500 to-pink-500 text-white hover:opacity-90',\n        glass:\n          'bg-white/10 backdrop-blur-md text-white border border-white/20 hover:bg-white/20',\n      },\n      size: {\n        default: 'h-9 px-4 py-2',\n        sm: 'h-8 rounded-md px-3 text-xs',\n        lg: 'h-10 rounded-md px-8',\n        icon: 'h-9 w-9',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n);\n\nexport interface ButtonProps\n  extends\n    React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof buttonVariants> {\n  asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, ...props }, ref) => {\n    const Comp = asChild ? Slot : 'button';\n    return (\n      <Comp\n        className={cn(buttonVariants({ variant, size, className }))}\n        ref={ref}\n        {...props}\n      />\n    );\n  },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n"
    },
    {
      "type": "registry:ui",
      "path": "components/ui/dropdown-menu.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { useEffect, useState } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';\nimport { motion, AnimatePresence, Variants } from 'motion/react';\nimport { cn } from '@/lib/utils';\n\nconst dropdownVariants: Variants = {\n  hidden: {\n    opacity: 0,\n    scale: 0.5,\n    rotateX: 40,\n    y: 20,\n  },\n  visible: {\n    opacity: 1,\n    scale: 1,\n    y: 0,\n    rotateX: 0,\n    transition: {\n      type: 'spring' as const,\n      stiffness: 260,\n      damping: 15,\n    },\n  },\n  exit: {\n    opacity: 0,\n    scale: 0.8,\n    rotateX: 10,\n    y: 10,\n    transition: {\n      duration: 0.2,\n    },\n  },\n};\n\nconst itemVariants: Variants = {\n  hidden: {\n    opacity: 0,\n    x: -20,\n  },\n  visible: (i: number) => ({\n    opacity: 1,\n    x: 0,\n    transition: {\n      delay: i * 0.05,\n      duration: 0.2,\n    },\n  }),\n  exit: {\n    opacity: 0,\n    x: -20,\n    transition: {\n      duration: 0.1,\n    },\n  },\n};\n\nconst useMobile = () => {\n  const [isMobile, setIsMobile] = useState(false);\n\n  useEffect(() => {\n    const checkIfMobile = () => {\n      setIsMobile(\n        window.innerWidth < 768 ||\n          /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n            navigator.userAgent,\n          ),\n      );\n    };\n\n    checkIfMobile();\n    window.addEventListener('resize', checkIfMobile);\n\n    return () => {\n      window.removeEventListener('resize', checkIfMobile);\n    };\n  }, []);\n\n  return isMobile;\n};\n\nconst DropdownMenuContext = React.createContext<{ animate: boolean }>({\n  animate: true,\n});\n\nfunction DropdownMenu({\n  animate = true,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Root> & {\n  animate?: boolean;\n}) {\n  return (\n    <DropdownMenuContext.Provider value={{ animate }}>\n      <DropdownMenuPrimitive.Root data-slot='dropdown-menu' {...props} />\n    </DropdownMenuContext.Provider>\n  );\n}\n\nfunction DropdownMenuTrigger({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <DropdownMenuPrimitive.Trigger\n      data-slot='dropdown-menu-trigger'\n      className={cn(\n        'inline-flex items-center justify-center rounded-lg text-sm font-medium transition-all duration-200',\n        'hover:shadow-lg',\n        className,\n      )}\n      asChild\n      {...props}\n    >\n      <motion.div\n        whileHover={animate ? { scale: 1.02 } : undefined}\n        whileTap={animate ? { scale: 0.98 } : undefined}\n        transition={\n          animate ? { type: 'spring', stiffness: 400, damping: 25 } : undefined\n        }\n        className='flex items-center gap-2 cursor-pointer'\n        style={{ touchAction: 'manipulation' }}\n      >\n        {children}\n      </motion.div>\n    </DropdownMenuPrimitive.Trigger>\n  );\n}\n\ninterface DropdownMenuContentProps extends React.ComponentPropsWithoutRef<\n  typeof DropdownMenuPrimitive.Content\n> {\n  className?: string;\n  sideOffset?: number;\n  children?: React.ReactNode;\n  maxHeight?: string | number;\n}\n\nfunction DropdownMenuContent({\n  className,\n  sideOffset = 4,\n  maxHeight = '16rem',\n  children,\n  ...props\n}: DropdownMenuContentProps) {\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <DropdownMenuPrimitive.Portal>\n      <DropdownMenuPrimitive.Content\n        data-slot='dropdown-menu-content'\n        sideOffset={sideOffset}\n        className='z-50'\n        asChild\n        {...props}\n      >\n        <motion.div\n          variants={animate ? dropdownVariants : undefined}\n          initial={animate ? 'hidden' : undefined}\n          animate={animate ? 'visible' : undefined}\n          exit={animate ? 'exit' : undefined}\n          className={cn(\n            'w-72 rounded-xl border shadow-xl overflow-hidden perspective-midrange transform-3d',\n            'bg-[#ffffff] border-neutral-900/10',\n            'dark:bg-[#262626] dark:border-neutral-50/10',\n            className,\n          )}\n          style={{\n            transformOrigin:\n              'var(--radix-dropdown-menu-content-transform-origin)',\n          }}\n        >\n          <div\n            className='relative z-20 overflow-y-auto scrollbar-visible'\n            style={{\n              maxHeight:\n                typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,\n              scrollbarWidth: 'thin',\n              scrollbarColor: 'rgba(155, 155, 155, 0.5) transparent',\n            }}\n          >\n            <style jsx global>{`\n              .scrollbar-visible::-webkit-scrollbar {\n                width: 6px;\n                display: block;\n              }\n              .scrollbar-visible::-webkit-scrollbar-track {\n                background: transparent;\n              }\n              .scrollbar-visible::-webkit-scrollbar-thumb {\n                background-color: rgba(155, 155, 155, 0.5);\n                border-radius: 20px;\n              }\n              .scrollbar-visible::-webkit-scrollbar-thumb:hover {\n                background-color: rgba(155, 155, 155, 0.7);\n              }\n            `}</style>\n            <div className='p-2'>\n              {React.Children.map(children, (child, index) =>\n                animate ? (\n                  <motion.div\n                    key={index}\n                    custom={index}\n                    variants={itemVariants}\n                    initial='hidden'\n                    animate='visible'\n                    exit='exit'\n                  >\n                    {child}\n                  </motion.div>\n                ) : (\n                  <div key={index}>{child}</div>\n                ),\n              )}\n            </div>\n          </div>\n        </motion.div>\n      </DropdownMenuPrimitive.Content>\n    </DropdownMenuPrimitive.Portal>\n  );\n}\n\nfunction DropdownMenuItem({\n  className,\n  inset,\n  variant = 'default',\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n  inset?: boolean;\n  variant?: 'default' | 'destructive';\n  className?: string;\n}) {\n  const [isHovered, setIsHovered] = useState(false);\n  const isMobile = useMobile();\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <DropdownMenuPrimitive.Item\n      data-slot='dropdown-menu-item'\n      data-inset={inset}\n      data-variant={variant}\n      className={cn(\n        'relative flex cursor-pointer items-center gap-3 rounded-lg p-2 text-sm outline-hidden select-none overflow-hidden',\n        'transition-all duration-200 ease-out',\n        'focus:outline-hidden focus:bg-transparent',\n        'data-disabled:pointer-events-none data-disabled:opacity-50',\n        'data-inset:pl-8',\n        'text-neutral-900 dark:text-neutral-50',\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      onMouseEnter={() => !isMobile && setIsHovered(true)}\n      onMouseLeave={() => !isMobile && setIsHovered(false)}\n      style={{ touchAction: 'manipulation' }}\n      asChild\n      {...props}\n    >\n      <motion.div\n        className='relative w-full'\n        initial={animate ? { opacity: 0, x: -20 } : undefined}\n        animate={animate ? { opacity: 1, x: 0 } : undefined}\n      >\n        <AnimatePresence>\n          {!isMobile && isHovered && (\n            <motion.div\n              layoutId={animate ? 'hoverBackground' : undefined}\n              initial={animate ? { opacity: 0 } : undefined}\n              animate={\n                animate\n                  ? {\n                      opacity: 1,\n                      scale: 1.05,\n                      transition: {\n                        type: 'spring',\n                        stiffness: 260,\n                        damping: 15,\n                      },\n                    }\n                  : { opacity: 1 }\n              }\n              exit={animate ? { opacity: 0 } : undefined}\n              className={cn(\n                'absolute inset-0 rounded-lg',\n                variant === 'destructive'\n                  ? 'bg-red-500/10 dark:bg-red-500/20'\n                  : 'bg-[#f5f5f5] dark:bg-[#404040]',\n              )}\n            />\n          )}\n        </AnimatePresence>\n\n        <div\n          className={cn(\n            'relative z-10 w-full flex items-center gap-3',\n            variant === 'destructive' && 'text-red-600 dark:text-red-400',\n          )}\n        >\n          {React.Children.map(children, (child, index) => {\n            if (\n              React.isValidElement(child) &&\n              (child.type === 'svg' ||\n                (child.props &&\n                  typeof child.props === 'object' &&\n                  'className' in child.props &&\n                  typeof child.props.className === 'string' &&\n                  child.props.className.includes('lucide')))\n            ) {\n              return (\n                <motion.div\n                  key={index}\n                  animate={\n                    animate\n                      ? {\n                          scale: !isMobile && isHovered ? 1.1 : 1,\n                          rotate: !isMobile && isHovered ? 5 : 0,\n                        }\n                      : undefined\n                  }\n                  transition={\n                    animate ? { type: 'spring', stiffness: 500 } : undefined\n                  }\n                >\n                  {child}\n                </motion.div>\n              );\n            }\n\n            if (typeof child === 'string') {\n              return (\n                <motion.span\n                  key={index}\n                  animate={\n                    animate\n                      ? {\n                          y: !isMobile && isHovered ? -1 : 0,\n                          x: !isMobile && isHovered ? 1 : 0,\n                        }\n                      : undefined\n                  }\n                  transition={\n                    animate ? { type: 'spring', stiffness: 500 } : undefined\n                  }\n                  className='font-medium flex-1'\n                >\n                  {child}\n                </motion.span>\n              );\n            }\n\n            return child;\n          })}\n        </div>\n      </motion.div>\n    </DropdownMenuPrimitive.Item>\n  );\n}\n\nfunction DropdownMenuCheckboxItem({\n  className,\n  children,\n  checked,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {\n  className?: string;\n}) {\n  const [isHovered, setIsHovered] = useState(false);\n  const isMobile = useMobile();\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  const handleSelect = (e: Event) => {\n    e.preventDefault();\n    setTimeout(() => {\n      const event = new KeyboardEvent('keydown', { key: 'Escape' });\n      document.dispatchEvent(event);\n    }, 150);\n    if (props.onSelect) props.onSelect(e);\n  };\n\n  return (\n    <DropdownMenuPrimitive.CheckboxItem\n      data-slot='dropdown-menu-checkbox-item'\n      className={cn(\n        'relative flex cursor-pointer items-center gap-3 rounded-lg py-2 pr-3 pl-8 text-sm outline-hidden select-none overflow-hidden',\n        'transition-all duration-200 ease-out',\n        'focus:outline-hidden focus:bg-transparent',\n        'data-disabled:pointer-events-none data-disabled:opacity-50',\n        'text-neutral-900 dark:text-neutral-50',\n        '[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4',\n        className,\n      )}\n      checked={checked}\n      onMouseEnter={() => !isMobile && setIsHovered(true)}\n      onMouseLeave={() => !isMobile && setIsHovered(false)}\n      onSelect={handleSelect}\n      style={{ touchAction: 'manipulation' }}\n      asChild\n      {...props}\n    >\n      <motion.div className='relative w-full'>\n        <AnimatePresence>\n          {!isMobile && isHovered && (\n            <motion.div\n              layoutId={animate ? 'checkboxHoverBackground' : undefined}\n              initial={animate ? { opacity: 0 } : undefined}\n              animate={\n                animate\n                  ? {\n                      opacity: 1,\n                      scale: 1.05,\n                      transition: {\n                        type: 'spring',\n                        stiffness: 260,\n                        damping: 15,\n                      },\n                    }\n                  : { opacity: 1 }\n              }\n              exit={animate ? { opacity: 0 } : undefined}\n              className='absolute inset-0 rounded-lg bg-[#f5f5f5] dark:bg-[#404040]'\n            />\n          )}\n        </AnimatePresence>\n\n        <span className='pointer-events-none absolute left-2 flex size-4 items-center justify-center'>\n          <DropdownMenuPrimitive.ItemIndicator>\n            <motion.div\n              initial={animate ? { scale: 0 } : undefined}\n              animate={animate ? { scale: 1 } : undefined}\n              transition={\n                animate\n                  ? { type: 'spring', stiffness: 400, damping: 25 }\n                  : undefined\n              }\n            >\n              <CheckIcon className='size-4' />\n            </motion.div>\n          </DropdownMenuPrimitive.ItemIndicator>\n        </span>\n\n        <motion.div\n          animate={\n            animate\n              ? {\n                  y: !isMobile && isHovered ? -1 : 0,\n                  x: !isMobile && isHovered ? 1 : 0,\n                }\n              : undefined\n          }\n          transition={animate ? { type: 'spring', stiffness: 500 } : undefined}\n          className='relative z-10'\n        >\n          {children}\n        </motion.div>\n      </motion.div>\n    </DropdownMenuPrimitive.CheckboxItem>\n  );\n}\n\nfunction DropdownMenuRadioGroup({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n  return (\n    <DropdownMenuPrimitive.RadioGroup\n      data-slot='dropdown-menu-radio-group'\n      {...props}\n    />\n  );\n}\n\nfunction DropdownMenuRadioItem({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {\n  className?: string;\n}) {\n  const [isHovered, setIsHovered] = useState(false);\n  const isMobile = useMobile();\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  const handleSelect = (e: Event) => {\n    e.preventDefault();\n    setTimeout(() => {\n      const event = new KeyboardEvent('keydown', { key: 'Escape' });\n      document.dispatchEvent(event);\n    }, 150);\n    if (props.onSelect) props.onSelect(e);\n  };\n\n  return (\n    <DropdownMenuPrimitive.RadioItem\n      data-slot='dropdown-menu-radio-item'\n      className={cn(\n        'relative flex cursor-pointer items-center gap-3 rounded-lg py-2 pr-3 pl-8 text-sm outline-hidden select-none overflow-hidden',\n        'transition-all duration-200 ease-out',\n        'focus:outline-hidden focus:bg-transparent',\n        'data-disabled:pointer-events-none data-disabled:opacity-50',\n        'text-neutral-900 dark:text-neutral-50',\n        '[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-2.5',\n        className,\n      )}\n      onMouseEnter={() => !isMobile && setIsHovered(true)}\n      onMouseLeave={() => !isMobile && setIsHovered(false)}\n      onSelect={handleSelect}\n      style={{ touchAction: 'manipulation' }}\n      asChild\n      {...props}\n    >\n      <motion.div className='relative w-full'>\n        <AnimatePresence>\n          {!isMobile && isHovered && (\n            <motion.div\n              layoutId={animate ? 'radioHoverBackground' : undefined}\n              initial={animate ? { opacity: 0 } : undefined}\n              animate={\n                animate\n                  ? {\n                      opacity: 1,\n                      scale: 1.05,\n                      transition: {\n                        type: 'spring',\n                        stiffness: 260,\n                        damping: 15,\n                      },\n                    }\n                  : { opacity: 1 }\n              }\n              exit={animate ? { opacity: 0 } : undefined}\n              className='absolute inset-0 rounded-lg bg-[#f5f5f5] dark:bg-[#404040]'\n            />\n          )}\n        </AnimatePresence>\n\n        <span className='pointer-events-none absolute left-2 flex size-4 items-center justify-center'>\n          <DropdownMenuPrimitive.ItemIndicator>\n            <motion.div\n              initial={animate ? { scale: 0 } : undefined}\n              animate={animate ? { scale: 1 } : undefined}\n              transition={\n                animate\n                  ? { type: 'spring', stiffness: 400, damping: 25 }\n                  : undefined\n              }\n            >\n              <CircleIcon className='size-2 fill-current' />\n            </motion.div>\n          </DropdownMenuPrimitive.ItemIndicator>\n        </span>\n\n        <motion.div\n          animate={\n            animate\n              ? {\n                  y: !isMobile && isHovered ? -1 : 0,\n                  x: !isMobile && isHovered ? 1 : 0,\n                }\n              : undefined\n          }\n          transition={animate ? { type: 'spring', stiffness: 500 } : undefined}\n          className='relative z-10'\n        >\n          {children}\n        </motion.div>\n      </motion.div>\n    </DropdownMenuPrimitive.RadioItem>\n  );\n}\n\nfunction DropdownMenuLabel({\n  className,\n  inset,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n  inset?: boolean;\n  className?: string;\n}) {\n  return (\n    <div className='p-2 sticky top-0 z-20'>\n      <DropdownMenuPrimitive.Label\n        data-slot='dropdown-menu-label'\n        data-inset={inset}\n        className={cn(\n          'px-3 py-2 text-sm font-bold text-neutral-900 dark:text-neutral-50',\n          'data-inset:pl-8',\n          className,\n        )}\n        {...props}\n      />\n    </div>\n  );\n}\n\nfunction DropdownMenuSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator> & {\n  className?: string;\n}) {\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <motion.div\n      initial={animate ? { scaleX: 0, opacity: 0 } : undefined}\n      animate={\n        animate\n          ? {\n              scaleX: 1,\n              opacity: 1,\n              transition: {\n                delay: 0.1,\n                type: 'spring',\n                stiffness: 400,\n                damping: 25,\n              },\n            }\n          : undefined\n      }\n      className='flex justify-center py-1'\n    >\n      <DropdownMenuPrimitive.Separator\n        data-slot='dropdown-menu-separator'\n        className={cn(\n          'my-1 h-px w-full bg-neutral-900/10 dark:bg-white/10',\n          className,\n        )}\n        {...props}\n      />\n    </motion.div>\n  );\n}\n\nfunction DropdownMenuShortcut({\n  className,\n  ...props\n}: React.ComponentProps<'span'>) {\n  return (\n    <span\n      data-slot='dropdown-menu-shortcut'\n      className={cn(\n        'ml-auto text-xs tracking-widest text-neutral-500 dark:text-neutral-400',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction DropdownMenuSub({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n  return <DropdownMenuPrimitive.Sub data-slot='dropdown-menu-sub' {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n  className,\n  inset,\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n  inset?: boolean;\n  className?: string;\n}) {\n  const [isHovered, setIsHovered] = useState(false);\n  const isMobile = useMobile();\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <DropdownMenuPrimitive.SubTrigger\n      data-slot='dropdown-menu-sub-trigger'\n      data-inset={inset}\n      className={cn(\n        'relative flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-sm outline-hidden select-none overflow-hidden',\n        'transition-all duration-200 ease-out',\n        'focus:outline-hidden',\n        'text-neutral-900 dark:text-neutral-50',\n        'data-inset:pl-8',\n        'data-[state=open]:bg-[#f5f5f5] dark:data-[state=open]:bg-[#404040]',\n        !isMobile && isHovered && 'bg-[#f5f5f5] dark:bg-[#404040]',\n        className,\n      )}\n      onMouseEnter={() => !isMobile && setIsHovered(true)}\n      onMouseLeave={() => !isMobile && setIsHovered(false)}\n      style={{ touchAction: 'manipulation' }}\n      {...props}\n    >\n      <div className='w-full flex items-center gap-3'>\n        <motion.div\n          animate={\n            animate\n              ? {\n                  y: !isMobile && isHovered ? -1 : 0,\n                  x: !isMobile && isHovered ? 1 : 0,\n                }\n              : undefined\n          }\n          transition={animate ? { type: 'spring', stiffness: 500 } : undefined}\n          className='flex-1'\n        >\n          {children}\n        </motion.div>\n        <motion.div\n          animate={\n            animate\n              ? {\n                  rotate: !isMobile && isHovered ? 90 : 0,\n                  scale: !isMobile && isHovered ? 1.1 : 1,\n                }\n              : undefined\n          }\n          transition={animate ? { type: 'spring', stiffness: 500 } : undefined}\n        >\n          <ChevronRightIcon className='ml-auto size-4' />\n        </motion.div>\n      </div>\n    </DropdownMenuPrimitive.SubTrigger>\n  );\n}\n\ninterface DropdownMenuSubContentProps extends React.ComponentPropsWithoutRef<\n  typeof DropdownMenuPrimitive.SubContent\n> {\n  className?: string;\n  children?: React.ReactNode;\n}\n\nfunction DropdownMenuSubContent({\n  className,\n  children,\n  ...props\n}: DropdownMenuSubContentProps) {\n  const { animate } = React.useContext(DropdownMenuContext);\n\n  return (\n    <DropdownMenuPrimitive.SubContent\n      data-slot='dropdown-menu-sub-content'\n      className='z-50'\n      asChild\n      {...props}\n    >\n      <motion.div\n        variants={animate ? dropdownVariants : undefined}\n        initial={animate ? 'hidden' : undefined}\n        animate={animate ? 'visible' : undefined}\n        exit={animate ? 'exit' : undefined}\n        className={cn(\n          'min-w-32 rounded-xl border shadow-xl overflow-hidden perspective-midrange transform-3d',\n          'bg-[#ffffff] border-neutral-900/10',\n          'dark:bg-[#262626] dark:border-neutral-50/10',\n          className,\n        )}\n        style={{\n          transformOrigin:\n            'var(--radix-dropdown-menu-content-transform-origin)',\n        }}\n      >\n        <div className='p-1 w-full relative z-20'>\n          {React.Children.map(children, (child, index) =>\n            animate ? (\n              <motion.div\n                key={index}\n                custom={index}\n                variants={itemVariants}\n                initial='hidden'\n                animate='visible'\n                exit='exit'\n              >\n                {child}\n              </motion.div>\n            ) : (\n              <div key={index}>{child}</div>\n            ),\n          )}\n        </div>\n      </motion.div>\n    </DropdownMenuPrimitive.SubContent>\n  );\n}\n\nfunction DropdownMenuGroup({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n  return (\n    <DropdownMenuPrimitive.Group data-slot='dropdown-menu-group' {...props} />\n  );\n}\n\nfunction DropdownMenuPortal({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n  return (\n    <DropdownMenuPrimitive.Portal data-slot='dropdown-menu-portal' {...props} />\n  );\n}\n\nexport {\n  DropdownMenu,\n  DropdownMenuPortal,\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuLabel,\n  DropdownMenuItem,\n  DropdownMenuCheckboxItem,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubTrigger,\n  DropdownMenuSubContent,\n};\n"
    },
    {
      "type": "registry:lib",
      "path": "lib/utils.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}"
    }
  ]
}
