{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ghost-svg",
  "type": "registry:block",
  "title": "Ghost svg",
  "description": "Ghost svg",
  "files": [
    {
      "path": "components/usages/ghostsvgusage.tsx",
      "content": "import GhostSVG from \"@/registry/open-source/ghost-svg\";\n\nexport default function Usage() {\n\treturn (\n\t\t<div className=\"min-h-screen bg-[#101010] flex items-center justify-center p-8\">\n\t\t\t<div className=\"max-w-md\">\n\t\t\t\t<GhostSVG />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/ghostsvgusage.tsx",
      "content": "import GhostSVG from \"@/registry/open-source/ghost-svg\";\n\nexport default function Usage() {\n\treturn (\n\t\t<div className=\"min-h-screen bg-[#101010] flex items-center justify-center p-8\">\n\t\t\t<div className=\"max-w-md\">\n\t\t\t\t<GhostSVG />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/ghost-svg.tsx",
      "content": "\"use client\";\r\n\r\nimport { useEffect, useMemo, useRef, useState } from \"react\";\r\n\r\nimport { Canvas, extend, useFrame } from \"@react-three/fiber\";\r\nimport { motion } from \"framer-motion\";\r\nimport { Color, MathUtils, Vector3 } from \"three\";\r\nimport * as THREE from \"three\";\r\n\r\nextend({ IcosahedronGeometry: THREE.IcosahedronGeometry });\r\n\r\n// Credits:\r\n// https://www.ui-layouts.com/components/mesh-gradients\r\n// https://v0.app/chat/shader-svg-TcgLzaGaXRC\r\n\r\nconst vertexShader = `\r\nuniform float u_intensity;\r\nuniform float u_time;\r\n\r\nvarying vec2 vUv;\r\nvarying float vDisplacement;\r\n\r\n// Classic Perlin 3D Noise functions\r\nvec4 permute(vec4 x) {\r\n    return mod(((x*34.0)+1.0)*x, 289.0);\r\n}\r\n\r\nvec4 taylorInvSqrt(vec4 r) {\r\n    return 1.79284291400159 - 0.85373472095314 * r;\r\n}\r\n\r\nvec3 fade(vec3 t) {\r\n    return t*t*t*(t*(t*6.0-15.0)+10.0);\r\n}\r\n\r\nfloat cnoise(vec3 P) {\r\n    vec3 Pi0 = floor(P);\r\n    vec3 Pi1 = Pi0 + vec3(1.0);\r\n    Pi0 = mod(Pi0, 289.0);\r\n    Pi1 = mod(Pi1, 289.0);\r\n    vec3 Pf0 = fract(P);\r\n    vec3 Pf1 = Pf0 - vec3(1.0);\r\n    vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);\r\n    vec4 iy = vec4(Pi0.yy, Pi1.yy);\r\n    vec4 iz0 = Pi0.zzzz;\r\n    vec4 iz1 = Pi1.zzzz;\r\n\r\n    vec4 ixy = permute(permute(ix) + iy);\r\n    vec4 ixy0 = permute(ixy + iz0);\r\n    vec4 ixy1 = permute(ixy + iz1);\r\n\r\n    vec4 gx0 = ixy0 / 7.0;\r\n    vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;\r\n    gx0 = fract(gx0);\r\n    vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);\r\n    vec4 sz0 = step(gz0, vec4(0.0));\r\n    gx0 -= sz0 * (step(0.0, gx0) - 0.5);\r\n    gy0 -= sz0 * (step(0.0, gy0) - 0.5);\r\n\r\n    vec4 gx1 = ixy1 / 7.0;\r\n    vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;\r\n    gx1 = fract(gx1);\r\n    vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);\r\n    vec4 sz1 = step(gz1, vec4(0.0));\r\n    gx1 -= sz1 * (step(0.0, gx1) - 0.5);\r\n    gy1 -= sz1 * (step(0.0, gy1) - 0.5);\r\n\r\n    vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);\r\n    vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);\r\n    vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);\r\n    vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);\r\n    vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);\r\n    vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);\r\n    vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);\r\n    vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);\r\n\r\n    vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));\r\n    g000 *= norm0.x;\r\n    g010 *= norm0.y;\r\n    g100 *= norm0.z;\r\n    g110 *= norm0.w;\r\n    vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));\r\n    g001 *= norm1.x;\r\n    g011 *= norm1.y;\r\n    g101 *= norm1.z;\r\n    g111 *= norm1.w;\r\n\r\n    float n000 = dot(g000, Pf0);\r\n    float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));\r\n    float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));\r\n    float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));\r\n    float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));\r\n    float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));\r\n    float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));\r\n    float n111 = dot(g111, Pf1);\r\n\r\n    vec3 fade_xyz = fade(Pf0);\r\n    vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);\r\n    vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);\r\n    float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); \r\n    return 2.2 * n_xyz;\r\n}\r\n\r\nvoid main() {\r\n    vUv = uv;\r\n\r\n    vDisplacement = cnoise(position + vec3(2.0 * u_time));\r\n  \r\n    vec3 newPosition = position + normal * (u_intensity * vDisplacement);\r\n  \r\n    vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);\r\n    vec4 viewPosition = viewMatrix * modelPosition;\r\n    vec4 projectedPosition = projectionMatrix * viewPosition;\r\n  \r\n    gl_Position = projectedPosition;\r\n}\r\n`;\r\n\r\nconst fragmentShader = `\r\nuniform float u_intensity;\r\nuniform float u_time;\r\nuniform vec3 u_color;\r\n\r\nvarying vec2 vUv;\r\nvarying float vDisplacement;\r\n\r\n// Function to generate random noise\r\nfloat random(vec2 st) {\r\n  return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);\r\n}\r\n\r\nvoid main() {\r\n  float distort = 2.0 * vDisplacement * u_intensity * sin(vUv.y * 10.0 + u_time);\r\n  vec3 color = mix(u_color, vec3(1.0, 1.0, 1.0), distort);\r\n\r\n  // Add screen-space random noise\r\n  float noise = random(gl_FragCoord.xy * u_time * 0.05) * 0.05; // tweak strength\r\n  color += noise;\r\n\r\n  gl_FragColor = vec4(color, 1.0);\r\n}\r\n`;\r\n\r\nconst GhostSVGElement = () => {\r\n\tconst mesh = useRef<THREE.Mesh>(null);\r\n\tconst hover = useRef(false);\r\n\r\n\tconst uniforms = useMemo(\r\n\t\t() => ({\r\n\t\t\tu_time: { value: 0 },\r\n\t\t\tu_intensity: { value: 0.3 },\r\n\t\t\tu_color: { value: new Color(\"#ffd717\") },\r\n\t\t}),\r\n\t\t[]\r\n\t);\r\n\r\n\tconst targetPosition = useRef(new Vector3(0, 0, 0));\r\n\tconst currentPosition = useRef(new Vector3(0, 0, 0));\r\n\r\n\tuseFrame((state) => {\r\n\t\tconst { clock, mouse } = state;\r\n\r\n\t\tif (mesh.current) {\r\n\t\t\tconst material = mesh.current.material as THREE.ShaderMaterial;\r\n\r\n\t\t\tmaterial.uniforms.u_time.value = 0.4 * clock.getElapsedTime();\r\n\r\n\t\t\tmaterial.uniforms.u_intensity.value = MathUtils.lerp(\r\n\t\t\t\tmaterial.uniforms.u_intensity.value,\r\n\t\t\t\thover.current ? 0.7 : 1,\r\n\t\t\t\t0.02\r\n\t\t\t);\r\n\r\n\t\t\t// Update target position based on mouse\r\n\t\t\ttargetPosition.current.set(mouse.x * 0.3, mouse.y * 0.3, 0);\r\n\t\t\tcurrentPosition.current.lerp(targetPosition.current, 0.1);\r\n\r\n\t\t\tmesh.current.position.copy(currentPosition.current);\r\n\t\t}\r\n\t});\r\n\r\n\treturn (\r\n\t\t<mesh\r\n\t\t\tref={mesh}\r\n\t\t\tscale={1.5}\r\n\t\t\tposition={[0, 0, 0]}\r\n\t\t\tonPointerOver={() => (hover.current = true)}\r\n\t\t\tonPointerOut={() => (hover.current = false)}\r\n\t\t>\r\n\t\t\t<icosahedronGeometry args={[2, 20]} />\r\n\t\t\t<shaderMaterial\r\n\t\t\t\tvertexShader={vertexShader}\r\n\t\t\t\tfragmentShader={fragmentShader}\r\n\t\t\t\tuniforms={uniforms}\r\n\t\t\t/>\r\n\t\t</mesh>\r\n\t);\r\n};\r\n\r\nexport default function GhostSVG() {\r\n\tconst [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });\r\n\tconst [eyeOffset, setEyeOffset] = useState({ x: 0, y: 0 });\r\n\r\n\tuseEffect(() => {\r\n\t\tconst handleMouseMove = (e: MouseEvent) => {\r\n\t\t\tsetMousePosition({ x: e.clientX, y: e.clientY });\r\n\t\t};\r\n\r\n\t\twindow.addEventListener(\"mousemove\", handleMouseMove);\r\n\t\treturn () => window.removeEventListener(\"mousemove\", handleMouseMove);\r\n\t}, []);\r\n\r\n\tuseEffect(() => {\r\n\t\tconst rect = document.querySelector(\"svg\")?.getBoundingClientRect();\r\n\t\tif (rect) {\r\n\t\t\tconst centerX = rect.left + rect.width / 2;\r\n\t\t\tconst centerY = rect.top + rect.height / 2;\r\n\r\n\t\t\tconst deltaX = (mousePosition.x - centerX) * 0.08;\r\n\t\t\tconst deltaY = (mousePosition.y - centerY) * 0.08;\r\n\r\n\t\t\tconst maxOffset = 8;\r\n\t\t\tsetEyeOffset({\r\n\t\t\t\tx: Math.max(-maxOffset, Math.min(maxOffset, deltaX)),\r\n\t\t\t\ty: Math.max(-maxOffset, Math.min(maxOffset, deltaY)),\r\n\t\t\t});\r\n\t\t}\r\n\t}, [mousePosition]);\r\n\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tclassName=\"relative w-full max-w-sm mx-auto p-8 rounded-lg\"\r\n\t\t\tanimate={{\r\n\t\t\t\ty: [0, -8, 0],\r\n\t\t\t\tscaleY: [1, 1.08, 1],\r\n\t\t\t}}\r\n\t\t\ttransition={{\r\n\t\t\t\tduration: 2.8,\r\n\t\t\t\trepeat: Number.POSITIVE_INFINITY,\r\n\t\t\t\tease: \"easeInOut\",\r\n\t\t\t}}\r\n\t\t\tstyle={{ transformOrigin: \"top center\" }}\r\n\t\t>\r\n\t\t\t<svg\r\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\r\n\t\t\t\twidth=\"231\"\r\n\t\t\t\theight=\"289\"\r\n\t\t\t\tviewBox=\"0 0 231 289\"\r\n\t\t\t\tclassName=\"w-full h-auto\"\r\n\t\t\t>\r\n\t\t\t\t<defs>\r\n\t\t\t\t\t<clipPath id=\"shapeClip\">\r\n\t\t\t\t\t\t<path d=\"M230.809 115.385V249.411C230.809 269.923 214.985 287.282 194.495 288.411C184.544 288.949 175.364 285.718 168.26 280C159.746 273.154 147.769 273.461 139.178 280.23C132.638 285.384 124.381 288.462 115.379 288.462C106.377 288.462 98.1451 285.384 91.6055 280.23C82.912 273.385 70.9353 273.385 62.2415 280.23C55.7532 285.334 47.598 288.411 38.7246 288.462C17.4132 288.615 0 270.667 0 249.359V115.385C0 51.6667 51.6756 0 115.404 0C179.134 0 230.809 51.6667 230.809 115.385Z\" />\r\n\t\t\t\t\t</clipPath>\r\n\t\t\t\t</defs>\r\n\r\n\t\t\t\t<foreignObject width=\"231\" height=\"289\" clipPath=\"url(#shapeClip)\">\r\n\t\t\t\t\t<div className=\"w-full h-full\">\r\n\t\t\t\t\t\t<Canvas>\r\n\t\t\t\t\t\t\t<GhostSVGElement />\r\n\t\t\t\t\t\t</Canvas>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</foreignObject>\r\n\r\n\t\t\t\t<motion.ellipse\r\n\t\t\t\t\trx=\"20\"\r\n\t\t\t\t\try=\"30\"\r\n\t\t\t\t\tfill=\"currentColor\"\r\n\t\t\t\t\tclassName=\"animate-blink\"\r\n\t\t\t\t\tanimate={{\r\n\t\t\t\t\t\tcx: 80 + eyeOffset.x,\r\n\t\t\t\t\t\tcy: 120 + eyeOffset.y,\r\n\t\t\t\t\t}}\r\n\t\t\t\t\ttransition={{ type: \"spring\", stiffness: 150, damping: 15 }}\r\n\t\t\t\t/>\r\n\t\t\t\t<motion.ellipse\r\n\t\t\t\t\trx=\"20\"\r\n\t\t\t\t\try=\"30\"\r\n\t\t\t\t\tfill=\"currentColor\"\r\n\t\t\t\t\tclassName=\"animate-blink\"\r\n\t\t\t\t\tanimate={{\r\n\t\t\t\t\t\tcx: 150 + eyeOffset.x,\r\n\t\t\t\t\t\tcy: 120 + eyeOffset.y,\r\n\t\t\t\t\t}}\r\n\t\t\t\t\ttransition={{ type: \"spring\", stiffness: 150, damping: 15 }}\r\n\t\t\t\t/>\r\n\t\t\t</svg>\r\n\r\n\t\t\t<style jsx>{`\r\n\t\t\t\t.animate-blink {\r\n\t\t\t\t\tanimation: blink 3s infinite ease-in-out;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@keyframes blink {\r\n\t\t\t\t\t0%,\r\n\t\t\t\t\t90%,\r\n\t\t\t\t\t100% {\r\n\t\t\t\t\t\try: 30;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t95% {\r\n\t\t\t\t\t\try: 3;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t`}</style>\r\n\t\t</motion.div>\r\n\t);\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}