{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "usage-card",
  "type": "registry:ui",
  "title": "Usage Card",
  "description": "A card for displaying usage metrics, billing cycle progress and itemized charges.",
  "files": [
    {
      "path": "src/registry/ui/usage-card.tsx",
      "content": "\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { ChevronDown, ChevronUp } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Progress } from \"@/components/ui/progress\";\nimport { cn } from \"@/lib/utils\";\n\nconst usageCardVariants = cva(\n  \"relative min-w-[280px] rounded-2xl border bg-card text-card-foreground\",\n  {\n    variants: {\n      variant: {\n        default: \"border-border\",\n        elevated: \"border-border shadow-lg\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\ninterface UsageCardProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof usageCardVariants> {}\n\nconst UsageCard = React.forwardRef<HTMLDivElement, UsageCardProps>(\n  ({ className, variant, ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(usageCardVariants({ variant, className }))}\n      {...props}\n    />\n  ),\n);\nUsageCard.displayName = \"UsageCard\";\n\ninterface UsageCardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst UsageCardHeader = React.forwardRef<HTMLDivElement, UsageCardHeaderProps>(\n  ({ className, ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(\n        \"flex items-center justify-between gap-4 p-4 pb-0\",\n        className,\n      )}\n      {...props}\n    />\n  ),\n);\nUsageCardHeader.displayName = \"UsageCardHeader\";\n\ninterface UsageCardPeriodProps extends React.HTMLAttributes<HTMLSpanElement> {\n  daysRemaining?: number;\n}\n\nconst UsageCardPeriod = React.forwardRef<HTMLSpanElement, UsageCardPeriodProps>(\n  ({ className, daysRemaining, children, ...props }, ref) => (\n    <span\n      ref={ref}\n      className={cn(\"text-sm font-medium text-foreground\", className)}\n      {...props}\n    >\n      {children ??\n        (daysRemaining !== undefined &&\n          `${daysRemaining} days remaining in cycle`)}\n    </span>\n  ),\n);\nUsageCardPeriod.displayName = \"UsageCardPeriod\";\n\ninterface UsageCardActionProps\n  extends React.ComponentPropsWithoutRef<typeof Button> {}\n\nconst UsageCardAction = React.forwardRef<\n  HTMLButtonElement,\n  UsageCardActionProps\n>(({ className, ...props }, ref) => (\n  <Button\n    ref={ref}\n    variant=\"outline\"\n    size=\"sm\"\n    className={cn(\"rounded-full\", className)}\n    {...props}\n  />\n));\nUsageCardAction.displayName = \"UsageCardAction\";\n\ninterface UsageCardSummaryProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst UsageCardSummary = React.forwardRef<\n  HTMLDivElement,\n  UsageCardSummaryProps\n>(({ className, ...props }, ref) => (\n  <div ref={ref} className={cn(\"p-4 space-y-3\", className)} {...props} />\n));\nUsageCardSummary.displayName = \"UsageCardSummary\";\n\ninterface UsageCardLabelsProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst UsageCardLabels = React.forwardRef<HTMLDivElement, UsageCardLabelsProps>(\n  ({ className, ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(\"flex items-start justify-between gap-4\", className)}\n      {...props}\n    />\n  ),\n);\nUsageCardLabels.displayName = \"UsageCardLabels\";\n\ninterface UsageCardLabelProps extends React.HTMLAttributes<HTMLDivElement> {\n  label: string;\n  amount: number;\n  limit?: number;\n  currency?: string;\n  align?: \"left\" | \"right\";\n}\n\nconst UsageCardLabel = React.forwardRef<HTMLDivElement, UsageCardLabelProps>(\n  (\n    {\n      className,\n      label,\n      amount,\n      limit,\n      currency = \"$\",\n      align = \"left\",\n      ...props\n    },\n    ref,\n  ) => (\n    <div\n      ref={ref}\n      className={cn(\n        \"flex flex-col gap-0.5\",\n        align === \"right\" && \"items-end\",\n        className,\n      )}\n      {...props}\n    >\n      <span className=\"text-xs text-muted-foreground\">{label}</span>\n      <span className=\"text-sm font-medium tabular-nums\">\n        {currency}\n        {amount.toLocaleString(\"en-US\", {\n          minimumFractionDigits: 2,\n          maximumFractionDigits: 2,\n        })}\n        {limit !== undefined && (\n          <span className=\"text-muted-foreground\">\n            {\" / \"}\n            {currency}\n            {limit.toLocaleString(\"en-US\", {\n              minimumFractionDigits: 0,\n              maximumFractionDigits: 0,\n            })}\n          </span>\n        )}\n      </span>\n    </div>\n  ),\n);\nUsageCardLabel.displayName = \"UsageCardLabel\";\n\ninterface UsageCardProgressProps\n  extends Omit<React.ComponentPropsWithoutRef<typeof Progress>, \"value\"> {\n  value: number;\n  max?: number;\n  showOverage?: boolean;\n}\n\nconst UsageCardProgress = React.forwardRef<\n  React.ComponentRef<typeof Progress>,\n  UsageCardProgressProps\n>(({ className, value, max = 100, showOverage = false, ...props }, ref) => {\n  const percentage = Math.min((value / max) * 100, 100);\n  const isOverage = value > max;\n\n  return (\n    <Progress\n      ref={ref}\n      value={percentage}\n      className={cn(\n        \"h-2 bg-muted\",\n        isOverage && \"*:data-[slot=progress-indicator]:bg-destructive\",\n        className,\n      )}\n      {...props}\n    />\n  );\n});\nUsageCardProgress.displayName = \"UsageCardProgress\";\n\ninterface UsageCardListContextValue {\n  expanded: boolean;\n  setExpanded: (expanded: boolean) => void;\n  itemCount: number;\n  collapsedHeight: number;\n  expandedHeight: number;\n}\n\nconst UsageCardListContext =\n  React.createContext<UsageCardListContextValue | null>(null);\n\nfunction useUsageCardList() {\n  const context = React.useContext(UsageCardListContext);\n  if (!context) {\n    throw new Error(\"useUsageCardList must be used within UsageCardList\");\n  }\n  return context;\n}\n\nconst ITEM_HEIGHT = 44;\n\ninterface UsageCardListProps extends React.HTMLAttributes<HTMLDivElement> {\n  defaultExpanded?: boolean;\n  /** Number of items to show when collapsed (can be decimal like 1.5 to show partial item) */\n  visibleItems?: number;\n  /** Enable collapse/expand functionality */\n  collapsible?: boolean;\n  /** Show dividers between items */\n  dividers?: boolean;\n}\n\nconst UsageCardList = React.forwardRef<HTMLDivElement, UsageCardListProps>(\n  (\n    {\n      className,\n      defaultExpanded = false,\n      visibleItems = 1.5,\n      collapsible = false,\n      dividers = true,\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    const [expanded, setExpanded] = React.useState(defaultExpanded);\n    const childrenArray = React.Children.toArray(children).filter((child) =>\n      React.isValidElement(child),\n    );\n    const itemCount = childrenArray.length;\n\n    const collapsedHeight = visibleItems * ITEM_HEIGHT;\n    const expandedHeight = itemCount * ITEM_HEIGHT;\n\n    return (\n      <UsageCardListContext.Provider\n        value={{\n          expanded,\n          setExpanded,\n          itemCount,\n          collapsedHeight,\n          expandedHeight,\n        }}\n      >\n        <div\n          ref={ref}\n          className={cn(\"relative\", collapsible && \"pb-4\", className)}\n          {...props}\n        >\n          {/* Content container */}\n          <div\n            className={cn(\n              \"overflow-hidden transition-[max-height] duration-300 ease-out\",\n              dividers && \"divide-y divide-border\",\n            )}\n            style={{\n              maxHeight:\n                collapsible && !expanded\n                  ? `${collapsedHeight}px`\n                  : `${expandedHeight}px`,\n            }}\n          >\n            {childrenArray}\n          </div>\n\n          {/* Fade overlay when collapsed */}\n          {collapsible && (\n            <div\n              className={cn(\n                \"pointer-events-none absolute inset-x-0 bottom-4 bg-linear-to-t from-card via-card/80 to-transparent transition-opacity duration-300\",\n                expanded ? \"opacity-0\" : \"opacity-100\",\n              )}\n              style={{ height: `${collapsedHeight * 0.6}px` }}\n            />\n          )}\n\n          {/* Toggle button - centered on bottom border */}\n          {collapsible && itemCount > 1 && (\n            <button\n              type=\"button\"\n              onClick={() => setExpanded(!expanded)}\n              className=\"absolute left-1/2 bottom-0 -translate-x-1/2 translate-y-1/2 z-10 flex h-7 w-7 items-center justify-center rounded-full border border-border bg-card text-muted-foreground shadow-sm hover:bg-muted hover:text-foreground transition-colors\"\n              aria-label={expanded ? \"Collapse\" : \"Expand\"}\n            >\n              {expanded ? (\n                <ChevronUp className=\"h-4 w-4\" />\n              ) : (\n                <ChevronDown className=\"h-4 w-4\" />\n              )}\n            </button>\n          )}\n        </div>\n      </UsageCardListContext.Provider>\n    );\n  },\n);\nUsageCardList.displayName = \"UsageCardList\";\n\ninterface UsageCardItemProps extends React.HTMLAttributes<HTMLDivElement> {\n  highlighted?: boolean;\n}\n\nconst UsageCardItem = React.forwardRef<HTMLDivElement, UsageCardItemProps>(\n  ({ className, highlighted = false, children, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn(\n          \"flex items-center justify-between gap-4 px-4 py-3 transition-colors\",\n          highlighted && \"bg-muted/50\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </div>\n    );\n  },\n);\nUsageCardItem.displayName = \"UsageCardItem\";\n\ninterface UsageCardItemLabelProps\n  extends React.HTMLAttributes<HTMLSpanElement> {}\n\nconst UsageCardItemLabel = React.forwardRef<\n  HTMLSpanElement,\n  UsageCardItemLabelProps\n>(({ className, ...props }, ref) => (\n  <span\n    ref={ref}\n    className={cn(\"text-sm text-foreground truncate\", className)}\n    {...props}\n  />\n));\nUsageCardItemLabel.displayName = \"UsageCardItemLabel\";\n\ninterface UsageCardItemValueProps\n  extends React.HTMLAttributes<HTMLSpanElement> {\n  amount?: number;\n  currency?: string;\n  unit?: string;\n}\n\nconst UsageCardItemValue = React.forwardRef<\n  HTMLSpanElement,\n  UsageCardItemValueProps\n>(({ className, amount, currency = \"$\", unit, children, ...props }, ref) => (\n  <span\n    ref={ref}\n    className={cn(\n      \"text-sm font-medium tabular-nums text-muted-foreground shrink-0\",\n      className,\n    )}\n    {...props}\n  >\n    {children ??\n      (amount !== undefined ? (\n        <>\n          {currency}\n          {amount.toLocaleString(\"en-US\", {\n            minimumFractionDigits: 2,\n            maximumFractionDigits: 2,\n          })}\n          {unit && <span className=\"text-xs ml-0.5\">{unit}</span>}\n        </>\n      ) : null)}\n  </span>\n));\nUsageCardItemValue.displayName = \"UsageCardItemValue\";\n\n// Metric bar for showing usage with visual indicator\ninterface UsageCardMeterProps extends React.HTMLAttributes<HTMLDivElement> {\n  used: number;\n  limit: number;\n  label: string;\n  unit?: string;\n  showPercentage?: boolean;\n}\n\nconst UsageCardMeter = React.forwardRef<HTMLDivElement, UsageCardMeterProps>(\n  (\n    { className, used, limit, label, unit, showPercentage = false, ...props },\n    ref,\n  ) => {\n    const percentage = Math.min((used / limit) * 100, 100);\n    const isWarning = percentage >= 80;\n    const isCritical = percentage >= 95;\n\n    return (\n      <div\n        ref={ref}\n        className={cn(\"px-4 py-3 space-y-2\", className)}\n        {...props}\n      >\n        <div className=\"flex items-center justify-between gap-2\">\n          <span className=\"text-sm text-foreground\">{label}</span>\n          <span className=\"text-sm tabular-nums text-muted-foreground\">\n            {used.toLocaleString()}\n            {unit && ` ${unit}`}\n            <span className=\"text-muted-foreground/60\">\n              {\" \"}\n              / {limit.toLocaleString()}\n              {unit && ` ${unit}`}\n            </span>\n            {showPercentage && (\n              <span\n                className={cn(\n                  \"ml-2\",\n                  isCritical\n                    ? \"text-destructive\"\n                    : isWarning\n                      ? \"text-amber-500\"\n                      : \"text-muted-foreground\",\n                )}\n              >\n                ({percentage.toFixed(0)}%)\n              </span>\n            )}\n          </span>\n        </div>\n        <div className=\"relative h-1.5 w-full overflow-hidden rounded-full bg-muted\">\n          <div\n            className={cn(\n              \"h-full rounded-full transition-all duration-500 ease-out\",\n              isCritical\n                ? \"bg-destructive\"\n                : isWarning\n                  ? \"bg-amber-500\"\n                  : \"bg-primary\",\n            )}\n            style={{ width: `${percentage}%` }}\n          />\n        </div>\n      </div>\n    );\n  },\n);\nUsageCardMeter.displayName = \"UsageCardMeter\";\n\n// Total row for the bottom\ninterface UsageCardTotalProps extends React.HTMLAttributes<HTMLDivElement> {\n  label?: string;\n  amount: number;\n  currency?: string;\n}\n\nconst UsageCardTotal = React.forwardRef<HTMLDivElement, UsageCardTotalProps>(\n  ({ className, label = \"Total\", amount, currency = \"$\", ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(\n        \"flex items-center justify-between gap-4 px-4 py-3 bg-muted/30 border-t border-border\",\n        className,\n      )}\n      {...props}\n    >\n      <span className=\"text-sm font-medium text-foreground\">{label}</span>\n      <span className=\"text-sm font-semibold tabular-nums\">\n        {currency}\n        {amount.toLocaleString(\"en-US\", {\n          minimumFractionDigits: 2,\n          maximumFractionDigits: 2,\n        })}\n      </span>\n    </div>\n  ),\n);\nUsageCardTotal.displayName = \"UsageCardTotal\";\n\nexport {\n  UsageCard,\n  UsageCardHeader,\n  UsageCardPeriod,\n  UsageCardAction,\n  UsageCardSummary,\n  UsageCardLabels,\n  UsageCardLabel,\n  UsageCardProgress,\n  UsageCardList,\n  UsageCardItem,\n  UsageCardItemLabel,\n  UsageCardItemValue,\n  UsageCardMeter,\n  UsageCardTotal,\n  usageCardVariants,\n  useUsageCardList,\n};\n\nexport type {\n  UsageCardProps,\n  UsageCardHeaderProps,\n  UsageCardPeriodProps,\n  UsageCardActionProps,\n  UsageCardSummaryProps,\n  UsageCardLabelsProps,\n  UsageCardLabelProps,\n  UsageCardProgressProps,\n  UsageCardListProps,\n  UsageCardItemProps,\n  UsageCardItemLabelProps,\n  UsageCardItemValueProps,\n  UsageCardMeterProps,\n  UsageCardTotalProps,\n  UsageCardListContextValue,\n};\n",
      "type": "registry:ui",
      "target": "components/ui/usage-card.tsx"
    },
    {
      "path": "src/registry/lib/utils.ts",
      "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n",
      "type": "registry:lib",
      "target": "lib/utils.ts"
    }
  ],
  "dependencies": [
    "class-variance-authority",
    "lucide-react",
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [
    "button",
    "progress"
  ]
}