{"version":3,"sources":["../../src/providerIcons/ProviderIcon.tsx"],"sourcesContent":["// ProviderIcon — the monochrome provider mark, keyed by models.dev provider id\n// (R3-1141; the same key as the catalogue's `modelsDevId`).\n//\n// The sprite is vendored (scripts/sync-provider-icons.mjs → sprite.generated.ts):\n// no runtime fetch — the CSP allows no external image host, and a refresh's diff is\n// reviewable. Monochrome is enforced by the generator (every paint is currentColor or\n// none), so the mark inherits the surrounding text color and no brand recoloring is\n// possible. A provider with no icon keeps its lettermark — a guessed logo misrepresents\n// the provider, which is worse than no logo.\n\nimport type { ReactNode } from 'react';\nimport { useEffect, useRef } from 'react';\nimport { PROVIDER_ICON_IDS, PROVIDER_ICON_SPRITE } from './sprite.generated';\n\nconst SPRITE_NODE_ID = 'ir-provider-icon-sprite';\n\n/** Inject the sprite once per document; a second renderer (or a remount) finds the\n *  existing node and adds nothing. */\nconst ensureSprite = (doc: Document): void => {\n  if (doc.getElementById(SPRITE_NODE_ID)) return;\n  const host = doc.createElement('div');\n  host.id = SPRITE_NODE_ID;\n  host.setAttribute('aria-hidden', 'true');\n  host.style.display = 'none';\n  host.innerHTML = PROVIDER_ICON_SPRITE;\n  doc.body.appendChild(host);\n};\n\nexport interface ProviderIconProps {\n  /** The models.dev provider id (the sprite's symbol key). */\n  id: string;\n  /** The accessible name — and the lettermark's source when no icon exists. */\n  label: string;\n  /** Square edge in px. */\n  size?: number;\n}\n\nexport function ProviderIcon({ id, label, size = 16 }: ProviderIconProps): ReactNode {\n  const known = (PROVIDER_ICON_IDS as readonly string[]).includes(id);\n  // useEffect, not render: the injection is a side effect, and a second render must not\n  // double-inject (the getElementById check is the idempotence, the effect is the rule).\n  const docRef = useRef<Document | null>(null);\n  if (typeof document !== 'undefined') docRef.current = document;\n  useEffect(() => {\n    if (known && docRef.current) ensureSprite(docRef.current);\n  }, [known]);\n\n  if (!known) {\n    // The lettermark: the label's first letter, no invented mark.\n    return (\n      <span\n        role=\"img\"\n        aria-label={label}\n        style={{ display: 'inline-block', width: size, height: size, textAlign: 'center' }}\n      >\n        {label.charAt(0).toUpperCase()}\n      </span>\n    );\n  }\n  return (\n    <svg role=\"img\" aria-label={label} width={size} height={size}>\n      <use href={`#pi-${id}`} />\n    </svg>\n  );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkDM;AAvCN,mBAAkC;AAClC,oBAAwD;AAExD,MAAM,iBAAiB;AAIvB,MAAM,eAAe,CAAC,QAAwB;AAC5C,MAAI,IAAI,eAAe,cAAc,EAAG;AACxC,QAAM,OAAO,IAAI,cAAc,KAAK;AACpC,OAAK,KAAK;AACV,OAAK,aAAa,eAAe,MAAM;AACvC,OAAK,MAAM,UAAU;AACrB,OAAK,YAAY;AACjB,MAAI,KAAK,YAAY,IAAI;AAC3B;AAWO,SAAS,aAAa,EAAE,IAAI,OAAO,OAAO,GAAG,GAAiC;AACnF,QAAM,QAAS,gCAAwC,SAAS,EAAE;AAGlE,QAAM,aAAS,qBAAwB,IAAI;AAC3C,MAAI,OAAO,aAAa,YAAa,QAAO,UAAU;AACtD,8BAAU,MAAM;AACd,QAAI,SAAS,OAAO,QAAS,cAAa,OAAO,OAAO;AAAA,EAC1D,GAAG,CAAC,KAAK,CAAC;AAEV,MAAI,CAAC,OAAO;AAEV,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,OAAO,EAAE,SAAS,gBAAgB,OAAO,MAAM,QAAQ,MAAM,WAAW,SAAS;AAAA,QAEhF,gBAAM,OAAO,CAAC,EAAE,YAAY;AAAA;AAAA,IAC/B;AAAA,EAEJ;AACA,SACE,4CAAC,SAAI,MAAK,OAAM,cAAY,OAAO,OAAO,MAAM,QAAQ,MACtD,sDAAC,SAAI,MAAM,OAAO,EAAE,IAAI,GAC1B;AAEJ;","names":[]}