{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "modal",
  "title": "Modal",
  "description": "Dialog with sm/md/lg/xl/fullscreen sizes and optional scrollable body.",
  "dependencies": ["@radix-ui/react-dialog", "lucide-react"],
  "registryDependencies": [
    "https://indiacn.in/r/theme.json",
    "https://indiacn.in/r/typography.json"
  ],
  "files": [
    {
      "path": "components/ui/modal.tsx",
      "content": "'use client';\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport { ComponentProps } from 'react';\n\nimport { Body2, Headline5, Label2 } from '@/components/ui/typography';\nimport { cn } from '@/lib/utils';\n\n/*\n * UX4G modal: border-radius 0.5rem, padding 1rem, border 1px solid rgba(0,0,0,0.175),\n * NO header border-bottom, NO footer border-top,\n * sizes: sm=300px, default=500px, lg=800px, xl=1140px,\n * animation: translate(0,-50px) -> none, 0.3s ease-out\n */\n\n/** Modal dialog root component. */\nfunction Modal(props: ComponentProps<typeof DialogPrimitive.Root>) {\n  return <DialogPrimitive.Root {...props} />;\n}\n\n/** Modal trigger button. */\nfunction ModalTrigger(props: ComponentProps<typeof DialogPrimitive.Trigger>) {\n  return <DialogPrimitive.Trigger {...props} />;\n}\n\n/** Modal close button. */\nfunction ModalClose(props: ComponentProps<typeof DialogPrimitive.Close>) {\n  return <DialogPrimitive.Close {...props} />;\n}\n\n/** Modal portal container. */\nfunction ModalPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n  return <DialogPrimitive.Portal {...props} />;\n}\n\n/** Semi-transparent backdrop overlay for modals. */\nfunction ModalOverlay({ className, ...props }: ComponentProps<typeof DialogPrimitive.Overlay>) {\n  return (\n    <DialogPrimitive.Overlay\n      className={cn(\n        '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 bg-black/50',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\ninterface IModalContentProps extends ComponentProps<typeof DialogPrimitive.Content> {\n  size?: 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen';\n  scrollable?: boolean;\n}\n\n/**\n * Main modal content container.\n * Matches the UX4G 2.0 Modal specification.\n *\n * Sizes match UX4G: sm=300px, md=500px, lg=800px, xl=1140px, fullscreen=100%.\n * UX4G removes borders between header/body/footer sections.\n */\nfunction ModalContent({\n  className,\n  size = 'md',\n  scrollable = false,\n  children,\n  ...props\n}: IModalContentProps) {\n  const sizeClasses = {\n    sm: 'max-w-[300px]',\n    md: 'max-w-[500px]',\n    lg: 'max-w-[800px]',\n    xl: 'max-w-[1140px]',\n    fullscreen: 'max-w-none h-full w-full rounded-none',\n  };\n\n  return (\n    <ModalPortal>\n      <ModalOverlay />\n      <DialogPrimitive.Content\n        className={cn(\n          'bg-neutral-0 fixed top-1/2 left-1/2 z-50 flex w-full -translate-x-1/2 -translate-y-1/2 flex-col rounded-lg border border-neutral-200 shadow-lg duration-300 ease-out',\n          'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-top-[50px] data-[state=open]:slide-in-from-top-[50px]',\n          scrollable && 'max-h-[calc(100vh-3.5rem)]',\n          sizeClasses[size],\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </DialogPrimitive.Content>\n    </ModalPortal>\n  );\n}\n\n/**\n * Modal header. UX4G: padding 1rem, NO border-bottom.\n */\nfunction ModalHeader({ className, children, ...props }: ComponentProps<'div'>) {\n  return (\n    <div className={cn('flex shrink-0 items-center justify-between p-4', className)} {...props}>\n      {children}\n      <DialogPrimitive.Close className='hover:bg-primary/8 focus:shadow-focus-primary active:bg-primary/16 rounded-lg p-2 opacity-70 transition-all hover:opacity-100 focus:outline-none'>\n        <X className='size-6' />\n        <Label2 className='sr-only'>Close</Label2>\n      </DialogPrimitive.Close>\n    </div>\n  );\n}\n\n/**\n * Modal title. UX4G: line-height 1.5.\n */\nfunction ModalTitle({\n  className,\n  children,\n  ...props\n}: ComponentProps<typeof DialogPrimitive.Title>) {\n  return (\n    <DialogPrimitive.Title asChild {...props}>\n      <Headline5 className={cn('leading-normal', className)}>{children}</Headline5>\n    </DialogPrimitive.Title>\n  );\n}\n\n/** Accessible description text for a modal. */\nfunction ModalDescription({\n  className,\n  children,\n  ...props\n}: ComponentProps<typeof DialogPrimitive.Description>) {\n  return (\n    <DialogPrimitive.Description asChild {...props}>\n      <Body2 className={cn('text-neutral-500', className)}>{children}</Body2>\n    </DialogPrimitive.Description>\n  );\n}\n\n/**\n * Modal body. UX4G: padding 1rem, flex 1 1 auto.\n */\nfunction ModalBody({\n  className,\n  scrollable,\n  ...props\n}: ComponentProps<'div'> & { scrollable?: boolean }) {\n  return (\n    <div className={cn('flex-1 p-4', scrollable && 'overflow-y-auto', className)} {...props} />\n  );\n}\n\n/**\n * Modal footer. UX4G: padding ~0.75rem, NO border-top, flex-end, gap 0.5rem.\n */\nfunction ModalFooter({ className, ...props }: ComponentProps<'div'>) {\n  return (\n    <div\n      className={cn('flex shrink-0 flex-wrap items-center justify-end gap-2 p-3', className)}\n      {...props}\n    />\n  );\n}\n\nexport {\n  Modal,\n  ModalTrigger,\n  ModalClose,\n  ModalContent,\n  ModalHeader,\n  ModalTitle,\n  ModalDescription,\n  ModalBody,\n  ModalFooter,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
