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