{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table-sheet",
  "title": "Data Table Sheet Detail Panel",
  "description": "Row detail side panel with cell renderers, keyboard navigation, and copy-to-clipboard.",
  "dependencies": [
    "@radix-ui/react-dialog",
    "class-variance-authority",
    "date-fns",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://data-table.openstatus.dev/r/data-table.json",
    "https://data-table.openstatus.dev/r/data-table-cell.json",
    "button",
    "dropdown-menu",
    "kbd",
    "separator",
    "skeleton",
    "tooltip"
  ],
  "files": [
    {
      "path": "src/components/data-table/data-table-sheet/data-table-sheet-details.tsx",
      "content": "\"use client\";\n\nimport {\n  Sheet,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetHeader,\n  SheetTitle,\n} from \"@/components/custom/sheet\";\nimport { useDataTable } from \"@/components/data-table/data-table-provider\";\nimport { Button } from \"@/components/ui/button\";\nimport { Kbd } from \"@/components/ui/kbd\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { useFilterActions } from \"@/lib/store/hooks/useFilterActions\";\nimport { useFilterState } from \"@/lib/store/hooks/useFilterState\";\nimport { cn } from \"@/lib/utils\";\nimport { ChevronDown, ChevronUp, X } from \"lucide-react\";\nimport * as React from \"react\";\n\nexport interface DataTableSheetDetailsProps {\n  title?: React.ReactNode;\n  titleClassName?: string;\n  children?: React.ReactNode;\n}\n\nexport function DataTableSheetDetails({\n  title,\n  titleClassName,\n  children,\n}: DataTableSheetDetailsProps) {\n  const { table, rowSelection, isLoading } = useDataTable();\n  const { setFilters } = useFilterActions();\n\n  const isMultiSelect = !!table.options.enableMultiRowSelection;\n\n  // Read the detail row ID from BYOS uuid when multi-select is enabled,\n  // otherwise fall back to rowSelection (existing single-select behavior)\n  const uuid = useFilterState((s) => s.uuid) as string | null | undefined;\n  const selectedRowKey = isMultiSelect\n    ? (uuid ?? undefined)\n    : Object.keys(rowSelection)?.[0];\n\n  const selectedRow = React.useMemo(() => {\n    if (isLoading && !selectedRowKey) return;\n    return table\n      .getRowModel()\n      .flatRows.find((row) => row.id === selectedRowKey);\n  }, [selectedRowKey, isLoading, table]);\n\n  const index = table\n    .getRowModel()\n    .flatRows.findIndex((row) => row.id === selectedRow?.id);\n\n  const nextId = React.useMemo(\n    () => table.getRowModel().flatRows[index + 1]?.id,\n    [index, isLoading, table],\n  );\n\n  const prevId = React.useMemo(\n    () => table.getRowModel().flatRows[index - 1]?.id,\n    [index, isLoading, table],\n  );\n\n  const onPrev = React.useCallback(() => {\n    if (!prevId) return;\n    if (isMultiSelect) {\n      setFilters({ uuid: prevId });\n    } else {\n      table.setRowSelection({ [prevId]: true });\n    }\n  }, [prevId, isLoading, table, isMultiSelect, setFilters]);\n\n  const onNext = React.useCallback(() => {\n    if (!nextId) return;\n    if (isMultiSelect) {\n      setFilters({ uuid: nextId });\n    } else {\n      table.setRowSelection({ [nextId]: true });\n    }\n  }, [nextId, isLoading, table, isMultiSelect, setFilters]);\n\n  React.useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if (!selectedRowKey) return;\n\n      // REMINDER: prevent dropdown navigation inside of sheet to change row selection\n      const activeElement = document.activeElement;\n      const isMenuActive = activeElement?.closest('[role=\"menu\"]');\n\n      if (isMenuActive) return;\n\n      if (e.key === \"ArrowUp\") {\n        e.preventDefault();\n        onPrev();\n      }\n      if (e.key === \"ArrowDown\") {\n        e.preventDefault();\n        onNext();\n      }\n    };\n\n    document.addEventListener(\"keydown\", down);\n    return () => document.removeEventListener(\"keydown\", down);\n  }, [selectedRowKey, onNext, onPrev]);\n\n  return (\n    <Sheet\n      open={!!selectedRowKey}\n      onOpenChange={() => {\n        // REMINDER: focus back to the row that was selected\n        // We need to manually focus back due to missing Trigger component\n        const el = selectedRowKey\n          ? document.getElementById(selectedRowKey)\n          : null;\n\n        if (isMultiSelect) {\n          setFilters({ uuid: null });\n        } else {\n          table.resetRowSelection();\n        }\n\n        // REMINDER: when navigating between tabs in the sheet and exit the sheet, the tab gets lost\n        // We need a minimal delay to allow the sheet to close before focusing back to the row\n        setTimeout(() => el?.focus(), 0);\n      }}\n    >\n      <SheetContent\n        // onCloseAutoFocus={(e) => e.preventDefault()}\n        className=\"overflow-y-auto p-0 sm:max-w-md\"\n        hideClose\n      >\n        <SheetHeader className=\"bg-background sticky top-0 z-10 border-b p-4\">\n          <div className=\"flex items-center justify-between gap-2\">\n            <SheetTitle className={cn(titleClassName, \"truncate text-left\")}>\n              {isLoading && !selectedRowKey ? (\n                <Skeleton className=\"h-7 w-36\" />\n              ) : (\n                title\n              )}\n            </SheetTitle>\n            <div className=\"flex h-7 items-center gap-1\">\n              <TooltipProvider>\n                <Tooltip delayDuration={100}>\n                  <TooltipTrigger asChild>\n                    <Button\n                      size=\"icon\"\n                      variant=\"ghost\"\n                      className=\"h-7 w-7\"\n                      disabled={!prevId}\n                      onClick={onPrev}\n                    >\n                      <ChevronUp className=\"h-5 w-5\" />\n                      <span className=\"sr-only\">Previous</span>\n                    </Button>\n                  </TooltipTrigger>\n                  <TooltipContent>\n                    <p>\n                      Navigate <Kbd>↑</Kbd>\n                    </p>\n                  </TooltipContent>\n                </Tooltip>\n              </TooltipProvider>\n              <TooltipProvider>\n                <Tooltip delayDuration={100}>\n                  <TooltipTrigger asChild>\n                    <Button\n                      size=\"icon\"\n                      variant=\"ghost\"\n                      className=\"h-7 w-7\"\n                      disabled={!nextId}\n                      onClick={onNext}\n                    >\n                      <ChevronDown className=\"h-5 w-5\" />\n                      <span className=\"sr-only\">Next</span>\n                    </Button>\n                  </TooltipTrigger>\n                  <TooltipContent>\n                    <p>\n                      Navigate <Kbd>↓</Kbd>\n                    </p>\n                  </TooltipContent>\n                </Tooltip>\n              </TooltipProvider>\n              <Separator orientation=\"vertical\" className=\"mx-1\" />\n              <SheetClose autoFocus={true} asChild>\n                <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\">\n                  <X className=\"h-5 w-5\" />\n                  <span className=\"sr-only\">Close</span>\n                </Button>\n              </SheetClose>\n            </div>\n          </div>\n        </SheetHeader>\n        <SheetDescription className=\"sr-only\">\n          Selected row details\n        </SheetDescription>\n        <div className=\"p-4\">{children}</div>\n      </SheetContent>\n    </Sheet>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/data-table/data-table-sheet/data-table-sheet-content.tsx",
      "content": "\"use client\";\n\nimport {\n  DataTableCellBadge,\n  DataTableCellBar,\n  DataTableCellBoolean,\n  DataTableCellCode,\n  DataTableCellHeatmap,\n  DataTableCellLevelIndicator,\n  DataTableCellNumber,\n  DataTableCellStar,\n  DataTableCellStatusCode,\n  DataTableCellText,\n  DataTableCellTimestamp,\n} from \"@/components/data-table/data-table-cell\";\nimport type { SerializableDisplayConfig } from \"@/lib/table-schema/types\";\nimport { cn } from \"@/lib/utils\";\nimport { Table } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { DataTableFilterField, SheetField } from \"../types\";\nimport { DataTableSheetRowAction } from \"./data-table-sheet-row-action\";\nimport { SheetDetailsContentSkeleton } from \"./data-table-sheet-skeleton\";\n\nfunction renderSheetValue(\n  rawValue: unknown,\n  display?: SerializableDisplayConfig,\n): React.ReactNode {\n  if (!display) return String(rawValue);\n  const colorMap = display.colorMap;\n  switch (display.type) {\n    case \"timestamp\": {\n      const hex = colorMap?.[String(rawValue)];\n      return rawValue instanceof Date ||\n        typeof rawValue === \"string\" ||\n        typeof rawValue === \"number\" ? (\n        <DataTableCellTimestamp date={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"number\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"number\" ? (\n        <DataTableCellNumber value={rawValue} unit={display.unit} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"bar\": {\n      return typeof rawValue === \"number\" ? (\n        <DataTableCellBar\n          value={rawValue}\n          min={display.min ?? 0}\n          max={display.max ?? 100}\n          unit={display.unit}\n          color={colorMap?.[String(rawValue)]}\n        />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"heatmap\": {\n      return typeof rawValue === \"number\" ? (\n        <DataTableCellHeatmap\n          value={rawValue}\n          min={display.min ?? 0}\n          max={display.max ?? 100}\n          color={display.color}\n        />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"boolean\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"boolean\" ? (\n        <DataTableCellBoolean value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"star\": {\n      return typeof rawValue === \"boolean\" ? (\n        <DataTableCellStar value={rawValue} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"badge\": {\n      if (Array.isArray(rawValue)) {\n        return (\n          <div className=\"flex flex-wrap justify-end gap-1\">\n            {rawValue.map((item, i) => (\n              <DataTableCellBadge\n                key={i}\n                value={item}\n                color={colorMap?.[String(item)]}\n              />\n            ))}\n          </div>\n        );\n      }\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"string\" || typeof rawValue === \"number\" ? (\n        <DataTableCellBadge value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"code\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"string\" || typeof rawValue === \"number\" ? (\n        <DataTableCellCode value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"status-code\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"number\" ? (\n        <DataTableCellStatusCode value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"level-indicator\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"string\" ? (\n        <DataTableCellLevelIndicator value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    case \"text\": {\n      const hex = colorMap?.[String(rawValue)];\n      return typeof rawValue === \"string\" || typeof rawValue === \"number\" ? (\n        <DataTableCellText value={rawValue} color={hex} />\n      ) : (\n        String(rawValue)\n      );\n    }\n    default:\n      return String(rawValue);\n  }\n}\n\ninterface DataTableSheetContentProps<TData, TMeta>\n  extends React.HTMLAttributes<HTMLDListElement> {\n  data?: TData;\n  table: Table<TData>;\n  fields: SheetField<TData, TMeta>[];\n  filterFields: DataTableFilterField<TData>[];\n  // totalRows: number;\n  // filterRows: number;\n  // totalRowsFetched: number;\n  metadata?: TMeta & {\n    totalRows: number;\n    filterRows: number;\n    totalRowsFetched: number;\n  };\n}\n\nexport function DataTableSheetContent<TData, TMeta>({\n  data,\n  table,\n  className,\n  fields,\n  filterFields,\n  metadata,\n  ...props\n}: DataTableSheetContentProps<TData, TMeta>) {\n  if (!data) return <SheetDetailsContentSkeleton fields={fields} />;\n\n  return (\n    <dl className={cn(\"divide-y\", className)} {...props}>\n      {fields.map((field) => {\n        if (field.condition && !field.condition(data)) return null;\n\n        const Component = field.component;\n        const rawValue = data[field.id];\n        const rendered = Component ? (\n          <Component {...data} metadata={metadata} />\n        ) : (\n          renderSheetValue(rawValue, field.display)\n        );\n\n        return (\n          <div key={field.id.toString()}>\n            {field.type === \"readonly\" ? (\n              <div\n                className={cn(\n                  \"my-1 flex w-full items-center justify-between gap-4 py-1 text-sm\",\n                  field.className,\n                )}\n              >\n                <dt className=\"text-muted-foreground shrink-0\">\n                  {field.label}\n                </dt>\n                <dd className=\"w-full text-right font-mono\">{rendered}</dd>\n              </div>\n            ) : (\n              <DataTableSheetRowAction\n                fieldValue={field.id}\n                filterFields={filterFields}\n                value={\n                  typeof rawValue === \"boolean\" || typeof rawValue === \"number\"\n                    ? rawValue\n                    : String(rawValue)\n                }\n                table={table}\n                className={cn(\n                  \"my-1 flex w-full items-center justify-between gap-4 py-1 text-sm\",\n                  field.className,\n                )}\n              >\n                <dt className=\"text-muted-foreground shrink-0\">\n                  {field.label}\n                </dt>\n                <dd className=\"w-full text-right font-mono\">{rendered}</dd>\n              </DataTableSheetRowAction>\n            )}\n          </div>\n        );\n      })}\n    </dl>\n  );\n}\n\nexport const MemoizedDataTableSheetContent = React.memo(\n  DataTableSheetContent,\n  (prev, next) => {\n    // REMINDER: only check if data is the same, rest is useless\n    return prev.data === next.data;\n  },\n) as typeof DataTableSheetContent;\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/data-table/data-table-sheet/data-table-sheet-row-action.tsx",
      "content": "import {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { useCopyToClipboard } from \"@/hooks/use-copy-to-clipboard\";\nimport { cn } from \"@/lib/utils\";\nimport { Table } from \"@tanstack/react-table\";\nimport { endOfDay, endOfHour, startOfDay, startOfHour } from \"date-fns\";\nimport {\n  CalendarClock,\n  CalendarDays,\n  CalendarSearch,\n  ChevronLeft,\n  ChevronRight,\n  Copy,\n  Equal,\n  Search,\n} from \"lucide-react\";\nimport { DataTableFilterField } from \"../types\";\n\ninterface DataTableSheetRowActionProps<\n  TData,\n  TFields extends DataTableFilterField<TData>,\n> extends Omit<\n    React.ComponentPropsWithRef<typeof DropdownMenuTrigger>,\n    \"value\"\n  > {\n  fieldValue: TFields[\"value\"];\n  filterFields: TFields[];\n  value: string | number | boolean;\n  table: Table<TData>;\n}\n\nexport function DataTableSheetRowAction<\n  TData,\n  TFields extends DataTableFilterField<TData>,\n>({\n  fieldValue,\n  filterFields,\n  value,\n  children,\n  className,\n  table,\n  onKeyDown,\n  ...props\n}: DataTableSheetRowActionProps<TData, TFields>) {\n  const { copy, isCopied } = useCopyToClipboard();\n  const field = filterFields.find((field) => field.value === fieldValue);\n  const column = table.getColumn(fieldValue.toString());\n\n  if (!field || !column) return null;\n\n  function renderOptions() {\n    if (!field) return null;\n    switch (field.type) {\n      case \"checkbox\":\n        return (\n          <DropdownMenuItem\n            onClick={() => {\n              // FIXME:\n              const filterValue = column?.getFilterValue() as\n                | undefined\n                | Array<unknown>;\n              const newValue = filterValue?.includes(value)\n                ? filterValue\n                : [...(filterValue || []), value];\n\n              column?.setFilterValue(newValue);\n            }}\n          >\n            <Search />\n            Include\n          </DropdownMenuItem>\n        );\n      case \"input\":\n        return (\n          <DropdownMenuItem onClick={() => column?.setFilterValue(value)}>\n            <Search />\n            Include\n          </DropdownMenuItem>\n        );\n      case \"slider\":\n        return (\n          <DropdownMenuGroup>\n            <DropdownMenuItem\n              onClick={() => column?.setFilterValue([0, value])}\n            >\n              {/* FIXME: change icon as it is not clear */}\n              <ChevronLeft />\n              Less or equal than\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              onClick={() => column?.setFilterValue([value, 5000])}\n            >\n              {/* FIXME: change icon as it is not clear */}\n              <ChevronRight />\n              Greater or equal than\n            </DropdownMenuItem>\n            <DropdownMenuItem onClick={() => column?.setFilterValue([value])}>\n              <Equal />\n              Equal to\n            </DropdownMenuItem>\n          </DropdownMenuGroup>\n        );\n      case \"timerange\":\n        const date = new Date(value as string | number);\n        return (\n          <DropdownMenuGroup>\n            <DropdownMenuItem onClick={() => column?.setFilterValue([date])}>\n              <CalendarSearch />\n              Exact timestamp\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              onClick={() => {\n                const start = startOfHour(date);\n                const end = endOfHour(date);\n                column?.setFilterValue([start, end]);\n              }}\n            >\n              <CalendarClock />\n              Same hour\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              onClick={() => {\n                const start = startOfDay(date);\n                const end = endOfDay(date);\n                column?.setFilterValue([start, end]);\n              }}\n            >\n              <CalendarDays />\n              Same day\n            </DropdownMenuItem>\n          </DropdownMenuGroup>\n        );\n      default:\n        return null;\n    }\n  }\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        className={cn(\n          \"focus-visible:border-ring focus-visible:ring-ring/50 rounded-md transition-all outline-none focus-visible:ring-[3px]\",\n          \"relative\",\n          className,\n        )}\n        onKeyDown={(e) => {\n          if (e.key === \"ArrowDown\") {\n            // REMINDER: default behavior is to open the dropdown menu\n            // But because we use it to navigate between rows, we need to prevent it\n            // and only use \"Enter\" to select the option\n            e.preventDefault();\n          }\n          onKeyDown?.(e);\n        }}\n        {...props}\n      >\n        {children}\n        {isCopied ? (\n          <div className=\"bg-background/70 absolute inset-0 place-content-center\">\n            Value copied\n          </div>\n        ) : null}\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"start\" side=\"left\" className=\"w-48\">\n        {renderOptions()}\n        <DropdownMenuSeparator />\n        <DropdownMenuItem\n          onClick={() => copy(String(value), { timeout: 1000 })}\n        >\n          <Copy />\n          Copy value\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/data-table/data-table-sheet/data-table-sheet-skeleton.tsx",
      "content": "import { Skeleton } from \"@/components/ui/skeleton\";\nimport { cn } from \"@/lib/utils\";\nimport { SheetField } from \"../types\";\n\ninterface SheetDetailsContentSkeletonProps<TData, TMeta> {\n  fields: SheetField<TData, TMeta>[];\n}\n\nexport function SheetDetailsContentSkeleton<TData, TMeta>({\n  fields,\n}: SheetDetailsContentSkeletonProps<TData, TMeta>) {\n  return (\n    <dl className=\"divide-y\">\n      {fields.map((field) => (\n        <div\n          key={field.id.toString()}\n          className=\"flex items-center justify-between gap-4 py-2 text-sm\"\n        >\n          <dt className=\"text-muted-foreground shrink-0\">{field.label}</dt>\n          <div>\n            <Skeleton className={cn(\"h-5 w-52\", field.skeletonClassName)} />\n          </div>\n        </div>\n      ))}\n    </dl>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/custom/sheet.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\n\nconst Sheet = SheetPrimitive.Root;\n\nconst SheetTrigger = SheetPrimitive.Trigger;\n\nconst SheetClose = SheetPrimitive.Close;\n\nconst SheetPortal = SheetPrimitive.Portal;\n\nfunction SheetOverlay({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n  return (\n    <SheetPrimitive.Overlay\n      data-slot=\"sheet-overlay\"\n      className={cn(\n        \"bg-background/40 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nconst sheetVariants = cva(\n  \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 gap-4 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n  {\n    variants: {\n      side: {\n        top: \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b\",\n        bottom:\n          \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t\",\n        left: \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n        right:\n          \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n      },\n    },\n    defaultVariants: {\n      side: \"right\",\n    },\n  },\n);\n\ninterface SheetContentProps\n  extends React.ComponentProps<typeof SheetPrimitive.Content>,\n    VariantProps<typeof sheetVariants> {\n  hideClose?: boolean;\n}\n\nfunction SheetContent({\n  side = \"right\",\n  className,\n  children,\n  hideClose,\n  ...props\n}: SheetContentProps) {\n  return (\n    <SheetPortal>\n      <SheetOverlay />\n      <SheetPrimitive.Content\n        data-slot=\"sheet-content\"\n        className={cn(sheetVariants({ side }), className)}\n        {...props}\n      >\n        {children}\n        {!hideClose ? (\n          <SheetPrimitive.Close\n            autoFocus={true}\n            className=\"data-[state=open]:bg-secondary focus-visible:border-ring focus-visible:ring-ring/50 absolute top-4 right-4 rounded-sm opacity-70 transition-all outline-none hover:opacity-100 focus-visible:ring-[3px] disabled:pointer-events-none\"\n          >\n            <X className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Close</span>\n          </SheetPrimitive.Close>\n        ) : null}\n      </SheetPrimitive.Content>\n    </SheetPortal>\n  );\n}\n\nfunction SheetHeader({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <div\n      className={cn(\n        \"flex flex-col space-y-2 text-center sm:text-left\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction SheetFooter({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <div\n      className={cn(\n        \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction SheetTitle({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n  return (\n    <SheetPrimitive.Title\n      data-slot=\"sheet-title\"\n      className={cn(\"text-foreground text-lg font-semibold\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction SheetDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n  return (\n    <SheetPrimitive.Description\n      data-slot=\"sheet-description\"\n      className={cn(\"text-muted-foreground text-sm\", className)}\n      {...props}\n    />\n  );\n}\n\nexport {\n  Sheet,\n  SheetPortal,\n  SheetOverlay,\n  SheetTrigger,\n  SheetClose,\n  SheetContent,\n  SheetHeader,\n  SheetFooter,\n  SheetTitle,\n  SheetDescription,\n};\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:block"
}