{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitives-buttons-flip",
  "title": "Flip Button",
  "description": "A button that flips between two states on hover.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "@odysseyui/lib-get-strict-context",
    "@odysseyui/primitives-animate-slot"
  ],
  "files": [
    {
      "path": "registry/primitives/buttons/flip/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { motion, type HTMLMotionProps, type Variant } from 'motion/react';\n\nimport { getStrictContext } from '@/lib/get-strict-context';\nimport { Slot, type WithAsChild } from '@/components/odyssey/primitives/animate/slot';\n\nconst buildVariant = ({\n  opacity,\n  rotation,\n  offset,\n  isVertical,\n  rotateAxis,\n}: {\n  opacity: number;\n  rotation: number;\n  offset: string | null;\n  isVertical: boolean;\n  rotateAxis: string;\n}): Variant => ({\n  opacity,\n  [rotateAxis]: rotation,\n  ...(isVertical && offset !== null ? { y: offset } : {}),\n  ...(!isVertical && offset !== null ? { x: offset } : {}),\n});\n\ntype FlipDirection = 'top' | 'bottom' | 'left' | 'right';\n\ntype FlipButtonContextType = {\n  from: FlipDirection;\n  isVertical: boolean;\n  rotateAxis: string;\n};\n\nconst [FlipButtonProvider, useFlipButton] =\n  getStrictContext<FlipButtonContextType>('FlipButtonContext');\n\ntype FlipButtonProps = WithAsChild<\n  HTMLMotionProps<'button'> & {\n    from?: FlipDirection;\n    tapScale?: number;\n  }\n>;\n\nfunction FlipButton({\n  from = 'top',\n  tapScale = 0.95,\n  asChild = false,\n  style,\n  ...props\n}: FlipButtonProps) {\n  const isVertical = from === 'top' || from === 'bottom';\n  const rotateAxis = isVertical ? 'rotateX' : 'rotateY';\n\n  const Component = asChild ? Slot : motion.button;\n\n  return (\n    <FlipButtonProvider value={{ from, isVertical, rotateAxis }}>\n      <Component\n        data-slot=\"flip-button\"\n        initial=\"initial\"\n        whileHover=\"hover\"\n        whileTap={{ scale: tapScale }}\n        style={{\n          display: 'inline-grid',\n          placeItems: 'center',\n          perspective: '1000px',\n          ...style,\n        }}\n        {...props}\n      />\n    </FlipButtonProvider>\n  );\n}\n\ntype FlipButtonFaceProps = WithAsChild<HTMLMotionProps<'span'>>;\n\nfunction FlipButtonFront({\n  transition = { type: 'spring', stiffness: 280, damping: 20 },\n  asChild = false,\n  style,\n  ...props\n}: FlipButtonFaceProps) {\n  const { from, isVertical, rotateAxis } = useFlipButton();\n\n  const frontOffset = from === 'top' || from === 'left' ? '50%' : '-50%';\n\n  const frontVariants = {\n    initial: buildVariant({\n      opacity: 1,\n      rotation: 0,\n      offset: '0%',\n      isVertical,\n      rotateAxis,\n    }),\n    hover: buildVariant({\n      opacity: 0,\n      rotation: 90,\n      offset: frontOffset,\n      isVertical,\n      rotateAxis,\n    }),\n  };\n\n  const Component = asChild ? Slot : motion.span;\n\n  return (\n    <Component\n      data-slot=\"flip-button-front\"\n      variants={frontVariants}\n      transition={transition}\n      style={{\n        gridArea: '1 / 1',\n        display: 'inline-flex',\n        alignItems: 'center',\n        justifyContent: 'center',\n        ...style,\n      }}\n      {...props}\n    />\n  );\n}\n\nfunction FlipButtonBack({\n  transition = { type: 'spring', stiffness: 280, damping: 20 },\n  asChild = false,\n  style,\n  ...props\n}: FlipButtonFaceProps) {\n  const { from, isVertical, rotateAxis } = useFlipButton();\n\n  const backOffset = from === 'top' || from === 'left' ? '-50%' : '50%';\n\n  const backVariants = {\n    initial: buildVariant({\n      opacity: 0,\n      rotation: 90,\n      offset: backOffset,\n      isVertical,\n      rotateAxis,\n    }),\n    hover: buildVariant({\n      opacity: 1,\n      rotation: 0,\n      offset: '0%',\n      isVertical,\n      rotateAxis,\n    }),\n  };\n\n  const Component = asChild ? Slot : motion.span;\n\n  return (\n    <Component\n      data-slot=\"flip-button-back\"\n      variants={backVariants}\n      transition={transition}\n      style={{\n        gridArea: '1 / 1',\n        display: 'inline-flex',\n        alignItems: 'center',\n        justifyContent: 'center',\n        ...style,\n      }}\n      {...props}\n    />\n  );\n}\n\nexport {\n  FlipButton,\n  FlipButtonFront,\n  FlipButtonBack,\n  useFlipButton,\n  type FlipButtonProps,\n  type FlipButtonFaceProps as FlipButtonFrontProps,\n  type FlipButtonFaceProps as FlipButtonBackProps,\n  type FlipDirection,\n  type FlipButtonContextType,\n};\n",
      "type": "registry:ui",
      "target": "components/odysseyui/primitives/buttons/flip.tsx"
    }
  ],
  "type": "registry:ui"
}