particle-network-bg 0.1.0 → 1.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.
package/README.md CHANGED
@@ -15,10 +15,10 @@ Run locally:
15
15
 
16
16
  ```bash
17
17
  # Vanilla
18
- cd lib/demo/vanilla && npm install && npm run dev
18
+ cd demo/vanilla && npm install && npm run dev
19
19
 
20
20
  # React
21
- cd lib/demo/react && npm install && npm run dev
21
+ cd demo/react && npm install && npm run dev
22
22
  ```
23
23
 
24
24
  ## Install
@@ -153,34 +153,69 @@ new ParticleNetwork(canvas, {
153
153
  color: "#88ccff",
154
154
  opacity: 0.6,
155
155
  reflectionStrength: 0.85,
156
- highlightPosition: "top-left",
156
+ highlightPosition: "top-left", // "top-left" | "top" | "top-right" | "center" | "bottom-right"
157
157
  highlightColor: "#ffffff",
158
158
  shadowStrength: 0.4,
159
159
  secondaryReflection: 0.25,
160
160
  secondaryHighlightPosition: "bottom-right",
161
+ minRadius: 20, // min size for liquid glass particles (overrides root minRadius)
162
+ maxRadius: 40, // max size for liquid glass particles (overrides root maxRadius)
161
163
  },
162
164
  });
163
165
  ```
164
166
 
165
167
  ## Particle Types
166
168
 
167
- Use `particleTypes` to mix circle, asset, and liquid glass particles with full control:
169
+ Use `particleTypes` to mix circle, asset, and liquid glass particles with full control. Each entry can carry **per-type overrides** that shadow the global config:
168
170
 
169
171
  ```js
170
172
  new ParticleNetwork(canvas, {
173
+ particleCount: 100,
174
+ particleColor: "#000000",
175
+ particleOpacity: 1,
176
+ pulseEnabled: false,
171
177
  particleTypes: [
172
- { type: "circle", percentage: 50 },
173
- { type: "liquidGlass", percentage: 30 },
174
- { type: "asset", asset: "star", count: 20, liquidGlass: true },
178
+ // 50% circles override color and enable pulse just for these
179
+ { type: "circle", percentage: 50, color: "#ff6600", pulse: true, pulseSpeed: 0.03 },
180
+ // 30% liquid glass override glass config just for these
181
+ { type: "liquidGlass", percentage: 30, liquidGlass: { color: "#00ccff", opacity: 0.8 } },
182
+ // 20 asset particles with custom opacity
183
+ { type: "asset", asset: "star", count: 20, opacity: 0.7 },
175
184
  ],
176
185
  assets: { star: "https://..." },
177
- liquidGlass: { mergeDistance: 40, color: "#88ccff", ... },
186
+ liquidGlass: { color: "#88ccff", blur: 12, contrast: 25 },
178
187
  });
179
188
  ```
180
189
 
181
- - **`circle`**: Normal circles
182
- - **`liquidGlass`**: Liquid glass blobs (merge when close)
183
- - **`asset`**: Icons/images; use `liquidGlass: true` to combine with glass
190
+ Per-type values are a **shallow override** on top of the root config. Omitted fields fall back to the global value, so existing usage without `particleTypes` stays unchanged.
191
+
192
+ ### Circle type overrides
193
+
194
+ | Field | Type | Description |
195
+ | ------------ | ------- | -------------------------------------------- |
196
+ | `color` | string | Particle color (hex). Overrides `particleColor` |
197
+ | `opacity` | number | Particle opacity (0–1). Overrides `particleOpacity` |
198
+ | `minRadius` | number | Min radius (px). Overrides root `minRadius` |
199
+ | `maxRadius` | number | Max radius (px). Overrides root `maxRadius` |
200
+ | `pulse` | boolean | Enable pulse. Overrides `pulseEnabled` |
201
+ | `pulseSpeed` | number | Pulse speed. Overrides root `pulseSpeed` |
202
+
203
+ ### Liquid glass type overrides
204
+
205
+ | Field | Type | Description |
206
+ | ------------ | ------------------------- | -------------------------------------------------------------- |
207
+ | `liquidGlass`| `Partial<LiquidGlassConfig>` | Shallow-merged over root `liquidGlass` (color, opacity, minRadius, etc.) |
208
+ | `pulse` | boolean | Enable pulse. Overrides `pulseEnabled` |
209
+ | `pulseSpeed` | number | Pulse speed. Overrides root `pulseSpeed` |
210
+
211
+ ### Asset type overrides
212
+
213
+ | Field | Type | Description |
214
+ | ------------ | ---------------------------------------- | ----------------------------------------------------------------- |
215
+ | `liquidGlass`| `boolean \| Partial<LiquidGlassConfig>` | `true` for glass rendering, or partial config for per-type glass |
216
+ | `opacity` | number | Particle opacity (0–1). Overrides `particleOpacity` |
217
+ | `pulse` | boolean | Enable pulse. Overrides `pulseEnabled` |
218
+ | `pulseSpeed` | number | Pulse speed. Overrides root `pulseSpeed` |
184
219
 
185
220
  ## Connection Rules
186
221
 
@@ -289,12 +324,140 @@ new ParticleNetwork(canvas, {
289
324
  });
290
325
  ```
