particle-network-bg 0.0.4 → 1.0.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
@@ -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
@@ -126,6 +126,126 @@ function App() {
126
126
  | `gradientOrbitRadius` | number | 0.3 | **Radial:** Orbit radius for center movement (0–1) |
127
127
  | `gradientDithering` | boolean | true | *(Deprecated)* No longer used with CSS gradients |
128
128
  | `gradientSmoothStops` | number | 4 | *(Deprecated)* No longer used with CSS gradients |
129
+ | `particleAssets` | array | — | Use icons/images as particles (see Asset Particles) |
130
+ | `assets` | object | — | Map of asset keys to URLs or SVG strings (required with `particleAssets`) |
131
+ | `assetColor` | string | — | Tint color for asset particles (hex). Omit to use original image colors |
132
+ | `assetOpacity` | number | 1 | Opacity for asset particles (0–1) |
133
+ | `mouseAttractPercentage` | number | — | % of particles that follow the mouse (0–100). Others repel |
134
+ | `mouseAttractAssets` | string[] | — | Asset keys whose particles follow the mouse. Others repel |
135
+ | `minParticleDistance` | number | — | Min distance (px). Particles repel when closer |
136
+ | `minParticleForce` | number | 0.5 | Strength of particle repulsion (0–2) |
137
+ | `connectionRules` | object | — | Control which categories connect (see Connection Rules) |
138
+ | `liquidGlass` | object | — | Liquid glass styling (see Liquid Glass) |
139
+ | `liquidGlassPercentage` | number | — | % of particles that render as liquid glass (0–100) |
140
+ | `liquidGlassCount` | number | — | Exact count of liquid glass particles |
141
+ | `particleTypes` | array | — | Mix circle, asset, liquidGlass (see Particle Types) |
142
+
143
+ ## Liquid Glass
144
+
145
+ 3D fluid spheres with blur + contrast for a gooey liquid feel. Each particle is rendered as a 3D sphere with shading, highlights, and blur. Overlapping blobs merge visually via the contrast filter.
146
+
147
+ ```js
148
+ new ParticleNetwork(canvas, {
149
+ liquidGlassPercentage: 40,
150
+ liquidGlass: {
151
+ blur: 12, // blur radius (px) for fluid gooey effect
152
+ contrast: 25, // container contrast for gooey merge
153
+ color: "#88ccff",
154
+ opacity: 0.6,
155
+ reflectionStrength: 0.85,
156
+ highlightPosition: "top-left", // "top-left" | "top" | "top-right" | "center" | "bottom-right"
157
+ highlightColor: "#ffffff",
158
+ shadowStrength: 0.4,
159
+ secondaryReflection: 0.25,
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)
163
+ },
164
+ });
165
+ ```
166
+
167
+ ## Particle Types
168
+
169
+ Use `particleTypes` to mix circle, asset, and liquid glass particles with full control:
170
+
171
+ ```js
172
+ new ParticleNetwork(canvas, {
173
+ particleTypes: [
174
+ { type: "circle", percentage: 50 },
175
+ { type: "liquidGlass", percentage: 30 },
176
+ { type: "asset", asset: "star", count: 20, liquidGlass: true },
177
+ ],
178
+ assets: { star: "https://..." },
179
+ liquidGlass: { color: "#88ccff", blur: 12, contrast: 25, ... },
180
+ });
181
+ ```
182
+
183
+ - **`circle`**: Normal circles
184
+ - **`liquidGlass`**: Liquid glass blobs (merge when close)
185
+ - **`asset`**: Icons/images; use `liquidGlass: true` to combine with glass
186
+
187
+ ## Connection Rules
188
+
189
+ Control which particle categories can connect to each other. Categories: `"default"` (normal circles) and asset keys (e.g. `"star"`, `"fa_solid_heart"`).
190
+
191
+ ```js
192
+ new ParticleNetwork(canvas, {
193
+ particleAssets: [
194
+ { asset: "star", count: 20 },
195
+ { asset: "heart", count: 20 },
196
+ ],
197
+ assets: { star: "...", heart: "..." },
198
+ connectionRules: {
199
+ allow: [["default", "star"], ["star", "heart"]], // only these pairs connect
200
+ deny: [["star", "heart"]], // or: all connect except these
201
+ },
202
+ });
203
+ ```
204
+
205
+ - **`allow`**: Only these category pairs connect. Omit or empty = all connect.
206
+ - **`deny`**: These pairs never connect (applied after allow).
207
+
208
+ ## Asset Particles
209
+
210
+ Use custom icons or images (SVG, PNG, etc.) as particles:
211
+
212
+ ```js
213
+ new ParticleNetwork(canvas, {
214
+ particleCount: 100,
215
+ particleAssets: [
216
+ { asset: "star", count: 10 }, // exactly 10 particles with star icon
217
+ { asset: "heart", percentage: 30 }, // 30% of particles with heart icon
218
+ ],
219
+ assets: {
220
+ star: "https://example.com/star.svg",
221
+ heart: "<svg>...</svg>", // inline SVG string also supported
222
+ },
223
+ });
224
+ ```
225
+
226
+ Each entry in `particleAssets` must specify exactly one of `count` (exact number) or `percentage` (0–100). Remaining particles render as default circles.
227
+
228
+ ## Mouse Attract
229
+
230
+ Control which particles follow vs repel the mouse. Use one or both:
231
+
232
+ ```js
233
+ new ParticleNetwork(canvas, {
234
+ mouseAttractPercentage: 30, // 30% of particles follow the mouse
235
+ mouseAttractAssets: ["fa_solid_star"], // particles with this asset follow
236
+ });
237
+ ```
238
+
239
+ ## Particle Repulsion
240
+
241
+ Keep particles from overlapping. When two particles are closer than `minParticleDistance`, they repel each other:
242
+
243
+ ```js
244
+ new ParticleNetwork(canvas, {
245
+ minParticleDistance: 20,
246
+ minParticleForce: 0.5,
247
+ });
248
+ ```
129
249
 
130
250
  ## Gradient Examples
131
251
 
@@ -171,12 +291,140 @@ new ParticleNetwork(canvas, {
171
291
  });
172
292
  ```
173
293
 
294
+ ## Child Particles
295
+
296
+ 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.
297
+
298
+ ### React
299
+
300
+ Use `ChildParticle` or `GlassChildParticle` as children of `ParticleNetworkBg`:
301
+
302
+ ```jsx
303
+ import { ParticleNetworkBg, ChildParticle, GlassChildParticle } from "particle-network-bg/react";
304
+
305
+ function App() {
306
+ return (
307
+ <ParticleNetworkBg config={{ particleCount: 60 }} style={{ width: "100%", height: "100vh" }}>
308
+ {/* Normal circle particle with a React child */}
309
+ <ChildParticle id="card-1" x={300} y={200} radius={50}>
310
+ <div style={{ color: "#fff", fontSize: 12 }}>Hello</div>
311
+ </ChildParticle>
312
+
313
+ {/* Liquid glass blob particle */}
314
+ <GlassChildParticle id="clock" x={600} y={400} radius={60}>
315
+ <span>🕐</span>
316
+ </GlassChildParticle>
317
+
318
+ {/* Rectangular child particle */}
319
+ <ChildParticle id="widget" x={900} y={300} width={160} height={80} borderRadius={16}>
320
+ <div>Widget content</div>
321
+ </ChildParticle>
322
+ </ParticleNetworkBg>
323
+ );
324
+ }
325
+ ```
326
+
327
+ ### `ChildParticle` / `GlassChildParticle` Props
328
+
329
+ | Prop | Type | Default | Description |
330
+ | ---------------- | --------- | -------- | ------------------------------------------------------------- |
331
+ | `id` | string | required | Unique identifier |
332
+ | `x` | number | required | Anchor X position (px) |
333
+ | `y` | number | required | Anchor Y position (px) |
334
+ | `radius` | number | required | Particle radius (px). Used for physics and as size |
335
+ | `width` | number | — | Rectangular width (px). Set with `height` for rect shape |
336
+ | `height` | number | — | Rectangular height (px) |
337
+ | `borderRadius` | number | — | Border radius (px) for rectangular shapes. Default: fully round |
338
+ | `overflow` | string | `"hidden"` | CSS overflow for the child content container |
339
+ | `anchorForce` | number | `0.05` | Spring force pulling back to anchor (0–1). Lower = more floaty |
340
+ | `mouseInfluence` | number | `0.1` | Mouse influence multiplier (0–1). 0 = ignores mouse |
341
+ | `children` | ReactNode | — | Content to render inside the particle |
342
+ | `style` | CSSProperties | — | Style applied to the inner wrapper div |
343
+ | `className` | string | — | Class applied to the inner wrapper div |
344
+
345
+ ### Vanilla JS
346
+
347
+ Use `addChildParticle` / `removeChildParticle` on the `ParticleNetwork` instance directly:
348
+
349
+ ```js
350
+ const network = new ParticleNetwork(canvas, { particleCount: 60 });
351
+ network.start();
352
+
353
+ // Add a child particle
354
+ network.addChildParticle({
355
+ id: "card-1",
356
+ x: 300,
357
+ y: 200,
358
+ radius: 50,
359
+ anchorForce: 0.05,
360
+ mouseInfluence: 0.1,
361
+ liquidGlass: false,
362
+ });
363
+
364
+ // Update its anchor (e.g. on scroll/resize)
365
+ network.updateChildParticle("card-1", { x: 400, y: 250 });
366
+
367
+ // Get current positions every frame via callback
368
+ network.onChildUpdate = (positions) => {
369
+ const pos = positions.get("card-1");
370
+ // pos.x, pos.y, pos.radius, pos.currentRadius, pos.width, pos.height, pos.rotation
371
+ myDomEl.style.transform = `translate(${pos.x}px, ${pos.y}px)`;
372
+ };
373
+
374
+ // Remove
375
+ network.removeChildParticle("card-1");
376
+ ```
377
+
378
+ ### Child Particle API
379
+
380
+ | Method / Property | Description |
381
+ | ---------------------------------------------- | -------------------------------------------------------------------- |
382
+ | `addChildParticle(config)` | Register a child particle. Creates the particle with anchor physics. |
383
+ | `removeChildParticle(id)` | Remove a child particle by ID. |
384
+ | `updateChildParticle(id, updates)` | Update anchor position or any config property at runtime. |
385
+ | `getChildParticlePositions()` | Returns a `Map<string, ChildParticlePosition>` with current state. |
386
+ | `onChildUpdate` | Callback fired every frame: `(positions: Map<string, ChildParticlePosition>) => void` |
387
+ | `getChildOverlayElement(id)` | Returns the DOM div overlay for a child particle (for manual use). |
388
+
389
+ ### Types
390
+
391
+ ```ts
392
+ import type { ChildParticleConfig, ChildParticlePosition } from "particle-network-bg";
393
+
394
+ interface ChildParticleConfig {
395
+ id: string;
396
+ x: number;
397
+ y: number;
398
+ radius: number;
399
+ width?: number;
400
+ height?: number;
401
+ borderRadius?: number;
402
+ overflow?: string;
403
+ anchorForce?: number;
404
+ mouseInfluence?: number;
405
+ liquidGlass?: boolean;
406
+ }
407
+
408
+ interface ChildParticlePosition {
409
+ x: number;
410
+ y: number;
411
+ radius: number;
412
+ currentRadius: number;
413
+ width?: number;
414
+ height?: number;
415
+ rotation: number; // blob rotation in radians (liquid glass only, 0 for normal)
416
+ }
417
+ ```
418
+
174
419
  ## API
175
420
 
176
421
  ### React (`particle-network-bg/react`)
177
422
 
178
- - `ParticleNetworkBg` – Wrapper component. Props: `config`, `style`, `className`
423
+ - `ParticleNetworkBg` – Wrapper component. Props: `config`, `style`, `className`, `children` (for `ChildParticle` / `GlassChildParticle`)
179
424
  - `useParticleNetwork(config?)` – Hook that returns a canvas ref
425
+ - `ChildParticle` – React child particle component (see [Child Particles](#child-particles))
426
+ - `GlassChildParticle` – Liquid glass variant of `ChildParticle`
427
+ - `ParticleNetworkContext` – React context exposing the `ParticleNetwork` instance; use `useContext(ParticleNetworkContext)` inside children of `ParticleNetworkBg` for direct instance access
180
428
 
181
429
  ### `ParticleNetwork` (vanilla)
182
430
 
@@ -193,6 +441,13 @@ import type {
193
441
  ParticleNetworkConfig,
194
442
  Particle,
195
443
  GradientType,
444
+ ConnectionRules,
445
+ LiquidGlassConfig,
446
+ LiquidGlassHighlightPosition,
447
+ ParticleTypeEntry,
448
+ ParticleAssetConfig,
449
+ ChildParticleConfig,
450
+ ChildParticlePosition,
196
451
  } from "particle-network-bg";
197
452
  ```
198
453