@stianlarsen/react-light-beam
Version:
A customizable React component that creates a light beam effect using conic gradients. Powered by GSAP for maximum performance. Supports dark mode and various customization options.
1 lines • 39.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/hooks/useDarkmode.tsx","../src/effects/DustParticles.tsx","../src/effects/MistEffect.tsx","../src/effects/PulseEffect.tsx","../src/index.tsx"],"names":["gsap","useMemo","useGSAP","jsx","Fragment","useEffect"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\";\nimport {useEffect, useState} from \"react\";\n\nexport const useIsDarkmode = () => {\n const [isDarkmode, setIsDarkmodeActive] = useState(false);\n\n useEffect(() => {\n const matchMedia = window.matchMedia(\"(prefers-color-scheme: dark)\");\n\n const handleChange = () => {\n console.log(\"Darkmode match?\", matchMedia.matches)\n \n setIsDarkmodeActive(matchMedia.matches);\n };\n\n // Set the initial value\n setIsDarkmodeActive(matchMedia.matches);\n\n // Listen for changes\n matchMedia.addEventListener(\"change\", handleChange);\n handleChange()\n\n // Cleanup listener on unmount\n return () => {\n matchMedia.removeEventListener(\"change\", handleChange);\n };\n }, []);\n\n return {isDarkmode};\n};\n","\"use client\";\nimport gsap from \"gsap\";\nimport {useGSAP} from \"@gsap/react\";\nimport {useMemo} from \"react\";\nimport {DustParticlesConfig} from \"../../types/types\";\n\ninterface DustParticlesProps {\n config: DustParticlesConfig;\n beamColor: string;\n}\n\nexport const DustParticles = ({config, beamColor}: DustParticlesProps) => {\n const {\n enabled = false,\n count = 30,\n speed = 1,\n sizeRange = [1, 3],\n opacityRange = [0.2, 0.6],\n color,\n } = config;\n\n // Generate particle data once\n const particles = useMemo(() => {\n if (!enabled) return [];\n\n return Array.from({length: count}, (_, i) => {\n // Random position\n const x = Math.random() * 100; // 0-100%\n const y = Math.random() * 100; // 0-100%\n\n // Random size within range\n const size = sizeRange[0] + Math.random() * (sizeRange[1] - sizeRange[0]);\n\n // Random opacity within range\n const opacity = opacityRange[0] + Math.random() * (opacityRange[1] - opacityRange[0]);\n\n // Random animation duration (inversely proportional to speed)\n const duration = (3 + Math.random() * 4) / speed; // 3-7s / speed\n\n // Random animation delay for stagger effect\n const delay = Math.random() * duration;\n\n return {\n id: `dust-${i}`,\n x,\n y,\n size,\n opacity,\n duration,\n delay,\n };\n });\n }, [enabled, count, sizeRange, opacityRange, speed]);\n\n useGSAP(\n () => {\n if (!enabled || particles.length === 0) return;\n\n const timelines: gsap.core.Timeline[] = [];\n\n particles.forEach((particle) => {\n const element = document.getElementById(particle.id);\n if (!element) return;\n\n // Create floating animation for each particle\n const tl = gsap.timeline({\n repeat: -1,\n yoyo: true,\n delay: particle.delay,\n });\n\n // Animate vertical movement and slight horizontal drift\n tl.to(element, {\n y: `-=${20 + Math.random() * 30}`, // Float upward 20-50px\n x: `+=${Math.random() * 20 - 10}`, // Slight horizontal drift ±10px\n opacity: particle.opacity * 0.5, // Fade slightly\n duration: particle.duration,\n ease: \"sine.inOut\",\n });\n\n timelines.push(tl);\n });\n\n return () => {\n timelines.forEach((tl) => tl.kill());\n };\n },\n {\n dependencies: [particles, enabled],\n }\n );\n\n if (!enabled) return null;\n\n const particleColor = color || beamColor;\n\n return (\n <>\n {particles.map((particle) => (\n <div\n key={particle.id}\n id={particle.id}\n style={{\n position: \"absolute\",\n left: `${particle.x}%`,\n top: `${particle.y}%`,\n width: `${particle.size}px`,\n height: `${particle.size}px`,\n borderRadius: \"50%\",\n backgroundColor: particleColor,\n opacity: particle.opacity,\n pointerEvents: \"none\",\n willChange: \"transform, opacity\",\n }}\n />\n ))}\n </>\n );\n};\n","\"use client\";\nimport gsap from \"gsap\";\nimport {useGSAP} from \"@gsap/react\";\nimport {useMemo} from \"react\";\nimport {MistConfig} from \"../../types/types\";\n\ninterface MistEffectProps {\n config: MistConfig;\n beamColor: string;\n}\n\nexport const MistEffect = ({config, beamColor}: MistEffectProps) => {\n const {\n enabled = false,\n intensity = 0.3,\n speed = 1,\n layers = 2,\n } = config;\n\n // Generate mist layer data\n const mistLayers = useMemo(() => {\n if (!enabled) return [];\n\n return Array.from({length: layers}, (_, i) => {\n // Each layer has different characteristics for depth\n const layerOpacity = (intensity * 0.6) / (i + 1); // Deeper layers are more transparent\n const duration = (8 + i * 3) / speed; // Deeper layers move slower\n const delay = (i * 1.5) / speed; // Stagger start times\n const scale = 1 + i * 0.2; // Deeper layers are larger\n\n return {\n id: `mist-layer-${i}`,\n opacity: layerOpacity,\n duration,\n delay,\n scale,\n };\n });\n }, [enabled, intensity, speed, layers]);\n\n useGSAP(\n () => {\n if (!enabled || mistLayers.length === 0) return;\n\n const timelines: gsap.core.Timeline[] = [];\n\n mistLayers.forEach((layer) => {\n const element = document.getElementById(layer.id);\n if (!element) return;\n\n // Create drifting mist animation\n const tl = gsap.timeline({\n repeat: -1,\n yoyo: false,\n });\n\n // Horizontal drift animation\n tl.fromTo(\n element,\n {\n x: \"-100%\",\n opacity: 0,\n },\n {\n x: \"100%\",\n opacity: layer.opacity,\n duration: layer.duration,\n ease: \"none\",\n delay: layer.delay,\n }\n ).to(element, {\n opacity: 0,\n duration: layer.duration * 0.2,\n ease: \"power1.in\",\n });\n\n timelines.push(tl);\n });\n\n return () => {\n timelines.forEach((tl) => tl.kill());\n };\n },\n {\n dependencies: [mistLayers, enabled],\n }\n );\n\n if (!enabled) return null;\n\n // Parse beam color and create mist color with lower opacity\n const mistColor = beamColor.replace(/[\\d.]+\\)$/g, `${intensity})`);\n\n return (\n <>\n {mistLayers.map((layer) => (\n <div\n key={layer.id}\n id={layer.id}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n background: `radial-gradient(ellipse 120% 80% at 50% 20%, ${mistColor}, transparent 70%)`,\n opacity: 0,\n pointerEvents: \"none\",\n willChange: \"transform, opacity\",\n transform: `scale(${layer.scale})`,\n filter: \"blur(40px)\",\n }}\n />\n ))}\n </>\n );\n};\n","\"use client\";\nimport gsap from \"gsap\";\nimport {useGSAP} from \"@gsap/react\";\nimport {PulseConfig} from \"../../types/types\";\n\ninterface PulseEffectProps {\n config: PulseConfig;\n containerRef: React.RefObject<HTMLDivElement | null>;\n}\n\nexport const PulseEffect = ({config, containerRef}: PulseEffectProps) => {\n const {\n enabled = false,\n duration = 2,\n intensity = 0.2,\n easing = \"sine.inOut\",\n } = config;\n\n useGSAP(\n () => {\n if (!enabled || !containerRef.current) return;\n\n const element = containerRef.current;\n\n // Create pulsing animation using GSAP timeline\n // Pulse multiplies the base opacity (from scroll) with pulse intensity\n const timeline = gsap.timeline({\n repeat: -1, // Infinite loop\n yoyo: true, // Reverse on each iteration\n });\n\n // Calculate pulse range based on intensity\n // Pulse multiplier varies from (1 - intensity) to (1 + intensity)\n const minMultiplier = Math.max(0, 1 - intensity);\n const maxMultiplier = Math.min(2, 1 + intensity);\n\n timeline.fromTo(\n element,\n {\n \"--pulse-multiplier\": 1,\n },\n {\n \"--pulse-multiplier\": maxMultiplier,\n duration: duration,\n ease: easing,\n }\n );\n\n // Apply combined opacity using calc()\n // opacity = base-opacity * pulse-multiplier\n const updateOpacity = () => {\n const baseOpacity = getComputedStyle(element).getPropertyValue('--base-opacity') || '1';\n const pulseMultiplier = getComputedStyle(element).getPropertyValue('--pulse-multiplier') || '1';\n element.style.opacity = `calc(${baseOpacity} * ${pulseMultiplier})`;\n };\n\n // Update opacity continuously during animation\n const ticker = gsap.ticker.add(updateOpacity);\n\n return () => {\n timeline.kill();\n gsap.ticker.remove(ticker);\n };\n },\n {\n dependencies: [enabled, duration, intensity, easing],\n scope: containerRef,\n }\n );\n\n // This component doesn't render anything - it just adds animations\n return null;\n};\n","\"use client\";\nimport gsap from \"gsap\";\nimport {ScrollTrigger} from \"gsap/ScrollTrigger\";\nimport {useGSAP} from \"@gsap/react\";\nimport React, {useEffect, useRef} from \"react\";\nimport {LightBeamProps} from \"../types/types\";\nimport {useIsDarkmode} from \"./hooks/useDarkmode\";\nimport {DustParticles} from \"./effects/DustParticles\";\nimport {MistEffect} from \"./effects/MistEffect\";\nimport {PulseEffect} from \"./effects/PulseEffect\";\n\n// Register GSAP plugins\ngsap.registerPlugin(ScrollTrigger, useGSAP);\n\n// Default inline styles using CSS variables for easy customization\n// Users can override via className by setting CSS variables\nconst defaultStyles: React.CSSProperties = {\n height: \"var(--react-light-beam-height, 500px)\",\n width: \"var(--react-light-beam-width, 100vw)\",\n // CRITICAL: NO transition on GSAP-controlled properties (background, opacity, mask)\n // Transitions would fight with GSAP's instant updates, causing visual glitches\n // especially when scroll direction changes\n transition: \"none\",\n willChange: \"background, opacity\", // Specific properties for better performance\n userSelect: \"none\",\n pointerEvents: \"none\",\n contain: \"layout style paint\", // CSS containment for better performance\n WebkitTransition: \"none\",\n WebkitUserSelect: \"none\",\n MozUserSelect: \"none\",\n};\n\nexport const LightBeam = ({\n className,\n style,\n colorLightmode = \"rgba(0,0,0, 0.5)\",\n colorDarkmode = \"rgba(255, 255, 255, 0.5)\",\n maskLightByProgress = false,\n fullWidth = 1.0, // Default to full width range\n invert = false,\n id = undefined,\n onLoaded = undefined,\n scrollElement,\n disableDefaultStyles = false,\n scrollStart = \"top bottom\",\n scrollEnd = \"top top\",\n dustParticles = {enabled: false},\n mist = {enabled: false},\n pulse = {enabled: false},\n }: LightBeamProps) => {\n const elementRef = useRef<HTMLDivElement>(null);\n const {isDarkmode} = useIsDarkmode();\n const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;\n\n // Use refs to track current values without triggering useGSAP re-runs\n const colorRef = useRef(chosenColor);\n const invertRef = useRef(invert);\n const maskByProgressRef = useRef(maskLightByProgress);\n\n // Store ScrollTrigger instance for manual updates\n const scrollTriggerRef = useRef<ScrollTrigger | null>(null);\n\n // Update refs whenever values change\n useEffect(() => {\n colorRef.current = chosenColor;\n\n // PERFORMANCE: Update color CSS variable when color changes\n // This avoids recreating ScrollTrigger on color changes\n if (elementRef.current) {\n elementRef.current.style.setProperty('--beam-color', chosenColor);\n }\n }, [chosenColor, colorLightmode, colorDarkmode]);\n\n // Handle invert changes separately - needs immediate update\n useEffect(() => {\n const prevInvert = invertRef.current;\n invertRef.current = invert;\n\n // If invert changed and ScrollTrigger exists, immediately update\n if (prevInvert !== invert && scrollTriggerRef.current && elementRef.current) {\n const st = scrollTriggerRef.current;\n const element = elementRef.current;\n\n // Force immediate recalculation with new invert value\n // This prevents lag/jitter when toggling invert during scroll\n st.refresh();\n }\n }, [invert]);\n\n // Handle maskLightByProgress changes separately - needs structure rebuild\n useEffect(() => {\n const prevMaskByProgress = maskByProgressRef.current;\n maskByProgressRef.current = maskLightByProgress;\n\n // If maskLightByProgress changed and element exists, rebuild mask structure\n if (prevMaskByProgress !== maskLightByProgress && elementRef.current) {\n const element = elementRef.current;\n\n // Rebuild mask gradient structure with new setting\n if (maskLightByProgress) {\n // Initialize mask stop value\n element.style.setProperty('--beam-mask-stop', '50%');\n element.style.maskImage = `linear-gradient(to bottom, var(--beam-color) 0%, transparent var(--beam-mask-stop))`;\n element.style.webkitMaskImage = `linear-gradient(to bottom, var(--beam-color) 0%, transparent var(--beam-mask-stop))`;\n } else {\n // Static mask\n element.style.maskImage = `linear-gradient(to bottom, var(--beam-color) 25%, transparent 95%)`;\n element.style.webkitMaskImage = `linear-gradient(to bottom, var(--beam-color) 25%, transparent 95%)`;\n }\n\n // If ScrollTrigger exists, refresh to apply current state\n if (scrollTriggerRef.current) {\n scrollTriggerRef.current.refresh();\n }\n }\n }, [maskLightByProgress]);\n\n // Call onLoaded callback when component mounts\n useEffect(() => {\n onLoaded && onLoaded();\n }, []);\n\n // GSAP ScrollTrigger implementation\n useGSAP(\n () => {\n const element = elementRef.current;\n if (!element || typeof window === \"undefined\") return;\n\n // Pre-calculate constants for performance\n const opacityMin = 0.839322;\n const opacityRange = 0.160678; // 1 - 0.839322\n\n // Helper function to set color (only when color changes, not every frame)\n const updateColorVar = (color: string): void => {\n element.style.setProperty('--beam-color', color);\n };\n\n // Set initial gradient structure (once, not per frame!)\n const initGradientStructure = (color: string): void => {\n updateColorVar(color);\n const baseGradient = `conic-gradient(from 90deg at var(--beam-left-pos) 0%, var(--beam-color), transparent 180deg) 0% 0% / 50% var(--beam-left-size) no-repeat, conic-gradient(from 270deg at var(--beam-right-pos) 0%, transparent 180deg, var(--beam-color)) 100% 0% / 50% 100% no-repeat`;\n element.style.background = baseGradient;\n\n // Set mask structure\n if (maskByProgressRef.current) {\n element.style.maskImage = `linear-gradient(to bottom, var(--beam-color) 0%, transparent var(--beam-mask-stop))`;\n element.style.webkitMaskImage = `linear-gradient(to bottom, var(--beam-color) 0%, transparent var(--beam-mask-stop))`;\n } else {\n element.style.maskImage = `linear-gradient(to bottom, var(--beam-color) 25%, transparent 95%)`;\n element.style.webkitMaskImage = `linear-gradient(to bottom, var(--beam-color) 25%, transparent 95%)`;\n }\n };\n\n // FRAMER MOTION LOGIC (PRESERVED):\n // fullWidth controls the MAXIMUM beam width expansion during scroll\n // fullWidth=1.0 → beam expands from 0% to 100% of maximum width (full range)\n // fullWidth=0.8 → beam expands from 0% to 80% of maximum width\n // fullWidth=0.5 → beam expands from 0% to 50% of maximum width\n // fullWidth=0.2 → beam expands from 0% to 20% of maximum width\n const adjustedFullWidth = 1 - fullWidth;\n\n // Helper function to calculate progress (EXACTLY like Framer Motion)\n const calculateProgress = (rawProgress: number): number => {\n // ScrollTrigger rawProgress: 0 (element entering) → 1 (element at trigger end)\n // We convert to match Framer's rect.top / windowHeight logic\n // GSAP progress (0→1) is INVERSE of Framer's normalizedPosition (1→0)\n\n // Apply fullWidth ceiling (maximum progress value)\n // Math.max ensures progress never goes below (1 - fullWidth)\n // This limits how much the beam can expand\n const normalizedPosition = Math.max(\n adjustedFullWidth, // Floor value (1 - fullWidth)\n Math.min(1, 1 - rawProgress) // Inverted GSAP progress\n );\n\n // Apply invert logic (EXACTLY like Framer Motion)\n // Use invertRef to get current value without closure issues\n return invertRef.current ? normalizedPosition : 1 - normalizedPosition;\n };\n\n // Determine scroll container\n const scroller = scrollElement\n ? (scrollElement as Element | Window)\n : undefined;\n\n // PERFORMANCE OPTIMIZATION: Shared update function to avoid code duplication\n // Batches all style updates for better performance\n const applyProgressState = (progress: number): void => {\n // Pre-calculate all values\n const leftPos = 90 - progress * 90;\n const rightPos = 10 + progress * 90;\n const leftSize = 150 - progress * 50;\n const baseOpacity = opacityMin + opacityRange * progress;\n const maskStop = maskByProgressRef.current ? 50 + progress * 45 : undefined;\n\n // BATCH UPDATE: Use single gsap.set() call instead of multiple setProperty()\n // This is significantly faster as GSAP batches all updates in one frame\n const cssProps: any = {\n '--beam-left-pos': `${leftPos}%`,\n '--beam-right-pos': `${rightPos}%`,\n '--beam-left-size': `${leftSize}%`,\n '--base-opacity': baseOpacity,\n };\n\n // Conditionally add mask stop\n if (maskStop !== undefined) {\n cssProps['--beam-mask-stop'] = `${maskStop}%`;\n }\n\n // Conditionally add opacity (only if pulse not enabled)\n if (!pulse.enabled) {\n cssProps.opacity = baseOpacity;\n }\n\n // Single batch update via GSAP (more efficient than multiple setProperty calls)\n gsap.set(element, cssProps);\n };\n\n // Initialize gradient structure once\n initGradientStructure(colorRef.current);\n\n // Create ScrollTrigger with customizable start/end positions\n // SCRUB VALUE EXPLANATION:\n // - scrub: true (or 1) = 1 second catch-up delay (causes visible lag and stuttering)\n // - scrub: 0.3 = 300ms catch-up (fast and smooth, optimal for UI) ← CURRENT SETTING\n // - scrub: 0 = instant (may feel jittery on fast scrolls, no smoothing)\n // Research: Lower values (0.2-0.5) recommended for responsive scroll UX\n const st = ScrollTrigger.create({\n trigger: element,\n start: scrollStart, // When to start the animation\n end: scrollEnd, // When to end the animation\n scroller: scroller,\n scrub: 0.15, // Fast catch-up (300ms) for responsive scroll without jitter\n onUpdate: (self) => {\n // Calculate progress using Framer Motion logic\n const progress = calculateProgress(self.progress);\n\n // Apply all updates in single batch\n applyProgressState(progress);\n },\n onRefresh: (self) => {\n // CRITICAL: ScrollTrigger.refresh() is called on window resize, orientation change,\n // or when content changes. We need to recalculate and reapply styles to ensure\n // the beam renders correctly after layout changes.\n const progress = calculateProgress(self.progress);\n\n // Apply all updates in single batch\n applyProgressState(progress);\n },\n });\n\n // Store ScrollTrigger instance for manual updates (invert/maskLightByProgress changes)\n scrollTriggerRef.current = st;\n\n // Set initial state immediately using batched update\n const initialProgress = calculateProgress(st.progress);\n applyProgressState(initialProgress);\n\n // Refresh ScrollTrigger after a brief delay to ensure layout is settled\n // This is especially important for Next.js SSR/hydration\n const refreshTimeout = setTimeout(() => {\n ScrollTrigger.refresh();\n }, 100);\n\n // Cleanup function to kill ScrollTrigger and clear timeout\n return () => {\n st.kill();\n clearTimeout(refreshTimeout);\n };\n },\n {\n // CRITICAL: Use refs for frequently changing values!\n // colorRef, invertRef, maskByProgressRef allow updates without recreating ScrollTrigger\n // This prevents visual glitches when these values change mid-scroll\n // Only include values that affect ScrollTrigger's position/range calculations\n dependencies: [\n fullWidth, // Affects progress range calculation\n scrollElement, // Affects which element to watch\n scrollStart, // Affects when animation starts\n scrollEnd, // Affects when animation ends\n ],\n scope: elementRef,\n }\n );\n\n const combinedClassName = `react-light-beam ${className || \"\"}`.trim();\n\n // Prepare final styles\n const finalStyles = disableDefaultStyles\n ? {\n // No default styles, only user styles\n willChange: \"background, opacity\",\n contain: \"layout style paint\",\n ...style, // User styles override\n }\n : {\n // Merge default styles with user styles\n ...defaultStyles,\n ...style, // User styles override everything\n };\n\n return (\n <div\n ref={elementRef}\n className={combinedClassName}\n style={finalStyles}\n {...(id ? {id} : {})}\n >\n {/* Atmospheric Effects */}\n {dustParticles.enabled && (\n <DustParticles config={dustParticles} beamColor={chosenColor}/>\n )}\n {mist.enabled && (\n <MistEffect config={mist} beamColor={chosenColor}/>\n )}\n {pulse.enabled && (\n <PulseEffect config={pulse} containerRef={elementRef}/>\n )}\n </div>\n );\n};\n"]}