291
326
 
327
+ ## Child Particles
328
+
329
+ Attach real UI components (React nodes or DOM elements) as physics particles. Each child particle has an anchor point it springs back to, reacts to the mouse, and can optionally render as a liquid glass blob.
330
+
331
+ ### React
332
+
333
+ Use `ChildParticle` or `GlassChildParticle` as children of `ParticleNetworkBg`:
334
+
335
+ ```jsx
336
+ import { ParticleNetworkBg, ChildParticle, GlassChildParticle } from "particle-network-bg/react";
337
+
338
+ function App() {
339
+ return (
340
+ <ParticleNetworkBg config={{ particleCount: 60 }} style={{ width: "100%", height: "100vh" }}>
341
+ {/* Normal circle particle with a React child */}
342
+ <ChildParticle id="card-1" x={300} y={200} radius={50}>
343
+ <div style={{ color: "#fff", fontSize: 12 }}>Hello</div>
344
+ </ChildParticle>
345
+
346
+ {/* Liquid glass blob particle */}
347
+ <GlassChildParticle id="clock" x={600} y={400} radius={60}>
348
+ <span>🕐</span>
349
+ </GlassChildParticle>
350
+
351
+ {/* Rectangular child particle */}
352
+ <ChildParticle id="widget" x={900} y={300} width={160} height={80} borderRadius={16}>
353
+ <div>Widget content</div>
354
+ </ChildParticle>
355
+ </ParticleNetworkBg>
356
+ );
357
+ }
358
+ ```
359
+
360
+ ### `ChildParticle` / `GlassChildParticle` Props
361
+
362
+ | Prop | Type | Default | Description |
363
+ | ---------------- | --------- | -------- | ------------------------------------------------------------- |
364
+ | `id` | string | required | Unique identifier |
365
+ | `x` | number | required | Anchor X position (px) |
366
+ | `y` | number | required | Anchor Y position (px) |
367
+ | `radius` | number | required | Particle radius (px). Used for physics and as size |
368
+ | `width` | number | — | Rectangular width (px). Set with `height` for rect shape |
369
+ | `height` | number | — | Rectangular height (px) |
370
+ | `borderRadius` | number | — | Border radius (px) for rectangular shapes. Default: fully round |
371
+ | `overflow` | string | `"hidden"` | CSS overflow for the child content container |
372
+ | `anchorForce` | number | `0.05` | Spring force pulling back to anchor (0–1). Lower = more floaty |
373
+ | `mouseInfluence` | number | `0.1` | Mouse influence multiplier (0–1). 0 = ignores mouse |
374
+ | `children` | ReactNode | — | Content to render inside the particle |
375
+ | `style` | CSSProperties | — | Style applied to the inner wrapper div |
376
+ | `className` | string | — | Class applied to the inner wrapper div |
377
+
378
+ ### Vanilla JS
379
+
380
+ Use `addChildParticle` / `removeChildParticle` on the `ParticleNetwork` instance directly:
381
+
382
+ ```js
383
+ const network = new ParticleNetwork(canvas, { particleCount: 60 });
384
+ network.start();
385
+
386
+ // Add a child particle
387
+ network.addChildParticle({
388
+ id: "card-1",
389
+ x: 300,
390
+ y: 200,
391
+ radius: 50,
392
+ anchorForce: 0.05,
393
+ mouseInfluence: 0.1,
394
+ liquidGlass: false,
395
+ });
396
+
397
+ // Update its anchor (e.g. on scroll/resize)
398
+ network.updateChildParticle("card-1", { x: 400, y: 250 });
399
+
400
+ // Get current positions every frame via callback
401
+ network.onChildUpdate = (positions) => {
402
+ const pos = positions.get("card-1");
403
+ // pos.x, pos.y, pos.radius, pos.currentRadius, pos.width, pos.height, pos.rotation
404
+ myDomEl.style.transform = `translate(${pos.x}px, ${pos.y}px)`;
405
+ };
406
+
407
+ // Remove
408
+ network.removeChildParticle("card-1");
409
+ ```
410
+
411
+ ### Child Particle API
412
+
413
+ | Method / Property | Description |
414
+ | ---------------------------------------------- | -------------------------------------------------------------------- |
415
+ | `addChildParticle(config)` | Register a child particle. Creates the particle with anchor physics. |
416
+ | `removeChildParticle(id)` | Remove a child particle by ID. |
417
+ | `updateChildParticle(id, updates)` | Update anchor position or any config property at runtime. |
418
+ | `getChildParticlePositions()` | Returns a `Map<string, ChildParticlePosition>` with current state. |
419
+ | `onChildUpdate` | Callback fired every frame: `(positions: Map<string, ChildParticlePosition>) => void` |
420
+ | `getChildOverlayElement(id)` | Returns the DOM div overlay for a child particle (for manual use). |
421
+
422
+ ### Types
423
+
424
+ ```ts
425
+ import type { ChildParticleConfig, ChildParticlePosition } from "particle-network-bg";
426
+
427
+ interface ChildParticleConfig {
428
+ id: string;
429
+ x: number;
430
+ y: number;
431
+ radius: number;
432
+ width?: number;
433
+ height?: number;
434
+ borderRadius?: number;
435
+ overflow?: string;
436
+ anchorForce?: number;
437
+ mouseInfluence?: number;
438
+ liquidGlass?: boolean;
439
+ }
440
+
441
+ interface ChildParticlePosition {
442
+ x: number;
443
+ y: number;
444
+ radius: number;
445
+ currentRadius: number;
446
+ width?: number;
447
+ height?: number;
448
+ rotation: number; // blob rotation in radians (liquid glass only, 0 for normal)
449
+ }
450
+ ```
451
+
292
452
  ## API
