partycles 0.3.0 → 0.4.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.
Files changed (124) hide show
  1. package/dist/animations/animations/bees.d.ts +8 -0
  2. package/dist/animations/animations/bees.d.ts.map +1 -0
  3. package/dist/animations/animations/butterflies.d.ts +8 -0
  4. package/dist/animations/animations/butterflies.d.ts.map +1 -0
  5. package/dist/animations/animations/candy.d.ts +8 -0
  6. package/dist/animations/animations/candy.d.ts.map +1 -0
  7. package/dist/animations/animations/champagne.d.ts +8 -0
  8. package/dist/animations/animations/champagne.d.ts.map +1 -0
  9. package/dist/animations/animations/crystals.d.ts +8 -0
  10. package/dist/animations/animations/crystals.d.ts.map +1 -0
  11. package/dist/animations/animations/dandelion.d.ts +8 -0
  12. package/dist/animations/animations/dandelion.d.ts.map +1 -0
  13. package/dist/animations/animations/dice.d.ts +8 -0
  14. package/dist/animations/animations/dice.d.ts.map +1 -0
  15. package/dist/animations/animations/donuts.d.ts +8 -0
  16. package/dist/animations/animations/donuts.d.ts.map +1 -0
  17. package/dist/animations/animations/dragons.d.ts +8 -0
  18. package/dist/animations/animations/dragons.d.ts.map +1 -0
  19. package/dist/animations/animations/galaxy.d.ts.map +1 -1
  20. package/dist/animations/animations/ghosts.d.ts +8 -0
  21. package/dist/animations/animations/ghosts.d.ts.map +1 -0
  22. package/dist/animations/animations/glitch.d.ts +8 -0
  23. package/dist/animations/animations/glitch.d.ts.map +1 -0
  24. package/dist/animations/animations/index.d.ts.map +1 -1
  25. package/dist/animations/animations/leaves.d.ts +8 -0
  26. package/dist/animations/animations/leaves.d.ts.map +1 -0
  27. package/dist/animations/animations/levelup.d.ts +8 -0
  28. package/dist/animations/animations/levelup.d.ts.map +1 -0
  29. package/dist/animations/animations/magicdust.d.ts +8 -0
  30. package/dist/animations/animations/magicdust.d.ts.map +1 -0
  31. package/dist/animations/animations/matrix.d.ts +8 -0
  32. package/dist/animations/animations/matrix.d.ts.map +1 -0
  33. package/dist/animations/animations/music.d.ts.map +1 -1
  34. package/dist/animations/animations/pixels.d.ts +8 -0
  35. package/dist/animations/animations/pixels.d.ts.map +1 -0
  36. package/dist/animations/animations/pizza.d.ts +8 -0
  37. package/dist/animations/animations/pizza.d.ts.map +1 -0
  38. package/dist/animations/animations/popcorn.d.ts +8 -0
  39. package/dist/animations/animations/popcorn.d.ts.map +1 -0
  40. package/dist/animations/animations/rain.d.ts +8 -0
  41. package/dist/animations/animations/rain.d.ts.map +1 -0
  42. package/dist/animations/animations/runes.d.ts +8 -0
  43. package/dist/animations/animations/runes.d.ts.map +1 -0
  44. package/dist/animations/bees.d.ts +8 -0
  45. package/dist/animations/bees.d.ts.map +1 -0
  46. package/dist/animations/bubbles.esm.js +3 -3
  47. package/dist/animations/bubbles.esm.js.map +1 -1
  48. package/dist/animations/bubbles.js +3 -3
  49. package/dist/animations/bubbles.js.map +1 -1
  50. package/dist/animations/butterflies.d.ts +8 -0
  51. package/dist/animations/butterflies.d.ts.map +1 -0
  52. package/dist/animations/candy.d.ts +8 -0
  53. package/dist/animations/candy.d.ts.map +1 -0
  54. package/dist/animations/champagne.d.ts +8 -0
  55. package/dist/animations/champagne.d.ts.map +1 -0
  56. package/dist/animations/confetti.esm.js +1 -1
  57. package/dist/animations/confetti.esm.js.map +1 -1
  58. package/dist/animations/confetti.js +1 -1
  59. package/dist/animations/confetti.js.map +1 -1
  60. package/dist/animations/crystals.d.ts +8 -0
  61. package/dist/animations/crystals.d.ts.map +1 -0
  62. package/dist/animations/dandelion.d.ts +8 -0
  63. package/dist/animations/dandelion.d.ts.map +1 -0
  64. package/dist/animations/dice.d.ts +8 -0
  65. package/dist/animations/dice.d.ts.map +1 -0
  66. package/dist/animations/donuts.d.ts +8 -0
  67. package/dist/animations/donuts.d.ts.map +1 -0
  68. package/dist/animations/dragons.d.ts +8 -0
  69. package/dist/animations/dragons.d.ts.map +1 -0
  70. package/dist/animations/emoji.esm.js.map +1 -1
  71. package/dist/animations/emoji.js.map +1 -1
  72. package/dist/animations/fireworks.esm.js +1 -1
  73. package/dist/animations/fireworks.esm.js.map +1 -1
  74. package/dist/animations/fireworks.js +1 -1
  75. package/dist/animations/fireworks.js.map +1 -1
  76. package/dist/animations/galaxy.d.ts.map +1 -1
  77. package/dist/animations/ghosts.d.ts +8 -0
  78. package/dist/animations/ghosts.d.ts.map +1 -0
  79. package/dist/animations/glitch.d.ts +8 -0
  80. package/dist/animations/glitch.d.ts.map +1 -0
  81. package/dist/animations/hearts.esm.js +1 -1
  82. package/dist/animations/hearts.esm.js.map +1 -1
  83. package/dist/animations/hearts.js +1 -1
  84. package/dist/animations/hearts.js.map +1 -1
  85. package/dist/animations/leaves.d.ts +8 -0
  86. package/dist/animations/leaves.d.ts.map +1 -0
  87. package/dist/animations/levelup.d.ts +8 -0
  88. package/dist/animations/levelup.d.ts.map +1 -0
  89. package/dist/animations/magicdust.d.ts +8 -0
  90. package/dist/animations/magicdust.d.ts.map +1 -0
  91. package/dist/animations/matrix.d.ts +8 -0
  92. package/dist/animations/matrix.d.ts.map +1 -0
  93. package/dist/animations/music.d.ts.map +1 -1
  94. package/dist/animations/pixels.d.ts +8 -0
  95. package/dist/animations/pixels.d.ts.map +1 -0
  96. package/dist/animations/pizza.d.ts +8 -0
  97. package/dist/animations/pizza.d.ts.map +1 -0
  98. package/dist/animations/popcorn.d.ts +8 -0
  99. package/dist/animations/popcorn.d.ts.map +1 -0
  100. package/dist/animations/rain.d.ts +8 -0
  101. package/dist/animations/rain.d.ts.map +1 -0
  102. package/dist/animations/runes.d.ts +8 -0
  103. package/dist/animations/runes.d.ts.map +1 -0
  104. package/dist/animations/snow.esm.js +1 -1
  105. package/dist/animations/snow.esm.js.map +1 -1
  106. package/dist/animations/snow.js +1 -1
  107. package/dist/animations/snow.js.map +1 -1
  108. package/dist/animations/sparkles.esm.js +1 -1
  109. package/dist/animations/sparkles.esm.js.map +1 -1
  110. package/dist/animations/sparkles.js +1 -1
  111. package/dist/animations/sparkles.js.map +1 -1
  112. package/dist/animations/stars.esm.js +1 -1
  113. package/dist/animations/stars.esm.js.map +1 -1
  114. package/dist/animations/stars.js +1 -1
  115. package/dist/animations/stars.js.map +1 -1
  116. package/dist/animations/types.d.ts +1 -1
  117. package/dist/animations/types.d.ts.map +1 -1
  118. package/dist/index.esm.js +1423 -92
  119. package/dist/index.esm.js.map +1 -1
  120. package/dist/index.js +1423 -92
  121. package/dist/index.js.map +1 -1
  122. package/dist/types.d.ts +1 -1
  123. package/dist/types.d.ts.map +1 -1
  124. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ const generateId = () => {
13
13
  return Math.random().toString(36).substring(2, 9);
14
14
  };
15
15
  const getRandomColor = (colors) => {
16
- return colors[Math.floor(Math.random() * colors.length)] || colors[0];
16
+ return colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff';
17
17
  };
18
18
  const createParticleStyle = (particle, containerRect) => {
19
19
  return {
@@ -28,9 +28,9 @@ const createParticleStyle = (particle, containerRect) => {
28
28
  };
29
29
  };
30
30
 
31
- const defaultColors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722'];
31
+ const defaultColors$f = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722'];
32
32
  const createConfettiParticles = (origin, config) => {
33
- const { particleCount = 50, startVelocity = 20, colors = defaultColors, elementSize = 20 } = config;
33
+ const { particleCount = 50, startVelocity = 20, colors = defaultColors$f, elementSize = 20 } = config;
34
34
  const particles = [];
35
35
  for (let i = 0; i < particleCount; i++) {
36
36
  const angle = randomInRange(0, 360);
@@ -76,7 +76,7 @@ const createSparkleParticles = (origin, config) => {
76
76
  opacity: 0,
77
77
  size: randomInRange(elementSize * 0.4, elementSize * 1.2),
78
78
  rotation: randomInRange(0, 360),
79
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
79
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
80
80
  });
81
81
  }
82
82
  return particles;
@@ -168,13 +168,13 @@ const createBubbleParticles = (origin, config) => {
168
168
  id: generateId(),
169
169
  x: origin.x + randomInRange(-spread, spread),
170
170
  y: origin.y,
171
- vx: randomInRange(-2, 2),
172
- vy: -randomInRange(startVelocity * 0.3, startVelocity * 0.6),
171
+ vx: randomInRange(-3, 3),
172
+ vy: -randomInRange(startVelocity * 0.7, startVelocity * 1.2),
173
173
  life: config.lifetime || 160,
174
174
  opacity: 0.7,
175
175
  size: randomInRange(elementSize * 0.4, elementSize * 1.2),
176
176
  rotation: 0,
177
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
177
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
178
178
  });
179
179
  }
180
180
  return particles;
@@ -211,7 +211,7 @@ const createStarParticles = (origin, config) => {
211
211
  opacity: 1,
212
212
  size: randomInRange(elementSize * 0.5, elementSize * 1.3),
213
213
  rotation: randomInRange(0, 360),
214
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
214
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
215
215
  });
216
216
  }
217
217
  return particles;
@@ -241,7 +241,7 @@ const createSnowParticles = (origin, config) => {
241
241
  opacity: randomInRange(0.4, 0.9),
242
242
  size: randomInRange(elementSize * 0.3, elementSize),
243
243
  rotation: randomInRange(0, 360),
244
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
244
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
245
245
  });
246
246
  }
247
247
  return particles;
@@ -324,7 +324,7 @@ const createCoinParticles = (origin, config) => {
324
324
  opacity: 1,
325
325
  size: randomInRange(elementSize * 0.8, elementSize * 1.2),
326
326
  rotation: randomInRange(0, 360),
327
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
327
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
328
328
  });
329
329
  }
330
330
  return particles;
@@ -378,7 +378,7 @@ const createLightningParticles = (origin, config) => {
378
378
  opacity: 1,
379
379
  size: randomInRange(elementSize * 0.5, elementSize * 1.5),
380
380
  rotation: randomInRange(0, 360),
381
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
381
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
382
382
  });
383
383
  }
