@stianlarsen/react-light-beam 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -94,25 +94,31 @@ var LightBeam = ({
94
94
  );
95
95
  const maskImage = maskLightByProgress ? maskImageOpacity : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;
96
96
  const combinedClassName = `react-light-beam ${className || ""}`.trim();
97
- const motionStyles = {
97
+ const finalStyles = disableDefaultStyles ? {
98
+ // No default styles, only motion values and user styles
98
99
  background: backgroundPosition,
99
100
  opacity,
100
101
  maskImage,
101
102
  WebkitMaskImage: maskImage,
102
- willChange: "background, opacity"
103
- };
104
- const mergedStyles = disableDefaultStyles ? {
105
- ...motionStyles,
103
+ willChange: "background, opacity",
106
104
  ...style
107
- // User styles override motion styles
105
+ // User styles override
108
106
  } : {
107
+ // Merge default styles with motion values
109
108
  ...defaultStyles,
110
- ...motionStyles,
109
+ background: backgroundPosition,
110
+ // MotionValue (overrides default)
111
+ opacity,
112
+ // MotionValue (overrides default)
113
+ maskImage,
114
+ // MotionValue or string
115
+ WebkitMaskImage: maskImage,
116
+ willChange: "background, opacity",
111
117
  ...style
112
118
  // User styles override everything
113
119
  };
114
120
  const motionProps = {
115
- style: mergedStyles,
121
+ style: finalStyles,
116
122
  ref: elementRef,
117
123
  className: combinedClassName,
118
124
  ...id ? { id } : {}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useDarkmode.tsx","../src/index.tsx"],"names":["useState","useEffect","useRef","useMotionValue","useTransform","jsx","motion"],"mappings":"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","file":"index.js","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 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\n // Cleanup listener on unmount\n return () => {\n matchMedia.removeEventListener(\"change\", handleChange);\n };\n }, []);\n\n return { isDarkmode };\n};\n","\"use client\";\nimport { motion, useMotionValue, useTransform } from \"framer-motion\";\nimport React, { useEffect, useRef } from \"react\";\nimport { LightBeamProps } from \"../types/types\";\nimport { useIsDarkmode } from \"./hooks/useDarkmode\";\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 transition: \"var(--react-light-beam-transition, all 0.25s ease)\",\n willChange: \"all\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n WebkitTransition: \"var(--react-light-beam-transition, all 0.25s ease)\",\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\n invert = false,\n id = undefined,\n onLoaded = undefined,\n scrollElement,\n disableDefaultStyles = false,\n}: LightBeamProps) => {\n const elementRef = useRef<HTMLDivElement>(null);\n const inViewProgress = useMotionValue(0);\n const opacity = useMotionValue(0.839322);\n const { isDarkmode } = useIsDarkmode();\n const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;\n\n useEffect(() => {\n onLoaded && onLoaded();\n }, []);\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n const handleScroll = () => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Invert the fullWidth value: 1 becomes 0, and 0 becomes 1\n const adjustedFullWidth = 1 - fullWidth;\n\n // Calculate progress\n const progress = invert\n ? 0 +\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight))\n : 1 -\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight));\n\n // Update motion values\n inViewProgress.set(progress);\n opacity.set(0.839322 + (1 - 0.839322) * progress);\n }\n };\n\n const handleScrollThrottled = throttle(handleScroll); // Approx 60fps\n\n const target = scrollElement || window;\n\n target.addEventListener(\"scroll\", handleScrollThrottled);\n window.addEventListener(\"resize\", handleScrollThrottled);\n\n // Initial call to handleScroll to set initial state\n handleScroll();\n\n return () => {\n target.removeEventListener(\"scroll\", handleScrollThrottled);\n window.removeEventListener(\"resize\", handleScrollThrottled);\n };\n }\n }, [inViewProgress, opacity, scrollElement]);\n\n const backgroundPosition = useTransform(\n inViewProgress,\n [0, 1],\n [\n `conic-gradient(from 90deg at 90% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 150% no-repeat, conic-gradient(from 270deg at 10% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n `conic-gradient(from 90deg at 0% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 100% no-repeat, conic-gradient(from 270deg at 100% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n ]\n );\n const maskImageOpacity = useTransform(\n inViewProgress,\n [0, 1],\n [\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 50%)`,\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 95%)`,\n ]\n );\n\n const maskImage = maskLightByProgress\n ? maskImageOpacity\n : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;\n\n const combinedClassName = `react-light-beam ${className || \"\"}`.trim();\n\n // Motion-specific styles (always applied)\n const motionStyles = {\n background: backgroundPosition,\n opacity: opacity,\n maskImage: maskImage,\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n };\n\n // Merge styles in order of priority:\n // 1. Default styles (lowest)\n // 2. Motion styles (middle)\n // 3. User's style prop (highest - overrides everything)\n const mergedStyles = disableDefaultStyles\n ? {\n ...motionStyles,\n ...style, // User styles override motion styles\n }\n : {\n ...defaultStyles,\n ...motionStyles,\n ...style, // User styles override everything\n };\n\n const motionProps: any = {\n style: mergedStyles,\n ref: elementRef,\n className: combinedClassName,\n ...(id ? { id } : {}),\n };\n\n return <motion.div {...motionProps} />;\n};\n\nconst throttle = (func: Function) => {\n let ticking = false;\n return function (this: any, ...args: any[]) {\n if (!ticking) {\n requestAnimationFrame(() => {\n func.apply(this, args);\n ticking = false;\n });\n ticking = true;\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/hooks/useDarkmode.tsx","../src/index.tsx"],"names":["useState","useEffect","useRef","useMotionValue","useTransform","jsx","motion"],"mappings":"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","file":"index.js","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 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\n // Cleanup listener on unmount\n return () => {\n matchMedia.removeEventListener(\"change\", handleChange);\n };\n }, []);\n\n return { isDarkmode };\n};\n","\"use client\";\nimport { motion, useMotionValue, useTransform } from \"framer-motion\";\nimport React, { useEffect, useRef } from \"react\";\nimport { LightBeamProps } from \"../types/types\";\nimport { useIsDarkmode } from \"./hooks/useDarkmode\";\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 transition: \"var(--react-light-beam-transition, all 0.25s ease)\",\n willChange: \"all\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n WebkitTransition: \"var(--react-light-beam-transition, all 0.25s ease)\",\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\n invert = false,\n id = undefined,\n onLoaded = undefined,\n scrollElement,\n disableDefaultStyles = false,\n}: LightBeamProps) => {\n const elementRef = useRef<HTMLDivElement>(null);\n const inViewProgress = useMotionValue(0);\n const opacity = useMotionValue(0.839322);\n const { isDarkmode } = useIsDarkmode();\n const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;\n\n useEffect(() => {\n onLoaded && onLoaded();\n }, []);\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n const handleScroll = () => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Invert the fullWidth value: 1 becomes 0, and 0 becomes 1\n const adjustedFullWidth = 1 - fullWidth;\n\n // Calculate progress\n const progress = invert\n ? 0 +\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight))\n : 1 -\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight));\n\n // Update motion values\n inViewProgress.set(progress);\n opacity.set(0.839322 + (1 - 0.839322) * progress);\n }\n };\n\n const handleScrollThrottled = throttle(handleScroll); // Approx 60fps\n\n const target = scrollElement || window;\n\n target.addEventListener(\"scroll\", handleScrollThrottled);\n window.addEventListener(\"resize\", handleScrollThrottled);\n\n // Initial call to handleScroll to set initial state\n handleScroll();\n\n return () => {\n target.removeEventListener(\"scroll\", handleScrollThrottled);\n window.removeEventListener(\"resize\", handleScrollThrottled);\n };\n }\n }, [inViewProgress, opacity, scrollElement]);\n\n const backgroundPosition = useTransform(\n inViewProgress,\n [0, 1],\n [\n `conic-gradient(from 90deg at 90% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 150% no-repeat, conic-gradient(from 270deg at 10% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n `conic-gradient(from 90deg at 0% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 100% no-repeat, conic-gradient(from 270deg at 100% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n ]\n );\n const maskImageOpacity = useTransform(\n inViewProgress,\n [0, 1],\n [\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 50%)`,\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 95%)`,\n ]\n );\n\n const maskImage = maskLightByProgress\n ? maskImageOpacity\n : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;\n\n const combinedClassName = `react-light-beam ${className || \"\"}`.trim();\n\n // CRITICAL: MotionValues must be passed directly to motion.div style prop\n // Don't spread them into plain objects or reactivity breaks!\n const finalStyles = disableDefaultStyles\n ? {\n // No default styles, only motion values and user styles\n background: backgroundPosition,\n opacity: opacity,\n maskImage: maskImage,\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n ...style, // User styles override\n }\n : {\n // Merge default styles with motion values\n ...defaultStyles,\n background: backgroundPosition, // MotionValue (overrides default)\n opacity: opacity, // MotionValue (overrides default)\n maskImage: maskImage, // MotionValue or string\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n ...style, // User styles override everything\n };\n\n const motionProps: any = {\n style: finalStyles,\n ref: elementRef,\n className: combinedClassName,\n ...(id ? { id } : {}),\n };\n\n return <motion.div {...motionProps} />;\n};\n\nconst throttle = (func: Function) => {\n let ticking = false;\n return function (this: any, ...args: any[]) {\n if (!ticking) {\n requestAnimationFrame(() => {\n func.apply(this, args);\n ticking = false;\n });\n ticking = true;\n }\n };\n};\n"]}
package/dist/index.mjs CHANGED
@@ -92,25 +92,31 @@ var LightBeam = ({
92
92
  );
93
93
  const maskImage = maskLightByProgress ? maskImageOpacity : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;
94
94
  const combinedClassName = `react-light-beam ${className || ""}`.trim();
95
- const motionStyles = {
95
+ const finalStyles = disableDefaultStyles ? {
96
+ // No default styles, only motion values and user styles
96
97
  background: backgroundPosition,
97
98
  opacity,
98
99
  maskImage,
99
100
  WebkitMaskImage: maskImage,
100
- willChange: "background, opacity"
101
- };
102
- const mergedStyles = disableDefaultStyles ? {
103
- ...motionStyles,
101
+ willChange: "background, opacity",
104
102
  ...style
105
- // User styles override motion styles
103
+ // User styles override
106
104
  } : {
105
+ // Merge default styles with motion values
107
106
  ...defaultStyles,
108
- ...motionStyles,
107
+ background: backgroundPosition,
108
+ // MotionValue (overrides default)
109
+ opacity,
110
+ // MotionValue (overrides default)
111
+ maskImage,
112
+ // MotionValue or string
113
+ WebkitMaskImage: maskImage,
114
+ willChange: "background, opacity",
109
115
  ...style
110
116
  // User styles override everything
111
117
  };
112
118
  const motionProps = {
113
- style: mergedStyles,
119
+ style: finalStyles,
114
120
  ref: elementRef,
115
121
  className: combinedClassName,
116
122
  ...id ? { id } : {}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useDarkmode.tsx","../src/index.tsx"],"names":["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 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\n // Cleanup listener on unmount\n return () => {\n matchMedia.removeEventListener(\"change\", handleChange);\n };\n }, []);\n\n return { isDarkmode };\n};\n","\"use client\";\nimport { motion, useMotionValue, useTransform } from \"framer-motion\";\nimport React, { useEffect, useRef } from \"react\";\nimport { LightBeamProps } from \"../types/types\";\nimport { useIsDarkmode } from \"./hooks/useDarkmode\";\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 transition: \"var(--react-light-beam-transition, all 0.25s ease)\",\n willChange: \"all\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n WebkitTransition: \"var(--react-light-beam-transition, all 0.25s ease)\",\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\n invert = false,\n id = undefined,\n onLoaded = undefined,\n scrollElement,\n disableDefaultStyles = false,\n}: LightBeamProps) => {\n const elementRef = useRef<HTMLDivElement>(null);\n const inViewProgress = useMotionValue(0);\n const opacity = useMotionValue(0.839322);\n const { isDarkmode } = useIsDarkmode();\n const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;\n\n useEffect(() => {\n onLoaded && onLoaded();\n }, []);\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n const handleScroll = () => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Invert the fullWidth value: 1 becomes 0, and 0 becomes 1\n const adjustedFullWidth = 1 - fullWidth;\n\n // Calculate progress\n const progress = invert\n ? 0 +\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight))\n : 1 -\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight));\n\n // Update motion values\n inViewProgress.set(progress);\n opacity.set(0.839322 + (1 - 0.839322) * progress);\n }\n };\n\n const handleScrollThrottled = throttle(handleScroll); // Approx 60fps\n\n const target = scrollElement || window;\n\n target.addEventListener(\"scroll\", handleScrollThrottled);\n window.addEventListener(\"resize\", handleScrollThrottled);\n\n // Initial call to handleScroll to set initial state\n handleScroll();\n\n return () => {\n target.removeEventListener(\"scroll\", handleScrollThrottled);\n window.removeEventListener(\"resize\", handleScrollThrottled);\n };\n }\n }, [inViewProgress, opacity, scrollElement]);\n\n const backgroundPosition = useTransform(\n inViewProgress,\n [0, 1],\n [\n `conic-gradient(from 90deg at 90% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 150% no-repeat, conic-gradient(from 270deg at 10% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n `conic-gradient(from 90deg at 0% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 100% no-repeat, conic-gradient(from 270deg at 100% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n ]\n );\n const maskImageOpacity = useTransform(\n inViewProgress,\n [0, 1],\n [\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 50%)`,\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 95%)`,\n ]\n );\n\n const maskImage = maskLightByProgress\n ? maskImageOpacity\n : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;\n\n const combinedClassName = `react-light-beam ${className || \"\"}`.trim();\n\n // Motion-specific styles (always applied)\n const motionStyles = {\n background: backgroundPosition,\n opacity: opacity,\n maskImage: maskImage,\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n };\n\n // Merge styles in order of priority:\n // 1. Default styles (lowest)\n // 2. Motion styles (middle)\n // 3. User's style prop (highest - overrides everything)\n const mergedStyles = disableDefaultStyles\n ? {\n ...motionStyles,\n ...style, // User styles override motion styles\n }\n : {\n ...defaultStyles,\n ...motionStyles,\n ...style, // User styles override everything\n };\n\n const motionProps: any = {\n style: mergedStyles,\n ref: elementRef,\n className: combinedClassName,\n ...(id ? { id } : {}),\n };\n\n return <motion.div {...motionProps} />;\n};\n\nconst throttle = (func: Function) => {\n let ticking = false;\n return function (this: any, ...args: any[]) {\n if (!ticking) {\n requestAnimationFrame(() => {\n func.apply(this, args);\n ticking = false;\n });\n ticking = true;\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/hooks/useDarkmode.tsx","../src/index.tsx"],"names":["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 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\n // Cleanup listener on unmount\n return () => {\n matchMedia.removeEventListener(\"change\", handleChange);\n };\n }, []);\n\n return { isDarkmode };\n};\n","\"use client\";\nimport { motion, useMotionValue, useTransform } from \"framer-motion\";\nimport React, { useEffect, useRef } from \"react\";\nimport { LightBeamProps } from \"../types/types\";\nimport { useIsDarkmode } from \"./hooks/useDarkmode\";\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 transition: \"var(--react-light-beam-transition, all 0.25s ease)\",\n willChange: \"all\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n WebkitTransition: \"var(--react-light-beam-transition, all 0.25s ease)\",\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\n invert = false,\n id = undefined,\n onLoaded = undefined,\n scrollElement,\n disableDefaultStyles = false,\n}: LightBeamProps) => {\n const elementRef = useRef<HTMLDivElement>(null);\n const inViewProgress = useMotionValue(0);\n const opacity = useMotionValue(0.839322);\n const { isDarkmode } = useIsDarkmode();\n const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;\n\n useEffect(() => {\n onLoaded && onLoaded();\n }, []);\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n const handleScroll = () => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Invert the fullWidth value: 1 becomes 0, and 0 becomes 1\n const adjustedFullWidth = 1 - fullWidth;\n\n // Calculate progress\n const progress = invert\n ? 0 +\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight))\n : 1 -\n Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight));\n\n // Update motion values\n inViewProgress.set(progress);\n opacity.set(0.839322 + (1 - 0.839322) * progress);\n }\n };\n\n const handleScrollThrottled = throttle(handleScroll); // Approx 60fps\n\n const target = scrollElement || window;\n\n target.addEventListener(\"scroll\", handleScrollThrottled);\n window.addEventListener(\"resize\", handleScrollThrottled);\n\n // Initial call to handleScroll to set initial state\n handleScroll();\n\n return () => {\n target.removeEventListener(\"scroll\", handleScrollThrottled);\n window.removeEventListener(\"resize\", handleScrollThrottled);\n };\n }\n }, [inViewProgress, opacity, scrollElement]);\n\n const backgroundPosition = useTransform(\n inViewProgress,\n [0, 1],\n [\n `conic-gradient(from 90deg at 90% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 150% no-repeat, conic-gradient(from 270deg at 10% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n `conic-gradient(from 90deg at 0% 0%, ${chosenColor}, transparent 180deg) 0% 0% / 50% 100% no-repeat, conic-gradient(from 270deg at 100% 0%, transparent 180deg, ${chosenColor}) 100% 0% / 50% 100% no-repeat`,\n ]\n );\n const maskImageOpacity = useTransform(\n inViewProgress,\n [0, 1],\n [\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 50%)`,\n `linear-gradient(to bottom, ${chosenColor} 0%, transparent 95%)`,\n ]\n );\n\n const maskImage = maskLightByProgress\n ? maskImageOpacity\n : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;\n\n const combinedClassName = `react-light-beam ${className || \"\"}`.trim();\n\n // CRITICAL: MotionValues must be passed directly to motion.div style prop\n // Don't spread them into plain objects or reactivity breaks!\n const finalStyles = disableDefaultStyles\n ? {\n // No default styles, only motion values and user styles\n background: backgroundPosition,\n opacity: opacity,\n maskImage: maskImage,\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n ...style, // User styles override\n }\n : {\n // Merge default styles with motion values\n ...defaultStyles,\n background: backgroundPosition, // MotionValue (overrides default)\n opacity: opacity, // MotionValue (overrides default)\n maskImage: maskImage, // MotionValue or string\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n ...style, // User styles override everything\n };\n\n const motionProps: any = {\n style: finalStyles,\n ref: elementRef,\n className: combinedClassName,\n ...(id ? { id } : {}),\n };\n\n return <motion.div {...motionProps} />;\n};\n\nconst throttle = (func: Function) => {\n let ticking = false;\n return function (this: any, ...args: any[]) {\n if (!ticking) {\n requestAnimationFrame(() => {\n func.apply(this, args);\n ticking = false;\n });\n ticking = true;\n }\n };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stianlarsen/react-light-beam",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "A customizable React component that creates a light beam effect using conic gradients. Supports dark mode and various customization options.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",