{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "EvilEye-TS-CSS",
	"title": "EvilEye",
	"description": "Procedural evil eye shader with animated iris, slit pupil, and fiery outer glow.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "EvilEye.css",
			"target": "@components/EvilEye.css",
			"content": ".evil-eye-container {\n  width: 100%;\n  height: 100%;\n}\n"
		},
		{
			"type": "registry:component",
			"path": "EvilEye.tsx",
			"content": "import { Renderer, Program, Mesh, Triangle, Texture } from 'ogl';\nimport { useEffect, useRef } from 'react';\nimport './EvilEye.css';\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  lightMode?: boolean;\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;\nuniform bool uLightMode;\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 eyeEnergy = uEyeColor * uIntensity * clamp(max(innerRing + innerEye, outerEyeGlow + outerBgGlow) - pupil, 0.0, 3.0);\n  vec3 color;\n  if (uLightMode) {\n    vec3 mapped = vec3(1.0) - exp(-max(eyeEnergy, vec3(0.0)) * 1.3);\n    float energy = clamp(max(mapped.r, max(mapped.g, mapped.b)), 0.0, 1.0);\n    vec3 hue = mapped / max(energy, 0.0001);\n    hue = pow(clamp(hue, 0.0, 1.0), vec3(1.2));\n    color = mix(uBgColor, hue, smoothstep(0.02, 0.82, energy) * 0.96);\n  } else {\n    color = eyeEnergy + uBgColor;\n  }\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  lightMode = false\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        uLightMode: { value: lightMode }\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, lightMode]);\n\n  return <div ref={containerRef} className=\"evil-eye-container\" />;\n}\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"ogl@^1.0.11"
	]
}