{
  "name": "sale-badge",
  "title": "SaleBadge",
  "description": "Sale/discount indicator with percentage and original price.",
  "type": "component",
  "registryDependencies": [
    "price",
    "cn"
  ],
  "files": [
    {
      "path": "sale-badge.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport type { Product, ProductDealInfo } from \"@cimplify/sdk\";\nimport type { ProductWithPrice } from \"@cimplify/sdk\";\nimport {\n  isOnSale,\n  getDiscountPercentage,\n  getBasePrice,\n  getProductCurrency,\n  parsePrice,\n} from \"@cimplify/sdk\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface SaleBadgeClassNames {\n  root?: string;\n  percentage?: string;\n  label?: string;\n  originalPrice?: string;\n}\n\nexport interface SaleBadgeProps {\n  /** Product, optionally enriched with price_info for sale detection. */\n  product: Product & Partial<ProductWithPrice>;\n  /** Deal info from useProductDeals / useProductsOnSale. */\n  dealInfo?: ProductDealInfo;\n  /** Override badge text entirely. */\n  label?: string;\n  /** Show the original (pre-discount) price with strikethrough styling. */\n  showOriginalPrice?: boolean;\n  /** Show the percentage off. Default: true. */\n  showPercentage?: boolean;\n  className?: string;\n  classNames?: SaleBadgeClassNames;\n}\n\n/**\n * SaleBadge — shows a sale/discount indicator for a product.\n *\n * Returns `null` when there's no deal, no sale price difference, and no label override,\n * so it's safe to render unconditionally — it simply won't show for non-sale products.\n */\nexport function SaleBadge({\n  product,\n  dealInfo,\n  label,\n  showOriginalPrice = false,\n  showPercentage = true,\n  className,\n  classNames,\n}: SaleBadgeProps): React.ReactElement | null {\n  const onSale = isOnSale(product);\n  const hasDeal = dealInfo !== undefined;\n\n  if (!hasDeal && !onSale && !label) {\n    return null;\n  }\n\n  // A live server sale is the canonical pricing decision. Deal metadata and\n  // scalar price differences are compatibility fallbacks only.\n  let percentage: number | null = null;\n  if (product.sale) {\n    percentage = parsePrice(product.sale.percent_off);\n  } else if (hasDeal && dealInfo.benefit_type === \"percentage\") {\n    percentage = parsePrice(dealInfo.value);\n  } else if (onSale) {\n    percentage = getDiscountPercentage(product);\n  }\n\n  // Badge text: explicit label > deal label > computed \"X% off\"\n  const badgeText =\n    label ??\n    product.sale?.badge_text ??\n    dealInfo?.label ??\n    (percentage != null && percentage > 0 ? `${percentage}% off` : null);\n\n  if (!badgeText) {\n    return null;\n  }\n\n  return (\n    <span\n      data-cimplify-sale-badge\n      className={cn(className, classNames?.root)}\n      style={{ display: \"inline-flex\", alignItems: \"center\", gap: \"0.375rem\" }}\n    >\n      {showPercentage && percentage != null && percentage > 0 && (\n        <span data-cimplify-sale-percentage className={classNames?.percentage}>\n          -{percentage}%\n        </span>\n      )}\n      <span data-cimplify-sale-label className={classNames?.label}>\n        {badgeText}\n      </span>\n      {showOriginalPrice && onSale && (\n        <span data-cimplify-sale-original-price className={classNames?.originalPrice}>\n          <Price amount={getBasePrice(product)} currency={getProductCurrency(product)} />\n        </span>\n      )}\n    </span>\n  );\n}\n"
    }
  ]
}
