@stianlarsen/react-light-beam 2.1.2 → 3.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/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -1,150 +1,56 @@
1
1
  # @stianlarsen/react-light-beam
2
2
 
3
- ## 🚀 v2.0 - Powered by GSAP!
3
+ ## 🚀 New Feature Alert!
4
4
 
5
- **Major upgrade!** LightBeam is now powered by **GSAP ScrollTrigger** for:
6
- - ⚡️ **40% faster** scroll performance
7
- - 🎯 **Pixel-perfect scrubbing** in both directions
8
- - 🔄 **Smoother animations** on all devices
9
- - 📦 **Lighter bundle** with tree-shaking
10
- - 🎨 **Live prop updates** without recreation
5
+ We've added a new prop: `scrollElement`. This allows you to specify which element should have the scroll listener attached, giving you greater flexibility in using the LightBeam component!
11
6
 
12
7
  [![npm version](https://badge.fury.io/js/%40stianlarsen%2Freact-light-beam.svg)](https://badge.fury.io/js/%40stianlarsen%2Freact-light-beam)
13
- [![Live Demo](https://img.shields.io/badge/demo-live-success)](https://your-demo-url.vercel.app)
14
8
 
15
- A high-performance React component that creates a scroll-triggered light beam effect using conic gradients. Fully responsive with automatic dark mode support. Perfect for hero sections, landing pages, and interactive storytelling.
16
-
17
- ## ✨ Key Features
18
-
19
- - 🚀 **Powered by GSAP** - Industry-leading animation performance
20
- - 📜 **Scroll-driven** - Smooth scrubbing with GSAP ScrollTrigger
21
- - 🌓 **Dark mode ready** - Auto-detects system preferences
22
- - ⚙️ **Highly customizable** - Control width, colors, direction, and more
23
- - 🎯 **Zero config** - Works out of the box with sensible defaults
24
- - 💪 **TypeScript** - Full type definitions included
25
- - 📦 **Tree-shakeable** - Optimized bundle size
9
+ A customizable React component that creates a light beam effect using conic gradients. The component is fully responsive and supports both light and dark modes. Ideal for adding dynamic and engaging visual elements to your web applications.
26
10
 
27
11
  ## Preview
28
12
 
29
- ![LightBeam Component](https://raw.githubusercontent.com/Stianlars1/react-light-beam/main/lightBeam.png)
13
+ ![LightBeam Component](https://github.com/Stianlars1/react-light-beam/blob/5422cdc60ae7ab6b52d644d452646bec7212f76f/lightBeam.png)
30
14
 
31
15
  _A preview of @stianlarsen/react-light-beam_
32
16
 
33
17
  ## Installation
34
18
 
35
19
  ```bash
36
- npm install @stianlarsen/react-light-beam gsap
20
+ npm install @stianlarsen/react-light-beam
37
21
  ```
38
22
 
39
- **Note:** GSAP is a peer dependency. If you don't have it already:
23
+ or
40
24
 
41
25
  ```bash
42
- npm install gsap @gsap/react
26
+ yarn add @stianlarsen/react-light-beam
43
27
  ```
44
28
 
45
29
  ## Usage
46
30
 
47
- ### Basic Usage (Works Immediately - No CSS Import!)
48
-
49
- The component works out of the box with default inline styles:
50
-
51
31
  ```jsx
52
32
  import { LightBeam } from "@stianlarsen/react-light-beam";
33
+ import "your-css-file.css"; // Include the necessary styles
53
34
 
54
35
  const App = () => {
55
36
  return (
56
37
  <div className="your-container-class">
57
38
  <LightBeam
39
+ id="unique-lightbeam"
40
+ className="your-lightbeam-class"
58
41
  colorDarkmode="rgba(255, 255, 255, 0.8)"
59
42
  colorLightmode="rgba(0, 0, 0, 0.2)"
60
43
  fullWidth={0.8}
61
44
  maskLightByProgress={true}
62
- scrollElement={window}
45
+ invert={false}
46
+ scrollElement={window} // New prop to specify scroll element
63
47
  />
64
48
  <YourContentHere />
65
49
  </div>
66
50
  );
67
51
  };
68
- ```
69
-
70
- ### Customizing Styles (Multiple Options!)
71
-
72
- #### Option 1: CSS Variables via className (Recommended!)
73
-
74
- Override default styles using CSS variables - works with className!
75
-
76
- ```jsx
77
- import { LightBeam } from "@stianlarsen/react-light-beam";
78
-
79
- const App = () => {
80
- return (
81
- <LightBeam
82
- className="custom-beam"
83
- colorDarkmode="rgba(255, 255, 255, 0.8)"
84
- />
85
- );
86
- };
87
- ```
88
-
89
- Then in your CSS:
90
52
 
91
- ```css
92
- .custom-beam {
93
- --react-light-beam-height: 800px;
94
- --react-light-beam-width: 80vw;
95
- /* Note: GSAP controls animations - transitions may not work as expected */
96
- }
97
- ```
98
-
99
- **Available CSS Variables:**
100
- - `--react-light-beam-height` (default: `500px`)
101
- - `--react-light-beam-width` (default: `100vw`)
102
-
103
- **Note:** CSS transitions are disabled by default to prevent conflicts with GSAP. GSAP handles all animations for optimal performance.
104
-
105
- #### Option 2: Inline Styles via `style` prop
106
-
107
- ```jsx
108
- <LightBeam
109
- style={{
110
- height: '800px',
111
- width: '80vw',
112
- marginTop: '-200px'
113
- }}
114
- colorDarkmode="rgba(255, 255, 255, 0.8)"
115
- />
116
- ```
117
-
118
- ### Advanced: Full CSS Control (className only)
119
-
120
- For complete control via CSS, disable default inline styles:
121
-
122
- ```jsx
123
- import { LightBeam } from "@stianlarsen/react-light-beam";
124
-
125
- const App = () => {
126
- return (
127
- <LightBeam
128
- disableDefaultStyles={true} // Disable all inline styles
129
- className="my-custom-lightbeam"
130
- colorDarkmode="rgba(255, 255, 255, 0.8)"
131
- />
132
- );
133
- };
134
- ```
135
-
136
- Then provide all styles via CSS:
137
-
138
- ```css
139
- .my-custom-lightbeam {
140
- height: 800px;
141
- width: 100%;
142
- position: absolute;
143
- transition: all 0.3s ease;
144
- user-select: none;
145
- pointer-events: none;
146
- /* Full control - you provide all styles */
147
- }
53
+ export default App;
148
54
  ```
149
55
 
150
56
  ### Props
@@ -153,37 +59,28 @@ Then provide all styles via CSS:
153
59
  | --------------------- | ---------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
154
60
  | `id` | `string` | `undefined` | Optional string representing a unique ID for the LightBeam container. |
155
61
  | `className` | `string` | `undefined` | Optional string representing custom classes to be added to the LightBeam container. |
156
- | `style` | `React.CSSProperties` | `undefined` | Custom inline styles to merge with or override default styles. User styles take priority. Example: `style={{ height: '800px', width: '80vw' }}` |
157
62
  | `colorLightmode` | `string` | `rgba(0,0,0, 0.5)` | Optional string representing the color of the light beam in light mode. |
158
63
  | `colorDarkmode` | `string` | `rgba(255, 255, 255, 0.5)` | Optional string representing the color of the light beam in dark mode. |
159
64
  | `fullWidth` | `number` | `1.0` | Optional number between `0` and `1` representing the maximum width the light beam can reach. |
160
65
  | `maskLightByProgress` | `boolean` | `false` | If `true`, the `mask-image`'s linear gradient will start with the chosen color at 0% and the transparent part starting at 50%. As the user scrolls, it will dynamically change to have the transparent part at 95%, reducing the glow effect. If `false`, it will default to `linear-gradient(to bottom, chosenColor 25%, transparent 95%)`. |
161
66
  | `invert` | `boolean` | `false` | Optional boolean to invert the scroll progress calculation. |
162
- | `scrollElement` | `EventTarget` or `undefined` | `document.body` | Optional prop for which element to attach the scroll listener to. Defaults to `document.body` (the `<body>` element). Can be set to `document.documentElement`, `window`, or any scrollable element. |
67
+ | `scrollElement` | `EventTarget` or `undefined` | `window` | Optional prop for which element to attach the scroll listener to. This could be the `window`, `document.body`, or any other scrollable element. |
163
68
  | `onLoaded` | `undefined or () => void` | `undefined` | Optional function to run when the component has mounted |
164
- | `disableDefaultStyles` | `boolean` | `false` | Disable default inline styles. Set to `true` if you want to provide all styles yourself via className. Gives you complete CSS control without any default styling. |
165
69
 
166
70
  ### Default Configuration
167
71
 
168
- The component includes **inline styles with CSS variables** (no CSS import needed, easy to customize!):
169
-
170
- ```javascript
171
- {
172
- height: "var(--react-light-beam-height, 500px)",
173
- width: "var(--react-light-beam-width, 100vw)",
174
- transition: "none", // GSAP handles animations
175
- willChange: "background, opacity",
176
- userSelect: "none",
177
- pointerEvents: "none",
178
- contain: "layout style paint" // Performance optimization
72
+ The component comes with the following default styles:
73
+
74
+ ```css
75
+ .react__light__beam {
76
+ height: 500px;
77
+ width: 100vw;
78
+ transition: all 0.5s ease;
79
+ will-change: auto;
179
80
  }
180
81
  ```
181
82
 
182
- **Benefits:**
183
- - ✅ Works immediately out of the box
184
- - ✅ Easy to customize via className (just set CSS variables!)
185
- - ✅ No CSS import required for basic usage
186
- - ✅ Inline styles use CSS variables, so className overrides work perfectly
83
+ These default styles ensure that the component is immediately visible when added to your application. However, for more effective use, you might want to customize its position and behavior.
187
84
 
188
85
  ### Recommended Usage
189
86
 
@@ -234,103 +131,6 @@ The component automatically adjusts between light and dark modes based on the us
234
131
  />
235
132
  ```
236
133
 
237
- ## 🌐 Hosting the Example/Demo
238
-
239
- The example Next.js app in `/example` can be easily deployed to Vercel, Netlify, or GitHub Pages:
240
-
241
- ### Quick Deploy to Vercel (Recommended - 2 minutes)
242
-
243
- 1. Push your code to GitHub
244
- 2. Go to [vercel.com](https://vercel.com)
245
- 3. Click "Add New Project"
246
- 4. Import your GitHub repository
247
- 5. Set **Root Directory** to `example`
248
- 6. Click "Deploy"
249
-
250
- Done! You'll get a live URL like `https://your-project.vercel.app`
251
-
252
- ### Alternative: GitHub Pages with GitHub Actions
253
-
254
- 1. Add `.github/workflows/deploy.yml`:
255
-
256
- ```yaml
257
- name: Deploy to GitHub Pages
258
-
259
- on:
260
- push:
261
- branches: [ main ]
262
-
263
- jobs:
264
- deploy:
265
- runs-on: ubuntu-latest
266
- steps:
267
- - uses: actions/checkout@v3
268
- - uses: actions/setup-node@v3
269
- with:
270
- node-version: 18
271
- - run: cd example && npm install && npm run build
272
- - uses: peaceiris/actions-gh-pages@v3
273
- with:
274
- github_token: ${{ secrets.GITHUB_TOKEN }}
275
- publish_dir: ./example/out
276
- ```
277
-
278
- 2. In `example/next.config.js`, add:
279
- ```js
280
- /** @type {import('next').NextConfig} */
281
- const nextConfig = {
282
- output: 'export',
283
- basePath: '/react-light-beam', // Your repo name
284
- }
285
- module.exports = nextConfig
286
- ```
287
-
288
- 3. Push to GitHub - your site will auto-deploy to `https://yourusername.github.io/react-light-beam`
289
-
290
- ### Alternative: Netlify
291
-
292
- 1. Go to [netlify.com](https://netlify.com)
293
- 2. Drag and drop your `/example` folder
294
- 3. Or connect to GitHub and set base directory to `example`
295
-
296
- ## 🤝 Contributing
297
-
298
- Contributions are welcome! Please feel free to submit a Pull Request.
299
-
300
- ### Development Setup
301
-
302
- ```bash
303
- # Clone the repo
304
- git clone https://github.com/stianalars1/react-light-beam.git
305
- cd react-light-beam
306
-
307
- # Install dependencies
308
- npm install
309
-
310
- # Build the package
311
- npm run build
312
-
313
- # Run the example
314
- cd example
315
- npm install
316
- npm run dev
317
- ```
318
-
319
- ## 📝 Changelog
320
-
321
- ### v2.0.0 (2026-01-04)
322
- - 🚀 **BREAKING:** Migrated from Framer Motion to GSAP ScrollTrigger
323
- - ⚡️ 40% performance improvement
324
- - 🐛 Fixed bidirectional scrolling issues
325
- - 🐛 Fixed invert prop behavior
326
- - 🐛 Fixed color switching glitches
327
- - 🎨 Removed CSS transitions to prevent conflicts with GSAP
328
- - 📦 Added `gsap` as peer dependency
329
-
330
- ## License
134
+ ### License
331
135
 
332
136
  MIT © [Stian Larsen](https://github.com/stianlarsen)
333
-
334
- ---
335
-
336
- **Built with ❤️ using GSAP ScrollTrigger**
package/dist/index.cjs ADDED
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.tsx
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ LightBeam: () => LightBeam
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var import_framer_motion = require("framer-motion");
28
+ var import_react2 = require("react");
29
+
30
+ // src/css/lightBeam.module.css
31
+ var lightBeam_default = {
32
+ react__light__beam: "lightBeam_react__light__beam"
33
+ };
34
+
35
+ // src/hooks/useDarkmode.tsx
36
+ var import_react = require("react");
37
+ var useIsDarkmode = () => {
38
+ const [isDarkmode, setIsDarkmodeActive] = (0, import_react.useState)(false);
39
+ (0, import_react.useEffect)(() => {
40
+ const matchMedia = window.matchMedia("(prefers-color-scheme: dark)");
41
+ const handleChange = () => {
42
+ setIsDarkmodeActive(matchMedia.matches);
43
+ };
44
+ setIsDarkmodeActive(matchMedia.matches);
45
+ matchMedia.addEventListener("change", handleChange);
46
+ return () => {
47
+ matchMedia.removeEventListener("change", handleChange);
48
+ };
49
+ }, []);
50
+ return { isDarkmode };
51
+ };
52
+
53
+ // src/index.tsx
54
+ var import_jsx_runtime = require("react/jsx-runtime");
55
+ var LightBeam = ({
56
+ className,
57
+ colorLightmode = "rgba(0,0,0, 0.5)",
58
+ colorDarkmode = "rgba(255, 255, 255, 0.5)",
59
+ maskLightByProgress = false,
60
+ fullWidth = 1,
61
+ // Default to full width
62
+ invert = false,
63
+ id = void 0,
64
+ onLoaded = void 0,
65
+ scrollElement
66
+ // Add this line
67
+ }) => {
68
+ const elementRef = (0, import_react2.useRef)(null);
69
+ const inViewProgress = (0, import_framer_motion.useMotionValue)(0);
70
+ const opacity = (0, import_framer_motion.useMotionValue)(0.839322);
71
+ const { isDarkmode } = useIsDarkmode();
72
+ const chosenColor = isDarkmode ? colorDarkmode : colorLightmode;
73
+ (0, import_react2.useEffect)(() => {
74
+ onLoaded && onLoaded();
75
+ }, []);
76
+ (0, import_react2.useEffect)(() => {
77
+ if (typeof window !== "undefined") {
78
+ const handleScroll = () => {
79
+ if (elementRef.current) {
80
+ const rect = elementRef.current.getBoundingClientRect();
81
+ const windowHeight = window.innerHeight;
82
+ const adjustedFullWidth = 1 - fullWidth;
83
+ const progress = invert ? 0 + Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight)) : 1 - Math.max(adjustedFullWidth, Math.min(1, rect.top / windowHeight));
84
+ inViewProgress.set(progress);
85
+ opacity.set(0.839322 + (1 - 0.839322) * progress);
86
+ }
87
+ };
88
+ const handleScrollThrottled = throttle(handleScroll);
89
+ const target = scrollElement || window;
90
+ target.addEventListener("scroll", handleScrollThrottled);
91
+ window.addEventListener("resize", handleScrollThrottled);
92
+ handleScroll();
93
+ return () => {
94
+ target.removeEventListener("scroll", handleScrollThrottled);
95
+ window.removeEventListener("resize", handleScrollThrottled);
96
+ };
97
+ }
98
+ }, [inViewProgress, opacity, scrollElement]);
99
+ const backgroundPosition = (0, import_framer_motion.useTransform)(
100
+ inViewProgress,
101
+ [0, 1],
102
+ [
103
+ `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`,
104
+ `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`
105
+ ]
106
+ );
107
+ const maskImageOpacity = (0, import_framer_motion.useTransform)(
108
+ inViewProgress,
109
+ [0, 1],
110
+ [
111
+ `linear-gradient(to bottom, ${chosenColor} 0%, transparent 50%)`,
112
+ `linear-gradient(to bottom, ${chosenColor} 0%, transparent 95%)`
113
+ ]
114
+ );
115
+ const maskImage = maskLightByProgress ? maskImageOpacity : `linear-gradient(to bottom, ${chosenColor} 25%, transparent 95%)`;
116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
117
+ import_framer_motion.motion.div,
118
+ {
119
+ style: {
120
+ background: backgroundPosition,
121
+ opacity,
122
+ maskImage,
123
+ WebkitMaskImage: maskImage,
124
+ willChange: "background, opacity"
125
+ },
126
+ ref: elementRef,
127
+ id,
128
+ className: `lightBeam ${className} ${lightBeam_default.react__light__beam}`
129
+ }
130
+ );
131
+ };
132
+ var throttle = (func) => {
133
+ let ticking = false;
134
+ return function(...args) {
135
+ if (!ticking) {
136
+ requestAnimationFrame(() => {
137
+ func.apply(this, args);
138
+ ticking = false;
139
+ });
140
+ ticking = true;
141
+ }
142
+ };
143
+ };
144
+ // Annotate the CommonJS export names for ESM import in node:
145
+ 0 && (module.exports = {
146
+ LightBeam
147
+ });
148
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx","../src/css/lightBeam.module.css","../src/hooks/useDarkmode.tsx"],"sourcesContent":["\"use client\";\nimport { motion, useMotionValue, useTransform } from \"framer-motion\";\nimport React, { useEffect, useRef } from \"react\";\nimport { LightBeamProps } from \"../types/types\";\nexport type { LightBeamProps } from \"../types/types\";\nimport styles from \"./css/lightBeam.module.css\";\nimport { useIsDarkmode } from \"./hooks/useDarkmode\";\n\nexport const LightBeam = ({\n className,\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, // Add this line\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 return (\n <motion.div\n style={{\n background: backgroundPosition,\n opacity: opacity,\n maskImage: maskImage,\n WebkitMaskImage: maskImage,\n willChange: \"background, opacity\",\n }}\n ref={elementRef}\n id={id}\n className={`lightBeam ${className} ${styles.react__light__beam}`}\n />\n );\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",".react__light__beam {\n height: 500px;\n width: 100vw;\n transition: all 0.25s ease;\n will-change: all;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n pointer-events: none;\n -webkit-transition: all 0.25s ease;\n}/*# sourceMappingURL=lightBeam.module.css.map */","\"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"],"mappings":"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","names":["import_react","react__light__beam"]}
package/dist/index.css ADDED
@@ -0,0 +1,13 @@
1
+ /* src/css/lightBeam.module.css */
2
+ .lightBeam_react__light__beam {
3
+ height: 500px;
4
+ width: 100vw;
5
+ transition: all 0.25s ease;
6
+ will-change: all;
7
+ -webkit-user-select: none;
8
+ -moz-user-select: none;
9
+ user-select: none;
10
+ pointer-events: none;
11
+ -webkit-transition: all 0.25s ease;
12
+ }
13
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/css/lightBeam.module.scss","../src/css/lightBeam.module.css"],"sourcesContent":[".react__light__beam {\n height: 500px;\n width: 100vw;\n transition: all 0.25s ease;\n will-change: all;\n user-select: none;\n pointer-events: none;\n -webkit-transition: all 0.25s ease;\n}\n",".react__light__beam {\n height: 500px;\n width: 100vw;\n transition: all 0.25s ease;\n will-change: all;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n pointer-events: none;\n -webkit-transition: all 0.25s ease;\n}/*# sourceMappingURL=lightBeam.module.css.map */"],"mappings":";AAAA,CAAAA;AACE,UAAA;AACA,SAAA;AACA,cAAA,IAAA,MAAA;AACA,eAAA;AACA,uBAAA;AAAA,oBAAA;AAAA,eAAA;AACA,kBAAA;AACA,sBAAA,IAAA,MAAA;ACCF;","names":["react__light__beam"]}
@@ -0,0 +1,17 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type LightBeamProps = {
4
+ className?: string;
5
+ fullWidth?: number;
6
+ colorLightmode?: string;
7
+ colorDarkmode?: string;
8
+ maskLightByProgress?: boolean;
9
+ invert?: boolean;
10
+ id?: string;
11
+ scrollElement?: EventTarget;
12
+ onLoaded?: () => void;
13
+ };
14
+
15
+ declare const LightBeam: ({ className, colorLightmode, colorDarkmode, maskLightByProgress, fullWidth, invert, id, onLoaded, scrollElement, }: LightBeamProps) => react_jsx_runtime.JSX.Element;
16
+
17
+ export { LightBeam, type LightBeamProps };
package/dist/index.d.ts CHANGED
@@ -2,12 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
3
  type LightBeamProps = {
4
4
  className?: string;
5
- /**
6
- * Custom styles to merge with or override default styles.
7
- * User styles take priority over defaults.
8
- * @example style={{ height: '800px', width: '80vw' }}
9
- */
10
- style?: React.CSSProperties;
11
5
  fullWidth?: number;
12
6
  colorLightmode?: string;
13
7
  colorDarkmode?: string;
@@ -16,13 +10,8 @@ type LightBeamProps = {
16
10
  id?: string;
17
11
  scrollElement?: EventTarget;
18
12
  onLoaded?: () => void;
19
- /**
20
- * Disable default inline styles. Set to true if you want to provide custom CSS via className only.
21
- * @default false
22
- */
23
- disableDefaultStyles?: boolean;
24
13
  };
25
14
 
26
- declare const LightBeam: ({ className, style, colorLightmode, colorDarkmode, maskLightByProgress, fullWidth, invert, id, onLoaded, scrollElement, disableDefaultStyles, }: LightBeamProps) => react_jsx_runtime.JSX.Element;
15
+ declare const LightBeam: ({ className, colorLightmode, colorDarkmode, maskLightByProgress, fullWidth, invert, id, onLoaded, scrollElement, }: LightBeamProps) => react_jsx_runtime.JSX.Element;
27
16
 
28
- export { LightBeam };
17
+ export { LightBeam, type LightBeamProps };