{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "SoftAurora-JS-CSS",
	"title": "SoftAurora",
	"description": "Soft aurora borealis shader with 3D Perlin noise and cosine gradient palettes.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "SoftAurora.css",
			"target": "@components/SoftAurora.css",
			"content": ".soft-aurora-container {\n  width: 100%;\n  height: 100%;\n}\n"
		},
		{
			"type": "registry:component",
			"path": "SoftAurora.jsx",
			"content": "import { Renderer, Program, Mesh, Triangle } from 'ogl';\nimport { useEffect, useRef } from 'react';\n\nimport './SoftAurora.css';\n\nfunction hexToVec3(hex) {\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\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 float uSpeed;\nuniform float uScale;\nuniform float uBrightness;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform float uNoiseFreq;\nuniform float uNoiseAmp;\nuniform float uBandHeight;\nuniform float uBandSpread;\nuniform float uOctaveDecay;\nuniform float uLayerOffset;\nuniform float uColorSpeed;\nuniform vec2 uMouse;\nuniform float uMouseInfluence;\nuniform bool uEnableMouse;\nuniform float uLightMode;\n\n#define TAU 6.28318\n\nvec3 gradientHash(vec3 p) {\n  p = vec3(\n    dot(p, vec3(127.1, 311.7, 234.6)),\n    dot(p, vec3(269.5, 183.3, 198.3)),\n    dot(p, vec3(169.5, 283.3, 156.9))\n  );\n  vec3 h = fract(sin(p) * 43758.5453123);\n  float phi = acos(2.0 * h.x - 1.0);\n  float theta = TAU * h.y;\n  return vec3(cos(theta) * sin(phi), sin(theta) * cos(phi), cos(phi));\n}\n\nfloat quinticSmooth(float t) {\n  float t2 = t * t;\n  float t3 = t * t2;\n  return 6.0 * t3 * t2 - 15.0 * t2 * t2 + 10.0 * t3;\n}\n\nvec3 cosineGradient(float t, vec3 a, vec3 b, vec3 c, vec3 d) {\n  return a + b * cos(TAU * (c * t + d));\n}\n\nfloat perlin3D(float amplitude, float frequency, float px, float py, float pz) {\n  float x = px * frequency;\n  float y = py * frequency;\n\n  float fx = floor(x); float fy = floor(y); float fz = floor(pz);\n  float cx = ceil(x);  float cy = ceil(y);  float cz = ceil(pz);\n\n  vec3 g000 = gradientHash(vec3(fx, fy, fz));\n  vec3 g100 = gradientHash(vec3(cx, fy, fz));\n  vec3 g010 = gradientHash(vec3(fx, cy, fz));\n  vec3 g110 = gradientHash(vec3(cx, cy, fz));\n  vec3 g001 = gradientHash(vec3(fx, fy, cz));\n  vec3 g101 = gradientHash(vec3(cx, fy, cz));\n  vec3 g011 = gradientHash(vec3(fx, cy, cz));\n  vec3 g111 = gradientHash(vec3(cx, cy, cz));\n\n  float d000 = dot(g000, vec3(x - fx, y - fy, pz - fz));\n  float d100 = dot(g100, vec3(x - cx, y - fy, pz - fz));\n  float d010 = dot(g010, vec3(x - fx, y - cy, pz - fz));\n  float d110 = dot(g110, vec3(x - cx, y - cy, pz - fz));\n  float d001 = dot(g001, vec3(x - fx, y - fy, pz - cz));\n  float d101 = dot(g101, vec3(x - cx, y - fy, pz - cz));\n  float d011 = dot(g011, vec3(x - fx, y - cy, pz - cz));\n  float d111 = dot(g111, vec3(x - cx, y - cy, pz - cz));\n\n  float sx = quinticSmooth(x - fx);\n  float sy = quinticSmooth(y - fy);\n  float sz = quinticSmooth(pz - fz);\n\n  float lx00 = mix(d000, d100, sx);\n  float lx10 = mix(d010, d110, sx);\n  float lx01 = mix(d001, d101, sx);\n  float lx11 = mix(d011, d111, sx);\n\n  float ly0 = mix(lx00, lx10, sy);\n  float ly1 = mix(lx01, lx11, sy);\n\n  return amplitude * mix(ly0, ly1, sz);\n}\n\nfloat auroraGlow(float t, vec2 shift) {\n  vec2 uv = gl_FragCoord.xy / uResolution.y;\n  uv += shift;\n\n  float noiseVal = 0.0;\n  float freq = uNoiseFreq;\n  float amp = uNoiseAmp;\n  vec2 samplePos = uv * uScale;\n\n  for (float i = 0.0; i < 3.0; i += 1.0) {\n    noiseVal += perlin3D(amp, freq, samplePos.x, samplePos.y, t);\n    amp *= uOctaveDecay;\n    freq *= 2.0;\n  }\n\n  float yBand = uv.y * 10.0 - uBandHeight * 10.0;\n  return 0.3 * max(exp(uBandSpread * (1.0 - 1.1 * abs(noiseVal + yBand))), 0.0);\n}\n\nvoid main() {\n  vec2 uv = gl_FragCoord.xy / uResolution.xy;\n  float t = uSpeed * 0.4 * uTime;\n\n  vec2 shift = vec2(0.0);\n  if (uEnableMouse) {\n    shift = (uMouse - 0.5) * uMouseInfluence;\n  }\n\n  float glow1 = auroraGlow(t, shift);\n  float glow2 = auroraGlow(t + uLayerOffset, shift);\n  vec3 gradient1 = cosineGradient(uv.x + uTime * uSpeed * 0.2 * uColorSpeed, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.3, 0.20, 0.20));\n  vec3 gradient2 = cosineGradient(uv.x + uTime * uSpeed * 0.1 * uColorSpeed, vec3(0.5), vec3(0.5), vec3(2.0, 1.0, 0.0), vec3(0.5, 0.20, 0.25));\n\n  vec3 col = 0.99 * glow1 * gradient1 * uColor1;\n  col += 0.99 * glow2 * gradient2 * uColor2;\n\n  col *= uBrightness;\n  float alpha = clamp(length(col), 0.0, 1.0);\n  if (uLightMode > 0.5) {\n    float phase1 = dot(gradient1, vec3(0.299, 0.587, 0.114));\n    float phase2 = dot(gradient2, vec3(0.299, 0.587, 0.114));\n    float weight1 = pow(max(glow1 * (0.62 + 0.38 * phase1), 0.0), 1.35);\n    float weight2 = pow(max(glow2 * (0.62 + 0.38 * phase2), 0.0), 1.35);\n    float weightSum = max(weight1 + weight2, 0.0001);\n\n    vec3 chroma = (weight1 * uColor1 + weight2 * uColor2) / weightSum;\n    float neutral = min(chroma.r, min(chroma.g, chroma.b));\n    chroma = max(chroma - vec3(neutral * 0.78), vec3(0.0));\n    float peak = max(chroma.r, max(chroma.g, chroma.b));\n    chroma = pow(clamp(chroma / max(peak, 0.0001), 0.0, 1.0), vec3(1.08));\n\n    float ink = clamp((weight1 + weight2) * uBrightness * 1.55, 0.0, 0.82);\n    gl_FragColor = vec4(mix(vec3(1.0), chroma, ink), 1.0);\n  } else {\n    gl_FragColor = vec4(col, alpha);\n  }\n}\n`;\n\nexport default function SoftAurora({\n  speed = 0.6,\n  scale = 1.5,\n  brightness = 1.0,\n  color1 = '#f7f7f7',\n  color2 = '#e100ff',\n  noiseFrequency = 2.5,\n  noiseAmplitude = 1.0,\n  bandHeight = 0.5,\n  bandSpread = 1.0,\n  octaveDecay = 0.1,\n  layerOffset = 0,\n  colorSpeed = 1.0,\n  enableMouseInteraction = true,\n  mouseInfluence = 0.25,\n  lightMode = false\n}) {\n  const containerRef = useRef(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    let program;\n    let currentMouse = [0.5, 0.5];\n    let targetMouse = [0.5, 0.5];\n\n    function handleMouseMove(e) {\n      const rect = gl.canvas.getBoundingClientRect();\n      targetMouse = [\n        (e.clientX - rect.left) / rect.width,\n        1.0 - (e.clientY - rect.top) / rect.height\n      ];\n    }\n\n    function handleMouseLeave() {\n      targetMouse = [0.5, 0.5];\n    }\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        uSpeed: { value: speed },\n        uScale: { value: scale },\n        uBrightness: { value: brightness },\n        uColor1: { value: hexToVec3(color1) },\n        uColor2: { value: hexToVec3(color2) },\n        uNoiseFreq: { value: noiseFrequency },\n        uNoiseAmp: { value: noiseAmplitude },\n        uBandHeight: { value: bandHeight },\n        uBandSpread: { value: bandSpread },\n        uOctaveDecay: { value: octaveDecay },\n        uLayerOffset: { value: layerOffset },\n        uColorSpeed: { value: colorSpeed },\n        uMouse: { value: new Float32Array([0.5, 0.5]) },\n        uMouseInfluence: { value: mouseInfluence },\n        uEnableMouse: { value: enableMouseInteraction },\n        uLightMode: { value: lightMode ? 1 : 0 }\n      }\n    });\n\n    const mesh = new Mesh(gl, { geometry, program });\n    container.appendChild(gl.canvas);\n\n    if (enableMouseInteraction) {\n      gl.canvas.addEventListener('mousemove', handleMouseMove);\n      gl.canvas.addEventListener('mouseleave', handleMouseLeave);\n    }\n\n    let animationFrameId;\n\n    function update(time) {\n      animationFrameId = requestAnimationFrame(update);\n      program.uniforms.uTime.value = time * 0.001;\n\n      if (enableMouseInteraction) {\n        currentMouse[0] += 0.05 * (targetMouse[0] - currentMouse[0]);\n        currentMouse[1] += 0.05 * (targetMouse[1] - currentMouse[1]);\n        program.uniforms.uMouse.value[0] = currentMouse[0];\n        program.uniforms.uMouse.value[1] = currentMouse[1];\n      } else {\n        program.uniforms.uMouse.value[0] = 0.5;\n        program.uniforms.uMouse.value[1] = 0.5;\n      }\n\n      renderer.render({ scene: mesh });\n    }\n    animationFrameId = requestAnimationFrame(update);\n\n    return () => {\n      cancelAnimationFrame(animationFrameId);\n      window.removeEventListener('resize', resize);\n      if (enableMouseInteraction) {\n        gl.canvas.removeEventListener('mousemove', handleMouseMove);\n        gl.canvas.removeEventListener('mouseleave', handleMouseLeave);\n      }\n      container.removeChild(gl.canvas);\n      gl.getExtension('WEBGL_lose_context')?.loseContext();\n    };\n  }, [speed, scale, brightness, color1, color2, noiseFrequency, noiseAmplitude, bandHeight, bandSpread, octaveDecay, layerOffset, colorSpeed, enableMouseInteraction, mouseInfluence, lightMode]);\n\n  return <div ref={containerRef} className=\"soft-aurora-container\" />;\n}\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"ogl@^1.0.11"
	]
}