@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 +14 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
105
|
+
// User styles override
|
|
108
106
|
} : {
|
|
107
|
+
// Merge default styles with motion values
|
|
109
108
|
...defaultStyles,
|
|
110
|
-
|
|
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:
|
|
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
|
|
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
|
|
103
|
+
// User styles override
|
|
106
104
|
} : {
|
|
105
|
+
// Merge default styles with motion values
|
|
107
106
|
...defaultStyles,
|
|
108
|
-
|
|
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:
|
|
119
|
+
style: finalStyles,
|
|
114
120
|
ref: elementRef,
|
|
115
121
|
className: combinedClassName,
|
|
116
122
|
...id ? { id } : {}
|
package/dist/index.mjs.map
CHANGED
|
@@ -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.
|
|
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",
|