384
384
  return particles;
@@ -433,7 +433,7 @@ const createPetalParticles = (origin, config) => {
433
433
  opacity: randomInRange(0.7, 1),
434
434
  size: randomInRange(elementSize * 0.7, elementSize * 1.3),
435
435
  rotation: randomInRange(0, 360),
436
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
436
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
437
437
  });
438
438
  }
439
439
  return particles;
@@ -491,7 +491,7 @@ const createAuroraParticles = (origin, config) => {
491
491
  opacity: 0,
492
492
  size: randomInRange(elementSize * 0.8, elementSize * 1.2),
493
493
  rotation: randomInRange(-15, 15),
494
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
494
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
495
495
  });
496
496
  }
497
497
  return particles;
@@ -548,7 +548,7 @@ const createFireflyParticles = (origin, config) => {
548
548
  opacity: 0,
549
549
  size: randomInRange(elementSize * 0.6, elementSize),
550
550
  rotation: randomInRange(0, 360), // Used for blink timing
551
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
551
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
552
552
  });
553
553
  }
554
554
  return particles;
@@ -618,7 +618,7 @@ const createPaintParticles = (origin, config) => {
618
618
  ? randomInRange(elementSize * 1.5, elementSize * 2.5)
619
619
  : randomInRange(elementSize * 0.3, elementSize),
620
620
  rotation: randomInRange(0, 360),
621
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
621
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
622
622
  });
623
623
  }
624
624
  return particles;
@@ -699,7 +699,7 @@ const createMusicParticles = (origin, config) => {
699
699
  opacity: 1,
700
700
  size: randomInRange(elementSize * 0.8, elementSize * 1.2),
701
701
  rotation: i % notes.length, // Store which note to use
702
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
702
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
703
703
  });
704
704
  }
705
705
  return particles;
@@ -710,9 +710,13 @@ const renderMusicParticle = (particle) => {
710
710
  // Wave motion as notes float up
711
711
  const waveX = Math.sin(particle.life * 0.05) * 20;
712
712
  const wobble = Math.sin(particle.life * 0.1) * 10;
713
- // Fade in/out
714
- const maxLife = 300; // Use longer lifetime for proper fading
715
- const fadeIn = particle.life > (maxLife - 20) ? (maxLife - particle.life) / 20 : 1;
713
+ // Simple fade based on particle life
714
+ // Assume default lifetime of 300 if not set
715
+ const totalLife = 300;
716
+ const age = totalLife - particle.life; // How old the particle is
717
+ // Fade in during first 20 frames
718
+ const fadeIn = age < 20 ? age / 20 : 1;
719
+ // Fade out during last 50 frames
716
720
  const fadeOut = particle.life < 50 ? particle.life / 50 : 1;
717
721
  const opacity = Math.min(fadeIn, fadeOut) * particle.opacity;
718
722
  return (React.createElement("div", { key: particle.id, style: {
@@ -764,15 +768,15 @@ const createBalloonParticles = (origin, config) => {
764
768
  const velocity = randomInRange(startVelocity * 0.7, startVelocity);
765
769
  particles.push({
766
770
  id: generateId(),
767
- x: origin.x + randomInRange(-30, 30),
768
- y: origin.y + randomInRange(0, 20),
769
- vx: Math.sin(angle) * velocity * 0.2,
771
+ x: origin.x + randomInRange(-spread * 0.8, spread * 0.8), // Spread balloons out more
772
+ y: origin.y + randomInRange(-10, 30),
773
+ vx: Math.sin(angle) * velocity * 0.3 + randomInRange(-1, 1), // Add horizontal drift
770
774
  vy: -velocity * 0.4, // Balloons float up slowly
771
775
  life: config.lifetime || 250,
772
776
  opacity: 0.9,
773
777
  size: randomInRange(elementSize * 0.8, elementSize * 1.2),
774
778
  rotation: randomInRange(-10, 10),
775
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
779
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
776
780
  });
777
781
  }
778
782
  return particles;
@@ -868,7 +872,7 @@ const createGalaxyParticles = (origin, config) => {
868
872
  opacity: 0,
869
873
  size: randomInRange(elementSize * 0.3, elementSize) * (1 - progress * 0.5), // Smaller at edges
870
874
  rotation: randomInRange(0, 360),
871
- color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
875
+ color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
872
876
  });
873
877
  }
874
878
  return particles;
@@ -936,74 +940,1401 @@ const renderGalaxyParticle = (particle) => {
936
940
  } }))));
937
941
  };
938
942
 
