jl-particle-interactive 0.2.1 → 0.3.0

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/README.md CHANGED
@@ -86,114 +86,175 @@ export default function App() {
86
86
 
87
87
  ---
88
88
 
89
- ## Examples
89
+ ## Text examples
90
90
 
91
- ### Text with a color palette
91
+ ### 1. Free-floating particles
92
92
 
93
- Assign multiple colors and each particle picks one at random.
93
+ When `text` is an empty string, particles scatter and drift freely across the canvas — great for ambient loading screens or decorative backgrounds.
94
94
 
95
95
  ```tsx
96
- <ParticleCanvas height="60vh">
97
- <TextParticleEngine
98
- text="React"
99
- particleColor={['#ff6b6b', '#feca57', '#48dbfb']}
100
- particleSize={1.5}
101
- />
102
- </ParticleCanvas>
96
+ import { ParticleCanvas, TextParticleEngine } from 'jl-particle-interactive';
97
+
98
+ export default function FloatingParticles() {
99
+ return (
100
+ <ParticleCanvas height="60vh" backgroundColor="#050505">
101
+ <TextParticleEngine
102
+ text=""
103
+ particleColor={['#60a5fa', '#a78bfa', '#34d399']}
104
+ particleSize={1.2}
105
+ isMagnet={true}
106
+ />
107
+ </ParticleCanvas>
108
+ );
109
+ }
103
110
  ```
104
111
 
105
112
  ---
106
113
 
107
- ### Repel on click
114
+ ### 2. Hello 🖐️ — magnetic hover + color palette
108
115
 
109
- Particles flee from the cursor while the mouse button is held down.
116
+ Particles form the text and spring toward the cursor on hover. Click and hold to repel them outward.
110
117
 
111
118
  ```tsx
112
- <ParticleCanvas height="60vh">
113
- <TextParticleEngine
114
- text="Boom"
115
- clickMode="repel"
116
- particleEase={2}
117
- />
118
- </ParticleCanvas>
119
+ import { ParticleCanvas, TextParticleEngine } from 'jl-particle-interactive';
120
+
121
+ export default function HelloParticles() {
122
+ return (
123
+ <ParticleCanvas height="60vh" backgroundColor="#050505">
124
+ <TextParticleEngine
125
+ text="Hello 🖐️"
126
+ particleColor={['#f472b6', '#fb923c', '#facc15', '#34d399', '#60a5fa']}
127
+ particleSize={1.3}
128
+ particleEase={1.2}
129
+ isMagnet={true}
130
+ clickMode="repel"
131
+ particleShape="circle"
132
+ />
133
+ </ParticleCanvas>
134
+ );
135
+ }
119
136
  ```
120
137
 
121
138
  ---
122
139
 
123
- ### Attract on click
140
+ ### 3. Word carousel — cycles every 3 seconds
124
141
 
125
- The opposite particles swarm toward the cursor on press.
142
+ The particles re-form automatically each time the `text` prop changes. No extra animation code needed.
126
143
 
127
144
  ```tsx
128
- <ParticleCanvas height="60vh">
129
- <TextParticleEngine
130
- text="Pull"
131
- clickMode="attract"
132
- isMagnet={false}
133
- />
134
- </ParticleCanvas>
145
+ import { useEffect, useState } from 'react';
146
+ import { ParticleCanvas, TextParticleEngine } from 'jl-particle-interactive';
147
+
148
+ const words = ['Create', 'Inspire', 'React'];
149
+
150
+ export default function WordCarousel() {
151
+ const [index, setIndex] = useState(0);
152
+
153
+ useEffect(() => {
154
+ const id = setInterval(() => setIndex(i => (i + 1) % words.length), 3000);
155
+ return () => clearInterval(id);
156
+ }, []);
157
+
158
+ return (
159
+ <ParticleCanvas height="60vh" backgroundColor="#050505">
160
+ <TextParticleEngine
161
+ text={words[index]}
162
+ particleColor={['#60a5fa', '#a78bfa', '#f472b6']}
163
+ particleSize={1.5}
164
+ particleEase={1.2}
165
+ isMagnet={true}
166
+ particleShape="bean"
167
+ />
168
+ </ParticleCanvas>
169
+ );
170
+ }
135
171
  ```
136
172
 
137
173
  ---
138
174
 
139
- ### Animated NET background
175
+ ## Background examples
176
+
177
+ Use `<ParticleBackground>` for standalone animated backgrounds. Set the mode with the `name` prop and pass all options through `config`.
140
178
 
141
- A connected particle network moves behind your content.
179
+ ### 1. FOLLOW_POINTER swarm that follows the cursor
180
+
181
+ Particles form a loose swarm that chases the cursor across the canvas.
142
182
 
143
183
  ```tsx
144
- <ParticleCanvas
145
- height="80vh"
146
- background={{
147
- name: 'NET',
148
- color: '#4ecdc4',
149
- lineDistance: 120,
150
- density: 0.8,
151
- }}
152
- >
153
- <TextParticleEngine text="Network" particleColor="#ffffff" />
154
- </ParticleCanvas>
184
+ import { ParticleBackground } from 'jl-particle-interactive';
185
+
186
+ export default function FollowPointerDemo() {
187
+ return (
188
+ <ParticleBackground
189
+ name="FOLLOW_POINTER"
190
+ height="60vh"
191
+ backgroundColor="#050505"
192
+ config={{
193
+ orientation: 'diagonal',
194
+ density: 1,
195
+ shape: 'bean',
196
+ colors: ['#00d4ff', '#6ee7b7', '#facc15'],
197
+ colorMode: 'wave',
198
+ particleSpeed: 1,
199
+ pointerTrackingSpeed: 0.06,
200
+ }}
201
+ />
202
+ );
203
+ }
155
204
  ```
156
205
 
157
206
  ---
158
207
 
159
- ### Jellyfish background
208
+ ### 2. NET — connected node graph
160
209
 
161
- Smooth, organic blobs that drift across the canvas.
210
+ Particles bounce around and draw lines between nearby nodes. Great for tech-style hero sections.
162
211
 
163
212
  ```tsx
164
- <ParticleCanvas
165
- height="80vh"
166
- background={{
167
- name: 'JELLYFISH',
168
- colors: ['#ff6b6b', '#a29bfe', '#00cec9'],
169
- colorMode: 'wave',
170
- }}
171
- >
172
- <TextParticleEngine text="Fluid" particleColor="#ffffff" />
173
- </ParticleCanvas>
213
+ import { ParticleBackground } from 'jl-particle-interactive';
214
+
215
+ export default function NetDemo() {
216
+ return (
217
+ <ParticleBackground
218
+ name="NET"
219
+ height="60vh"
220
+ backgroundColor="#050505"
221
+ config={{
222
+ density: 0.9,
223
+ shape: 'circle',
224
+ colors: ['#7dd3fc', '#60a5fa', '#a78bfa'],
225
+ colorMode: 'mixed',
226
+ particleSpeed: 1,
227
+ pointerTrackingSpeed: 0.08,
228
+ }}
229
+ />
230
+ );
231
+ }
174
232
  ```
175
233
 
176
234
  ---
177
235
 
178
- ### Dynamic text
236
+ ### 3. JELLYFISH — organic pulsing glow
179
237
 
180
- Change the `text` prop and the particles re-form automatically.
238
+ Soft concentric rings expand and contract in a slow breathing cycle. Particles drift with organic float noise.
181
239
 
182
240
  ```tsx
183
- const words = ['Hello', 'World', 'React'];
184
-
185
- export default function Carousel() {
186
- const [index, setIndex] = useState(0);
187
-
188
- useEffect(() => {
189
- const id = setInterval(() => setIndex(i => (i + 1) % words.length), 2000);
190
- return () => clearInterval(id);
191
- }, []);
241
+ import { ParticleBackground } from 'jl-particle-interactive';
192
242
 
243
+ export default function JellyfishDemo() {
193
244
  return (
194
- <ParticleCanvas height="60vh">
195
- <TextParticleEngine text={words[index]} />
196
- </ParticleCanvas>
245
+ <ParticleBackground
246
+ name="JELLYFISH"
247
+ height="60vh"
248
+ backgroundColor="#050505"
249
+ config={{
250
+ density: 1.1,
251
+ shape: 'circle',
252
+ colors: ['#f472b6', '#a78bfa', '#22d3ee'],
253
+ colorMode: 'wave',
254
+ particleSpeed: 1,
255
+ pointerTrackingSpeed: 0.02,
256
+ }}
257
+ />
197
258
  );
198
259
  }
199
260
  ```
@@ -202,14 +263,48 @@ export default function Carousel() {
202
263
 
203
264
  ## API reference
204
265
 
266
+ ### `<ParticleBackground>`
267
+
268
+ Standalone background component. Use this when you want an animated background without any text particles.
269
+
270
+ | Prop | Type | Default | Description |
271
+ |---|---|---|---|
272
+ | `name` | `'NONE' \| 'FOLLOW_POINTER' \| 'NET' \| 'JELLYFISH'` | **required** | Background engine to render |
273
+ | `config` | `BackgroundConfig` | `undefined` | All engine options (see table below) |
274
+ | `width` | `string \| number` | `'100%'` | Container width |
275
+ | `height` | `string \| number` | `'60vh'` | Container height |
276
+ | `backgroundColor` | `string` | `'#050505'` | Background fill color |
277
+ | `className` | `string` | `''` | Additional CSS class |
278
+ | `style` | `CSSProperties` | — | Inline style overrides |
279
+
280
+ ### `BackgroundConfig` (`config` prop options)
281
+
282
+ All fields are optional. Pass any combination inside the `config` prop of `<ParticleBackground>`.
283
+
284
+ | Option | Type | Applies to | Description |
285
+ |---|---|---|---|
286
+ | `density` | `number` | all modes | Particle count multiplier. Base counts: FOLLOW_POINTER=350, NET≈300, JELLYFISH=350 |
287
+ | `color` | `string` | all modes | Single hex color for all particles |
288
+ | `colors` | `string[]` | all modes | Palette of hex colors; overrides `color` |
289
+ | `colorMode` | `'wave' \| 'mixed'` | all modes | How colors propagate across particles |
290
+ | `shape` | `'circle' \| 'square' \| 'bean'` | all modes | Particle drawing shape |
291
+ | `particleSpeed` | `number` | all modes | Animation speed multiplier |
292
+ | `pointerTrackingSpeed` | `number` | all modes | How fast particles follow the cursor (lower = floatier) |
293
+ | `orientation` | `'vertical' \| 'horizontal' \| 'diagonal'` | FOLLOW_POINTER only | Swarm drift direction |
294
+ | `interactionRadius` | `number` | — | Declared in type; not applied in current version |
295
+ | `lineDistance` | `number` | — | Declared in type; not applied in current version |
296
+
205
297
  ### `<ParticleCanvas>`
206
298
 
299
+ Container that combines text particles with an optional background. Use `background` to activate a background engine alongside `<TextParticleEngine>` children.
300
+
207
301
  | Prop | Type | Default | Description |
208
302
  |---|---|---|---|
303
+ | `children` | `ReactNode` | — | Content rendered above background (z-index 10) |
209
304
  | `width` | `string \| number` | `'100%'` | Container width |
210
305
  | `height` | `string \| number` | `'60vh'` | Container height |
211
- | `backgroundColor` | `string` | `'#050505'` | Background color |
212
- | `background` | `BackgroundCanvas` | `{ name: 'NONE' }` | Animated background config |
306
+ | `backgroundColor` | `string` | `'#050505'` | Background fill color |
307
+ | `background` | `BackgroundCanvas` | `{ name: 'NONE' }` | Background engine config (flat object with `name` + all options) |
213
308
  | `className` | `string` | `''` | Additional CSS class |
214
309
  | `style` | `CSSProperties` | — | Inline style overrides |
215
310
 
@@ -0,0 +1,12 @@
1
+ import { CSSProperties } from 'react';
2
+ import { BackgroundModeName, BackgroundCanvas } from '../../types/background';
3
+ export interface ParticleBackgroundProps {
4
+ name: BackgroundModeName;
5
+ config?: Omit<BackgroundCanvas, 'name'>;
6
+ width?: string | number;
7
+ height?: string | number;
8
+ backgroundColor?: string;
9
+ className?: string;
10
+ style?: CSSProperties;
11
+ }
12
+ export default function ParticleBackground({ name, config, width, height, backgroundColor, className, style, }: ParticleBackgroundProps): import("react/jsx-runtime").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export { default as ParticleCanvas } from './components/ParticleCanvas';
2
2
  export type { ParticleCanvasProps } from './components/ParticleCanvas';
3
3
  export { default as TextParticleEngine } from './components/text/TextParticleEngine';
4
4
  export type { TextParticleEngineProps } from './components/text/TextParticleEngine';
5
+ export { default as ParticleBackground } from './components/background/ParticleBackground';
6
+ export type { ParticleBackgroundProps } from './components/background/ParticleBackground';
5
7
  export { useParticleInteraction, getMagnetTarget } from './hooks/useParticleInteraction';
6
8
  export type { ClickMode } from './hooks/useParticleInteraction';
7
9
  export { useTextParticles } from './hooks/text/useTextParticles';
@@ -1,30 +1,30 @@
1
1
  var J = Object.defineProperty;
2
2
  var K = (t, e, n) => e in t ? J(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
3
- var g = (t, e, n) => K(t, typeof e != "symbol" ? e + "" : e, n);
3
+ var m = (t, e, n) => K(t, typeof e != "symbol" ? e + "" : e, n);
4
4
  import { jsx as $, jsxs as _ } from "react/jsx-runtime";
5
5
  import { useRef as I, useEffect as L } from "react";
6
6
  function U(t, e, n, i) {
7
- let s = e + t.baseX, m = n + t.baseY;
8
- s += Math.sin(i * t.randomSpeed + t.baseY * 0.05) * 15 * t.z, m += Math.cos(i * t.randomSpeed + t.baseX * 0.05) * 15 * t.z;
9
- const r = s - t.x, o = m - t.y, h = r * 0.06, y = o * 0.06;
10
- return { forceX: h, forceY: y };
7
+ let s = e + t.baseX, y = n + t.baseY;
8
+ s += Math.sin(i * t.randomSpeed + t.baseY * 0.05) * 15 * t.z, y += Math.cos(i * t.randomSpeed + t.baseX * 0.05) * 15 * t.z;
9
+ const r = s - t.x, o = y - t.y, h = r * 0.06, g = o * 0.06;
10
+ return { forceX: h, forceY: g };
11
11
  }
12
- function Q(t, e, n, i, s, m) {
13
- const r = i, o = s, h = t.x - r, y = t.y - o, d = Math.max(Math.sqrt(h * h + y * y), 1);
12
+ function Q(t, e, n, i, s, y) {
13
+ const r = i, o = s, h = t.x - r, g = t.y - o, d = Math.max(Math.sqrt(h * h + g * g), 1);
14
14
  let c = 0, a = 0;
15
- const u = Math.sin(d * 0.02 - m * 3) * 2.5 * t.z;
16
- c += h / d * u, a += y / d * u;
17
- const P = Math.cos(d * 0.01 - m * 1 + t.randomSpeed) * 0.8 * t.z, q = -y / d, b = h / d;
18
- return c += q * P, a += b * P, { forceX: c, forceY: a, dxCenter: h, dyCenter: y, distToCenter: d };
15
+ const u = Math.sin(d * 0.02 - y * 3) * 2.5 * t.z;
16
+ c += h / d * u, a += g / d * u;
17
+ const P = Math.cos(d * 0.01 - y * 1 + t.randomSpeed) * 0.8 * t.z, q = -g / d, b = h / d;
18
+ return c += q * P, a += b * P, { forceX: c, forceY: a, dxCenter: h, dyCenter: g, distToCenter: d };
19
19
  }
20
20
  function V(t, e) {
21
21
  let s = Math.min(e / 400, 1) * 2.5 + t.sizeBias * 1;
22
22
  s < 0.4 && (s = 0), t.scale += (s - t.scale) * 0.15;
23
23
  }
24
- function Z(t, e, n, i, s, m) {
24
+ function Z(t, e, n, i, s, y) {
25
25
  let r = 0, o = 0;
26
26
  s === "horizontal" ? (r = 1, o = 0) : s === "diagonal" ? (r = -e / i, o = -n / i) : (r = -n / i, o = e / i);
27
- const h = Math.atan2(o, r), y = t.sizeBias > 0.3 ? 1 : 0, d = Math.max(0, Math.sin(m * 0.5 + t.randomSpeed * 10)), c = Math.sin(m * 3 + t.baseX * 0.1 + t.randomSpeed) * 0.5 * d * y;
27
+ const h = Math.atan2(o, r), g = t.sizeBias > 0.3 ? 1 : 0, d = Math.max(0, Math.sin(y * 0.5 + t.randomSpeed * 10)), c = Math.sin(y * 3 + t.baseX * 0.1 + t.randomSpeed) * 0.5 * d * g;
28
28
  r = Math.cos(h + c), o = Math.sin(h + c);
29
29
  const a = Math.max(1 - i / 400, 0.1);
30
30
  s === "horizontal" ? (t.dirX = t.dirX * (1 - 0.2) + r * 0.2, t.dirY = t.dirY * (1 - 0.2) + o * 0.2) : (t.dirX = t.dirX * (1 - a * 0.3) + r * a * 0.3, t.dirY = t.dirY * (1 - a * 0.3) + o * a * 0.3);
@@ -33,31 +33,31 @@ function Z(t, e, n, i, s, m) {
33
33
  }
34
34
  class tt {
35
35
  constructor(e, n, i) {
36
- g(this, "x");
37
- g(this, "y");
38
- g(this, "baseX");
36
+ m(this, "x");
37
+ m(this, "y");
38
+ m(this, "baseX");
39
39
  // Relative X to swarm center
40
- g(this, "baseY");
40
+ m(this, "baseY");
41
41
  // Relative Y to swarm center
42
- g(this, "z");
43
- g(this, "vx");
44
- g(this, "vy");
45
- g(this, "color");
46
- g(this, "targetColor", null);
47
- g(this, "colorDelay", 0);
48
- g(this, "angleTarget");
49
- g(this, "randomSpeed");
50
- g(this, "sizeBias");
51
- g(this, "scale");
52
- g(this, "dirX");
53
- g(this, "dirY");
54
- g(this, "initialized", !1);
42
+ m(this, "z");
43
+ m(this, "vx");
44
+ m(this, "vy");
45
+ m(this, "color");
46
+ m(this, "targetColor", null);
47
+ m(this, "colorDelay", 0);
48
+ m(this, "angleTarget");
49
+ m(this, "randomSpeed");
50
+ m(this, "sizeBias");
51
+ m(this, "scale");
52
+ m(this, "dirX");
53
+ m(this, "dirY");
54
+ m(this, "initialized", !1);
55
55
  this.x = e, this.y = n, this.baseX = e, this.baseY = n, this.z = Math.random() * 1.5 + 0.2, this.vx = 0, this.vy = 0, this.color = i, this.angleTarget = Math.random() * Math.PI * 2, this.randomSpeed = Math.random() * 2 + 1, this.sizeBias = Math.random(), this.scale = 1, this.dirX = Math.cos(this.angleTarget), this.dirY = Math.sin(this.angleTarget);
56
56
  }
57
- update(e, n, i, s, m, r, o, h = "vertical") {
57
+ update(e, n, i, s, y, r, o, h = "vertical") {
58
58
  this.initialized || (this.x = i + this.baseX, this.y = s + this.baseY, this.initialized = !0);
59
59
  const {
60
- forceX: y,
60
+ forceX: g,
61
61
  forceY: d,
62
62
  dxCenter: c,
63
63
  dyCenter: a,
@@ -66,13 +66,13 @@ class tt {
66
66
  forceX: u,
67
67
  forceY: w
68
68
  } = U(this, i, s, o);
69
- this.vx += y + u, this.vy += d + w, this.vx *= 0.75, this.vy *= 0.75, this.x += this.vx, this.y += this.vy, V(this, l), Z(this, c, a, l, h, o), this.targetColor && (this.colorDelay -= 1, this.colorDelay <= 0 && (this.color = this.targetColor, this.targetColor = null));
69
+ this.vx += g + u, this.vy += d + w, this.vx *= 0.75, this.vy *= 0.75, this.x += this.vx, this.y += this.vy, V(this, l), Z(this, c, a, l, h, o), this.targetColor && (this.colorDelay -= 1, this.colorDelay <= 0 && (this.color = this.targetColor, this.targetColor = null));
70
70
  }
71
71
  draw(e, n, i = "bean") {
72
72
  if (this.scale <= 0.05) return;
73
73
  e.fillStyle = this.color;
74
- const s = Math.sqrt(this.baseX * this.baseX + this.baseY * this.baseY), m = Math.max(0, 1 - s / 350);
75
- if (e.globalAlpha = Math.min(1, (0.5 + this.z * 0.5) * Math.min(this.scale, 1) * m), !(e.globalAlpha <= 0.01))
74
+ const s = Math.sqrt(this.baseX * this.baseX + this.baseY * this.baseY), y = Math.max(0, 1 - s / 350);
75
+ if (e.globalAlpha = Math.min(1, (0.5 + this.z * 0.5) * Math.min(this.scale, 1) * y), !(e.globalAlpha <= 0.01))
76
76
  if (i === "circle") {
77
77
  const r = Math.max(0.1, 2 * this.scale * this.z);
78
78
  e.beginPath(), e.arc(this.x, this.y, r, 0, Math.PI * 2), e.fill();
@@ -80,13 +80,13 @@ class tt {
80
80
  const r = Math.max(0.1, 2 * this.scale * this.z);
81
81
  e.fillRect(this.x - r, this.y - r, r * 2, r * 2);
82
82
  } else {
83
- const o = (6 + this.sizeBias * 6) * this.scale, h = Math.sin(n * 3.5 + this.baseX * 0.1 + this.randomSpeed * 5), y = 0.4 + 0.6 * ((h + 1) / 2), d = o * 0.5 * y, c = Math.max(0.8, this.z * 1.5 * this.scale * (0.8 + 0.2 * h)), a = Math.atan2(this.dirY, this.dirX);
83
+ const o = (6 + this.sizeBias * 6) * this.scale, h = Math.sin(n * 3.5 + this.baseX * 0.1 + this.randomSpeed * 5), g = 0.4 + 0.6 * ((h + 1) / 2), d = o * 0.5 * g, c = Math.max(0.8, this.z * 1.5 * this.scale * (0.8 + 0.2 * h)), a = Math.atan2(this.dirY, this.dirX);
84
84
  e.beginPath(), e.ellipse(this.x, this.y, d, c, a, 0, Math.PI * 2), e.fill();
85
85
  }
86
86
  }
87
87
  }
88
88
  function et({ config: t, backgroundColor: e }) {
89
- const n = I(null), i = I(null), s = I([]), m = I(0), r = I({ x: -1e3, y: -1e3, isDown: !1, active: !1 }), o = I({ x: 0, y: 0, initialized: !1 });
89
+ const n = I(null), i = I(null), s = I([]), y = I(0), r = I({ x: -1e3, y: -1e3, isDown: !1, active: !1 }), o = I({ x: 0, y: 0, initialized: !1 });
90
90
  L(() => {
91
91
  const c = (l) => {
92
92
  if (!n.current) return;
@@ -99,11 +99,11 @@ function et({ config: t, backgroundColor: e }) {
99
99
  window.removeEventListener("pointermove", c), window.removeEventListener("pointerleave", a);
100
100
  };
101
101
  }, []);
102
- const h = I(t), y = I(null), d = I(0);
102
+ const h = I(t), g = I(null), d = I(0);
103
103
  return L(() => {
104
104
  h.current = t;
105
105
  }, [t]), L(() => {
106
- if (y.current && (clearInterval(y.current), y.current = null), !t.colors || t.colors.length === 0) {
106
+ if (g.current && (clearInterval(g.current), g.current = null), !t.colors || t.colors.length === 0) {
107
107
  const a = t.color || "#8B5CF6";
108
108
  s.current.forEach((l) => {
109
109
  l.targetColor = a, l.colorDelay = Math.random() * 20;
@@ -119,11 +119,11 @@ function et({ config: t, backgroundColor: e }) {
119
119
  };
120
120
  return t.colorMode === "mixed" ? s.current.forEach((a, l) => {
121
121
  a.targetColor = t.colors[l % t.colors.length], a.colorDelay = Math.random() * 20;
122
- }) : (d.current = 0, c(t.colors[0]), t.colors.length > 1 && (y.current = setInterval(() => {
122
+ }) : (d.current = 0, c(t.colors[0]), t.colors.length > 1 && (g.current = setInterval(() => {
123
123
  const a = t.colors;
124
124
  d.current = (d.current + 1) % a.length, c(a[d.current]);
125
125
  }, 3e3))), () => {
126
- y.current && clearInterval(y.current);
126
+ g.current && clearInterval(g.current);
127
127
  };
128
128
  }, [t.colors, t.color, t.colorMode]), L(() => {
129
129
  if (!n.current || !i.current || h.current.name === "NONE") return;
@@ -179,49 +179,49 @@ function et({ config: t, backgroundColor: e }) {
179
179
  M.draw(w, P, x);
180
180
  }
181
181
  }
182
- m.current = requestAnimationFrame(q);
182
+ y.current = requestAnimationFrame(q);
183
183
  };
184
184
  return q(), () => {
185
- u.disconnect(), cancelAnimationFrame(m.current);
185
+ u.disconnect(), cancelAnimationFrame(y.current);
186
186
  };
187
187
  }, [e, t.density]), t.name === "NONE" ? null : /* @__PURE__ */ $("div", { ref: n, style: { position: "absolute", inset: 0, zIndex: 0, overflow: "hidden" }, children: /* @__PURE__ */ $("canvas", { ref: i, style: { display: "block", width: "100%", height: "100%" } }) });
188
188
  }
189
189
  class nt {
190
190
  constructor(e, n) {
191
- g(this, "x");
192
- g(this, "y");
193
- g(this, "vx");
194
- g(this, "vy");
195
- g(this, "radius");
196
- g(this, "currentColor", "#8B5CF6");
197
- g(this, "targetColor", null);
198
- g(this, "colorDelay", 0);
191
+ m(this, "x");
192
+ m(this, "y");
193
+ m(this, "vx");
194
+ m(this, "vy");
195
+ m(this, "radius");
196
+ m(this, "currentColor", "#8B5CF6");
197
+ m(this, "targetColor", null);
198
+ m(this, "colorDelay", 0);
199
199
  this.x = e, this.y = n;
200
200
  const i = Math.random() * Math.PI * 2, s = Math.random() * 0.5 + 0.1;
201
201
  this.vx = Math.cos(i) * s, this.vy = Math.sin(i) * s, this.radius = Math.random() * 1.5 + 1;
202
202
  }
203
- update(e, n, i, s, m = 1, r = 0.06) {
204
- if (this.x += this.vx * m, this.y += this.vy * m, this.x < 0 ? (this.x = 0, this.vx *= -1) : this.x > e && (this.x = e, this.vx *= -1), this.y < 0 ? (this.y = 0, this.vy *= -1) : this.y > n && (this.y = n, this.vy *= -1), i !== null && s !== null) {
205
- const o = i - this.x, h = s - this.y, y = o * o + h * h, d = 150, c = d * d;
206
- if (y < c) {
207
- const a = Math.sqrt(y), l = (d - a) / d, u = r / 0.06;
203
+ update(e, n, i, s, y = 1, r = 0.06) {
204
+ if (this.x += this.vx * y, this.y += this.vy * y, this.x < 0 ? (this.x = 0, this.vx *= -1) : this.x > e && (this.x = e, this.vx *= -1), this.y < 0 ? (this.y = 0, this.vy *= -1) : this.y > n && (this.y = n, this.vy *= -1), i !== null && s !== null) {
205
+ const o = i - this.x, h = s - this.y, g = o * o + h * h, d = 150, c = d * d;
206
+ if (g < c) {
207
+ const a = Math.sqrt(g), l = (d - a) / d, u = r / 0.06;
208
208
  this.x -= o / a * l * 2 * u, this.y -= h / a * l * 2 * u;
209
209
  }
210
210
  }
211
- this.targetColor && (this.colorDelay -= 1 * m, this.colorDelay <= 0 && (this.currentColor = this.targetColor, this.targetColor = null));
211
+ this.targetColor && (this.colorDelay -= 1 * y, this.colorDelay <= 0 && (this.currentColor = this.targetColor, this.targetColor = null));
212
212
  }
213
213
  draw(e, n = "circle", i = 0) {
214
214
  if (e.fillStyle = this.currentColor, n === "square")
215
215
  e.fillRect(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
216
216
  else if (n === "bean") {
217
- const s = Math.sin(i * 0.05 + this.x * 0.01 + this.y * 0.01), m = this.radius * 2 * (0.8 + 0.4 * s), r = this.radius * (0.8 + 0.2 * s), o = this.vx !== 0 || this.vy !== 0 ? Math.atan2(this.vy, this.vx) : 0;
218
- e.beginPath(), e.ellipse(this.x, this.y, m, r, o, 0, Math.PI * 2), e.fill();
217
+ const s = Math.sin(i * 0.05 + this.x * 0.01 + this.y * 0.01), y = this.radius * 2 * (0.8 + 0.4 * s), r = this.radius * (0.8 + 0.2 * s), o = this.vx !== 0 || this.vy !== 0 ? Math.atan2(this.vy, this.vx) : 0;
218
+ e.beginPath(), e.ellipse(this.x, this.y, y, r, o, 0, Math.PI * 2), e.fill();
219
219
  } else
220
220
  e.beginPath(), e.arc(this.x, this.y, this.radius, 0, Math.PI * 2), e.fill();
221
221
  }
222
222
  }
223
223
  function rt({ config: t, backgroundColor: e }) {
224
- const n = I(null), i = I(null), s = I([]), m = I(0), r = I({ x: -1e3, y: -1e3, active: !1 });
224
+ const n = I(null), i = I(null), s = I([]), y = I(0), r = I({ x: -1e3, y: -1e3, active: !1 });
225
225
  L(() => {
226
226
  const d = (a) => {
227
227
  if (!n.current) return;
@@ -234,11 +234,11 @@ function rt({ config: t, backgroundColor: e }) {
234
234
  window.removeEventListener("pointermove", d), window.removeEventListener("pointerleave", c);
235
235
  };
236
236
  }, []);
237
- const o = I(t), h = I(0), y = I(null);
237
+ const o = I(t), h = I(0), g = I(null);
238
238
  return L(() => {
239
239
  o.current = t;
240
240
  }, [t]), L(() => {
241
- if (y.current && (clearInterval(y.current), y.current = null), !t.colors || t.colors.length === 0) {
241
+ if (g.current && (clearInterval(g.current), g.current = null), !t.colors || t.colors.length === 0) {
242
242
  const l = t.color || "#8B5CF6";
243
243
  s.current.forEach((u) => {
244
244
  u.targetColor = l, u.colorDelay = Math.random() * 20;
@@ -253,11 +253,11 @@ function rt({ config: t, backgroundColor: e }) {
253
253
  };
254
254
  return t.colorMode === "mixed" ? s.current.forEach((l, u) => {
255
255
  l.targetColor = t.colors[u % t.colors.length], l.colorDelay = Math.random() * 20;
256
- }) : (h.current = 0, a(t.colors[0]), t.colors.length > 1 && (y.current = setInterval(() => {
256
+ }) : (h.current = 0, a(t.colors[0]), t.colors.length > 1 && (g.current = setInterval(() => {
257
257
  const l = t.colors;
258
258
  h.current = (h.current + 1) % l.length, a(l[h.current]);
259
259
  }, 3e3))), () => {
260
- y.current && clearInterval(y.current);
260
+ g.current && clearInterval(g.current);
261
261
  };
262
262
  }, [t.colors, t.color, t.colorMode]), L(() => {
263
263
  if (!n.current || !i.current) return;
@@ -304,44 +304,44 @@ function rt({ config: t, backgroundColor: e }) {
304
304
  u.beginPath(), u.moveTo(x.x, x.y), u.lineTo(b, C), u.strokeStyle = x.currentColor, u.globalAlpha = F * 0.8, u.lineWidth = 1.5, u.stroke();
305
305
  }
306
306
  }
307
- u.globalAlpha = 1, m.current = requestAnimationFrame(P);
307
+ u.globalAlpha = 1, y.current = requestAnimationFrame(P);
308
308
  };
309
309
  return P(), () => {
310
- l.disconnect(), cancelAnimationFrame(m.current);
310
+ l.disconnect(), cancelAnimationFrame(y.current);
311
311
  };
312
312
  }, [e, t.density]), /* @__PURE__ */ $("div", { ref: n, style: { position: "absolute", inset: 0, zIndex: 0, overflow: "hidden" }, children: /* @__PURE__ */ $("canvas", { ref: i, style: { display: "block", width: "100%", height: "100%" } }) });
313
313
  }
314
314
  class st {
315
315
  constructor(e, n, i, s) {
316
- g(this, "x", 0);
317
- g(this, "y", 0);
318
- g(this, "baseX");
319
- g(this, "baseY");
320
- g(this, "vx", 0);
321
- g(this, "vy", 0);
322
- g(this, "color");
323
- g(this, "size");
324
- g(this, "angle");
325
- g(this, "dist");
326
- g(this, "spring");
327
- g(this, "friction");
328
- g(this, "targetColor", null);
329
- g(this, "colorDelay", 0);
316
+ m(this, "x", 0);
317
+ m(this, "y", 0);
318
+ m(this, "baseX");
319
+ m(this, "baseY");
320
+ m(this, "vx", 0);
321
+ m(this, "vy", 0);
322
+ m(this, "color");
323
+ m(this, "size");
324
+ m(this, "angle");
325
+ m(this, "dist");
326
+ m(this, "spring");
327
+ m(this, "friction");
328
+ m(this, "targetColor", null);
329
+ m(this, "colorDelay", 0);
330
330
  this.baseX = e, this.baseY = n, this.color = i, this.size = s, this.angle = Math.atan2(n, e), this.dist = Math.sqrt(e * e + n * n);
331
- const m = Math.min(1, this.dist / 350);
332
- this.spring = 0.15 - m * 0.13, this.friction = 0.85 + m * 0.1;
331
+ const y = Math.min(1, this.dist / 350);
332
+ this.spring = 0.15 - y * 0.13, this.friction = 0.85 + y * 0.1;
333
333
  }
334
334
  update(e, n, i, s) {
335
- const r = 1 + Math.sin(this.angle * 3 + i * 1.2) * 0.05 + Math.cos(this.angle * 5 - i * 0.6) * 0.03, o = this.dist * s * r, h = Math.cos(this.angle) * o, y = Math.sin(this.angle) * o, d = this.dist * 0.1 * r, c = Math.sin(i * 3 + this.dist * 0.05) * d, a = e + h + Math.cos(this.angle + Math.PI / 2) * c, l = n + y + Math.sin(this.angle + Math.PI / 2) * c, u = a - this.x, w = l - this.y;
335
+ const r = 1 + Math.sin(this.angle * 3 + i * 1.2) * 0.05 + Math.cos(this.angle * 5 - i * 0.6) * 0.03, o = this.dist * s * r, h = Math.cos(this.angle) * o, g = Math.sin(this.angle) * o, d = this.dist * 0.1 * r, c = Math.sin(i * 3 + this.dist * 0.05) * d, a = e + h + Math.cos(this.angle + Math.PI / 2) * c, l = n + g + Math.sin(this.angle + Math.PI / 2) * c, u = a - this.x, w = l - this.y;
336
336
  this.vx += u * this.spring, this.vy += w * this.spring, this.vx *= this.friction, this.vy *= this.friction, this.x += this.vx, this.y += this.vy, this.targetColor && (this.colorDelay -= 1, this.colorDelay <= 0 && (this.color = this.targetColor, this.targetColor = null));
337
337
  }
338
338
  draw(e, n, i) {
339
- const s = Math.min(1, this.dist / 350), m = 1 + (1 - s) * (i - 1) * 1.5, r = this.size * m;
339
+ const s = Math.min(1, this.dist / 350), y = 1 + (1 - s) * (i - 1) * 1.5, r = this.size * y;
340
340
  e.globalAlpha = Math.max(0.15, 1 - s * 0.7), e.fillStyle = this.color, e.beginPath(), n === "circle" ? e.arc(this.x, this.y, r, 0, Math.PI * 2) : n === "square" ? e.rect(this.x - r, this.y - r, r * 2, r * 2) : e.ellipse(this.x, this.y, r * 1.5, r, 0, 0, Math.PI * 2), e.fill();
341
341
  }
342
342
  }
343
343
  function ot({ config: t, backgroundColor: e }) {
344
- const n = I(null), i = I(null), s = I([]), m = I(0), r = I({ x: -1e3, y: -1e3, active: !1 }), o = I({ x: 0, y: 0, initialized: !1, angle: -Math.PI / 2 });
344
+ const n = I(null), i = I(null), s = I([]), y = I(0), r = I({ x: -1e3, y: -1e3, active: !1 }), o = I({ x: 0, y: 0, initialized: !1, angle: -Math.PI / 2 });
345
345
  L(() => {
346
346
  const c = (a) => {
347
347
  if (!n.current) return;
@@ -352,7 +352,7 @@ function ot({ config: t, backgroundColor: e }) {
352
352
  window.removeEventListener("pointermove", c);
353
353
  };
354
354
  }, []);
355
- const h = I(t), y = I(0), d = I(null);
355
+ const h = I(t), g = I(0), d = I(null);
356
356
  return L(() => {
357
357
  h.current = t;
358
358
  }, [t]), L(() => {
@@ -370,9 +370,9 @@ function ot({ config: t, backgroundColor: e }) {
370
370
  };
371
371
  return t.colorMode === "mixed" ? s.current.forEach((a, l) => {
372
372
  a.targetColor = t.colors[l % t.colors.length], a.colorDelay = Math.max(0, a.dist * 0.2) + Math.random() * 10;
373
- }) : (y.current = 0, c(t.colors[0]), t.colors.length > 1 && (d.current = setInterval(() => {
373
+ }) : (g.current = 0, c(t.colors[0]), t.colors.length > 1 && (d.current = setInterval(() => {
374
374
  const a = t.colors;
375
- y.current = (y.current + 1) % a.length, c(a[y.current]);
375
+ g.current = (g.current + 1) % a.length, c(a[g.current]);
376
376
  }, 3e3))), () => {
377
377
  d.current && clearInterval(d.current);
378
378
  };
@@ -444,10 +444,10 @@ function ot({ config: t, backgroundColor: e }) {
444
444
  const G = h.current.shape || "circle";
445
445
  B.draw(w, G, E);
446
446
  }
447
- m.current = requestAnimationFrame(q);
447
+ y.current = requestAnimationFrame(q);
448
448
  };
449
449
  return q(), () => {
450
- u.disconnect(), cancelAnimationFrame(m.current);
450
+ u.disconnect(), cancelAnimationFrame(y.current);
451
451
  };
452
452
  }, [e, t.density]), /* @__PURE__ */ $(
453
453
  "div",
@@ -472,20 +472,20 @@ const it = {
472
472
  boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
473
473
  transition: "all 300ms ease-out"
474
474
  };
475
- function ft({
475
+ function ct({
476
476
  children: t,
477
477
  width: e = "100%",
478
478
  height: n = "60vh",
479
479
  backgroundColor: i = "#050505",
480
480
  className: s = "",
481
- style: m,
481
+ style: y,
482
482
  background: r = { name: "NONE" }
483
483
  }) {
484
484
  return /* @__PURE__ */ _(
485
485
  "div",
486
486
  {
487
487
  className: s,
488
- style: { ...it, width: e, height: n, backgroundColor: i, ...m },
488
+ style: { ...it, width: e, height: n, backgroundColor: i, ...y },
489
489
  children: [
490
490
  r.name === "FOLLOW_POINTER" && /* @__PURE__ */ $(et, { config: r, backgroundColor: i }),
491
491
  r.name === "NET" && /* @__PURE__ */ $(rt, { config: r, backgroundColor: i }),
@@ -495,7 +495,7 @@ function ft({
495
495
  }
496
496
  );
497
497
  }
498
- function ct(t) {
498
+ function at(t) {
499
499
  const e = I({ x: -1e3, y: -1e3, isDown: !1, active: !1 });
500
500
  return L(() => {
501
501
  const n = t.current;
@@ -505,70 +505,70 @@ function ct(t) {
505
505
  e.current.x = o.clientX - h.left, e.current.y = o.clientY - h.top, e.current.active = !0;
506
506
  }, s = () => {
507
507
  e.current.active = !1;
508
- }, m = () => {
508
+ }, y = () => {
509
509
  e.current.isDown = !0;
510
510
  }, r = () => {
511
511
  e.current.isDown = !1;
512
512
  };
513
- return n.addEventListener("pointermove", i), n.addEventListener("pointerleave", s), n.addEventListener("pointerdown", m), n.addEventListener("pointerup", r), n.style.touchAction = "none", () => {
514
- n.removeEventListener("pointermove", i), n.removeEventListener("pointerleave", s), n.removeEventListener("pointerdown", m), n.removeEventListener("pointerup", r);
513
+ return n.addEventListener("pointermove", i), n.addEventListener("pointerleave", s), n.addEventListener("pointerdown", y), n.addEventListener("pointerup", r), n.style.touchAction = "none", () => {
514
+ n.removeEventListener("pointermove", i), n.removeEventListener("pointerleave", s), n.removeEventListener("pointerdown", y), n.removeEventListener("pointerup", r);
515
515
  };
516
516
  }, [t]), e;
517
517
  }
518
- function at(t, e, n, i, s, m, r, o, h) {
519
- if (s === null || m === null || !o && h === "none")
518
+ function lt(t, e, n, i, s, y, r, o, h) {
519
+ if (s === null || y === null || !o && h === "none")
520
520
  return { x: n, y: i };
521
- let y = n, d = i;
522
- const c = s - t, a = m - e, l = c * c + a * a, u = Math.sqrt(l);
521
+ let g = n, d = i;
522
+ const c = s - t, a = y - e, l = c * c + a * a, u = Math.sqrt(l);
523
523
  if (o && !r && l < 3e4) {
524
524
  const P = (3e4 - l) / 3e4;
525
- y += c * P * 0.15, d += a * P * 0.15;
525
+ g += c * P * 0.15, d += a * P * 0.15;
526
526
  }
527
527
  if (r && h !== "none") {
528
528
  if (h === "attract") {
529
529
  if (l < 3e4) {
530
530
  const P = (3e4 - l) / 3e4;
531
- y += c * P * 0.8, d += a * P * 0.8;
531
+ g += c * P * 0.8, d += a * P * 0.8;
532
532
  }
533
533
  } else if (h === "repel" && l < 5e4 && u > 0) {
534
534
  const P = Math.pow(Math.max(0, 5e4 - l) / 5e4, 1.2);
535
- y -= c / u * P * 400, d -= a / u * P * 400;
535
+ g -= c / u * P * 400, d -= a / u * P * 400;
536
536
  }
537
537
  }
538
- return { x: y, y: d };
538
+ return { x: g, y: d };
539
539
  }
540
540
  class H {
541
541
  constructor(e, n, i = "255, 255, 255") {
542
- g(this, "x");
543
- g(this, "y");
544
- g(this, "vx");
545
- g(this, "vy");
546
- g(this, "targetX");
547
- g(this, "targetY");
548
- g(this, "baseColor");
549
- g(this, "opacity");
550
- g(this, "size");
551
- g(this, "sizeMultiplier");
552
- g(this, "friction");
553
- g(this, "ease");
554
- g(this, "easeMultiplier");
555
- g(this, "floatSpeed");
556
- g(this, "floatOffset");
557
- g(this, "randomSpeed");
542
+ m(this, "x");
543
+ m(this, "y");
544
+ m(this, "vx");
545
+ m(this, "vy");
546
+ m(this, "targetX");
547
+ m(this, "targetY");
548
+ m(this, "baseColor");
549
+ m(this, "opacity");
550
+ m(this, "size");
551
+ m(this, "sizeMultiplier");
552
+ m(this, "friction");
553
+ m(this, "ease");
554
+ m(this, "easeMultiplier");
555
+ m(this, "floatSpeed");
556
+ m(this, "floatOffset");
557
+ m(this, "randomSpeed");
558
558
  this.x = Math.random() * e, this.y = Math.random() * n, this.targetX = this.x, this.targetY = this.y, this.vx = 0, this.vy = 0, this.size = Math.random() * 1.8 + 0.5, this.sizeMultiplier = 1, this.baseColor = Array.isArray(i) ? i[Math.floor(Math.random() * i.length)] : i, this.opacity = 0.4 + Math.random() * 0.6, this.friction = 0.82 + Math.random() * 0.1, this.ease = 0.03 + Math.random() * 0.05, this.easeMultiplier = 1, this.floatSpeed = Math.random() * 0.02 + 5e-3, this.floatOffset = Math.random() * Math.PI * 2, this.randomSpeed = Math.random();
559
559
  }
560
- update(e, n, i = null, s = null, m = !1, r = !0, o = "none") {
561
- const { x: h, y } = at(
560
+ update(e, n, i = null, s = null, y = !1, r = !0, o = "none") {
561
+ const { x: h, y: g } = lt(
562
562
  this.x,
563
563
  this.y,
564
564
  this.targetX,
565
565
  this.targetY,
566
566
  i,
567
567
  s,
568
- m,
568
+ y,
569
569
  r,
570
570
  o
571
- ), d = h - this.x, c = y - this.y, a = n ? 0 : Math.cos(e * 0.01 + this.y * 0.01) * 0.5, l = n ? 0 : Math.sin(e * 0.01 + this.x * 0.01) * 0.5;
571
+ ), d = h - this.x, c = g - this.y, a = n ? 0 : Math.cos(e * 0.01 + this.y * 0.01) * 0.5, l = n ? 0 : Math.sin(e * 0.01 + this.x * 0.01) * 0.5;
572
572
  this.vx += d * (this.ease * this.easeMultiplier) + a, this.vy += c * (this.ease * this.easeMultiplier) + l, this.vx *= this.friction, this.vy *= this.friction, this.x += this.vx, this.y += this.vy;
573
573
  const u = n ? 0.2 : 2;
574
574
  this.x += Math.cos(e * this.floatSpeed + this.floatOffset) * u, this.y += Math.sin(e * this.floatSpeed + this.floatOffset) * u;
@@ -579,8 +579,8 @@ class H {
579
579
  if (n === "square")
580
580
  e.fillRect(this.x - s, this.y - s, s * 2, s * 2);
581
581
  else if (n === "bean") {
582
- const m = 6 + this.size * 2 * this.sizeMultiplier, r = Math.sin(i * 0.05 + this.x * 0.01 + this.randomSpeed * 5), o = 0.4 + 0.6 * ((r + 1) / 2), h = m * 0.5 * o, y = Math.max(0.8, s * 1.5 * (0.8 + 0.2 * r)), d = this.vx !== 0 || this.vy !== 0 ? Math.atan2(this.vy, this.vx) : 0;
583
- e.beginPath(), e.ellipse(this.x, this.y, h, y, d, 0, Math.PI * 2), e.fill();
582
+ const y = 6 + this.size * 2 * this.sizeMultiplier, r = Math.sin(i * 0.05 + this.x * 0.01 + this.randomSpeed * 5), o = 0.4 + 0.6 * ((r + 1) / 2), h = y * 0.5 * o, g = Math.max(0.8, s * 1.5 * (0.8 + 0.2 * r)), d = this.vx !== 0 || this.vy !== 0 ? Math.atan2(this.vy, this.vx) : 0;
583
+ e.beginPath(), e.ellipse(this.x, this.y, h, g, d, 0, Math.PI * 2), e.fill();
584
584
  } else
585
585
  e.beginPath(), e.arc(this.x, this.y, s, 0, Math.PI * 2), e.fill();
586
586
  }
@@ -592,36 +592,36 @@ function j(t, e, n) {
592
592
  const s = i.getContext("2d", { willReadFrequently: !0 });
593
593
  if (!s) return [];
594
594
  s.clearRect(0, 0, e, n);
595
- let m = Math.min(e, n) * 0.65;
596
- s.font = `bold ${m}px "Georgia", serif`;
595
+ let y = Math.min(e, n) * 0.65;
596
+ s.font = `bold ${y}px "Georgia", serif`;
597
597
  const r = s.measureText(t);
598
- r.width > e * 0.9 && (m = m * (e * 0.9) / r.width, s.font = `bold ${m}px "Georgia", serif`), s.fillStyle = "white", s.textAlign = "center", s.textBaseline = "middle", s.fillText(t, e / 2, n / 2.05);
599
- const h = s.getImageData(0, 0, e, n).data, y = [], d = window.innerWidth < 600 ? 6 : 8;
598
+ r.width > e * 0.9 && (y = y * (e * 0.9) / r.width, s.font = `bold ${y}px "Georgia", serif`), s.fillStyle = "white", s.textAlign = "center", s.textBaseline = "middle", s.fillText(t, e / 2, n / 2.05);
599
+ const h = s.getImageData(0, 0, e, n).data, g = [], d = window.innerWidth < 600 ? 6 : 8;
600
600
  for (let c = 0; c < n; c += d)
601
601
  for (let a = 0; a < e; a += d) {
602
602
  const l = (c * e + a) * 4;
603
- h[l + 3] > 128 && y.push({
603
+ h[l + 3] > 128 && g.push({
604
604
  x: a + (Math.random() - 0.5) * 4,
605
605
  y: c + (Math.random() - 0.5) * 4
606
606
  });
607
607
  }
608
- return y;
608
+ return g;
609
609
  }
610
- function lt(t, e, n) {
610
+ function ht(t, e, n) {
611
611
  const i = I(t);
612
612
  return L(() => {
613
613
  i.current = t;
614
- }, [t]), { getPixelsForText: j, updateTextTargets: (m, r, o) => {
614
+ }, [t]), { getPixelsForText: j, updateTextTargets: (y, r, o) => {
615
615
  var q, b;
616
- const h = r || ((q = n.current) == null ? void 0 : q.offsetWidth) || window.innerWidth, y = o || ((b = n.current) == null ? void 0 : b.offsetHeight) || window.innerHeight;
617
- if (!m) {
616
+ const h = r || ((q = n.current) == null ? void 0 : q.offsetWidth) || window.innerWidth, g = o || ((b = n.current) == null ? void 0 : b.offsetHeight) || window.innerHeight;
617
+ if (!y) {
618
618
  e.current.forEach((f) => {
619
- const p = 50 + Math.random() * (h - 100), R = 50 + Math.random() * (y - 100);
619
+ const p = 50 + Math.random() * (h - 100), R = 50 + Math.random() * (g - 100);
620
620
  (Math.abs(p - f.x) > 20 || Math.abs(R - f.y) > 20) && (f.vx += (Math.random() - 0.5) * 20, f.vy += (Math.random() - 0.5) * 20), f.targetX = p, f.targetY = R;
621
621
  });
622
622
  return;
623
623
  }
624
- const d = j(m, h, y);
624
+ const d = j(y, h, g);
625
625
  if (d.length === 0) return;
626
626
  const c = h * 0.15, a = d.map((C) => ({ pt: C, key: C.x + (Math.random() - 0.5) * c }));
627
627
  a.sort((C, f) => C.key - f.key);
@@ -666,14 +666,14 @@ function yt({
666
666
  particleSize: n = 1,
667
667
  particleDensity: i = 1,
668
668
  particleEase: s = 1,
669
- isMagnet: m = !0,
669
+ isMagnet: y = !0,
670
670
  clickMode: r = "none",
671
671
  particleShape: o = "circle",
672
672
  backgroundColor: h = "#050505"
673
673
  }) {
674
- const y = I(null), d = I(null), c = I([]), a = I(0), l = I(0), u = ct(d), w = I({ isMagnet: m, clickMode: r, particleShape: o, backgroundColor: h });
675
- w.current = { isMagnet: m, clickMode: r, particleShape: o, backgroundColor: h };
676
- const { updateTextTargets: P, textRef: q } = lt(
674
+ const g = I(null), d = I(null), c = I([]), a = I(0), l = I(0), u = at(d), w = I({ isMagnet: y, clickMode: r, particleShape: o, backgroundColor: h });
675
+ w.current = { isMagnet: y, clickMode: r, particleShape: o, backgroundColor: h };
676
+ const { updateTextTargets: P, textRef: q } = ht(
677
677
  t,
678
678
  c,
679
679
  d
@@ -701,7 +701,7 @@ function yt({
701
701
  f.easeMultiplier = s;
702
702
  });
703
703
  }, [s]), L(() => {
704
- if (c.current.length > 0 && y.current && d.current) {
704
+ if (c.current.length > 0 && g.current && d.current) {
705
705
  const f = window.innerWidth < 600 ? 1500 : 3e3, p = Math.floor(f * i), R = c.current.length;
706
706
  if (p > R) {
707
707
  const S = d.current.getBoundingClientRect(), D = b();
@@ -713,7 +713,7 @@ function yt({
713
713
  } else p < R && c.current.splice(p);
714
714
  }
715
715
  }, [i]), L(() => {
716
- const f = d.current, p = y.current;
716
+ const f = d.current, p = g.current;
717
717
  if (!f || !p) return;
718
718
  const R = (v) => {
719
719
  for (const X of v) {
@@ -753,17 +753,40 @@ function yt({
753
753
  children: /* @__PURE__ */ $(
754
754
  "canvas",
755
755
  {
756
- ref: y,
756
+ ref: g,
757
757
  style: { display: "block", width: "100%", height: "100%" }
758
758
  }
759
759
  )
760
760
  }
761
761
  );
762
762
  }
763
+ function gt({
764
+ name: t,
765
+ config: e,
766
+ width: n = "100%",
767
+ height: i = "60vh",
768
+ backgroundColor: s = "#050505",
769
+ className: y = "",
770
+ style: r
771
+ }) {
772
+ const o = { name: t, ...e };
773
+ return /* @__PURE__ */ $(
774
+ ct,
775
+ {
776
+ width: n,
777
+ height: i,
778
+ backgroundColor: s,
779
+ className: y,
780
+ style: r,
781
+ background: o
782
+ }
783
+ );
784
+ }
763
785
  export {
764
- ft as ParticleCanvas,
786
+ gt as ParticleBackground,
787
+ ct as ParticleCanvas,
765
788
  yt as TextParticleEngine,
766
- at as getMagnetTarget,
767
- ct as useParticleInteraction,
768
- lt as useTextParticles
789
+ lt as getMagnetTarget,
790
+ at as useParticleInteraction,
791
+ ht as useTextParticles
769
792
  };
@@ -1 +1 @@
1
- (function(A,q){typeof exports=="object"&&typeof module<"u"?q(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],q):(A=typeof globalThis<"u"?globalThis:A||self,q(A.JlParticleInteractive={},A.ReactJsxRuntime,A.React))})(this,(function(A,q,f){"use strict";var lt=Object.defineProperty;var ht=(A,q,f)=>q in A?lt(A,q,{enumerable:!0,configurable:!0,writable:!0,value:f}):A[q]=f;var v=(A,q,f)=>ht(A,typeof q!="symbol"?q+"":q,f);function _(t,e,n,i){let s=e+t.baseX,m=n+t.baseY;s+=Math.sin(i*t.randomSpeed+t.baseY*.05)*15*t.z,m+=Math.cos(i*t.randomSpeed+t.baseX*.05)*15*t.z;const r=s-t.x,o=m-t.y,h=r*.06,g=o*.06;return{forceX:h,forceY:g}}function U(t,e,n,i,s,m){const r=i,o=s,h=t.x-r,g=t.y-o,d=Math.max(Math.sqrt(h*h+g*g),1);let c=0,a=0;const u=Math.sin(d*.02-m*3)*2.5*t.z;c+=h/d*u,a+=g/d*u;const E=Math.cos(d*.01-m*1+t.randomSpeed)*.8*t.z,T=-g/d,b=h/d;return c+=T*E,a+=b*E,{forceX:c,forceY:a,dxCenter:h,dyCenter:g,distToCenter:d}}function Q(t,e){let s=Math.min(e/400,1)*2.5+t.sizeBias*1;s<.4&&(s=0),t.scale+=(s-t.scale)*.15}function V(t,e,n,i,s,m){let r=0,o=0;s==="horizontal"?(r=1,o=0):s==="diagonal"?(r=-e/i,o=-n/i):(r=-n/i,o=e/i);const h=Math.atan2(o,r),g=t.sizeBias>.3?1:0,d=Math.max(0,Math.sin(m*.5+t.randomSpeed*10)),c=Math.sin(m*3+t.baseX*.1+t.randomSpeed)*.5*d*g;r=Math.cos(h+c),o=Math.sin(h+c);const a=Math.max(1-i/400,.1);s==="horizontal"?(t.dirX=t.dirX*(1-.2)+r*.2,t.dirY=t.dirY*(1-.2)+o*.2):(t.dirX=t.dirX*(1-a*.3)+r*a*.3,t.dirY=t.dirY*(1-a*.3)+o*a*.3);const l=Math.sqrt(t.dirX*t.dirX+t.dirY*t.dirY);l>0&&(t.dirX/=l,t.dirY/=l)}class Z{constructor(e,n,i){v(this,"x");v(this,"y");v(this,"baseX");v(this,"baseY");v(this,"z");v(this,"vx");v(this,"vy");v(this,"color");v(this,"targetColor",null);v(this,"colorDelay",0);v(this,"angleTarget");v(this,"randomSpeed");v(this,"sizeBias");v(this,"scale");v(this,"dirX");v(this,"dirY");v(this,"initialized",!1);this.x=e,this.y=n,this.baseX=e,this.baseY=n,this.z=Math.random()*1.5+.2,this.vx=0,this.vy=0,this.color=i,this.angleTarget=Math.random()*Math.PI*2,this.randomSpeed=Math.random()*2+1,this.sizeBias=Math.random(),this.scale=1,this.dirX=Math.cos(this.angleTarget),this.dirY=Math.sin(this.angleTarget)}update(e,n,i,s,m,r,o,h="vertical"){this.initialized||(this.x=i+this.baseX,this.y=s+this.baseY,this.initialized=!0);const{forceX:g,forceY:d,dxCenter:c,dyCenter:a,distToCenter:l}=U(this,e,n,i,s,o),{forceX:u,forceY:R}=_(this,i,s,o);this.vx+=g+u,this.vy+=d+R,this.vx*=.75,this.vy*=.75,this.x+=this.vx,this.y+=this.vy,Q(this,l),V(this,c,a,l,h,o),this.targetColor&&(this.colorDelay-=1,this.colorDelay<=0&&(this.color=this.targetColor,this.targetColor=null))}draw(e,n,i="bean"){if(this.scale<=.05)return;e.fillStyle=this.color;const s=Math.sqrt(this.baseX*this.baseX+this.baseY*this.baseY),m=Math.max(0,1-s/350);if(e.globalAlpha=Math.min(1,(.5+this.z*.5)*Math.min(this.scale,1)*m),!(e.globalAlpha<=.01))if(i==="circle"){const r=Math.max(.1,2*this.scale*this.z);e.beginPath(),e.arc(this.x,this.y,r,0,Math.PI*2),e.fill()}else if(i==="square"){const r=Math.max(.1,2*this.scale*this.z);e.fillRect(this.x-r,this.y-r,r*2,r*2)}else{const o=(6+this.sizeBias*6)*this.scale,h=Math.sin(n*3.5+this.baseX*.1+this.randomSpeed*5),g=.4+.6*((h+1)/2),d=o*.5*g,c=Math.max(.8,this.z*1.5*this.scale*(.8+.2*h)),a=Math.atan2(this.dirY,this.dirX);e.beginPath(),e.ellipse(this.x,this.y,d,c,a,0,Math.PI*2),e.fill()}}}function tt({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),m=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,isDown:!1,active:!1}),o=f.useRef({x:0,y:0,initialized:!1});f.useEffect(()=>{const c=l=>{if(!n.current)return;const u=n.current.getBoundingClientRect();r.current.x=l.clientX-u.left,r.current.y=l.clientY-u.top,r.current.active=!0},a=()=>{r.current.active=!1};return window.addEventListener("pointermove",c),window.addEventListener("pointerleave",a),()=>{window.removeEventListener("pointermove",c),window.removeEventListener("pointerleave",a)}},[]);const h=f.useRef(t),g=f.useRef(null),d=f.useRef(0);return f.useEffect(()=>{h.current=t},[t]),f.useEffect(()=>{if(g.current&&(clearInterval(g.current),g.current=null),!t.colors||t.colors.length===0){const a=t.color||"#8B5CF6";s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.random()*20});return}const c=a=>{const l=r.current.active?r.current.x:o.current.x,u=r.current.active?r.current.y:o.current.y;s.current.forEach(R=>{const E=R.x-l,T=R.y-u,b=Math.sqrt(E*E+T*T);R.targetColor=a,R.colorDelay=Math.max(0,b*.15)})};return t.colorMode==="mixed"?s.current.forEach((a,l)=>{a.targetColor=t.colors[l%t.colors.length],a.colorDelay=Math.random()*20}):(d.current=0,c(t.colors[0]),t.colors.length>1&&(g.current=setInterval(()=>{const a=t.colors;d.current=(d.current+1)%a.length,c(a[d.current])},3e3))),()=>{g.current&&clearInterval(g.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current||h.current.name==="NONE")return;const c=i.current,a=n.current,l=b=>{for(const C of b){const{width:y,height:w}=C.contentRect,P=window.devicePixelRatio||1;c.width=y*P,c.height=w*P,c.style.width=`${y}px`,c.style.height=`${w}px`;const S=c.getContext("2d");S&&S.scale(P,P),s.current=[];const z=Math.floor(350*(h.current.density??1)),M=h.current.colors,D=h.current.colorMode||"wave";for(let x=0;x<z;x++){const p=Math.sqrt(Math.random())*350,X=Math.random()*Math.PI*2,Y=Math.cos(X)*p,L=Math.sin(X)*p;let F;if(M&&M.length>0)F=D==="mixed"?M[x%M.length]:M[0];else if(h.current.color)F=h.current.color;else{const O=210+Math.max(0,Math.min(1,(Y+350)/700))*130+(Math.random()*15-7.5),$=75+Math.random()*25,N=60+Math.random()*15;F=`hsl(${O}, ${$}%, ${N}%)`}s.current.push(new Z(Y,L,F))}}},u=new ResizeObserver(l);u.observe(a);const R=c.getContext("2d");let E=0;const T=()=>{const b=a.getBoundingClientRect();if(R.clearRect(0,0,b.width,b.height),e!=="transparent"&&(R.fillStyle=e,R.fillRect(0,0,b.width,b.height)),o.current.initialized||(o.current.x=b.width/2,o.current.y=b.height/2,o.current.initialized=!0),h.current.name==="FOLLOW_POINTER"){let C=b.width/2,y=b.height/2;const w=r.current.active?r.current.x:null,P=r.current.active?r.current.y:null;w!==null&&P!==null&&(C=w,y=P);const S=h.current.pointerTrackingSpeed??.06;o.current.x+=(C-o.current.x)*S,o.current.y+=(y-o.current.y)*S;const I=h.current.particleSpeed??1;E+=.012*I;const z=s.current,M=18,D=M*M;for(let x=0;x<z.length;x++){const p=z[x];for(let X=x+1;X<z.length;X++){const Y=z[X],L=p.x-Y.x,F=p.y-Y.y,W=L*L+F*F;if(W<D&&W>0){const O=Math.sqrt(W),$=(M-O)/M,N=L/O*$*.8,B=F/O*$*.8;p.x+=N,p.y+=B,Y.x-=N,Y.y-=B,p.vx+=N*.1,p.vy+=B*.1,Y.vx-=N*.1,Y.vy-=B*.1}}}for(const x of z){x.update(w,P,o.current.x,o.current.y,b.width,b.height,E,h.current.orientation);const p=h.current.shape||"bean";x.draw(R,E,p)}}m.current=requestAnimationFrame(T)};return T(),()=>{u.disconnect(),cancelAnimationFrame(m.current)}},[e,t.density]),t.name==="NONE"?null:q.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:q.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%"}})})}class et{constructor(e,n){v(this,"x");v(this,"y");v(this,"vx");v(this,"vy");v(this,"radius");v(this,"currentColor","#8B5CF6");v(this,"targetColor",null);v(this,"colorDelay",0);this.x=e,this.y=n;const i=Math.random()*Math.PI*2,s=Math.random()*.5+.1;this.vx=Math.cos(i)*s,this.vy=Math.sin(i)*s,this.radius=Math.random()*1.5+1}update(e,n,i,s,m=1,r=.06){if(this.x+=this.vx*m,this.y+=this.vy*m,this.x<0?(this.x=0,this.vx*=-1):this.x>e&&(this.x=e,this.vx*=-1),this.y<0?(this.y=0,this.vy*=-1):this.y>n&&(this.y=n,this.vy*=-1),i!==null&&s!==null){const o=i-this.x,h=s-this.y,g=o*o+h*h,d=150,c=d*d;if(g<c){const a=Math.sqrt(g),l=(d-a)/d,u=r/.06;this.x-=o/a*l*2*u,this.y-=h/a*l*2*u}}this.targetColor&&(this.colorDelay-=1*m,this.colorDelay<=0&&(this.currentColor=this.targetColor,this.targetColor=null))}draw(e,n="circle",i=0){if(e.fillStyle=this.currentColor,n==="square")e.fillRect(this.x-this.radius,this.y-this.radius,this.radius*2,this.radius*2);else if(n==="bean"){const s=Math.sin(i*.05+this.x*.01+this.y*.01),m=this.radius*2*(.8+.4*s),r=this.radius*(.8+.2*s),o=this.vx!==0||this.vy!==0?Math.atan2(this.vy,this.vx):0;e.beginPath(),e.ellipse(this.x,this.y,m,r,o,0,Math.PI*2),e.fill()}else e.beginPath(),e.arc(this.x,this.y,this.radius,0,Math.PI*2),e.fill()}}function nt({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),m=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,active:!1});f.useEffect(()=>{const d=a=>{if(!n.current)return;const l=n.current.getBoundingClientRect();r.current.x=a.clientX-l.left,r.current.y=a.clientY-l.top,r.current.active=!0},c=()=>{r.current.active=!1};return window.addEventListener("pointermove",d),window.addEventListener("pointerleave",c),()=>{window.removeEventListener("pointermove",d),window.removeEventListener("pointerleave",c)}},[]);const o=f.useRef(t),h=f.useRef(0),g=f.useRef(null);return f.useEffect(()=>{o.current=t},[t]),f.useEffect(()=>{if(g.current&&(clearInterval(g.current),g.current=null),!t.colors||t.colors.length===0){const l=t.color||"#8B5CF6";s.current.forEach(u=>{u.targetColor=l,u.colorDelay=Math.random()*20});return}const d=r.current.active?r.current.x:n.current?n.current.clientWidth/2:0,c=r.current.active?r.current.y:n.current?n.current.clientHeight/2:0,a=l=>{s.current.forEach(u=>{const R=u.x-d,E=u.y-c,T=Math.sqrt(R*R+E*E);u.targetColor=l,u.colorDelay=Math.max(0,T*.2)})};return t.colorMode==="mixed"?s.current.forEach((l,u)=>{l.targetColor=t.colors[u%t.colors.length],l.colorDelay=Math.random()*20}):(h.current=0,a(t.colors[0]),t.colors.length>1&&(g.current=setInterval(()=>{const l=t.colors;h.current=(h.current+1)%l.length,a(l[h.current])},3e3))),()=>{g.current&&clearInterval(g.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current)return;const d=i.current,c=n.current,a=T=>{for(const b of T){const{width:C,height:y}=b.contentRect,w=window.devicePixelRatio||1;d.width=C*w,d.height=y*w,d.style.width=`${C}px`,d.style.height=`${y}px`;const P=d.getContext("2d");P&&P.scale(w,w),s.current=[];const S=C*y,I=o.current.density??1,z=Math.min(Math.floor(300*I),Math.floor(S/6e3*I)),M=o.current.colors,D=o.current.colorMode||"wave";for(let x=0;x<z;x++){const p=new et(Math.random()*C,Math.random()*y);M&&M.length>0?p.currentColor=D==="mixed"?M[x%M.length]:M[0]:o.current.color&&(p.currentColor=o.current.color),s.current.push(p)}}},l=new ResizeObserver(a);l.observe(c);const u=d.getContext("2d");let R=0;const E=()=>{R+=1;const T=c.getBoundingClientRect();u.clearRect(0,0,T.width,T.height),e!=="transparent"&&(u.fillStyle=e,u.fillRect(0,0,T.width,T.height));const b=r.current.active?r.current.x:null,C=r.current.active?r.current.y:null,y=s.current,w=o.current.shape||"circle",P=120,S=P*P,I=o.current.particleSpeed??1,z=o.current.pointerTrackingSpeed??.06;for(let M=0;M<y.length;M++){const D=y[M];D.update(T.width,T.height,b,C,I,z),u.globalAlpha=1,D.draw(u,w,R);for(let x=M+1;x<y.length;x++){const p=y[x],X=D.x-p.x,Y=D.y-p.y,L=X*X+Y*Y;if(L<S){const F=1-Math.sqrt(L)/P;u.beginPath(),u.moveTo(D.x,D.y),u.lineTo(p.x,p.y),u.strokeStyle=D.currentColor,u.globalAlpha=F*.5,u.lineWidth=1,u.stroke()}}}if(u.globalAlpha=1,b!==null&&C!==null)for(let x=0;x<y.length;x++){const p=y[x],X=p.x-b,Y=p.y-C,L=X*X+Y*Y;if(L<22500){const F=1-Math.sqrt(L)/150;u.beginPath(),u.moveTo(p.x,p.y),u.lineTo(b,C),u.strokeStyle=p.currentColor,u.globalAlpha=F*.8,u.lineWidth=1.5,u.stroke()}}u.globalAlpha=1,m.current=requestAnimationFrame(E)};return E(),()=>{l.disconnect(),cancelAnimationFrame(m.current)}},[e,t.density]),q.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:q.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%"}})})}class rt{constructor(e,n,i,s){v(this,"x",0);v(this,"y",0);v(this,"baseX");v(this,"baseY");v(this,"vx",0);v(this,"vy",0);v(this,"color");v(this,"size");v(this,"angle");v(this,"dist");v(this,"spring");v(this,"friction");v(this,"targetColor",null);v(this,"colorDelay",0);this.baseX=e,this.baseY=n,this.color=i,this.size=s,this.angle=Math.atan2(n,e),this.dist=Math.sqrt(e*e+n*n);const m=Math.min(1,this.dist/350);this.spring=.15-m*.13,this.friction=.85+m*.1}update(e,n,i,s){const r=1+Math.sin(this.angle*3+i*1.2)*.05+Math.cos(this.angle*5-i*.6)*.03,o=this.dist*s*r,h=Math.cos(this.angle)*o,g=Math.sin(this.angle)*o,d=this.dist*.1*r,c=Math.sin(i*3+this.dist*.05)*d,a=e+h+Math.cos(this.angle+Math.PI/2)*c,l=n+g+Math.sin(this.angle+Math.PI/2)*c,u=a-this.x,R=l-this.y;this.vx+=u*this.spring,this.vy+=R*this.spring,this.vx*=this.friction,this.vy*=this.friction,this.x+=this.vx,this.y+=this.vy,this.targetColor&&(this.colorDelay-=1,this.colorDelay<=0&&(this.color=this.targetColor,this.targetColor=null))}draw(e,n,i){const s=Math.min(1,this.dist/350),m=1+(1-s)*(i-1)*1.5,r=this.size*m;e.globalAlpha=Math.max(.15,1-s*.7),e.fillStyle=this.color,e.beginPath(),n==="circle"?e.arc(this.x,this.y,r,0,Math.PI*2):n==="square"?e.rect(this.x-r,this.y-r,r*2,r*2):e.ellipse(this.x,this.y,r*1.5,r,0,0,Math.PI*2),e.fill()}}function st({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),m=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,active:!1}),o=f.useRef({x:0,y:0,initialized:!1,angle:-Math.PI/2});f.useEffect(()=>{const c=a=>{if(!n.current)return;const l=n.current.getBoundingClientRect();r.current.x=a.clientX-l.left,r.current.y=a.clientY-l.top,r.current.active=!0};return window.addEventListener("pointermove",c),()=>{window.removeEventListener("pointermove",c)}},[]);const h=f.useRef(t),g=f.useRef(0),d=f.useRef(null);return f.useEffect(()=>{h.current=t},[t]),f.useEffect(()=>{if(d.current&&(clearInterval(d.current),d.current=null),!t.colors||t.colors.length===0){const a=t.color||"#8B5CF6";s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.random()*20});return}const c=a=>{s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.max(0,l.dist*.2)})};return t.colorMode==="mixed"?s.current.forEach((a,l)=>{a.targetColor=t.colors[l%t.colors.length],a.colorDelay=Math.max(0,a.dist*.2)+Math.random()*10}):(g.current=0,c(t.colors[0]),t.colors.length>1&&(d.current=setInterval(()=>{const a=t.colors;g.current=(g.current+1)%a.length,c(a[g.current])},3e3))),()=>{d.current&&clearInterval(d.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current)return;const c=i.current,a=n.current,l=b=>{for(const C of b){const{width:y,height:w}=C.contentRect,P=window.devicePixelRatio||1;c.width=y*P,c.height=w*P,c.style.width=`${y}px`,c.style.height=`${w}px`;const S=c.getContext("2d");S&&S.scale(P,P),s.current=[];const z=Math.floor(350*(h.current.density??1)),M=h.current.colors,D=h.current.colorMode||"wave";for(let x=0;x<z;x++){const p=Math.random()*Math.PI*2,X=Math.sqrt(Math.random())*350,Y=Math.cos(p)*X,L=Math.sin(p)*X;let F;if(M&&M.length>0)F=D==="mixed"?M[x%M.length]:M[0];else if(h.current.color)F=h.current.color;else{const $=260+Math.random()*60,N=70+Math.random()*30,B=60+Math.random()*20;F=`hsl(${$}, ${N}%, ${B}%)`}let W=2+Math.random()*2;X>200&&(W*=.6),X<80&&(W*=1.5);const O=new rt(Y,L,F,W);O.x=y/2,O.y=w/2,s.current.push(O)}}},u=new ResizeObserver(l);u.observe(a);const R=c.getContext("2d");let E=0;const T=()=>{const b=a.getBoundingClientRect();R.globalCompositeOperation="source-over",e==="transparent"?R.clearRect(0,0,b.width,b.height):(R.fillStyle=e,R.fillRect(0,0,b.width,b.height)),o.current.initialized||(o.current.x=b.width/2,o.current.y=b.height/2,o.current.initialized=!0);let C=b.width/2,y=b.height/2;const w=r.current.active?r.current.x:null,P=r.current.active?r.current.y:null;w!==null&&P!==null&&(C=w,y=P);const S=C-o.current.x,I=y-o.current.y,z=Math.sqrt(S*S+I*I);let M=0,D=0;z>1?(M=S/z,D=I/z,o.current.angle=Math.atan2(D,M)):(M=Math.cos(o.current.angle),D=Math.sin(o.current.angle));const x=h.current.particleSpeed??1;E+=.02*x;const p=E%4;let X=1,Y=1,L=0;if(p<1){const B=p;X=1-Math.sin(B*Math.PI)*.3,Y=1+Math.sin(B*Math.PI)*.15,L=Math.sin(B*Math.PI)*12}else{const B=(p-1)/3;X=.7+.3*Math.sin(B*Math.PI/2),Y=1,L=0}const F=h.current.pointerTrackingSpeed??.02;o.current.x+=S*F,o.current.y+=I*F,o.current.x+=M*L*x,o.current.y+=D*L*x;const O=200*(Y+(p<1?p*.15:0)),$=R.createRadialGradient(o.current.x,o.current.y,0,o.current.x,o.current.y,O);$.addColorStop(0,"rgba(80, 150, 255, 0.05)"),$.addColorStop(1,"rgba(80, 150, 255, 0)"),R.fillStyle=$,R.beginPath(),R.arc(o.current.x,o.current.y,O,0,Math.PI*2),R.fill();const N=s.current;R.globalCompositeOperation="source-over";for(const B of N){B.update(o.current.x,o.current.y,E,X);const at=h.current.shape||"circle";B.draw(R,at,Y)}m.current=requestAnimationFrame(T)};return T(),()=>{u.disconnect(),cancelAnimationFrame(m.current)}},[e,t.density]),q.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden",pointerEvents:"none"},children:q.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%",pointerEvents:"none"}})})}const ot={position:"relative",border:"1px solid rgba(255, 255, 255, 0.1)",borderRadius:"1rem",overflow:"hidden",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",transition:"all 300ms ease-out"};function it({children:t,width:e="100%",height:n="60vh",backgroundColor:i="#050505",className:s="",style:m,background:r={name:"NONE"}}){return q.jsxs("div",{className:s,style:{...ot,width:e,height:n,backgroundColor:i,...m},children:[r.name==="FOLLOW_POINTER"&&q.jsx(tt,{config:r,backgroundColor:i}),r.name==="NET"&&q.jsx(nt,{config:r,backgroundColor:i}),r.name==="JELLYFISH"&&q.jsx(st,{config:r,backgroundColor:i}),q.jsx("div",{style:{position:"relative",zIndex:10,width:"100%",height:"100%"},children:t})]})}function k(t){const e=f.useRef({x:-1e3,y:-1e3,isDown:!1,active:!1});return f.useEffect(()=>{const n=t.current;if(!n)return;const i=o=>{const h=n.getBoundingClientRect();e.current.x=o.clientX-h.left,e.current.y=o.clientY-h.top,e.current.active=!0},s=()=>{e.current.active=!1},m=()=>{e.current.isDown=!0},r=()=>{e.current.isDown=!1};return n.addEventListener("pointermove",i),n.addEventListener("pointerleave",s),n.addEventListener("pointerdown",m),n.addEventListener("pointerup",r),n.style.touchAction="none",()=>{n.removeEventListener("pointermove",i),n.removeEventListener("pointerleave",s),n.removeEventListener("pointerdown",m),n.removeEventListener("pointerup",r)}},[t]),e}function H(t,e,n,i,s,m,r,o,h){if(s===null||m===null||!o&&h==="none")return{x:n,y:i};let g=n,d=i;const c=s-t,a=m-e,l=c*c+a*a,u=Math.sqrt(l);if(o&&!r&&l<3e4){const E=(3e4-l)/3e4;g+=c*E*.15,d+=a*E*.15}if(r&&h!=="none"){if(h==="attract"){if(l<3e4){const E=(3e4-l)/3e4;g+=c*E*.8,d+=a*E*.8}}else if(h==="repel"&&l<5e4&&u>0){const E=Math.pow(Math.max(0,5e4-l)/5e4,1.2);g-=c/u*E*400,d-=a/u*E*400}}return{x:g,y:d}}class J{constructor(e,n,i="255, 255, 255"){v(this,"x");v(this,"y");v(this,"vx");v(this,"vy");v(this,"targetX");v(this,"targetY");v(this,"baseColor");v(this,"opacity");v(this,"size");v(this,"sizeMultiplier");v(this,"friction");v(this,"ease");v(this,"easeMultiplier");v(this,"floatSpeed");v(this,"floatOffset");v(this,"randomSpeed");this.x=Math.random()*e,this.y=Math.random()*n,this.targetX=this.x,this.targetY=this.y,this.vx=0,this.vy=0,this.size=Math.random()*1.8+.5,this.sizeMultiplier=1,this.baseColor=Array.isArray(i)?i[Math.floor(Math.random()*i.length)]:i,this.opacity=.4+Math.random()*.6,this.friction=.82+Math.random()*.1,this.ease=.03+Math.random()*.05,this.easeMultiplier=1,this.floatSpeed=Math.random()*.02+.005,this.floatOffset=Math.random()*Math.PI*2,this.randomSpeed=Math.random()}update(e,n,i=null,s=null,m=!1,r=!0,o="none"){const{x:h,y:g}=H(this.x,this.y,this.targetX,this.targetY,i,s,m,r,o),d=h-this.x,c=g-this.y,a=n?0:Math.cos(e*.01+this.y*.01)*.5,l=n?0:Math.sin(e*.01+this.x*.01)*.5;this.vx+=d*(this.ease*this.easeMultiplier)+a,this.vy+=c*(this.ease*this.easeMultiplier)+l,this.vx*=this.friction,this.vy*=this.friction,this.x+=this.vx,this.y+=this.vy;const u=n?.2:2;this.x+=Math.cos(e*this.floatSpeed+this.floatOffset)*u,this.y+=Math.sin(e*this.floatSpeed+this.floatOffset)*u}draw(e,n="circle",i=0){e.fillStyle=`rgba(${this.baseColor}, ${this.opacity})`;const s=Math.max(.1,this.size*this.sizeMultiplier);if(n==="square")e.fillRect(this.x-s,this.y-s,s*2,s*2);else if(n==="bean"){const m=6+this.size*2*this.sizeMultiplier,r=Math.sin(i*.05+this.x*.01+this.randomSpeed*5),o=.4+.6*((r+1)/2),h=m*.5*o,g=Math.max(.8,s*1.5*(.8+.2*r)),d=this.vx!==0||this.vy!==0?Math.atan2(this.vy,this.vx):0;e.beginPath(),e.ellipse(this.x,this.y,h,g,d,0,Math.PI*2),e.fill()}else e.beginPath(),e.arc(this.x,this.y,s,0,Math.PI*2),e.fill()}}function G(t,e,n){if(e<=0||n<=0)return[];const i=document.createElement("canvas");i.width=e,i.height=n;const s=i.getContext("2d",{willReadFrequently:!0});if(!s)return[];s.clearRect(0,0,e,n);let m=Math.min(e,n)*.65;s.font=`bold ${m}px "Georgia", serif`;const r=s.measureText(t);r.width>e*.9&&(m=m*(e*.9)/r.width,s.font=`bold ${m}px "Georgia", serif`),s.fillStyle="white",s.textAlign="center",s.textBaseline="middle",s.fillText(t,e/2,n/2.05);const h=s.getImageData(0,0,e,n).data,g=[],d=window.innerWidth<600?6:8;for(let c=0;c<n;c+=d)for(let a=0;a<e;a+=d){const l=(c*e+a)*4;h[l+3]>128&&g.push({x:a+(Math.random()-.5)*4,y:c+(Math.random()-.5)*4})}return g}function K(t,e,n){const i=f.useRef(t);return f.useEffect(()=>{i.current=t},[t]),{getPixelsForText:G,updateTextTargets:(m,r,o)=>{var T,b;const h=r||((T=n.current)==null?void 0:T.offsetWidth)||window.innerWidth,g=o||((b=n.current)==null?void 0:b.offsetHeight)||window.innerHeight;if(!m){e.current.forEach(y=>{const w=50+Math.random()*(h-100),P=50+Math.random()*(g-100);(Math.abs(w-y.x)>20||Math.abs(P-y.y)>20)&&(y.vx+=(Math.random()-.5)*20,y.vy+=(Math.random()-.5)*20),y.targetX=w,y.targetY=P});return}const d=G(m,h,g);if(d.length===0)return;const c=h*.15,a=d.map(C=>({pt:C,key:C.x+(Math.random()-.5)*c}));a.sort((C,y)=>C.key-y.key);const l=a.map(C=>C.pt),u=e.current.map((C,y)=>({i:y,key:C.x+(Math.random()-.5)*c}));u.sort((C,y)=>C.key-y.key);const R=u.map(C=>C.i),E=Math.ceil(Math.sqrt(R.length));for(let C=0;C<R.length;C+=E){const y=Math.min(C+E,R.length),w=R.slice(C,y),P=[];for(let S=C;S<y;S++)P.push(l[S%l.length]);w.sort((S,I)=>e.current[S].y-e.current[I].y),P.sort((S,I)=>S.y-I.y);for(let S=0;S<w.length;S++){const I=w[S],z=e.current[I],M=P[S],D=M.x-z.x,x=M.y-z.y;if(Math.abs(D)>20||Math.abs(x)>20){z.vx+=(Math.random()-.5)*20,z.vy+=(Math.random()-.5)*20;const p=(Math.random()>.5?1:-1)*(Math.random()*10+5);z.vx+=Math.sign(x)*p,z.vy-=Math.sign(D)*p}z.targetX=M.x,z.targetY=M.y}}},textRef:i}}const j=t=>{if(!t||typeof t!="string")return"0, 0, 0";try{let e=0,n=0,i=0;if(t.length===4)e=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16),i=parseInt(t[3]+t[3],16);else if(t.length===7)e=parseInt(t.substring(1,3),16),n=parseInt(t.substring(3,5),16),i=parseInt(t.substring(5,7),16);else return t;return`${e}, ${n}, ${i}`}catch{return"0, 0, 0"}};function ct({text:t,particleColor:e="255, 255, 255",particleSize:n=1,particleDensity:i=1,particleEase:s=1,isMagnet:m=!0,clickMode:r="none",particleShape:o="circle",backgroundColor:h="#050505"}){const g=f.useRef(null),d=f.useRef(null),c=f.useRef([]),a=f.useRef(0),l=f.useRef(0),u=k(d),R=f.useRef({isMagnet:m,clickMode:r,particleShape:o,backgroundColor:h});R.current={isMagnet:m,clickMode:r,particleShape:o,backgroundColor:h};const{updateTextTargets:E,textRef:T}=K(t,c,d),b=()=>Array.isArray(e)?e.map(y=>j(y)):j(e),C=(y,w,P=1)=>{const S=window.innerWidth<600?1500:3e3,I=Math.floor(S*P),z=[],M=b();for(let D=0;D<I;D++){const x=new J(y,w,M);x.sizeMultiplier=n,x.easeMultiplier=s,z.push(x)}c.current=z};return f.useEffect(()=>{if(c.current.length>0){const y=b();c.current.forEach(w=>{w.baseColor=Array.isArray(y)?y[Math.floor(Math.random()*y.length)]:y})}},[e]),f.useEffect(()=>{c.current.length>0&&c.current.forEach(y=>{y.sizeMultiplier=n})},[n]),f.useEffect(()=>{c.current.length>0&&c.current.forEach(y=>{y.easeMultiplier=s})},[s]),f.useEffect(()=>{if(c.current.length>0&&g.current&&d.current){const y=window.innerWidth<600?1500:3e3,w=Math.floor(y*i),P=c.current.length;if(w>P){const S=d.current.getBoundingClientRect(),I=b();for(let z=0;z<w-P;z++){const M=new J(S.width,S.height,I);M.sizeMultiplier=n,c.current.push(M)}E(t)}else w<P&&c.current.splice(w)}},[i]),f.useEffect(()=>{const y=d.current,w=g.current;if(!y||!w)return;const P=M=>{for(const D of M){const{width:x,height:p}=D.contentRect,X=window.devicePixelRatio||1;w.width=x*X,w.height=p*X,w.style.width=`${x}px`,w.style.height=`${p}px`;const Y=w.getContext("2d");Y&&Y.scale(X,X),c.current.length===0&&C(x,p,i),E(t,x,p)}},S=new ResizeObserver(P);S.observe(y);const I=w.getContext("2d"),z=()=>{l.current++;const M=y.getBoundingClientRect(),{isMagnet:D,clickMode:x,particleShape:p,backgroundColor:X}=R.current;if(X==="transparent")I.clearRect(0,0,M.width,M.height),I.globalCompositeOperation="source-over";else{const O=j(X);I.fillStyle=`rgba(${O}, 0.25)`,I.fillRect(0,0,M.width,M.height),I.globalCompositeOperation="screen"}const Y=T.current!=="",L=u.current.active?u.current.x:null,F=u.current.active?u.current.y:null,W=u.current.isDown;for(let O=0;O<c.current.length;O++){const $=c.current[O];$.update(l.current,!!Y,L,F,W,D,x),$.draw(I,p,l.current)}I.globalCompositeOperation="source-over",a.current=requestAnimationFrame(z)};return z(),()=>{S.disconnect(),cancelAnimationFrame(a.current)}},[]),f.useEffect(()=>{E(t)},[t]),q.jsx("div",{ref:d,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:q.jsx("canvas",{ref:g,style:{display:"block",width:"100%",height:"100%"}})})}A.ParticleCanvas=it,A.TextParticleEngine=ct,A.getMagnetTarget=H,A.useParticleInteraction=k,A.useTextParticles=K,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(B,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],T):(B=typeof globalThis<"u"?globalThis:B||self,T(B.JlParticleInteractive={},B.ReactJsxRuntime,B.React))})(this,(function(B,T,f){"use strict";var ht=Object.defineProperty;var ut=(B,T,f)=>T in B?ht(B,T,{enumerable:!0,configurable:!0,writable:!0,value:f}):B[T]=f;var m=(B,T,f)=>ut(B,typeof T!="symbol"?T+"":T,f);function U(t,e,n,i){let s=e+t.baseX,g=n+t.baseY;s+=Math.sin(i*t.randomSpeed+t.baseY*.05)*15*t.z,g+=Math.cos(i*t.randomSpeed+t.baseX*.05)*15*t.z;const r=s-t.x,o=g-t.y,h=r*.06,v=o*.06;return{forceX:h,forceY:v}}function Q(t,e,n,i,s,g){const r=i,o=s,h=t.x-r,v=t.y-o,d=Math.max(Math.sqrt(h*h+v*v),1);let c=0,a=0;const u=Math.sin(d*.02-g*3)*2.5*t.z;c+=h/d*u,a+=v/d*u;const E=Math.cos(d*.01-g*1+t.randomSpeed)*.8*t.z,q=-v/d,b=h/d;return c+=q*E,a+=b*E,{forceX:c,forceY:a,dxCenter:h,dyCenter:v,distToCenter:d}}function V(t,e){let s=Math.min(e/400,1)*2.5+t.sizeBias*1;s<.4&&(s=0),t.scale+=(s-t.scale)*.15}function Z(t,e,n,i,s,g){let r=0,o=0;s==="horizontal"?(r=1,o=0):s==="diagonal"?(r=-e/i,o=-n/i):(r=-n/i,o=e/i);const h=Math.atan2(o,r),v=t.sizeBias>.3?1:0,d=Math.max(0,Math.sin(g*.5+t.randomSpeed*10)),c=Math.sin(g*3+t.baseX*.1+t.randomSpeed)*.5*d*v;r=Math.cos(h+c),o=Math.sin(h+c);const a=Math.max(1-i/400,.1);s==="horizontal"?(t.dirX=t.dirX*(1-.2)+r*.2,t.dirY=t.dirY*(1-.2)+o*.2):(t.dirX=t.dirX*(1-a*.3)+r*a*.3,t.dirY=t.dirY*(1-a*.3)+o*a*.3);const l=Math.sqrt(t.dirX*t.dirX+t.dirY*t.dirY);l>0&&(t.dirX/=l,t.dirY/=l)}class tt{constructor(e,n,i){m(this,"x");m(this,"y");m(this,"baseX");m(this,"baseY");m(this,"z");m(this,"vx");m(this,"vy");m(this,"color");m(this,"targetColor",null);m(this,"colorDelay",0);m(this,"angleTarget");m(this,"randomSpeed");m(this,"sizeBias");m(this,"scale");m(this,"dirX");m(this,"dirY");m(this,"initialized",!1);this.x=e,this.y=n,this.baseX=e,this.baseY=n,this.z=Math.random()*1.5+.2,this.vx=0,this.vy=0,this.color=i,this.angleTarget=Math.random()*Math.PI*2,this.randomSpeed=Math.random()*2+1,this.sizeBias=Math.random(),this.scale=1,this.dirX=Math.cos(this.angleTarget),this.dirY=Math.sin(this.angleTarget)}update(e,n,i,s,g,r,o,h="vertical"){this.initialized||(this.x=i+this.baseX,this.y=s+this.baseY,this.initialized=!0);const{forceX:v,forceY:d,dxCenter:c,dyCenter:a,distToCenter:l}=Q(this,e,n,i,s,o),{forceX:u,forceY:R}=U(this,i,s,o);this.vx+=v+u,this.vy+=d+R,this.vx*=.75,this.vy*=.75,this.x+=this.vx,this.y+=this.vy,V(this,l),Z(this,c,a,l,h,o),this.targetColor&&(this.colorDelay-=1,this.colorDelay<=0&&(this.color=this.targetColor,this.targetColor=null))}draw(e,n,i="bean"){if(this.scale<=.05)return;e.fillStyle=this.color;const s=Math.sqrt(this.baseX*this.baseX+this.baseY*this.baseY),g=Math.max(0,1-s/350);if(e.globalAlpha=Math.min(1,(.5+this.z*.5)*Math.min(this.scale,1)*g),!(e.globalAlpha<=.01))if(i==="circle"){const r=Math.max(.1,2*this.scale*this.z);e.beginPath(),e.arc(this.x,this.y,r,0,Math.PI*2),e.fill()}else if(i==="square"){const r=Math.max(.1,2*this.scale*this.z);e.fillRect(this.x-r,this.y-r,r*2,r*2)}else{const o=(6+this.sizeBias*6)*this.scale,h=Math.sin(n*3.5+this.baseX*.1+this.randomSpeed*5),v=.4+.6*((h+1)/2),d=o*.5*v,c=Math.max(.8,this.z*1.5*this.scale*(.8+.2*h)),a=Math.atan2(this.dirY,this.dirX);e.beginPath(),e.ellipse(this.x,this.y,d,c,a,0,Math.PI*2),e.fill()}}}function et({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),g=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,isDown:!1,active:!1}),o=f.useRef({x:0,y:0,initialized:!1});f.useEffect(()=>{const c=l=>{if(!n.current)return;const u=n.current.getBoundingClientRect();r.current.x=l.clientX-u.left,r.current.y=l.clientY-u.top,r.current.active=!0},a=()=>{r.current.active=!1};return window.addEventListener("pointermove",c),window.addEventListener("pointerleave",a),()=>{window.removeEventListener("pointermove",c),window.removeEventListener("pointerleave",a)}},[]);const h=f.useRef(t),v=f.useRef(null),d=f.useRef(0);return f.useEffect(()=>{h.current=t},[t]),f.useEffect(()=>{if(v.current&&(clearInterval(v.current),v.current=null),!t.colors||t.colors.length===0){const a=t.color||"#8B5CF6";s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.random()*20});return}const c=a=>{const l=r.current.active?r.current.x:o.current.x,u=r.current.active?r.current.y:o.current.y;s.current.forEach(R=>{const E=R.x-l,q=R.y-u,b=Math.sqrt(E*E+q*q);R.targetColor=a,R.colorDelay=Math.max(0,b*.15)})};return t.colorMode==="mixed"?s.current.forEach((a,l)=>{a.targetColor=t.colors[l%t.colors.length],a.colorDelay=Math.random()*20}):(d.current=0,c(t.colors[0]),t.colors.length>1&&(v.current=setInterval(()=>{const a=t.colors;d.current=(d.current+1)%a.length,c(a[d.current])},3e3))),()=>{v.current&&clearInterval(v.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current||h.current.name==="NONE")return;const c=i.current,a=n.current,l=b=>{for(const C of b){const{width:y,height:w}=C.contentRect,P=window.devicePixelRatio||1;c.width=y*P,c.height=w*P,c.style.width=`${y}px`,c.style.height=`${w}px`;const S=c.getContext("2d");S&&S.scale(P,P),s.current=[];const z=Math.floor(350*(h.current.density??1)),M=h.current.colors,D=h.current.colorMode||"wave";for(let x=0;x<z;x++){const p=Math.sqrt(Math.random())*350,X=Math.random()*Math.PI*2,Y=Math.cos(X)*p,L=Math.sin(X)*p;let F;if(M&&M.length>0)F=D==="mixed"?M[x%M.length]:M[0];else if(h.current.color)F=h.current.color;else{const A=210+Math.max(0,Math.min(1,(Y+350)/700))*130+(Math.random()*15-7.5),$=75+Math.random()*25,k=60+Math.random()*15;F=`hsl(${A}, ${$}%, ${k}%)`}s.current.push(new tt(Y,L,F))}}},u=new ResizeObserver(l);u.observe(a);const R=c.getContext("2d");let E=0;const q=()=>{const b=a.getBoundingClientRect();if(R.clearRect(0,0,b.width,b.height),e!=="transparent"&&(R.fillStyle=e,R.fillRect(0,0,b.width,b.height)),o.current.initialized||(o.current.x=b.width/2,o.current.y=b.height/2,o.current.initialized=!0),h.current.name==="FOLLOW_POINTER"){let C=b.width/2,y=b.height/2;const w=r.current.active?r.current.x:null,P=r.current.active?r.current.y:null;w!==null&&P!==null&&(C=w,y=P);const S=h.current.pointerTrackingSpeed??.06;o.current.x+=(C-o.current.x)*S,o.current.y+=(y-o.current.y)*S;const I=h.current.particleSpeed??1;E+=.012*I;const z=s.current,M=18,D=M*M;for(let x=0;x<z.length;x++){const p=z[x];for(let X=x+1;X<z.length;X++){const Y=z[X],L=p.x-Y.x,F=p.y-Y.y,W=L*L+F*F;if(W<D&&W>0){const A=Math.sqrt(W),$=(M-A)/M,k=L/A*$*.8,O=F/A*$*.8;p.x+=k,p.y+=O,Y.x-=k,Y.y-=O,p.vx+=k*.1,p.vy+=O*.1,Y.vx-=k*.1,Y.vy-=O*.1}}}for(const x of z){x.update(w,P,o.current.x,o.current.y,b.width,b.height,E,h.current.orientation);const p=h.current.shape||"bean";x.draw(R,E,p)}}g.current=requestAnimationFrame(q)};return q(),()=>{u.disconnect(),cancelAnimationFrame(g.current)}},[e,t.density]),t.name==="NONE"?null:T.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:T.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%"}})})}class nt{constructor(e,n){m(this,"x");m(this,"y");m(this,"vx");m(this,"vy");m(this,"radius");m(this,"currentColor","#8B5CF6");m(this,"targetColor",null);m(this,"colorDelay",0);this.x=e,this.y=n;const i=Math.random()*Math.PI*2,s=Math.random()*.5+.1;this.vx=Math.cos(i)*s,this.vy=Math.sin(i)*s,this.radius=Math.random()*1.5+1}update(e,n,i,s,g=1,r=.06){if(this.x+=this.vx*g,this.y+=this.vy*g,this.x<0?(this.x=0,this.vx*=-1):this.x>e&&(this.x=e,this.vx*=-1),this.y<0?(this.y=0,this.vy*=-1):this.y>n&&(this.y=n,this.vy*=-1),i!==null&&s!==null){const o=i-this.x,h=s-this.y,v=o*o+h*h,d=150,c=d*d;if(v<c){const a=Math.sqrt(v),l=(d-a)/d,u=r/.06;this.x-=o/a*l*2*u,this.y-=h/a*l*2*u}}this.targetColor&&(this.colorDelay-=1*g,this.colorDelay<=0&&(this.currentColor=this.targetColor,this.targetColor=null))}draw(e,n="circle",i=0){if(e.fillStyle=this.currentColor,n==="square")e.fillRect(this.x-this.radius,this.y-this.radius,this.radius*2,this.radius*2);else if(n==="bean"){const s=Math.sin(i*.05+this.x*.01+this.y*.01),g=this.radius*2*(.8+.4*s),r=this.radius*(.8+.2*s),o=this.vx!==0||this.vy!==0?Math.atan2(this.vy,this.vx):0;e.beginPath(),e.ellipse(this.x,this.y,g,r,o,0,Math.PI*2),e.fill()}else e.beginPath(),e.arc(this.x,this.y,this.radius,0,Math.PI*2),e.fill()}}function rt({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),g=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,active:!1});f.useEffect(()=>{const d=a=>{if(!n.current)return;const l=n.current.getBoundingClientRect();r.current.x=a.clientX-l.left,r.current.y=a.clientY-l.top,r.current.active=!0},c=()=>{r.current.active=!1};return window.addEventListener("pointermove",d),window.addEventListener("pointerleave",c),()=>{window.removeEventListener("pointermove",d),window.removeEventListener("pointerleave",c)}},[]);const o=f.useRef(t),h=f.useRef(0),v=f.useRef(null);return f.useEffect(()=>{o.current=t},[t]),f.useEffect(()=>{if(v.current&&(clearInterval(v.current),v.current=null),!t.colors||t.colors.length===0){const l=t.color||"#8B5CF6";s.current.forEach(u=>{u.targetColor=l,u.colorDelay=Math.random()*20});return}const d=r.current.active?r.current.x:n.current?n.current.clientWidth/2:0,c=r.current.active?r.current.y:n.current?n.current.clientHeight/2:0,a=l=>{s.current.forEach(u=>{const R=u.x-d,E=u.y-c,q=Math.sqrt(R*R+E*E);u.targetColor=l,u.colorDelay=Math.max(0,q*.2)})};return t.colorMode==="mixed"?s.current.forEach((l,u)=>{l.targetColor=t.colors[u%t.colors.length],l.colorDelay=Math.random()*20}):(h.current=0,a(t.colors[0]),t.colors.length>1&&(v.current=setInterval(()=>{const l=t.colors;h.current=(h.current+1)%l.length,a(l[h.current])},3e3))),()=>{v.current&&clearInterval(v.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current)return;const d=i.current,c=n.current,a=q=>{for(const b of q){const{width:C,height:y}=b.contentRect,w=window.devicePixelRatio||1;d.width=C*w,d.height=y*w,d.style.width=`${C}px`,d.style.height=`${y}px`;const P=d.getContext("2d");P&&P.scale(w,w),s.current=[];const S=C*y,I=o.current.density??1,z=Math.min(Math.floor(300*I),Math.floor(S/6e3*I)),M=o.current.colors,D=o.current.colorMode||"wave";for(let x=0;x<z;x++){const p=new nt(Math.random()*C,Math.random()*y);M&&M.length>0?p.currentColor=D==="mixed"?M[x%M.length]:M[0]:o.current.color&&(p.currentColor=o.current.color),s.current.push(p)}}},l=new ResizeObserver(a);l.observe(c);const u=d.getContext("2d");let R=0;const E=()=>{R+=1;const q=c.getBoundingClientRect();u.clearRect(0,0,q.width,q.height),e!=="transparent"&&(u.fillStyle=e,u.fillRect(0,0,q.width,q.height));const b=r.current.active?r.current.x:null,C=r.current.active?r.current.y:null,y=s.current,w=o.current.shape||"circle",P=120,S=P*P,I=o.current.particleSpeed??1,z=o.current.pointerTrackingSpeed??.06;for(let M=0;M<y.length;M++){const D=y[M];D.update(q.width,q.height,b,C,I,z),u.globalAlpha=1,D.draw(u,w,R);for(let x=M+1;x<y.length;x++){const p=y[x],X=D.x-p.x,Y=D.y-p.y,L=X*X+Y*Y;if(L<S){const F=1-Math.sqrt(L)/P;u.beginPath(),u.moveTo(D.x,D.y),u.lineTo(p.x,p.y),u.strokeStyle=D.currentColor,u.globalAlpha=F*.5,u.lineWidth=1,u.stroke()}}}if(u.globalAlpha=1,b!==null&&C!==null)for(let x=0;x<y.length;x++){const p=y[x],X=p.x-b,Y=p.y-C,L=X*X+Y*Y;if(L<22500){const F=1-Math.sqrt(L)/150;u.beginPath(),u.moveTo(p.x,p.y),u.lineTo(b,C),u.strokeStyle=p.currentColor,u.globalAlpha=F*.8,u.lineWidth=1.5,u.stroke()}}u.globalAlpha=1,g.current=requestAnimationFrame(E)};return E(),()=>{l.disconnect(),cancelAnimationFrame(g.current)}},[e,t.density]),T.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:T.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%"}})})}class st{constructor(e,n,i,s){m(this,"x",0);m(this,"y",0);m(this,"baseX");m(this,"baseY");m(this,"vx",0);m(this,"vy",0);m(this,"color");m(this,"size");m(this,"angle");m(this,"dist");m(this,"spring");m(this,"friction");m(this,"targetColor",null);m(this,"colorDelay",0);this.baseX=e,this.baseY=n,this.color=i,this.size=s,this.angle=Math.atan2(n,e),this.dist=Math.sqrt(e*e+n*n);const g=Math.min(1,this.dist/350);this.spring=.15-g*.13,this.friction=.85+g*.1}update(e,n,i,s){const r=1+Math.sin(this.angle*3+i*1.2)*.05+Math.cos(this.angle*5-i*.6)*.03,o=this.dist*s*r,h=Math.cos(this.angle)*o,v=Math.sin(this.angle)*o,d=this.dist*.1*r,c=Math.sin(i*3+this.dist*.05)*d,a=e+h+Math.cos(this.angle+Math.PI/2)*c,l=n+v+Math.sin(this.angle+Math.PI/2)*c,u=a-this.x,R=l-this.y;this.vx+=u*this.spring,this.vy+=R*this.spring,this.vx*=this.friction,this.vy*=this.friction,this.x+=this.vx,this.y+=this.vy,this.targetColor&&(this.colorDelay-=1,this.colorDelay<=0&&(this.color=this.targetColor,this.targetColor=null))}draw(e,n,i){const s=Math.min(1,this.dist/350),g=1+(1-s)*(i-1)*1.5,r=this.size*g;e.globalAlpha=Math.max(.15,1-s*.7),e.fillStyle=this.color,e.beginPath(),n==="circle"?e.arc(this.x,this.y,r,0,Math.PI*2):n==="square"?e.rect(this.x-r,this.y-r,r*2,r*2):e.ellipse(this.x,this.y,r*1.5,r,0,0,Math.PI*2),e.fill()}}function ot({config:t,backgroundColor:e}){const n=f.useRef(null),i=f.useRef(null),s=f.useRef([]),g=f.useRef(0),r=f.useRef({x:-1e3,y:-1e3,active:!1}),o=f.useRef({x:0,y:0,initialized:!1,angle:-Math.PI/2});f.useEffect(()=>{const c=a=>{if(!n.current)return;const l=n.current.getBoundingClientRect();r.current.x=a.clientX-l.left,r.current.y=a.clientY-l.top,r.current.active=!0};return window.addEventListener("pointermove",c),()=>{window.removeEventListener("pointermove",c)}},[]);const h=f.useRef(t),v=f.useRef(0),d=f.useRef(null);return f.useEffect(()=>{h.current=t},[t]),f.useEffect(()=>{if(d.current&&(clearInterval(d.current),d.current=null),!t.colors||t.colors.length===0){const a=t.color||"#8B5CF6";s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.random()*20});return}const c=a=>{s.current.forEach(l=>{l.targetColor=a,l.colorDelay=Math.max(0,l.dist*.2)})};return t.colorMode==="mixed"?s.current.forEach((a,l)=>{a.targetColor=t.colors[l%t.colors.length],a.colorDelay=Math.max(0,a.dist*.2)+Math.random()*10}):(v.current=0,c(t.colors[0]),t.colors.length>1&&(d.current=setInterval(()=>{const a=t.colors;v.current=(v.current+1)%a.length,c(a[v.current])},3e3))),()=>{d.current&&clearInterval(d.current)}},[t.colors,t.color,t.colorMode]),f.useEffect(()=>{if(!n.current||!i.current)return;const c=i.current,a=n.current,l=b=>{for(const C of b){const{width:y,height:w}=C.contentRect,P=window.devicePixelRatio||1;c.width=y*P,c.height=w*P,c.style.width=`${y}px`,c.style.height=`${w}px`;const S=c.getContext("2d");S&&S.scale(P,P),s.current=[];const z=Math.floor(350*(h.current.density??1)),M=h.current.colors,D=h.current.colorMode||"wave";for(let x=0;x<z;x++){const p=Math.random()*Math.PI*2,X=Math.sqrt(Math.random())*350,Y=Math.cos(p)*X,L=Math.sin(p)*X;let F;if(M&&M.length>0)F=D==="mixed"?M[x%M.length]:M[0];else if(h.current.color)F=h.current.color;else{const $=260+Math.random()*60,k=70+Math.random()*30,O=60+Math.random()*20;F=`hsl(${$}, ${k}%, ${O}%)`}let W=2+Math.random()*2;X>200&&(W*=.6),X<80&&(W*=1.5);const A=new st(Y,L,F,W);A.x=y/2,A.y=w/2,s.current.push(A)}}},u=new ResizeObserver(l);u.observe(a);const R=c.getContext("2d");let E=0;const q=()=>{const b=a.getBoundingClientRect();R.globalCompositeOperation="source-over",e==="transparent"?R.clearRect(0,0,b.width,b.height):(R.fillStyle=e,R.fillRect(0,0,b.width,b.height)),o.current.initialized||(o.current.x=b.width/2,o.current.y=b.height/2,o.current.initialized=!0);let C=b.width/2,y=b.height/2;const w=r.current.active?r.current.x:null,P=r.current.active?r.current.y:null;w!==null&&P!==null&&(C=w,y=P);const S=C-o.current.x,I=y-o.current.y,z=Math.sqrt(S*S+I*I);let M=0,D=0;z>1?(M=S/z,D=I/z,o.current.angle=Math.atan2(D,M)):(M=Math.cos(o.current.angle),D=Math.sin(o.current.angle));const x=h.current.particleSpeed??1;E+=.02*x;const p=E%4;let X=1,Y=1,L=0;if(p<1){const O=p;X=1-Math.sin(O*Math.PI)*.3,Y=1+Math.sin(O*Math.PI)*.15,L=Math.sin(O*Math.PI)*12}else{const O=(p-1)/3;X=.7+.3*Math.sin(O*Math.PI/2),Y=1,L=0}const F=h.current.pointerTrackingSpeed??.02;o.current.x+=S*F,o.current.y+=I*F,o.current.x+=M*L*x,o.current.y+=D*L*x;const A=200*(Y+(p<1?p*.15:0)),$=R.createRadialGradient(o.current.x,o.current.y,0,o.current.x,o.current.y,A);$.addColorStop(0,"rgba(80, 150, 255, 0.05)"),$.addColorStop(1,"rgba(80, 150, 255, 0)"),R.fillStyle=$,R.beginPath(),R.arc(o.current.x,o.current.y,A,0,Math.PI*2),R.fill();const k=s.current;R.globalCompositeOperation="source-over";for(const O of k){O.update(o.current.x,o.current.y,E,X);const lt=h.current.shape||"circle";O.draw(R,lt,Y)}g.current=requestAnimationFrame(q)};return q(),()=>{u.disconnect(),cancelAnimationFrame(g.current)}},[e,t.density]),T.jsx("div",{ref:n,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden",pointerEvents:"none"},children:T.jsx("canvas",{ref:i,style:{display:"block",width:"100%",height:"100%",pointerEvents:"none"}})})}const it={position:"relative",border:"1px solid rgba(255, 255, 255, 0.1)",borderRadius:"1rem",overflow:"hidden",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",transition:"all 300ms ease-out"};function j({children:t,width:e="100%",height:n="60vh",backgroundColor:i="#050505",className:s="",style:g,background:r={name:"NONE"}}){return T.jsxs("div",{className:s,style:{...it,width:e,height:n,backgroundColor:i,...g},children:[r.name==="FOLLOW_POINTER"&&T.jsx(et,{config:r,backgroundColor:i}),r.name==="NET"&&T.jsx(rt,{config:r,backgroundColor:i}),r.name==="JELLYFISH"&&T.jsx(ot,{config:r,backgroundColor:i}),T.jsx("div",{style:{position:"relative",zIndex:10,width:"100%",height:"100%"},children:t})]})}function H(t){const e=f.useRef({x:-1e3,y:-1e3,isDown:!1,active:!1});return f.useEffect(()=>{const n=t.current;if(!n)return;const i=o=>{const h=n.getBoundingClientRect();e.current.x=o.clientX-h.left,e.current.y=o.clientY-h.top,e.current.active=!0},s=()=>{e.current.active=!1},g=()=>{e.current.isDown=!0},r=()=>{e.current.isDown=!1};return n.addEventListener("pointermove",i),n.addEventListener("pointerleave",s),n.addEventListener("pointerdown",g),n.addEventListener("pointerup",r),n.style.touchAction="none",()=>{n.removeEventListener("pointermove",i),n.removeEventListener("pointerleave",s),n.removeEventListener("pointerdown",g),n.removeEventListener("pointerup",r)}},[t]),e}function J(t,e,n,i,s,g,r,o,h){if(s===null||g===null||!o&&h==="none")return{x:n,y:i};let v=n,d=i;const c=s-t,a=g-e,l=c*c+a*a,u=Math.sqrt(l);if(o&&!r&&l<3e4){const E=(3e4-l)/3e4;v+=c*E*.15,d+=a*E*.15}if(r&&h!=="none"){if(h==="attract"){if(l<3e4){const E=(3e4-l)/3e4;v+=c*E*.8,d+=a*E*.8}}else if(h==="repel"&&l<5e4&&u>0){const E=Math.pow(Math.max(0,5e4-l)/5e4,1.2);v-=c/u*E*400,d-=a/u*E*400}}return{x:v,y:d}}class G{constructor(e,n,i="255, 255, 255"){m(this,"x");m(this,"y");m(this,"vx");m(this,"vy");m(this,"targetX");m(this,"targetY");m(this,"baseColor");m(this,"opacity");m(this,"size");m(this,"sizeMultiplier");m(this,"friction");m(this,"ease");m(this,"easeMultiplier");m(this,"floatSpeed");m(this,"floatOffset");m(this,"randomSpeed");this.x=Math.random()*e,this.y=Math.random()*n,this.targetX=this.x,this.targetY=this.y,this.vx=0,this.vy=0,this.size=Math.random()*1.8+.5,this.sizeMultiplier=1,this.baseColor=Array.isArray(i)?i[Math.floor(Math.random()*i.length)]:i,this.opacity=.4+Math.random()*.6,this.friction=.82+Math.random()*.1,this.ease=.03+Math.random()*.05,this.easeMultiplier=1,this.floatSpeed=Math.random()*.02+.005,this.floatOffset=Math.random()*Math.PI*2,this.randomSpeed=Math.random()}update(e,n,i=null,s=null,g=!1,r=!0,o="none"){const{x:h,y:v}=J(this.x,this.y,this.targetX,this.targetY,i,s,g,r,o),d=h-this.x,c=v-this.y,a=n?0:Math.cos(e*.01+this.y*.01)*.5,l=n?0:Math.sin(e*.01+this.x*.01)*.5;this.vx+=d*(this.ease*this.easeMultiplier)+a,this.vy+=c*(this.ease*this.easeMultiplier)+l,this.vx*=this.friction,this.vy*=this.friction,this.x+=this.vx,this.y+=this.vy;const u=n?.2:2;this.x+=Math.cos(e*this.floatSpeed+this.floatOffset)*u,this.y+=Math.sin(e*this.floatSpeed+this.floatOffset)*u}draw(e,n="circle",i=0){e.fillStyle=`rgba(${this.baseColor}, ${this.opacity})`;const s=Math.max(.1,this.size*this.sizeMultiplier);if(n==="square")e.fillRect(this.x-s,this.y-s,s*2,s*2);else if(n==="bean"){const g=6+this.size*2*this.sizeMultiplier,r=Math.sin(i*.05+this.x*.01+this.randomSpeed*5),o=.4+.6*((r+1)/2),h=g*.5*o,v=Math.max(.8,s*1.5*(.8+.2*r)),d=this.vx!==0||this.vy!==0?Math.atan2(this.vy,this.vx):0;e.beginPath(),e.ellipse(this.x,this.y,h,v,d,0,Math.PI*2),e.fill()}else e.beginPath(),e.arc(this.x,this.y,s,0,Math.PI*2),e.fill()}}function K(t,e,n){if(e<=0||n<=0)return[];const i=document.createElement("canvas");i.width=e,i.height=n;const s=i.getContext("2d",{willReadFrequently:!0});if(!s)return[];s.clearRect(0,0,e,n);let g=Math.min(e,n)*.65;s.font=`bold ${g}px "Georgia", serif`;const r=s.measureText(t);r.width>e*.9&&(g=g*(e*.9)/r.width,s.font=`bold ${g}px "Georgia", serif`),s.fillStyle="white",s.textAlign="center",s.textBaseline="middle",s.fillText(t,e/2,n/2.05);const h=s.getImageData(0,0,e,n).data,v=[],d=window.innerWidth<600?6:8;for(let c=0;c<n;c+=d)for(let a=0;a<e;a+=d){const l=(c*e+a)*4;h[l+3]>128&&v.push({x:a+(Math.random()-.5)*4,y:c+(Math.random()-.5)*4})}return v}function _(t,e,n){const i=f.useRef(t);return f.useEffect(()=>{i.current=t},[t]),{getPixelsForText:K,updateTextTargets:(g,r,o)=>{var q,b;const h=r||((q=n.current)==null?void 0:q.offsetWidth)||window.innerWidth,v=o||((b=n.current)==null?void 0:b.offsetHeight)||window.innerHeight;if(!g){e.current.forEach(y=>{const w=50+Math.random()*(h-100),P=50+Math.random()*(v-100);(Math.abs(w-y.x)>20||Math.abs(P-y.y)>20)&&(y.vx+=(Math.random()-.5)*20,y.vy+=(Math.random()-.5)*20),y.targetX=w,y.targetY=P});return}const d=K(g,h,v);if(d.length===0)return;const c=h*.15,a=d.map(C=>({pt:C,key:C.x+(Math.random()-.5)*c}));a.sort((C,y)=>C.key-y.key);const l=a.map(C=>C.pt),u=e.current.map((C,y)=>({i:y,key:C.x+(Math.random()-.5)*c}));u.sort((C,y)=>C.key-y.key);const R=u.map(C=>C.i),E=Math.ceil(Math.sqrt(R.length));for(let C=0;C<R.length;C+=E){const y=Math.min(C+E,R.length),w=R.slice(C,y),P=[];for(let S=C;S<y;S++)P.push(l[S%l.length]);w.sort((S,I)=>e.current[S].y-e.current[I].y),P.sort((S,I)=>S.y-I.y);for(let S=0;S<w.length;S++){const I=w[S],z=e.current[I],M=P[S],D=M.x-z.x,x=M.y-z.y;if(Math.abs(D)>20||Math.abs(x)>20){z.vx+=(Math.random()-.5)*20,z.vy+=(Math.random()-.5)*20;const p=(Math.random()>.5?1:-1)*(Math.random()*10+5);z.vx+=Math.sign(x)*p,z.vy-=Math.sign(D)*p}z.targetX=M.x,z.targetY=M.y}}},textRef:i}}const N=t=>{if(!t||typeof t!="string")return"0, 0, 0";try{let e=0,n=0,i=0;if(t.length===4)e=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16),i=parseInt(t[3]+t[3],16);else if(t.length===7)e=parseInt(t.substring(1,3),16),n=parseInt(t.substring(3,5),16),i=parseInt(t.substring(5,7),16);else return t;return`${e}, ${n}, ${i}`}catch{return"0, 0, 0"}};function ct({text:t,particleColor:e="255, 255, 255",particleSize:n=1,particleDensity:i=1,particleEase:s=1,isMagnet:g=!0,clickMode:r="none",particleShape:o="circle",backgroundColor:h="#050505"}){const v=f.useRef(null),d=f.useRef(null),c=f.useRef([]),a=f.useRef(0),l=f.useRef(0),u=H(d),R=f.useRef({isMagnet:g,clickMode:r,particleShape:o,backgroundColor:h});R.current={isMagnet:g,clickMode:r,particleShape:o,backgroundColor:h};const{updateTextTargets:E,textRef:q}=_(t,c,d),b=()=>Array.isArray(e)?e.map(y=>N(y)):N(e),C=(y,w,P=1)=>{const S=window.innerWidth<600?1500:3e3,I=Math.floor(S*P),z=[],M=b();for(let D=0;D<I;D++){const x=new G(y,w,M);x.sizeMultiplier=n,x.easeMultiplier=s,z.push(x)}c.current=z};return f.useEffect(()=>{if(c.current.length>0){const y=b();c.current.forEach(w=>{w.baseColor=Array.isArray(y)?y[Math.floor(Math.random()*y.length)]:y})}},[e]),f.useEffect(()=>{c.current.length>0&&c.current.forEach(y=>{y.sizeMultiplier=n})},[n]),f.useEffect(()=>{c.current.length>0&&c.current.forEach(y=>{y.easeMultiplier=s})},[s]),f.useEffect(()=>{if(c.current.length>0&&v.current&&d.current){const y=window.innerWidth<600?1500:3e3,w=Math.floor(y*i),P=c.current.length;if(w>P){const S=d.current.getBoundingClientRect(),I=b();for(let z=0;z<w-P;z++){const M=new G(S.width,S.height,I);M.sizeMultiplier=n,c.current.push(M)}E(t)}else w<P&&c.current.splice(w)}},[i]),f.useEffect(()=>{const y=d.current,w=v.current;if(!y||!w)return;const P=M=>{for(const D of M){const{width:x,height:p}=D.contentRect,X=window.devicePixelRatio||1;w.width=x*X,w.height=p*X,w.style.width=`${x}px`,w.style.height=`${p}px`;const Y=w.getContext("2d");Y&&Y.scale(X,X),c.current.length===0&&C(x,p,i),E(t,x,p)}},S=new ResizeObserver(P);S.observe(y);const I=w.getContext("2d"),z=()=>{l.current++;const M=y.getBoundingClientRect(),{isMagnet:D,clickMode:x,particleShape:p,backgroundColor:X}=R.current;if(X==="transparent")I.clearRect(0,0,M.width,M.height),I.globalCompositeOperation="source-over";else{const A=N(X);I.fillStyle=`rgba(${A}, 0.25)`,I.fillRect(0,0,M.width,M.height),I.globalCompositeOperation="screen"}const Y=q.current!=="",L=u.current.active?u.current.x:null,F=u.current.active?u.current.y:null,W=u.current.isDown;for(let A=0;A<c.current.length;A++){const $=c.current[A];$.update(l.current,!!Y,L,F,W,D,x),$.draw(I,p,l.current)}I.globalCompositeOperation="source-over",a.current=requestAnimationFrame(z)};return z(),()=>{S.disconnect(),cancelAnimationFrame(a.current)}},[]),f.useEffect(()=>{E(t)},[t]),T.jsx("div",{ref:d,style:{position:"absolute",inset:0,zIndex:0,overflow:"hidden"},children:T.jsx("canvas",{ref:v,style:{display:"block",width:"100%",height:"100%"}})})}function at({name:t,config:e,width:n="100%",height:i="60vh",backgroundColor:s="#050505",className:g="",style:r}){const o={name:t,...e};return T.jsx(j,{width:n,height:i,backgroundColor:s,className:g,style:r,background:o})}B.ParticleBackground=at,B.ParticleCanvas=j,B.TextParticleEngine=ct,B.getMagnetTarget=J,B.useParticleInteraction=H,B.useTextParticles=_,Object.defineProperty(B,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jl-particle-interactive",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "description": "Canvas-based React library for particle text animations and interactive backgrounds — spring physics, magnetic hover, click attract/repel, NET/JELLYFISH modes. TypeScript. Zero dependencies.",
6
6
  "author": {