{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "galaxy",
  "type": "registry:block",
  "title": "Galaxy",
  "description": "Galaxy",
  "files": [
    {
      "path": "components/usages/galaxyusage.tsx",
      "content": "import Galaxy from \"@/registry/open-source/galaxy\";\n\n\n// With custom prop values\nexport default function Usage() {\n    return (\n        <div style={{ width: '100%', height: '600px', position: 'relative' }}>\n            <Galaxy\n                mouseRepulsion\n                mouseInteraction={false}\n                density={1}\n                glowIntensity={0.3}\n                saturation={0}\n                hueShift={140}\n                twinkleIntensity={0.3}\n                rotationSpeed={0.1}\n                repulsionStrength={2}\n                autoCenterRepulsion={0}\n                starSpeed={0.5}\n                speed={1}\n            />\n        </div>\n    );\n}",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/galaxyusage.tsx",
      "content": "import Galaxy from \"@/registry/open-source/galaxy\";\n\n\n// With custom prop values\nexport default function Usage() {\n    return (\n        <div style={{ width: '100%', height: '600px', position: 'relative' }}>\n            <Galaxy\n                mouseRepulsion\n                mouseInteraction={false}\n                density={1}\n                glowIntensity={0.3}\n                saturation={0}\n                hueShift={140}\n                twinkleIntensity={0.3}\n                rotationSpeed={0.1}\n                repulsionStrength={2}\n                autoCenterRepulsion={0}\n                starSpeed={0.5}\n                speed={1}\n            />\n        </div>\n    );\n}",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/galaxy.tsx",
      "content": "import { Renderer, Program, Mesh, Color, Triangle } from 'ogl';\nimport { useEffect, useRef } from 'react';\n\nconst vertexShader = `\nattribute vec2 uv;\nattribute vec2 position;\n\nvarying vec2 vUv;\n\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 vec2 uFocal;\nuniform vec2 uRotation;\nuniform float uStarSpeed;\nuniform float uDensity;\nuniform float uHueShift;\nuniform float uSpeed;\nuniform vec2 uMouse;\nuniform float uGlowIntensity;\nuniform float uSaturation;\nuniform bool uMouseRepulsion;\nuniform float uTwinkleIntensity;\nuniform float uRotationSpeed;\nuniform float uRepulsionStrength;\nuniform float uMouseActiveFactor;\nuniform float uAutoCenterRepulsion;\nuniform bool uTransparent;\n\nvarying vec2 vUv;\n\n#define NUM_LAYER 4.0\n#define STAR_COLOR_CUTOFF 0.2\n#define MAT45 mat2(0.7071, -0.7071, 0.7071, 0.7071)\n#define PERIOD 3.0\n\nfloat Hash21(vec2 p) {\n  p = fract(p * vec2(123.34, 456.21));\n  p += dot(p, p + 45.32);\n  return fract(p.x * p.y);\n}\n\nfloat tri(float x) {\n  return abs(fract(x) * 2.0 - 1.0);\n}\n\nfloat tris(float x) {\n  float t = fract(x);\n  return 1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0));\n}\n\nfloat trisn(float x) {\n  float t = fract(x);\n  return 2.0 * (1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0))) - 1.0;\n}\n\nvec3 hsv2rgb(vec3 c) {\n  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n  vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n  return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nfloat Star(vec2 uv, float flare) {\n  float d = length(uv);\n  float m = (0.05 * uGlowIntensity) / d;\n  float rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));\n  m += rays * flare * uGlowIntensity;\n  uv *= MAT45;\n  rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));\n  m += rays * 0.3 * flare * uGlowIntensity;\n  m *= smoothstep(1.0, 0.2, d);\n  return m;\n}\n\nvec3 StarLayer(vec2 uv) {\n  vec3 col = vec3(0.0);\n\n  vec2 gv = fract(uv) - 0.5; \n  vec2 id = floor(uv);\n\n  for (int y = -1; y <= 1; y++) {\n    for (int x = -1; x <= 1; x++) {\n      vec2 offset = vec2(float(x), float(y));\n      vec2 si = id + vec2(float(x), float(y));\n      float seed = Hash21(si);\n      float size = fract(seed * 345.32);\n      float glossLocal = tri(uStarSpeed / (PERIOD * seed + 1.0));\n      float flareSize = smoothstep(0.9, 1.0, size) * glossLocal;\n\n      float red = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 1.0)) + STAR_COLOR_CUTOFF;\n      float blu = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 3.0)) + STAR_COLOR_CUTOFF;\n      float grn = min(red, blu) * seed;\n      vec3 base = vec3(red, grn, blu);\n      \n      float hue = atan(base.g - base.r, base.b - base.r) / (2.0 * 3.14159) + 0.5;\n      hue = fract(hue + uHueShift / 360.0);\n      float sat = length(base - vec3(dot(base, vec3(0.299, 0.587, 0.114)))) * uSaturation;\n      float val = max(max(base.r, base.g), base.b);\n      base = hsv2rgb(vec3(hue, sat, val));\n\n      vec2 pad = vec2(tris(seed * 34.0 + uTime * uSpeed / 10.0), tris(seed * 38.0 + uTime * uSpeed / 30.0)) - 0.5;\n\n      float star = Star(gv - offset - pad, flareSize);\n      vec3 color = base;\n\n      float twinkle = trisn(uTime * uSpeed + seed * 6.2831) * 0.5 + 1.0;\n      twinkle = mix(1.0, twinkle, uTwinkleIntensity);\n      star *= twinkle;\n      \n      col += star * size * color;\n    }\n  }\n\n  return col;\n}\n\nvoid main() {\n  vec2 focalPx = uFocal * uResolution.xy;\n  vec2 uv = (vUv * uResolution.xy - focalPx) / uResolution.y;\n\n  vec2 mouseNorm = uMouse - vec2(0.5);\n  \n  if (uAutoCenterRepulsion > 0.0) {\n    vec2 centerUV = vec2(0.0, 0.0);\n    float centerDist = length(uv - centerUV);\n    vec2 repulsion = normalize(uv - centerUV) * (uAutoCenterRepulsion / (centerDist + 0.1));\n    uv += repulsion * 0.05;\n  } else if (uMouseRepulsion) {\n    vec2 mousePosUV = (uMouse * uResolution.xy - focalPx) / uResolution.y;\n    float mouseDist = length(uv - mousePosUV);\n    vec2 repulsion = normalize(uv - mousePosUV) * (uRepulsionStrength / (mouseDist + 0.1));\n    uv += repulsion * 0.05 * uMouseActiveFactor;\n  } else {\n    vec2 mouseOffset = mouseNorm * 0.1 * uMouseActiveFactor;\n    uv += mouseOffset;\n  }\n\n  float autoRotAngle = uTime * uRotationSpeed;\n  mat2 autoRot = mat2(cos(autoRotAngle), -sin(autoRotAngle), sin(autoRotAngle), cos(autoRotAngle));\n  uv = autoRot * uv;\n\n  uv = mat2(uRotation.x, -uRotation.y, uRotation.y, uRotation.x) * uv;\n\n  vec3 col = vec3(0.0);\n\n  for (float i = 0.0; i < 1.0; i += 1.0 / NUM_LAYER) {\n    float depth = fract(i + uStarSpeed * uSpeed);\n    float scale = mix(20.0 * uDensity, 0.5 * uDensity, depth);\n    float fade = depth * smoothstep(1.0, 0.9, depth);\n    col += StarLayer(uv * scale + i * 453.32) * fade;\n  }\n\n  if (uTransparent) {\n    float alpha = length(col);\n    alpha = smoothstep(0.0, 0.3, alpha);\n    alpha = min(alpha, 1.0);\n    gl_FragColor = vec4(col, alpha);\n  } else {\n    gl_FragColor = vec4(col, 1.0);\n  }\n}\n`;\n\ninterface GalaxyProps {\n    focal?: [number, number];\n    rotation?: [number, number];\n    starSpeed?: number;\n    density?: number;\n    hueShift?: number;\n    disableAnimation?: boolean;\n    speed?: number;\n    mouseInteraction?: boolean;\n    glowIntensity?: number;\n    saturation?: number;\n    mouseRepulsion?: boolean;\n    twinkleIntensity?: number;\n    rotationSpeed?: number;\n    repulsionStrength?: number;\n    autoCenterRepulsion?: number;\n    transparent?: boolean;\n}\n\nexport default function Galaxy({\n    focal = [0.5, 0.5],\n    rotation = [1.0, 0.0],\n    starSpeed = 0.5,\n    density = 1,\n    hueShift = 140,\n    disableAnimation = false,\n    speed = 1.0,\n    mouseInteraction = true,\n    glowIntensity = 0.3,\n    saturation = 0.0,\n    mouseRepulsion = true,\n    repulsionStrength = 2,\n    twinkleIntensity = 0.3,\n    rotationSpeed = 0.1,\n    autoCenterRepulsion = 0,\n    transparent = true,\n    ...rest\n}: GalaxyProps) {\n    const ctnDom = useRef<HTMLDivElement>(null);\n    const targetMousePos = useRef({ x: 0.5, y: 0.5 });\n    const smoothMousePos = useRef({ x: 0.5, y: 0.5 });\n    const targetMouseActive = useRef(0.0);\n    const smoothMouseActive = useRef(0.0);\n\n    useEffect(() => {\n        if (!ctnDom.current) return;\n        const ctn = ctnDom.current;\n        const renderer = new Renderer({\n            alpha: transparent,\n            premultipliedAlpha: false\n        });\n        const gl = renderer.gl;\n\n        if (transparent) {\n            gl.enable(gl.BLEND);\n            gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n            gl.clearColor(0, 0, 0, 0);\n        } else {\n            gl.clearColor(0, 0, 0, 1);\n        }\n\n        let program: Program;\n\n        function resize() {\n            const scale = 1;\n            renderer.setSize(ctn.offsetWidth * scale, ctn.offsetHeight * scale);\n            if (program) {\n                program.uniforms.uResolution.value = new Color(\n                    gl.canvas.width,\n                    gl.canvas.height,\n                    gl.canvas.width / gl.canvas.height\n                );\n            }\n        }\n        window.addEventListener('resize', resize, false);\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: {\n                    value: new Color(gl.canvas.width, gl.canvas.height, gl.canvas.width / gl.canvas.height)\n                },\n                uFocal: { value: new Float32Array(focal) },\n                uRotation: { value: new Float32Array(rotation) },\n                uStarSpeed: { value: starSpeed },\n                uDensity: { value: density },\n                uHueShift: { value: hueShift },\n                uSpeed: { value: speed },\n                uMouse: {\n                    value: new Float32Array([smoothMousePos.current.x, smoothMousePos.current.y])\n                },\n                uGlowIntensity: { value: glowIntensity },\n                uSaturation: { value: saturation },\n                uMouseRepulsion: { value: mouseRepulsion },\n                uTwinkleIntensity: { value: twinkleIntensity },\n                uRotationSpeed: { value: rotationSpeed },\n                uRepulsionStrength: { value: repulsionStrength },\n                uMouseActiveFactor: { value: 0.0 },\n                uAutoCenterRepulsion: { value: autoCenterRepulsion },\n                uTransparent: { value: transparent }\n            }\n        });\n\n        const mesh = new Mesh(gl, { geometry, program });\n        let animateId: number;\n\n        function update(t: number) {\n            animateId = requestAnimationFrame(update);\n            if (!disableAnimation) {\n                program.uniforms.uTime.value = t * 0.001;\n                program.uniforms.uStarSpeed.value = (t * 0.001 * starSpeed) / 10.0;\n            }\n\n            const lerpFactor = 0.05;\n            smoothMousePos.current.x += (targetMousePos.current.x - smoothMousePos.current.x) * lerpFactor;\n            smoothMousePos.current.y += (targetMousePos.current.y - smoothMousePos.current.y) * lerpFactor;\n\n            smoothMouseActive.current += (targetMouseActive.current - smoothMouseActive.current) * lerpFactor;\n\n            program.uniforms.uMouse.value[0] = smoothMousePos.current.x;\n            program.uniforms.uMouse.value[1] = smoothMousePos.current.y;\n            program.uniforms.uMouseActiveFactor.value = smoothMouseActive.current;\n\n            renderer.render({ scene: mesh });\n        }\n        animateId = requestAnimationFrame(update);\n        ctn.appendChild(gl.canvas);\n\n        function handleMouseMove(e: MouseEvent) {\n            const rect = ctn.getBoundingClientRect();\n            const x = (e.clientX - rect.left) / rect.width;\n            const y = 1.0 - (e.clientY - rect.top) / rect.height;\n            targetMousePos.current = { x, y };\n            targetMouseActive.current = 1.0;\n        }\n\n        function handleMouseLeave() {\n            targetMouseActive.current = 0.0;\n        }\n\n        if (mouseInteraction) {\n            ctn.addEventListener('mousemove', handleMouseMove);\n            ctn.addEventListener('mouseleave', handleMouseLeave);\n        }\n\n        return () => {\n            cancelAnimationFrame(animateId);\n            window.removeEventListener('resize', resize);\n            if (mouseInteraction) {\n                ctn.removeEventListener('mousemove', handleMouseMove);\n                ctn.removeEventListener('mouseleave', handleMouseLeave);\n            }\n            ctn.removeChild(gl.canvas);\n            gl.getExtension('WEBGL_lose_context')?.loseContext();\n        };\n    }, [\n        focal,\n        rotation,\n        starSpeed,\n        density,\n        hueShift,\n        disableAnimation,\n        speed,\n        mouseInteraction,\n        glowIntensity,\n        saturation,\n        mouseRepulsion,\n        twinkleIntensity,\n        rotationSpeed,\n        repulsionStrength,\n        autoCenterRepulsion,\n        transparent\n    ]);\n\n    return <div ref={ctnDom} className=\"w-full h-full relative\" {...rest} />;\n}\n",
      "type": "registry:ui"
    }
  ]
}