@quitscope/discord-welcomecard 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.
package/dist/index.js ADDED
@@ -0,0 +1,727 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-PZ5AY32C.js";
4
+
5
+ // src/constants.ts
6
+ var CARD_WIDTH = 1024;
7
+ var CARD_HEIGHT = 384;
8
+ var GIF_FRAMES = 30;
9
+ var GIF_DELAY_MS = 50;
10
+ var GIF_SCALE = 0.5;
11
+ var DEFAULT_OPTIONS = {
12
+ preset: "centered",
13
+ theme: "dark",
14
+ font: {},
15
+ animations: []
16
+ };
17
+
18
+ // src/assets/fonts/register.ts
19
+ import { GlobalFonts } from "@napi-rs/canvas";
20
+ import { fileURLToPath } from "url";
21
+ import { dirname, join } from "path";
22
+ import { existsSync } from "fs";
23
+ var here = dirname(fileURLToPath(import.meta.url));
24
+ var candidates = [
25
+ join(here, "Poppins-Bold.ttf"),
26
+ join(here, "assets", "fonts", "Poppins-Bold.ttf"),
27
+ join(here, "..", "src", "assets", "fonts", "Poppins-Bold.ttf")
28
+ ];
29
+ var fontPath = candidates.find(existsSync);
30
+ if (fontPath) {
31
+ GlobalFonts.registerFromPath(fontPath, "WelcomeCard");
32
+ }
33
+ var DEFAULT_FONT_FAMILY = "WelcomeCard";
34
+
35
+ // src/presets/centered.ts
36
+ var EDGE_PAD = 24;
37
+ var TOP_BASELINE = 36;
38
+ function resolvePosition(position, width, height) {
39
+ const pos = position === void 0 || position === "corner" ? "bottom-right" : position;
40
+ const [v, h] = pos === "center" ? ["center", "center"] : pos.split("-");
41
+ return {
42
+ x: h === "left" ? EDGE_PAD : h === "center" ? width / 2 : width - EDGE_PAD,
43
+ y: v === "top" ? TOP_BASELINE : v === "center" ? height / 2 : height - EDGE_PAD,
44
+ align: h
45
+ };
46
+ }
47
+ function centeredLayout(opts) {
48
+ const width = CARD_WIDTH;
49
+ const height = CARD_HEIGHT;
50
+ const accent = opts.theme === "dark" ? "#89b4fa" : "#1e66f5";
51
+ const bgColor = typeof opts.background === "string" && opts.background.startsWith("#") ? opts.background : opts.theme === "dark" ? "#1e1e2e" : "#eff1f5";
52
+ const textColor = opts.font.color ?? (opts.theme === "dark" ? "#ffffff" : "#11111b");
53
+ const family = opts.font.family ?? DEFAULT_FONT_FAMILY;
54
+ const avatarSize = 120;
55
+ const avatarY = 50;
56
+ return {
57
+ width,
58
+ height,
59
+ backgroundColor: bgColor,
60
+ background: typeof opts.background === "string" && opts.background.startsWith("#") ? void 0 : opts.background,
61
+ avatar: {
62
+ x: width / 2 - avatarSize / 2,
63
+ y: avatarY,
64
+ size: avatarSize,
65
+ ringColor: accent,
66
+ source: opts.avatar
67
+ },
68
+ username: {
69
+ text: opts.username ?? "",
70
+ x: width / 2,
71
+ y: avatarY + avatarSize + 60,
72
+ size: opts.font.size ?? 44,
73
+ color: textColor,
74
+ family,
75
+ align: "center"
76
+ },
77
+ subtitle: opts.subtitle ? {
78
+ text: opts.subtitle,
79
+ x: width / 2,
80
+ y: avatarY + avatarSize + 105,
81
+ size: 24,
82
+ color: textColor,
83
+ family,
84
+ align: "center"
85
+ } : void 0,
86
+ memberCount: opts.memberCount !== void 0 ? {
87
+ text: `MEMBER #${opts.memberCount}`,
88
+ // centered preset: everything centered by default, count included
89
+ ...resolvePosition(opts.memberCountPosition ?? "bottom-center", width, height),
90
+ size: 16,
91
+ color: textColor,
92
+ family
93
+ } : void 0
94
+ };
95
+ }
96
+
97
+ // src/presets/neon.ts
98
+ function neonLayout(opts) {
99
+ const base = centeredLayout(opts);
100
+ return {
101
+ ...base,
102
+ backgroundColor: opts.background?.startsWith("#") ? opts.background : "#0b0b1a",
103
+ avatar: { ...base.avatar, ringColor: "#00ffd5" },
104
+ username: { ...base.username, color: opts.font.color ?? "#00ffd5" }
105
+ };
106
+ }
107
+
108
+ // src/presets/minimal.ts
109
+ function minimalLayout(opts) {
110
+ const base = centeredLayout(opts);
111
+ return {
112
+ ...base,
113
+ backgroundColor: opts.background?.startsWith("#") ? opts.background : "#ffffff",
114
+ avatar: { ...base.avatar, ringColor: "#222222" },
115
+ username: { ...base.username, color: opts.font.color ?? "#111111" },
116
+ subtitle: base.subtitle ? { ...base.subtitle, color: "#555555" } : void 0
117
+ };
118
+ }
119
+
120
+ // src/presets/hero.ts
121
+ function heroLayout(opts) {
122
+ const base = centeredLayout(opts);
123
+ const avatarX = 60;
124
+ const textX = avatarX + base.avatar.size + 40;
125
+ return {
126
+ ...base,
127
+ backgroundColor: opts.background?.startsWith("#") ? opts.background : "#101830",
128
+ avatar: { ...base.avatar, x: avatarX, y: base.height / 2 - base.avatar.size / 2 },
129
+ username: { ...base.username, x: textX, y: base.height / 2 - 6, align: "left" },
130
+ subtitle: base.subtitle ? { ...base.subtitle, x: textX, y: base.height / 2 + 30, align: "left" } : void 0,
131
+ memberCount: base.memberCount ? (
132
+ // hero is asymmetric — default the count to the corner, not bottom-center
133
+ {
134
+ ...base.memberCount,
135
+ ...resolvePosition(opts.memberCountPosition ?? "bottom-right", base.width, base.height)
136
+ }
137
+ ) : void 0
138
+ };
139
+ }
140
+
141
+ // src/presets/index.ts
142
+ var PRESETS = {
143
+ centered: centeredLayout,
144
+ neon: neonLayout,
145
+ minimal: minimalLayout,
146
+ hero: heroLayout
147
+ };
148
+
149
+ // src/errors.ts
150
+ var WelcomeCardError = class extends Error {
151
+ constructor(message) {
152
+ super(message);
153
+ this.name = "WelcomeCardError";
154
+ }
155
+ };
156
+
157
+ // src/render/toPNG.ts
158
+ import { createCanvas as createCanvas2 } from "@napi-rs/canvas";
159
+
160
+ // src/render/layout.ts
161
+ function layout(opts) {
162
+ const fn = PRESETS[opts.preset];
163
+ if (!fn) {
164
+ throw new WelcomeCardError(
165
+ `Unknown preset "${opts.preset}". Allowed: ${Object.keys(PRESETS).join(", ")}`
166
+ );
167
+ }
168
+ return fn(opts);
169
+ }
170
+
171
+ // src/assets/loadImage.ts
172
+ import { loadImage, createCanvas } from "@napi-rs/canvas";
173
+ async function solidImage(color, w, h) {
174
+ const canvas = createCanvas(w, h);
175
+ const ctx = canvas.getContext("2d");
176
+ ctx.fillStyle = color;
177
+ ctx.fillRect(0, 0, w, h);
178
+ return loadImage(canvas.toBuffer("image/png"));
179
+ }
180
+ var cache = /* @__PURE__ */ new Map();
181
+ async function loadImageOrFallback(source, fallbackColor, w = 256, h = 256) {
182
+ if (source === void 0) return solidImage(fallbackColor, w, h);
183
+ const hit = cache.get(source);
184
+ if (hit) return hit;
185
+ try {
186
+ const img = await loadImage(source);
187
+ cache.set(source, img);
188
+ return img;
189
+ } catch {
190
+ return solidImage(fallbackColor, w, h);
191
+ }
192
+ }
193
+
194
+ // src/render/drawFrame.ts
195
+ var STATIC_FRAME = { textAlpha: 1, avatarGlow: 1, backgroundShift: 0 };
196
+ function drawText(ctx, box, alpha) {
197
+ ctx.save();
198
+ ctx.globalAlpha = alpha;
199
+ ctx.fillStyle = box.color;
200
+ ctx.textAlign = box.align;
201
+ ctx.textBaseline = "alphabetic";
202
+ ctx.font = `${box.size}px ${box.family}`;
203
+ ctx.fillText(box.text, box.x, box.y);
204
+ ctx.restore();
205
+ }
206
+ async function drawFrame(ctx, l, state) {
207
+ ctx.fillStyle = l.backgroundColor;
208
+ ctx.fillRect(0, 0, l.width, l.height);
209
+ if (l.background !== void 0) {
210
+ const bg = await loadImageOrFallback(l.background, l.backgroundColor, l.width, l.height);
211
+ ctx.drawImage(bg, 0, 0, l.width, l.height);
212
+ }
213
+ if (state.backgroundShift > 0) {
214
+ const x2 = (state.backgroundShift * 2 - 1) * l.width * 2;
215
+ const g = ctx.createLinearGradient(x2, 0, x2 + l.width, l.height);
216
+ g.addColorStop(0, "rgba(255,255,255,0)");
217
+ g.addColorStop(0.5, "rgba(255,255,255,0.10)");
218
+ g.addColorStop(1, "rgba(255,255,255,0)");
219
+ ctx.fillStyle = g;
220
+ ctx.fillRect(0, 0, l.width, l.height);
221
+ }
222
+ const { x, y, size, ringColor } = l.avatar;
223
+ const cx = x + size / 2;
224
+ const cy = y + size / 2;
225
+ ctx.save();
226
+ ctx.shadowColor = ringColor;
227
+ ctx.shadowBlur = 10 + state.avatarGlow * 25;
228
+ ctx.lineWidth = 6;
229
+ ctx.strokeStyle = ringColor;
230
+ ctx.beginPath();
231
+ ctx.arc(cx, cy, size / 2 + 3, 0, Math.PI * 2);
232
+ ctx.stroke();
233
+ ctx.restore();
234
+ const avatarImg = await loadImageOrFallback(l.avatar.source, ringColor, size, size);
235
+ ctx.save();
236
+ ctx.beginPath();
237
+ ctx.arc(cx, cy, size / 2, 0, Math.PI * 2);
238
+ ctx.clip();
239
+ ctx.drawImage(avatarImg, x, y, size, size);
240
+ ctx.restore();
241
+ drawText(ctx, l.username, state.textAlpha);
242
+ if (l.subtitle) drawText(ctx, l.subtitle, state.textAlpha);
243
+ if (l.memberCount) drawText(ctx, l.memberCount, state.textAlpha);
244
+ }
245
+
246
+ // src/render/toPNG.ts
247
+ async function renderPNG(opts) {
248
+ const l = layout(opts);
249
+ const canvas = createCanvas2(l.width, l.height);
250
+ const ctx = canvas.getContext("2d");
251
+ await drawFrame(ctx, l, STATIC_FRAME);
252
+ return canvas.toBuffer("image/png");
253
+ }
254
+
255
+ // src/render/toGIF.ts
256
+ import { createCanvas as createCanvas3 } from "@napi-rs/canvas";
257
+
258
+ // node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/dist/gifenc.esm.js
259
+ var gifenc_esm_exports = {};
260
+ __export(gifenc_esm_exports, {
261
+ GIFEncoder: () => ct,
262
+ applyPalette: () => nt,
263
+ default: () => Bt,
264
+ nearestColor: () => ot,
265
+ nearestColorIndex: () => W,
266
+ nearestColorIndexWithDistance: () => N,
267
+ prequantize: () => et,
268
+ quantize: () => H,
269
+ snapColorsToPalette: () => rt
270
+ });
271
+ var X = { signature: "GIF", version: "89a", trailer: 59, extensionIntroducer: 33, applicationExtensionLabel: 255, graphicControlExtensionLabel: 249, imageSeparator: 44, signatureSize: 3, versionSize: 3, globalColorTableFlagMask: 128, colorResolutionMask: 112, sortFlagMask: 8, globalColorTableSizeMask: 7, applicationIdentifierSize: 8, applicationAuthCodeSize: 3, disposalMethodMask: 28, userInputFlagMask: 2, transparentColorFlagMask: 1, localColorTableFlagMask: 128, interlaceFlagMask: 64, idSortFlagMask: 32, localColorTableSizeMask: 7 };
272
+ function F(t = 256) {
273
+ let e = 0, s = new Uint8Array(t);
274
+ return { get buffer() {
275
+ return s.buffer;
276
+ }, reset() {
277
+ e = 0;
278
+ }, bytesView() {
279
+ return s.subarray(0, e);
280
+ }, bytes() {
281
+ return s.slice(0, e);
282
+ }, writeByte(r) {
283
+ n(e + 1), s[e] = r, e++;
284
+ }, writeBytes(r, o = 0, i = r.length) {
285
+ n(e + i);
286
+ for (let c = 0; c < i; c++) s[e++] = r[c + o];
287
+ }, writeBytesView(r, o = 0, i = r.byteLength) {
288
+ n(e + i), s.set(r.subarray(o, o + i), e), e += i;
289
+ } };
290
+ function n(r) {
291
+ var o = s.length;
292
+ if (o >= r) return;
293
+ var i = 1024 * 1024;
294
+ r = Math.max(r, o * (o < i ? 2 : 1.125) >>> 0), o != 0 && (r = Math.max(r, 256));
295
+ let c = s;
296
+ s = new Uint8Array(r), e > 0 && s.set(c.subarray(0, e), 0);
297
+ }
298
+ }
299
+ var O = 12;
300
+ var J = 5003;
301
+ var lt = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535];
302
+ function at(t, e, s, n, r = F(512), o = new Uint8Array(256), i = new Int32Array(J), c = new Int32Array(J)) {
303
+ let x = i.length, a = Math.max(2, n);
304
+ o.fill(0), c.fill(0), i.fill(-1);
305
+ let l = 0, f = 0, g = a + 1, h = g, b = false, w = h, _ = (1 << w) - 1, u = 1 << g - 1, k = u + 1, B = u + 2, p = 0, A = s[0], z = 0;
306
+ for (let y = x; y < 65536; y *= 2) ++z;
307
+ z = 8 - z, r.writeByte(a), I(u);
308
+ let d = s.length;
309
+ for (let y = 1; y < d; y++) {
310
+ t: {
311
+ let m = s[y], v = (m << O) + A, M = m << z ^ A;
312
+ if (i[M] === v) {
313
+ A = c[M];
314
+ break t;
315
+ }
316
+ let V = M === 0 ? 1 : x - M;
317
+ for (; i[M] >= 0; ) if (M -= V, M < 0 && (M += x), i[M] === v) {
318
+ A = c[M];
319
+ break t;
320
+ }
321
+ I(A), A = m, B < 1 << O ? (c[M] = B++, i[M] = v) : (i.fill(-1), B = u + 2, b = true, I(u));
322
+ }
323
+ }
324
+ return I(A), I(k), r.writeByte(0), r.bytesView();
325
+ function I(y) {
326
+ for (l &= lt[f], f > 0 ? l |= y << f : l = y, f += w; f >= 8; ) o[p++] = l & 255, p >= 254 && (r.writeByte(p), r.writeBytesView(o, 0, p), p = 0), l >>= 8, f -= 8;
327
+ if ((B > _ || b) && (b ? (w = h, _ = (1 << w) - 1, b = false) : (++w, _ = w === O ? 1 << w : (1 << w) - 1)), y == k) {
328
+ for (; f > 0; ) o[p++] = l & 255, p >= 254 && (r.writeByte(p), r.writeBytesView(o, 0, p), p = 0), l >>= 8, f -= 8;
329
+ p > 0 && (r.writeByte(p), r.writeBytesView(o, 0, p), p = 0);
330
+ }
331
+ }
332
+ }
333
+ var $ = at;
334
+ function D(t, e, s) {
335
+ return t << 8 & 63488 | e << 2 & 992 | s >> 3;
336
+ }
337
+ function G(t, e, s, n) {
338
+ return t >> 4 | e & 240 | (s & 240) << 4 | (n & 240) << 8;
339
+ }
340
+ function j(t, e, s) {
341
+ return t >> 4 << 8 | e & 240 | s >> 4;
342
+ }
343
+ function R(t, e, s) {
344
+ return t < e ? e : t > s ? s : t;
345
+ }
346
+ function T(t) {
347
+ return t * t;
348
+ }
349
+ function tt(t, e, s) {
350
+ var n = 0, r = 1e100;
351
+ let o = t[e], i = o.cnt, c = o.ac, x = o.rc, a = o.gc, l = o.bc;
352
+ for (var f = o.fw; f != 0; f = t[f].fw) {
353
+ let h = t[f], b = h.cnt, w = i * b / (i + b);
354
+ if (!(w >= r)) {
355
+ var g = 0;
356
+ s && (g += w * T(h.ac - c), g >= r) || (g += w * T(h.rc - x), !(g >= r) && (g += w * T(h.gc - a), !(g >= r) && (g += w * T(h.bc - l), !(g >= r) && (r = g, n = f))));
357
+ }
358
+ }
359
+ o.err = r, o.nn = n;
360
+ }
361
+ function Q() {
362
+ return { ac: 0, rc: 0, gc: 0, bc: 0, cnt: 0, nn: 0, fw: 0, bk: 0, tm: 0, mtm: 0, err: 0 };
363
+ }
364
+ function ut(t, e) {
365
+ let s = e === "rgb444" ? 4096 : 65536, n = new Array(s), r = t.length;
366
+ if (e === "rgba4444") for (let o = 0; o < r; ++o) {
367
+ let i = t[o], c = i >> 24 & 255, x = i >> 16 & 255, a = i >> 8 & 255, l = i & 255, f = G(l, a, x, c), g = f in n ? n[f] : n[f] = Q();
368
+ g.rc += l, g.gc += a, g.bc += x, g.ac += c, g.cnt++;
369
+ }
370
+ else if (e === "rgb444") for (let o = 0; o < r; ++o) {
371
+ let i = t[o], c = i >> 16 & 255, x = i >> 8 & 255, a = i & 255, l = j(a, x, c), f = l in n ? n[l] : n[l] = Q();
372
+ f.rc += a, f.gc += x, f.bc += c, f.cnt++;
373
+ }
374
+ else for (let o = 0; o < r; ++o) {
375
+ let i = t[o], c = i >> 16 & 255, x = i >> 8 & 255, a = i & 255, l = D(a, x, c), f = l in n ? n[l] : n[l] = Q();
376
+ f.rc += a, f.gc += x, f.bc += c, f.cnt++;
377
+ }
378
+ return n;
379
+ }
380
+ function H(t, e, s = {}) {
381
+ let { format: n = "rgb565", clearAlpha: r = true, clearAlphaColor: o = 0, clearAlphaThreshold: i = 0, oneBitAlpha: c = false } = s;
382
+ if (!t || !t.buffer) throw new Error("quantize() expected RGBA Uint8Array data");
383
+ if (!(t instanceof Uint8Array) && !(t instanceof Uint8ClampedArray)) throw new Error("quantize() expected RGBA Uint8Array data");
384
+ let x = new Uint32Array(t.buffer), a = s.useSqrt !== false, l = n === "rgba4444", f = ut(x, n), g = f.length, h = g - 1, b = new Uint32Array(g + 1);
385
+ for (var w = 0, u = 0; u < g; ++u) {
386
+ let C = f[u];
387
+ if (C != null) {
388
+ var _ = 1 / C.cnt;
389
+ l && (C.ac *= _), C.rc *= _, C.gc *= _, C.bc *= _, f[w++] = C;
390
+ }
391
+ }
392
+ T(e) / w < 0.022 && (a = false);
393
+ for (var u = 0; u < w - 1; ++u) f[u].fw = u + 1, f[u + 1].bk = u, a && (f[u].cnt = Math.sqrt(f[u].cnt));
394
+ a && (f[u].cnt = Math.sqrt(f[u].cnt));
395
+ var k, B, p;
396
+ for (u = 0; u < w; ++u) {
397
+ tt(f, u, false);
398
+ var A = f[u].err;
399
+ for (B = ++b[0]; B > 1 && (p = B >> 1, !(f[k = b[p]].err <= A)); B = p) b[B] = k;
400
+ b[B] = u;
401
+ }
402
+ var z = w - e;
403
+ for (u = 0; u < z; ) {
404
+ for (var d; ; ) {
405
+ var I = b[1];
406
+ if (d = f[I], d.tm >= d.mtm && f[d.nn].mtm <= d.tm) break;
407
+ d.mtm == h ? I = b[1] = b[b[0]--] : (tt(f, I, false), d.tm = u);
408
+ var A = f[I].err;
409
+ for (B = 1; (p = B + B) <= b[0] && (p < b[0] && f[b[p]].err > f[b[p + 1]].err && p++, !(A <= f[k = b[p]].err)); B = p) b[B] = k;
410
+ b[B] = I;
411
+ }
412
+ var y = f[d.nn], m = d.cnt, v = y.cnt, _ = 1 / (m + v);
413
+ l && (d.ac = _ * (m * d.ac + v * y.ac)), d.rc = _ * (m * d.rc + v * y.rc), d.gc = _ * (m * d.gc + v * y.gc), d.bc = _ * (m * d.bc + v * y.bc), d.cnt += y.cnt, d.mtm = ++u, f[y.bk].fw = y.fw, f[y.fw].bk = y.bk, y.mtm = h;
414
+ }
415
+ let M = [];
416
+ var V = 0;
417
+ for (u = 0; ; ++V) {
418
+ let L = R(Math.round(f[u].rc), 0, 255), C = R(Math.round(f[u].gc), 0, 255), Y = R(Math.round(f[u].bc), 0, 255), E = 255;
419
+ if (l) {
420
+ if (E = R(Math.round(f[u].ac), 0, 255), c) {
421
+ let st = typeof c == "number" ? c : 127;
422
+ E = E <= st ? 0 : 255;
423
+ }
424
+ r && E <= i && (L = C = Y = o, E = 0);
425
+ }
426
+ let K = l ? [L, C, Y, E] : [L, C, Y];
427
+ if (xt(M, K) || M.push(K), (u = f[u].fw) == 0) break;
428
+ }
429
+ return M;
430
+ }
431
+ function xt(t, e) {
432
+ for (let s = 0; s < t.length; s++) {
433
+ let n = t[s], r = n[0] === e[0] && n[1] === e[1] && n[2] === e[2], o = n.length >= 4 && e.length >= 4 ? n[3] === e[3] : true;
434
+ if (r && o) return true;
435
+ }
436
+ return false;
437
+ }
438
+ function U(t, e) {
439
+ var s = 0, n;
440
+ for (n = 0; n < t.length; n++) {
441
+ let r = t[n] - e[n];
442
+ s += r * r;
443
+ }
444
+ return s;
445
+ }
446
+ function P(t, e) {
447
+ return e > 1 ? Math.round(t / e) * e : t;
448
+ }
449
+ function et(t, { roundRGB: e = 5, roundAlpha: s = 10, oneBitAlpha: n = null } = {}) {
450
+ let r = new Uint32Array(t.buffer);
451
+ for (let o = 0; o < r.length; o++) {
452
+ let i = r[o], c = i >> 24 & 255, x = i >> 16 & 255, a = i >> 8 & 255, l = i & 255;
453
+ if (c = P(c, s), n) {
454
+ let f = typeof n == "number" ? n : 127;
455
+ c = c <= f ? 0 : 255;
456
+ }
457
+ l = P(l, e), a = P(a, e), x = P(x, e), r[o] = c << 24 | x << 16 | a << 8 | l << 0;
458
+ }
459
+ }
460
+ function nt(t, e, s = "rgb565") {
461
+ if (!t || !t.buffer) throw new Error("quantize() expected RGBA Uint8Array data");
462
+ if (!(t instanceof Uint8Array) && !(t instanceof Uint8ClampedArray)) throw new Error("quantize() expected RGBA Uint8Array data");
463
+ if (e.length > 256) throw new Error("applyPalette() only works with 256 colors or less");
464
+ let n = new Uint32Array(t.buffer), r = n.length, o = s === "rgb444" ? 4096 : 65536, i = new Uint8Array(r), c = new Array(o), x = s === "rgba4444";
465
+ if (s === "rgba4444") for (let a = 0; a < r; a++) {
466
+ let l = n[a], f = l >> 24 & 255, g = l >> 16 & 255, h = l >> 8 & 255, b = l & 255, w = G(b, h, g, f), _ = w in c ? c[w] : c[w] = gt(b, h, g, f, e);
467
+ i[a] = _;
468
+ }
469
+ else {
470
+ let a = s === "rgb444" ? j : D;
471
+ for (let l = 0; l < r; l++) {
472
+ let f = n[l], g = f >> 16 & 255, h = f >> 8 & 255, b = f & 255, w = a(b, h, g), _ = w in c ? c[w] : c[w] = bt(b, h, g, e);
473
+ i[l] = _;
474
+ }
475
+ }
476
+ return i;
477
+ }
478
+ function gt(t, e, s, n, r) {
479
+ let o = 0, i = 1e100;
480
+ for (let c = 0; c < r.length; c++) {
481
+ let x = r[c], a = x[3], l = q(a - n);
482
+ if (l > i) continue;
483
+ let f = x[0];
484
+ if (l += q(f - t), l > i) continue;
485
+ let g = x[1];
486
+ if (l += q(g - e), l > i) continue;
487
+ let h = x[2];
488
+ l += q(h - s), !(l > i) && (i = l, o = c);
489
+ }
490
+ return o;
491
+ }
492
+ function bt(t, e, s, n) {
493
+ let r = 0, o = 1e100;
494
+ for (let i = 0; i < n.length; i++) {
495
+ let c = n[i], x = c[0], a = q(x - t);
496
+ if (a > o) continue;
497
+ let l = c[1];
498
+ if (a += q(l - e), a > o) continue;
499
+ let f = c[2];
500
+ a += q(f - s), !(a > o) && (o = a, r = i);
501
+ }
502
+ return r;
503
+ }
504
+ function rt(t, e, s = 5) {
505
+ if (!t.length || !e.length) return;
506
+ let n = t.map((i) => i.slice(0, 3)), r = s * s, o = t[0].length;
507
+ for (let i = 0; i < e.length; i++) {
508
+ let c = e[i];
509
+ c.length < o ? c = [c[0], c[1], c[2], 255] : c.length > o ? c = c.slice(0, 3) : c = c.slice();
510
+ let x = N(n, c.slice(0, 3), U), a = x[0], l = x[1];
511
+ l > 0 && l <= r && (t[a] = c);
512
+ }
513
+ }
514
+ function q(t) {
515
+ return t * t;
516
+ }
517
+ function W(t, e, s = U) {
518
+ let n = Infinity, r = -1;
519
+ for (let o = 0; o < t.length; o++) {
520
+ let i = t[o], c = s(e, i);
521
+ c < n && (n = c, r = o);
522
+ }
523
+ return r;
524
+ }
525
+ function N(t, e, s = U) {
526
+ let n = Infinity, r = -1;
527
+ for (let o = 0; o < t.length; o++) {
528
+ let i = t[o], c = s(e, i);
529
+ c < n && (n = c, r = o);
530
+ }
531
+ return [r, n];
532
+ }
533
+ function ot(t, e, s = U) {
534
+ return t[W(t, e, s)];
535
+ }
536
+ function ct(t = {}) {
537
+ let { initialCapacity: e = 4096, auto: s = true } = t, n = F(e), r = 5003, o = new Uint8Array(256), i = new Int32Array(r), c = new Int32Array(r), x = false;
538
+ return { reset() {
539
+ n.reset(), x = false;
540
+ }, finish() {
541
+ n.writeByte(X.trailer);
542
+ }, bytes() {
543
+ return n.bytes();
544
+ }, bytesView() {
545
+ return n.bytesView();
546
+ }, get buffer() {
547
+ return n.buffer;
548
+ }, get stream() {
549
+ return n;
550
+ }, writeHeader: a, writeFrame(l, f, g, h = {}) {
551
+ let { transparent: b = false, transparentIndex: w = 0, delay: _ = 0, palette: u = null, repeat: k = 0, colorDepth: B = 8, dispose: p = -1 } = h, A = false;
552
+ if (s ? x || (A = true, a(), x = true) : A = Boolean(h.first), f = Math.max(0, Math.floor(f)), g = Math.max(0, Math.floor(g)), A) {
553
+ if (!u) throw new Error("First frame must include a { palette } option");
554
+ pt(n, f, g, u, B), it(n, u), k >= 0 && dt(n, k);
555
+ }
556
+ let z = Math.round(_ / 10);
557
+ wt(n, p, z, b, w);
558
+ let d = Boolean(u) && !A;
559
+ ht(n, f, g, d ? u : null), d && it(n, u), yt(n, l, f, g, B, o, i, c);
560
+ } };
561
+ function a() {
562
+ ft(n, "GIF89a");
563
+ }
564
+ }
565
+ function wt(t, e, s, n, r) {
566
+ t.writeByte(33), t.writeByte(249), t.writeByte(4), r < 0 && (r = 0, n = false);
567
+ var o, i;
568
+ n ? (o = 1, i = 2) : (o = 0, i = 0), e >= 0 && (i = e & 7), i <<= 2;
569
+ let c = 0;
570
+ t.writeByte(0 | i | c | o), S(t, s), t.writeByte(r || 0), t.writeByte(0);
571
+ }
572
+ function pt(t, e, s, n, r = 8) {
573
+ let o = 1, i = 0, c = Z(n.length) - 1, x = o << 7 | r - 1 << 4 | i << 3 | c, a = 0, l = 0;
574
+ S(t, e), S(t, s), t.writeBytes([x, a, l]);
575
+ }
576
+ function dt(t, e) {
577
+ t.writeByte(33), t.writeByte(255), t.writeByte(11), ft(t, "NETSCAPE2.0"), t.writeByte(3), t.writeByte(1), S(t, e), t.writeByte(0);
578
+ }
579
+ function it(t, e) {
580
+ let s = 1 << Z(e.length);
581
+ for (let n = 0; n < s; n++) {
582
+ let r = [0, 0, 0];
583
+ n < e.length && (r = e[n]), t.writeByte(r[0]), t.writeByte(r[1]), t.writeByte(r[2]);
584
+ }
585
+ }
586
+ function ht(t, e, s, n) {
587
+ if (t.writeByte(44), S(t, 0), S(t, 0), S(t, e), S(t, s), n) {
588
+ let r = 0, o = 0, i = Z(n.length) - 1;
589
+ t.writeByte(128 | r | o | 0 | i);
590
+ } else t.writeByte(0);
591
+ }
592
+ function yt(t, e, s, n, r = 8, o, i, c) {
593
+ $(s, n, e, r, t, o, i, c);
594
+ }
595
+ function S(t, e) {
596
+ t.writeByte(e & 255), t.writeByte(e >> 8 & 255);
597
+ }
598
+ function ft(t, e) {
599
+ for (var s = 0; s < e.length; s++) t.writeByte(e.charCodeAt(s));
600
+ }
601
+ function Z(t) {
602
+ return Math.max(Math.ceil(Math.log2(t)), 1);
603
+ }
604
+ var Bt = ct;
605
+
606
+ // src/animate/text.ts
607
+ function textAlpha(progress) {
608
+ const p = Math.min(progress / 0.7, 1);
609
+ return 1 - Math.pow(1 - p, 3);
610
+ }
611
+
612
+ // src/animate/avatar.ts
613
+ function avatarGlow(progress) {
614
+ return (Math.sin(progress * Math.PI * 2) + 1) / 2;
615
+ }
616
+
617
+ // src/animate/background.ts
618
+ function backgroundShift(progress) {
619
+ return progress;
620
+ }
621
+
622
+ // src/animate/index.ts
623
+ function frameStateFor(animations, progress) {
624
+ return {
625
+ textAlpha: animations.includes("text") ? textAlpha(progress) : 1,
626
+ avatarGlow: animations.includes("avatar") ? avatarGlow(progress) : 1,
627
+ backgroundShift: animations.includes("background") ? backgroundShift(progress) : 0
628
+ };
629
+ }
630
+
631
+ // src/render/toGIF.ts
632
+ var { GIFEncoder, quantize, applyPalette } = "GIFEncoder" in gifenc_esm_exports ? gifenc_esm_exports : Bt;
633
+ async function renderGIF(opts) {
634
+ const l = layout(opts);
635
+ const canvas = createCanvas3(l.width, l.height);
636
+ const ctx = canvas.getContext("2d");
637
+ const gw = Math.round(l.width * GIF_SCALE);
638
+ const gh = Math.round(l.height * GIF_SCALE);
639
+ const out = createCanvas3(gw, gh);
640
+ const outCtx = out.getContext("2d");
641
+ const enc = GIFEncoder();
642
+ const frames = opts.animations.length === 0 ? 1 : GIF_FRAMES;
643
+ let palette;
644
+ for (let i = 0; i < frames; i++) {
645
+ const progress = frames === 1 ? 0 : i / frames;
646
+ const state = frameStateFor(opts.animations, progress);
647
+ await drawFrame(ctx, l, state);
648
+ outCtx.drawImage(canvas, 0, 0, gw, gh);
649
+ const { data } = outCtx.getImageData(0, 0, gw, gh);
650
+ palette ??= quantize(data, 256);
651
+ const index = applyPalette(data, palette);
652
+ enc.writeFrame(index, gw, gh, { palette, delay: GIF_DELAY_MS });
653
+ }
654
+ enc.finish();
655
+ return Buffer.from(enc.bytes());
656
+ }
657
+
658
+ // src/WelcomeCard.ts
659
+ var WelcomeCard = class {
660
+ opts = { ...DEFAULT_OPTIONS, font: {}, animations: [] };
661
+ setPreset(preset) {
662
+ if (!PRESETS[preset]) {
663
+ throw new WelcomeCardError(
664
+ `Unknown preset "${preset}". Allowed: ${Object.keys(PRESETS).join(", ")}`
665
+ );
666
+ }
667
+ this.opts.preset = preset;
668
+ return this;
669
+ }
670
+ setUsername(username) {
671
+ this.opts.username = username;
672
+ return this;
673
+ }
674
+ setAvatar(avatar) {
675
+ this.opts.avatar = avatar;
676
+ return this;
677
+ }
678
+ setSubtitle(subtitle) {
679
+ this.opts.subtitle = subtitle;
680
+ return this;
681
+ }
682
+ setMemberCount(count) {
683
+ this.opts.memberCount = count;
684
+ return this;
685
+ }
686
+ setMemberCountPosition(position) {
687
+ this.opts.memberCountPosition = position;
688
+ return this;
689
+ }
690
+ setBackground(background) {
691
+ this.opts.background = background;
692
+ return this;
693
+ }
694
+ setTheme(theme) {
695
+ this.opts.theme = theme;
696
+ return this;
697
+ }
698
+ setFont(font) {
699
+ this.opts.font = { ...this.opts.font, ...font };
700
+ return this;
701
+ }
702
+ setAnimations(animations) {
703
+ this.opts.animations = animations;
704
+ return this;
705
+ }
706
+ validate() {
707
+ if (!this.opts.username) {
708
+ throw new WelcomeCardError("username is required \u2014 call .setUsername() before rendering.");
709
+ }
710
+ }
711
+ async toPNG() {
712
+ this.validate();
713
+ return renderPNG(this.opts);
714
+ }
715
+ async toGIF() {
716
+ this.validate();
717
+ if (this.opts.animations.length === 0) {
718
+ console.warn("[welcomecard] toGIF() called with no animations \u2014 output will be static.");
719
+ }
720
+ return renderGIF(this.opts);
721
+ }
722
+ };
723
+ export {
724
+ WelcomeCard,
725
+ WelcomeCardError
726
+ };
727
+ //# sourceMappingURL=index.js.map