particle-network-bg 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,80 @@
1
+ type GradientType = "linear" | "radial";
2
+ interface ParticleNetworkConfig {
3
+ particleCount: number;
4
+ minRadius: number;
5
+ maxRadius: number;
6
+ particleColor: string;
7
+ lineColor: string;
8
+ lineWidth: number;
9
+ lineOpacity: number;
10
+ maxDistance: number;
11
+ moveSpeed: number;
12
+ backgroundColor: string;
13
+ backgroundOpacity: number;
14
+ particleOpacity: number;
15
+ mouseRadius: number;
16
+ mouseInteraction: boolean;
17
+ pulseEnabled: boolean;
18
+ pulseSpeed: number;
19
+ depthEffectEnabled: boolean;
20
+ depthSpeed: number;
21
+ gradientEnabled: boolean;
22
+ gradientType: GradientType;
23
+ gradientColors: string[];
24
+ gradientStops?: number[];
25
+ gradientSpeed: number;
26
+ gradientMouseReaction: boolean;
27
+ gradientMouseInfluence: number;
28
+ gradientAngle: number;
29
+ gradientRadius: number;
30
+ gradientSpin: boolean;
31
+ gradientFlowAngle: number;
32
+ gradientOrbitRadius: number;
33
+ }
34
+ interface Particle {
35
+ x: number;
36
+ y: number;
37
+ dx: number;
38
+ dy: number;
39
+ radius: number;
40
+ z: number;
41
+ dz: number;
42
+ currentRadius?: number;
43
+ }
44
+ declare class ParticleNetwork {
45
+ private canvas;
46
+ private ctx;
47
+ config: ParticleNetworkConfig;
48
+ private particles;
49
+ private animationId;
50
+ private isRunning;
51
+ private mousePosition;
52
+ private pulseAngle;
53
+ private gradientAngle;
54
+ private gradientFlowOffset;
55
+ private gradientCenter;
56
+ private smoothedMouseAngle;
57
+ private boundHandleResize;
58
+ private boundHandleMouseMove;
59
+ private boundHandleMouseLeave;
60
+ constructor(canvas: HTMLCanvasElement, config?: Partial<ParticleNetworkConfig>);
61
+ private validateConfig;
62
+ private setupEventListeners;
63
+ cleanup(): void;
64
+ private handleMouseMove;
65
+ private handleMouseLeave;
66
+ private handleResize;
67
+ private createParticles;
68
+ private updateParticles;
69
+ private drawParticles;
70
+ private drawConnections;
71
+ private drawBackground;
72
+ private hexToRgb;
73
+ stop(): void;
74
+ start(): void;
75
+ private animate;
76
+ updateConfig<K extends keyof ParticleNetworkConfig>(property: K, value: ParticleNetworkConfig[K]): void;
77
+ reset(defaults: Partial<ParticleNetworkConfig>): void;
78
+ }
79
+
80
+ export { type GradientType, type Particle, ParticleNetwork, type ParticleNetworkConfig };
@@ -0,0 +1,80 @@
1
+ type GradientType = "linear" | "radial";
2
+ interface ParticleNetworkConfig {
3
+ particleCount: number;
4
+ minRadius: number;
5
+ maxRadius: number;
6
+ particleColor: string;
7
+ lineColor: string;
8
+ lineWidth: number;
9
+ lineOpacity: number;
10
+ maxDistance: number;
11
+ moveSpeed: number;
12
+ backgroundColor: string;
13
+ backgroundOpacity: number;
14
+ particleOpacity: number;
15
+ mouseRadius: number;
16
+ mouseInteraction: boolean;
17
+ pulseEnabled: boolean;
18
+ pulseSpeed: number;
19
+ depthEffectEnabled: boolean;
20
+ depthSpeed: number;
21
+ gradientEnabled: boolean;
22
+ gradientType: GradientType;
23
+ gradientColors: string[];
24
+ gradientStops?: number[];
25
+ gradientSpeed: number;
26
+ gradientMouseReaction: boolean;
27
+ gradientMouseInfluence: number;
28
+ gradientAngle: number;
29
+ gradientRadius: number;
30
+ gradientSpin: boolean;
31
+ gradientFlowAngle: number;
32
+ gradientOrbitRadius: number;
33
+ }
34
+ interface Particle {
35
+ x: number;
36
+ y: number;
37
+ dx: number;
38
+ dy: number;
39
+ radius: number;
40
+ z: number;
41
+ dz: number;
42
+ currentRadius?: number;
43
+ }
44
+ declare class ParticleNetwork {
45
+ private canvas;
46
+ private ctx;
47
+ config: ParticleNetworkConfig;
48
+ private particles;
49
+ private animationId;
50
+ private isRunning;
51
+ private mousePosition;
52
+ private pulseAngle;
53
+ private gradientAngle;
54
+ private gradientFlowOffset;
55
+ private gradientCenter;
56
+ private smoothedMouseAngle;
57
+ private boundHandleResize;
58
+ private boundHandleMouseMove;
59
+ private boundHandleMouseLeave;
60
+ constructor(canvas: HTMLCanvasElement, config?: Partial<ParticleNetworkConfig>);
61
+ private validateConfig;
62
+ private setupEventListeners;
63
+ cleanup(): void;
64
+ private handleMouseMove;
65
+ private handleMouseLeave;
66
+ private handleResize;
67
+ private createParticles;
68
+ private updateParticles;
69
+ private drawParticles;
70
+ private drawConnections;
71
+ private drawBackground;
72
+ private hexToRgb;
73
+ stop(): void;
74
+ start(): void;
75
+ private animate;
76
+ updateConfig<K extends keyof ParticleNetworkConfig>(property: K, value: ParticleNetworkConfig[K]): void;
77
+ reset(defaults: Partial<ParticleNetworkConfig>): void;
78
+ }
79
+
80
+ export { type GradientType, type Particle, ParticleNetwork, type ParticleNetworkConfig };
package/dist/index.js ADDED
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ ParticleNetwork: () => ParticleNetwork
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+ var DEFAULT_CONFIG = {
27
+ particleCount: 100,
28
+ minRadius: 2,
29
+ maxRadius: 6,
30
+ particleColor: "#000000",
31
+ lineColor: "#000000",
32
+ lineWidth: 1,
33
+ lineOpacity: 0.2,
34
+ maxDistance: 150,
35
+ moveSpeed: 1,
36
+ backgroundColor: "#ffffff",
37
+ backgroundOpacity: 1,
38
+ particleOpacity: 1,
39
+ mouseRadius: 200,
40
+ mouseInteraction: true,
41
+ pulseEnabled: true,
42
+ pulseSpeed: 0,
43
+ depthEffectEnabled: true,
44
+ depthSpeed: 0.02,
45
+ gradientEnabled: false,
46
+ gradientType: "linear",
47
+ gradientColors: ["#667eea", "#764ba2"],
48
+ gradientSpeed: 0.02,
49
+ gradientMouseReaction: true,
50
+ gradientMouseInfluence: 0.5,
51
+ gradientAngle: 0,
52
+ gradientRadius: 1,
53
+ gradientSpin: false,
54
+ gradientFlowAngle: 45,
55
+ gradientOrbitRadius: 0.3
56
+ };
57
+ var HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;
58
+ var ParticleNetwork = class {
59
+ constructor(canvas, config = {}) {
60
+ this.particles = [];
61
+ this.animationId = null;
62
+ this.isRunning = false;
63
+ this.mousePosition = null;
64
+ this.pulseAngle = 0;
65
+ this.gradientAngle = 0;
66
+ this.gradientFlowOffset = 0;
67
+ this.gradientCenter = { x: 0, y: 0 };
68
+ this.smoothedMouseAngle = 0;
69
+ this.canvas = canvas;
70
+ const ctx = canvas.getContext("2d", { alpha: true });
71
+ if (!ctx) {
72
+ throw new Error("Could not initialize canvas context");
73
+ }
74
+ this.ctx = ctx;
75
+ this.config = this.validateConfig({ ...DEFAULT_CONFIG, ...config });
76
+ this.boundHandleResize = this.handleResize.bind(this);
77
+ this.boundHandleMouseMove = this.handleMouseMove.bind(this);
78
+ this.boundHandleMouseLeave = this.handleMouseLeave.bind(this);
79
+ this.handleResize();
80
+ this.createParticles();
81
+ this.setupEventListeners();
82
+ }
83
+ validateConfig(config) {
84
+ const numericParams = [
85
+ "particleCount",
86
+ "minRadius",
87
+ "maxRadius",
88
+ "lineWidth",
89
+ "lineOpacity",
90
+ "maxDistance",
91
+ "moveSpeed",
92
+ "backgroundOpacity",
93
+ "particleOpacity",
94
+ "mouseRadius",
95
+ "pulseSpeed",
96
+ "depthSpeed",
97
+ "gradientSpeed",
98
+ "gradientMouseInfluence",
99
+ "gradientAngle",
100
+ "gradientRadius",
101
+ "gradientFlowAngle",
102
+ "gradientOrbitRadius"
103
+ ];
104
+ for (const param of numericParams) {
105
+ const val = config[param];
106
+ if (typeof val !== "number" || isNaN(val)) {
107
+ throw new Error(`Invalid ${param}: must be a number`);
108
+ }
109
+ }
110
+ const booleanParams = [
111
+ "mouseInteraction",
112
+ "pulseEnabled",
113
+ "depthEffectEnabled",
114
+ "gradientEnabled",
115
+ "gradientMouseReaction",
116
+ "gradientSpin"
117
+ ];
118
+ for (const param of booleanParams) {
119
+ if (typeof config[param] !== "boolean") {
120
+ throw new Error(`Invalid ${param}: must be a boolean`);
121
+ }
122
+ }
123
+ const colorParams = [
124
+ "backgroundColor",
125
+ "particleColor",
126
+ "lineColor"
127
+ ];
128
+ for (const param of colorParams) {
129
+ if (!HEX_COLOR_REGEX.test(config[param])) {
130
+ throw new Error(`Invalid ${param}: must be a valid hex color`);
131
+ }
132
+ }
133
+ if (config.gradientEnabled) {
134
+ if (!Array.isArray(config.gradientColors) || config.gradientColors.length < 2) {
135
+ throw new Error(
136
+ "gradientColors must be an array of at least 2 hex colors"
137
+ );
138
+ }
139
+ for (const c of config.gradientColors) {
140
+ if (!HEX_COLOR_REGEX.test(c)) {
141
+ throw new Error(`Invalid gradient color: ${c} must be valid hex`);
142
+ }
143
+ }
144
+ if (config.gradientType !== "linear" && config.gradientType !== "radial") {
145
+ throw new Error("gradientType must be 'linear' or 'radial'");
146
+ }
147
+ if (config.gradientStops) {
148
+ if (config.gradientStops.length !== config.gradientColors.length) {
149
+ throw new Error(
150
+ "gradientStops length must match gradientColors length"
151
+ );
152
+ }
153
+ for (let i = 0; i < config.gradientStops.length; i++) {
154
+ const s = config.gradientStops[i];
155
+ if (typeof s !== "number" || s < 0 || s > 1) {
156
+ throw new Error(`gradientStops[${i}] must be a number 0-1`);
157
+ }
158
+ if (i > 0 && s <= config.gradientStops[i - 1]) {
159
+ throw new Error("gradientStops must be strictly increasing");
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return config;
165
+ }
166
+ setupEventListeners() {
167
+ window.addEventListener("resize", this.boundHandleResize);
168
+ this.canvas.addEventListener("mousemove", this.boundHandleMouseMove);
169
+ this.canvas.addEventListener("mouseleave", this.boundHandleMouseLeave);
170
+ }
171
+ cleanup() {
172
+ window.removeEventListener("resize", this.boundHandleResize);
173
+ this.canvas.removeEventListener("mousemove", this.boundHandleMouseMove);
174
+ this.canvas.removeEventListener("mouseleave", this.boundHandleMouseLeave);
175
+ this.stop();
176
+ }
177
+ handleMouseMove(e) {
178
+ const rect = this.canvas.getBoundingClientRect();
179
+ this.mousePosition = {
180
+ x: e.clientX - rect.left,
181
+ y: e.clientY - rect.top
182
+ };
183
+ }
184
+ handleMouseLeave() {
185
+ this.mousePosition = null;
186
+ }
187
+ handleResize() {
188
+ this.canvas.width = window.innerWidth;
189
+ this.canvas.height = window.innerHeight;
190
+ this.gradientCenter = {
191
+ x: this.canvas.width / 2,
192
+ y: this.canvas.height / 2
193
+ };
194
+ }
195
+ createParticles() {
196
+ this.particles = [];
197
+ for (let i = 0; i < this.config.particleCount; i++) {
198
+ const sizeRange = this.config.maxRadius - this.config.minRadius;
199
+ const randomSize = Math.random() * sizeRange + this.config.minRadius;
200
+ this.particles.push({
201
+ x: Math.random() * this.canvas.width,
202
+ y: Math.random() * this.canvas.height,
203
+ dx: (Math.random() - 0.5) * this.config.moveSpeed,
204
+ dy: (Math.random() - 0.5) * this.config.moveSpeed,
205
+ radius: randomSize,
206
+ z: Math.random(),
207
+ dz: (Math.random() - 0.5) * this.config.depthSpeed * 2
208
+ });
209
+ }
210
+ }
211
+ updateParticles() {
212
+ this.particles.forEach((particle) => {
213
+ if (this.config.depthEffectEnabled) {
214
+ particle.z += particle.dz;
215
+ if (particle.z <= 0) {
216
+ particle.z = 0;
217
+ particle.dz = Math.abs(particle.dz);
218
+ } else if (particle.z >= 1) {
219
+ particle.z = 1;
220
+ particle.dz = -Math.abs(particle.dz);
221
+ }
222
+ }
223
+ if (this.config.pulseEnabled) {
224
+ this.pulseAngle += this.config.pulseSpeed;
225
+ const pulseScale = Math.sin(this.pulseAngle) * 0.5 + 1;
226
+ particle.currentRadius = particle.radius * pulseScale;
227
+ } else {
228
+ particle.currentRadius = particle.radius;
229
+ }
230
+ if (this.config.depthEffectEnabled) {
231
+ const depthScale = 0.4 + 0.6 * particle.z;
232
+ particle.currentRadius = (particle.currentRadius ?? particle.radius) * depthScale;
233
+ }
234
+ particle.x += particle.dx;
235
+ particle.y += particle.dy;
236
+ if (this.config.mouseInteraction && this.mousePosition) {
237
+ const dx = this.mousePosition.x - particle.x;
238
+ const dy = this.mousePosition.y - particle.y;
239
+ const distance = Math.sqrt(dx * dx + dy * dy);
240
+ if (distance < this.config.mouseRadius) {
241
+ const force = (this.config.mouseRadius - distance) / this.config.mouseRadius;
242
+ const angle = Math.atan2(dy, dx);
243
+ const repelX = Math.cos(angle) * force * 0.5;
244
+ const repelY = Math.sin(angle) * force * 0.5;
245
+ particle.dx -= repelX;
246
+ particle.dy -= repelY;
247
+ }
248
+ }
249
+ if (particle.x < 0 || particle.x > this.canvas.width) {
250
+ particle.dx = -particle.dx;
251
+ }
252
+ if (particle.y < 0 || particle.y > this.canvas.height) {
253
+ particle.dy = -particle.dy;
254
+ }
255
+ const speed = Math.sqrt(
256
+ particle.dx * particle.dx + particle.dy * particle.dy
257
+ );
258
+ if (speed > this.config.moveSpeed) {
259
+ particle.dx = particle.dx / speed * this.config.moveSpeed;
260
+ particle.dy = particle.dy / speed * this.config.moveSpeed;
261
+ }
262
+ });
263
+ }
264
+ drawParticles() {
265
+ this.ctx.fillStyle = this.config.particleColor;
266
+ this.particles.forEach((particle) => {
267
+ let opacity = this.config.particleOpacity;
268
+ if (this.config.depthEffectEnabled) {
269
+ opacity *= 0.6 + 0.4 * particle.z;
270
+ }
271
+ this.ctx.globalAlpha = opacity;
272
+ this.ctx.beginPath();
273
+ this.ctx.arc(
274
+ particle.x,
275
+ particle.y,
276
+ particle.currentRadius ?? particle.radius,
277
+ 0,
278
+ Math.PI * 2
279
+ );
280
+ this.ctx.fill();
281
+ });
282
+ this.ctx.globalAlpha = 1;
283
+ }
284
+ drawConnections() {
285
+ for (let i = 0; i < this.particles.length; i++) {
286
+ for (let j = i + 1; j < this.particles.length; j++) {
287
+ const dx = this.particles[i].x - this.particles[j].x;
288
+ const dy = this.particles[i].y - this.particles[j].y;
289
+ const distance = Math.sqrt(dx * dx + dy * dy);
290
+ if (distance < this.config.maxDistance) {
291
+ const opacity = 1 - distance / this.config.maxDistance;
292
+ const color = this.hexToRgb(this.config.lineColor);
293
+ this.ctx.beginPath();
294
+ this.ctx.strokeStyle = `rgba(${color}, ${opacity * this.config.lineOpacity})`;
295
+ this.ctx.lineWidth = this.config.lineWidth;
296
+ this.ctx.moveTo(this.particles[i].x, this.particles[i].y);
297
+ this.ctx.lineTo(this.particles[j].x, this.particles[j].y);
298
+ this.ctx.stroke();
299
+ }
300
+ }
301
+ }
302
+ }
303
+ drawBackground() {
304
+ this.ctx.globalAlpha = this.config.backgroundOpacity;
305
+ if (this.config.gradientEnabled) {
306
+ const w = this.canvas.width;
307
+ const h = this.canvas.height;
308
+ const colors = this.config.gradientColors;
309
+ const stops = this.config.gradientStops ?? colors.map((_, i) => i / (colors.length - 1));
310
+ if (this.config.gradientType === "linear") {
311
+ const baseAngleRad = this.config.gradientFlowAngle * Math.PI / 180;
312
+ const diag = Math.sqrt(w * w + h * h);
313
+ let angle;
314
+ let offsetX = 0;
315
+ let offsetY = 0;
316
+ if (this.config.gradientSpin) {
317
+ this.gradientAngle += this.config.gradientSpeed;
318
+ angle = this.gradientAngle;
319
+ } else {
320
+ this.gradientFlowOffset = (this.gradientFlowOffset + this.config.gradientSpeed) % (Math.PI * 2);
321
+ const t = this.gradientFlowOffset / (Math.PI * 2);
322
+ offsetX = Math.cos(baseAngleRad) * t * diag;
323
+ offsetY = Math.sin(baseAngleRad) * t * diag;
324
+ angle = baseAngleRad;
325
+ }
326
+ const cos = Math.cos(angle);
327
+ const sin = Math.sin(angle);
328
+ const lineLen = this.config.gradientSpin ? diag / 2 : diag * 1.5;
329
+ const cx = w / 2 + offsetX;
330
+ const cy = h / 2 + offsetY;
331
+ const x1 = cx - cos * lineLen;
332
+ const y1 = cy - sin * lineLen;
333
+ const x2 = cx + cos * lineLen;
334
+ const y2 = cy + sin * lineLen;
335
+ const gradient = this.ctx.createLinearGradient(x1, y1, x2, y2);
336
+ if (this.config.gradientSpin) {
337
+ colors.forEach((c, i) => gradient.addColorStop(stops[i], c));
338
+ } else {
339
+ const extColors = [...colors, colors[0]];
340
+ for (let rep = 0; rep < 3; rep++) {
341
+ extColors.forEach((c, i) => {
342
+ gradient.addColorStop((rep + i / (extColors.length - 1)) / 3, c);
343
+ });
344
+ }
345
+ }
346
+ this.ctx.fillStyle = gradient;
347
+ } else {
348
+ const cx = w / 2;
349
+ const cy = h / 2;
350
+ const orbitR = Math.min(w, h) * this.config.gradientOrbitRadius;
351
+ let targetX;
352
+ let targetY;
353
+ this.gradientAngle += this.config.gradientSpeed;
354
+ targetX = cx + Math.cos(this.gradientAngle) * orbitR;
355
+ targetY = cy + Math.sin(this.gradientAngle) * orbitR;
356
+ if (this.config.gradientMouseReaction && this.mousePosition) {
357
+ const influence = this.config.gradientMouseInfluence;
358
+ targetX = targetX + (this.mousePosition.x - targetX) * influence;
359
+ targetY = targetY + (this.mousePosition.y - targetY) * influence;
360
+ }
361
+ const lerpFactor = 0.03;
362
+ this.gradientCenter.x += (targetX - this.gradientCenter.x) * lerpFactor;
363
+ this.gradientCenter.y += (targetY - this.gradientCenter.y) * lerpFactor;
364
+ this.gradientFlowOffset = (this.gradientFlowOffset + this.config.gradientSpeed) % (Math.PI * 2);
365
+ const t = this.gradientFlowOffset / (Math.PI * 2);
366
+ const r = Math.max(w, h) * this.config.gradientRadius * 2;
367
+ const gradient = this.ctx.createRadialGradient(
368
+ this.gradientCenter.x,
369
+ this.gradientCenter.y,
370
+ 0,
371
+ this.gradientCenter.x,
372
+ this.gradientCenter.y,
373
+ r
374
+ );
375
+ const extColors = [...colors, colors[0]];
376
+ const entries = [];
377
+ for (let rep = 0; rep < 3; rep++) {
378
+ extColors.forEach((c, i) => {
379
+ const base = (rep + i / (extColors.length - 1)) / 3;
380
+ entries.push({ stop: (base + t) % 1, color: c });
381
+ });
382
+ }
383
+ entries.sort((a, b) => a.stop - b.stop);
384
+ if (entries[0].stop > 1e-3) {
385
+ entries.unshift({ stop: 0, color: entries[entries.length - 1].color });
386
+ }
387
+ if (entries[entries.length - 1].stop < 0.999) {
388
+ entries.push({ stop: 1, color: entries[0].color });
389
+ }
390
+ entries.forEach((e) => gradient.addColorStop(e.stop, e.color));
391
+ this.ctx.fillStyle = gradient;
392
+ }
393
+ } else {
394
+ this.ctx.fillStyle = this.config.backgroundColor;
395
+ }
396
+ this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
397
+ this.ctx.globalAlpha = 1;
398
+ }
399
+ hexToRgb(hex) {
400
+ hex = hex.replace(/^#/, "");
401
+ if (hex.length === 3) {
402
+ hex = hex.split("").map((c) => c + c).join("");
403
+ }
404
+ const result = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
405
+ if (!result) return "255,255,255";
406
+ return result.slice(1).map((n) => parseInt(n, 16)).join(",");
407
+ }
408
+ stop() {
409
+ this.isRunning = false;
410
+ if (this.animationId !== null) {
411
+ cancelAnimationFrame(this.animationId);
412
+ this.animationId = null;
413
+ }
414
+ }
415
+ start() {
416
+ if (!this.isRunning) {
417
+ this.isRunning = true;
418
+ this.animate();
419
+ }
420
+ }
421
+ animate() {
422
+ this.drawBackground();
423
+ this.updateParticles();
424
+ this.drawParticles();
425
+ this.drawConnections();
426
+ if (this.isRunning) {
427
+ this.animationId = requestAnimationFrame(() => this.animate());
428
+ }
429
+ }
430
+ updateConfig(property, value) {
431
+ this.config[property] = value;
432
+ if (property === "particleCount") {
433
+ this.createParticles();
434
+ }
435
+ if (property === "moveSpeed") {
436
+ this.particles.forEach((particle) => {
437
+ const currentSpeed = Math.sqrt(
438
+ particle.dx * particle.dx + particle.dy * particle.dy
439
+ );
440
+ if (currentSpeed > 0) {
441
+ particle.dx = particle.dx / currentSpeed * value;
442
+ particle.dy = particle.dy / currentSpeed * value;
443
+ }
444
+ });
445
+ }
446
+ if (property === "minRadius" || property === "maxRadius") {
447
+ this.particles.forEach((particle) => {
448
+ const sizeRange = this.config.maxRadius - this.config.minRadius;
449
+ const randomSize = Math.random() * sizeRange + this.config.minRadius;
450
+ particle.radius = randomSize;
451
+ });
452
+ }
453
+ if (property === "depthSpeed") {
454
+ this.particles.forEach((particle) => {
455
+ const sign = particle.dz >= 0 ? 1 : -1;
456
+ particle.dz = sign * (Math.random() * 0.5 + 0.5) * value * 2;
457
+ });
458
+ }
459
+ }
460
+ reset(defaults) {
461
+ this.config = this.validateConfig({
462
+ ...DEFAULT_CONFIG,
463
+ ...defaults
464
+ });
465
+ this.createParticles();
466
+ this.stop();
467
+ this.start();
468
+ }
469
+ };
470
+ // Annotate the CommonJS export names for ESM import in node:
471
+ 0 && (module.exports = {
472
+ ParticleNetwork
473
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,6 @@
1
+ import {
2
+ ParticleNetwork
3
+ } from "./chunk-WD7BVW5Q.mjs";
4
+ export {
5
+ ParticleNetwork
6
+ };
@@ -0,0 +1,13 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { CSSProperties, RefObject } from 'react';
3
+ import { ParticleNetworkConfig } from './index.mjs';
4
+
5
+ declare function useParticleNetwork(config?: Partial<ParticleNetworkConfig>): RefObject<HTMLCanvasElement | null>;
6
+ interface ParticleNetworkBgProps {
7
+ config?: Partial<ParticleNetworkConfig>;
8
+ style?: CSSProperties;
9
+ className?: string;
10
+ }
11
+ declare function ParticleNetworkBg({ config, style, className, }: ParticleNetworkBgProps): react_jsx_runtime.JSX.Element;
12
+
13
+ export { ParticleNetworkBg, type ParticleNetworkBgProps, useParticleNetwork };
@@ -0,0 +1,13 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { CSSProperties, RefObject } from 'react';
3
+ import { ParticleNetworkConfig } from './index.js';
4
+
5
+ declare function useParticleNetwork(config?: Partial<ParticleNetworkConfig>): RefObject<HTMLCanvasElement | null>;
6
+ interface ParticleNetworkBgProps {
7
+ config?: Partial<ParticleNetworkConfig>;
8
+ style?: CSSProperties;
9
+ className?: string;
10
+ }
11
+ declare function ParticleNetworkBg({ config, style, className, }: ParticleNetworkBgProps): react_jsx_runtime.JSX.Element;
12
+
13
+ export { ParticleNetworkBg, type ParticleNetworkBgProps, useParticleNetwork };