939
- const animations = {
940
- confetti: {
941
- createParticles: createConfettiParticles,
942
- renderParticle: renderConfettiParticle,
943
- },
944
- sparkles: {
945
- createParticles: createSparkleParticles,
946
- renderParticle: renderSparkleParticle,
947
- },
948
- hearts: {
949
- createParticles: createHeartParticles,
950
- renderParticle: renderHeartParticle,
951
- },
952
- fireworks: {
953
- createParticles: createFireworkParticles,
954
- renderParticle: renderFireworkParticle,
955
- },
956
- bubbles: {
957
- createParticles: createBubbleParticles,
958
- renderParticle: renderBubbleParticle,
959
- },
960
- stars: {
961
- createParticles: createStarParticles,
962
- renderParticle: renderStarParticle,
963
- },
964
- snow: {
965
- createParticles: createSnowParticles,
966
- renderParticle: renderSnowParticle,
967
- },
968
- emoji: {
969
- createParticles: createEmojiParticles,
970
- renderParticle: renderEmojiParticle,
971
- },
972
- coins: {
973
- createParticles: createCoinParticles,
974
- renderParticle: renderCoinParticle,
975
- },
976
- lightning: {
977
- createParticles: createLightningParticles,
978
- renderParticle: renderLightningParticle,
979
- },
980
- petals: {
981
- createParticles: createPetalParticles,
982
- renderParticle: renderPetalParticle,
983
- },
984
- aurora: {
985
- createParticles: createAuroraParticles,
986
- renderParticle: renderAuroraParticle,
987
- },
988
- fireflies: {
989
- createParticles: createFireflyParticles,
990
- renderParticle: renderFireflyParticle,
991
- },
992
- paint: {
993
- createParticles: createPaintParticles,
994
- renderParticle: renderPaintParticle,
995
- },
996
- music: {
997
- createParticles: createMusicParticles,
998
- renderParticle: renderMusicParticle,
999
- },
1000
- balloons: {
1001
- createParticles: createBalloonParticles,
1002
- renderParticle: renderBalloonParticle,
1003
- },
1004
- galaxy: {
1005
- createParticles: createGalaxyParticles,
1006
- renderParticle: renderGalaxyParticle,
943
+ const matrixChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン';
944
+ const createMatrixParticles = (origin, config) => {
945
+ const { particleCount = 50, elementSize = 300 } = config;
946
+ const particles = [];
947
+ const columns = Math.floor(elementSize / 20);
948
+ for (let i = 0; i < columns; i++) {
949
+ const columnX = origin.x - elementSize / 2 + (i / columns) * elementSize;
950
+ const columnParticles = Math.floor(Math.random() * 15) + 10;
951
+ for (let j = 0; j < columnParticles; j++) {
952
+ const charIndex = Math.floor(Math.random() * matrixChars.length);
953
+ const speed = randomInRange(80, 120);
954
+ particles.push({
955
+ id: generateId(),
956
+ x: columnX + randomInRange(-10, 10),
957
+ y: origin.y - elementSize / 2 - j * 25 - randomInRange(0, 100),
958
+ vx: columnParticles, // Store columnHeight in vx (since we don't use horizontal movement)
959
+ vy: speed,
960
+ life: config.lifetime || 150,
961
+ opacity: 1,
962
+ size: 20 + (j * 0.1), // Store fadeDelay as decimal part
963
+ rotation: charIndex + (columnParticles * 1000), // Store charIndex and columnHeight
964
+ color: '#00ff00',
965
+ });
966
+ }
967
+ }
968
+ return particles.slice(0, particleCount);
969
+ };
970
+ const renderMatrixParticle = (particle) => {
971
+ // Extract stored values
972
+ const charIndex = Math.floor(particle.rotation % 1000);
973
+ const columnHeight = Math.floor(particle.rotation / 1000);
974
+ const fadeDelay = (particle.size - Math.floor(particle.size));
975
+ const character = matrixChars[charIndex] || matrixChars[0];
976
+ const brightness = 1 - (fadeDelay / columnHeight) * 0.5;
977
+ return (React.createElement("div", { key: particle.id, style: {
978
+ fontSize: '20px',
979
+ fontFamily: 'monospace',
980
+ fontWeight: 'bold',
981
+ color: `rgba(${0}, ${255 * brightness}, ${0}, ${particle.opacity})`,
982
+ textShadow: `0 0 10px rgba(0, ${255 * brightness}, 0, ${particle.opacity * 0.8})`,
983
+ userSelect: 'none',
984
+ } }, character));
985
+ };
986
+
987
+ const pixelColors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#FF1493'];
988
+ const createPixelParticles = (origin, config) => {
989
+ const { particleCount = 30, colors = pixelColors, elementSize = 20 } = config;
990
+ const particles = [];
991
+ const gridSize = Math.floor(Math.sqrt(particleCount));
992
+ const spacing = 30;
993
+ for (let i = 0; i < gridSize; i++) {
994
+ for (let j = 0; j < gridSize; j++) {
995
+ const targetX = origin.x + (i - gridSize / 2) * spacing;
996
+ const targetY = origin.y + (j - gridSize / 2) * spacing;
997
+ const angle = randomInRange(0, 360);
998
+ const velocity = randomInRange(150, 300);
999
+ particles.push({
1000
+ id: generateId(),
1001
+ x: targetX,
1002
+ y: targetY,
1003
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1004
+ vy: Math.sin(degreesToRadians(angle)) * velocity,
1005
+ life: config.lifetime || 150,
1006
+ opacity: 1,
1007
+ size: randomInRange(elementSize * 0.6, elementSize),
1008
+ // Store targetX offset in rotation (from -500 to 500, add 1000 to make positive)
1009
+ rotation: ((targetX - origin.x) + 500) + ((targetY - origin.y) + 500) * 1000,
1010
+ color: getRandomColor(colors),
1011
+ });
1012
+ }
1013
+ }
1014
+ return particles.slice(0, particleCount);
1015
+ };
1016
+ const renderPixelParticle = (particle) => {
1017
+ return (React.createElement("div", { key: particle.id, style: {
1018
+ width: `${particle.size}px`,
1019
+ height: `${particle.size}px`,
1020
+ backgroundColor: particle.color,
1021
+ boxShadow: `0 0 ${particle.size / 2}px ${particle.color}`,
1022
+ } }));
1023
+ };
1024
+
1025
+ const createGlitchParticles = (origin, config) => {
1026
+ const { particleCount = 20, elementSize = 200 } = config;
1027
+ const particles = [];
1028
+ const channels = ['r', 'g', 'b'];
1029
+ for (let i = 0; i < particleCount; i++) {
1030
+ const isHorizontal = Math.random() > 0.3;
1031
+ const channelIndex = i % 3;
1032
+ const channel = channels[channelIndex];
1033
+ // Encode all data in rotation:
1034
+ // bits 0-1: channel (0=r, 1=g, 2=b)
1035
+ // bit 2: isHorizontal (0=false, 1=true)
1036
+ // bits 3-10: width (0-255)
1037
+ // bits 11-18: height (0-255)
1038
+ // bits 19-24: glitchOffset + 32 (to make positive)
1039
+ const width = isHorizontal ? randomInRange(50, 200) : randomInRange(2, 8);
1040
+ const height = isHorizontal ? randomInRange(2, 8) : randomInRange(50, 200);
1041
+ const glitchOffset = randomInRange(-20, 20);
1042
+ const encodedData = channelIndex +
1043
+ (isHorizontal ? 4 : 0) +
1044
+ (Math.floor(width) << 3) +
1045
+ (Math.floor(height) << 11) +
1046
+ ((glitchOffset + 32) << 19);
1047
+ particles.push({
1048
+ id: generateId(),
1049
+ x: origin.x + randomInRange(-elementSize / 2, elementSize / 2),
1050
+ y: origin.y + randomInRange(-elementSize / 2, elementSize / 2),
1051
+ vx: randomInRange(-50, 50),
1052
+ vy: randomInRange(-30, 30),
1053
+ life: config.lifetime || 150,
1054
+ opacity: randomInRange(0.3, 1),
1055
+ size: randomInRange(5, 20), // Store distortionAmount
1056
+ rotation: encodedData,
1057
+ color: channel === 'r' ? '#ff0000' : channel === 'g' ? '#00ff00' : '#0000ff',
1058
+ });
1059
+ }
1060
+ return particles;
1061
+ };
1062
+ const renderGlitchParticle = (particle) => {
1063
+ // Decode data from rotation
1064
+ const channelIndex = particle.rotation & 3;
1065
+ const width = (particle.rotation >> 3) & 255;
1066
+ const height = (particle.rotation >> 11) & 255;
1067
+ const glitchOffset = ((particle.rotation >> 19) & 63) - 32;
1068
+ const channel = ['r', 'g', 'b'][channelIndex];
1069
+ const distortionAmount = particle.size;
1070
+ const colors = {
1071
+ r: channel === 'r' ? 255 : 0,
1072
+ g: channel === 'g' ? 255 : 0,
1073
+ b: channel === 'b' ? 255 : 0,
1074
+ };
1075
+ const mixBlendMode = channel === 'r' ? 'screen' :
1076
+ channel === 'g' ? 'multiply' : 'difference';
1077
+ return (React.createElement("div", { key: particle.id, style: {
1078
+ width: `${width}px`,
1079
+ height: `${height}px`,
1080
+ backgroundColor: `rgba(${colors.r}, ${colors.g}, ${colors.b}, ${particle.opacity})`,
1081
+ mixBlendMode,
1082
+ filter: `blur(${randomInRange(0, 2)}px)`,
1083
+ boxShadow: `${glitchOffset}px 0 ${distortionAmount}px rgba(${colors.r}, ${colors.g}, ${colors.b}, ${particle.opacity * 0.5})`,
1084
+ } }));
1085
+ };
1086
+
1087
+ const getDiceFace = (value) => {
1088
+ const faces = ['⚀', '⚁', '⚂', '⚃', '⚄', '⚅'];
1089
+ return faces[value - 1] || '⚀';
1090
+ };
1091
+ const createDiceParticles = (origin, config) => {
1092
+ const { particleCount = 8, startVelocity = 25, elementSize = 40 } = config;
1093
+ const particles = [];
1094
+ for (let i = 0; i < particleCount; i++) {
1095
+ const angle = randomInRange(0, 360);
1096
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1097
+ const diceValue = Math.floor(randomInRange(1, 7));
1098
+ particles.push({
1099
+ id: generateId(),
1100
+ x: origin.x,
1101
+ y: origin.y,
1102
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1103
+ vy: Math.sin(degreesToRadians(angle)) * velocity - 30,
1104
+ life: config.lifetime || 150,
1105
+ opacity: 1,
1106
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1107
+ // Store dice value (1-6) in lower bits, and rotation angles in upper bits
1108
+ rotation: diceValue + (Math.floor(randomInRange(0, 360)) * 10),
1109
+ color: '#ffffff',
1110
+ });
1111
+ }
1112
+ return particles;
1113
+ };
1114
+ const renderDiceParticle = (particle) => {
1115
+ const diceValue = particle.rotation % 10;
1116
+ const rotationAngle = Math.floor(particle.rotation / 10);
1117
+ return (React.createElement("div", { key: particle.id, style: {
1118
+ width: `${particle.size}px`,
1119
+ height: `${particle.size}px`,
1120
+ fontSize: `${particle.size * 0.8}px`,
1121
+ display: 'flex',
1122
+ alignItems: 'center',
1123
+ justifyContent: 'center',
1124
+ backgroundColor: '#fff',
1125
+ color: '#000',
1126
+ borderRadius: `${particle.size * 0.2}px`,
1127
+ transform: `rotate(${rotationAngle}deg)`,
1128
+ transformStyle: 'preserve-3d',
1129
+ boxShadow: '0 4px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.5)',
1130
+ border: '2px solid #333',
1131
+ fontWeight: 'bold',
1132
+ } }, getDiceFace(diceValue)));
1133
+ };
1134
+
1135
+ const levelUpTexts = ['+1', '+10', '+100', 'XP', '+XP', 'LEVEL UP!', 'CRITICAL!', 'COMBO!', 'PERFECT!'];
1136
+ const levelUpColors = [
1137
+ { text: '#FFD700', glow: '#FFA500' }, // Gold
1138
+ { text: '#00FF00', glow: '#00AA00' }, // Green
1139
+ { text: '#00FFFF', glow: '#0088FF' }, // Cyan
1140
+ { text: '#FF00FF', glow: '#AA00AA' }, // Magenta
1141
+ { text: '#FFFF00', glow: '#FFAA00' }, // Yellow
1142
+ ];
1143
+ const createLevelUpParticles = (origin, config) => {
1144
+ const { particleCount = 10, startVelocity = 20, elementSize = 30 } = config;
1145
+ const particles = [];
1146
+ for (let i = 0; i < particleCount; i++) {
1147
+ const angle = randomInRange(-45, 45);
1148
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity * 1.5);
1149
+ const colorSetIndex = Math.floor(Math.random() * levelUpColors.length);
1150
+ const colorSet = levelUpColors[colorSetIndex] || levelUpColors[0];
1151
+ const textIndex = Math.floor(Math.random() * levelUpTexts.length);
1152
+ const text = levelUpTexts[textIndex];
1153
+ const isMainText = text === 'LEVEL UP!' || text === 'CRITICAL!';
1154
+ const fontSize = isMainText ? randomInRange(elementSize * 1.3, elementSize * 2) : randomInRange(elementSize * 0.7, elementSize * 1.2);
1155
+ particles.push({
1156
+ id: generateId(),
1157
+ x: origin.x,
1158
+ y: origin.y,
1159
+ vx: Math.sin(degreesToRadians(angle)) * velocity,
1160
+ vy: -Math.cos(degreesToRadians(angle)) * velocity - 10,
1161
+ life: config.lifetime || 150,
1162
+ opacity: 1,
1163
+ size: fontSize, // Store fontSize in size
1164
+ // Store textIndex (0-8) + colorSetIndex (0-4) * 10 + delay (0-50) * 100
1165
+ rotation: textIndex + (colorSetIndex * 10) + (Math.floor(i * 5) * 100),
1166
+ color: colorSet.text,
1167
+ });
1168
+ }
1169
+ return particles;
1170
+ };
1171
+ const renderLevelUpParticle = (particle) => {
1172
+ // Extract encoded values
1173
+ const textIndex = particle.rotation % 10;
1174
+ const colorSetIndex = Math.floor((particle.rotation % 100) / 10);
1175
+ const delay = Math.floor(particle.rotation / 100) / 100;
1176
+ const text = levelUpTexts[textIndex] || levelUpTexts[0];
1177
+ const colorSet = levelUpColors[colorSetIndex] || levelUpColors[0];
1178
+ return (React.createElement("div", { key: particle.id, style: {
1179
+ fontSize: `${particle.size}px`,
1180
+ fontWeight: 'bold',
1181
+ fontFamily: 'Arial, sans-serif',
1182
+ color: particle.color,
1183
+ textShadow: `
1184
+ 0 0 10px ${colorSet.glow},
1185
+ 0 0 20px ${colorSet.glow},
1186
+ 0 0 30px ${particle.color},
1187
+ 0 2px 4px rgba(0,0,0,0.5)
1188
+ `,
1189
+ letterSpacing: '2px',
1190
+ textTransform: 'uppercase',
1191
+ whiteSpace: 'nowrap',
1192
+ userSelect: 'none',
1193
+ animationDelay: `${delay}s`,
1194
+ } }, text));
1195
+ };
1196
+
1197
+ const defaultColors$e = ['#9C27B0', '#E91E63', '#FF00FF', '#00FFFF', '#FFD700', '#FF69B4', '#DA70D6', '#9370DB'];
1198
+ const createMagicDustParticles = (origin, config) => {
1199
+ const { particleCount = 40, startVelocity = 8, colors = defaultColors$e, elementSize = 12 } = config;
1200
+ const particles = [];
1201
+ for (let i = 0; i < particleCount; i++) {
1202
+ // Create particles in a circular pattern with some randomness
1203
+ const angle = (i / particleCount) * 360 + randomInRange(-30, 30);
1204
+ const velocity = randomInRange(startVelocity * 0.3, startVelocity);
1205
+ const color = getRandomColor(colors);
1206
+ // Add some particles that trail behind cursor movement
1207
+ const offsetAngle = randomInRange(0, 360);
1208
+ const offsetDistance = randomInRange(0, 30);
1209
+ particles.push({
1210
+ id: generateId(),
1211
+ x: origin.x + Math.cos(degreesToRadians(offsetAngle)) * offsetDistance,
1212
+ y: origin.y + Math.sin(degreesToRadians(offsetAngle)) * offsetDistance,
1213
+ vx: Math.cos(degreesToRadians(angle)) * velocity + randomInRange(-2, 2),
1214
+ vy: Math.sin(degreesToRadians(angle)) * velocity + randomInRange(-2, 2),
1215
+ life: config.lifetime || 120,
1216
+ opacity: randomInRange(0.4, 1),
1217
+ size: randomInRange(elementSize * 0.3, elementSize),
1218
+ rotation: randomInRange(0, 360),
1219
+ color,
1220
+ });
1221
+ }
1222
+ return particles;
1223
+ };
1224
+ const renderMagicDustParticle = (particle) => {
1225
+ const sparkleSize = particle.size * 0.7;
1226
+ return (React.createElement("div", { key: particle.id, style: {
1227
+ width: `${particle.size}px`,
1228
+ height: `${particle.size}px`,
1229
+ position: 'relative',
1230
+ } },
1231
+ React.createElement("div", { style: {
1232
+ position: 'absolute',
1233
+ width: '100%',
1234
+ height: '100%',
1235
+ backgroundColor: particle.color,
1236
+ borderRadius: '50%',
1237
+ boxShadow: `0 0 ${particle.size}px ${particle.color}, 0 0 ${particle.size * 2}px ${particle.color}`,
1238
+ filter: 'blur(1px)',
1239
+ } }),
1240
+ React.createElement("div", { style: {
1241
+ position: 'absolute',
1242
+ top: '50%',
1243
+ left: '50%',
1244
+ width: `${sparkleSize}px`,
1245
+ height: `${sparkleSize}px`,
1246
+ transform: `translate(-50%, -50%) rotate(${particle.rotation}deg)`,
1247
+ } },
1248
+ React.createElement("div", { style: {
1249
+ position: 'absolute',
1250
+ width: '100%',
1251
+ height: '2px',
1252
+ backgroundColor: 'white',
1253
+ top: '50%',
1254
+ left: '0',
1255
+ transform: 'translateY(-50%)',
1256
+ boxShadow: '0 0 4px white',
1257
+ } }),
1258
+ React.createElement("div", { style: {
1259
+ position: 'absolute',
1260
+ width: '2px',
1261
+ height: '100%',
1262
+ backgroundColor: 'white',
1263
+ left: '50%',
1264
+ top: '0',
1265
+ transform: 'translateX(-50%)',
1266
+ boxShadow: '0 0 4px white',
1267
+ } }))));
1268
+ };
1269
+
1270
+ const defaultColors$d = ['#FFFFFF', '#F0F0F0', '#E8E8E8', '#F5F5F5', '#FAFAFA'];
1271
+ const createGhostParticles = (origin, config) => {
1272
+ const { particleCount = 8, startVelocity = 5, colors = defaultColors$d, elementSize = 30 } = config;
1273
+ const particles = [];
1274
+ for (let i = 0; i < particleCount; i++) {
1275
+ // Ghosts float upward with slight horizontal movement
1276
+ const angle = randomInRange(250, 290); // Mostly upward
1277
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1278
+ const color = getRandomColor(colors);
1279
+ particles.push({
1280
+ id: generateId(),
1281
+ x: origin.x + randomInRange(-50, 50),
1282
+ y: origin.y + randomInRange(-20, 20),
1283
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1284
+ vy: Math.sin(degreesToRadians(angle)) * velocity,
1285
+ life: config.lifetime || 200,
1286
+ opacity: randomInRange(0.5, 0.8),
1287
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1288
+ rotation: randomInRange(-15, 15),
1289
+ color,
1290
+ });
1291
+ }
1292
+ return particles;
1293
+ };
1294
+ const renderGhostParticle = (particle) => {
1295
+ // Calculate wave effect for tail
1296
+ const waveOffset = Math.sin(Date.now() * 0.003 + particle.x * 0.01) * 3;
1297
+ return (React.createElement("div", { key: particle.id, style: {
1298
+ width: `${particle.size}px`,
1299
+ height: `${particle.size * 1.4}px`,
1300
+ position: 'relative',
1301
+ transform: `rotate(${particle.rotation}deg)`,
1302
+ } },
1303
+ React.createElement("div", { style: {
1304
+ position: 'absolute',
1305
+ width: '100%',
1306
+ height: '70%',
1307
+ backgroundColor: particle.color,
1308
+ borderRadius: '50% 50% 0 0',
1309
+ boxShadow: `0 0 20px rgba(255, 255, 255, 0.5), inset 0 0 10px rgba(0, 0, 0, 0.1)`,
1310
+ } }),
1311
+ React.createElement("div", { style: {
1312
+ position: 'absolute',
1313
+ bottom: 0,
1314
+ width: '100%',
1315
+ height: '40%',
1316
+ backgroundColor: particle.color,
1317
+ clipPath: `polygon(
1318
+ 0 0,
1319
+ 100% 0,
1320
+ 100% 60%,
1321
+ ${75 + waveOffset}% 80%,
1322
+ ${50 - waveOffset}% 100%,
1323
+ ${25 + waveOffset}% 80%,
1324
+ 0 60%
1325
+ )`,
1326
+ } }),
1327
+ React.createElement("div", { style: {
1328
+ position: 'absolute',
1329
+ top: '30%',
1330
+ left: '25%',
1331
+ width: '15%',
1332
+ height: '15%',
1333
+ backgroundColor: '#000',
1334
+ borderRadius: '50%',
1335
+ } }),
1336
+ React.createElement("div", { style: {
1337
+ position: 'absolute',
1338
+ top: '30%',
1339
+ right: '25%',
1340
+ width: '15%',
1341
+ height: '15%',
1342
+ backgroundColor: '#000',
1343
+ borderRadius: '50%',
1344
+ } }),
1345
+ React.createElement("div", { style: {
1346
+ position: 'absolute',
1347
+ top: '45%',
1348
+ left: '50%',
1349
+ transform: 'translateX(-50%)',
1350
+ width: '25%',
1351
+ height: '15%',
1352
+ border: '2px solid #000',
1353
+ borderTop: 'none',
1354
+ borderRadius: '0 0 50% 50%',
1355
+ } })));
1356
+ };
1357
+
1358
+ const defaultColors$c = ['#FF1493', '#00CED1', '#FFD700', '#FF69B4', '#7B68EE', '#00FA9A', '#FF6347', '#4169E1'];
1359
+ const createCrystalParticles = (origin, config) => {
1360
+ const { particleCount = 15, startVelocity = 15, colors = defaultColors$c, elementSize = 25 } = config;
1361
+ const particles = [];
1362
+ for (let i = 0; i < particleCount; i++) {
1363
+ // Crystals explode outward and fall with gravity
1364
+ const angle = randomInRange(0, 360);
1365
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1366
+ const color = getRandomColor(colors);
1367
+ particles.push({
1368
+ id: generateId(),
1369
+ x: origin.x,
1370
+ y: origin.y,
1371
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1372
+ vy: Math.sin(degreesToRadians(angle)) * velocity - 10,
1373
+ life: config.lifetime || 150,
1374
+ opacity: randomInRange(0.7, 1),
1375
+ size: randomInRange(elementSize * 0.6, elementSize),
1376
+ rotation: randomInRange(0, 360),
1377
+ color,
1378
+ });
1379
+ }
1380
+ return particles;
1381
+ };
1382
+ const renderCrystalParticle = (particle) => {
1383
+ // Create rainbow refraction effect
1384
+ const hue = (Date.now() * 0.5 + particle.x + particle.y) % 360;
1385
+ return (React.createElement("div", { key: particle.id, style: {
1386
+ width: `${particle.size}px`,
1387
+ height: `${particle.size * 1.5}px`,
1388
+ position: 'relative',
1389
+ transform: `rotate(${particle.rotation}deg)`,
1390
+ } },
1391
+ React.createElement("div", { style: {
1392
+ position: 'absolute',
1393
+ width: '100%',
1394
+ height: '100%',
1395
+ background: `linear-gradient(135deg, ${particle.color}, ${particle.color}88, transparent)`,
1396
+ clipPath: 'polygon(50% 0%, 100% 40%, 75% 100%, 25% 100%, 0% 40%)',
1397
+ boxShadow: `0 0 ${particle.size}px ${particle.color}44`,
1398
+ } }),
1399
+ React.createElement("div", { style: {
1400
+ position: 'absolute',
1401
+ width: '80%',
1402
+ height: '80%',
1403
+ top: '10%',
1404
+ left: '10%',
1405
+ background: `linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.4), transparent)`,
1406
+ clipPath: 'polygon(50% 10%, 90% 45%, 65% 90%, 35% 90%, 10% 45%)',
1407
+ } }),
1408
+ React.createElement("div", { style: {
1409
+ position: 'absolute',
1410
+ width: '100%',
1411
+ height: '100%',
1412
+ background: `linear-gradient(${hue}deg,
1413
+ hsla(${hue}, 100%, 50%, 0.3),
1414
+ hsla(${(hue + 60) % 360}, 100%, 50%, 0.3),
1415
+ hsla(${(hue + 120) % 360}, 100%, 50%, 0.3)
1416
+ )`,
1417
+ clipPath: 'polygon(50% 0%, 100% 40%, 75% 100%, 25% 100%, 0% 40%)',
1418
+ mixBlendMode: 'screen',
1419
+ } }),
1420
+ React.createElement("div", { style: {
1421
+ position: 'absolute',
1422
+ width: '30%',
1423
+ height: '30%',
1424
+ top: '20%',
1425
+ left: '35%',
1426
+ background: 'radial-gradient(circle, rgba(255, 255, 255, 0.8), transparent)',
1427
+ borderRadius: '50%',
1428
+ filter: 'blur(2px)',
1429
+ } })));
1430
+ };
1431
+
1432
+ const defaultColors$b = ['#FF4500', '#DC143C', '#B22222', '#8B0000', '#FF6347', '#FF8C00'];
1433
+ const createDragonParticles = (origin, config) => {
1434
+ const { particleCount = 6, startVelocity = 12, colors = defaultColors$b, elementSize = 40 } = config;
1435
+ const particles = [];
1436
+ for (let i = 0; i < particleCount; i++) {
1437
+ // Dragons fly in various directions with swooping motion
1438
+ const angle = randomInRange(0, 360);
1439
+ const velocity = randomInRange(startVelocity * 0.7, startVelocity);
1440
+ const color = getRandomColor(colors);
1441
+ particles.push({
1442
+ id: generateId(),
1443
+ x: origin.x + randomInRange(-30, 30),
1444
+ y: origin.y + randomInRange(-30, 30),
1445
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1446
+ vy: Math.sin(degreesToRadians(angle)) * velocity,
1447
+ life: config.lifetime || 180,
1448
+ opacity: 1,
1449
+ size: randomInRange(elementSize * 0.8, elementSize),
1450
+ rotation: angle,
1451
+ color,
1452
+ });
1453
+ }
1454
+ return particles;
1455
+ };
1456
+ const renderDragonParticle = (particle) => {
1457
+ // Calculate wing flap animation
1458
+ const wingFlap = Math.sin(Date.now() * 0.01 + particle.x) * 10;
1459
+ // Calculate fire breath pulse
1460
+ const firePulse = (Math.sin(Date.now() * 0.005 + particle.y) + 1) / 2;
1461
+ return (React.createElement("div", { key: particle.id, style: {
1462
+ width: `${particle.size}px`,
1463
+ height: `${particle.size}px`,
1464
+ position: 'relative',
1465
+ transform: `rotate(${particle.rotation}deg)`,
1466
+ } },
1467
+ React.createElement("div", { style: {
1468
+ position: 'absolute',
1469
+ width: '60%',
1470
+ height: '40%',
1471
+ top: '30%',
1472
+ left: '20%',
1473
+ backgroundColor: particle.color,
1474
+ borderRadius: '50% 40% 40% 50%',
1475
+ boxShadow: `0 2px 10px rgba(0, 0, 0, 0.3)`,
1476
+ } }),
1477
+ React.createElement("div", { style: {
1478
+ position: 'absolute',
1479
+ width: '35%',
1480
+ height: '35%',
1481
+ top: '25%',
1482
+ right: '15%',
1483
+ backgroundColor: particle.color,
1484
+ borderRadius: '40% 50% 50% 40%',
1485
+ transform: 'rotate(-10deg)',
1486
+ } },
1487
+ React.createElement("div", { style: {
1488
+ position: 'absolute',
1489
+ width: '20%',
1490
+ height: '20%',
1491
+ top: '30%',
1492
+ right: '25%',
1493
+ backgroundColor: '#FFD700',
1494
+ borderRadius: '50%',
1495
+ boxShadow: '0 0 4px #FFD700',
1496
+ } })),
1497
+ React.createElement("div", { style: {
1498
+ position: 'absolute',
1499
+ width: '40%',
1500
+ height: '50%',
1501
+ top: '15%',
1502
+ left: '30%',
1503
+ backgroundColor: `${particle.color}CC`,
1504
+ clipPath: 'polygon(0% 100%, 50% 0%, 100% 30%, 90% 60%, 100% 90%, 50% 100%)',
1505
+ transform: `rotateX(${wingFlap}deg)`,
1506
+ transformOrigin: 'bottom center',
1507
+ } }),
1508
+ React.createElement("div", { style: {
1509
+ position: 'absolute',
1510
+ width: '40%',
1511
+ height: '50%',
1512
+ top: '35%',
1513
+ left: '30%',
1514
+ backgroundColor: `${particle.color}AA`,
1515
+ clipPath: 'polygon(0% 0%, 50% 0%, 100% 30%, 90% 60%, 100% 90%, 50% 100%)',
1516
+ transform: `rotateX(${-wingFlap}deg)`,
1517
+ transformOrigin: 'top center',
1518
+ } }),
1519
+ React.createElement("div", { style: {
1520
+ position: 'absolute',
1521
+ width: '40%',
1522
+ height: '15%',
1523
+ top: '35%',
1524
+ left: '5%',
1525
+ backgroundColor: particle.color,
1526
+ clipPath: 'polygon(0% 50%, 70% 0%, 100% 20%, 100% 80%, 70% 100%, 0% 50%)',
1527
+ } }),
1528
+ React.createElement("div", { style: {
1529
+ position: 'absolute',
1530
+ width: '30%',
1531
+ height: '20%',
1532
+ top: '35%',
1533
+ right: '5%',
1534
+ background: `radial-gradient(ellipse, #FFD700 0%, #FF4500 50%, transparent 100%)`,
1535
+ transform: `scale(${0.8 + firePulse * 0.4})`,
1536
+ opacity: 0.8 + firePulse * 0.2,
1537
+ filter: 'blur(1px)',
1538
+ } }),
1539
+ React.createElement("div", { style: {
1540
+ position: 'absolute',
1541
+ width: '25%',
1542
+ height: '15%',
1543
+ top: '37%',
1544
+ right: '0%',
1545
+ background: `radial-gradient(ellipse, #FFA500 0%, #FF6347 50%, transparent 100%)`,
1546
+ transform: `scale(${0.6 + firePulse * 0.6})`,
1547
+ opacity: 0.6 + firePulse * 0.4,
1548
+ filter: 'blur(2px)',
1549
+ } })));
1550
+ };
1551
+
1552
+ const defaultColors$a = ['#9C27B0', '#673AB7', '#3F51B5', '#00BCD4', '#4CAF50', '#FFEB3B', '#FF9800'];
1553
+ // Ancient rune symbols
1554
+ const runeSymbols = [
1555
+ 'ᚠ', 'ᚢ', 'ᚦ', 'ᚨ', 'ᚱ', 'ᚲ', 'ᚷ', 'ᚹ', 'ᚺ', 'ᚾ', 'ᛁ', 'ᛃ', 'ᛇ', 'ᛈ', 'ᛉ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛖ', 'ᛗ', 'ᛚ', 'ᛜ', 'ᛞ', 'ᛟ'
1556
+ ];
1557
+ const createRuneParticles = (origin, config) => {
1558
+ const { particleCount = 12, startVelocity = 6, colors = defaultColors$a, elementSize = 35 } = config;
1559
+ const particles = [];
1560
+ for (let i = 0; i < particleCount; i++) {
1561
+ // Runes float upward in a mystical pattern
1562
+ const angle = randomInRange(250, 290); // Mostly upward
1563
+ const velocity = randomInRange(startVelocity * 0.3, startVelocity * 0.7);
1564
+ const color = getRandomColor(colors);
1565
+ // Create circular spawn pattern
1566
+ const spawnAngle = (i / particleCount) * 360;
1567
+ const spawnRadius = randomInRange(20, 60);
1568
+ const runeIndex = Math.floor(Math.random() * runeSymbols.length);
1569
+ particles.push({
1570
+ id: generateId(),
1571
+ x: origin.x + Math.cos(degreesToRadians(spawnAngle)) * spawnRadius,
1572
+ y: origin.y + Math.sin(degreesToRadians(spawnAngle)) * spawnRadius,
1573
+ vx: Math.cos(degreesToRadians(angle)) * velocity + randomInRange(-1, 1),
1574
+ vy: Math.sin(degreesToRadians(angle)) * velocity,
1575
+ life: config.lifetime || 160,
1576
+ opacity: 0,
1577
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1578
+ // Store runeIndex in lower bits of rotation, keep rotation angle in upper bits
1579
+ rotation: runeIndex + (Math.floor(randomInRange(0, 360)) * 100),
1580
+ color,
1581
+ });
1582
+ }
1583
+ return particles;
1584
+ };
1585
+ const renderRuneParticle = (particle) => {
1586
+ // Extract rune index and rotation from encoded value
1587
+ const runeIndex = particle.rotation % 100;
1588
+ const rotationAngle = Math.floor(particle.rotation / 100);
1589
+ const runeSymbol = runeSymbols[runeIndex] || runeSymbols[0];
1590
+ // Calculate pulsing glow effect
1591
+ const glowIntensity = (Math.sin(Date.now() * 0.003 + particle.x * 0.01) + 1) / 2;
1592
+ // Fade in and out based on life
1593
+ const fadeProgress = particle.life > 120 ? (160 - particle.life) / 40 : particle.life < 40 ? particle.life / 40 : 1;
1594
+ return (React.createElement("div", { key: particle.id, style: {
1595
+ width: `${particle.size}px`,
1596
+ height: `${particle.size}px`,
1597
+ position: 'relative',
1598
+ transform: `rotate(${rotationAngle}deg)`,
1599
+ opacity: fadeProgress,
1600
+ } },
1601
+ React.createElement("div", { style: {
1602
+ position: 'absolute',
1603
+ width: '100%',
1604
+ height: '100%',
1605
+ borderRadius: '50%',
1606
+ background: `radial-gradient(circle, ${particle.color}44 0%, transparent 70%)`,
1607
+ transform: `scale(${1.5 + glowIntensity * 0.5})`,
1608
+ filter: 'blur(4px)',
1609
+ } }),
1610
+ React.createElement("div", { style: {
1611
+ position: 'absolute',
1612
+ width: '100%',
1613
+ height: '100%',
1614
+ borderRadius: '50%',
1615
+ background: `radial-gradient(circle, ${particle.color}88 0%, ${particle.color}44 50%, transparent 100%)`,
1616
+ transform: `scale(${1.2 + glowIntensity * 0.3})`,
1617
+ } }),
1618
+ React.createElement("div", { style: {
1619
+ position: 'absolute',
1620
+ width: '100%',
1621
+ height: '100%',
1622
+ display: 'flex',
1623
+ alignItems: 'center',
1624
+ justifyContent: 'center',
1625
+ fontSize: `${particle.size * 0.7}px`,
1626
+ fontWeight: 'bold',
1627
+ color: '#FFFFFF',
1628
+ textShadow: `
1629
+ 0 0 10px ${particle.color},
1630
+ 0 0 20px ${particle.color},
1631
+ 0 0 30px ${particle.color},
1632
+ 0 0 40px ${particle.color}
1633
+ `,
1634
+ filter: `brightness(${1.5 + glowIntensity * 0.5})`,
1635
+ } }, runeSymbol),
1636
+ [0, 72, 144, 216, 288].map((angle, index) => (React.createElement("div", { key: index, style: {
1637
+ position: 'absolute',
1638
+ width: '4px',
1639
+ height: '4px',
1640
+ backgroundColor: '#FFFFFF',
1641
+ borderRadius: '50%',
1642
+ top: '50%',
1643
+ left: '50%',
1644
+ transform: `
1645
+ translate(-50%, -50%)
1646
+ rotate(${angle + rotationAngle}deg)
1647
+ translateY(-${particle.size * 0.6}px)
1648
+ scale(${0.5 + glowIntensity})
1649
+ `,
1650
+ boxShadow: '0 0 6px #FFFFFF',
1651
+ opacity: glowIntensity,
1652
+ } })))));
1653
+ };
1654
+
1655
+ const defaultColors$9 = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#F7DC6F', '#BB8FCE'];
1656
+ const createButterflyParticles = (origin, config) => {
1657
+ const { particleCount = 6, startVelocity = 3, colors = defaultColors$9, elementSize = 40 } = config;
1658
+ const particles = [];
1659
+ for (let i = 0; i < particleCount; i++) {
1660
+ const angle = randomInRange(0, 360);
1661
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1662
+ particles.push({
1663
+ id: generateId(),
1664
+ x: origin.x + randomInRange(-50, 50),
1665
+ y: origin.y + randomInRange(-30, 30),
1666
+ vx: Math.cos(angle * Math.PI / 180) * velocity,
1667
+ vy: -Math.abs(Math.sin(angle * Math.PI / 180) * velocity * 0.5), // Float upward
1668
+ life: config.lifetime || 200,
1669
+ opacity: 1,
1670
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1671
+ // Encode wing phase (0-360), wobble phase (0-360), and rotation speed (-10 to 10)
1672
+ rotation: Math.floor(randomInRange(0, 360)) + (Math.floor(randomInRange(0, 360)) * 1000) + ((Math.floor(randomInRange(-10, 10)) + 10) * 1000000),
1673
+ color: getRandomColor(colors),
1674
+ });
1675
+ }
1676
+ return particles;
1677
+ };
1678
+ const renderButterflyParticle = (particle) => {
1679
+ // Extract encoded values
1680
+ const wingPhase = (particle.rotation % 1000);
1681
+ const wobblePhase = Math.floor((particle.rotation % 1000000) / 1000);
1682
+ const rotationSpeed = (Math.floor(particle.rotation / 1000000) - 10) / 10;
1683
+ // Calculate wing flapping and wobble
1684
+ const wingAngle = Math.sin((Date.now() * 0.01 + wingPhase) * Math.PI / 180) * 30;
1685
+ const wobbleX = Math.sin((Date.now() * 0.003 + wobblePhase) * Math.PI / 180) * 10;
1686
+ const rotation = (Date.now() * rotationSpeed * 0.01) % 360;
1687
+ return (React.createElement("div", { key: particle.id, style: {
1688
+ width: `${particle.size}px`,
1689
+ height: `${particle.size}px`,
1690
+ position: 'relative',
1691
+ transform: `translateX(${wobbleX}px) rotate(${rotation}deg)`,
1692
+ } },
1693
+ React.createElement("svg", { width: particle.size, height: particle.size, viewBox: "-25 -25 50 50", style: {
1694
+ position: 'absolute',
1695
+ top: 0,
1696
+ left: 0,
1697
+ } },
1698
+ React.createElement("ellipse", { cx: "-8", cy: "0", rx: "12", ry: "18", fill: particle.color, opacity: "0.8", transform: `rotate(${-wingAngle} 0 0)` }),
1699
+ React.createElement("ellipse", { cx: "-6", cy: "-10", rx: "8", ry: "12", fill: particle.color, opacity: "0.6", transform: `rotate(${-wingAngle - 15} 0 0)` }),
1700
+ React.createElement("ellipse", { cx: "8", cy: "0", rx: "12", ry: "18", fill: particle.color, opacity: "0.8", transform: `rotate(${wingAngle} 0 0)` }),
1701
+ React.createElement("ellipse", { cx: "6", cy: "-10", rx: "8", ry: "12", fill: particle.color, opacity: "0.6", transform: `rotate(${wingAngle + 15} 0 0)` }),
1702
+ React.createElement("ellipse", { cx: "0", cy: "0", rx: "3", ry: "15", fill: "#333" }),
1703
+ React.createElement("line", { x1: "0", y1: "-12", x2: "-3", y2: "-18", stroke: "#333", strokeWidth: "1" }),
1704
+ React.createElement("line", { x1: "0", y1: "-12", x2: "3", y2: "-18", stroke: "#333", strokeWidth: "1" }),
1705
+ React.createElement("circle", { cx: "-8", cy: "0", r: "3", fill: "white", opacity: "0.4" }),
1706
+ React.createElement("circle", { cx: "8", cy: "0", r: "3", fill: "white", opacity: "0.4" }),
1707
+ React.createElement("circle", { cx: "-6", cy: "-8", r: "2", fill: "black", opacity: "0.3" }),
1708
+ React.createElement("circle", { cx: "6", cy: "-8", r: "2", fill: "black", opacity: "0.3" }))));
1709
+ };
1710
+
1711
+ const defaultColors$8 = ['#D2691E', '#CD853F', '#8B4513', '#A0522D', '#FF8C00', '#FF6347'];
1712
+ const createLeafParticles = (origin, config) => {
1713
+ const { particleCount = 10, colors = defaultColors$8, elementSize = 25 } = config;
1714
+ const particles = [];
1715
+ for (let i = 0; i < particleCount; i++) {
1716
+ particles.push({
1717
+ id: generateId(),
1718
+ x: origin.x + randomInRange(-100, 100),
1719
+ y: origin.y + randomInRange(-50, 0),
1720
+ vx: randomInRange(-1, 1),
1721
+ vy: randomInRange(0.5, 2),
1722
+ life: config.lifetime || 300,
1723
+ opacity: 1,
1724
+ size: randomInRange(elementSize * 0.6, elementSize),
1725
+ // Encode tumble phase (0-360), sway phase (0-360), and sway amount (20-40) + rotation speed (-3 to 3)
1726
+ rotation: Math.floor(randomInRange(0, 360)) +
1727
+ (Math.floor(randomInRange(0, 360)) * 1000) +
1728
+ (Math.floor(randomInRange(20, 40)) * 1000000) +
1729
+ ((Math.floor(randomInRange(-3, 3)) + 3) * 100000000),
1730
+ color: getRandomColor(colors),
1731
+ });
1732
+ }
1733
+ return particles;
1734
+ };
1735
+ const renderLeafParticle = (particle) => {
1736
+ // Extract encoded values
1737
+ const tumblePhase = particle.rotation % 1000;
1738
+ const swayPhase = Math.floor((particle.rotation % 1000000) / 1000);
1739
+ const swayAmount = Math.floor((particle.rotation % 100000000) / 1000000);
1740
+ const rotationSpeed = (Math.floor(particle.rotation / 100000000) - 3);
1741
+ // Calculate tumbling and swaying
1742
+ const tumble = Math.sin((Date.now() * 0.002 + tumblePhase) * Math.PI / 180) * 30;
1743
+ const swayX = Math.sin((Date.now() * 0.001 + swayPhase) * Math.PI / 180) * swayAmount;
1744
+ const rotation = (Date.now() * rotationSpeed * 0.01 + tumble) % 360;
1745
+ return (React.createElement("div", { key: particle.id, style: {
1746
+ width: `${particle.size}px`,
1747
+ height: `${particle.size}px`,
1748
+ position: 'relative',
1749
+ transform: `translateX(${swayX}px) rotate(${rotation}deg)`,
1750
+ } },
1751
+ React.createElement("svg", { width: particle.size, height: particle.size, viewBox: `-${particle.size / 2} -${particle.size / 2} ${particle.size} ${particle.size}`, style: {
1752
+ position: 'absolute',
1753
+ top: 0,
1754
+ left: 0,
1755
+ } },
1756
+ React.createElement("path", { d: `
1757
+ M 0,-${particle.size / 2}
1758
+ C -${particle.size / 3},-${particle.size / 3} -${particle.size / 3},${particle.size / 3} 0,${particle.size / 2}
1759
+ C ${particle.size / 3},${particle.size / 3} ${particle.size / 3},-${particle.size / 3} 0,-${particle.size / 2}
1760
+ `, fill: particle.color, opacity: "0.9" }),
1761
+ React.createElement("line", { x1: "0", y1: -particle.size / 2, x2: "0", y2: particle.size / 2, stroke: "#8B4513", strokeWidth: "1", opacity: "0.5" }),
1762
+ React.createElement("line", { x1: "0", y1: -particle.size / 4, x2: -particle.size / 4, y2: -particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
1763
+ React.createElement("line", { x1: "0", y1: -particle.size / 4, x2: particle.size / 4, y2: -particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
1764
+ React.createElement("line", { x1: "0", y1: particle.size / 4, x2: -particle.size / 4, y2: particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
1765
+ React.createElement("line", { x1: "0", y1: particle.size / 4, x2: particle.size / 4, y2: particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }))));
1766
+ };
1767
+
1768
+ const defaultColors$7 = ['#4A90E2', '#5BA0F2', '#6BB0FF', '#3A80D2'];
1769
+ const createRainParticles = (origin, config) => {
1770
+ const { particleCount = 50, colors = defaultColors$7, elementSize = 300 } = config;
1771
+ const particles = [];
1772
+ for (let i = 0; i < particleCount; i++) {
1773
+ particles.push({
1774
+ id: generateId(),
1775
+ x: randomInRange(origin.x - elementSize / 2, origin.x + elementSize / 2),
1776
+ y: origin.y - randomInRange(0, elementSize),
1777
+ vx: randomInRange(-0.5, 0.5),
1778
+ vy: randomInRange(8, 12),
1779
+ life: config.lifetime || 150,
1780
+ opacity: randomInRange(0.3, 0.7),
1781
+ size: randomInRange(2, 4),
1782
+ // Encode: length (15-25) + splashing state (0 or 1) * 100 + splash frame (0-15) * 1000
1783
+ rotation: Math.floor(randomInRange(15, 25)),
1784
+ color: getRandomColor(colors),
1785
+ });
1786
+ }
1787
+ return particles;
1788
+ };
1789
+ const renderRainParticle = (particle) => {
1790
+ // Extract encoded values
1791
+ const length = particle.rotation % 100;
1792
+ const isSplashing = Math.floor((particle.rotation % 1000) / 100) === 1;
1793
+ const splashFrame = Math.floor(particle.rotation / 1000);
1794
+ // Render splash effect
1795
+ if (isSplashing && splashFrame < 15) {
1796
+ const splashRadius = splashFrame * 2;
1797
+ const splashOpacity = Math.max(0, 1 - splashFrame / 15) * 0.5;
1798
+ return (React.createElement("div", { key: particle.id, style: { position: 'relative' } },
1799
+ React.createElement("svg", { width: splashRadius * 4, height: splashRadius * 2, style: {
1800
+ position: 'absolute',
1801
+ left: -splashRadius * 2,
1802
+ top: -splashRadius,
1803
+ } },
1804
+ React.createElement("ellipse", { cx: splashRadius * 2, cy: splashRadius, rx: splashRadius, ry: splashRadius / 3, fill: "none", stroke: particle.color, strokeWidth: "1", opacity: splashOpacity }),
1805
+ [0, 1, 2, 3].map((i) => {
1806
+ const angle = (i * 90 + 45) * Math.PI / 180;
1807
+ const distance = splashFrame * 1.5;
1808
+ const dropX = splashRadius * 2 + Math.cos(angle) * distance;
1809
+ const dropY = splashRadius - Math.sin(angle) * distance + splashFrame * 0.5;
1810
+ return (React.createElement("circle", { key: i, cx: dropX, cy: dropY, r: "1.5", fill: particle.color, opacity: splashOpacity }));
1811
+ }))));
1812
+ }
1813
+ // Render falling raindrop
1814
+ return (React.createElement("div", { key: particle.id, style: { position: 'relative' } },
1815
+ React.createElement("svg", { width: particle.size * 2, height: length + particle.size * 3, style: {
1816
+ position: 'absolute',
1817
+ left: -particle.size,
1818
+ top: -length,
1819
+ } },
1820
+ React.createElement("line", { x1: particle.size, y1: 0, x2: particle.size, y2: length, stroke: particle.color, strokeWidth: particle.size, strokeLinecap: "round", opacity: particle.opacity * 0.3 }),
1821
+ React.createElement("ellipse", { cx: particle.size, cy: length + particle.size * 1.5, rx: particle.size, ry: particle.size * 1.5, fill: particle.color, opacity: particle.opacity }))));
1822
+ };
1823
+
1824
+ const defaultColors$6 = ['#FFFFFF', '#F5F5F5', '#FAFAFA'];
1825
+ const createDandelionParticles = (origin, config) => {
1826
+ const { particleCount = 15, colors = defaultColors$6, elementSize = 15 } = config;
1827
+ const particles = [];
1828
+ for (let i = 0; i < particleCount; i++) {
1829
+ particles.push({
1830
+ id: generateId(),
1831
+ x: origin.x + randomInRange(-20, 20),
1832
+ y: origin.y + randomInRange(-20, 20),
1833
+ vx: randomInRange(-2, 2),
1834
+ vy: randomInRange(-1, -0.3),
1835
+ life: config.lifetime || 200,
1836
+ opacity: 1,
1837
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1838
+ // Encode: rotation angle + float phase * 1000 + drift phase * 1000000
1839
+ rotation: Math.floor(randomInRange(0, 360)) +
1840
+ (Math.floor(randomInRange(0, 360)) * 1000) +
1841
+ (Math.floor(randomInRange(0, 360)) * 1000000),
1842
+ color: getRandomColor(colors),
1843
+ });
1844
+ }
1845
+ return particles;
1846
+ };
1847
+ const renderDandelionParticle = (particle) => {
1848
+ // Extract encoded values
1849
+ const rotationAngle = particle.rotation % 1000;
1850
+ const floatPhase = Math.floor((particle.rotation % 1000000) / 1000);
1851
+ const driftPhase = Math.floor(particle.rotation / 1000000);
1852
+ // Calculate floating effects
1853
+ const floatY = Math.sin((Date.now() * 0.002 + floatPhase) * Math.PI / 180) * 5;
1854
+ const driftX = Math.sin((Date.now() * 0.001 + driftPhase) * Math.PI / 180) * 3;
1855
+ const rotation = (Date.now() * 0.01 + rotationAngle) % 360;
1856
+ const seedCount = 7;
1857
+ return (React.createElement("div", { key: particle.id, style: {
1858
+ width: `${particle.size * 2}px`,
1859
+ height: `${particle.size * 2}px`,
1860
+ position: 'relative',
1861
+ transform: `translate(${driftX}px, ${floatY}px) rotate(${rotation}deg)`,
1862
+ opacity: particle.opacity,
1863
+ } },
1864
+ React.createElement("svg", { width: particle.size * 2, height: particle.size * 2, viewBox: `-${particle.size} -${particle.size} ${particle.size * 2} ${particle.size * 2}`, style: {
1865
+ position: 'absolute',
1866
+ top: 0,
1867
+ left: 0,
1868
+ } },
1869
+ React.createElement("circle", { cx: "0", cy: "0", r: "2", fill: "#F5F5DC" }),
1870
+ Array.from({ length: seedCount }).map((_, i) => {
1871
+ const angle = (i * 360 / seedCount) * Math.PI / 180;
1872
+ const endX = Math.cos(angle) * particle.size;
1873
+ const endY = Math.sin(angle) * particle.size;
1874
+ const midX = Math.cos(angle) * particle.size * 0.7;
1875
+ const midY = Math.sin(angle) * particle.size * 0.7;
1876
+ return (React.createElement("g", { key: i },
1877
+ React.createElement("line", { x1: "0", y1: "0", x2: endX, y2: endY, stroke: "#E5E5E5", strokeWidth: "0.5", opacity: "0.8" }),
1878
+ React.createElement("circle", { cx: endX, cy: endY, r: "3", fill: particle.color, opacity: "0.6" }),
1879
+ React.createElement("circle", { cx: midX, cy: midY, r: "2", fill: particle.color, opacity: "0.4" }),
1880
+ [0, 1, 2].map((j) => {
1881
+ const filamentAngle = angle + (j - 1) * 0.1;
1882
+ const filamentX = endX + Math.cos(filamentAngle) * 2;
1883
+ const filamentY = endY + Math.sin(filamentAngle) * 2;
1884
+ return (React.createElement("line", { key: j, x1: endX, y1: endY, x2: filamentX, y2: filamentY, stroke: "#E5E5E5", strokeWidth: "0.3", opacity: "0.6" }));
1885
+ })));
1886
+ }))));
1887
+ };
1888
+
1889
+ const defaultColors$5 = ['#FFD700', '#FFA500'];
1890
+ const createBeeParticles = (origin, config) => {
1891
+ const { particleCount = 5, colors = defaultColors$5, elementSize = 18 } = config;
1892
+ const particles = [];
1893
+ for (let i = 0; i < particleCount; i++) {
1894
+ particles.push({
1895
+ id: generateId(),
1896
+ x: origin.x + randomInRange(-50, 50),
1897
+ y: origin.y + randomInRange(-50, 50),
1898
+ vx: randomInRange(2, 4),
1899
+ vy: randomInRange(-1, 1),
1900
+ life: config.lifetime || 300,
1901
+ opacity: 1,
1902
+ size: randomInRange(elementSize * 0.8, elementSize * 1.1),
1903
+ // Encode: zigzag phase (0-360) + wing phase (0-360) * 1000 + buzz phase (0-360) * 1000000
1904
+ rotation: Math.floor(randomInRange(0, 360)) +
1905
+ (Math.floor(randomInRange(0, 360)) * 1000) +
1906
+ (Math.floor(randomInRange(0, 360)) * 1000000),
1907
+ color: getRandomColor(colors),
1908
+ });
1909
+ }
1910
+ return particles;
1911
+ };
1912
+ const renderBeeParticle = (particle) => {
1913
+ // Extract encoded values
1914
+ const zigzagPhase = particle.rotation % 1000;
1915
+ const wingPhase = Math.floor((particle.rotation % 1000000) / 1000);
1916
+ const buzzPhase = Math.floor(particle.rotation / 1000000);
1917
+ // Calculate animations
1918
+ const zigzagY = Math.sin((Date.now() * 0.005 + zigzagPhase) * Math.PI / 180) * 15;
1919
+ const wingAngle = Math.sin((Date.now() * 0.02 + wingPhase) * Math.PI / 180) * 20;
1920
+ const buzzOffset = Math.sin((Date.now() * 0.015 + buzzPhase) * Math.PI / 180) * 2;
1921
+ // Calculate rotation based on movement direction
1922
+ const movementAngle = Math.atan2(particle.vy, particle.vx) * 180 / Math.PI;
1923
+ return (React.createElement("div", { key: particle.id, style: {
1924
+ width: `${particle.size * 2}px`,
1925
+ height: `${particle.size * 2}px`,
1926
+ position: 'relative',
1927
+ transform: `translate(${buzzOffset}px, ${zigzagY}px) rotate(${movementAngle}deg)`,
1928
+ } },
1929
+ React.createElement("svg", { width: particle.size * 2, height: particle.size * 2, viewBox: "-15 -10 30 20", style: {
1930
+ position: 'absolute',
1931
+ top: 0,
1932
+ left: 0,
1933
+ } },
1934
+ React.createElement("ellipse", { cx: "-2", cy: "-3", rx: "8", ry: "4", fill: "#E5E5E5", opacity: "0.7", transform: `rotate(${-wingAngle - 20} -2 -3)` }),
1935
+ React.createElement("ellipse", { cx: "-2", cy: "3", rx: "8", ry: "4", fill: "#E5E5E5", opacity: "0.7", transform: `rotate(${wingAngle + 20} -2 3)` }),
1936
+ React.createElement("ellipse", { cx: "0", cy: "0", rx: "8", ry: "6", fill: particle.color }),
1937
+ React.createElement("ellipse", { cx: "-6", cy: "0", rx: "6", ry: "5", fill: "#333" }),
1938
+ React.createElement("rect", { x: "-3", y: "-6", width: "2", height: "12", fill: "#333" }),
1939
+ React.createElement("rect", { x: "1", y: "-6", width: "2", height: "12", fill: "#333" }),
1940
+ React.createElement("rect", { x: "5", y: "-5", width: "2", height: "10", fill: "#333" }),
1941
+ React.createElement("circle", { cx: "8", cy: "0", r: "4", fill: "#333" }),
1942
+ React.createElement("circle", { cx: "9", cy: "-1.5", r: "1", fill: "#FFF" }),
1943
+ React.createElement("circle", { cx: "9", cy: "1.5", r: "1", fill: "#FFF" }),
1944
+ React.createElement("line", { x1: "10", y1: "-2", x2: "12", y2: "-4", stroke: "#333", strokeWidth: "0.5" }),
1945
+ React.createElement("line", { x1: "10", y1: "2", x2: "12", y2: "4", stroke: "#333", strokeWidth: "0.5" }),
1946
+ React.createElement("polygon", { points: "-10,0 -12,1 -12,-1", fill: "#333" }))));
1947
+ };
1948
+
1949
+ const defaultColors$4 = ['#FFE5B4', '#FFF8DC', '#FFFACD', '#FFF5EE'];
1950
+ const createPopcornParticles = (origin, config) => {
1951
+ const { particleCount = 20, startVelocity = 25, colors = defaultColors$4, elementSize = 20 } = config;
1952
+ const particles = [];
1953
+ for (let i = 0; i < particleCount; i++) {
1954
+ const angle = randomInRange(0, 360);
1955
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1956
+ particles.push({
1957
+ id: generateId(),
1958
+ x: origin.x,
1959
+ y: origin.y,
1960
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
1961
+ vy: Math.sin(degreesToRadians(angle)) * velocity - 10, // Initial upward boost
1962
+ life: config.lifetime || 150,
1963
+ opacity: 1,
1964
+ size: randomInRange(elementSize * 0.8, elementSize * 1.2),
1965
+ rotation: randomInRange(0, 360),
1966
+ color: getRandomColor(colors),
1967
+ });
1968
+ }
1969
+ return particles;
1970
+ };
1971
+ const renderPopcornParticle = (particle) => {
1972
+ // Add some rotation animation
1973
+ const rotation = particle.rotation + (150 - particle.life) * 3;
1974
+ // Add bounce effect
1975
+ const bounceProgress = (150 - particle.life) / 150;
1976
+ const scale = 0.5 + Math.sin(bounceProgress * Math.PI) * 0.5;
1977
+ return (React.createElement("div", { key: particle.id, style: {
1978
+ fontSize: `${particle.size}px`,
1979
+ transform: `rotate(${rotation}deg) scale(${scale})`,
1980
+ opacity: particle.opacity,
1981
+ userSelect: 'none',
1982
+ } }, "\uD83C\uDF7F"));
1983
+ };
1984
+
1985
+ const defaultColors$3 = ['#F0E68C', '#FFD700', '#FFF8DC', '#FFFACD', '#F5DEB3'];
1986
+ const createChampagneParticles = (origin, config) => {
1987
+ const { particleCount = 40, startVelocity = 30, colors = defaultColors$3, elementSize = 12 } = config;
1988
+ const particles = [];
1989
+ for (let i = 0; i < particleCount; i++) {
1990
+ const isBubble = i < particleCount * 0.7;
1991
+ const angle = isBubble
1992
+ ? randomInRange(60, 120) // Mostly upward for bubbles
1993
+ : randomInRange(0, 360); // Any direction for cork
1994
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
1995
+ particles.push({
1996
+ id: generateId(),
1997
+ x: origin.x,
1998
+ y: origin.y,
1999
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
2000
+ vy: Math.sin(degreesToRadians(angle)) * velocity * (isBubble ? -1 : 1),
2001
+ life: config.lifetime || 200,
2002
+ opacity: isBubble ? 0.6 : 1,
2003
+ size: isBubble ? randomInRange(4, 8) : elementSize,
2004
+ // Encode: isBubble (0 or 1) + wobble phase * 10
2005
+ rotation: (isBubble ? 0 : 1) + Math.floor(randomInRange(0, 360)) * 10,
2006
+ color: getRandomColor(colors),
2007
+ });
2008
+ }
2009
+ return particles;
2010
+ };
2011
+ const renderChampagneParticle = (particle) => {
2012
+ const isBubble = (particle.rotation % 10) === 0;
2013
+ const wobblePhase = Math.floor(particle.rotation / 10);
2014
+ if (isBubble) {
2015
+ // Render bubble
2016
+ const wobble = Math.sin((Date.now() * 0.003 + wobblePhase) * Math.PI / 180) * 10;
2017
+ return (React.createElement("div", { key: particle.id, style: {
2018
+ width: `${particle.size}px`,
2019
+ height: `${particle.size}px`,
2020
+ borderRadius: '50%',
2021
+ backgroundColor: particle.color,
2022
+ opacity: particle.opacity,
2023
+ border: `1px solid ${particle.color}`,
2024
+ transform: `translateX(${wobble}px)`,
2025
+ boxShadow: `inset -2px -2px 4px rgba(0,0,0,0.1), inset 2px 2px 4px rgba(255,255,255,0.5)`,
2026
+ } }));
2027
+ }
2028
+ // Render cork (champagne bottle)
2029
+ const rotation = (Date.now() * 0.2 + wobblePhase) % 360;
2030
+ return (React.createElement("div", { key: particle.id, style: {
2031
+ fontSize: `${particle.size}px`,
2032
+ transform: `rotate(${rotation}deg)`,
2033
+ opacity: particle.opacity,
2034
+ userSelect: 'none',
2035
+ } }, "\uD83C\uDF7E"));
2036
+ };
2037
+
2038
+ const defaultColors$2 = ['#FF69B4', '#FF1493', '#FFB6C1', '#FFC0CB', '#FF6347', '#FFA500', '#FFD700', '#98FB98', '#87CEEB', '#DDA0DD'];
2039
+ const candyEmojis = ['🍬', '🍭', '🍮', '🍯'];
2040
+ const createCandyParticles = (origin, config) => {
2041
+ const { particleCount = 20, startVelocity = 20, colors = defaultColors$2, elementSize = 25 } = config;
2042
+ const particles = [];
2043
+ for (let i = 0; i < particleCount; i++) {
2044
+ const angle = randomInRange(-30, 30); // Mostly falling down
2045
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
2046
+ particles.push({
2047
+ id: generateId(),
2048
+ x: origin.x,
2049
+ y: origin.y - 50, // Start above origin
2050
+ vx: Math.sin(angle * Math.PI / 180) * velocity * 0.5,
2051
+ vy: randomInRange(3, 6), // Fall down
2052
+ life: config.lifetime || 180,
2053
+ opacity: 1,
2054
+ size: randomInRange(elementSize * 0.7, elementSize * 1.3),
2055
+ // Encode candy type (0-3) + initial rotation * 10
2056
+ rotation: Math.floor(Math.random() * candyEmojis.length) + (Math.floor(randomInRange(0, 360)) * 10),
2057
+ color: getRandomColor(colors),
2058
+ });
2059
+ }
2060
+ return particles;
2061
+ };
2062
+ const renderCandyParticle = (particle) => {
2063
+ const candyIndex = particle.rotation % 10;
2064
+ const initialRotation = Math.floor(particle.rotation / 10);
2065
+ const candy = candyEmojis[candyIndex] || candyEmojis[0];
2066
+ // Add tumbling rotation
2067
+ const tumbleSpeed = 5;
2068
+ const rotation = initialRotation + (180 - particle.life) * tumbleSpeed;
2069
+ // Add sway effect
2070
+ const swayAmount = Math.sin((180 - particle.life) * 0.05) * 20;
2071
+ return (React.createElement("div", { key: particle.id, style: {
2072
+ fontSize: `${particle.size}px`,
2073
+ transform: `translateX(${swayAmount}px) rotate(${rotation}deg)`,
2074
+ opacity: particle.opacity,
2075
+ userSelect: 'none',
2076
+ } }, candy));
2077
+ };
2078
+
2079
+ const defaultColors$1 = ['#FFB6C1', '#FF69B4', '#FFD700', '#FF6347', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E2'];
2080
+ const createDonutParticles = (origin, config) => {
2081
+ const { particleCount = 15, startVelocity = 25, colors = defaultColors$1, elementSize = 30 } = config;
2082
+ const particles = [];
2083
+ for (let i = 0; i < particleCount; i++) {
2084
+ const angle = randomInRange(0, 360);
2085
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
2086
+ particles.push({
2087
+ id: generateId(),
2088
+ x: origin.x,
2089
+ y: origin.y,
2090
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
2091
+ vy: Math.sin(degreesToRadians(angle)) * velocity - 10, // Initial upward boost
2092
+ life: config.lifetime || 200,
2093
+ opacity: 1,
2094
+ size: randomInRange(elementSize * 0.6, elementSize * 1.4),
2095
+ rotation: randomInRange(0, 360),
2096
+ color: getRandomColor(colors),
2097
+ });
2098
+ }
2099
+ return particles;
2100
+ };
2101
+ const renderDonutParticle = (particle) => {
2102
+ // Add spinning animation
2103
+ const spinSpeed = 8;
2104
+ const rotation = particle.rotation + (200 - particle.life) * spinSpeed;
2105
+ // Add bounce effect
2106
+ const bounceProgress = (200 - particle.life) / 200;
2107
+ const scale = 0.9 + Math.sin(bounceProgress * Math.PI * 2) * 0.1;
2108
+ return (React.createElement("div", { key: particle.id, style: {
2109
+ fontSize: `${particle.size}px`,
2110
+ transform: `rotate(${rotation}deg) scale(${scale})`,
2111
+ opacity: particle.opacity,
2112
+ userSelect: 'none',
2113
+ position: 'relative',
2114
+ } },
2115
+ "\uD83C\uDF69",
2116
+ [0, 120, 240].map((angle, i) => (React.createElement("div", { key: i, style: {
2117
+ position: 'absolute',
2118
+ width: '3px',
2119
+ height: '8px',
2120
+ backgroundColor: particle.color,
2121
+ borderRadius: '40%',
2122
+ top: '50%',
2123
+ left: '50%',
2124
+ transform: `
2125
+ translate(-50%, -50%)
2126
+ rotate(${angle + rotation}deg)
2127
+ translateY(${particle.size * 0.3}px)
2128
+ scale(${scale})
2129
+ `,
2130
+ opacity: particle.opacity * 0.8,
2131
+ } })))));
2132
+ };
2133
+
2134
+ const defaultColors = ['#FF6347', '#FFD700', '#98D8C8', '#FF8C00', '#DC143C'];
2135
+ const createPizzaParticles = (origin, config) => {
2136
+ const { particleCount = 12, startVelocity = 30, colors = defaultColors, elementSize = 35 } = config;
2137
+ const particles = [];
2138
+ for (let i = 0; i < particleCount; i++) {
2139
+ const angle = randomInRange(0, 360);
2140
+ const velocity = randomInRange(startVelocity * 0.5, startVelocity);
2141
+ particles.push({
2142
+ id: generateId(),
2143
+ x: origin.x,
2144
+ y: origin.y,
2145
+ vx: Math.cos(degreesToRadians(angle)) * velocity,
2146
+ vy: Math.sin(degreesToRadians(angle)) * velocity - 15, // Initial upward boost
2147
+ life: config.lifetime || 180,
2148
+ opacity: 1,
2149
+ size: randomInRange(elementSize * 0.5, elementSize * 1.2),
2150
+ rotation: randomInRange(0, 360),
2151
+ color: getRandomColor(colors),
2152
+ });
2153
+ }
2154
+ return particles;
2155
+ };
2156
+ const renderPizzaParticle = (particle) => {
2157
+ // Add spinning and flipping animation
2158
+ const spinSpeed = 10;
2159
+ const rotation = particle.rotation + (180 - particle.life) * spinSpeed;
2160
+ const flipAngle = (180 - particle.life) * 2;
2161
+ // Add wobble effect
2162
+ const wobble = Math.sin((180 - particle.life) * 0.1) * 10;
2163
+ // Scale animation
2164
+ const progress = (180 - particle.life) / 180;
2165
+ const scale = 0.8 + Math.sin(progress * Math.PI) * 0.2;
2166
+ return (React.createElement("div", { key: particle.id, style: {
2167
+ fontSize: `${particle.size}px`,
2168
+ transform: `
2169
+ translateX(${wobble}px)
2170
+ rotate(${rotation}deg)
2171
+ rotateX(${flipAngle}deg)
2172
+ scale(${scale})
2173
+ `,
2174
+ transformStyle: 'preserve-3d',
2175
+ opacity: particle.opacity,
2176
+ userSelect: 'none',
2177
+ position: 'relative',
2178
+ } },
2179
+ "\uD83C\uDF55",
2180
+ Math.random() > 0.5 && (React.createElement("div", { style: {
2181
+ position: 'absolute',
2182
+ fontSize: `${particle.size * 0.4}px`,
2183
+ top: `${10 + Math.random() * 30}%`,
2184
+ left: `${10 + Math.random() * 30}%`,
2185
+ transform: `rotate(${Math.random() * 360}deg)`,
2186
+ opacity: particle.opacity * 0.8,
2187
+ } }, ['🍅', '🧀', '🌶️'][Math.floor(Math.random() * 3)]))));
2188
+ };
2189
+
2190
+ const animations = {
2191
+ confetti: {
2192
+ createParticles: createConfettiParticles,
2193
+ renderParticle: renderConfettiParticle,
2194
+ },
2195
+ sparkles: {
2196
+ createParticles: createSparkleParticles,
2197
+ renderParticle: renderSparkleParticle,
2198
+ },
2199
+ hearts: {
2200
+ createParticles: createHeartParticles,
2201
+ renderParticle: renderHeartParticle,
2202
+ },
2203
+ fireworks: {
2204
+ createParticles: createFireworkParticles,
2205
+ renderParticle: renderFireworkParticle,
2206
+ },
2207
+ bubbles: {
2208
+ createParticles: createBubbleParticles,
2209
+ renderParticle: renderBubbleParticle,
2210
+ },
2211
+ stars: {
2212
+ createParticles: createStarParticles,
2213
+ renderParticle: renderStarParticle,
2214
+ },
2215
+ snow: {
2216
+ createParticles: createSnowParticles,
2217
+ renderParticle: renderSnowParticle,
2218
+ },
2219
+ emoji: {
2220
+ createParticles: createEmojiParticles,
2221
+ renderParticle: renderEmojiParticle,
2222
+ },
2223
+ coins: {
2224
+ createParticles: createCoinParticles,
2225
+ renderParticle: renderCoinParticle,
2226
+ },
2227
+ lightning: {
2228
+ createParticles: createLightningParticles,
2229
+ renderParticle: renderLightningParticle,
2230
+ },
2231
+ petals: {
2232
+ createParticles: createPetalParticles,
2233
+ renderParticle: renderPetalParticle,
2234
+ },
2235
+ aurora: {
2236
+ createParticles: createAuroraParticles,
2237
+ renderParticle: renderAuroraParticle,
2238
+ },
2239
+ fireflies: {
2240
+ createParticles: createFireflyParticles,
2241
+ renderParticle: renderFireflyParticle,
2242
+ },
2243
+ paint: {
2244
+ createParticles: createPaintParticles,
2245
+ renderParticle: renderPaintParticle,
2246
+ },
2247
+ music: {
2248
+ createParticles: createMusicParticles,
2249
+ renderParticle: renderMusicParticle,
2250
+ },
2251
+ balloons: {
2252
+ createParticles: createBalloonParticles,
2253
+ renderParticle: renderBalloonParticle,
2254
+ },
2255
+ galaxy: {
2256
+ createParticles: createGalaxyParticles,
2257
+ renderParticle: renderGalaxyParticle,
2258
+ },
2259
+ matrix: {
2260
+ createParticles: createMatrixParticles,
2261
+ renderParticle: renderMatrixParticle,
2262
+ },
2263
+ pixels: {
2264
+ createParticles: createPixelParticles,
2265
+ renderParticle: renderPixelParticle,
2266
+ },
2267
+ glitch: {
2268
+ createParticles: createGlitchParticles,
2269
+ renderParticle: renderGlitchParticle,
2270
+ },
2271
+ dice: {
2272
+ createParticles: createDiceParticles,
2273
+ renderParticle: renderDiceParticle,
2274
+ },
2275
+ levelup: {
2276
+ createParticles: createLevelUpParticles,
2277
+ renderParticle: renderLevelUpParticle,
2278
+ },
2279
+ magicdust: {
2280
+ createParticles: createMagicDustParticles,
2281
+ renderParticle: renderMagicDustParticle,
2282
+ },
2283
+ ghosts: {
2284
+ createParticles: createGhostParticles,
2285
+ renderParticle: renderGhostParticle,
2286
+ },
2287
+ crystals: {
2288
+ createParticles: createCrystalParticles,
2289
+ renderParticle: renderCrystalParticle,
2290
+ },
2291
+ dragons: {
2292
+ createParticles: createDragonParticles,
2293
+ renderParticle: renderDragonParticle,
2294
+ },
2295
+ runes: {
2296
+ createParticles: createRuneParticles,
2297
+ renderParticle: renderRuneParticle,
2298
+ },
2299
+ butterflies: {
2300
+ createParticles: createButterflyParticles,
2301
+ renderParticle: renderButterflyParticle,
2302
+ },
2303
+ leaves: {
2304
+ createParticles: createLeafParticles,
2305
+ renderParticle: renderLeafParticle,
2306
+ },
2307
+ rain: {
2308
+ createParticles: createRainParticles,
2309
+ renderParticle: renderRainParticle,
2310
+ },
2311
+ dandelion: {
2312
+ createParticles: createDandelionParticles,
2313
+ renderParticle: renderDandelionParticle,
2314
+ },
2315
+ bees: {
2316
+ createParticles: createBeeParticles,
2317
+ renderParticle: renderBeeParticle,
2318
+ },
2319
+ popcorn: {
2320
+ createParticles: createPopcornParticles,
2321
+ renderParticle: renderPopcornParticle,
2322
+ },
2323
+ champagne: {
2324
+ createParticles: createChampagneParticles,
2325
+ renderParticle: renderChampagneParticle,
2326
+ },
2327
+ candy: {
2328
+ createParticles: createCandyParticles,
2329
+ renderParticle: renderCandyParticle,
2330
+ },
2331
+ donuts: {
2332
+ createParticles: createDonutParticles,
2333
+ renderParticle: renderDonutParticle,
2334
+ },
2335
+ pizza: {
2336
+ createParticles: createPizzaParticles,
2337
+ renderParticle: renderPizzaParticle,
1007
2338
  },
1008
2339
  };
1009
2340