{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "motion-drawer",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/ui/motion-drawer.tsx",
      "content": "'use client';\nimport { cn } from '@/lib/utils';\nimport { Menu, X } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport type React from 'react';\nimport { useState } from 'react';\n\nexport type SideMenuDirection = 'left' | 'right';\nexport type ButtonOpeningVariants = 'push' | 'merge' | 'stay';\n\ninterface SideMenuProps {\n  // Appearance\n  overlayColor?: string;\n  width?: number;\n  direction?: SideMenuDirection;\n  backgroundColor?: string;\n\n  // Content\n  children: React.ReactNode;\n\n  // Behavior\n  isOpen?: boolean;\n  onToggle?: (isOpen: boolean) => void;\n  showToggleButton?: boolean;\n  toggleButtonText?: {\n    open: string;\n    close: string;\n  };\n\n  // Styling\n  btnClassName?: string;\n  className?: string;\n  contentClassName?: string;\n  clsBtnClassName?: string;\n  overlayClassName?: string;\n\n  // Animation\n  animationConfig?: {\n    type?: 'spring' | 'tween';\n    damping?: number;\n    stiffness?: number;\n    duration?: number;\n  };\n\n  // Drag behavior\n  enableDrag?: boolean;\n  dragThreshold?: number;\n\n  // New prop\n  buttonOpeningVariants?: ButtonOpeningVariants;\n}\n\nconst getOpenButtonVariants = (\n  direction: SideMenuDirection,\n  width: number,\n  type: ButtonOpeningVariants\n) => {\n  switch (type) {\n    case 'merge':\n      return direction === 'left'\n        ? {\n            closed: { x: 0, opacity: 1, scale: 1, borderRadius: '0.5rem' },\n            open: {\n              x: width - 68,\n              opacity: 0,\n              scale: 1,\n              borderRadius: '0rem',\n            },\n          }\n        : {\n            closed: { x: 0, opacity: 1, scale: 1, borderRadius: '0.5rem' },\n            open: {\n              x: 68 - width,\n              opacity: 0,\n              scale: 1,\n              borderRadius: '0rem',\n            },\n          };\n\n    case 'push':\n      return direction === 'left'\n        ? { closed: { x: 0, opacity: 1 }, open: { x: width + 20, opacity: 0 } }\n        : {\n            closed: { x: 0, opacity: 1 },\n            open: { x: -(width + 20), opacity: 0 },\n          };\n\n    case 'stay':\n    default:\n      return {\n        closed: { x: 0, opacity: 1 },\n        open: { x: 0, opacity: 0 },\n      };\n  }\n};\n\nconst MotionDrawer: React.FC<SideMenuProps> = ({\n  // Appearance\n  overlayColor = 'rgba(0, 0, 0, 0.3)',\n  width = 250,\n  direction = 'left',\n  backgroundColor = '#ffffff',\n\n  // Content\n  children,\n\n  // Behavior\n  isOpen: controlledIsOpen,\n  onToggle,\n  showToggleButton = true,\n\n  // Styling\n  btnClassName = '',\n  clsBtnClassName = '',\n  className = '',\n  contentClassName = '',\n  overlayClassName = '',\n\n  // Animation\n  animationConfig = {\n    type: 'spring',\n    damping: 25,\n    stiffness: 120,\n  },\n\n  // Drag behavior\n  enableDrag = true,\n  dragThreshold = 0.3,\n\n  buttonOpeningVariants = 'merge',\n}) => {\n  const [internalIsOpen, setInternalIsOpen] = useState<boolean>(false);\n\n  const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n  const setIsOpen = (value: boolean) => {\n    if (controlledIsOpen === undefined) {\n      setInternalIsOpen(value);\n    }\n    onToggle?.(value);\n  };\n\n  const getDrawerVariants = () => {\n    if (direction === 'left') {\n      return {\n        closed: { x: -width },\n        open: { x: 0 },\n      };\n    } else {\n      return {\n        closed: { x: width },\n        open: { x: 0 },\n      };\n    }\n  };\n\n  const buttonVariants = getOpenButtonVariants(direction, width, buttonOpeningVariants);\n\n  const getDragConstraints = () => {\n    if (direction === 'left') {\n      return { left: -width, right: 0 };\n    } else {\n      return { left: 0, right: width };\n    }\n  };\n\n  const handleDragEnd = (_event: any, info: any) => {\n    if (!enableDrag) return;\n\n    const threshold = width * dragThreshold;\n    const dragDistance = Math.abs(info.offset.x);\n\n    if (direction === 'left') {\n      const isDraggingLeft = info.offset.x < 0;\n      if (isDraggingLeft && dragDistance > threshold && isOpen) {\n        setIsOpen(false);\n      } else if (!isDraggingLeft && dragDistance > threshold && !isOpen) {\n        setIsOpen(true);\n      }\n    } else {\n      const isDraggingRight = info.offset.x > 0;\n      if (isDraggingRight && dragDistance > threshold && isOpen) {\n        setIsOpen(false);\n      } else if (!isDraggingRight && dragDistance > threshold && !isOpen) {\n        setIsOpen(true);\n      }\n    }\n  };\n\n  const drawerPositionClasses = direction === 'left' ? 'left-0' : 'right-0';\n  const openButtonPositionClasses = direction === 'left' ? 'top-4 left-4' : 'top-4 right-4';\n\n  return (\n    <>\n      {showToggleButton && (\n        <motion.button\n          className={cn(\n            `fixed z-99 text-primary cursor-pointer ${openButtonPositionClasses}`,\n            btnClassName\n          )}\n          onClick={() => setIsOpen(true)}\n          variants={buttonVariants}\n          animate={isOpen ? 'open' : 'closed'}\n          transition={animationConfig}\n          whileHover={{ scale: 1.05 }}\n          whileTap={{ scale: 0.95 }}\n        >\n          <Menu />\n          {/* Open */}\n        </motion.button>\n      )}\n\n      <AnimatePresence>\n        {isOpen && (\n          <div className={`fixed w-full h-full top-0 left-0 z-9999 ${className}`}>\n            {/* Overlay */}\n            <motion.div\n              className={`absolute w-full h-full top-0 left-0 ${overlayClassName}`}\n              style={{ backgroundColor: overlayColor }}\n              onClick={() => setIsOpen(false)}\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 0 }}\n              transition={{ duration: 0.3 }}\n            />\n\n            {/* Drawer */}\n            <motion.div\n              className={`absolute h-full shadow-[8px_1px_21px_0px_rgba(17,17,26,0.1)] ${drawerPositionClasses} ${contentClassName}`}\n              style={{\n                backgroundColor,\n                width: `${width}px`,\n                padding: '60px 30px 30px 30px',\n                boxSizing: 'border-box',\n              }}\n              drag={enableDrag ? 'x' : false}\n              dragElastic={0.1}\n              dragConstraints={getDragConstraints()}\n              dragMomentum={false}\n              onDragEnd={handleDragEnd}\n              variants={getDrawerVariants()}\n              initial='closed'\n              animate='open'\n              exit='closed'\n              transition={animationConfig}\n            >\n              {/* Close Button */}\n              {showToggleButton && (\n                <motion.button\n                  className={cn(\n                    'absolute top-2 right-8 p-2 text-black cursor-pointer',\n                    clsBtnClassName\n                  )}\n                  onClick={() => setIsOpen(false)}\n                  whileHover={{ scale: 1.1 }}\n                  whileTap={{ scale: 0.9 }}\n                  transition={{ duration: 0.2 }}\n                >\n                  <X size={20} /> {/* Close */}\n                </motion.button>\n              )}\n\n              {/* Content */}\n              <div className='h-full overflow-y-auto'>{children}</div>\n            </motion.div>\n          </div>\n        )}\n      </AnimatePresence>\n    </>\n  );\n};\n\nexport default MotionDrawer;\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}