{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "card-flip",
  "title": "3d Flip Card",
  "description": "An interactive card component that flips on hover with smooth 3D transitions.",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "registry/cards/card-flip/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { HTMLMotionProps, motion } from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\nconst TRANSITION_CONFIG = {\n  duration: 0.7,\n  ease: [0.4, 0.2, 0.2, 1],\n} as const;\n\nconst TRANSFORM_STYLES: React.CSSProperties = {\n  transformStyle: 'preserve-3d',\n  perspective: '1000px',\n  backfaceVisibility: 'hidden',\n};\n\ntype FlipDirection = 'horizontal' | 'vertical';\ninterface CardFlipProps extends React.HTMLAttributes<HTMLDivElement> {\n  flipDirection?: FlipDirection;\n  initialFlipped?: boolean;\n  onFlip?: (isFlipped: boolean) => void;\n  disabled?: boolean;\n}\ninterface CardFlipContextValue {\n  isFlipped: boolean;\n  flipDirection: FlipDirection;\n  disabled?: boolean;\n}\n\nconst CardFlipContext = React.createContext<CardFlipContextValue | undefined>(\n  undefined,\n);\nfunction useCardFlipContext() {\n  const context = React.useContext(CardFlipContext);\n  if (!context) {\n    throw new Error('useCardFlipContext must be used within a CardFlip');\n  }\n  return context;\n}\n\nconst CardFlip = React.memo(\n  React.forwardRef<HTMLDivElement, CardFlipProps>(\n    (\n      {\n        className,\n        flipDirection = 'horizontal',\n        initialFlipped = false,\n        onFlip,\n        disabled,\n        ...props\n      },\n      ref,\n    ) => {\n      const [isFlipped, setIsFlipped] = React.useState(initialFlipped);\n\n      const handleMouseEnter = React.useCallback(() => {\n        if (!disabled) {\n          setIsFlipped(true);\n          onFlip?.(true);\n        }\n      }, [disabled, onFlip]);\n\n      const handleMouseLeave = React.useCallback(() => {\n        if (!disabled) {\n          setIsFlipped(false);\n          onFlip?.(false);\n        }\n      }, [disabled, onFlip]);\n\n      const contextValue = React.useMemo(\n        () => ({ isFlipped, flipDirection, disabled }),\n        [isFlipped, flipDirection, disabled],\n      );\n\n      return (\n        <CardFlipContext.Provider value={contextValue}>\n          <div\n            ref={ref}\n            className={cn(\n              'relative border-none bg-none shadow-none',\n              disabled && 'pointer-events-none',\n              className,\n            )}\n            style={{\n              ...TRANSFORM_STYLES,\n              ...props.style,\n            }}\n            onMouseEnter={handleMouseEnter}\n            onMouseLeave={handleMouseLeave}\n            role=\"button\"\n            tabIndex={disabled ? -1 : 0}\n            aria-pressed={isFlipped}\n            {...props}\n          />\n        </CardFlipContext.Provider>\n      );\n    },\n  ),\n);\nCardFlip.displayName = 'CardFlip';\n\nconst CardFlipFront = React.memo(\n  React.forwardRef<HTMLDivElement, HTMLMotionProps<'div'>>(\n    ({ className, ...props }, ref) => {\n      const { isFlipped, flipDirection } = useCardFlipContext();\n\n      const rotation = React.useMemo(() => {\n        if (!isFlipped) return { rotateX: 0, rotateY: 0 };\n        return flipDirection === 'horizontal'\n          ? { rotateY: -180, rotateX: 0 }\n          : { rotateX: -180, rotateY: 0 };\n      }, [isFlipped, flipDirection]);\n\n      return (\n        <motion.div\n          ref={ref}\n          className={cn(\n            'absolute inset-0 z-20 size-full overflow-hidden',\n            className,\n          )}\n          initial={false}\n          animate={rotation}\n          transition={TRANSITION_CONFIG}\n          style={{\n            ...TRANSFORM_STYLES,\n            ...props.style,\n          }}\n          {...props}\n        />\n      );\n    },\n  ),\n);\nCardFlipFront.displayName = 'CardFlipFront';\n\nconst CardFlipBack = React.memo(\n  React.forwardRef<HTMLDivElement, HTMLMotionProps<'div'>>(\n    ({ className, ...props }, ref) => {\n      const { isFlipped, flipDirection } = useCardFlipContext();\n\n      const rotation = React.useMemo(() => {\n        if (isFlipped) return { rotateX: 0, rotateY: 0 };\n        return flipDirection === 'horizontal'\n          ? { rotateY: 180, rotateX: 0 }\n          : { rotateX: 180, rotateY: 0 };\n      }, [isFlipped, flipDirection]);\n\n      return (\n        <motion.div\n          ref={ref}\n          className={cn('absolute inset-0 z-10 size-full', className)}\n          initial={false}\n          animate={rotation}\n          transition={TRANSITION_CONFIG}\n          style={{\n            ...TRANSFORM_STYLES,\n            ...props.style,\n          }}\n          {...props}\n        />\n      );\n    },\n  ),\n);\nCardFlipBack.displayName = 'CardFlipBack';\n\nexport { CardFlip, CardFlipFront, CardFlipBack };\n",
      "type": "registry:ui",
      "target": "components/systaliko-ui/card-flip.tsx"
    }
  ],
  "type": "registry:ui"
}