1- import { Component , Element , type JSX , Prop , Watch , h } from "@stencil/core" ;
1+ import { Component , type JSX , Prop , Watch , h } from "@stencil/core" ;
22import { Container , type ISourceOptions , tsParticles } from "@tsparticles/engine" ;
3- // ✅ Import the shared type instead of redefining it locally
4- // Adjust the path to match your actual project structure
53import type { ParticlesPluginRegistrar } from "../../initParticlesEngine" ;
4+ import { initParticlesEngine } from "../../initParticlesEngine" ;
65
76@Component ( {
87 tag : "stencil-particles" ,
98} )
109export class StencilParticles {
11- @Element ( ) private readonly host ! : HTMLElement ;
1210 private containerElement ?: HTMLDivElement ;
1311
14- // ✅ Removed `containerId`: loading via `element` avoids ID collisions entirely
1512 @Prop ( ) options ?: ISourceOptions ;
1613 @Prop ( ) url ?: string ;
1714 @Prop ( ) init ?: ParticlesPluginRegistrar ;
1815
1916 private container ?: Container ;
2017 private renderId = 0 ;
2118
22- // ✅ Static flag to prevent redundant `tsParticles.init()` calls
23- // when multiple instances of this component are mounted on the same page
24- private static engineInitialized = false ;
25-
2619 async componentDidLoad ( ) : Promise < void > {
2720 await this . loadParticles ( ++ this . renderId ) ;
2821 }
@@ -43,7 +36,6 @@ export class StencilParticles {
4336 private async loadParticles ( currentRenderId : number ) : Promise < void > {
4437 this . container ?. destroy ( ) ;
4538
46- // ✅ Guard clause: `containerElement` is now strictly required
4739 if ( ! this . containerElement ) {
4840 console . warn ( "[stencil-particles] container element not available yet" ) ;
4941 return ;
@@ -52,20 +44,19 @@ export class StencilParticles {
5244 let container : Container | undefined ;
5345
5446 try {
55- if ( ! StencilParticles . engineInitialized ) {
56- if ( this . init ) {
57- await this . init ( tsParticles ) ;
58- }
59- await tsParticles . init ( ) ;
60- StencilParticles . engineInitialized = true ;
47+ // Use the shared initialization logic to ensure consistent plugin registration
48+ // and avoid duplicate initialization when multiple instances mount concurrently.
49+ // initParticlesEngine handles promise de-duplication and enforces a stable init callback.
50+ if ( this . init ) {
51+ await initParticlesEngine ( this . init ) ;
6152 }
6253
6354 if ( ! this . options && ! this . url ) {
6455 console . warn ( "[stencil-particles] neither options nor url provided" ) ;
6556 return ;
6657 }
6758
68- // ✅ Load directly onto the DOM element.
59+ // Load particles directly onto the DOM element.
6960 // tsParticles will auto-generate a unique internal ID, preventing collisions.
7061 const loadParams = {
7162 element : this . containerElement ,
@@ -91,7 +82,6 @@ export class StencilParticles {
9182 return (
9283 < div
9384 ref = { el => {
94- // ✅ Ref is actively captured and passed to the engine
9585 this . containerElement = el as HTMLDivElement ;
9686 } }
9787 style = { { width : "100%" , height : "100%" } }
0 commit comments