@ansh-ui/core 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/behaviours.cjs +20 -15
  2. package/dist/behaviours.d.cts +2 -2
  3. package/dist/behaviours.d.ts +2 -2
  4. package/dist/behaviours.js +3 -2
  5. package/dist/{chunk-56NNBIAO.js → chunk-2DOA43UB.js} +1047 -18
  6. package/dist/chunk-2DOA43UB.js.map +1 -0
  7. package/dist/{chunk-7MYTSAPR.js → chunk-37GPMMMT.js} +3 -3
  8. package/dist/{chunk-7MYTSAPR.js.map → chunk-37GPMMMT.js.map} +1 -1
  9. package/dist/{chunk-23GSSIMK.cjs → chunk-4ORYTFY3.cjs} +3 -3
  10. package/dist/{chunk-23GSSIMK.cjs.map → chunk-4ORYTFY3.cjs.map} +1 -1
  11. package/dist/{chunk-MMO7KO53.cjs → chunk-FNR4B3KY.cjs} +3 -3
  12. package/dist/{chunk-MMO7KO53.cjs.map → chunk-FNR4B3KY.cjs.map} +1 -1
  13. package/dist/{chunk-BOQQHICI.js → chunk-GQH5ZHPB.js} +3 -3
  14. package/dist/{chunk-BOQQHICI.js.map → chunk-GQH5ZHPB.js.map} +1 -1
  15. package/dist/{chunk-R7UJ7MWP.cjs → chunk-OSNUN5JJ.cjs} +1070 -34
  16. package/dist/chunk-OSNUN5JJ.cjs.map +1 -0
  17. package/dist/{chunk-GHBRGMSO.cjs → chunk-PZF3YXVE.cjs} +6 -6
  18. package/dist/{chunk-GHBRGMSO.cjs.map → chunk-PZF3YXVE.cjs.map} +1 -1
  19. package/dist/{chunk-UJBXY6QC.cjs → chunk-SSAWZIO2.cjs} +150 -28
  20. package/dist/chunk-SSAWZIO2.cjs.map +1 -0
  21. package/dist/{chunk-C6XPQO2O.js → chunk-WLOGUD3G.js} +126 -5
  22. package/dist/{chunk-C6XPQO2O.js.map → chunk-WLOGUD3G.js.map} +1 -1
  23. package/dist/{chunk-KTUBCQC3.js → chunk-YHSCAGCI.js} +3 -3
  24. package/dist/{chunk-KTUBCQC3.js.map → chunk-YHSCAGCI.js.map} +1 -1
  25. package/dist/color.cjs +39 -39
  26. package/dist/color.d.cts +5 -4
  27. package/dist/color.d.ts +5 -4
  28. package/dist/color.js +3 -3
  29. package/dist/effects.cjs +53 -25
  30. package/dist/effects.d.cts +4 -4
  31. package/dist/effects.d.ts +4 -4
  32. package/dist/effects.js +4 -4
  33. package/dist/{index-CQEEPu-D.d.ts → index-DN0bQII7.d.ts} +47 -2
  34. package/dist/{index-DHOfsEIn.d.cts → index-DmJ3i1Tr.d.cts} +330 -4
  35. package/dist/{index-Dl8GCsya.d.cts → index-Dv3gw7Mb.d.cts} +47 -2
  36. package/dist/{index-CCdpefMp.d.ts → index-SO8zHlVo.d.ts} +330 -4
  37. package/dist/index.cjs +186 -154
  38. package/dist/index.d.cts +10 -9
  39. package/dist/index.d.ts +10 -9
  40. package/dist/index.js +9 -9
  41. package/dist/math.d.cts +3 -2
  42. package/dist/math.d.ts +3 -2
  43. package/dist/noise.d.cts +2 -1
  44. package/dist/noise.d.ts +2 -1
  45. package/dist/{palette-6HkVltYU.d.ts → palette-Dcomsp9R.d.cts} +2 -1
  46. package/dist/{palette-6HkVltYU.d.cts → palette-Dcomsp9R.d.ts} +2 -1
  47. package/dist/{random--4mSc5Lp.d.cts → random-YnhdaiIx.d.cts} +2 -1
  48. package/dist/{random--4mSc5Lp.d.ts → random-YnhdaiIx.d.ts} +2 -1
  49. package/dist/{reduced-motion-D0LUgZle.d.cts → reduced-motion-DaeXwgzb.d.cts} +2 -1
  50. package/dist/{reduced-motion-D0LUgZle.d.ts → reduced-motion-DaeXwgzb.d.ts} +2 -1
  51. package/package.json +1 -1
  52. package/dist/chunk-56NNBIAO.js.map +0 -1
  53. package/dist/chunk-R7UJ7MWP.cjs.map +0 -1
  54. package/dist/chunk-UJBXY6QC.cjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunk23GSSIMK_cjs = require('./chunk-23GSSIMK.cjs');
3
+ var chunk4ORYTFY3_cjs = require('./chunk-4ORYTFY3.cjs');
4
4
  var chunkDXJ63QAR_cjs = require('./chunk-DXJ63QAR.cjs');
5
- var chunkFNR35HTL_cjs = require('./chunk-FNR35HTL.cjs');
6
- var chunkMMO7KO53_cjs = require('./chunk-MMO7KO53.cjs');
5
+ var chunkFNR4B3KY_cjs = require('./chunk-FNR4B3KY.cjs');
7
6
  var chunkLGA3N3YJ_cjs = require('./chunk-LGA3N3YJ.cjs');
7
+ var chunkFNR35HTL_cjs = require('./chunk-FNR35HTL.cjs');
8
8
  var chunkILKUL7GD_cjs = require('./chunk-ILKUL7GD.cjs');
9
9
 
10
10
  // src/render/surface.ts
@@ -73,7 +73,7 @@ function createSurface(canvas, options = {}) {
73
73
  }
74
74
  });
75
75
  };
