{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "primitives",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "Bank/merchant logo with the full fallback ladder.",
  "files": [
    {
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport { BuildingLibraryIcon, BuildingOffice2Icon, CreditCardIcon, ShoppingBagIcon } from \"@/components/ledger/icons\";\n\ntype Category = \"bank\" | \"merchant\" | \"card\" | \"company\";\n\nconst CATEGORY_ICON = {\n  bank: BuildingLibraryIcon,\n  card: CreditCardIcon,\n  company: BuildingOffice2Icon,\n  merchant: ShoppingBagIcon,\n} as const;\n\nexport interface EntityMarkProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  category?: Category;\n  name: string;\n  size?: 20 | 24 | 32 | 40 | 48;\n  src?: string;\n}\n\n/**\n * The full fallback ladder — provided → deterministic monogram → category\n * icon. Never a broken image.\n */\nexport const EntityMark = React.forwardRef<HTMLDivElement, EntityMarkProps>(\n  ({ className, name, src, category = \"merchant\", size = 32, ...props }, ref) => {\n    const Icon = CATEGORY_ICON[category];\n    const monogram = initials(name);\n\n    return (\n      <div\n        aria-hidden=\"true\"\n        className={cn(\n          \"grid shrink-0 place-items-center overflow-hidden rounded-sm bg-surface-sunken\",\n          \"border border-border-subtle\",\n          className,\n        )}\n        ref={ref}\n        style={{ height: size, width: size }}\n        title={name}\n        {...props}\n      >\n        {src ? (\n          // eslint-disable-next-line @next/next/no-img-element\n          <img alt=\"\" className=\"size-full object-contain p-[20%] [filter:saturate(0.85)]\" src={src} />\n        ) : monogram ? (\n          <span className=\"font-medium text-text-secondary\" style={{ fontSize: Math.round(size * 0.38) }}>\n            {monogram}\n          </span>\n        ) : (\n          <Icon className=\"text-text-tertiary\" style={{ height: size * 0.5, width: size * 0.5 }} />\n        )}\n      </div>\n    );\n  },\n);\nEntityMark.displayName = \"EntityMark\";\n\nfunction initials(name: string): string {\n  const words = name.trim().split(/\\s+/).filter(Boolean);\n  if (words.length === 0) return \"\";\n  if (words.length === 1) return words[0].slice(0, 2).toUpperCase();\n  return (words[0][0] + words[1][0]).toUpperCase();\n}\n",
      "path": "components/ledger/entity-mark.tsx",
      "target": "components/ledger/entity-mark.tsx",
      "type": "registry:ui"
    }
  ],
  "name": "entity-mark",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/cn",
    "@lopifi/icons"
  ],
  "title": "EntityMark",
  "type": "registry:ui"
}
