Fallback Avatar
spell-ui/fallback-avatarFreeComponent
A unique gradient avatar generated from a name string.
Live preview
live · rendered by the registry
Rendered by spell-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://spell.sh/r/fallback-avatar.jsonSource
1"use client";23import { useCallback, useEffect, useRef, useState } from "react";4import { cn } from "@/lib/utils";56// --- Hash utilities ---78function hashString(str: string): [number, number] {9 let h1 = 0xdeadbeef;10 let h2 = 0x41c6ce57;11 for (let i = 0; i < str.length; i++) {12 const ch = str.charCodeAt(i);13 h1 = Math.imul(h1 ^ ch, 2654435761);14 h2 = Math.imul(h2 ^ ch, 1597334677);15 }16 h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);17 h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);18 h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);19 h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);20 return [h1 >>> 0, h2 >>> 0];21}2223function mulberry32(seed: number) {24 return function () {25 seed |= 0;26 seed = (seed + 0x6d2b79f5) | 0;27 let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);28 t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;29 return ((t ^ (t >>> 14)) >>> 0) / 4294967296;30 };31}3233function deriveHue(hash: [number, number]): number {34 const bytes: number[] = [];35 for (let i = 0; i < 4; i++) {36 bytes.push((hash[0] >> (i * 8)) & 0xff);37 bytes.push((hash[1] >> (i * 8)) & 0xff);38 }39 return bytes.reduce((a, b) => a + b, 0) % 360;40}4142function oklchToRgb(43 L: number,44 C: number,45 H: number46): [number, number, number] {47 const hRad = (H * Math.PI) / 180;48 const a = C * Math.cos(hRad);49 const b = C * Math.sin(hRad);50 const l_ = L + 0.3963377774 * a + 0.2158037573 * b;51 const m_ = L - 0.1055613458 * a - 0.0638541728 * b;52 const s_ = L - 0.0894841775 * a - 1.291485548 * b;53 const l = l_ * l_ * l_;54 const m = m_ * m_ * m_;55 const s = s_ * s_ * s_;56 let R = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;57 let G = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;58 let B = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;59 const gamma = (v: number) =>60 v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;61 return [62 Math.round(Math.max(0, Math.min(1, gamma(R))) * 255),63 Math.round(Math.max(0, Math.min(1, gamma(G))) * 255),64 Math.round(Math.max(0, Math.min(1, gamma(B))) * 255),65 ];66}6768function getColors(69 hash: [number, number]70): [[number, number, number], [number, number, number]] {71 const hue = deriveHue(hash);72 return [oklchToRgb(0.8, 0.18, hue), oklchToRgb(0.45, 0.18, hue)];73}7475// --- Uniforms ---7677interface Uniforms {78 S: number;79 H: number;80 P: [number, number, number, number];81 Q: [number, number, number, number];82 C1: [number, number, number];83// … truncated
Files it writes
More from spell-ui
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Checkboxanimated-checkbox | spell-ui | Components | Free | 1 dep | |
| Animated Gradientanimated-gradient | spell-ui | Components | Free | no deps | |
| Badgebadge | spell-ui | Components | Free | 2 deps | |
| Bars Spinnerbars-spinner | spell-ui | Components | Free | no deps | |
| Blur Revealblur-reveal | spell-ui | Components | Free | 1 dep | |
| Chartchart | spell-ui | Components | Free | no deps | |
| Color Selectorcolor-selector | spell-ui | Components | Free | no deps | |
| Copy Buttoncopy-button | spell-ui | Components | Free | 1 dep |
