{
  "$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": [
    "@unlumen-ui/lib-get-strict-context",
    "@unlumen-ui/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/unlumen-ui/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/unlumen-ui/primitives/buttons/flip.tsx"
    }
  ],
  "type": "registry:ui"
}