{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loginform",
  "type": "registry:ui",
  "title": "Login Form",
  "description": "Modern, responsive login form with smooth transitions and gradient accents.",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": [
    "@scrollxui/button",
    "@scrollxui/card",
    "@scrollxui/label",
    "@scrollxui/transition"
  ],
  "dependencies": [
    "motion",
    "@radix-ui/react-slot",
    "class-variance-authority",
    "@radix-ui/react-label",
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/loginform.tsx",
      "content": "'use client';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Label } from '@/components/ui/label';\nimport Transition from '@/components/ui/transition';\nimport { motion } from 'motion/react';\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 bg-background px-3 py-2 text-base ring-offset-background 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 transition-all duration-300',\n          className,\n        )}\n        style={{\n          borderWidth: '2px',\n          borderImage: `conic-gradient(\n            rgb(212, 212, 212) 0deg,\n            rgb(23, 23, 23) 90deg,\n            rgb(212, 212, 212) 180deg,\n            rgb(23, 23, 23) 270deg,\n            rgb(212, 212, 212) 360deg\n          ) 1 / 1 / 0 stretch`,\n        }}\n        ref={ref}\n        {...props}\n      />\n    );\n  },\n);\n\nInput.displayName = 'Input';\n\nexport function LoginForm({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  const introContent = (triggerExit: () => void) => (\n    <div className='flex flex-col items-center justify-center '>\n      <div className='mb-6 text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold text-white dark:text-black text-center'>\n        ScrollX UI\n      </div>\n      <div className='text-lg sm:text-xl md:text-2xl text-white dark:text-black font-light tracking-wide opacity-80 max-w-70 sm:max-w-md text-center wrap-break-word'>\n        Welcome back, let's craft something cool\n      </div>\n      <div className='mt-4 w-16 h-0.5 bg-white/50'></div>\n      <button\n        onClick={triggerExit}\n        className='mt-8 px-6 py-2 border border-white/30 dark:border-black/30 text-white dark:text-black hover:bg-white/10 dark:hover:bg-black/10 rounded-full transition-all duration-300 text-sm tracking-wide'\n      >\n        Click to continue\n      </button>\n    </div>\n  );\n\n  const [transitionEnded, setTransitionEnded] = React.useState(false);\n\n  return (\n    <div className='bg-muted flex min-h-svh flex-col items-center justify-center p-6 md:p-10'>\n      <div className='w-full max-w-sm  md:max-w-3xl'>\n        <div\n          className={cn('flex flex-col gap-6 overflow-hidden ', className)}\n          {...props}\n        >\n          <Transition\n            intro={introContent}\n            introDuration={3}\n            transitionDuration={1.2}\n            type='slide'\n            direction='right'\n            className='bg-neutral-900 dark:bg-white rounded-xl'\n            autoExit={false}\n            onFinished={() => setTransitionEnded(true)}\n          >\n            <Card className='overflow-hidden p-0 border-0 backdrop-blur-xs'>\n              <CardContent className='grid p-0 md:grid-cols-2 bg-[hsla(240,4%,16%,1)]  dark:bg-white'>\n                <div className='p-6 md:p-8 relative'>\n                  <div className='flex flex-col gap-6 relative z-10'>\n                    <div className='flex flex-col items-center text-center'>\n                      <h1 className='text-3xl font-bold bg-linear-to-r from-purple-600 to-purple-700 hover:from-purple-700 hover:to-purple-800 bg-clip-text text-transparent'>\n                        Welcome back\n                      </h1>\n                      <p className='text-muted-foreground text-balance mt-2'>\n                        Login to your account\n                      </p>\n                    </div>\n\n                    <div className='grid gap-4'>\n                      <div className='space-y-2'>\n                        <Label\n                          htmlFor='email'\n                          className='text-sm dark:text-black text-white font-medium'\n                        >\n                          Email\n                        </Label>\n                        <Input\n                          id='email'\n                          type='email'\n                          placeholder='s@example.com'\n                          required\n                          className='h-12 border-gray-200 focus:border-purple-500 focus:ring-purple-500/20 transition-all duration-200'\n                        />\n                      </div>\n                      <div className='space-y-2'>\n                        <div className='flex items-center justify-between'>\n                          <Label\n                            htmlFor='password'\n                            className='text-sm dark:text-black text-white  font-medium'\n                          >\n                            Password\n                          </Label>\n                          <a\n                            href='#'\n                            className='text-sm text-purple-600 hover:text-purple-700 underline-offset-2 hover:underline transition-colors'\n                          >\n                            Forgot password?\n                          </a>\n                        </div>\n                        <Input\n                          id='password'\n                          type='password'\n                          required\n                          className='h-12 border-gray-200 focus:border-purple-500 focus:ring-purple-500/20 transition-all duration-200'\n                        />\n                      </div>\n                    </div>\n\n                    <Button\n                      type='submit'\n                      className='w-full h-12 bg-linear-to-r from-purple-600 to-purple-700 hover:from-purple-700 hover:to-purple-800 text-white font-medium rounded-lg shadow-lg hover:shadow-xl transition-all duration-200 transform hover:-translate-y-0.5'\n                    >\n                      Sign In\n                    </Button>\n\n                    <div className='relative'>\n                      <div className='absolute inset-0 flex items-center'>\n                        <span className='w-full border-t border-gray-200' />\n                      </div>\n                      <div className='relative flex justify-center text-xs uppercase'>\n                        <span className='bg-white dark:bg-black dark:text-gray-200 px-3 text-gray-500 font-medium'>\n                          Or continue with\n                        </span>\n                      </div>\n                    </div>\n\n                    <div className='grid grid-cols-3 gap-3'>\n                      <Button\n                        variant='outline'\n                        type='button'\n                        className='h-12 border-gray-200 hover:border-gray-300 hover:bg-gray-200 dark:hover:bg-neutral-800 transition-all duration-200 hover:shadow-md'\n                      >\n                        <svg\n                          xmlns='http://www.w3.org/2000/svg'\n                          viewBox='0 0 24 24'\n                          className='w-5 h-5'\n                        >\n                          <path\n                            d='M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701'\n                            fill='currentColor'\n                          />\n                        </svg>\n                        <span className='sr-only'>Login with Apple</span>\n                      </Button>\n                      <Button\n                        variant='outline'\n                        type='button'\n                        className='h-12 border-gray-200 hover:border-gray-300 hover:bg-gray-200 dark:hover:bg-neutral-800 transition-all duration-200 hover:shadow-md'\n                      >\n                        <svg\n                          xmlns='http://www.w3.org/2000/svg'\n                          viewBox='0 0 24 24'\n                          className='w-5 h-5'\n                        >\n                          <path\n                            d='M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z'\n                            fill='currentColor'\n                          />\n                        </svg>\n                        <span className='sr-only'>Login with Google</span>\n                      </Button>\n                      <Button\n                        variant='outline'\n                        type='button'\n                        className='h-12 border-gray-200 hover:border-gray-300 hover:bg-gray-200 dark:hover:bg-neutral-800 transition-all duration-200 hover:shadow-md'\n                      >\n                        <svg\n                          xmlns='http://www.w3.org/2000/svg'\n                          width='48'\n                          height='48'\n                          viewBox='0 0 21 21'\n                        >\n                          <g\n                            fill='none'\n                            stroke='currentColor'\n                            strokeLinecap='round'\n                            strokeLinejoin='round'\n                            strokeWidth='2'\n                          >\n                            <path\n                              strokeDasharray='32'\n                              strokeDashoffset='32'\n                              d='M12 4c1.67 0 2.61 0.4 3 0.5c0.53 -0.43 1.94 -1.5 3.5 -1.5c0.34 1 0.29 2.22 0 3c0.75 1 1 2 1 3.5c0 2.19 -0.48 3.58 -1.5 4.5c-1.02 0.92 -2.11 1.37 -3.5 1.5c0.65 0.54 0.5 1.87 0.5 2.5c0 0.73 0 3 0 3M12 4c-1.67 0 -2.61 0.4 -3 0.5c-0.53 -0.43 -1.94 -1.5 -3.5 -1.5c-0.34 1 -0.29 2.22 0 3c-0.75 1 -1 2 -1 3.5c0 2.19 0.48 3.58 1.5 4.5c1.02 0.92 2.11 1.37 3.5 1.5c-0.65 0.54 -0.5 1.87 -0.5 2.5c0 0.73 0 3 0 3'\n                            >\n                              <animate\n                                fill='freeze'\n                                attributeName='stroke-dashoffset'\n                                dur='0.7s'\n                                values='32;0'\n                              />\n                            </path>\n                            <path\n                              strokeDasharray='10'\n                              strokeDashoffset='10'\n                              d='M9 19c-1.41 0 -2.84 -0.56 -3.69 -1.19c-0.84 -0.63 -1.09 -1.66 -2.31 -2.31'\n                            >\n                              <animate\n                                fill='freeze'\n                                attributeName='stroke-dashoffset'\n                                begin='0.8s'\n                                dur='0.2s'\n                                values='10;0'\n                              />\n                            </path>\n                          </g>\n                        </svg>\n                        <span className='sr-only'>Login with Github</span>\n                      </Button>\n                    </div>\n\n                    <div className='text-center text-sm dark:text-gray-600 text-gray-400'>\n                      Don&apos;t have an account?{' '}\n                      <a\n                        href='#'\n                        className='text-purple-600 hover:text-purple-700 underline underline-offset-4 transition-colors'\n                      >\n                        Sign up\n                      </a>\n                    </div>\n                  </div>\n                </div>\n\n                <div className='relative hidden md:flex overflow-hidden w-full h-full'>\n                  <img\n                    src='https://images.unsplash.com/photo-1636928332666-5b92cd14a46c?q=80&w=1920&auto=format&fit=crop&ixlib=rb-4.0.3'\n                    alt='Background'\n                    className='absolute inset-0 w-full h-full object-cover'\n                  />\n                </div>\n              </CardContent>\n            </Card>\n          </Transition>\n\n          {transitionEnded && (\n            <div className='w-full max-w-sm md:max-w-3xl mx-auto px-4 sm:px-6'>\n              <motion.div\n                className='text-muted-foreground text-center text-xs sm:text-sm text-balance wrap-break-word'\n                initial={{ opacity: 0, y: 16 }}\n                animate={{ opacity: 1, y: 0 }}\n                transition={{ duration: 0.5, ease: 'easeOut' }}\n              >\n                By clicking continue, you agree to our{' '}\n                <a\n                  href='#'\n                  className='text-purple-600 hover:text-purple-700 underline underline-offset-4 transition-colors'\n                >\n                  Terms of Service\n                </a>{' '}\n                and{' '}\n                <a\n                  href='#'\n                  className='text-purple-600 hover:text-purple-700 underline underline-offset-4 transition-colors'\n                >\n                  Privacy Policy\n                </a>\n                .\n              </motion.div>\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\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/card.tsx",
      "content": "import * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nfunction Card({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card'\n      className={cn(\n        'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-xs',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-header'\n      className={cn(\n        '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-title'\n      className={cn('leading-none font-semibold', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-description'\n      className={cn('text-muted-foreground text-sm', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-action'\n      className={cn(\n        'col-start-2 row-span-2 row-start-1 self-start justify-self-end',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-content'\n      className={cn('px-6', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-footer'\n      className={cn('flex items-center px-6 [.border-t]:pt-6', className)}\n      {...props}\n    />\n  );\n}\n\nexport {\n  Card,\n  CardHeader,\n  CardFooter,\n  CardTitle,\n  CardAction,\n  CardDescription,\n  CardContent,\n};\n"
    },
    {
      "type": "registry:ui",
      "path": "components/ui/label.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { motion, useInView, HTMLMotionProps } from 'motion/react';\nimport { cn } from '@/lib/utils';\n\ninterface LabelProps extends Omit<HTMLMotionProps<'label'>, 'direction'> {\n  direction?: 'left' | 'right' | 'top' | 'bottom';\n  disableAnimation?: boolean;\n}\n\nfunction mergeRefs<T>(\n  ...refs: Array<React.Ref<T> | undefined>\n): React.RefCallback<T> {\n  return (value) => {\n    refs.forEach((ref) => {\n      if (!ref) return;\n      if (typeof ref === 'function') ref(value);\n      else (ref as React.MutableRefObject<T | null>).current = value;\n    });\n  };\n}\n\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n  ({ direction = 'left', disableAnimation, className, ...props }, ref) => {\n    const localRef = React.useRef<HTMLLabelElement>(null);\n    const isInView = useInView(localRef, { once: false, margin: '-50px' });\n\n    const variants = {\n      left: { initial: { x: -20 }, animate: { x: 0 } },\n      right: { initial: { x: 20 }, animate: { x: 0 } },\n      top: { initial: { y: -20 }, animate: { y: 0 } },\n      bottom: { initial: { y: 20 }, animate: { y: 0 } },\n    };\n\n    const baseClasses = cn(\n      'flex items-center gap-2 text-sm leading-none font-medium select-none user-select-none',\n      'peer-disabled:cursor-not-allowed peer-disabled:opacity-70',\n      className,\n    );\n\n    if (disableAnimation) {\n      return (\n        <motion.label\n          ref={mergeRefs(ref, localRef)}\n          className={baseClasses}\n          {...props}\n        />\n      );\n    }\n\n    return (\n      <motion.label\n        ref={mergeRefs(ref, localRef)}\n        initial={variants[direction].initial}\n        animate={\n          isInView ? variants[direction].animate : variants[direction].initial\n        }\n        transition={{ duration: 0.4, ease: 'easeOut' }}\n        className={baseClasses}\n        {...props}\n      />\n    );\n  },\n);\n\nLabel.displayName = 'Label';\n\nexport { Label };\n"
    },
    {
      "type": "registry:ui",
      "path": "components/ui/transition.tsx",
      "content": "'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useInView } from 'motion/react';\n\ntype Type = 'curved' | 'slide';\ntype Dir = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface TransitionProps {\n  intro: React.ReactNode | ((triggerExit: () => void) => React.ReactNode);\n  children: React.ReactNode;\n  introDuration?: number;\n  transitionDuration?: number;\n  type?: Type;\n  direction?: Dir;\n  className?: string;\n  skip?: boolean;\n  autoExit?: boolean;\n  trigger?: boolean;\n  onFinished?: () => void;\n}\n\nconst easeInOutCubic = (t: number) =>\n  t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;\n\nexport const Transition: React.FC<TransitionProps> = ({\n  intro,\n  children,\n  introDuration = 1.5,\n  transitionDuration = 0.9,\n  type = 'curved',\n  direction = 'bottom',\n  className = 'bg-neutral-900 dark:bg-white',\n  skip = false,\n  autoExit = true,\n  trigger,\n  onFinished,\n}) => {\n  const [showIntro, setShowIntro] = useState(!skip);\n  const [animating, setAnimating] = useState(false);\n  const [progress, setProgress] = useState(0);\n\n  const ref = useRef<HTMLDivElement>(null);\n  const inView = useInView(ref, { margin: '-100px', once: true });\n\n  const rafRef = useRef<number | null>(null);\n  const timersRef = useRef<number[]>([]);\n\n  const propsRef = useRef({ transitionDuration, onFinished });\n  useEffect(() => {\n    propsRef.current = { transitionDuration, onFinished };\n  }, [transitionDuration, onFinished]);\n\n  const [triggerExit] = useState(() => {\n    return () => {\n      setAnimating(true);\n      let startTime: number | null = null;\n\n      const tick = (now: number) => {\n        if (!startTime) startTime = now;\n        const elapsed = (now - startTime) / 1000;\n        const raw = Math.min(elapsed / propsRef.current.transitionDuration, 1);\n        const eased = easeInOutCubic(raw);\n        setProgress(eased);\n\n        if (raw < 1) {\n          rafRef.current = requestAnimationFrame(tick);\n        } else {\n          setAnimating(false);\n          setShowIntro(false);\n          setProgress(0);\n          rafRef.current = null;\n          propsRef.current.onFinished?.();\n        }\n      };\n\n      rafRef.current = requestAnimationFrame(tick);\n    };\n  });\n\n  const startTransition = triggerExit;\n\n  useEffect(() => {\n    if (skip) {\n      onFinished?.();\n      return;\n    }\n\n    if (inView && autoExit) {\n      const t = window.setTimeout(\n        () => startTransition(),\n        introDuration * 1000,\n      );\n      timersRef.current.push(t);\n    }\n\n    const currentTimers = timersRef.current;\n    return () => {\n      currentTimers.forEach(clearTimeout);\n      if (rafRef.current) cancelAnimationFrame(rafRef.current);\n    };\n  }, [skip, inView, introDuration, autoExit, onFinished, startTransition]);\n\n  useEffect(() => {\n    if (!autoExit && trigger && showIntro) {\n      startTransition();\n    }\n  }, [trigger, autoExit, showIntro, startTransition]);\n\n  const getCurvedClip = (p: number) => {\n    const startRadius = 160;\n    const radius = Math.max(0, startRadius * (1 - p));\n    switch (direction) {\n      case 'top':\n        return `circle(${radius}% at 50% 0%)`;\n      case 'bottom':\n        return `circle(${radius}% at 50% 100%)`;\n      case 'left':\n        return `circle(${radius}% at 0% 50%)`;\n      case 'right':\n      default:\n        return `circle(${radius}% at 100% 50%)`;\n    }\n  };\n\n  const getSlideTransform = (p: number) => {\n    const pct = Math.round(p * 100);\n    switch (direction) {\n      case 'bottom':\n        return `translateY(${pct}%)`;\n      case 'top':\n        return `translateY(${-pct}%)`;\n      case 'left':\n        return `translateX(${-pct}%)`;\n      case 'right':\n      default:\n        return `translateX(${pct}%)`;\n    }\n  };\n\n  return (\n    <div ref={ref} className='relative w-full h-full min-h-full'>\n      <div className='relative z-0 w-full h-full'>{children}</div>\n\n      {showIntro && (\n        <div\n          className='absolute inset-0 z-40 flex items-center justify-center'\n          aria-hidden={!showIntro ? undefined : true}\n        >\n          <div\n            className='absolute inset-0'\n            style={\n              type === 'curved'\n                ? {\n                    clipPath: getCurvedClip(progress),\n                    transition: animating ? undefined : 'none',\n                  }\n                : { transform: getSlideTransform(progress) }\n            }\n          >\n            <div className={`absolute inset-0 ${className}`} />\n            <div className='absolute inset-0 flex items-center justify-center'>\n              {typeof intro === 'function' ? intro(triggerExit) : intro}\n            </div>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default Transition;\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}"
    }
  ]
}
