{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "glow-radial", "title": "Glow Radial", "author": "designbycode", "dependencies": [ "react", "clsx", "tailwind-merge" ], "registryDependencies": [ "https://ui.designbycode.co.za/r/glow-stack.json" ], "files": [ { "path": "resources/js/registry/new-york/components/ui/glow/glow-radial.tsx", "content": "'use client';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useGlowStack } from '@/registry/new-york/components/ui/glow/glow-stack';\nimport { isCircleOverlappingRect, isPointInRect, toElementSpace } from '@/registry/new-york/lib/glow-geometry';\n\nconst BORDER_MASK = {\n padding: '2px',\n background: 'transparent',\n mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0) border-box',\n maskComposite: 'exclude' as const,\n WebkitMask:\n 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0) border-box',\n WebkitMaskComposite: 'xor' as const,\n} as const;\n\ninterface GlowRadialProps extends HTMLAttributes {\n children?: ReactNode;\n /** Colors for the radial gradient. First color is the center. */\n colors?: string | string[];\n /** Gradient radius in px. Default: 500 */\n size?: number;\n /** Border width in px. Default: 2 */\n borderWidth?: number;\n /** Render as any block element. Default: \"div\" */\n as?: 'div' | 'section' | 'article' | 'main' | 'header' | 'footer' | 'aside';\n}\n\nexport function GlowRadial({\n className,\n children,\n colors = 'var(--color-primary)',\n size = 500,\n borderWidth = 3,\n as: Comp = 'div',\n style,\n ...props\n}: GlowRadialProps) {\n const ref = useRef(null);\n const glowStack = useGlowStack();\n const position = glowStack?.position ?? { x: -1000, y: -1000 };\n const radius = glowStack?.radius ?? 100;\n const [rect, setRect] = useState(null);\n\n useEffect(() => {\n const updateRect = () => {\n setRect(ref.current?.getBoundingClientRect() ?? null);\n };\n\n updateRect();\n\n const handleUpdate = () => updateRect();\n window.addEventListener('resize', handleUpdate, { passive: true });\n window.addEventListener('scroll', handleUpdate, { passive: true });\n\n return () => {\n window.removeEventListener('resize', handleUpdate);\n window.removeEventListener('scroll', handleUpdate);\n };\n }, []);\n\n const near = rect ? isCircleOverlappingRect(position, radius, rect) : false;\n const over = rect ? isPointInRect(position, rect) : false;\n const ep = rect ? toElementSpace(position, rect) : { x: 0, y: 0 };\n\n const colorsArray = Array.isArray(colors)\n ? colors\n : [colors, 'transparent'];\n const gradient = `radial-gradient(circle at ${ep.x}px ${ep.y}px, ${colorsArray.join(', ')}, transparent ${size}px)`;\n const borderMask = { ...BORDER_MASK, padding: `${borderWidth}px` };\n\n return (\n \n {/* Hard border glow */}\n \n {/* Soft blur halo */}\n \n {/* Subtle fill when directly over */}\n \n {children}\n \n );\n}\n", "type": "registry:ui" } ], "meta": { "category": "components", "version": "1.0.0" }, "type": "registry:ui" }