{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chain-icon",
  "title": "Chain icon",
  "description": "Theme-aware chain artwork with initials, a dark-ground backplate and optional tile frame.",
  "dependencies": [
    "class-variance-authority@^0.7"
  ],
  "registryDependencies": [
    "@dwellir/dwellir-theme",
    "@dwellir/utils"
  ],
  "files": [
    {
      "path": "components/ui/chain-icon.tsx",
      "content": "'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { type ComponentProps, useEffect, useRef, useState } from 'react';\nimport iconBackplates from '@/lib/networkCatalog/iconBackplates.json';\nimport { cn } from '@/lib/utils';\n\nconst catalogBackplates: Readonly<Record<string, boolean>> = iconBackplates;\n\nconst chainIconVariants = cva('inline-flex shrink-0 items-center justify-center align-middle', {\n  variants: {\n    size: {\n      sm: 'size-6 text-xs',\n      md: 'size-8 text-sm',\n      lg: 'size-12 text-base',\n    },\n    frame: {\n      none: '',\n      tile: 'rounded-xl border border-border bg-background p-2',\n    },\n  },\n  compoundVariants: [\n    { size: 'sm', frame: 'tile', class: 'size-10' },\n    { size: 'md', frame: 'tile', class: 'size-12' },\n    { size: 'lg', frame: 'tile', class: 'size-16' },\n  ],\n  defaultVariants: { size: 'md', frame: 'none' },\n});\n\nconst glyphVariants = cva('relative flex size-full items-center justify-center rounded-full', {\n  variants: {\n    theme: {\n      shared: '',\n      light: 'dark:hidden',\n      dark: 'hidden dark:flex',\n    },\n    backplate: {\n      true: 'dark:bg-chain-icon-ground dark:p-1',\n      false: '',\n    },\n  },\n});\n\ntype ChainIconProps = Omit<ComponentProps<'span'>, 'children'> &\n  VariantProps<typeof chainIconVariants> & {\n    name: string;\n    /** The light-theme source, or the only source when no dark artwork exists. */\n    src?: string | null;\n    darkSrc?: string | null;\n    /** Decorative beside a name. Supply alt when the logo stands alone. */\n    alt?: string;\n    loading?: 'eager' | 'lazy';\n  };\n\nfunction ChainGlyph({\n  src,\n  initials,\n  theme,\n  backplate,\n  loading,\n  onError,\n}: Pick<ChainIconProps, 'src' | 'loading'> &\n  VariantProps<typeof glyphVariants> & { initials: string; onError: () => void }) {\n  const imageRef = useRef<HTMLImageElement>(null);\n  const retried = useRef(false);\n  useEffect(() => {\n    const image = imageRef.current;\n    // A cached failure can precede hydration. Zero intrinsic width can also describe a valid SVG.\n    if (src && image?.complete && image.naturalWidth === 0 && !retried.current) {\n      retried.current = true;\n      image.src = src;\n    }\n  }, [src]);\n  return (\n    <span\n      data-slot=\"chain-icon-glyph\"\n      className={cn(glyphVariants({ theme, backplate }), src && 'chain-icon-edge')}\n    >\n      {src ? (\n        <img\n          data-slot=\"chain-icon-image\"\n          ref={imageRef}\n          src={src}\n          alt=\"\"\n          width={48}\n          height={48}\n          loading={loading}\n          decoding=\"async\"\n          draggable={false}\n          className=\"chain-icon-image size-full object-contain\"\n          onError={onError}\n        />\n      ) : (\n        <span\n          data-slot=\"chain-icon-fallback\"\n          className=\"absolute inset-0 flex items-center justify-center rounded-full bg-muted font-label font-bold text-foreground\"\n        >\n          {initials}\n        </span>\n      )}\n    </span>\n  );\n}\n\nfunction ChainArtwork({\n  src,\n  darkSrc,\n  initials,\n  loading,\n}: Pick<ChainIconProps, 'src' | 'darkSrc' | 'loading'> & { initials: string }) {\n  const [lightFailed, setLightFailed] = useState(false);\n  const [darkFailed, setDarkFailed] = useState(false);\n  const showDark = Boolean(darkSrc) && !darkFailed;\n  const lightSrc = lightFailed ? undefined : src;\n  const file = lightSrc?.split(/[?#]/)[0].split('/').at(-1);\n  return (\n    <>\n      <ChainGlyph\n        src={lightSrc}\n        initials={initials}\n        theme={showDark ? 'light' : 'shared'}\n        backplate={!showDark && Boolean(file && catalogBackplates[file])}\n        loading={loading}\n        onError={() => setLightFailed(true)}\n      />\n      {showDark && (\n        <ChainGlyph\n          src={darkSrc}\n          initials={initials}\n          theme=\"dark\"\n          loading={loading}\n          onError={() => setDarkFailed(true)}\n        />\n      )}\n    </>\n  );\n}\n\nfunction ChainIcon({\n  name,\n  src,\n  darkSrc,\n  alt = '',\n  loading = 'lazy',\n  size = 'md',\n  frame = 'none',\n  className,\n  ...props\n}: ChainIconProps) {\n  const initials =\n    name\n      .trim()\n      .split(/\\s+/)\n      .slice(0, 2)\n      .map((word) => Array.from(word)[0])\n      .join('')\n      .toUpperCase() || '?';\n  return (\n    <span\n      data-slot=\"chain-icon\"\n      data-size={size}\n      data-frame={frame}\n      role=\"img\"\n      aria-label={alt || undefined}\n      aria-hidden={alt ? undefined : true}\n      className={cn(chainIconVariants({ size, frame }), className)}\n      {...props}\n    >\n      <ChainArtwork\n        key={JSON.stringify([src, darkSrc])}\n        src={src}\n        darkSrc={darkSrc}\n        initials={initials}\n        loading={loading}\n      />\n    </span>\n  );\n}\n\nexport type { ChainIconProps };\nexport { ChainIcon, chainIconVariants };\n",
      "type": "registry:ui"
    },
    {
      "path": "lib/networkCatalog/iconBackplates.json",
      "content": "{\n  \"Polkadot_Logo_Horizontal_Pink_Black.svg\": true,\n  \"Polkadot_Logo_Vertical_Pink-Black.svg\": true,\n  \"acala.svg\": true,\n  \"acurast.svg\": true,\n  \"ajuna.svg\": true,\n  \"alephzero.svg\": true,\n  \"amplitude.svg\": false,\n  \"aptos-dark.svg\": false,\n  \"aptos-light.svg\": true,\n  \"arbitrum.svg\": false,\n  \"arc.svg\": true,\n  \"assethub.svg\": true,\n  \"astar.svg\": true,\n  \"astar_dot.svg\": true,\n  \"astar_eth.svg\": true,\n  \"avail.svg\": false,\n  \"avax.svg\": false,\n  \"aventus.svg\": true,\n  \"balanceai.svg\": false,\n  \"base.svg\": true,\n  \"basilisk.svg\": false,\n  \"bera.svg\": true,\n  \"bifrost.svg\": true,\n  \"bittensor.svg\": false,\n  \"blast-dark.svg\": false,\n  \"blast-light.svg\": true,\n  \"bnb.svg\": false,\n  \"boba-network.svg\": false,\n  \"bridge-hub.svg\": true,\n  \"bridgehub.svg\": true,\n  \"btc.svg\": false,\n  \"celestia.svg\": true,\n  \"celo.svg\": false,\n  \"centrifuge.svg\": true,\n  \"chainflip.svg\": false,\n  \"chiliz.svg\": false,\n  \"chromia-dark.svg\": false,\n  \"chromia-light.svg\": true,\n  \"chronicle.svg\": false,\n  \"collectives.svg\": false,\n  \"composable.svg\": true,\n  \"coretime.svg\": true,\n  \"cronos-dark.svg\": false,\n  \"cronos-light.svg\": true,\n  \"crust.svg\": false,\n  \"darwinia.svg\": false,\n  \"darwinia_crab.svg\": true,\n  \"done.svg\": false,\n  \"dwellir.svg\": false,\n  \"dwellir_circle.svg\": true,\n  \"efinity.svg\": true,\n  \"elysium.svg\": true,\n  \"encointer.svg\": false,\n  \"energywebx.svg\": true,\n  \"enjin.svg\": true,\n  \"equilibrium.svg\": true,\n  \"ethereum.svg\": true,\n  \"etherlink.svg\": true,\n  \"fantom.svg\": false,\n  \"filecoin.svg\": false,\n  \"flow.svg\": false,\n  \"frequency.svg\": true,\n  \"gnosis-dark.svg\": false,\n  \"gnosis-light.svg\": true,\n  \"gravity.svg\": true,\n  \"heima.svg\": true,\n  \"humanode.svg\": true,\n  \"humanode.webp\": true,\n  \"hydra_dx_circle.svg\": true,\n  \"hydra_v1.svg\": false,\n  \"hyperbridge.svg\": true,\n  \"hyperbridge.webp\": true,\n  \"hyperliquid-dark.svg\": false,\n  \"hyperliquid-light.svg\": true,\n  \"immutable-dark.svg\": false,\n  \"immutable-light.svg\": true,\n  \"ink.svg\": true,\n  \"integritee.svg\": true,\n  \"interlay.svg\": true,\n  \"invarch.svg\": true,\n  \"iotex.svg\": false,\n  \"joystream.svg\": false,\n  \"karura.svg\": true,\n  \"khala.svg\": true,\n  \"kilt.svg\": true,\n  \"kintsugi.svg\": true,\n  \"krest.svg\": false,\n  \"kusama.svg\": true,\n  \"liberland.svg\": false,\n  \"liberland.webp\": false,\n  \"linea-dark.svg\": false,\n  \"linea-light.svg\": false,\n  \"lisk-dark.svg\": false,\n  \"lisk-light.svg\": true,\n  \"litentry_v1.svg\": false,\n  \"logoipsum-logo-1.svg\": true,\n  \"logoipsum-logo-2.svg\": true,\n  \"logoipsum-logo-3.svg\": true,\n  \"logoipsum-logo-4.svg\": true,\n  \"logoipsum-logo-5.svg\": true,\n  \"logoipsum-logo-6.svg\": true,\n  \"logoipsum-logo-7.svg\": true,\n  \"manta-atlantic.svg\": false,\n  \"manta.svg\": false,\n  \"mantle.svg\": true,\n  \"megaeth-dark.svg\": false,\n  \"megaeth-light.svg\": true,\n  \"monad.svg\": false,\n  \"moonbase_alpha-dark.svg\": false,\n  \"moonbase_alpha-light.svg\": true,\n  \"moonbeam-dark.svg\": false,\n  \"moonbeam-light.svg\": true,\n  \"moonriver-dark.svg\": false,\n  \"moonriver-light.svg\": true,\n  \"movement-dark.svg\": false,\n  \"movement-light.svg\": true,\n  \"mythos.svg\": false,\n  \"neuroweb.svg\": true,\n  \"nodle.svg\": false,\n  \"oak.svg\": true,\n  \"operator.svg\": false,\n  \"optimism.svg\": false,\n  \"palm-network.svg\": true,\n  \"parallel.svg\": false,\n  \"paseo.svg\": true,\n  \"peaq.svg\": false,\n  \"pendulum.svg\": true,\n  \"people-polkadot.svg\": false,\n  \"people.svg\": true,\n  \"phala.svg\": true,\n  \"picasso.svg\": true,\n  \"plasma-dark.svg\": false,\n  \"plasma-light.svg\": true,\n  \"polimec.svg\": false,\n  \"polkadex.svg\": true,\n  \"polkadot.svg\": true,\n  \"polygon.svg\": true,\n  \"pulse.svg\": true,\n  \"robinhood-dark.svg\": false,\n  \"robinhood-light.svg\": true,\n  \"robonomics.svg\": true,\n  \"ronin.svg\": true,\n  \"scroll.svg\": false,\n  \"shibuya.svg\": true,\n  \"shibuya.webp\": true,\n  \"shiden.svg\": true,\n  \"sonic.svg\": true,\n  \"sora.svg\": true,\n  \"sqd.svg\": true,\n  \"stable.svg\": false,\n  \"staking_interest.svg\": false,\n  \"staking_interestrc.svg\": false,\n  \"starknet.svg\": true,\n  \"subsocial.svg\": true,\n  \"sui.svg\": false,\n  \"taiko.svg\": false,\n  \"tangle.svg\": false,\n  \"tempo-dark.svg\": false,\n  \"tempo-light.svg\": true,\n  \"tokenterminal.svg\": true,\n  \"ton.svg\": false,\n  \"tron.svg\": true,\n  \"unichain.svg\": false,\n  \"unichain_testnet.svg\": false,\n  \"unique.svg\": false,\n  \"viction.svg\": false,\n  \"waves.svg\": true,\n  \"westend.svg\": false,\n  \"worldchain-dark.svg\": false,\n  \"worldchain-light.svg\": true,\n  \"worldchain.svg\": true,\n  \"xdc-dark.svg\": false,\n  \"xdc-light.svg\": true,\n  \"xx-network.svg\": false,\n  \"zeitgeist.svg\": true,\n  \"zetachain.svg\": true,\n  \"zksync.svg\": true,\n  \"zora.svg\": true\n}\n",
      "type": "registry:file",
      "target": "@lib/networkCatalog/iconBackplates.json"
    }
  ],
  "type": "registry:ui"
}