76
- const stopResizeObserver = canvas.parentElement ? chunkMMO7KO53_cjs.observeResize(canvas.parentElement, scheduleResize) : () => {
76
+ const stopResizeObserver = canvas.parentElement ? chunkFNR4B3KY_cjs.observeResize(canvas.parentElement, scheduleResize) : () => {
77
77
  };
78
78
  const onContextLost = (event) => {
79
79
  event.preventDefault();
@@ -184,7 +184,7 @@ function buildRadial(ctx, radius, stops) {
184
184
  }
185
185
  function drawDot(ctx, x, y, radius, color) {
186
186
  if (radius <= 0) return;
187
- ctx.fillStyle = chunk23GSSIMK_cjs.toRgbString(color);
187
+ ctx.fillStyle = chunk4ORYTFY3_cjs.toRgbString(color);
188
188
  ctx.beginPath();
189
189
  ctx.arc(x, y, radius, 0, chunkILKUL7GD_cjs.TAU);
190
190
  ctx.fill();
@@ -289,7 +289,7 @@ var CANVAS_STYLE = {
289
289
  pointerEvents: "none"
290
290
  };
291
291
  function mountEffect(definition, host, userOptions = {}) {
292
- chunkMMO7KO53_cjs.getRegistry().requireCapability(definition.capability ?? "effect:core");
292
+ chunkFNR4B3KY_cjs.getRegistry().requireCapability(definition.capability ?? "effect:core");
293
293
  let options = { ...definition.defaults, ...stripUndefined(userOptions) };
294
294
  const canvas = document.createElement("canvas");
295
295
  canvas.setAttribute("aria-hidden", "true");
@@ -306,9 +306,9 @@ function mountEffect(definition, host, userOptions = {}) {
306
306
  let destroyed = false;
307
307
  let userPaused = options.paused ?? false;
308
308
  let offscreen = false;
309
- let motion = chunkMMO7KO53_cjs.resolveMotion(options.reducedMotion, 0.25);
309
+ let motion = chunkFNR4B3KY_cjs.resolveMotion(options.reducedMotion, 0.25);
310
310
  let pendingSingleFrame = false;
311
- const ticker = chunkMMO7KO53_cjs.getTicker();
311
+ const ticker = chunkFNR4B3KY_cjs.getTicker();
312
312
  const surface = createSurface(canvas, {
313
313
  resolution: options.resolution ?? 1,
314
314
  alpha: true,
@@ -348,7 +348,7 @@ function mountEffect(definition, host, userOptions = {}) {
348
348
  function ensurePointer() {
349
349
  const wants = options.interactive !== false;
350
350
  if (wants && !pointer) {
351
- pointer = chunkMMO7KO53_cjs.trackPointer(host);
351
+ pointer = chunkFNR4B3KY_cjs.trackPointer(host);
352
352
  } else if (!wants && pointer) {
353
353
  pointer.destroy();
354
354
  pointer = null;
@@ -392,7 +392,7 @@ function mountEffect(definition, host, userOptions = {}) {
392
392
  if (options.performance === "high") ticker.lockQuality(1);
393
393
  else if (options.performance === "low") ticker.lockQuality(0.4);
394
394
  if (options.pauseOffscreen !== false) {
395
- intersectionSubscription = chunkMMO7KO53_cjs.observeIntersection(
395
+ intersectionSubscription = chunkFNR4B3KY_cjs.observeIntersection(
396
396
  host,
397
397
  (entry) => {
398
398
  offscreen = !entry.isIntersecting;
@@ -404,8 +404,8 @@ function mountEffect(definition, host, userOptions = {}) {
404
404
  { rootMargin: "200px" }
405
405
  );
406
406
  }
407
- reducedMotionSubscription = chunkMMO7KO53_cjs.onReducedMotionChange(() => {
408
- motion = chunkMMO7KO53_cjs.resolveMotion(options.reducedMotion, 0.25);
407
+ reducedMotionSubscription = chunkFNR4B3KY_cjs.onReducedMotionChange(() => {
408
+ motion = chunkFNR4B3KY_cjs.resolveMotion(options.reducedMotion, 0.25);
409
409
  if (motion.animate && !userPaused && !offscreen) {
410
410
  startTicker();
411
411
  } else {
@@ -448,7 +448,7 @@ function mountEffect(definition, host, userOptions = {}) {
448
448
  if (options.resolution !== void 0) surface.setResolution(options.resolution);
449
449
  const wasPaused = userPaused;
450
450
  userPaused = options.paused ?? false;
451
- motion = chunkMMO7KO53_cjs.resolveMotion(options.reducedMotion, 0.25);
451
+ motion = chunkFNR4B3KY_cjs.resolveMotion(options.reducedMotion, 0.25);
452
452
  if (wasPaused && !userPaused && motion.animate && !offscreen) startTicker();
453
453
  if (!wasPaused && userPaused) stopTicker();
454
454
  if (!motion.animate && motion.renderOnce) renderSingleFrame();
@@ -491,7 +491,7 @@ function resolveResolvedColors(colors, host) {
491
491
  return chunkLGA3N3YJ_cjs.parseColor(color);
492
492
  });
493
493
  }
494
- return chunk23GSSIMK_cjs.resolvePalette(colors);
494
+ return chunk4ORYTFY3_cjs.resolvePalette(colors);
495
495
  }
496
496
  function resolveAgainst(value, host) {
497
497
  const probe = document.createElement("span");
@@ -514,7 +514,7 @@ function stripUndefined(input) {
514
514
  return out;
515
515
  }
516
516
  function defineEffect(definition) {
517
- const registry = chunkMMO7KO53_cjs.getRegistry();
517
+ const registry = chunkFNR4B3KY_cjs.getRegistry();
518
518
  if (!registry.has("effect", definition.name)) {
519
519
  registry.register("effect", definition.name, definition);
520
520
  }
@@ -770,7 +770,7 @@ var aurora = defineEffect({
770
770
  const flow = context.noise.fbm2D({ octaves: 2, gain: 0.5 });
771
771
  function build() {
772
772
  const count = Math.max(1, Math.floor(opts.curtains));
773
- const palette = chunk23GSSIMK_cjs.expandPalette(context.colors, count);
773
+ const palette = chunk4ORYTFY3_cjs.expandPalette(context.colors, count);
774
774
  const rng = context.rng;
775
775
  curtains = [];
776
776
  for (let i = 0; i < count; i++) {
@@ -884,7 +884,7 @@ var meshGradient = defineEffect({
884
884
  let grainTile = null;
885
885
  function build() {
886
886
  const count = Math.max(1, Math.floor(opts.points));
887
- const palette = chunk23GSSIMK_cjs.expandPalette(context.colors, count);
887
+ const palette = chunk4ORYTFY3_cjs.expandPalette(context.colors, count);
888
888
  const rng = context.rng;
889
889
  backdropColor = palette.reduce(
890
890
  (darkest, c) => c.r + c.g + c.b < darkest.r + darkest.g + darkest.b ? c : darkest
@@ -1051,7 +1051,7 @@ var animatedGradient = defineEffect({
1051
1051
  function build() {
1052
1052
  const count = Math.max(2, Math.floor(opts.stops));
1053
1053
  const doubled = [...context.colors, ...context.colors, context.colors[0]];
1054
- samples = chunk23GSSIMK_cjs.expandPalette(doubled, count * 2);
1054
+ samples = chunk4ORYTFY3_cjs.expandPalette(doubled, count * 2);
1055
1055
  }
1056
1056
  build();
1057
1057
  return {
@@ -1420,8 +1420,447 @@ var constellation = defineEffect({
1420
1420
  }
1421
1421
  });
1422
1422
 
1423
- // src/effects/atmosphere/meteors.ts
1423
+ // src/effects/particles/powder-explosion.ts
1424
1424
  var DEFAULTS5 = {
1425
+ colors: ["#ff9d5c", "#ffd76f", "#ff6b8b", "#7cc4ff"],
1426
+ speed: 1,
1427
+ intensity: 1,
1428
+ opacity: 1,
1429
+ blur: 0,
1430
+ blend: "lighter",
1431
+ seed: 59,
1432
+ interactive: true,
1433
+ resolution: 1,
1434
+ performance: "auto",
1435
+ reducedMotion: "pause",
1436
+ paused: false,
1437
+ pauseOffscreen: true,
1438
+ burstSize: 90,
1439
+ burstRate: 0.8,
1440
+ force: 420,
1441
+ drag: 0.92,
1442
+ gravity: 90,
1443
+ life: 1.9,
1444
+ size: 3,
1445
+ glow: 3.2,
1446
+ burstOnPress: true
1447
+ };
1448
+ var MAX_PARTICLES2 = 1600;
1449
+ var FADE_SHAPE = 1.4;
1450
+ var powderExplosion = defineEffect({
1451
+ name: "powder-explosion",
1452
+ defaults: DEFAULTS5,
1453
+ structuralOptions: ["burstSize"],
1454
+ setup(context, options) {
1455
+ let opts = options;
1456
+ const perBurst = Math.max(1, Math.floor(opts.burstSize));
1457
+ const concurrent = Math.max(2, Math.ceil(opts.life * opts.burstRate) + 2);
1458
+ const capacity = Math.min(MAX_PARTICLES2, perBurst * concurrent);
1459
+ const buffer = new ParticleBuffer(capacity);
1460
+ const gradients = new GradientCache(64);
1461
+ let untilNextBurst = 0;
1462
+ let wasDown = false;
1463
+ function burst(x, y) {
1464
+ const rng = context.rng;
1465
+ const colorCount = Math.max(1, context.colors.length);
1466
+ const family = rng.int(0, colorCount - 1);
1467
+ for (let i = 0; i < perBurst; i++) {
1468
+ const index = buffer.spawn();
1469
+ if (index < 0) return;
1470
+ const angle = rng.angle();
1471
+ const t = rng.next();
1472
+ const speed = opts.force * t * t * rng.range(0.85, 1.15);
1473
+ buffer.x[index] = x;
1474
+ buffer.y[index] = y;
1475
+ buffer.vx[index] = Math.cos(angle) * speed;
1476
+ buffer.vy[index] = Math.sin(angle) * speed;
1477
+ buffer.size[index] = opts.size * rng.range(0.55, 1.5);
1478
+ buffer.colorIndex[index] = rng.bool(0.75) ? family : rng.int(0, colorCount - 1);
1479
+ buffer.maxLife[index] = opts.life * rng.range(0.6, 1.3);
1480
+ buffer.life[index] = buffer.maxLife[index];
1481
+ buffer.seed[index] = rng.range(0, chunkILKUL7GD_cjs.TAU);
1482
+ buffer.extra[index] = rng.range(0.85, 1.2);
1483
+ }
1484
+ }
1485
+ return {
1486
+ frame({ delta, quality }) {
1487
+ const { ctx, size, surface, pointer, colors } = context;
1488
+ const { width, height } = size;
1489
+ if (width < 1 || height < 1) return;
1490
+ surface.clear();
1491
+ if (colors.length === 0) return;
1492
+ const rng = context.rng;
1493
+ const rate = opts.burstRate * (opts.performance === "high" ? 1 : quality);
1494
+ untilNextBurst -= delta * rate;
1495
+ if (untilNextBurst <= 0) {
1496
+ burst(rng.range(width * 0.15, width * 0.85), rng.range(height * 0.2, height * 0.8));
1497
+ untilNextBurst = -Math.log(1 - rng.next());
1498
+ }
1499
+ const interactive = opts.interactive !== false && pointer !== null;
1500
+ if (interactive && opts.burstOnPress) {
1501
+ if (pointer.down && !wasDown) burst(pointer.x, pointer.y);
1502
+ wasDown = pointer.down;
1503
+ }
1504
+ const retain = Math.pow(1 - chunkILKUL7GD_cjs.clamp(opts.drag, 0, 0.999), delta);
1505
+ const gravity = opts.gravity * delta;
1506
+ const alphaScale = chunkILKUL7GD_cjs.clamp(opts.opacity * opts.intensity, 0, 1);
1507
+ const colorCount = Math.max(1, colors.length);
1508
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
1509
+ let i = 0;
1510
+ while (i < buffer.count) {
1511
+ buffer.life[i] -= delta;
1512
+ if (buffer.life[i] <= 0) {
1513
+ buffer.kill(i);
1514
+ continue;
1515
+ }
1516
+ buffer.vx[i] *= retain;
1517
+ buffer.vy[i] = buffer.vy[i] * retain + gravity;
1518
+ buffer.x[i] += buffer.vx[i] * delta;
1519
+ buffer.y[i] += buffer.vy[i] * delta;
1520
+ const age = chunkILKUL7GD_cjs.clamp(1 - buffer.life[i] / buffer.maxLife[i], 0, 1);
1521
+ const alpha = alphaScale * Math.pow(1 - age, FADE_SHAPE);
1522
+ if (alpha > 2e-3) {
1523
+ drawGlow(
1524
+ ctx,
1525
+ buffer.x[i],
1526
+ buffer.y[i],
1527
+ buffer.size[i] * opts.glow * buffer.extra[i],
1528
+ colors[buffer.colorIndex[i] % colorCount],
1529
+ alpha,
1530
+ gradients
1531
+ );
1532
+ }
1533
+ i++;
1534
+ }
1535
+ ctx.globalCompositeOperation = "source-over";
1536
+ },
1537
+ update(next) {
1538
+ opts = {
1539
+ ...opts,
1540
+ ...next
1541
+ };
1542
+ gradients.clear();
1543
+ },
1544
+ destroy() {
1545
+ buffer.clear();
1546
+ gradients.clear();
1547
+ }
1548
+ };
1549
+ }
1550
+ });
1551
+
1552
+ // src/effects/particles/strange-attractor.ts
1553
+ var DEFAULTS6 = {
1554
+ colors: ["#7cc4ff", "#a78bfa", "#5eead4", "#fbbf7c"],
1555
+ speed: 1,
1556
+ intensity: 1,
1557
+ opacity: 1,
1558
+ blur: 0,
1559
+ blend: "lighter",
1560
+ seed: 83,
1561
+ interactive: false,
1562
+ resolution: 1,
1563
+ performance: "auto",
1564
+ reducedMotion: "slow",
1565
+ paused: false,
1566
+ pauseOffscreen: true,
1567
+ kind: "clifford",
1568
+ count: 2600,
1569
+ drift: 0.12,
1570
+ driftSpeed: 0.05,
1571
+ size: 0.9,
1572
+ pointOpacity: 0.34,
1573
+ fade: 0.12,
1574
+ scale: 0.42
1575
+ };
1576
+ var MAX_WALKERS = 8e3;
1577
+ var PARAM_SETS = {
1578
+ clifford: [
1579
+ [-1.4, 1.6, 1, 0.7],
1580
+ [1.7, 1.7, 0.06, 1.2],
1581
+ [-1.7, 1.3, -0.1, -1.21],
1582
+ [1.5, -1.8, 1.6, 0.9],
1583
+ [-1.8, -2, -0.5, -0.9]
1584
+ ],
1585
+ dejong: [
1586
+ [1.4, -2.3, 2.4, -2.1],
1587
+ [2.01, -2.53, 1.61, -0.33],
1588
+ [-2.7, -0.09, -0.86, -2.2],
1589
+ [1.641, 1.902, 0.316, 1.525]
1590
+ ],
1591
+ svensson: [
1592
+ [1.4, 1.56, 1.4, -6.56],
1593
+ [-1.78, -1.28, -0.75, 1.34],
1594
+ [1.94, 1.1, -1.63, 0.42]
1595
+ ]
1596
+ };
1597
+ var strangeAttractor = defineEffect({
1598
+ name: "strange-attractor",
1599
+ defaults: DEFAULTS6,
1600
+ structuralOptions: ["count", "kind"],
1601
+ setup(context, options) {
1602
+ let opts = options;
1603
+ const count = Math.min(MAX_WALKERS, Math.max(1, Math.floor(opts.count)));
1604
+ const px = new Float32Array(count);
1605
+ const py = new Float32Array(count);
1606
+ const colorIndex = new Uint8Array(count);
1607
+ const rng = context.rng;
1608
+ const sets = PARAM_SETS[opts.kind] ?? PARAM_SETS.clifford;
1609
+ const [baseA, baseB, baseC, baseD] = sets[rng.int(0, sets.length - 1)];
1610
+ const phaseA = rng.angle();
1611
+ const phaseB = rng.angle();
1612
+ const phaseC = rng.angle();
1613
+ const phaseD = rng.angle();
1614
+ let seeded = false;
1615
+ function seed() {
1616
+ const colorCount = Math.max(1, context.colors.length);
1617
+ for (let i = 0; i < count; i++) {
1618
+ px[i] = rng.range(-1, 1);
1619
+ py[i] = rng.range(-1, 1);
1620
+ colorIndex[i] = rng.int(0, colorCount - 1);
1621
+ }
1622
+ seeded = true;
1623
+ }
1624
+ return {
1625
+ frame({ time, quality }) {
1626
+ const { ctx, size, surface, colors } = context;
1627
+ const { width, height } = size;
1628
+ if (width < 1 || height < 1) return;
1629
+ if (colors.length === 0) return;
1630
+ if (!seeded) seed();
1631
+ const fade = chunkILKUL7GD_cjs.clamp(opts.fade, 0, 1);
1632
+ if (fade >= 1) {
1633
+ surface.clear();
1634
+ } else if (fade > 0) {
1635
+ ctx.globalCompositeOperation = "destination-out";
1636
+ ctx.fillStyle = `rgba(0,0,0,${fade})`;
1637
+ ctx.fillRect(0, 0, width, height);
1638
+ }
1639
+ const wobble = opts.drift;
1640
+ const rate = opts.driftSpeed * time;
1641
+ const a = baseA + Math.sin(rate + phaseA) * wobble;
1642
+ const b = baseB + Math.sin(rate * 1.31 + phaseB) * wobble;
1643
+ const c = baseC + Math.sin(rate * 0.77 + phaseC) * wobble;
1644
+ const d = baseD + Math.sin(rate * 1.13 + phaseD) * wobble;
1645
+ const kind = opts.kind;
1646
+ const extent = kind === "dejong" ? 2 : 1 + Math.max(Math.abs(c), Math.abs(d));
1647
+ const span = Math.min(width, height) * opts.scale;
1648
+ const cx = width / 2;
1649
+ const cy = height / 2;
1650
+ const radius = Math.max(0.35, opts.size);
1651
+ const diameter = radius * 2;
1652
+ const walkers = opts.performance === "high" ? count : Math.max(64, Math.round(count * quality));
1653
+ const alpha = chunkILKUL7GD_cjs.clamp(opts.pointOpacity * opts.opacity * opts.intensity, 0, 1);
1654
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
1655
+ ctx.globalAlpha = alpha;
1656
+ const colorCount = colors.length;
1657
+ let currentColor = -1;
1658
+ for (let i = 0; i < walkers; i++) {
1659
+ const x = px[i];
1660
+ const y = py[i];
1661
+ let nx;
1662
+ let ny;
1663
+ if (kind === "dejong") {
1664
+ nx = Math.sin(a * y) - Math.cos(b * x);
1665
+ ny = Math.sin(c * x) - Math.cos(d * y);
1666
+ } else if (kind === "svensson") {
1667
+ nx = d * Math.sin(a * x) - Math.sin(b * y);
1668
+ ny = c * Math.cos(a * x) + Math.cos(b * y);
1669
+ } else {
1670
+ nx = Math.sin(a * y) + c * Math.cos(a * x);
1671
+ ny = Math.sin(b * x) + d * Math.cos(b * y);
1672
+ }
1673
+ px[i] = nx;
1674
+ py[i] = ny;
1675
+ const ci = colorIndex[i] % colorCount;
1676
+ if (ci !== currentColor) {
1677
+ const colour = colors[ci];
1678
+ ctx.fillStyle = `rgb(${Math.round(colour.r * 255)},${Math.round(colour.g * 255)},${Math.round(colour.b * 255)})`;
1679
+ currentColor = ci;
1680
+ }
1681
+ ctx.fillRect(
1682
+ cx + nx / extent * span - radius,
1683
+ cy + ny / extent * span - radius,
1684
+ diameter,
1685
+ diameter
1686
+ );
1687
+ }
1688
+ ctx.globalAlpha = 1;
1689
+ ctx.globalCompositeOperation = "source-over";
1690
+ },
1691
+ resize() {
1692
+ seeded = false;
1693
+ },
1694
+ update(next) {
1695
+ opts = {
1696
+ ...opts,
1697
+ ...next
1698
+ };
1699
+ }
1700
+ };
1701
+ }
1702
+ });
1703
+
1704
+ // src/effects/particles/swarm.ts
1705
+ var DEFAULTS7 = {
1706
+ colors: ["#3b82f6", "#a78bfa", "#f472b6", "#fbbf24"],
1707
+ speed: 1,
1708
+ intensity: 1,
1709
+ opacity: 1,
1710
+ blur: 0,
1711
+ blend: "lighter",
1712
+ seed: 89,
1713
+ interactive: true,
1714
+ resolution: 1,
1715
+ performance: "auto",
1716
+ reducedMotion: "slow",
1717
+ paused: false,
1718
+ pauseOffscreen: true,
1719
+ count: 900,
1720
+ attractors: 3,
1721
+ gravity: 260,
1722
+ swirl: 0.85,
1723
+ softening: 70,
1724
+ drag: 0.45,
1725
+ attractorSpeed: 0.08,
1726
+ size: 1.4,
1727
+ fastSpeed: 320,
1728
+ pointerGravity: 1.6
1729
+ };
1730
+ var MAX_PARTICLES3 = 4e3;
1731
+ var MAX_ATTRACTORS = 8;
1732
+ var MAX_DELTA_V = 900;
1733
+ var swarm = defineEffect({
1734
+ name: "swarm",
1735
+ defaults: DEFAULTS7,
1736
+ structuralOptions: ["count", "attractors"],
1737
+ setup(context, options) {
1738
+ let opts = options;
1739
+ const capacity = Math.min(MAX_PARTICLES3, Math.max(1, Math.floor(opts.count)));
1740
+ const attractorCount = Math.min(MAX_ATTRACTORS, Math.max(1, Math.floor(opts.attractors)));
1741
+ const buffer = new ParticleBuffer(capacity);
1742
+ const ax = new Float32Array(attractorCount);
1743
+ const ay = new Float32Array(attractorCount);
1744
+ const fx = new Float32Array(attractorCount);
1745
+ const fy = new Float32Array(attractorCount);
1746
+ const phx = new Float32Array(attractorCount);
1747
+ const phy = new Float32Array(attractorCount);
1748
+ const rng = context.rng;
1749
+ for (let a = 0; a < attractorCount; a++) {
1750
+ ax[a] = rng.range(0.18, 0.34);
1751
+ ay[a] = rng.range(0.18, 0.34);
1752
+ fx[a] = rng.range(0.6, 1.4);
1753
+ fy[a] = rng.range(0.6, 1.4);
1754
+ phx[a] = rng.angle();
1755
+ phy[a] = rng.angle();
1756
+ }
1757
+ let seeded = false;
1758
+ function seed() {
1759
+ const { width, height } = context.size;
1760
+ buffer.clear();
1761
+ for (let i = 0; i < capacity; i++) {
1762
+ const index = buffer.spawn();
1763
+ if (index < 0) break;
1764
+ buffer.x[index] = rng.next() * width;
1765
+ buffer.y[index] = rng.next() * height;
1766
+ const angle = rng.angle();
1767
+ const speed = rng.range(20, 90);
1768
+ buffer.vx[index] = Math.cos(angle) * speed;
1769
+ buffer.vy[index] = Math.sin(angle) * speed;
1770
+ buffer.size[index] = opts.size * rng.range(0.7, 1.5);
1771
+ buffer.life[index] = Infinity;
1772
+ buffer.maxLife[index] = Infinity;
1773
+ }
1774
+ seeded = true;
1775
+ }
1776
+ return {
1777
+ frame({ time, delta, quality }) {
1778
+ const { ctx, size, surface, pointer, colors } = context;
1779
+ const { width, height } = size;
1780
+ if (width < 1 || height < 1) return;
1781
+ if (!seeded || buffer.count === 0) seed();
1782
+ surface.clear();
1783
+ if (colors.length === 0) return;
1784
+ const target = opts.performance === "high" ? capacity : Math.max(32, Math.floor(capacity * quality));
1785
+ if (buffer.count > target) buffer.truncate(target);
1786
+ const cx = width / 2;
1787
+ const cy = height / 2;
1788
+ const t = time * opts.attractorSpeed * chunkILKUL7GD_cjs.TAU;
1789
+ const atx = [];
1790
+ const aty = [];
1791
+ for (let a = 0; a < attractorCount; a++) {
1792
+ atx.push(cx + Math.sin(t * fx[a] + phx[a]) * width * ax[a]);
1793
+ aty.push(cy + Math.cos(t * fy[a] + phy[a]) * height * ay[a]);
1794
+ }
1795
+ const interactive = opts.interactive !== false && pointer !== null && pointer.everInside;
1796
+ if (interactive && opts.pointerGravity !== 0) {
1797
+ atx.push(pointer.smoothX);
1798
+ aty.push(pointer.smoothY);
1799
+ }
1800
+ const gravity = opts.gravity * opts.intensity;
1801
+ const pointerBoost = opts.pointerGravity;
1802
+ const swirl = opts.swirl;
1803
+ const softening = Math.max(1, opts.softening);
1804
+ const retain = Math.pow(1 - chunkILKUL7GD_cjs.clamp(opts.drag, 0, 0.999), delta);
1805
+ const invFast = 1 / Math.max(1, opts.fastSpeed);
1806
+ const alpha = chunkILKUL7GD_cjs.clamp(opts.opacity * opts.intensity, 0, 1);
1807
+ const colorCount = colors.length;
1808
+ const live = buffer.count;
1809
+ const activeAttractors = atx.length;
1810
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
1811
+ ctx.globalAlpha = alpha;
1812
+ let currentColor = -1;
1813
+ for (let i = 0; i < live; i++) {
1814
+ let axSum = 0;
1815
+ let aySum = 0;
1816
+ for (let a = 0; a < activeAttractors; a++) {
1817
+ const dx = atx[a] - buffer.x[i];
1818
+ const dy = aty[a] - buffer.y[i];
1819
+ const distance = Math.hypot(dx, dy);
1820
+ const inv = 1 / (distance + softening);
1821
+ const peak = a === attractorCount && interactive ? gravity * pointerBoost : gravity;
1822
+ const strength = peak * softening * inv;
1823
+ const nx = dx * inv;
1824
+ const ny = dy * inv;
1825
+ axSum += nx * strength;
1826
+ aySum += ny * strength;
1827
+ axSum += -ny * strength * swirl;
1828
+ aySum += nx * strength * swirl;
1829
+ }
1830
+ const dvx = chunkILKUL7GD_cjs.clamp(axSum * delta, -MAX_DELTA_V, MAX_DELTA_V);
1831
+ const dvy = chunkILKUL7GD_cjs.clamp(aySum * delta, -MAX_DELTA_V, MAX_DELTA_V);
1832
+ buffer.vx[i] = (buffer.vx[i] + dvx) * retain;
1833
+ buffer.vy[i] = (buffer.vy[i] + dvy) * retain;
1834
+ buffer.x[i] += buffer.vx[i] * delta;
1835
+ buffer.y[i] += buffer.vy[i] * delta;
1836
+ const speed = Math.hypot(buffer.vx[i], buffer.vy[i]);
1837
+ const ci = Math.min(colorCount - 1, Math.floor(chunkILKUL7GD_cjs.clamp(speed * invFast, 0, 1) * colorCount));
1838
+ if (ci !== currentColor) {
1839
+ const colour = colors[ci];
1840
+ ctx.fillStyle = `rgb(${Math.round(colour.r * 255)},${Math.round(colour.g * 255)},${Math.round(colour.b * 255)})`;
1841
+ currentColor = ci;
1842
+ }
1843
+ const r = buffer.size[i];
1844
+ ctx.fillRect(buffer.x[i] - r, buffer.y[i] - r, r * 2, r * 2);
1845
+ }
1846
+ ctx.globalAlpha = 1;
1847
+ ctx.globalCompositeOperation = "source-over";
1848
+ },
1849
+ resize() {
1850
+ seeded = false;
1851
+ },
1852
+ update(next) {
1853
+ opts = { ...opts, ...next };
1854
+ },
1855
+ destroy() {
1856
+ buffer.clear();
1857
+ }
1858
+ };
1859
+ }
1860
+ });
1861
+
1862
+ // src/effects/atmosphere/meteors.ts
1863
+ var DEFAULTS8 = {
1425
1864
  colors: ["#ffffff", "#a5c8ff", "#8a2be2"],
1426
1865
  speed: 1,
1427
1866
  intensity: 1,
@@ -1447,7 +1886,7 @@ var DEFAULTS5 = {
1447
1886
  var MAX_METEORS = 200;
1448
1887
  var meteors = defineEffect({
1449
1888
  name: "meteors",
1450
- defaults: DEFAULTS5,
1889
+ defaults: DEFAULTS8,
1451
1890
  structuralOptions: ["count"],
1452
1891
  setup(context, options) {
1453
1892
  let opts = options;
@@ -1835,7 +2274,7 @@ var snow = defineEffect({
1835
2274
  });
1836
2275
 
1837
2276
  // src/effects/atmosphere/fireflies.ts
1838
- var DEFAULTS6 = {
2277
+ var DEFAULTS9 = {
1839
2278
  colors: ["#ffe98a", "#c8ff8a", "#8affd4"],
1840
2279
  speed: 1,
1841
2280
  intensity: 1,
@@ -1859,7 +2298,7 @@ var DEFAULTS6 = {
1859
2298
  };
1860
2299
  var fireflies = defineEffect({
1861
2300
  name: "fireflies",
1862
- defaults: DEFAULTS6,
2301
+ defaults: DEFAULTS9,
1863
2302
  structuralOptions: ["count"],
1864
2303
  setup(context, options) {
1865
2304
  let opts = options;
@@ -1966,8 +2405,591 @@ var fireflies = defineEffect({
1966
2405
  }
1967
2406
  });
1968
2407
 
2408
+ // src/effects/atmosphere/light-rays.ts
2409
+ var DEFAULTS10 = {
2410
+ colors: ["#fff4d6", "#ffd9a0", "#ffb865"],
2411
+ speed: 1,
2412
+ intensity: 1,
2413
+ opacity: 1,
2414
+ blur: 0,
2415
+ blend: "lighter",
2416
+ seed: 41,
2417
+ interactive: true,
2418
+ resolution: 1,
2419
+ performance: "auto",
2420
+ reducedMotion: "slow",
2421
+ paused: false,
2422
+ pauseOffscreen: true,
2423
+ count: 16,
2424
+ originX: 0.5,
2425
+ originY: -0.6,
2426
+ angle: Math.PI / 2,
2427
+ spread: 1.1,
2428
+ rayWidth: 0.03,
2429
+ length: 1.4,
2430
+ falloff: 0.5,
2431
+ softness: 0.65,
2432
+ flicker: 0.55,
2433
+ flickerSpeed: 0.35,
2434
+ sway: 0.06,
2435
+ swaySpeed: 0.12,
2436
+ pointerPull: 0.25
2437
+ };
2438
+ var MAX_RAYS = 64;
2439
+ var MIN_BRIGHTNESS = 0.15;
2440
+ var MAX_SOFT_SPREAD = 2.5;
2441
+ var SOFT_LAYERS = [
2442
+ { width: 1, alpha: 0.28 },
2443
+ { width: 0.55, alpha: 0.32 },
2444
+ { width: 0.28, alpha: 0.4 }
2445
+ ];
2446
+ var lightRays = defineEffect({
2447
+ name: "light-rays",
2448
+ defaults: DEFAULTS10,
2449
+ structuralOptions: ["count"],
2450
+ setup(context, options) {
2451
+ let opts = options;
2452
+ const count = Math.min(MAX_RAYS, Math.max(1, Math.floor(opts.count)));
2453
+ const angleJitter = new Float32Array(count);
2454
+ const widthScale = new Float32Array(count);
2455
+ const noiseOffset = new Float32Array(count);
2456
+ const colorIndex = new Uint8Array(count);
2457
+ const rng = context.rng;
2458
+ for (let i = 0; i < count; i++) {
2459
+ angleJitter[i] = rng.range(-0.5, 0.5);
2460
+ widthScale[i] = rng.range(0.45, 1.55);
2461
+ noiseOffset[i] = rng.range(0, 128);
2462
+ colorIndex[i] = rng.int(0, 255);
2463
+ }
2464
+ const brightness = context.noise.fbm2D({ octaves: 2, gain: 0.55 });
2465
+ let gradients = [];
2466
+ let gradientLength = -1;
2467
+ function buildGradients(rayLength) {
2468
+ const { ctx, colors } = context;
2469
+ gradients = colors.map((color) => {
2470
+ const rgb = `${Math.round(color.r * 255)},${Math.round(color.g * 255)},${Math.round(color.b * 255)}`;
2471
+ const gradient = ctx.createLinearGradient(0, 0, Math.max(1, rayLength), 0);
2472
+ const reach = chunkILKUL7GD_cjs.clamp(opts.falloff, 0.05, 1);
2473
+ gradient.addColorStop(0, `rgba(${rgb},${color.a * 0.7})`);
2474
+ gradient.addColorStop(reach * 0.4, `rgba(${rgb},${color.a * 0.36})`);
2475
+ gradient.addColorStop(reach, `rgba(${rgb},${color.a * 0.12})`);
2476
+ gradient.addColorStop(1, `rgba(${rgb},0)`);
2477
+ return gradient;
2478
+ });
2479
+ gradientLength = rayLength;
2480
+ }
2481
+ return {
2482
+ frame({ time, quality }) {
2483
+ const { ctx, size, surface, pointer, colors } = context;
2484
+ const { width, height } = size;
2485
+ if (width < 1 || height < 1) return;
2486
+ surface.clear();
2487
+ if (colors.length === 0) return;
2488
+ const rayLength = Math.hypot(width, height) * opts.length;
2489
+ if (rayLength !== gradientLength) buildGradients(rayLength);
2490
+ const drawn = opts.performance === "high" ? count : Math.max(3, Math.round(count * quality));
2491
+ let originX = opts.originX;
2492
+ let originY = opts.originY;
2493
+ const interactive = opts.interactive !== false && pointer !== null && pointer.everInside;
2494
+ if (interactive) {
2495
+ const pull = chunkILKUL7GD_cjs.clamp(opts.pointerPull, 0, 1);
2496
+ originX += (pointer.smoothNx - originX) * pull;
2497
+ originY += (pointer.smoothNy - originY) * pull;
2498
+ }
2499
+ const sourceX = originX * width;
2500
+ const sourceY = originY * height;
2501
+ const sway = Math.sin(time * opts.swaySpeed * chunkILKUL7GD_cjs.TAU) * opts.sway;
2502
+ const half = opts.spread / 2;
2503
+ const step = opts.spread / drawn;
2504
+ const flickerDepth = chunkILKUL7GD_cjs.clamp(opts.flicker, 0, 1);
2505
+ const alphaScale = chunkILKUL7GD_cjs.clamp(opts.opacity * opts.intensity, 0, 1);
2506
+ ctx.save();
2507
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
2508
+ ctx.translate(sourceX, sourceY);
2509
+ for (let i = 0; i < drawn; i++) {
2510
+ const rayAngle = opts.angle - half + (i + 0.5) * step + angleJitter[i] * step + sway;
2511
+ const n = brightness(noiseOffset[i], time * opts.flickerSpeed);
2512
+ const varied = 1 - flickerDepth * (1 - (n * 0.5 + 0.5));
2513
+ const alpha = chunkILKUL7GD_cjs.clamp(Math.max(MIN_BRIGHTNESS, varied) * alphaScale, 0, 1);
2514
+ if (alpha <= 2e-3) continue;
2515
+ const halfWidth = opts.rayWidth * widthScale[i];
2516
+ const spreadFactor = 1 + chunkILKUL7GD_cjs.clamp(opts.softness, 0, 1) * MAX_SOFT_SPREAD;
2517
+ ctx.save();
2518
+ ctx.rotate(rayAngle);
2519
+ ctx.fillStyle = gradients[colorIndex[i] % gradients.length];
2520
+ for (const layer of SOFT_LAYERS) {
2521
+ const hw = halfWidth * (1 + (spreadFactor - 1) * layer.width);
2522
+ ctx.globalAlpha = alpha * layer.alpha;
2523
+ ctx.beginPath();
2524
+ ctx.moveTo(0, 0);
2525
+ ctx.lineTo(Math.cos(-hw) * rayLength, Math.sin(-hw) * rayLength);
2526
+ ctx.lineTo(Math.cos(hw) * rayLength, Math.sin(hw) * rayLength);
2527
+ ctx.closePath();
2528
+ ctx.fill();
2529
+ }
2530
+ ctx.restore();
2531
+ }
2532
+ ctx.restore();
2533
+ ctx.globalAlpha = 1;
2534
+ ctx.globalCompositeOperation = "source-over";
2535
+ },
2536
+ resize() {
2537
+ gradientLength = -1;
2538
+ },
2539
+ update(next) {
2540
+ opts = { ...opts, ...next };
2541
+ gradientLength = -1;
2542
+ },
2543
+ destroy() {
2544
+ gradients = [];
2545
+ }
2546
+ };
2547
+ }
2548
+ });
2549
+
2550
+ // src/effects/atmosphere/smoke.ts
2551
+ var DEFAULTS11 = {
2552
+ colors: ["#8e9bb0", "#b9c3d1", "#6b7688"],
2553
+ speed: 1,
2554
+ intensity: 1,
2555
+ opacity: 1,
2556
+ blur: 0,
2557
+ // `source-over`, not `lighter` — the one place this effect deliberately breaks with the other
2558
+ // particle effects here. Smoke *occludes* light rather than emitting it, and additive blending
2559
+ // drives overlapping puffs to pure white, which reads as a lens flare rather than a plume.
2560
+ blend: "source-over",
2561
+ seed: 53,
2562
+ interactive: false,
2563
+ resolution: 0.85,
2564
+ performance: "auto",
2565
+ reducedMotion: "slow",
2566
+ paused: false,
2567
+ pauseOffscreen: true,
2568
+ count: 100,
2569
+ sourceX: 0.5,
2570
+ sourceY: 1.05,
2571
+ // Tight at the emitter: a wide spawn scatters puffs into unrelated blobs instead of a column,
2572
+ // and the curl field widens the plume on its own as it climbs.
2573
+ spread: 16,
2574
+ rise: 54,
2575
+ turbulence: 26,
2576
+ scale: 35e-4,
2577
+ size: 18,
2578
+ growth: 2.2,
2579
+ life: 4.5,
2580
+ drag: 0.55,
2581
+ density: 0.16
2582
+ };
2583
+ var MAX_PUFFS = 400;
2584
+ var FADE_IN = 0.14;
2585
+ var FIELD_DRIFT = 0.12;
2586
+ var DECAY_SHAPE = 1.6;
2587
+ var smoke = defineEffect({
2588
+ name: "smoke",
2589
+ defaults: DEFAULTS11,
2590
+ structuralOptions: ["count"],
2591
+ setup(context, options) {
2592
+ let opts = options;
2593
+ const capacity = Math.min(MAX_PUFFS, Math.max(1, Math.floor(opts.count)));
2594
+ const buffer = new ParticleBuffer(capacity);
2595
+ const gradients = new GradientCache(64);
2596
+ const curl = context.noise.curlAnimated({ octaves: 2, gain: 0.5 });
2597
+ let seeded = false;
2598
+ function place(index, ageOffset) {
2599
+ const { width, height } = context.size;
2600
+ const rng = context.rng;
2601
+ const colorCount = Math.max(1, context.colors.length);
2602
+ buffer.x[index] = opts.sourceX * width + rng.range(-opts.spread, opts.spread);
2603
+ buffer.y[index] = opts.sourceY * height + rng.range(-opts.spread, opts.spread) * 0.35;
2604
+ buffer.vx[index] = rng.range(-8, 8);
2605
+ buffer.vy[index] = -opts.rise * rng.range(0.7, 1.3);
2606
+ buffer.size[index] = opts.size * rng.range(0.65, 1.4);
2607
+ buffer.colorIndex[index] = rng.int(0, colorCount - 1);
2608
+ buffer.maxLife[index] = opts.life * rng.range(0.75, 1.25);
2609
+ buffer.life[index] = buffer.maxLife[index] * (1 - ageOffset);
2610
+ buffer.seed[index] = rng.range(0, 500);
2611
+ buffer.extra[index] = rng.range(0.7, 1.35);
2612
+ }
2613
+ function seed() {
2614
+ buffer.clear();
2615
+ for (let i = 0; i < capacity; i++) {
2616
+ const index = buffer.spawn();
2617
+ if (index < 0) break;
2618
+ place(index, context.rng.next());
2619
+ }
2620
+ seeded = true;
2621
+ }
2622
+ return {
2623
+ frame({ time, delta, quality }) {
2624
+ const { ctx, size, surface, colors } = context;
2625
+ const { width, height } = size;
2626
+ if (width < 1 || height < 1) return;
2627
+ if (!seeded || buffer.count === 0) seed();
2628
+ const target = opts.performance === "high" ? capacity : Math.max(4, Math.floor(capacity * quality));
2629
+ if (buffer.count > target) buffer.truncate(target);
2630
+ surface.clear();
2631
+ if (colors.length === 0) return;
2632
+ const count = buffer.count;
2633
+ const colorCount = Math.max(1, colors.length);
2634
+ const retain = Math.pow(1 - chunkILKUL7GD_cjs.clamp(opts.drag, 0, 0.999), delta);
2635
+ const turbulence = opts.turbulence * opts.intensity;
2636
+ const rise = opts.rise * opts.intensity;
2637
+ const peak = chunkILKUL7GD_cjs.clamp(opts.density, 0, 1) * chunkILKUL7GD_cjs.clamp(opts.opacity, 0, 1);
2638
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
2639
+ for (let i = 0; i < count; i++) {
2640
+ buffer.life[i] -= delta;
2641
+ if (buffer.life[i] <= 0) {
2642
+ place(i, 0);
2643
+ continue;
2644
+ }
2645
+ const flow = curl(
2646
+ (buffer.x[i] + buffer.seed[i]) * opts.scale,
2647
+ buffer.y[i] * opts.scale,
2648
+ time * FIELD_DRIFT
2649
+ );
2650
+ buffer.vx[i] = buffer.vx[i] * retain + flow.x * turbulence * delta;
2651
+ buffer.vy[i] = buffer.vy[i] * retain + (flow.y * turbulence - rise) * delta;
2652
+ buffer.x[i] += buffer.vx[i] * delta;
2653
+ buffer.y[i] += buffer.vy[i] * delta;
2654
+ const age = chunkILKUL7GD_cjs.clamp(1 - buffer.life[i] / buffer.maxLife[i], 0, 1);
2655
+ const fadeIn = Math.min(1, age / FADE_IN);
2656
+ const decay = Math.pow(1 - age, DECAY_SHAPE);
2657
+ const alpha = peak * fadeIn * decay;
2658
+ if (alpha <= 2e-3) continue;
2659
+ const radius = buffer.size[i] * (1 + opts.growth * age) * buffer.extra[i];
2660
+ drawGlow(
2661
+ ctx,
2662
+ buffer.x[i],
2663
+ buffer.y[i],
2664
+ radius,
2665
+ colors[buffer.colorIndex[i] % colorCount],
2666
+ alpha,
2667
+ gradients
2668
+ );
2669
+ }
2670
+ ctx.globalCompositeOperation = "source-over";
2671
+ },
2672
+ resize() {
2673
+ seeded = false;
2674
+ },
2675
+ update(next) {
2676
+ opts = { ...opts, ...next };
2677
+ gradients.clear();
2678
+ },
2679
+ destroy() {
2680
+ buffer.clear();
2681
+ gradients.clear();
2682
+ }
2683
+ };
2684
+ }
2685
+ });
2686
+
2687
+ // src/effects/geometry/floating-geometry.ts
2688
+ var ALL_SHAPES = ["triangle", "square", "pentagon", "hexagon", "circle"];
2689
+ var DEFAULTS12 = {
2690
+ colors: ["#7cc4ff", "#a78bfa", "#5eead4"],
2691
+ speed: 1,
2692
+ intensity: 1,
2693
+ opacity: 1,
2694
+ blur: 0,
2695
+ blend: "lighter",
2696
+ seed: 67,
2697
+ interactive: false,
2698
+ resolution: 1,
2699
+ performance: "auto",
2700
+ reducedMotion: "slow",
2701
+ paused: false,
2702
+ pauseOffscreen: true,
2703
+ count: 18,
2704
+ shapes: ALL_SHAPES,
2705
+ size: 46,
2706
+ drift: 26,
2707
+ spin: 0.06,
2708
+ perspective: 1,
2709
+ depth: 2.6,
2710
+ haze: 0.25,
2711
+ filled: false,
2712
+ lineWidth: 1.5
2713
+ };
2714
+ var MAX_SHAPES = 120;
2715
+ var CIRCLE = 0;
2716
+ function sidesFor(shape) {
2717
+ switch (shape) {
2718
+ case "triangle":
2719
+ return 3;
2720
+ case "square":
2721
+ return 4;
2722
+ case "pentagon":
2723
+ return 5;
2724
+ case "hexagon":
2725
+ return 6;
2726
+ default:
2727
+ return CIRCLE;
2728
+ }
2729
+ }
2730
+ var floatingGeometry = defineEffect({
2731
+ name: "floating-geometry",
2732
+ defaults: DEFAULTS12,
2733
+ structuralOptions: ["count", "shapes"],
2734
+ setup(context, options) {
2735
+ let opts = options;
2736
+ const count = Math.min(MAX_SHAPES, Math.max(1, Math.floor(opts.count)));
2737
+ const x = new Float32Array(count);
2738
+ const y = new Float32Array(count);
2739
+ const z = new Float32Array(count);
2740
+ const rotation = new Float32Array(count);
2741
+ const spinRate = new Float32Array(count);
2742
+ const radius = new Float32Array(count);
2743
+ const driftX = new Float32Array(count);
2744
+ const driftY = new Float32Array(count);
2745
+ const sides = new Uint8Array(count);
2746
+ const colorIndex = new Uint8Array(count);
2747
+ const order = new Int32Array(count);
2748
+ let seeded = false;
2749
+ function seed() {
2750
+ const { width, height } = context.size;
2751
+ const rng = context.rng;
2752
+ const colorCount = Math.max(1, context.colors.length);
2753
+ const palette = opts.shapes.length > 0 ? opts.shapes : ALL_SHAPES;
2754
+ for (let i = 0; i < count; i++) {
2755
+ x[i] = rng.next() * width;
2756
+ y[i] = rng.next() * height;
2757
+ z[i] = rng.next();
2758
+ rotation[i] = rng.angle();
2759
+ spinRate[i] = rng.range(-1, 1) * opts.spin * chunkILKUL7GD_cjs.TAU;
2760
+ radius[i] = opts.size * rng.range(0.55, 1.45);
2761
+ const angle = rng.angle();
2762
+ driftX[i] = Math.cos(angle);
2763
+ driftY[i] = Math.sin(angle);
2764
+ sides[i] = sidesFor(palette[rng.int(0, palette.length - 1)]);
2765
+ colorIndex[i] = rng.int(0, colorCount - 1);
2766
+ order[i] = i;
2767
+ }
2768
+ const indices = Array.from(order);
2769
+ indices.sort((a, b) => z[b] - z[a]);
2770
+ for (let i = 0; i < count; i++) order[i] = indices[i];
2771
+ seeded = true;
2772
+ }
2773
+ return {
2774
+ frame({ delta, quality }) {
2775
+ const { ctx, size, surface, colors } = context;
2776
+ const { width, height } = size;
2777
+ if (width < 1 || height < 1) return;
2778
+ if (!seeded) seed();
2779
+ surface.clear();
2780
+ if (colors.length === 0) return;
2781
+ const drawn = opts.performance === "high" ? count : Math.max(3, Math.round(count * quality));
2782
+ const focal = Math.max(0.05, opts.perspective);
2783
+ const spread = Math.max(0, opts.depth);
2784
+ const drift = opts.drift * opts.intensity;
2785
+ const haze = chunkILKUL7GD_cjs.clamp(opts.haze, 0, 1);
2786
+ const alphaScale = chunkILKUL7GD_cjs.clamp(opts.opacity, 0, 1);
2787
+ const colorCount = Math.max(1, colors.length);
2788
+ ctx.save();
2789
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
2790
+ const firstDrawn = count - drawn;
2791
+ for (let k = 0; k < count; k++) {
2792
+ const i = order[k];
2793
+ const projected = focal / (focal + z[i] * spread);
2794
+ x[i] += driftX[i] * drift * projected * delta;
2795
+ y[i] += driftY[i] * drift * projected * delta;
2796
+ rotation[i] += spinRate[i] * delta;
2797
+ const margin = radius[i] * projected + opts.lineWidth * 2;
2798
+ if (x[i] < -margin) x[i] = width + margin;
2799
+ else if (x[i] > width + margin) x[i] = -margin;
2800
+ if (y[i] < -margin) y[i] = height + margin;
2801
+ else if (y[i] > height + margin) y[i] = -margin;
2802
+ if (k < firstDrawn) continue;
2803
+ const alpha = alphaScale * chunkILKUL7GD_cjs.lerp(1, haze, z[i]);
2804
+ if (alpha <= 2e-3) continue;
2805
+ const r = radius[i] * projected;
2806
+ const color = colors[colorIndex[i] % colorCount];
2807
+ ctx.save();
2808
+ ctx.translate(x[i], y[i]);
2809
+ ctx.rotate(rotation[i]);
2810
+ ctx.globalAlpha = alpha;
2811
+ ctx.beginPath();
2812
+ if (sides[i] === CIRCLE) {
2813
+ ctx.arc(0, 0, r, 0, chunkILKUL7GD_cjs.TAU);
2814
+ } else {
2815
+ const n = sides[i];
2816
+ for (let v = 0; v < n; v++) {
2817
+ const a = v / n * chunkILKUL7GD_cjs.TAU;
2818
+ const px = Math.cos(a) * r;
2819
+ const py = Math.sin(a) * r;
2820
+ if (v === 0) ctx.moveTo(px, py);
2821
+ else ctx.lineTo(px, py);
2822
+ }
2823
+ ctx.closePath();
2824
+ }
2825
+ if (opts.filled) {
2826
+ ctx.fillStyle = chunk4ORYTFY3_cjs.toRgbString(color);
2827
+ ctx.fill();
2828
+ } else {
2829
+ ctx.lineWidth = Math.max(0.3, opts.lineWidth * projected);
2830
+ ctx.strokeStyle = chunk4ORYTFY3_cjs.toRgbString(color);
2831
+ ctx.stroke();
2832
+ }
2833
+ ctx.restore();
2834
+ }
2835
+ ctx.restore();
2836
+ ctx.globalAlpha = 1;
2837
+ ctx.globalCompositeOperation = "source-over";
2838
+ },
2839
+ resize() {
2840
+ seeded = false;
2841
+ },
2842
+ update(next) {
2843
+ opts = {
2844
+ ...opts,
2845
+ ...next
2846
+ };
2847
+ }
2848
+ };
2849
+ }
2850
+ });
2851
+
2852
+ // src/effects/geometry/orbit.ts
2853
+ var DEFAULTS13 = {
2854
+ colors: ["#7cc4ff", "#a78bfa", "#5eead4", "#fbbf7c"],
2855
+ speed: 1,
2856
+ intensity: 1,
2857
+ opacity: 1,
2858
+ blur: 0,
2859
+ blend: "lighter",
2860
+ seed: 71,
2861
+ interactive: false,
2862
+ resolution: 1,
2863
+ performance: "auto",
2864
+ reducedMotion: "slow",
2865
+ paused: false,
2866
+ pauseOffscreen: true,
2867
+ rings: 3,
2868
+ perRing: 14,
2869
+ radius: 0.42,
2870
+ innerRadius: 0.45,
2871
+ tilt: 0.34,
2872
+ orbitSpeed: 0.05,
2873
+ size: 3.2,
2874
+ glow: 3,
2875
+ counterRotate: true,
2876
+ showOrbits: true,
2877
+ orbitOpacity: 0.12,
2878
+ core: 26
2879
+ };
2880
+ var MAX_RINGS = 12;
2881
+ var MAX_PER_RING = 80;
2882
+ var DEPTH_SCALE_FAR = 0.55;
2883
+ var DEPTH_SCALE_NEAR = 1.3;
2884
+ var DEPTH_ALPHA_FAR = 0.3;
2885
+ var DEPTH_ALPHA_NEAR = 1;
2886
+ var INNER_RING_SPEEDUP = 1.8;
2887
+ var orbit = defineEffect({
2888
+ name: "orbit",
2889
+ defaults: DEFAULTS13,
2890
+ structuralOptions: ["rings", "perRing"],
2891
+ setup(context, options) {
2892
+ let opts = options;
2893
+ const rings = Math.min(MAX_RINGS, Math.max(1, Math.floor(opts.rings)));
2894
+ const perRing = Math.min(MAX_PER_RING, Math.max(1, Math.floor(opts.perRing)));
2895
+ const total = rings * perRing;
2896
+ const phase = new Float32Array(total);
2897
+ const sizeScale = new Float32Array(total);
2898
+ const colorIndex = new Uint8Array(total);
2899
+ const ringPhase = new Float32Array(rings);
2900
+ const rng = context.rng;
2901
+ const colorCount = Math.max(1, context.colors.length);
2902
+ for (let r = 0; r < rings; r++) {
2903
+ ringPhase[r] = rng.angle();
2904
+ for (let p = 0; p < perRing; p++) {
2905
+ const i = r * perRing + p;
2906
+ phase[i] = p / perRing * chunkILKUL7GD_cjs.TAU + rng.range(-0.12, 0.12);
2907
+ sizeScale[i] = rng.range(0.7, 1.35);
2908
+ colorIndex[i] = rng.int(0, colorCount - 1);
2909
+ }
2910
+ }
2911
+ const gradients = new GradientCache(64);
2912
+ return {
2913
+ frame({ time, quality }) {
2914
+ const { ctx, size, surface, colors } = context;
2915
+ const { width, height } = size;
2916
+ if (width < 1 || height < 1) return;
2917
+ surface.clear();
2918
+ if (colors.length === 0) return;
2919
+ const cx = width / 2;
2920
+ const cy = height / 2;
2921
+ const outer = Math.min(width, height) * opts.radius;
2922
+ const inner = outer * chunkILKUL7GD_cjs.clamp(opts.innerRadius, 0.05, 1);
2923
+ const tilt = chunkILKUL7GD_cjs.clamp(opts.tilt, 0.02, 1);
2924
+ const alphaScale = chunkILKUL7GD_cjs.clamp(opts.opacity * opts.intensity, 0, 1);
2925
+ const count = colors.length;
2926
+ const drawnPerRing = opts.performance === "high" ? perRing : Math.max(3, Math.round(perRing * quality));
2927
+ ctx.save();
2928
+ ctx.globalCompositeOperation = opts.blend ?? "lighter";
2929
+ const drawPoints = (near) => {
2930
+ for (let r = 0; r < rings; r++) {
2931
+ const t = rings === 1 ? 1 : r / (rings - 1);
2932
+ const ringRadius = chunkILKUL7GD_cjs.lerp(inner, outer, t);
2933
+ const direction = opts.counterRotate && r % 2 === 1 ? -1 : 1;
2934
+ const rate = opts.orbitSpeed * chunkILKUL7GD_cjs.TAU * direction * chunkILKUL7GD_cjs.lerp(INNER_RING_SPEEDUP, 1, t);
2935
+ const base = ringPhase[r] + time * rate;
2936
+ for (let p = 0; p < drawnPerRing; p++) {
2937
+ const i = r * perRing + p;
2938
+ const theta = base + phase[i];
2939
+ const depth = Math.sin(theta);
2940
+ if (near !== depth > 0) continue;
2941
+ const d = depth * 0.5 + 0.5;
2942
+ const alpha = alphaScale * chunkILKUL7GD_cjs.lerp(DEPTH_ALPHA_FAR, DEPTH_ALPHA_NEAR, d);
2943
+ if (alpha <= 2e-3) continue;
2944
+ const scale = chunkILKUL7GD_cjs.lerp(DEPTH_SCALE_FAR, DEPTH_SCALE_NEAR, d);
2945
+ drawGlow(
2946
+ ctx,
2947
+ cx + Math.cos(theta) * ringRadius,
2948
+ cy + depth * ringRadius * tilt,
2949
+ opts.size * opts.glow * sizeScale[i] * scale,
2950
+ colors[colorIndex[i] % count],
2951
+ alpha,
2952
+ gradients
2953
+ );
2954
+ }
2955
+ }
2956
+ };
2957
+ drawPoints(false);
2958
+ if (opts.showOrbits && opts.orbitOpacity > 0) {
2959
+ const guide = colors[0];
2960
+ ctx.globalAlpha = chunkILKUL7GD_cjs.clamp(opts.orbitOpacity * alphaScale, 0, 1);
2961
+ ctx.strokeStyle = `rgb(${Math.round(guide.r * 255)},${Math.round(guide.g * 255)},${Math.round(guide.b * 255)})`;
2962
+ ctx.lineWidth = 1;
2963
+ for (let r = 0; r < rings; r++) {
2964
+ const t = rings === 1 ? 1 : r / (rings - 1);
2965
+ const ringRadius = chunkILKUL7GD_cjs.lerp(inner, outer, t);
2966
+ ctx.beginPath();
2967
+ ctx.ellipse(cx, cy, ringRadius, ringRadius * tilt, 0, 0, chunkILKUL7GD_cjs.TAU);
2968
+ ctx.stroke();
2969
+ }
2970
+ ctx.globalAlpha = 1;
2971
+ }
2972
+ if (opts.core > 0) {
2973
+ drawGlow(ctx, cx, cy, opts.core, colors[0], alphaScale, gradients);
2974
+ }
2975
+ drawPoints(true);
2976
+ ctx.restore();
2977
+ ctx.globalAlpha = 1;
2978
+ ctx.globalCompositeOperation = "source-over";
2979
+ },
2980
+ update(next) {
2981
+ opts = { ...opts, ...next };
2982
+ gradients.clear();
2983
+ },
2984
+ destroy() {
2985
+ gradients.clear();
2986
+ }
2987
+ };
2988
+ }
2989
+ });
2990
+
1969
2991
  // src/effects/surfaces/waves.ts
1970
- var DEFAULTS7 = {
2992
+ var DEFAULTS14 = {
1971
2993
  colors: "abyss",
1972
2994
  speed: 1,
1973
2995
  intensity: 1,
@@ -1992,7 +3014,7 @@ var DEFAULTS7 = {
1992
3014
  };
1993
3015
  var waves = defineEffect({
1994
3016
  name: "waves",
1995
- defaults: DEFAULTS7,
3017
+ defaults: DEFAULTS14,
1996
3018
  structuralOptions: ["layers"],
1997
3019
  setup(context, options) {
1998
3020
  let opts = options;
@@ -2001,7 +3023,7 @@ var waves = defineEffect({
2001
3023
  let crest = [];
2002
3024
  function build() {
2003
3025
  const count = Math.max(1, Math.floor(opts.layers));
2004
- const palette = chunk23GSSIMK_cjs.expandPalette(context.colors, count);
3026
+ const palette = chunk4ORYTFY3_cjs.expandPalette(context.colors, count);
2005
3027
  const rng = context.rng;
2006
3028
  layers = [];
2007
3029
  for (let i = 0; i < count; i++) {
@@ -2087,7 +3109,7 @@ var waves = defineEffect({
2087
3109
  });
2088
3110
 
2089
3111
  // src/effects/surfaces/blob.ts
2090
- var DEFAULTS8 = {
3112
+ var DEFAULTS15 = {
2091
3113
  colors: "ansh",
2092
3114
  speed: 1,
2093
3115
  intensity: 1,
@@ -2114,7 +3136,7 @@ var DEFAULTS8 = {
2114
3136
  };
2115
3137
  var blob = defineEffect({
2116
3138
  name: "blob",
2117
- defaults: DEFAULTS8,
3139
+ defaults: DEFAULTS15,
2118
3140
  structuralOptions: ["count", "segments"],
2119
3141
  setup(context, options) {
2120
3142
  let opts = options;
@@ -2123,7 +3145,7 @@ var blob = defineEffect({
2123
3145
  let ring = [];
2124
3146
  function build() {
2125
3147
  const count = Math.max(1, Math.floor(opts.count));
2126
- const palette = chunk23GSSIMK_cjs.expandPalette(context.colors, count);
3148
+ const palette = chunk4ORYTFY3_cjs.expandPalette(context.colors, count);
2127
3149
  const rng = context.rng;
2128
3150
  blobs = [];
2129
3151
  for (let i = 0; i < count; i++) {
@@ -2216,7 +3238,7 @@ var blob = defineEffect({
2216
3238
  });
2217
3239
 
2218
3240
  // src/effects/overlays/noise-layer.ts
2219
- var DEFAULTS9 = {
3241
+ var DEFAULTS16 = {
2220
3242
  colors: ["#ffffff"],
2221
3243
  speed: 1,
2222
3244
  intensity: 1,
@@ -2243,7 +3265,7 @@ var DEFAULTS9 = {
2243
3265
  };
2244
3266
  var noiseLayer = defineEffect({
2245
3267
  name: "noise-layer",
2246
- defaults: DEFAULTS9,
3268
+ defaults: DEFAULTS16,
2247
3269
  structuralOptions: ["tileSize", "frames", "grainSize", "monochrome"],
2248
3270
  setup(context, options) {
2249
3271
  let opts = options;
@@ -2334,7 +3356,7 @@ var noiseLayer = defineEffect({
2334
3356
  });
2335
3357
 
2336
3358
  // src/effects/overlays/spotlight.ts
2337
- var DEFAULTS10 = {
3359
+ var DEFAULTS17 = {
2338
3360
  colors: ["#ffffff"],
2339
3361
  speed: 1,
2340
3362
  intensity: 0.35,
@@ -2361,7 +3383,7 @@ var DEFAULTS10 = {
2361
3383
  };
2362
3384
  var spotlight = defineEffect({
2363
3385
  name: "spotlight",
2364
- defaults: DEFAULTS10,
3386
+ defaults: DEFAULTS17,
2365
3387
  setup(context, options) {
2366
3388
  let opts = options;
2367
3389
  let presence = opts.ambient ? 1 : 0;
@@ -2433,10 +3455,17 @@ var effects = {
2433
3455
  "animated-gradient": animatedGradient,
2434
3456
  "particle-field": particleField,
2435
3457
  constellation,
3458
+ "powder-explosion": powderExplosion,
3459
+ "strange-attractor": strangeAttractor,
3460
+ swarm,
2436
3461
  meteors,
2437
3462
  rain,
2438
3463
  snow,
2439
3464
  fireflies,
3465
+ "light-rays": lightRays,
3466
+ smoke,
3467
+ "floating-geometry": floatingGeometry,
3468
+ orbit,
2440
3469
  waves,
2441
3470
  blob,
2442
3471
  "noise-layer": noiseLayer,
@@ -2457,23 +3486,30 @@ exports.drawDot = drawDot;
2457
3486
  exports.drawGlow = drawGlow;
2458
3487
  exports.effects = effects;
2459
3488
  exports.fireflies = fireflies;
3489
+ exports.floatingGeometry = floatingGeometry;
2460
3490
  exports.integrate = integrate;
3491
+ exports.lightRays = lightRays;
2461
3492
  exports.meshGradient = meshGradient;
2462
3493
  exports.meteors = meteors;
2463
3494
  exports.mountEffect = mountEffect;
2464
3495
  exports.noiseLayer = noiseLayer;
3496
+ exports.orbit = orbit;
2465
3497
  exports.particleField = particleField;
3498
+ exports.powderExplosion = powderExplosion;
2466
3499
  exports.rain = rain;
2467
3500
  exports.resetFilterSupport = resetFilterSupport;
3501
+ exports.smoke = smoke;
2468
3502
  exports.snow = snow;
2469
3503
  exports.spotlight = spotlight;
3504
+ exports.strangeAttractor = strangeAttractor;
2470
3505
  exports.supportsCanvasFilter = supportsCanvasFilter;
2471
3506
  exports.supportsOffscreenCanvas = supportsOffscreenCanvas;
2472
3507
  exports.supportsWorkerRendering = supportsWorkerRendering;
3508
+ exports.swarm = swarm;
2473
3509
  exports.traceClosedSpline = traceClosedSpline;
2474
3510
  exports.traceOpenSpline = traceOpenSpline;
2475
3511
  exports.traceRoundRect = traceRoundRect;
2476
3512
  exports.waves = waves;
2477
3513
  exports.wrapBounds = wrapBounds;
2478
- //# sourceMappingURL=chunk-R7UJ7MWP.cjs.map
2479
- //# sourceMappingURL=chunk-R7UJ7MWP.cjs.map
3514
+ //# sourceMappingURL=chunk-OSNUN5JJ.cjs.map
3515
+ //# sourceMappingURL=chunk-OSNUN5JJ.cjs.map