{"version":3,"sources":["../src/engine.ts","../src/index.tsx"],"names":["colors","a","useRef","useMemo","useEffect","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Gradient engine for @outpacelabs/avatars.\n *\n * Framework-agnostic mesh-gradient avatar generator. Every seed (string or\n * number) deterministically produces a unique gradient, no stored images,\n * no network. Pure palette/RNG core plus optional Canvas2D render helpers.\n */\n\nexport type Harmony =\n\t| \"analogous\"\n\t| \"triadic\"\n\t| \"splitComplementary\"\n\t| \"tetradic\"\n\t| \"complementary\"\n\t/** Not a harmony rule, the palette came from caller-supplied `colors`. */\n\t| \"custom\";\n\nexport interface GradientPalette {\n\t/** The numeric seed the palette was derived from. */\n\tseed: number;\n\t/** Hex color stops used to paint the mesh (`#RRGGBB`). */\n\tcolors: string[];\n\t/** Which color-harmony rule produced the hues (or `\"custom\"`). */\n\tharmony: Harmony;\n}\n\nexport interface PaletteOptions {\n\t/**\n\t * Bring your own colors instead of the seed-derived harmony. Accepts hex\n\t * (`#rgb` or `#rrggbb`, `#` optional); invalid entries are dropped, and an\n\t * empty/absent list falls back to seed generation. The seed still drives the\n\t * layout and rotates the palette, so each seed stays unique but on-brand.\n\t */\n\tcolors?: string[];\n}\n\n/** Options shared by the Canvas2D renderers. */\nexport interface DrawOptions extends PaletteOptions {\n\t/**\n\t * Render in the Display P3 wide-gamut color space. On P3-capable screens the\n\t * palette reads more vivid; elsewhere the browser maps it back to sRGB.\n\t * Requires the target canvas to be a P3 context, the `renderGradient`,\n\t * `gradientTo*`, and `<GradientAvatar>` paths set this up for you.\n\t */\n\tp3?: boolean;\n\t/**\n\t * The size the avatar is shown at on screen, in CSS pixels. This drives the\n\t * level of detail: a small avatar gets fewer colors and fewer, larger shapes\n\t * so it reads as one clean mark, a large one gets the full complexity.\n\t *\n\t * Defaults to the `size` the renderer draws at, which is correct when the\n\t * canvas draws at its display size. Set it when the render resolution is\n\t * higher than the display size, for example when you draw at 256 px for a\n\t * 32 px avatar. `<GradientAvatar>` wires this from its `size` prop.\n\t */\n\tdisplaySize?: number;\n}\n\n/** The generated harmonies, everything except caller-supplied `\"custom\"`. */\ntype GeneratedHarmony = Exclude<Harmony, \"custom\">;\n\nconst HARMONY_TYPES: GeneratedHarmony[] = [\n\t\"analogous\",\n\t\"triadic\",\n\t\"splitComplementary\",\n\t\"tetradic\",\n\t\"complementary\",\n];\n\n// Golden-ratio conjugate, for golden-ratio hashing of the base hue. The\n// fraction of `s * this` is evenly spread across 0..1, so sequential seeds\n// fan out and hashed seeds keep full resolution. The old `(s * 137.5) % 360`\n// gave only 144 distinct hues, so different string seeds collided often.\nconst GOLDEN_RATIO_CONJUGATE = 0.618033988749895;\n\n/** Default blur radius as a fraction of the rendered dimension. */\nexport const DEFAULT_BLUR_FRACTION = 0.06;\n\nfunction seededRandom(seed: number): () => number {\n\tlet s = seed;\n\treturn () => {\n\t\ts += 0x6d2b79f5;\n\t\tlet t = s;\n\t\tt = Math.imul(t ^ (t >>> 15), t | 1);\n\t\tt ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n\t\treturn ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n\t};\n}\n\nfunction hslToHex(h: number, s: number, l: number): string {\n\th = ((h % 360) + 360) % 360;\n\ts = Math.max(0, Math.min(100, s)) / 100;\n\tl = Math.max(0, Math.min(100, l)) / 100;\n\n\tconst c = (1 - Math.abs(2 * l - 1)) * s;\n\tconst x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n\tconst m = l - c / 2;\n\n\tlet r = 0;\n\tlet g = 0;\n\tlet b = 0;\n\tif (h < 60) {\n\t\tr = c;\n\t\tg = x;\n\t} else if (h < 120) {\n\t\tr = x;\n\t\tg = c;\n\t} else if (h < 180) {\n\t\tg = c;\n\t\tb = x;\n\t} else if (h < 240) {\n\t\tg = x;\n\t\tb = c;\n\t} else if (h < 300) {\n\t\tr = x;\n\t\tb = c;\n\t} else {\n\t\tr = c;\n\t\tb = x;\n\t}\n\n\tconst toHex = (n: number) => {\n\t\tconst hex = Math.round((n + m) * 255).toString(16);\n\t\treturn hex.length === 1 ? `0${hex}` : hex;\n\t};\n\treturn `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();\n}\n\nfunction harmonyHues(baseHue: number, harmony: GeneratedHarmony): number[] {\n\tswitch (harmony) {\n\t\tcase \"analogous\":\n\t\t\treturn [baseHue, baseHue + 30, baseHue + 60, baseHue - 30];\n\t\tcase \"triadic\":\n\t\t\treturn [baseHue, baseHue + 120, baseHue + 240];\n\t\tcase \"splitComplementary\":\n\t\t\treturn [baseHue, baseHue + 150, baseHue + 210];\n\t\tcase \"tetradic\":\n\t\t\treturn [baseHue, baseHue + 90, baseHue + 180, baseHue + 270];\n\t\tcase \"complementary\":\n\t\t\treturn [baseHue, baseHue + 180, baseHue + 20, baseHue + 200];\n\t}\n}\n\n/**\n * Stable string → 32-bit unsigned hash (FNV-1a + bit-mixing avalanche).\n * Uses the full uint32 range as a seed so similar strings diverge fully.\n */\nexport function seedFromString(input: string): number {\n\tlet h = 2166136261 >>> 0;\n\tfor (let i = 0; i < input.length; i++) {\n\t\th ^= input.charCodeAt(i);\n\t\th = Math.imul(h, 16777619) >>> 0;\n\t}\n\th ^= h >>> 16;\n\th = Math.imul(h, 0x7feb352d) >>> 0;\n\th ^= h >>> 15;\n\th = Math.imul(h, 0x846ca68b) >>> 0;\n\th ^= h >>> 16;\n\treturn h >>> 0;\n}\n\n/** Normalize a string or number seed to the numeric seed used internally. */\nexport function toSeed(seed: number | string): number {\n\tif (typeof seed === \"number\") return seed;\n\treturn seedFromString(seed);\n}\n\n/** `#rgb`/`#rrggbb` (with or without `#`) → `#RRGGBB`, or null if invalid. */\nfunction normalizeHex(color: string): string | null {\n\tconst m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color.trim());\n\tif (!m) return null;\n\tlet h = m[1];\n\tif (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n\treturn `#${h.toUpperCase()}`;\n}\n\n/** Validate + normalize a caller-supplied palette, or null to fall back. */\nfunction normalizeColors(colors?: string[]): string[] | null {\n\tif (!colors?.length) return null;\n\tconst out: string[] = [];\n\tfor (const c of colors) {\n\t\tconst h = normalizeHex(c);\n\t\tif (h) out.push(h);\n\t}\n\treturn out.length ? out : null;\n}\n\n/**\n * Derive the deterministic color palette for a seed. Pass `colors` to override\n * the harmony with your own palette (still placed deterministically per seed).\n */\nexport function generatePalette(\n\tseed: number | string,\n\toptions: PaletteOptions = {},\n): GradientPalette {\n\tconst s = toSeed(seed);\n\tconst custom = normalizeColors(options.colors);\n\tif (custom) {\n\t\t// Rotate the palette by the seed so different seeds emphasize different\n\t\t// colors (colors[0] becomes the dominant base fill) while staying on-brand.\n\t\tconst offset = s % custom.length;\n\t\tconst colors = custom.map((_, i) => custom[(i + offset) % custom.length]);\n\t\treturn { seed: s, colors, harmony: \"custom\" };\n\t}\n\tconst random = seededRandom(s);\n\tconst baseHue = ((s * GOLDEN_RATIO_CONJUGATE) % 1) * 360;\n\tconst harmonyIndex = Math.floor(random() * HARMONY_TYPES.length);\n\tconst harmony = HARMONY_TYPES[harmonyIndex];\n\tconst hues = harmonyHues(baseHue, harmony);\n\tconst colors = hues.map((hue) => {\n\t\tconst saturation = 75 + random() * 25;\n\t\tconst lightness = 50 + random() * 20;\n\t\treturn hslToHex(hue, saturation, lightness);\n\t});\n\treturn { seed: s, colors, harmony };\n}\n\n/** `#RRGGBB` → [r, g, b] in 0–1. */\nfunction hexToRgb01(hex: string): [number, number, number] {\n\tconst n = Number.parseInt(hex.slice(1), 16);\n\treturn [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n}\n\n/**\n * A palette color at `alpha` (0–1) as a canvas fill string. In P3 mode the hex\n * components are emitted as `color(display-p3 …)`, on a P3 canvas this widens\n * into the P3 gamut (more vivid); off P3 it maps back to the same sRGB color.\n * Otherwise it's the familiar 8-digit hex, so the default output is unchanged.\n */\nfunction fill(hex: string, alpha: number, p3: boolean): string {\n\tif (p3) {\n\t\tconst [r, g, b] = hexToRgb01(hex);\n\t\tconst a = alpha >= 1 ? \"\" : ` / ${alpha}`;\n\t\treturn `color(display-p3 ${r.toFixed(4)} ${g.toFixed(4)} ${b.toFixed(4)}${a})`;\n\t}\n\tconst a = Math.round(alpha * 255)\n\t\t.toString(16)\n\t\t.padStart(2, \"0\")\n\t\t.toUpperCase();\n\treturn `${hex}${a}`;\n}\n\n/** Radial-spot falloff alphas, match the original 0xFF/DD/88/00 stops. */\nconst SPOT_ALPHAS = [1, 221 / 255, 136 / 255, 0];\n\n/* ── level of detail: complexity follows the display size ── */\n\n/**\n * Both engines pack the same amount of detail into every avatar, which is\n * right at 160 px and wrong at 24 px: four hues and a dozen soft spots average\n * out into one muddy blob, and dither cells below a screen pixel shimmer. So\n * the complexity ramps with the size the avatar is shown at. Same seed, same\n * palette order, same layout, just fewer and bigger parts when small.\n */\n\n/** At or below this display size (CSS px), draw the simplest version. */\nconst DETAIL_MIN_SIZE = 16;\n/** At or above this display size (CSS px), draw the full complexity. */\nconst DETAIL_FULL_SIZE = 160;\n/** Colors a simplified avatar keeps, the start of the seed's palette. */\nconst MIN_COLORS = 2;\n/** Mesh spots a simplified avatar keeps, the largest ones. */\nconst MIN_SPOTS = 4;\n/** How far the kept spots move toward the center at the smallest size. */\nconst CENTER_PULL = 0.15;\n/** How much the kept spots grow at the smallest size. */\nconst RADIUS_BOOST = 0.2;\n/** A dither cell never gets smaller than this on screen (CSS px). */\nconst MIN_CELL_PX = 3;\n/** Dither cells across the frame, at the two ends of the ramp. */\nconst MIN_DITHER_CELLS = 8;\nconst MAX_DITHER_CELLS = 64;\n\n/**\n * How much complexity a display size can carry, 0 (tiny) to 1 (large).\n * The ramp is logarithmic because what the eye reads is the doubling of the\n * size, not the pixel count.\n */\nfunction detailFor(displaySize: number): number {\n\tif (!(displaySize > 0)) return 1;\n\tconst t =\n\t\tMath.log2(displaySize / DETAIL_MIN_SIZE) /\n\t\tMath.log2(DETAIL_FULL_SIZE / DETAIL_MIN_SIZE);\n\treturn Math.max(0, Math.min(1, t));\n}\n\n/**\n * The palette trimmed to the number of colors `detail` can carry. The kept\n * colors are the first ones, so a small avatar is the same avatar with its\n * later accent hues dropped, not a different one.\n */\nfunction paletteForDetail(colors: string[], detail: number): string[] {\n\tif (colors.length <= MIN_COLORS) return colors;\n\tconst n = Math.round(MIN_COLORS + detail * (colors.length - MIN_COLORS));\n\treturn colors.slice(0, Math.max(MIN_COLORS, Math.min(colors.length, n)));\n}\n\n/** Dither cells across the frame for a display size (cells stay visible). */\nfunction ditherCells(displaySize: number): number {\n\tconst byPixels = Math.floor(displaySize / MIN_CELL_PX);\n\treturn Math.max(MIN_DITHER_CELLS, Math.min(MAX_DITHER_CELLS, byPixels));\n}\n\n/**\n * Minimal Canvas2D context surface the renderer needs. Both\n * `HTMLCanvasElement` and `OffscreenCanvas` 2D contexts satisfy it.\n */\nexport type GradientContext = {\n\tfillStyle: string | CanvasGradient | CanvasPattern;\n\tglobalCompositeOperation: GlobalCompositeOperation;\n\tfillRect(x: number, y: number, w: number, h: number): void;\n\tcreateRadialGradient(\n\t\tx0: number,\n\t\ty0: number,\n\t\tr0: number,\n\t\tx1: number,\n\t\ty1: number,\n\t\tr1: number,\n\t): CanvasGradient;\n};\n\n/**\n * Draw the mesh gradient for `seed` into `ctx` at `size` x `size`.\n * The caller is responsible for any blur, apply `filter: blur(…)` on the\n * displayed canvas (≈6% of the rendered dimension) for the signature look,\n * or use {@link renderGradient} / {@link gradientToDataURL} which bake it in.\n */\nexport function drawMeshGradient(\n\tctx: GradientContext,\n\tseed: number | string,\n\tsize: number,\n\toptions: DrawOptions = {},\n): void {\n\tconst s = toSeed(seed);\n\tconst { colors } = generatePalette(s, options);\n\tconst p3 = options.p3 ?? false;\n\tconst detail = detailFor(options.displaySize ?? size);\n\tconst palette = paletteForDetail(colors, detail);\n\tconst random = seededRandom(s * 12345);\n\n\tctx.fillStyle = fill(palette[0], 1, p3);\n\tctx.fillRect(0, 0, size, size);\n\n\tconst numSpots = 8 + Math.floor(random() * 5);\n\tconst spots: Array<{ x: number; y: number; radius: number; color: string }> =\n\t\t[];\n\n\tfor (let i = 0; i < numSpots; i++) {\n\t\tconst angle = random() * Math.PI * 2;\n\t\tconst distance = random() * size * 0.4;\n\t\tconst centerX = size / 2 + Math.cos(angle) * distance;\n\t\tconst centerY = size / 2 + Math.sin(angle) * distance;\n\t\tspots.push({\n\t\t\tx: centerX + (random() - 0.5) * size * 0.3,\n\t\t\ty: centerY + (random() - 0.5) * size * 0.3,\n\t\t\tradius: size * (0.3 + random() * 0.4),\n\t\t\tcolor: palette[i % palette.length],\n\t\t});\n\t}\n\n\tspots.sort((a, b) => b.radius - a.radius);\n\n\t// Level of detail. The spots are already sorted largest first, so a small\n\t// avatar keeps the shapes that carry the composition and drops the fine\n\t// ones. The survivors then grow and pull toward the center, which fills\n\t// the frame the dropped spots used to cover.\n\tconst keep = Math.max(\n\t\tMIN_SPOTS,\n\t\tMath.round(MIN_SPOTS + detail * (numSpots - MIN_SPOTS)),\n\t);\n\tconst spread = 1 - (1 - detail) * CENTER_PULL;\n\tconst grow = 1 + (1 - detail) * RADIUS_BOOST;\n\tconst mid = size / 2;\n\n\tctx.globalCompositeOperation = \"source-over\";\n\tfor (const raw of spots.slice(0, keep)) {\n\t\tconst spot = {\n\t\t\tx: mid + (raw.x - mid) * spread,\n\t\t\ty: mid + (raw.y - mid) * spread,\n\t\t\tradius: raw.radius * grow,\n\t\t\tcolor: raw.color,\n\t\t};\n\t\tconst g = ctx.createRadialGradient(\n\t\t\tspot.x,\n\t\t\tspot.y,\n\t\t\t0,\n\t\t\tspot.x,\n\t\t\tspot.y,\n\t\t\tspot.radius,\n\t\t);\n\t\tg.addColorStop(0, fill(spot.color, SPOT_ALPHAS[0], p3));\n\t\tg.addColorStop(0.3, fill(spot.color, SPOT_ALPHAS[1], p3));\n\t\tg.addColorStop(0.6, fill(spot.color, SPOT_ALPHAS[2], p3));\n\t\tg.addColorStop(1, fill(spot.color, SPOT_ALPHAS[3], p3));\n\t\tctx.fillStyle = g;\n\t\tctx.fillRect(0, 0, size, size);\n\t}\n\n\tconst hx = size * 0.3 + random() * size * 0.2;\n\tconst hy = size * 0.3 + random() * size * 0.2;\n\tconst hg = ctx.createRadialGradient(hx, hy, 0, hx, hy, size * 0.3);\n\thg.addColorStop(0, \"rgba(255,255,255,0.15)\");\n\thg.addColorStop(1, \"rgba(255,255,255,0)\");\n\tctx.fillStyle = hg;\n\tctx.fillRect(0, 0, size, size);\n}\n\n/** Which engine paints the avatar. */\nexport type Pattern = \"mesh\" | \"dither\";\n\n/* ── dither: ordered (Bayer 8×8) ramp of the palette along a fixed axis ── */\n\n/**\n * Every dither ramps along the same axis so the pattern reads as one\n * consistent family. A 45° diagonal (top-left → bottom-right).\n */\nconst DITHER_ANGLE = Math.PI / 4;\n\nfunction makeBayer(n: number): number[][] {\n\tlet m: number[][] = [[0]];\n\tfor (let k = 0; k < n; k++) {\n\t\tconst s = m.length;\n\t\tconst next: number[][] = Array.from({ length: s * 2 }, () => []);\n\t\tfor (let y = 0; y < s * 2; y++) {\n\t\t\tfor (let x = 0; x < s * 2; x++) {\n\t\t\t\tconst base = m[y % s][x % s] * 4;\n\t\t\t\tconst add = x < s ? (y < s ? 0 : 3) : y < s ? 2 : 1;\n\t\t\t\tnext[y][x] = base + add;\n\t\t\t}\n\t\t}\n\t\tm = next;\n\t}\n\tconst max = m.length * m.length;\n\treturn m.map((row) => row.map((v) => (v + 0.5) / max));\n}\n\nconst BAYER = makeBayer(3); // 8×8, thresholds in (0,1)\n\n/**\n * Draw an ordered (Bayer 8×8) dither of the seed's palette into `ctx` at\n * `size` x `size`. A crisp, retro alternative to {@link drawMeshGradient} that\n * shares the same deterministic colors, no blur wanted.\n */\nexport function drawDither(\n\tctx: GradientContext,\n\tseed: number | string,\n\tsize: number,\n\toptions: DrawOptions = {},\n): void {\n\tconst s = toSeed(seed);\n\tconst { colors } = generatePalette(s, options);\n\tconst p3 = options.p3 ?? false;\n\tconst display = options.displaySize ?? size;\n\t// Level of detail: fewer, chunkier cells and fewer bands when small, so the\n\t// cells stay above ~3 screen pixels instead of dissolving into noise.\n\tconst detail = detailFor(display);\n\tconst palette = paletteForDetail(colors, detail);\n\tconst n = ditherCells(display);\n\n\t// Shared gradient axis, normalized to 0..1 across the unit square, so every\n\t// dither ramps the same direction.\n\tconst dx = Math.cos(DITHER_ANGLE);\n\tconst dy = Math.sin(DITHER_ANGLE);\n\tconst min = Math.min(0, dx) + Math.min(0, dy);\n\tconst span = Math.abs(dx) + Math.abs(dy) || 1;\n\n\tfor (let gy = 0; gy < n; gy++) {\n\t\t// Cell edges are rounded off the exact grid, so the cells tile the\n\t\t// frame with no seam and no overlap at any cell count.\n\t\tconst y0 = Math.round((gy * size) / n);\n\t\tconst y1 = Math.round(((gy + 1) * size) / n);\n\t\tfor (let gx = 0; gx < n; gx++) {\n\t\t\tconst x0 = Math.round((gx * size) / n);\n\t\t\tconst x1 = Math.round(((gx + 1) * size) / n);\n\t\t\tconst px = (gx + 0.5) / n;\n\t\t\tconst py = (gy + 0.5) / n;\n\t\t\tconst v = (px * dx + py * dy - min) / span; // 0..1\n\t\t\tconst scaled = v * (palette.length - 1);\n\t\t\tconst idx = Math.floor(scaled);\n\t\t\tconst frac = scaled - idx;\n\t\t\tconst t = BAYER[gy % 8][gx % 8];\n\t\t\tconst ci = frac > t ? Math.min(idx + 1, palette.length - 1) : idx;\n\t\t\tctx.fillStyle = fill(palette[ci], 1, p3);\n\t\t\tctx.fillRect(x0, y0, x1 - x0, y1 - y0);\n\t\t}\n\t}\n}\n\nexport interface RenderOptions extends DrawOptions {\n\t/**\n\t * Blur radius in pixels. Defaults to ~6% of the canvas size for the\n\t * signature soft look. Pass `0` to disable. Ignored for the dither pattern,\n\t * which is always crisp.\n\t */\n\tblur?: number;\n\t/** Which engine to paint. Default: `\"mesh\"`. */\n\tpattern?: Pattern;\n}\n\n/** Get a 2D context in the requested color space (P3 when `p3`). */\nfunction get2d(\n\tcanvas: HTMLCanvasElement | OffscreenCanvas,\n\tp3?: boolean,\n): CanvasRenderingContext2D | null {\n\treturn canvas.getContext(\"2d\", {\n\t\tcolorSpace: p3 ? \"display-p3\" : \"srgb\",\n\t}) as CanvasRenderingContext2D | null;\n}\n\nfunction blurFor(size: number, blur?: number): number {\n\tif (blur === 0) return 0;\n\treturn blur ?? Math.round(size * DEFAULT_BLUR_FRACTION);\n}\n\n/**\n * Render a seed's gradient into an existing canvas, baking in the soft blur.\n * Draws at the canvas's current `width`/`height`. Browser/OffscreenCanvas only.\n */\nexport function renderGradient(\n\tcanvas: HTMLCanvasElement | OffscreenCanvas,\n\tseed: number | string,\n\toptions: RenderOptions = {},\n): void {\n\tconst size = canvas.width;\n\tconst blur = blurFor(size, options.blur);\n\n\tconst ctx = get2d(canvas, options.p3);\n\tif (!ctx) return;\n\n\t// The dither is always crisp, no blur bounce.\n\tif (options.pattern === \"dither\") {\n\t\tctx.clearRect(0, 0, size, size);\n\t\tdrawDither(ctx, seed, size, options);\n\t\treturn;\n\t}\n\n\tif (blur <= 0) {\n\t\tctx.clearRect(0, 0, size, size);\n\t\tdrawMeshGradient(ctx, seed, size, options);\n\t\treturn;\n\t}\n\n\t// Draw the raw mesh on a scratch canvas (same color space so the P3 gamut\n\t// survives the composite), then blur it back scaled up slightly so the soft\n\t// edges fall outside the frame (no ring).\n\tconst scratch = createCanvas(size, size);\n\tconst sctx = get2d(scratch, options.p3);\n\tif (!sctx) return;\n\tdrawMeshGradient(sctx, seed, size, options);\n\n\tconst scaleUp = 1 + (blur / size) * 4;\n\tconst dw = size * scaleUp;\n\tconst offset = (dw - size) / 2;\n\tctx.clearRect(0, 0, size, size);\n\tif (supportsCanvasFilter()) {\n\t\tctx.filter = `blur(${blur}px)`;\n\t\tctx.drawImage(scratch as CanvasImageSource, -offset, -offset, dw, dw);\n\t\tctx.filter = \"none\";\n\t\treturn;\n\t}\n\t// 2D-canvas `filter` is a silent no-op on Safari < 17: approximate the\n\t// gaussian by bouncing through a small canvas. Bilinear resampling on the\n\t// way down and back up smears by roughly the downscale factor, which is\n\t// plenty for a mesh that is already smooth gradients.\n\tconst factor = Math.max(2, Math.min(16, blur / 2));\n\tconst sw = Math.max(1, Math.round(size / factor));\n\tconst small = createCanvas(sw, sw);\n\tconst smallCtx = get2d(small, options.p3);\n\tif (!smallCtx) {\n\t\tctx.drawImage(scratch as CanvasImageSource, -offset, -offset, dw, dw);\n\t\treturn;\n\t}\n\tsmallCtx.imageSmoothingEnabled = true;\n\tsmallCtx.imageSmoothingQuality = \"high\";\n\tsmallCtx.drawImage(scratch as CanvasImageSource, 0, 0, sw, sw);\n\tctx.imageSmoothingEnabled = true;\n\tctx.imageSmoothingQuality = \"high\";\n\tctx.drawImage(small as CanvasImageSource, -offset, -offset, dw, dw);\n}\n\n/* Engines that honor 2D-canvas `filter` echo an assigned value back from the\n * property; Safari < 17 ignores the assignment. Probed once, then cached. */\nlet canvasFilterSupport: boolean | null = null;\nfunction supportsCanvasFilter(): boolean {\n\tif (canvasFilterSupport !== null) return canvasFilterSupport;\n\tconst probe = createCanvas(1, 1).getContext(\n\t\t\"2d\",\n\t) as CanvasRenderingContext2D | null;\n\tif (!probe) {\n\t\tcanvasFilterSupport = false;\n\t\treturn canvasFilterSupport;\n\t}\n\tprobe.filter = \"blur(1px)\";\n\tcanvasFilterSupport = probe.filter === \"blur(1px)\";\n\treturn canvasFilterSupport;\n}\n\nfunction createCanvas(\n\tw: number,\n\th: number,\n): HTMLCanvasElement | OffscreenCanvas {\n\tif (typeof OffscreenCanvas !== \"undefined\") {\n\t\treturn new OffscreenCanvas(w, h);\n\t}\n\tconst c = document.createElement(\"canvas\");\n\tc.width = w;\n\tc.height = h;\n\treturn c;\n}\n\nexport interface ExportOptions extends RenderOptions {\n\t/** Output pixel dimensions (square). Default: 512. */\n\tsize?: number;\n\t/** Image MIME type. Default: \"image/png\". */\n\ttype?: string;\n\t/** Quality 0–1 for lossy types. Default: 0.92. */\n\tquality?: number;\n}\n\n/** Render a seed's gradient and return it as a data URL. Browser only. */\nexport function gradientToDataURL(\n\tseed: number | string,\n\toptions: ExportOptions = {},\n): string {\n\tconst { size = 512, type = \"image/png\", quality = 0.92 } = options;\n\tconst canvas = document.createElement(\"canvas\");\n\tcanvas.width = size;\n\tcanvas.height = size;\n\trenderGradient(canvas, seed, options);\n\treturn canvas.toDataURL(type, quality);\n}\n\n/** Render a seed's gradient and resolve a Blob (or null). Browser only. */\nexport function gradientToBlob(\n\tseed: number | string,\n\toptions: ExportOptions = {},\n): Promise<Blob | null> {\n\tconst { size = 512, type = \"image/png\", quality = 0.92 } = options;\n\tconst canvas = document.createElement(\"canvas\");\n\tcanvas.width = size;\n\tcanvas.height = size;\n\trenderGradient(canvas, seed, options);\n\treturn new Promise((resolve) => canvas.toBlob(resolve, type, quality));\n}\n","import type { CSSProperties } from \"react\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { drawDither, drawMeshGradient, type Pattern } from \"./engine\";\n\nexport interface GradientAvatarProps {\n\t/** Any string or number, each unique seed produces a unique gradient. */\n\tseed: number | string;\n\t/** Rendered size in pixels. Default: 32. */\n\tsize?: number;\n\t/**\n\t * Render style. `\"mesh\"` is the signature soft gradient; `\"dither\"` is an\n\t * ordered (Bayer) dither of the same palette, crisp with no blur.\n\t * Default: `\"mesh\"`.\n\t */\n\tpattern?: Pattern;\n\t/**\n\t * Corner radius. Number = pixels, string = any CSS length.\n\t * Defaults to a full circle; pass `0` for a square or e.g. `12` for a\n\t * rounded square. Default: \"9999px\".\n\t */\n\tradius?: number | string;\n\t/**\n\t * Bring your own colors (hex) instead of the seed-derived harmony. The seed\n\t * still drives the layout, so each seed stays unique but on-brand.\n\t */\n\tcolors?: string[];\n\t/**\n\t * Render in the Display P3 wide-gamut color space, more vivid on capable\n\t * screens, and the same on the rest. Default: `false`.\n\t */\n\tp3?: boolean;\n\t/** Additional CSS classes on the wrapper. */\n\tclassName?: string;\n\t/** Extra inline styles merged onto the wrapper. */\n\tstyle?: CSSProperties;\n}\n\n/** Internal render resolution. Higher than display size so the CSS blur is smooth. */\nconst RENDER_SIZE = 256;\n/** Blur radius as a fraction of display size. */\nconst BLUR_FRACTION = 0.06;\n\n/**\n * Renders a deterministic mesh-gradient avatar on a `<canvas>`.\n * The same seed always produces the same gradient.\n */\nexport function GradientAvatar({\n\tseed,\n\tsize = 32,\n\tpattern = \"mesh\",\n\tradius = \"9999px\",\n\tcolors,\n\tp3 = false,\n\tclassName,\n\tstyle,\n}: GradientAvatarProps) {\n\tconst canvasRef = useRef<HTMLCanvasElement>(null);\n\n\t// Normalize `colors` to a stable string so an inline `colors={[...]}` array\n\t// (a new reference every render) doesn't force a redraw each time; the memo\n\t// below rebuilds the palette only when the actual values change.\n\tconst colorsKey = colors?.join(\",\");\n\tconst palette = useMemo(\n\t\t() => (colorsKey ? colorsKey.split(\",\") : undefined),\n\t\t[colorsKey],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\t\tconst ctx = canvas.getContext(\"2d\", {\n\t\t\tcolorSpace: p3 ? \"display-p3\" : \"srgb\",\n\t\t}) as CanvasRenderingContext2D | null;\n\t\tif (!ctx) return;\n\t\tctx.clearRect(0, 0, RENDER_SIZE, RENDER_SIZE);\n\t\t// Always drawn at RENDER_SIZE for a smooth blur, but the complexity\n\t\t// follows `size`: a 24px avatar gets a simpler mark than a 160px one.\n\t\tconst opts = { colors: palette, p3, displaySize: size };\n\t\tif (pattern === \"dither\") drawDither(ctx, seed, RENDER_SIZE, opts);\n\t\telse drawMeshGradient(ctx, seed, RENDER_SIZE, opts);\n\t}, [seed, pattern, p3, palette, size]);\n\n\t// The dither is crisp; only the mesh gets the signature soft blur.\n\tconst blurPx =\n\t\tpattern === \"dither\" ? 0 : Math.max(1, Math.round(size * BLUR_FRACTION));\n\n\treturn (\n\t\t<span\n\t\t\tclassName={className}\n\t\t\tstyle={{\n\t\t\t\tdisplay: \"inline-block\",\n\t\t\t\toverflow: \"hidden\",\n\t\t\t\tborderRadius: radius,\n\t\t\t\twidth: size,\n\t\t\t\theight: size,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<canvas\n\t\t\t\tref={canvasRef}\n\t\t\t\twidth={RENDER_SIZE}\n\t\t\t\theight={RENDER_SIZE}\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\theight: \"100%\",\n\t\t\t\t\tdisplay: \"block\",\n\t\t\t\t\tfilter: blurPx > 0 ? `blur(${blurPx}px)` : undefined,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</span>\n\t);\n}\n\nexport type {\n\tDrawOptions,\n\tExportOptions,\n\tGradientPalette,\n\tHarmony,\n\tPaletteOptions,\n\tPattern,\n\tRenderOptions,\n} from \"./engine\";\nexport {\n\tdrawDither,\n\tdrawMeshGradient,\n\tgeneratePalette,\n\tgradientToBlob,\n\tgradientToDataURL,\n\trenderGradient,\n\tseedFromString,\n\ttoSeed,\n} from \"./engine\";\n"]}