{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "evil-eye",
  "type": "registry:block",
  "title": "Evil eye",
  "description": "Evil eye",
  "files": [
    {
      "path": "components/usages/evileyeusage.tsx",
      "content": "import EvilEye from \"@/registry/open-source/evil-eye\";\n\nexport default function EvilEyeUsage() {\n    return (\n        <div>\n\n            <EvilEye\n                eyeColor=\"#FF6F37\"\n                intensity={1.5}\n                pupilSize={0.6}\n                irisWidth={0.25}\n                glowIntensity={0.35}\n                scale={0.8}\n                noiseScale={1}\n                pupilFollow={1}\n                flameSpeed={1}\n                backgroundColor=\"#060010\"\n            />       </div>\n    )\n}",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/evileyeusage.tsx",
      "content": "import EvilEye from \"@/registry/open-source/evil-eye\";\n\nexport default function EvilEyeUsage() {\n    return (\n        <div>\n\n            <EvilEye\n                eyeColor=\"#FF6F37\"\n                intensity={1.5}\n                pupilSize={0.6}\n                irisWidth={0.25}\n                glowIntensity={0.35}\n                scale={0.8}\n                noiseScale={1}\n                pupilFollow={1}\n                flameSpeed={1}\n                backgroundColor=\"#060010\"\n            />       </div>\n    )\n}",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/evil-eye.tsx",
      "content": "import { Renderer, Program, Mesh, Triangle, Texture } from 'ogl';\nimport { useEffect, useRef } from 'react';\n\ninterface EvilEyeProps {\n    eyeColor?: string;\n    intensity?: number;\n    pupilSize?: number;\n    irisWidth?: number;\n    glowIntensity?: number;\n    scale?: number;\n    noiseScale?: number;\n    pupilFollow?: number;\n    flameSpeed?: number;\n    backgroundColor?: string;\n}\n\nfunction hexToVec3(hex: string): [number, number, number] {\n    const h = hex.replace('#', '');\n    return [\n        parseInt(h.slice(0, 2), 16) / 255,\n        parseInt(h.slice(2, 4), 16) / 255,\n        parseInt(h.slice(4, 6), 16) / 255\n    ];\n}\n\nfunction generateNoiseTexture(size = 256): Uint8Array {\n    const data = new Uint8Array(size * size * 4);\n\n    function hash(x: number, y: number, s: number): number {\n        let n = x * 374761393 + y * 668265263 + s * 1274126177;\n        n = Math.imul(n ^ (n >>> 13), 1274126177);\n        return ((n ^ (n >>> 16)) >>> 0) / 4294967296;\n    }\n\n    function noise(px: number, py: number, freq: number, seed: number): number {\n        const fx = (px / size) * freq;\n        const fy = (py / size) * freq;\n        const ix = Math.floor(fx);\n        const iy = Math.floor(fy);\n        const tx = fx - ix;\n        const ty = fy - iy;\n        const w = freq | 0;\n        const v00 = hash(((ix % w) + w) % w, ((iy % w) + w) % w, seed);\n        const v10 = hash((((ix + 1) % w) + w) % w, ((iy % w) + w) % w, seed);\n        const v01 = hash(((ix % w) + w) % w, (((iy + 1) % w) + w) % w, seed);\n        const v11 = hash((((ix + 1) % w) + w) % w, (((iy + 1) % w) + w) % w, seed);\n        return v00 * (1 - tx) * (1 - ty) + v10 * tx * (1 - ty) + v01 * (1 - tx) * ty + v11 * tx * ty;\n    }\n\n    for (let y = 0; y < size; y++) {\n        for (let x = 0; x < size; x++) {\n            let v = 0;\n            let amp = 0.4;\n            let totalAmp = 0;\n            for (let o = 0; o < 8; o++) {\n                const f = 32 * (1 << o);\n                v += amp * noise(x, y, f, o * 31);\n                totalAmp += amp;\n                amp *= 0.65;\n            }\n            v /= totalAmp;\n            v = (v - 0.5) * 2.2 + 0.5;\n            v = Math.max(0, Math.min(1, v));\n            const val = Math.round(v * 255);\n            const i = (y * size + x) * 4;\n            data[i] = val;\n            data[i + 1] = val;\n            data[i + 2] = val;\n            data[i + 3] = 255;\n        }\n    }\n\n    return data;\n}\n\nconst vertexShader = `\nattribute vec2 uv;\nattribute vec2 position;\nvarying vec2 vUv;\nvoid main() {\n  vUv = uv;\n  gl_Position = vec4(position, 0, 1);\n}\n`;\n\nconst fragmentShader = `\nprecision highp float;\n\nuniform float uTime;\nuniform vec3 uResolution;\nuniform sampler2D uNoiseTexture;\nuniform float uPupilSize;\nuniform float uIrisWidth;\nuniform float uGlowIntensity;\nuniform float uIntensity;\nuniform float uScale;\nuniform float uNoiseScale;\nuniform vec2 uMouse;\nuniform float uPupilFollow;\nuniform float uFlameSpeed;\nuniform vec3 uEyeColor;\nuniform vec3 uBgColor;\n\nvoid main() {\n  vec2 uv = (gl_FragCoord.xy * 2.0 - uResolution.xy) / uResolution.y;\n  uv /= uScale;\n  float ft = uTime * uFlameSpeed;\n\n  float polarRadius = length(uv) * 2.0;\n  float polarAngle = (2.0 * atan(uv.x, uv.y)) / 6.28 * 0.3;\n  vec2 polarUv = vec2(polarRadius, polarAngle);\n\n  vec4 noiseA = texture2D(uNoiseTexture, polarUv * vec2(0.2, 7.0) * uNoiseScale + vec2(-ft * 0.1, 0.0));\n  vec4 noiseB = texture2D(uNoiseTexture, polarUv * vec2(0.3, 4.0) * uNoiseScale + vec2(-ft * 0.2, 0.0));\n  vec4 noiseC = texture2D(uNoiseTexture, polarUv * vec2(0.1, 5.0) * uNoiseScale + vec2(-ft * 0.1, 0.0));\n\n  float distanceMask = 1.0 - length(uv);\n\n  // Inner ring\n  float innerRing = clamp(-1.0 * ((distanceMask - 0.7) / uIrisWidth), 0.0, 1.0);\n  innerRing = (innerRing * distanceMask - 0.2) / 0.28;\n  innerRing += noiseA.r - 0.5;\n  innerRing *= 1.3;\n  innerRing = clamp(innerRing, 0.0, 1.0);\n\n  float outerRing = clamp(-1.0 * ((distanceMask - 0.5) / 0.2), 0.0, 1.0);\n  outerRing = (outerRing * distanceMask - 0.1) / 0.38;\n  outerRing += noiseC.r - 0.5;\n  outerRing *= 1.3;\n  outerRing = clamp(outerRing, 0.0, 1.0);\n\n  innerRing += outerRing;\n\n  // Inner eye\n  float innerEye = distanceMask - 0.1 * 2.0;\n  innerEye *= noiseB.r * 2.0;\n\n  // Pupil with cursor tracking\n  vec2 pupilOffset = uMouse * uPupilFollow * 0.12;\n  vec2 pupilUv = uv - pupilOffset;\n  float pupil = 1.0 - length(pupilUv * vec2(9.0, 2.3));\n  pupil *= uPupilSize;\n  pupil = clamp(pupil, 0.0, 1.0);\n  pupil /= 0.35;\n\n  // Outer eye\n  float outerEyeGlow = 1.0 - length(uv * vec2(0.5, 1.5));\n  outerEyeGlow = clamp(outerEyeGlow + 0.5, 0.0, 1.0);\n  outerEyeGlow += noiseC.r - 0.5;\n  float outerBgGlow = outerEyeGlow;\n  outerEyeGlow = pow(outerEyeGlow, 2.0);\n  outerEyeGlow += distanceMask;\n  outerEyeGlow *= uGlowIntensity;\n  outerEyeGlow = clamp(outerEyeGlow, 0.0, 1.0);\n  outerEyeGlow *= pow(1.0 - distanceMask, 2.0) * 2.5;\n\n  // Outer eye bg glow\n  outerBgGlow += distanceMask;\n  outerBgGlow = pow(outerBgGlow, 0.5);\n  outerBgGlow *= 0.15;\n\n  vec3 color = uEyeColor * uIntensity * clamp(max(innerRing + innerEye, outerEyeGlow + outerBgGlow) - pupil, 0.0, 3.0);\n  color += uBgColor;\n\n  gl_FragColor = vec4(color, 1.0);\n}\n`;\n\nexport default function EvilEye({\n    eyeColor = '#FF6F37',\n    intensity = 1.5,\n    pupilSize = 0.6,\n    irisWidth = 0.25,\n    glowIntensity = 0.35,\n    scale = 0.8,\n    noiseScale = 1.0,\n    pupilFollow = 1.0,\n    flameSpeed = 1.0,\n    backgroundColor = '#000000'\n}: EvilEyeProps) {\n    const containerRef = useRef<HTMLDivElement>(null);\n\n    useEffect(() => {\n        if (!containerRef.current) return;\n        const container = containerRef.current;\n        const renderer = new Renderer({ alpha: true, premultipliedAlpha: false });\n        const gl = renderer.gl;\n        gl.clearColor(0, 0, 0, 0);\n\n        const noiseData = generateNoiseTexture(256);\n        const noiseTexture = new Texture(gl, {\n            image: noiseData,\n            width: 256,\n            height: 256,\n            generateMipmaps: false,\n            flipY: false,\n        });\n        noiseTexture.minFilter = gl.LINEAR;\n        noiseTexture.magFilter = gl.LINEAR;\n        noiseTexture.wrapS = gl.REPEAT;\n        noiseTexture.wrapT = gl.REPEAT;\n\n        const mouse = { x: 0, y: 0, tx: 0, ty: 0 };\n\n        function onMouseMove(e: MouseEvent) {\n            const rect = container.getBoundingClientRect();\n            mouse.tx = ((e.clientX - rect.left) / rect.width) * 2 - 1;\n            mouse.ty = -(((e.clientY - rect.top) / rect.height) * 2 - 1);\n        }\n\n        function onMouseLeave() {\n            mouse.tx = 0;\n            mouse.ty = 0;\n        }\n\n        container.addEventListener('mousemove', onMouseMove);\n        container.addEventListener('mouseleave', onMouseLeave);\n\n        let program: Program;\n\n        function resize() {\n            renderer.setSize(container.offsetWidth, container.offsetHeight);\n            if (program) {\n                program.uniforms.uResolution.value = [gl.canvas.width, gl.canvas.height, gl.canvas.width / gl.canvas.height];\n            }\n        }\n        window.addEventListener('resize', resize);\n        resize();\n\n        const geometry = new Triangle(gl);\n        program = new Program(gl, {\n            vertex: vertexShader,\n            fragment: fragmentShader,\n            uniforms: {\n                uTime: { value: 0 },\n                uResolution: { value: [gl.canvas.width, gl.canvas.height, gl.canvas.width / gl.canvas.height] },\n                uNoiseTexture: { value: noiseTexture },\n                uPupilSize: { value: pupilSize },\n                uIrisWidth: { value: irisWidth },\n                uGlowIntensity: { value: glowIntensity },\n                uIntensity: { value: intensity },\n                uScale: { value: scale },\n                uNoiseScale: { value: noiseScale },\n                uMouse: { value: [0, 0] },\n                uPupilFollow: { value: pupilFollow },\n                uFlameSpeed: { value: flameSpeed },\n                uEyeColor: { value: hexToVec3(eyeColor) },\n                uBgColor: { value: hexToVec3(backgroundColor) }\n            }\n        });\n\n        const mesh = new Mesh(gl, { geometry, program });\n        container.appendChild(gl.canvas);\n\n        let animationFrameId: number;\n\n        function update(time: number) {\n            animationFrameId = requestAnimationFrame(update);\n            mouse.x += (mouse.tx - mouse.x) * 0.05;\n            mouse.y += (mouse.ty - mouse.y) * 0.05;\n            program.uniforms.uMouse.value = [mouse.x, mouse.y];\n            program.uniforms.uTime.value = time * 0.001;\n            renderer.render({ scene: mesh });\n        }\n        animationFrameId = requestAnimationFrame(update);\n\n        return () => {\n            cancelAnimationFrame(animationFrameId);\n            window.removeEventListener('resize', resize);\n            container.removeEventListener('mousemove', onMouseMove);\n            container.removeEventListener('mouseleave', onMouseLeave);\n            container.removeChild(gl.canvas);\n            gl.getExtension('WEBGL_lose_context')?.loseContext();\n        };\n    }, [eyeColor, intensity, pupilSize, irisWidth, glowIntensity, scale, noiseScale, pupilFollow, flameSpeed, backgroundColor]);\n\n    return <div ref={containerRef} className=\"w-full h-full\" />;\n}\n",
      "type": "registry:ui"
    }
  ]
}