293
453
 
294
454
  ### React (`particle-network-bg/react`)
295
455
 
296
- - `ParticleNetworkBg` – Wrapper component. Props: `config`, `style`, `className`
456
+ - `ParticleNetworkBg` – Wrapper component. Props: `config`, `style`, `className`, `children` (for `ChildParticle` / `GlassChildParticle`)
297
457
  - `useParticleNetwork(config?)` – Hook that returns a canvas ref
458
+ - `ChildParticle` – React child particle component (see [Child Particles](#child-particles))
459
+ - `GlassChildParticle` – Liquid glass variant of `ChildParticle`
460
+ - `ParticleNetworkContext` – React context exposing the `ParticleNetwork` instance; use `useContext(ParticleNetworkContext)` inside children of `ParticleNetworkBg` for direct instance access
298
461
 
299
462
  ### `ParticleNetwork` (vanilla)
300
463
 
@@ -313,7 +476,14 @@ import type {
313
476
  GradientType,
314
477
  ConnectionRules,
315
478
  LiquidGlassConfig,
479
+ LiquidGlassHighlightPosition,
316
480
  ParticleTypeEntry,
481
+ CircleTypeEntry,
482
+ LiquidGlassTypeEntry,
483
+ AssetTypeEntry,
484
+ ParticleAssetConfig,
485
+ ChildParticleConfig,
486
+ ChildParticlePosition,
317
487
  } from "particle-network-bg";
318
488
  ```
319
489