{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "airplane-icon",
  "dependencies": ["motion"],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "icons/airplane-icon.tsx",
      "content": "import { forwardRef, useImperativeHandle, useCallback } from \"react\";\nimport type { AnimatedIconHandle, AnimatedIconProps } from \"./types\";\nimport { motion, useAnimate } from \"motion/react\";\n\ntype CustomAnimation = {\n  airPlaneDuration: number;\n  windDuration: number;\n  exitDuration: number;\n};\n\nconst AirplaneIcon = forwardRef<\n  AnimatedIconHandle,\n  AnimatedIconProps & CustomAnimation\n>(\n  (\n    {\n      size = 24,\n      color = \"currentColor\",\n      strokeWidth = 2,\n      className = \"\",\n      airPlaneDuration = 0.3,\n      windDuration = 0.8,\n      exitDuration = 0.3,\n    },\n    ref,\n  ) => {\n    const [scope, animate] = useAnimate();\n\n    const start = useCallback(async () => {\n      // Subtle vibration for the plane\n      animate(\n        \".airplane\",\n        { x: [0, 0.5, 0], y: [0, -0.5, 0] },\n        { duration: airPlaneDuration },\n      );\n\n      // Streak 1: Upper Wing (Top-right streak)\n      animate(\n        \".wind1\",\n        {\n          x: -12,\n          y: 24,\n          opacity: 1,\n        },\n        { duration: windDuration, ease: \"easeOut\" },\n      );\n\n      // Streak 2: Lower Wing (Middle-left streak)\n      animate(\n        \".wind2\",\n        {\n          x: 0,\n          y: 26,\n          opacity: 1,\n        },\n        { duration: windDuration, ease: \"easeOut\", delay: 0.2 },\n      );\n    }, [animate, airPlaneDuration, windDuration]);\n\n    const stop = useCallback(async () => {\n      animate(\".airplane\", { x: 0, y: 0 }, { duration: exitDuration });\n      animate(\n        \".wind1\",\n        { opacity: 0, x: 12, y: -4 },\n        { duration: exitDuration },\n      );\n      animate(\n        \".wind2\",\n        { opacity: 0, x: 26, y: 8 },\n        { duration: exitDuration },\n      );\n    }, [animate, exitDuration]);\n\n    useImperativeHandle(\n      ref,\n      () => ({\n        startAnimation: start,\n        stopAnimation: stop,\n      }),\n      [start, stop],\n    );\n\n    return (\n      <motion.svg\n        ref={scope}\n        xmlns=\"http://www.w3.org/2000/svg\"\n        width={size}\n        height={size}\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke={color}\n        strokeWidth={strokeWidth}\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        className={`cursor-pointer ${className}`}\n        onHoverStart={start}\n        onHoverEnd={stop}\n      >\n        <motion.path\n          className=\"airplane\"\n          d=\"M13.617 1.53c.926-.747 1.964-.793 3.097-.777.587.009.88.013 1.115.104.373.145.67.442.815.815.09.235.095.528.104 1.115.016 1.133-.03 2.17-.778 3.097-.63.78-1.714 1.188-2.235 2.05-.398.656-.213 1.337-.042 2.038l1.28 5.245c.255 1.046.06 1.715-.67 2.446-.39.39-.713.37-1.028-.133l-3.862-6.154-1.845 1.466c-.67.532-1.003.798-1.18 1.172-.41.876-.15 2.192-.136 3.142.008.525-.446 1.56-1.088 1.594-.396.022-.531-.452-.66-.743l-1.232-2.802c-.294-.67-.306-.682-.976-.976l-2.802-1.233c-.29-.128-.765-.263-.743-.66.035-.641 1.07-1.095 1.594-1.087.95.013 2.266.274 3.142-.137.374-.176.64-.51 1.172-1.18l1.466-1.844L1.97 4.226c-.503-.316-.522-.64-.133-1.028.73-.73 1.4-.925 2.446-.67l5.245 1.28c.7.17 1.382.356 2.039-.042.86-.52 1.269-1.604 2.049-2.235\"\n        />\n\n        <motion.path\n          className=\"wind1\"\n          initial={{ opacity: 0, x: 10, y: -6 }}\n          d=\"m.5 3.5 3-3\"\n        ></motion.path>\n        <motion.path\n          className=\"wind2\"\n          initial={{ opacity: 0, x: 26, y: 8 }}\n          d=\"m.5 3.5 3-3\"\n        ></motion.path>\n      </motion.svg>\n    );\n  },\n);\n\nAirplaneIcon.displayName = \"AirplaneIcon\";\nexport default AirplaneIcon;\n",
      "type": "registry:ui"
    },
    {
      "path": "icons/types.ts",
      "content": "import type { SVGProps } from \"react\";\n\n/** Standard stroke width for 24×24 outline icons */\nexport const DEFAULT_STROKE_WIDTH = 2;\n\n/** Scale stroke to match DEFAULT_STROKE_WIDTH on non-24 viewBoxes */\nexport function scaledStrokeWidth(\n  strokeWidth: number,\n  viewBoxSize: number,\n): number {\n  return strokeWidth * (viewBoxSize / 24);\n}\n\nexport type IconEasing =\n  | \"linear\"\n  | \"easeIn\"\n  | \"easeOut\"\n  | \"easeInOut\"\n  | \"circIn\"\n  | \"circOut\"\n  | \"circInOut\"\n  | \"backIn\"\n  | \"backOut\"\n  | \"backInOut\"\n  | \"anticipate\";\n\nexport interface AnimatedIconProps extends Omit<\n  SVGProps<SVGSVGElement>,\n  | \"ref\"\n  | \"onAnimationStart\"\n  | \"onAnimationEnd\"\n  | \"onAnimationIteration\"\n  | \"onDrag\"\n  | \"onDragEnd\"\n  | \"onDragEnter\"\n  | \"onDragExit\"\n  | \"onDragLeave\"\n  | \"onDragOver\"\n  | \"onDragStart\"\n  | \"onDrop\"\n  | \"values\"\n> {\n  /** Icon size in pixels or CSS string */\n  size?: number | string;\n  /** Icon color (defaults to currentColor) */\n  color?: string;\n  /** SVG stroke width */\n  strokeWidth?: number;\n  /** Additional CSS classes */\n  className?: string;\n}\n\nexport interface AnimatedIconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
