@dopaminefx/effect-confetti 0.1.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.
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Confetti Canvas2D PANEL drawing — the PANEL-DRAW SEAM.
3
+ *
4
+ * Confetti is a PANEL HYBRID (like comic/heartburst): the paper pieces are
5
+ * rasterized into an offscreen Canvas2D panel each frame (each pose computed
6
+ * ONCE per frame, in JS) and the fragment shader (confetti-shader.ts) samples
7
+ * that texture and applies the screen-space finish (the global gain, ACES
8
+ * tonemap, cel posterize, ordered dither, soft cast shadow). This is now
9
+ * CONVERGED across all three platforms: the native ConfettiPanel files
10
+ * (CoreGraphics / android.graphics) are faithful ports of this draw, the shader
11
+ * is single-source GLSL, and the factory / tempo / uniforms are GENERATED from
12
+ * confetti.dope.json. The pieces' MOTION (the ballistic launch-then-fall poses)
13
+ * is panel GEOMETRY — code by design — so this draw is the ONE hand-written web
14
+ * source beyond the shader (the per-platform panel-draw seam).
15
+ *
16
+ * PERFORMANCE: the original single-pass design re-derived all MAX_PIECES poses
17
+ * (hash + ballistic + sway + spin) at EVERY pixel — O(pixels × pieces), fine on
18
+ * a GPU but crawling under software/ANGLE WebGL. The pieces cover a tiny
19
+ * fraction of the screen, so the work belongs where it scales with COVERED
20
+ * AREA, not pixel count.
21
+ *
22
+ * Panel channel encoding consumed by confetti-shader.ts:
23
+ * RGB = the per-piece LIT colour (palette × paper/cel shading), pre-multiplied
24
+ * by the piece's lifetime fade and accumulated additively across pieces.
25
+ * The shader applies the global gain (amp × exposure), tonemap + finish.
26
+ */
27
+ import { type PanelDraw, type RGB } from "@dopaminefx/core";
28
+ /** Resolved render params the confetti panel consumes. */
29
+ export interface ConfettiRenderParams {
30
+ durationMs: number;
31
+ palette: RGB[];
32
+ style: number;
33
+ exposure: number;
34
+ pieceCount: number;
35
+ spread: number;
36
+ launchSpeed: number;
37
+ gravity: number;
38
+ flutter: number;
39
+ pieceSize: number;
40
+ spin: number;
41
+ overshoot: number;
42
+ pieceSeed: number;
43
+ }
44
+ /**
45
+ * Draw one frame of confetti into the offscreen panel. `life` is whole-effect
46
+ * progress 0..1; `center` is the launch anchor (device px, canvas y-down).
47
+ *
48
+ * Mirrors the original shader's `pieceAt` motion (a mostly-up launch cone, a
49
+ * gravity arc, an air-drag sway, and a tumbling spin with a face-flash) and its
50
+ * per-piece lit colour (paper shading ↔ flat cel by whimsy), computed once per
51
+ * piece in JS instead of once per pixel in GLSL.
52
+ */
53
+ /**
54
+ * The per-frame panel draw in the generic `PanelDraw` shape — the ONE
55
+ * code-shaped hook the data-driven panel factory wires
56
+ * (`registerDopePanelEffect`). The whole-effect amplitude envelope is DATA
57
+ * (`tempo.frame.amp` in confetti.dope.json); this draw owns only the pieces'
58
+ * panel GEOMETRY (the ballistic launch-then-fall poses), which is code by
59
+ * design. Hands off to {@link drawConfettiPanel}.
60
+ */
61
+ export declare const drawConfettiFrame: PanelDraw;
62
+ export declare function drawConfettiPanel(ctx: CanvasRenderingContext2D, w: number, h: number, params: ConfettiRenderParams, life: number, center: {
63
+ x: number;
64
+ y: number;
65
+ }): void;
66
+ //# sourceMappingURL=confetti-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-renderer.d.ts","sourceRoot":"","sources":["../src/confetti-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAGxE,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAuBD;;;;;;;;GAQG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAE/B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,wBAAwB,EAC7B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,IAAI,CAgGN"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Confetti Canvas2D PANEL drawing — the PANEL-DRAW SEAM.
3
+ *
4
+ * Confetti is a PANEL HYBRID (like comic/heartburst): the paper pieces are
5
+ * rasterized into an offscreen Canvas2D panel each frame (each pose computed
6
+ * ONCE per frame, in JS) and the fragment shader (confetti-shader.ts) samples
7
+ * that texture and applies the screen-space finish (the global gain, ACES
8
+ * tonemap, cel posterize, ordered dither, soft cast shadow). This is now
9
+ * CONVERGED across all three platforms: the native ConfettiPanel files
10
+ * (CoreGraphics / android.graphics) are faithful ports of this draw, the shader
11
+ * is single-source GLSL, and the factory / tempo / uniforms are GENERATED from
12
+ * confetti.dope.json. The pieces' MOTION (the ballistic launch-then-fall poses)
13
+ * is panel GEOMETRY — code by design — so this draw is the ONE hand-written web
14
+ * source beyond the shader (the per-platform panel-draw seam).
15
+ *
16
+ * PERFORMANCE: the original single-pass design re-derived all MAX_PIECES poses
17
+ * (hash + ballistic + sway + spin) at EVERY pixel — O(pixels × pieces), fine on
18
+ * a GPU but crawling under software/ANGLE WebGL. The pieces cover a tiny
19
+ * fraction of the screen, so the work belongs where it scales with COVERED
20
+ * AREA, not pixel count.
21
+ *
22
+ * Panel channel encoding consumed by confetti-shader.ts:
23
+ * RGB = the per-piece LIT colour (palette × paper/cel shading), pre-multiplied
24
+ * by the piece's lifetime fade and accumulated additively across pieces.
25
+ * The shader applies the global gain (amp × exposure), tonemap + finish.
26
+ */
27
+ import { mulberry32 } from "@dopaminefx/core";
28
+ import { MAX_PIECES } from "./confetti-shader.js";
29
+ const TAU = Math.PI * 2;
30
+ const clamp01 = (x) => (x < 0 ? 0 : x > 1 ? 1 : x);
31
+ const mix = (a, b, t) => a + (b - a) * t;
32
+ const fract = (x) => x - Math.floor(x);
33
+ const smoothstep = (e0, e1, x) => {
34
+ const t = clamp01((x - e0) / (e1 - e0));
35
+ return t * t * (3 - 2 * t);
36
+ };
37
+ /** paletteMix from the look lib: two-segment lerp across the three stops. */
38
+ function paletteMix(pal, t) {
39
+ t = clamp01(t);
40
+ const [c0, c1, c2] = pal;
41
+ if (t < 0.5) {
42
+ const k = t * 2;
43
+ return { r: mix(c0.r, c1.r, k), g: mix(c0.g, c1.g, k), b: mix(c0.b, c1.b, k) };
44
+ }
45
+ const k = (t - 0.5) * 2;
46
+ return { r: mix(c1.r, c2.r, k), g: mix(c1.g, c2.g, k), b: mix(c1.b, c2.b, k) };
47
+ }
48
+ /**
49
+ * Draw one frame of confetti into the offscreen panel. `life` is whole-effect
50
+ * progress 0..1; `center` is the launch anchor (device px, canvas y-down).
51
+ *
52
+ * Mirrors the original shader's `pieceAt` motion (a mostly-up launch cone, a
53
+ * gravity arc, an air-drag sway, and a tumbling spin with a face-flash) and its
54
+ * per-piece lit colour (paper shading ↔ flat cel by whimsy), computed once per
55
+ * piece in JS instead of once per pixel in GLSL.
56
+ */
57
+ /**
58
+ * The per-frame panel draw in the generic `PanelDraw` shape — the ONE
59
+ * code-shaped hook the data-driven panel factory wires
60
+ * (`registerDopePanelEffect`). The whole-effect amplitude envelope is DATA
61
+ * (`tempo.frame.amp` in confetti.dope.json); this draw owns only the pieces'
62
+ * panel GEOMETRY (the ballistic launch-then-fall poses), which is code by
63
+ * design. Hands off to {@link drawConfettiPanel}.
64
+ */
65
+ export const drawConfettiFrame = (pctx, w, h, params, info) => {
66
+ drawConfettiPanel(pctx, w, h, params, info.life, info.centerPx);
67
+ };
68
+ export function drawConfettiPanel(ctx, w, h, params, life, center) {
69
+ ctx.clearRect(0, 0, w, h);
70
+ if (life <= 0 || life >= 1)
71
+ return;
72
+ const minDim = Math.min(w, h);
73
+ const count = Math.max(0, Math.min(MAX_PIECES, Math.round(params.pieceCount)));
74
+ const rng = mulberry32(((params.pieceSeed * 1000) >>> 0) + 1);
75
+ const style = params.style;
76
+ ctx.save();
77
+ ctx.globalCompositeOperation = "lighter"; // additive accumulation, like the shader's `col +=`
78
+ for (let i = 0; i < count; i++) {
79
+ // Five per-piece randoms in a fixed order (≈ the GLSL hash21/hash11 draws).
80
+ const hx = rng(), hy = rng(), h2x = rng(), h2y = rng(), h3 = rng();
81
+ // Spawn stagger: most pieces fire in the first ~12%, renormalized to a full arc.
82
+ const delay = h2x * 0.12;
83
+ const pl = clamp01((life - delay) / (1 - delay));
84
+ if (pl <= 0 || pl >= 1)
85
+ continue;
86
+ // Launch direction (y-up local frame): a mostly-up cone fanned by spread.
87
+ const fan = (hx - 0.5) * 2;
88
+ const dlen = Math.hypot(fan * (0.35 + params.spread), 1.0);
89
+ const dirx = (fan * (0.35 + params.spread)) / dlen;
90
+ const diry = 1.0 / dlen;
91
+ const speed = (0.85 + hy * 0.6) * params.launchSpeed * minDim * 1.15;
92
+ const grav = (0.9 + h3 * 0.4) * params.gravity * minDim * 1.5;
93
+ // Ballistic arc: up, then down under gravity (y-up).
94
+ let px = dirx * speed * pl;
95
+ let py = diry * speed * pl - grav * pl * pl;
96
+ // Air-drag flutter: a growing sideways sway as the piece slows + falls.
97
+ const swayPhase = hx * TAU + h2y * 3.0;
98
+ const swayFreq = 3.0 + h2x * 4.0;
99
+ const fallT = smoothstep(0.12, 0.7, pl);
100
+ const swayAmp = params.flutter * minDim * 0.06 * (0.4 + fallT);
101
+ const sway = Math.sin(pl * swayFreq + swayPhase) * swayAmp +
102
+ Math.sin(pl * swayFreq * 0.37 + swayPhase * 1.7) * swayAmp * 0.4;
103
+ px += sway;
104
+ // Spin + face-flash (wide/bright face-on, dim edge-on).
105
+ const spinRate = (3.0 + h3 * 6.0) * params.spin;
106
+ const rot = pl * spinRate * TAU + swayPhase;
107
+ const flip = Math.abs(Math.cos(rot * 0.5 + sway * 0.02));
108
+ const face = mix(0.18, 1.0, flip);
109
+ // Paper shape: rectangles + a few petals, foreshortened by the face angle.
110
+ const aspect = mix(0.5, 1.6, h2y);
111
+ const s = minDim * 0.011 * params.pieceSize * (0.7 + hy * 0.7);
112
+ const fore = mix(1.0, face, 0.65);
113
+ const heX = Math.max(s * aspect * fore, 0.5);
114
+ const heY = Math.max(s * fore, 0.5);
115
+ const hue = fract(h2y * 0.9 + h3 * 0.31);
116
+ const petal = h3 >= 0.78;
117
+ // Per-piece lit colour (paper shading ↔ flat cel), pre-multiplied by fade.
118
+ const base = paletteMix(params.palette, hue);
119
+ const shade = mix(0.45, 1.15, face);
120
+ const spec = smoothstep(0.85, 1.0, face) * 0.5;
121
+ const celK = face >= 0.5 ? 1 : 0;
122
+ const celShade = mix(0.55, 1.1, celK);
123
+ const fade = (1 - Math.pow(pl, 1.4)) * smoothstep(0.0, 0.08, pl);
124
+ const lit = (c) => {
125
+ const paper = c * shade + spec;
126
+ const cel = c * celShade;
127
+ return clamp01(mix(paper, cel, style)) * fade;
128
+ };
129
+ const r = Math.round(lit(base.r) * 255);
130
+ const g = Math.round(lit(base.g) * 255);
131
+ const bl = Math.round(lit(base.b) * 255);
132
+ if (r + g + bl <= 0)
133
+ continue;
134
+ // Place in canvas space (flip y: local y-up → canvas y-down).
135
+ const cx = center.x + px;
136
+ const cy = center.y - py;
137
+ ctx.save();
138
+ ctx.translate(cx, cy);
139
+ ctx.rotate(rot);
140
+ ctx.fillStyle = `rgb(${r},${g},${bl})`;
141
+ if (petal) {
142
+ ctx.beginPath();
143
+ ctx.ellipse(0, 0, heX * 1.05, heY * 1.05, 0, 0, TAU);
144
+ ctx.fill();
145
+ }
146
+ else {
147
+ const rad = Math.min(heX, heY) * 0.5;
148
+ ctx.beginPath();
149
+ ctx.roundRect(-heX, -heY, heX * 2, heY * 2, rad);
150
+ ctx.fill();
151
+ }
152
+ ctx.restore();
153
+ }
154
+ ctx.restore();
155
+ }
156
+ //# sourceMappingURL=confetti-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-renderer.js","sourceRoot":"","sources":["../src/confetti-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,UAAU,EAA4B,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAmBlD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACxB,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AACzE,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,MAAM,UAAU,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,CAAS,EAAU,EAAE;IAC/D,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,6EAA6E;AAC7E,SAAS,UAAU,CAAC,GAAU,EAAE,CAAS;IACvC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC;IACzB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACjF,CAAC;AAED;;;;;;;;GAQG;AACH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAc,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IACvE,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,MAAyC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACrG,CAAC,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAC/B,GAA6B,EAC7B,CAAS,EACT,CAAS,EACT,MAA4B,EAC5B,IAAY,EACZ,MAAgC;IAEhC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO;IAEnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAE3B,GAAG,CAAC,IAAI,EAAE,CAAC;IACX,GAAG,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAAC,oDAAoD;IAE9F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,4EAA4E;QAC5E,MAAM,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,GAAG,GAAG,EAAE,EAAE,GAAG,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC;QAEnE,iFAAiF;QACjF,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;QACzB,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACjD,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;YAAE,SAAS;QAEjC,0EAA0E;QAC1E,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;QACnD,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;QACxB,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;QACrE,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,GAAG,CAAC;QAE9D,qDAAqD;QACrD,IAAI,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;QAC3B,IAAI,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;QAE5C,wEAAwE;QACxE,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;QACvC,MAAM,QAAQ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;QACjC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;QAC/D,MAAM,IAAI,GACR,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC,GAAG,OAAO;YAC7C,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,CAAC,GAAG,OAAO,GAAG,GAAG,CAAC;QACnE,EAAE,IAAI,IAAI,CAAC;QAEX,wDAAwD;QACxD,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QAChD,MAAM,GAAG,GAAG,EAAE,GAAG,QAAQ,GAAG,GAAG,GAAG,SAAS,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAElC,2EAA2E;QAC3E,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,EAAE,IAAI,IAAI,CAAC;QAEzB,2EAA2E;QAC3E,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE;YAChC,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;YACzB,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;QAChD,CAAC,CAAC;QACF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;YAAE,SAAS;QAE9B,8DAA8D;QAC9D,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAEzB,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChB,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,SAAS,EAAE,CAAC;YAChB,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YACrD,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;YACrC,GAAG,CAAC,SAAS,EAAE,CAAC;YAChB,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YACjD,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC;QACD,GAAG,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * GLSL ES 3.00 source for Confetti (web, PANEL architecture).
3
+ *
4
+ * The paper pieces are rasterized into an offscreen Canvas2D panel each frame
5
+ * (see confetti-renderer.ts) — each piece's pose + lit colour computed ONCE in JS
6
+ * rather than re-derived at every pixel. This shader is now a cheap O(pixels)
7
+ * pass: it SAMPLES that panel and applies only the screen-space finish that wants
8
+ * to be procedural —
9
+ * - the global gain (envelope amp × exposure) + filmic ACES tonemap so dense
10
+ * bursts roll off gracefully on the screen-blend page,
11
+ * - the cel posterize / saturation punch toward the whimsy (cel) end,
12
+ * - an ordered dither to kill screen-blend banding,
13
+ * - and a cheap soft drop-shadow on the multiply pass (a ring-blurred sample of
14
+ * the panel's mass, offset toward the implied light).
15
+ *
16
+ * Why: the old single-pass design looped MAX_PIECES at every fragment
17
+ * (O(pixels × pieces)) which is fine on a GPU but crawls under software/ANGLE
18
+ * WebGL. Sampling a pre-rasterized panel makes the per-pixel cost independent of
19
+ * piece count. Mirrors the comic/heartburst hybrid effects. (The Swift/Metal
20
+ * confetti keeps its analytic GPU pass — this change is web-only; the .dope is
21
+ * unchanged across platforms.)
22
+ */
23
+ /**
24
+ * Max confetti pieces. Single source of truth: BOTH the panel renderer's loop
25
+ * bound and the integer-clamp const the `.dope` mapping references (passed to the
26
+ * loader as `MAX_PIECES`). Counts above this won't render.
27
+ */
28
+ export declare const MAX_PIECES = 120;
29
+ export declare const CONFETTI_VERTEX_SRC = "#version 300 es\nout vec2 vUv;\nvoid main() {\n // Single full-screen triangle from gl_VertexID \u2014 no vertex buffers needed.\n vec2 pos = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));\n vUv = pos;\n gl_Position = vec4(pos * 2.0 - 1.0, 0.0, 1.0);\n}";
30
+ export declare const CONFETTI_FRAGMENT_SRC = "#version 300 es\nprecision highp float;\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform sampler2D uPanel; // RGB = accumulated per-piece lit colour \u00D7 fade\nuniform vec2 uResolution; // device pixels\nuniform float uAmp; // envelope amplitude (peaks > 1) \u2014 overall brightness\nuniform float uTimeS; // elapsed seconds (snapped \"on twos\" with style)\nuniform float uExposure;\nuniform float uStyle; // 0..1 photoreal paper -> flat cel shapes\nuniform float uShadow; // 0 = light pass (screen), 1 = shadow pass (multiply)\nuniform vec2 uShadowOffset; // device-px offset of the cast silhouette\nuniform float uShadowSoft; // penumbra softness in device px (blur tap radius)\nuniform float uShadowStrength;// 0..1 max darkening of the multiply layer\nuniform vec3 uC0;\n\n\n#define TAU 6.28318530718\n\n\nfloat hash11(float p){ p = fract(p * 0.1031); p *= p + 33.33; p *= p + p; return fract(p); }\nvec2 hash21(float p){\n vec3 p3 = fract(vec3(p) * vec3(0.1031, 0.1030, 0.0973));\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\n\nvec3 tonemapACES(vec3 x){\n const float a = 2.51, b = 0.03, c = 2.43, d = 0.59, e = 0.14;\n return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0, 1.0);\n}\n\n\nvec3 ditherAdd(vec3 col, vec2 frag, float t, float fade){\n float dz = hash11(dot(frag, vec2(12.989, 78.233)) + t) - 0.5;\n return col + (dz / 255.0) * fade;\n}\n\n\nvoid main() {\n vec2 frag = vUv * uResolution;\n\n // ---- SHADOW pass (multiply layer) --------------------------------------\n // A cheap soft drop-shadow: ring-blur the panel's mass at a sample point pushed\n // against the light offset. White = no shadow; darker = cast silhouette.\n if (uShadow > 0.5) {\n vec2 px = 1.0 / uResolution;\n vec2 souv = vUv - uShadowOffset * px;\n float occ = 0.0;\n for (int i = 0; i < 8; i++) {\n float a = float(i) / 8.0 * TAU;\n vec2 o = vec2(cos(a), sin(a)) * uShadowSoft * px;\n vec2 tuv = souv + o;\n vec2 inb = step(vec2(0.0), tuv) * step(tuv, vec2(1.0));\n vec3 s = texture(uPanel, tuv).rgb;\n occ += (s.r + s.g + s.b) * (1.0 / 3.0) * inb.x * inb.y;\n }\n occ /= 8.0;\n float dark = clamp(occ * uAmp, 0.0, 1.0) * uShadowStrength;\n vec3 tint = mix(vec3(1.0), 0.6 + 0.4 * normalize(uC0 + 1e-3), 0.2);\n vec3 mul = mix(vec3(1.0), tint, dark);\n fragColor = vec4(mul, 1.0);\n return;\n }\n\n // ---- LIGHT pass --------------------------------------------------------\n // The panel already holds \u03A3(lit \u00D7 fade) per piece; apply the global gain, then\n // the same filmic + cel + dither finish the original single-pass shader did.\n vec3 col = texture(uPanel, vUv).rgb * (uAmp * uExposure) * 1.35;\n\n col = tonemapACES(col * 0.85);\n\n // Cel posterize at the whimsy end: punch saturation + quantize into hard bands.\n if (uStyle > 0.001) {\n float l = dot(col, vec3(0.299, 0.587, 0.114));\n vec3 neon = clamp(l + (col - l) * 1.5, 0.0, 1.0);\n vec3 styled = mix(col, neon, 0.65);\n float bands = mix(40.0, 5.0, uStyle);\n styled = floor(styled * bands + 0.5) / bands;\n col = mix(col, styled, uStyle);\n }\n\n // Ordered dither to break screen-blend banding; faded toward the cel end.\n col = ditherAdd(col, frag, uTimeS, 1.0 - uStyle);\n\n fragColor = vec4(col, 1.0);\n}";
31
+ //# sourceMappingURL=confetti-shader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-shader.d.ts","sourceRoot":"","sources":["../src/confetti-shader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH;;;;GAIG;AACH,eAAO,MAAM,UAAU,MAAM,CAAC;AAE9B,eAAO,MAAM,mBAAmB,oRAO9B,CAAC;AAEH,eAAO,MAAM,qBAAqB,mzGAqEhC,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * GLSL ES 3.00 source for Confetti (web, PANEL architecture).
3
+ *
4
+ * The paper pieces are rasterized into an offscreen Canvas2D panel each frame
5
+ * (see confetti-renderer.ts) — each piece's pose + lit colour computed ONCE in JS
6
+ * rather than re-derived at every pixel. This shader is now a cheap O(pixels)
7
+ * pass: it SAMPLES that panel and applies only the screen-space finish that wants
8
+ * to be procedural —
9
+ * - the global gain (envelope amp × exposure) + filmic ACES tonemap so dense
10
+ * bursts roll off gracefully on the screen-blend page,
11
+ * - the cel posterize / saturation punch toward the whimsy (cel) end,
12
+ * - an ordered dither to kill screen-blend banding,
13
+ * - and a cheap soft drop-shadow on the multiply pass (a ring-blurred sample of
14
+ * the panel's mass, offset toward the implied light).
15
+ *
16
+ * Why: the old single-pass design looped MAX_PIECES at every fragment
17
+ * (O(pixels × pieces)) which is fine on a GPU but crawls under software/ANGLE
18
+ * WebGL. Sampling a pre-rasterized panel makes the per-pixel cost independent of
19
+ * piece count. Mirrors the comic/heartburst hybrid effects. (The Swift/Metal
20
+ * confetti keeps its analytic GPU pass — this change is web-only; the .dope is
21
+ * unchanged across platforms.)
22
+ */
23
+ import { GLSL_CONSTANTS, GLSL_DITHER, GLSL_HASH, GLSL_TONEMAP_ACES, } from "@dopaminefx/core";
24
+ /**
25
+ * Max confetti pieces. Single source of truth: BOTH the panel renderer's loop
26
+ * bound and the integer-clamp const the `.dope` mapping references (passed to the
27
+ * loader as `MAX_PIECES`). Counts above this won't render.
28
+ */
29
+ export const MAX_PIECES = 120;
30
+ export const CONFETTI_VERTEX_SRC = /* glsl */ `#version 300 es
31
+ out vec2 vUv;
32
+ void main() {
33
+ // Single full-screen triangle from gl_VertexID — no vertex buffers needed.
34
+ vec2 pos = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
35
+ vUv = pos;
36
+ gl_Position = vec4(pos * 2.0 - 1.0, 0.0, 1.0);
37
+ }`;
38
+ export const CONFETTI_FRAGMENT_SRC = /* glsl */ `#version 300 es
39
+ precision highp float;
40
+ in vec2 vUv;
41
+ out vec4 fragColor;
42
+
43
+ uniform sampler2D uPanel; // RGB = accumulated per-piece lit colour × fade
44
+ uniform vec2 uResolution; // device pixels
45
+ uniform float uAmp; // envelope amplitude (peaks > 1) — overall brightness
46
+ uniform float uTimeS; // elapsed seconds (snapped "on twos" with style)
47
+ uniform float uExposure;
48
+ uniform float uStyle; // 0..1 photoreal paper -> flat cel shapes
49
+ uniform float uShadow; // 0 = light pass (screen), 1 = shadow pass (multiply)
50
+ uniform vec2 uShadowOffset; // device-px offset of the cast silhouette
51
+ uniform float uShadowSoft; // penumbra softness in device px (blur tap radius)
52
+ uniform float uShadowStrength;// 0..1 max darkening of the multiply layer
53
+ uniform vec3 uC0;
54
+
55
+ ${GLSL_CONSTANTS}
56
+ ${GLSL_HASH}
57
+ ${GLSL_TONEMAP_ACES}
58
+ ${GLSL_DITHER}
59
+
60
+ void main() {
61
+ vec2 frag = vUv * uResolution;
62
+
63
+ // ---- SHADOW pass (multiply layer) --------------------------------------
64
+ // A cheap soft drop-shadow: ring-blur the panel's mass at a sample point pushed
65
+ // against the light offset. White = no shadow; darker = cast silhouette.
66
+ if (uShadow > 0.5) {
67
+ vec2 px = 1.0 / uResolution;
68
+ vec2 souv = vUv - uShadowOffset * px;
69
+ float occ = 0.0;
70
+ for (int i = 0; i < 8; i++) {
71
+ float a = float(i) / 8.0 * TAU;
72
+ vec2 o = vec2(cos(a), sin(a)) * uShadowSoft * px;
73
+ vec2 tuv = souv + o;
74
+ vec2 inb = step(vec2(0.0), tuv) * step(tuv, vec2(1.0));
75
+ vec3 s = texture(uPanel, tuv).rgb;
76
+ occ += (s.r + s.g + s.b) * (1.0 / 3.0) * inb.x * inb.y;
77
+ }
78
+ occ /= 8.0;
79
+ float dark = clamp(occ * uAmp, 0.0, 1.0) * uShadowStrength;
80
+ vec3 tint = mix(vec3(1.0), 0.6 + 0.4 * normalize(uC0 + 1e-3), 0.2);
81
+ vec3 mul = mix(vec3(1.0), tint, dark);
82
+ fragColor = vec4(mul, 1.0);
83
+ return;
84
+ }
85
+
86
+ // ---- LIGHT pass --------------------------------------------------------
87
+ // The panel already holds Σ(lit × fade) per piece; apply the global gain, then
88
+ // the same filmic + cel + dither finish the original single-pass shader did.
89
+ vec3 col = texture(uPanel, vUv).rgb * (uAmp * uExposure) * 1.35;
90
+
91
+ col = tonemapACES(col * 0.85);
92
+
93
+ // Cel posterize at the whimsy end: punch saturation + quantize into hard bands.
94
+ if (uStyle > 0.001) {
95
+ float l = dot(col, vec3(0.299, 0.587, 0.114));
96
+ vec3 neon = clamp(l + (col - l) * 1.5, 0.0, 1.0);
97
+ vec3 styled = mix(col, neon, 0.65);
98
+ float bands = mix(40.0, 5.0, uStyle);
99
+ styled = floor(styled * bands + 0.5) / bands;
100
+ col = mix(col, styled, uStyle);
101
+ }
102
+
103
+ // Ordered dither to break screen-blend banding; faded toward the cel end.
104
+ col = ditherAdd(col, frag, uTimeS, 1.0 - uStyle);
105
+
106
+ fragColor = vec4(col, 1.0);
107
+ }`;
108
+ //# sourceMappingURL=confetti-shader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-shader.js","sourceRoot":"","sources":["../src/confetti-shader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAE9B,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;;;;;;;EAO5C,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;EAiB9C,cAAc;EACd,SAAS;EACT,iBAAiB;EACjB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiDX,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Confetti's bespoke timing — the launch-then-fall amplitude envelope.
3
+ *
4
+ * Unlike the success effects' held-breath `envelope` (which decays from its
5
+ * early peak), confetti stays BRIGHT through the long fall — per-piece
6
+ * `particleFade` in the shader handles each piece dimming as it lands. So this
7
+ * is a sharp POP attack (overshoot at launch), a near-full sustain while
8
+ * everything falls, then a gentle fade only at the very end as the last pieces
9
+ * settle. Built on the generic `easeOutBack`/`easeOutCubic` primitives.
10
+ */
11
+ /** Confetti launch-then-fall amplitude over normalized life. Peak > 1 at launch. */
12
+ export declare function confettiAmp(life: number, overshoot: number): number;
13
+ //# sourceMappingURL=confetti-tempo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-tempo.d.ts","sourceRoot":"","sources":["../src/confetti-tempo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAYnE"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Confetti's bespoke timing — the launch-then-fall amplitude envelope.
3
+ *
4
+ * Unlike the success effects' held-breath `envelope` (which decays from its
5
+ * early peak), confetti stays BRIGHT through the long fall — per-piece
6
+ * `particleFade` in the shader handles each piece dimming as it lands. So this
7
+ * is a sharp POP attack (overshoot at launch), a near-full sustain while
8
+ * everything falls, then a gentle fade only at the very end as the last pieces
9
+ * settle. Built on the generic `easeOutBack`/`easeOutCubic` primitives.
10
+ */
11
+ import { easeOutBack, easeOutCubic } from "@dopaminefx/core";
12
+ /** Confetti launch-then-fall amplitude over normalized life. Peak > 1 at launch. */
13
+ export function confettiAmp(life, overshoot) {
14
+ if (life <= 0 || life >= 1)
15
+ return 0;
16
+ const attack = 0.12;
17
+ if (life < attack) {
18
+ // Sharp pop with a little overshoot (the burst leaving the action).
19
+ return easeOutBack(life / attack, overshoot);
20
+ }
21
+ // Long luminous sustain, then a soft fade over the last ~30% as pieces settle.
22
+ const tailStart = 0.7;
23
+ if (life < tailStart)
24
+ return 1;
25
+ const x = (life - tailStart) / (1 - tailStart);
26
+ return 1 - easeOutCubic(x) * 0.85;
27
+ }
28
+ //# sourceMappingURL=confetti-tempo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confetti-tempo.js","sourceRoot":"","sources":["../src/confetti-tempo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7D,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,SAAiB;IACzD,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;QAClB,oEAAoE;QACpE,OAAO,WAAW,CAAC,IAAI,GAAG,MAAM,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;IACD,+EAA+E;IAC/E,MAAM,SAAS,GAAG,GAAG,CAAC;IACtB,IAAI,IAAI,GAAG,SAAS;QAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC"}