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
|
-
##
|
|
89
|
+
## Text examples
|
|
90
90
|
|
|
91
|
-
###
|
|
91
|
+
### 1. Free-floating particles
|
|
92
92
|
|
|
93
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
###
|
|
114
|
+
### 2. Hello 🖐️ — magnetic hover + color palette
|
|
108
115
|
|
|
109
|
-
Particles
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
###
|
|
140
|
+
### 3. Word carousel — cycles every 3 seconds
|
|
124
141
|
|
|
125
|
-
The
|
|
142
|
+
The particles re-form automatically each time the `text` prop changes. No extra animation code needed.
|
|
126
143
|
|
|
127
144
|
```tsx
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
###
|
|
208
|
+
### 2. NET — connected node graph
|
|
160
209
|
|
|
161
|
-
|
|
210
|
+
Particles bounce around and draw lines between nearby nodes. Great for tech-style hero sections.
|
|
162
211
|
|
|
163
212
|
```tsx
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
###
|
|
236
|
+
### 3. JELLYFISH — organic pulsing glow
|
|
179
237
|
|
|
180
|
-
|
|
238
|
+
Soft concentric rings expand and contract in a slow breathing cycle. Particles drift with organic float noise.
|
|
181
239
|
|
|
182
240
|
```tsx
|
|
183
|
-
|
|
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
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
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' }` |
|
|
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
|
|
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,
|
|
8
|
-
s += Math.sin(i * t.randomSpeed + t.baseY * 0.05) * 15 * t.z,
|
|
9
|
-
const r = s - t.x, o =
|
|
10
|
-
return { forceX: h, forceY:
|
|
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,
|
|
13
|
-
const r = i, o = s, h = t.x - r,
|
|
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 -
|
|
16
|
-
c += h / d * u, a +=
|
|
17
|
-
const P = Math.cos(d * 0.01 -
|
|
18
|
-
return c += q * P, a += b * P, { forceX: c, forceY: a, dxCenter: h, dyCenter:
|
|
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,
|
|
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),
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
m(this, "x");
|
|
37
|
+
m(this, "y");
|
|
38
|
+
m(this, "baseX");
|
|
39
39
|
// Relative X to swarm center
|
|
40
|
-
|
|
40
|
+
m(this, "baseY");
|
|
41
41
|
// Relative Y to swarm center
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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,
|
|
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:
|
|
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 +=
|
|
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),
|
|
75
|
-
if (e.globalAlpha = Math.min(1, (0.5 + this.z * 0.5) * Math.min(this.scale, 1) *
|
|
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),
|
|
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([]),
|
|
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),
|
|
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 (
|
|
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 && (
|
|
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
|
-
|
|
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
|
-
|
|
182
|
+
y.current = requestAnimationFrame(q);
|
|
183
183
|
};
|
|
184
184
|
return q(), () => {
|
|
185
|
-
u.disconnect(), cancelAnimationFrame(
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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,
|
|
204
|
-
if (this.x += this.vx *
|
|
205
|
-
const o = i - this.x, h = s - this.y,
|
|
206
|
-
if (
|
|
207
|
-
const a = Math.sqrt(
|
|
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 *
|
|
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),
|
|
218
|
-
e.beginPath(), e.ellipse(this.x, this.y,
|
|
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([]),
|
|
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),
|
|
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 (
|
|
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 && (
|
|
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
|
-
|
|
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,
|
|
307
|
+
u.globalAlpha = 1, y.current = requestAnimationFrame(P);
|
|
308
308
|
};
|
|
309
309
|
return P(), () => {
|
|
310
|
-
l.disconnect(), cancelAnimationFrame(
|
|
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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
|
332
|
-
this.spring = 0.15 -
|
|
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,
|
|
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),
|
|
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([]),
|
|
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),
|
|
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
|
-
}) : (
|
|
373
|
+
}) : (g.current = 0, c(t.colors[0]), t.colors.length > 1 && (d.current = setInterval(() => {
|
|
374
374
|
const a = t.colors;
|
|
375
|
-
|
|
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
|
-
|
|
447
|
+
y.current = requestAnimationFrame(q);
|
|
448
448
|
};
|
|
449
449
|
return q(), () => {
|
|
450
|
-
u.disconnect(), cancelAnimationFrame(
|
|
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
|
|
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:
|
|
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, ...
|
|
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
|
|
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
|
-
},
|
|
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",
|
|
514
|
-
n.removeEventListener("pointermove", i), n.removeEventListener("pointerleave", s), n.removeEventListener("pointerdown",
|
|
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
|
|
519
|
-
if (s === null ||
|
|
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
|
|
522
|
-
const c = s - t, a =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
535
|
+
g -= c / u * P * 400, d -= a / u * P * 400;
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
|
-
return { x:
|
|
538
|
+
return { x: g, y: d };
|
|
539
539
|
}
|
|
540
540
|
class H {
|
|
541
541
|
constructor(e, n, i = "255, 255, 255") {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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,
|
|
561
|
-
const { x: h, y } =
|
|
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
|
-
|
|
568
|
+
y,
|
|
569
569
|
r,
|
|
570
570
|
o
|
|
571
|
-
), d = h - this.x, c =
|
|
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
|
|
583
|
-
e.beginPath(), e.ellipse(this.x, this.y, h,
|
|
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
|
|
596
|
-
s.font = `bold ${
|
|
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 && (
|
|
599
|
-
const h = s.getImageData(0, 0, e, n).data,
|
|
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 &&
|
|
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
|
|
608
|
+
return g;
|
|
609
609
|
}
|
|
610
|
-
function
|
|
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: (
|
|
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,
|
|
617
|
-
if (!
|
|
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() * (
|
|
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(
|
|
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:
|
|
669
|
+
isMagnet: y = !0,
|
|
670
670
|
clickMode: r = "none",
|
|
671
671
|
particleShape: o = "circle",
|
|
672
672
|
backgroundColor: h = "#050505"
|
|
673
673
|
}) {
|
|
674
|
-
const
|
|
675
|
-
w.current = { isMagnet:
|
|
676
|
-
const { updateTextTargets: P, textRef: q } =
|
|
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 &&
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
786
|
+
gt as ParticleBackground,
|
|
787
|
+
ct as ParticleCanvas,
|
|
765
788
|
yt as TextParticleEngine,
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
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.
|
|
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": {
|