{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "usage-overview-card",
  "type": "registry:block",
  "title": "Usage overview card",
  "description": "Host-authoritative budget figure and meter, metrics, and expandable connection rows with distinct known, partial, unknown and over-limit readings.",
  "registryDependencies": [
    "card"
  ],
  "dependencies": [
    "@usagekit/react@0.9.1",
    "@usagekit/views@0.9.1",
    "@usagekit/core@0.9.1"
  ],
  "files": [
    {
      "path": "registry/radix/usage-overview-card/usage-overview-card.tsx",
      "type": "registry:component",
      "target": "@components/usagekit/usage-overview-card.tsx",
      "content": "\"use client\";\n\nimport { Children } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { UsageMark, UsageMeter } from \"@/components/usagekit/usage-meter\";\nimport { UsageStatus, usageMotion } from \"@/components/usagekit/usage-motion\";\nimport type { UsageTone } from \"@/components/usagekit/usage-motion\";\nimport { severerLevel, usageProgress } from \"@/components/usagekit/usage-progress\";\nimport type { UsageProgress } from \"@/components/usagekit/usage-progress\";\n\nexport const usageOverviewCardLabels = {\n  unknown: \"Usage unknown\",\n  empty: \"No connections yet.\",\n  ok: \"Within budget\",\n  warning: \"Near limit\",\n  exceeded: \"Over limit\",\n  partial: \"Still measuring\",\n  loading: \"Loading usage.\",\n};\nexport type UsageOverviewCardLabels = typeof usageOverviewCardLabels;\nexport type UsageOverviewCardProps = {\n  title: string;\n  description?: string;\n  period?: string;\n  id?: string;\n  className?: string;\n  action?: ReactNode;\n  introduction?: ReactNode;\n  notice?: { message: string; action?: ReactNode };\n  budget: {\n    label: string;\n    /** Complete localized reading; announced by the meter and shown when no figure is given. */\n    value: string;\n    /** Short display figure such as \"28%\" or \"At least 62%\". */\n    figure?: string;\n    /** Small words before the figure, such as \"At least\" for a partial reading. */\n    qualifier?: string;\n    /** Context under the figure, such as the tightest connection. */\n    caption?: string;\n    /** Status words; defaults to the level labels. */\n    status?: string;\n    explanation?: string;\n    percent: number | null;\n    partial: boolean;\n    meterLabel?: string;\n    /** Percent where the warning level starts; omit to hide the mark. */\n    warningAt?: number | null;\n    /** Severity the host knows beyond the percent, such as reserved usage; the severer level shows. */\n    level?: UsageProgress[\"level\"];\n  };\n  metrics: readonly { id: string; label: string; value: string }[];\n  /** Connection list items supplied by the host, usually UsageConnectionRow. */\n  children?: ReactNode;\n  empty?: string;\n  emptyAction?: ReactNode;\n  /** Initial read in progress: placeholders keep the layout instead of empty figures. */\n  loading?: boolean;\n  /** Headline figure size: \"lg\" leads a page, \"md\" and \"sm\" suit denser hosts. */\n  size?: \"sm\" | \"md\" | \"lg\";\n  labels?: Partial<UsageOverviewCardLabels>;\n};\n\nconst figureSize = { sm: \"text-2xl tracking-tight\", md: \"text-3xl leading-none tracking-tight\", lg: \"text-4xl leading-none tracking-tighter @xl:text-5xl\" };\n\nconst placeholder = \"rounded-md bg-accent block animate-pulse motion-reduce:animate-none\";\n\n/** Shared usage framing; accounting, localized values and authority stay with the host. */\nexport function UsageOverviewCard({\n  title,\n  description,\n  period,\n  id,\n  className,\n  action,\n  introduction,\n  notice,\n  budget,\n  metrics,\n  children,\n  empty,\n  emptyAction,\n  loading = false,\n  size = \"lg\",\n  labels: custom,\n}: UsageOverviewCardProps) {\n  const labels = { ...usageOverviewCardLabels, ...custom };\n  const progress = usageProgress(budget.percent, budget.partial);\n  const level = severerLevel(progress.level, budget.level);\n  const unknown = progress.kind === \"unknown\";\n  // A partial reading below the warning point cannot confirm that usage is within budget.\n  const settling = progress.kind === \"partial\" && level === \"ok\";\n  const tone: UsageTone = unknown\n    ? \"unknown\"\n    : progress.kind === \"none\" || settling\n      ? \"neutral\"\n      : level === \"ok\"\n        ? \"positive\"\n        : level;\n  const status =\n    budget.status ??\n    (unknown || progress.kind === \"none\" ? null : settling ? labels.partial : labels[level]);\n  const figure = unknown ? labels.unknown : (budget.figure ?? budget.value);\n  const hasConnections = Children.toArray(children).length > 0;\n  const emptyText = empty ?? labels.empty;\n  return (\n    <Card\n      id={id}\n      data-usagekit=\"usage-overview-card\"\n      data-level={progress.kind === \"none\" || unknown ? progress.kind : level}\n      aria-busy={loading || undefined}\n      className={`min-h-0 w-full min-w-0 overflow-hidden ${className ?? \"\"}`}\n    >\n      <CardHeader>\n        <div className=\"flex min-w-0 flex-wrap items-start justify-between gap-3\">\n          <div className=\"min-w-48 flex-1 space-y-1\">\n            <CardTitle role=\"heading\" aria-level={2} className=\"break-words\">\n              {title}\n            </CardTitle>\n            {description && (\n              <CardDescription className=\"max-w-prose\">{description}</CardDescription>\n            )}\n            {period && <p className=\"text-xs/relaxed text-muted-foreground tabular-nums\">{period}</p>}\n          </div>\n          {action && <div className=\"flex max-w-full flex-wrap items-center gap-2\">{action}</div>}\n        </div>\n      </CardHeader>\n      <CardContent className=\"gap-6 flex min-w-0 flex-col\">\n        {notice && (\n          <div\n            role=\"alert\"\n            className={`rounded-lg border px-4 py-3 text-sm flex min-w-0 flex-wrap items-start gap-x-[0.75em] gap-y-1 border-destructive/30 bg-destructive/5 ${usageMotion.enter}`}\n          >\n            <svg\n              aria-hidden\n              viewBox=\"0 0 16 16\"\n              className=\"mt-[0.15em] size-[1.15em] shrink-0 text-destructive\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"1.5\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M8 1.75 14.75 13.5H1.25L8 1.75Z\" />\n              <path d=\"M8 6.25v3M8 11.5v.01\" />\n            </svg>\n            <span className=\"min-w-0 flex-1 basis-48 break-words font-semibold leading-snug\">\n              {notice.message}\n            </span>\n            {notice.action && <span className=\"shrink-0 leading-snug\">{notice.action}</span>}\n          </div>\n        )}\n        {loading ? (\n          <div role=\"status\" className=\"@container min-w-0\">\n            <span className=\"sr-only\">{labels.loading}</span>\n            <div\n              aria-hidden\n              className=\"grid min-w-0 gap-6 @4xl:grid-cols-[minmax(0,1fr)_minmax(12rem,16rem)] @4xl:gap-10\"\n            >\n              <span className=\"block min-w-0\">\n                <span className={`${placeholder} h-4 w-24`} />\n                <span className={`${placeholder} mt-3 h-10 w-32`} />\n                <span className={`${placeholder} mt-3 h-4 w-56 max-w-full`} />\n                <span className=\"rounded-full bg-primary/20 h-2.5 mt-5 block w-full animate-pulse motion-reduce:animate-none\" />\n              </span>\n              <span className=\"grid min-w-0 grid-cols-2 content-start gap-x-6 gap-y-5 border-t border-border pt-5 @xl:grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] @4xl:grid-cols-1 @4xl:gap-y-4 @4xl:border-t-0 @4xl:border-l @4xl:pt-0 @4xl:pl-8\">\n                {[0, 1, 2].map((key) => (\n                  <span key={key} className=\"block\">\n                    <span className={`${placeholder} h-3 w-20`} />\n                    <span className={`${placeholder} mt-2 h-5 w-24`} />\n                  </span>\n                ))}\n              </span>\n            </div>\n          </div>\n        ) : (\n          <div className=\"@container min-w-0\">\n            <div className=\"grid min-w-0 gap-6 @4xl:grid-cols-[minmax(0,1fr)_minmax(12rem,16rem)] @4xl:gap-10\">\n              <section aria-label={budget.label} className=\"min-w-0\">\n                <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-x-3 gap-y-1\">\n                  <span className=\"text-sm text-muted-foreground\">{budget.label}</span>\n                  {status && (\n                    <UsageStatus key={status} tone={tone} className={usageMotion.enter}>\n                      {status}\n                    </UsageStatus>\n                  )}\n                </div>\n                <p\n                  key={`${budget.qualifier ?? \"\"}${figure}`}\n                  className={`mt-2 flex min-w-0 flex-wrap items-baseline gap-x-2 ${usageMotion.enter}`}\n                >\n                  {budget.qualifier && !unknown && (\n                    <span className=\"text-sm font-medium text-muted-foreground\">\n                      {budget.qualifier}{\" \"}\n                    </span>\n                  )}\n                  <span\n                    className={`min-w-0 break-words font-semibold tabular-nums ${unknown ? \"text-2xl tracking-tight text-muted-foreground\" : budget.figure ? figureSize[size] : \"text-2xl tracking-tight\"} ${level === \"exceeded\" && !unknown ? \"text-destructive\" : \"\"}`}\n                  >\n                    {figure}\n                  </span>\n                </p>\n                {budget.caption && !unknown && (\n                  <p className=\"text-sm mt-2 min-w-0 break-words text-muted-foreground\">\n                    {budget.caption}\n                  </p>\n                )}\n                {progress.kind !== \"none\" && (\n                  <UsageMeter\n                    size=\"lg\"\n                    percent={budget.percent}\n                    partial={budget.partial}\n                    level={budget.level}\n                    label={budget.meterLabel ?? budget.label}\n                    valueText={budget.value}\n                    className=\"mt-5\"\n                    marks={\n                      budget.warningAt !== undefined && budget.warningAt !== null ? (\n                        <UsageMark at={`${budget.warningAt}%`} />\n                      ) : null\n                    }\n                  />\n                )}\n                {budget.explanation && (\n                  <p className=\"text-xs/relaxed mt-3 max-w-prose text-muted-foreground\">\n                    {budget.explanation}\n                  </p>\n                )}\n              </section>\n              {metrics.length > 0 && (\n                <dl className=\"grid min-w-0 grid-cols-2 content-start gap-x-6 gap-y-5 border-t border-border pt-5 @xl:grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] @4xl:grid-cols-1 @4xl:gap-y-4 @4xl:border-t-0 @4xl:border-l @4xl:pt-0 @4xl:pl-8\">\n                  {metrics.map((metric, index) => (\n                    <div key={metric.id} className=\"min-w-0 space-y-1\">\n                      <dt className=\"text-xs text-muted-foreground\">{metric.label}</dt>\n                      <dd\n                        key={metric.value}\n                        className={`break-words font-semibold tabular-nums ${index === 0 ? \"text-lg leading-snug\" : \"text-base leading-snug\"} ${usageMotion.enter}`}\n                      >\n                        {metric.value}\n                      </dd>\n                    </div>\n                  ))}\n                </dl>\n              )}\n            </div>\n          </div>\n        )}\n        {hasConnections ? (\n          <ul className=\"m-0 min-w-0 list-none divide-y divide-border border-t border-border p-0\">\n            {children}\n          </ul>\n        ) : (\n          (emptyText || emptyAction) &&\n          !loading && (\n            <div className=\"rounded-lg border border-dashed px-4 py-3.5 flex min-w-0 flex-wrap items-center justify-between gap-3 border-border\">\n              {emptyText && (\n                <p className=\"text-sm min-w-0 text-muted-foreground\">{emptyText}</p>\n              )}\n              {emptyAction}\n            </div>\n          )\n        )}\n        {introduction && (\n          <div className=\"min-w-0 space-y-2 border-t border-border pt-5\">{introduction}</div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n"
    },
    {
      "path": "registry/radix/usage-connection-row/usage-connection-row.tsx",
      "type": "registry:component",
      "target": "@components/usagekit/usage-connection-row.tsx",
      "content": "\"use client\";\n\nimport { Fragment, useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { UsageMeter } from \"@/components/usagekit/usage-meter\";\nimport {\n  UsageChevron,\n  UsageReveal,\n  UsageStatus,\n  usageMotion,\n} from \"@/components/usagekit/usage-motion\";\nimport type { UsageTone } from \"@/components/usagekit/usage-motion\";\nimport { usageProgress } from \"@/components/usagekit/usage-progress\";\n\nexport type UsageReading = {\n  id: string;\n  label: string;\n  /** Localized reading, such as \"28 of 100 searches used\" or \"No cap\". */\n  value: string;\n  /** Percent of the limit; null when the reading has no limit. */\n  percent: number | null;\n  partial?: boolean;\n  meterLabel?: string;\n};\nexport type UsageReadingGroup = {\n  id: string;\n  label?: string;\n  /** Inactive groups stay readable but recede, such as a funding source not in use. */\n  active?: boolean;\n  readings: readonly UsageReading[];\n  note?: ReactNode;\n  empty?: string;\n};\nexport type UsageBreakdownItem = {\n  id: string;\n  label: string;\n  value: string;\n  tags?: readonly string[];\n};\nexport const usageConnectionRowLabels = { unknown: \"Unknown\" };\nexport type UsageConnectionRowLabels = typeof usageConnectionRowLabels;\nexport type UsageConnectionRowProps = {\n  name: string;\n  tags?: readonly string[];\n  status?: { label: string; tone: UsageTone };\n  /** The reading summarized in the collapsed row, usually the tightest limit. */\n  summary?: { value: string; percent: number | null; partial?: boolean };\n  groups?: readonly UsageReadingGroup[];\n  /** Always visible below the summary, such as delayed reconciliation. */\n  notice?: ReactNode;\n  notes?: ReactNode;\n  breakdown?: readonly UsageBreakdownItem[];\n  /** Additional host details shown when the row is open. */\n  children?: ReactNode;\n  defaultOpen?: boolean;\n  /** Position in the list, used to stagger the first settle. */\n  index?: number;\n  labels?: Partial<UsageConnectionRowLabels>;\n};\n\n/** One connection inside UsageOverviewCard: a summary line that unfolds its readings. */\nexport function UsageConnectionRow({\n  name,\n  tags = [],\n  status,\n  summary,\n  groups = [],\n  notice,\n  notes,\n  breakdown = [],\n  children,\n  defaultOpen = false,\n  index = 0,\n  labels: custom,\n}: UsageConnectionRowProps) {\n  const labels = { ...usageConnectionRowLabels, ...custom };\n  const id = useId();\n  // An unknown summary never shows a host figure such as \"0%\".\n  const summaryText =\n    summary && usageProgress(summary.percent, summary.partial ?? false).kind === \"unknown\"\n      ? labels.unknown\n      : summary?.value;\n  const [open, setOpen] = useState(defaultOpen);\n  // Each opening remounts the readings so their meters settle in view.\n  const [opened, setOpened] = useState(0);\n  const toggle = () => {\n    if (!open) setOpened(opened + 1);\n    setOpen(!open);\n  };\n  return (\n    <li className=\"min-w-0\" data-open={open}>\n      <div className=\"-mx-2\">\n        <button\n          type=\"button\"\n          aria-expanded={open}\n          aria-controls={`${id}-details`}\n          onClick={toggle}\n          className={`rounded-md py-3.5 hover:bg-accent/50 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 px-2 text-left ${usageMotion.respond}`}\n        >\n          {/* Spaces between the parts keep the accessible name readable in every engine. */}\n          <span className=\"flex min-w-0 flex-wrap items-center gap-x-4 gap-y-2\">\n            <span className=\"flex min-w-0 flex-1 basis-40 flex-wrap items-center gap-2\">\n              <span className=\"text-sm min-w-0 break-words font-semibold\">{name}</span>\n              {tags.map((tag) => (\n                <Fragment key={tag}>\n                  {\" \"}\n                  <span className=\"h-5 rounded-full border border-border px-2 text-xs font-medium text-muted-foreground inline-flex items-center\">{tag}</span>\n                </Fragment>\n              ))}\n            </span>{\" \"}\n            <span className=\"flex min-w-0 flex-wrap items-center gap-x-4 gap-y-2\">\n              {status && <UsageStatus tone={status.tone}>{status.label}</UsageStatus>}{\" \"}\n              {summary && (\n                <span className=\"flex items-center gap-3\">\n                  <UsageMeter\n                    size=\"md\"\n                    percent={summary.percent}\n                    partial={summary.partial}\n                    delay={120 + index * 70}\n                    className=\"w-16 sm:w-24\"\n                  />\n                  <span className=\"text-sm min-w-10 text-right font-medium tabular-nums\">\n                    {summaryText}\n                  </span>\n                </span>\n              )}\n            </span>\n          </span>\n          <UsageChevron open={open} className=\"text-muted-foreground\" />\n        </button>\n      </div>\n      {notice && (\n        <p className=\"text-xs/relaxed flex min-w-0 items-start gap-[0.4em] pb-3\">\n          <svg\n            aria-hidden\n            viewBox=\"0 0 16 16\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.5\"\n            strokeLinecap=\"round\"\n            className=\"mt-[0.15em] size-[1.15em] shrink-0 text-chart-4\"\n          >\n            <circle cx=\"8\" cy=\"8\" r=\"6\" />\n            <path d=\"M8 4.75v3.75M8 11v.01\" />\n          </svg>\n          <span className=\"min-w-0 break-words\">{notice}</span>\n        </p>\n      )}\n      <UsageReveal open={open} id={`${id}-details`}>\n        <div key={opened} className=\"gap-4 flex min-w-0 flex-col pb-5 pt-1\">\n          {groups.map((group) => (\n            <div\n              key={group.id}\n              data-active={group.active === false ? \"false\" : \"true\"}\n              className={`gap-3 flex min-w-0 flex-col ${group.active === false ? \"opacity-70\" : \"\"}`}\n            >\n              {group.label && (\n                <p className=\"text-xs font-medium text-muted-foreground\">{group.label}</p>\n              )}\n              {group.readings.length > 0 ? (\n                <dl className=\"grid min-w-0 grid-cols-[minmax(5.5rem,auto)_minmax(3rem,1fr)] items-center gap-x-4 gap-y-2 sm:grid-cols-[minmax(7rem,auto)_minmax(6rem,1fr)_minmax(0,auto)]\">\n                  {group.readings.map((reading, at) => (\n                    <Fragment key={reading.id}>\n                      <dt className=\"text-xs min-w-0 break-words text-muted-foreground\">\n                        {reading.label}\n                      </dt>\n                      <dd className=\"min-w-0\">\n                        <UsageMeter\n                          size=\"md\"\n                          percent={reading.percent}\n                          partial={reading.partial}\n                          label={reading.meterLabel ?? `${name} ${reading.label}`}\n                          valueText={reading.value}\n                          delay={at * 70}\n                        />\n                      </dd>\n                      <dd\n                        className={`text-xs/relaxed col-span-2 min-w-0 break-words tabular-nums sm:col-span-1 sm:text-right ${reading.percent !== null && reading.percent >= 100 ? \"text-destructive\" : \"\"}`}\n                      >\n                        {reading.value}\n                      </dd>\n                    </Fragment>\n                  ))}\n                </dl>\n              ) : (\n                group.empty && <p className=\"text-xs/relaxed text-muted-foreground\">{group.empty}</p>\n              )}\n              {group.note && (\n                <p className=\"text-xs/relaxed text-muted-foreground tabular-nums\">{group.note}</p>\n              )}\n            </div>\n          ))}\n          {notes && (\n            <div className=\"text-xs/relaxed flex min-w-0 flex-col gap-1 text-muted-foreground\">\n              {notes}\n            </div>\n          )}\n          {breakdown.length > 0 && (\n            <dl className=\"rounded-lg bg-muted/50 px-3.5 py-3 grid min-w-0 gap-x-6 gap-y-4 sm:grid-cols-2 xl:grid-cols-3\">\n              {breakdown.map((item) => (\n                <div key={item.id} className=\"min-w-0\">\n                  <dt className=\"text-xs text-muted-foreground\">{item.label}</dt>\n                  <dd className=\"text-sm mt-1 break-words font-semibold tabular-nums\">\n                    {item.value}\n                  </dd>\n                  {item.tags && item.tags.length > 0 && (\n                    <dd className=\"mt-2 flex flex-wrap gap-1.5\">\n                      {item.tags.map((tag) => (\n                        <span\n                          key={tag}\n                          className=\"h-5 rounded-full border border-border px-2 text-xs font-medium text-muted-foreground inline-flex items-center tabular-nums\"\n                        >\n                          {tag}\n                        </span>\n                      ))}\n                    </dd>\n                  )}\n                </div>\n              ))}\n            </dl>\n          )}\n          {children}\n        </div>\n      </UsageReveal>\n    </li>\n  );\n}\n"
    },
    {
      "path": "registry/radix/usage-meter/usage-meter.tsx",
      "type": "registry:component",
      "target": "@components/usagekit/usage-meter.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps, CSSProperties, ReactNode } from \"react\";\nimport { severerLevel, usageProgress } from \"@/components/usagekit/usage-progress\";\nimport type { UsageProgress } from \"@/components/usagekit/usage-progress\";\n\nexport type UsageLevel = \"ok\" | \"warning\" | \"exceeded\";\nexport type UsageMeterSize = \"lg\" | \"md\" | \"sm\";\n\n/** Fill tone per budget level, shared by every meter. */\nexport const usageFill: Record<UsageLevel, string> = {\n  ok: \"bg-primary\",\n  warning: \"bg-chart-4\",\n  exceeded: \"bg-destructive\",\n};\nconst hatchTone: Record<UsageLevel, string> = {\n  ok: \"text-primary\",\n  warning: \"text-chart-4\",\n  exceeded: \"text-destructive\",\n};\n// Track shape, colour and heights come from the host's shadcn style, like its progress bar.\nconst height: Record<UsageMeterSize, string> = {\n  lg: \"h-2.5\",\n  md: \"h-2\",\n  sm: \"h-1.5\",\n};\nconst tail: Record<UsageMeterSize, string> = { lg: \"2.5rem\", md: \"1rem\", sm: \"0.5rem\" };\nconst hatch = \"bg-[repeating-linear-gradient(-45deg,currentColor_0_1px,transparent_1px_4px)]\";\n// Layers are full-width and translated, so their ends keep the track's shape and motion stays on\n// the compositor.\nconst layer =\n  \"absolute inset-0 rounded-[inherit] transition-[translate,background-color] duration-700 ease-out delay-[var(--usage-delay)] starting:-translate-x-full motion-reduce:transition-none\";\n\nexport type UsageTrackProps = Omit<ComponentProps<\"span\">, \"children\"> & {\n  size?: UsageMeterSize;\n  level: UsageLevel;\n  /** Confirmed extent as CSS percent text, for example \"28%\" or \"12.5%\". */\n  fill: string;\n  /** Reserved extent continuing after the fill, as CSS percent text. */\n  reserved?: string;\n  /** Lower-bound reading: a hatched tail shows that the total may be higher. */\n  partial?: boolean;\n  /** The reading passed its limit; a notch past the end of the scale marks the overflow. */\n  over?: boolean;\n  /** Scale marks such as thresholds; drawn above the fill and never clipped. */\n  marks?: ReactNode;\n  /** Settle delay in milliseconds, used to stagger related meters. */\n  delay?: number;\n  /** A nonzero reading keeps a visible trace even when it rounds to an empty bar. */\n  trace?: boolean;\n};\n\n/**\n * Meter geometry only. Callers own the semantics: role=\"meter\" or decorative with nearby text.\n * The track is a block: it fills block containers, and flex rows give it an explicit width.\n */\nexport function UsageTrack({\n  size = \"md\",\n  level,\n  fill,\n  reserved,\n  partial = false,\n  over = false,\n  marks,\n  delay = 0,\n  trace = false,\n  className = \"\",\n  style,\n  ...props\n}: UsageTrackProps) {\n  return (\n    <span\n      {...props}\n      data-usage-track={level}\n      className={`relative block min-w-0 ${height[size]} ${className}`}\n      style={\n        {\n          \"--usage-fill\": fill,\n          \"--usage-reserved\": reserved ?? \"0%\",\n          \"--usage-tail\": tail[size],\n          \"--usage-delay\": `${delay}ms`,\n          \"--usage-min\": trace ? \"0.25rem\" : \"0px\",\n          ...style,\n        } as CSSProperties\n      }\n    >\n      <span className=\"rounded-full bg-primary/20 absolute inset-0 overflow-hidden\">\n        {reserved && (\n          <span\n            className={`${layer} ${usageFill[level]} opacity-35 translate-x-[calc(var(--usage-fill)_+_var(--usage-reserved)_-_100%)]`}\n          />\n        )}\n        {partial && (\n          <span\n            className={`${layer} ${hatchTone[level]} ${hatch} opacity-80 [mask-image:linear-gradient(to_left,transparent,black_var(--usage-tail))] translate-x-[calc(max(var(--usage-fill),var(--usage-min))_+_var(--usage-tail)_-_100%)]`}\n          />\n        )}\n        <span\n          className={`${layer} ${usageFill[level]} translate-x-[calc(max(var(--usage-fill),var(--usage-min))_-_100%)]`}\n        />\n      </span>\n      {over && (\n        <span\n          aria-hidden\n          data-usage-over\n          className=\"rounded-full absolute -right-1 -top-[3px] h-[calc(100%+6px)] w-[3px] bg-destructive transition-[opacity,scale] delay-500 duration-300 ease-out starting:scale-y-0 starting:opacity-0 motion-reduce:transition-none\"\n        />\n      )}\n      {marks}\n    </span>\n  );\n}\n\n/**\n * A threshold on the scale, such as the 80 percent warning point or an alert. A ring in the\n * surface color cuts it into the fill, so a mark stays visible in a fill of its own tone.\n */\nexport function UsageMark({\n  at,\n  label,\n  tone = \"bg-foreground/40\",\n}: {\n  /** Position as CSS percent text. */\n  at: string;\n  /** Accessible description; omit when the threshold is described in nearby text. */\n  label?: string;\n  tone?: string;\n}) {\n  return (\n    <span\n      role={label ? \"img\" : undefined}\n      aria-label={label}\n      aria-hidden={label ? undefined : true}\n      className={`absolute -top-[3px] h-[calc(100%+6px)] w-px -translate-x-1/2 ring-1 ring-card ${tone}`}\n      style={{ left: at }}\n    />\n  );\n}\n\n/** Track for a reading that is not known: hatched and empty, never a zero fill. */\nexport function UsageUnknownTrack({\n  size = \"md\",\n  className = \"\",\n}: {\n  size?: UsageMeterSize;\n  className?: string;\n}) {\n  return (\n    <span\n      aria-hidden\n      data-usage-track=\"unknown\"\n      className={`rounded-full bg-primary/20 block min-w-0 overflow-hidden text-muted-foreground/30 ${hatch} ${height[size]} ${className}`}\n    />\n  );\n}\n\n/** Baseline for an uncapped reading: there is no scale to fill. */\nexport function UsageNoCapTrack({\n  size = \"md\",\n  className = \"\",\n}: {\n  size?: UsageMeterSize;\n  className?: string;\n}) {\n  return (\n    <span\n      aria-hidden\n      data-usage-track=\"none\"\n      className={`relative block min-w-0 ${height[size]} ${className}`}\n    >\n      <span className=\"absolute inset-x-0 top-1/2 border-t border-dashed border-muted-foreground/40\" />\n    </span>\n  );\n}\n\nexport type UsageMeterProps = {\n  /** Host-observed percent of the limit; null means there is no limit to measure against. */\n  percent: number | null;\n  /** The percent is a confirmed lower bound while some usage is still unmeasured. */\n  partial?: boolean;\n  size?: UsageMeterSize;\n  /** Accessible name. Without it the meter is decorative and nearby text carries the reading. */\n  label?: string;\n  /** Localized reading announced for the meter, such as \"At least 62%\". */\n  valueText?: string;\n  /** Severity the host knows beyond the percent, such as reserved usage; the severer level shows. */\n  level?: UsageProgress[\"level\"];\n  marks?: ReactNode;\n  delay?: number;\n  className?: string;\n};\n\n/** Host observation meter: known, partial, unknown, uncapped and over-limit readings. */\nexport function UsageMeter({\n  percent,\n  partial = false,\n  size = \"md\",\n  label,\n  valueText,\n  level: host,\n  marks,\n  delay,\n  className = \"\",\n}: UsageMeterProps) {\n  const progress = usageProgress(percent, partial);\n  const level = severerLevel(progress.level, host);\n  if (progress.kind === \"none\") return <UsageNoCapTrack size={size} className={className} />;\n  if (progress.percent === null) return <UsageUnknownTrack size={size} className={className} />;\n  const value = Math.min(100, Math.max(0, progress.percent));\n  const track = {\n    size,\n    level,\n    fill: `${value}%`,\n    partial: progress.kind === \"partial\",\n    over: progress.percent > 100,\n    marks,\n    delay,\n    trace: progress.percent > 0,\n    className,\n  };\n  if (!label) return <UsageTrack {...track} aria-hidden data-level={level} />;\n  return (\n    <UsageTrack\n      {...track}\n      role=\"meter\"\n      aria-label={label}\n      aria-valuenow={value}\n      aria-valuetext={valueText}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      data-kind={progress.kind}\n      data-level={level}\n    />\n  );\n}\n"
    },
    {
      "path": "registry/radix/usage-progress/usage-progress.tsx",
      "type": "registry:component",
      "target": "@components/usagekit/usage-progress.tsx",
      "content": "export type UsageProgress = {\n  kind: \"none\" | \"known\" | \"partial\" | \"unknown\";\n  percent: number | null;\n  level: \"ok\" | \"warning\" | \"exceeded\";\n};\n\n/** Pure host-observation projection. A lower bound of zero does not establish zero usage. */\nexport function usageProgress(percent: number | null, partial: boolean): UsageProgress {\n  if (percent === null) return { kind: \"none\", percent: null, level: \"ok\" };\n  if (!Number.isFinite(percent) || percent < 0 || (partial && percent === 0))\n    return { kind: \"unknown\", percent: null, level: \"ok\" };\n  return {\n    kind: partial ? \"partial\" : \"known\",\n    percent,\n    level: percent >= 100 ? \"exceeded\" : percent >= 80 ? \"warning\" : \"ok\",\n  };\n}\n\nconst severity = { ok: 0, warning: 1, exceeded: 2 } as const;\n/** The more severe level; host accounting such as reservations or alerts can raise a reading. */\nexport function severerLevel(\n  level: UsageProgress[\"level\"],\n  host: UsageProgress[\"level\"] | undefined,\n): UsageProgress[\"level\"] {\n  return host !== undefined && severity[host] > severity[level] ? host : level;\n}\n"
    },
    {
      "path": "registry/radix/usage-motion/usage-motion.tsx",
      "type": "registry:component",
      "target": "@components/usagekit/usage-motion.tsx",
      "content": "\"use client\";\n\nimport type { CSSProperties, ReactNode } from \"react\";\n\n/**\n * Shared motion vocabulary. Entries run from @starting-style, so they play once when an element\n * appears; keyed elements replay when their content changes. Reduced motion removes every\n * transition, which also skips the starting styles.\n */\nexport const usageMotion = {\n  /** Messages, revealed fields and changed figures: fade in while rising a few pixels. */\n  enter:\n    \"transition-[opacity,translate] duration-300 ease-out starting:translate-y-1 starting:opacity-0 motion-reduce:transition-none\",\n  /** Control feedback such as hover and selection. */\n  respond: \"transition-colors duration-150 ease-out motion-reduce:transition-none\",\n  /** Dims content that is about to be replaced by a newer reading. */\n  settle: \"transition-opacity duration-200 ease-out motion-reduce:transition-none\",\n} as const;\n\n/** Height and opacity reveal that keeps collapsed content out of focus and assistive tech. */\nexport function UsageReveal({\n  open,\n  id,\n  className = \"\",\n  children,\n}: {\n  open: boolean;\n  id?: string;\n  className?: string;\n  children: ReactNode;\n}) {\n  return (\n    <div\n      id={id}\n      inert={!open}\n      data-state={open ? \"open\" : \"closed\"}\n      className={`grid transition-[grid-template-rows,opacity] duration-300 ease-out motion-reduce:transition-none ${open ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\"} ${className}`}\n    >\n      <div className=\"min-h-0 min-w-0 overflow-hidden\">{children}</div>\n    </div>\n  );\n}\n\n/** Disclosure caret that turns with its region. */\nexport function UsageChevron({ open, className = \"\" }: { open: boolean; className?: string }) {\n  return (\n    <svg\n      aria-hidden\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={`size-4 shrink-0 transition-transform duration-300 ease-out motion-reduce:transition-none ${open ? \"rotate-180\" : \"\"} ${className}`}\n    >\n      <path d=\"M4 6l4 4 4-4\" />\n    </svg>\n  );\n}\n\n/** Pending indicator for the control that started the work; text still states the pending state. */\nexport function UsageSpinner({ className = \"\" }: { className?: string }) {\n  return (\n    <svg\n      aria-hidden\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      className={`size-3.5 shrink-0 animate-spin motion-reduce:animate-none ${className}`}\n    >\n      <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeOpacity=\"0.25\" strokeWidth=\"2\" />\n      <path d=\"M14 8a6 6 0 0 0-6-6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n    </svg>\n  );\n}\n\nexport type UsageTone = \"ok\" | \"warning\" | \"exceeded\" | \"positive\" | \"neutral\" | \"unknown\";\n\nconst dotClass: Record<UsageTone, string> = {\n  ok: \"bg-primary\",\n  positive: \"bg-chart-2\",\n  warning: \"bg-chart-4\",\n  exceeded: \"bg-destructive\",\n  neutral: \"bg-muted-foreground/50\",\n  unknown: \"border border-muted-foreground/60 bg-transparent\",\n};\n\n/** Status in words with a colored dot; color only reinforces the text. */\nexport function UsageStatus({\n  tone,\n  children,\n  className = \"\",\n}: {\n  tone: UsageTone;\n  children: ReactNode;\n  className?: string;\n}) {\n  return (\n    <span\n      data-tone={tone}\n      className={`text-xs inline-flex min-w-0 items-center gap-1.5 ${tone === \"exceeded\" ? \"text-destructive\" : \"text-foreground\"} ${className}`}\n    >\n      <span\n        aria-hidden\n        className={`size-1.5 rounded-full shrink-0 transition-colors duration-300 motion-reduce:transition-none ${dotClass[tone]}`}\n      />\n      <span className=\"min-w-0 break-words\">{children}</span>\n    </span>\n  );\n}\n\nexport type UsageSegmentOption<T extends string> = { value: T; label: string };\n\n/** Choice between a few options; the selection indicator slides to the chosen one. */\nexport function UsageSegmented<T extends string>({\n  value,\n  options,\n  onChange,\n  disabled = false,\n  label,\n  className = \"\",\n}: {\n  value: T | null;\n  options: readonly UsageSegmentOption<T>[];\n  onChange: (value: T) => void;\n  disabled?: boolean;\n  /** Accessible group name when no surrounding legend names the choice. */\n  label?: string;\n  className?: string;\n}) {\n  const index = options.findIndex((option) => option.value === value);\n  // Equal segments keep the indicator's geometry simple; a choice wider than its container\n  // scrolls sideways instead of cutting labels short.\n  return (\n    <div\n      role={label ? \"group\" : undefined}\n      aria-label={label}\n      className={`rounded-lg bg-muted w-fit max-w-full overflow-x-auto [scrollbar-width:thin] ${disabled ? \"opacity-60\" : \"\"} ${className}`}\n    >\n      <div\n        className=\"p-[3px] relative grid min-w-max auto-cols-fr grid-flow-col\"\n        style={{ \"--count\": options.length, \"--index\": Math.max(index, 0) } as CSSProperties}\n      >\n        {index >= 0 && (\n          <span\n            aria-hidden\n            className=\"inset-y-[3px] left-[3px] w-[calc((100%_-_6px)/var(--count))] rounded-md border border-transparent bg-background shadow-sm dark:border-input dark:bg-input/30 absolute translate-x-[calc(100%_*_var(--index))] transition-transform duration-300 ease-out motion-reduce:transition-none\"\n          />\n        )}\n        {options.map((option) => (\n          <button\n            key={option.value}\n            type=\"button\"\n            aria-pressed={option.value === value}\n            disabled={disabled}\n            onClick={() => onChange(option.value)}\n            className={`rounded-md px-2.5 py-1 text-sm font-medium outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 relative whitespace-nowrap disabled:cursor-not-allowed ${option.value === value ? \"text-foreground\" : \"text-foreground/70 hover:text-foreground\"} ${usageMotion.respond}`}\n          >\n            {option.label}\n          </button>\n        ))}\n      </div>\n    </div>\n  );\n}\n\n/** Keep focus on the moved row when its triggering button becomes disabled. */\nexport function retainMovedRowFocus(button: HTMLButtonElement) {\n  requestAnimationFrame(() => {\n    if (\n      !button.isConnected ||\n      !button.disabled ||\n      (document.activeElement !== document.body && document.activeElement !== button)\n    )\n      return;\n    button.closest(\"li\")?.querySelector<HTMLButtonElement>(\"button:not(:disabled)\")?.focus();\n  });\n}\n\nexport type UsageNoticeTone = \"positive\" | \"warning\" | \"error\" | \"neutral\";\n\nconst noticeClass: Record<UsageNoticeTone, string> = {\n  positive: \"text-foreground\",\n  warning: \"text-foreground\",\n  error: \"text-destructive\",\n  neutral: \"text-muted-foreground\",\n};\nconst noticeIcon: Record<UsageNoticeTone, string> = {\n  positive: \"text-chart-2\",\n  warning: \"text-chart-4\",\n  error: \"text-destructive\",\n  neutral: \"text-muted-foreground\",\n};\n\n/** Result feedback that rises in; keyed by its text so each new outcome replays the entry. */\nexport function UsageNotice({\n  tone,\n  role = \"status\",\n  id,\n  children,\n  className = \"\",\n}: {\n  tone: UsageNoticeTone;\n  role?: \"status\" | \"alert\";\n  id?: string;\n  children: ReactNode;\n  className?: string;\n}) {\n  return (\n    <p\n      id={id}\n      role={role}\n      data-tone={tone}\n      className={`text-sm flex min-w-0 items-start gap-[0.5em] ${noticeClass[tone]} ${usageMotion.enter} ${className}`}\n    >\n      <svg\n        aria-hidden\n        viewBox=\"0 0 16 16\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.6\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        className={`mt-[0.1em] size-[1.15em] shrink-0 ${noticeIcon[tone]}`}\n      >\n        {tone === \"positive\" ? (\n          <path d=\"m3.5 8.5 3 3 6-7\" />\n        ) : tone === \"neutral\" ? (\n          <>\n            <circle cx=\"8\" cy=\"8\" r=\"6\" />\n            <path d=\"M8 7.5V11M8 5v.01\" />\n          </>\n        ) : (\n          <>\n            <circle cx=\"8\" cy=\"8\" r=\"6\" />\n            <path d=\"M8 4.75v3.75M8 11v.01\" />\n          </>\n        )}\n      </svg>\n      <span className=\"min-w-0 break-words\">{children}</span>\n    </p>\n  );\n}\n"
    }
  ],
  "docs": "Rebind @/components/ui/card to host primitives. Pass authorized native observations, localized labels and actions. Bundles UsageConnectionRow, the shared usage meter and motion helpers, and the pure usageProgress helper for headless presentation; no Meter or balance authority is inferred."
}
