{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "health-metric",
  "type": "registry:component",
  "title": "Health metric",
  "description": "A supplied health reading, unit, time and source with explicit pending, unavailable and stale states.",
  "registryDependencies": [
    "https://vlak.dev/r/vlak-base.json",
    "https://vlak.dev/r/inter.json",
    "https://vlak.dev/r/vlak-lib.json"
  ],
  "dependencies": [
    "@stylexjs/stylex"
  ],
  "devDependencies": [
    "@stylexjs/babel-plugin"
  ],
  "docs": "Vlak leaves are StyleX. Compile them with @stylexjs/babel-plugin (Vite: @stylexjs/unplugin, Next: @stylexjs/nextjs-plugin). If you would rather not run a compiler, import @noorddev/vlak-react instead: it ships precompiled with one stylesheet.",
  "files": [
    {
      "path": "vlak/health-metric.tsx",
      "content": "import * as React from \"react\";\nimport * as stylex from \"@stylexjs/stylex\";\nimport { vlak } from \"./tokens.stylex\";\nimport { rs } from \"./rs\";\n\nexport type HealthMetricStatus = \"available\" | \"pending\" | \"unavailable\" | \"stale\";\n\nexport interface HealthMetricProps extends React.HTMLAttributes<HTMLDivElement> {\n  label: React.ReactNode;\n  /** A supplied reading. Zero is a reading; empty strings and non-finite numbers are missing. */\n  value?: number | string | null;\n  unit?: string;\n  /** Supplied by the application. Freshness is never inferred from the timestamp. */\n  status?: HealthMetricStatus;\n  statusLabel?: React.ReactNode;\n  dateTime?: string;\n  /** Human-readable time, including the relevant timezone. Falls back to dateTime. */\n  timeLabel?: string;\n  source?: React.ReactNode;\n  description?: React.ReactNode;\n}\n\nconst styles = stylex.create({\n  root: { display: \"grid\", gap: \"0.5rem\", minWidth: 0, color: vlak.ink, paddingBlock: \"1rem\", borderTopWidth: vlak.hairline, borderTopStyle: \"solid\", borderTopColor: vlak.divider, lineHeight: 1.45, overflowWrap: \"anywhere\" },\n  label: { margin: 0, fontSize: \"0.875rem\", fontWeight: 500 },\n  reading: { margin: 0, display: \"flex\", alignItems: \"baseline\", flexWrap: \"wrap\", gap: \"0.5rem\", fontVariantNumeric: \"tabular-nums\" },\n  value: { fontSize: \"2rem\", lineHeight: 1.2, fontWeight: 500, letterSpacing: \"-0.04em\" },\n  unit: { fontSize: \"0.875rem\", color: vlak.gray },\n  status: { margin: 0, fontSize: \"0.75rem\", fontWeight: 500 },\n  meta: { margin: 0, fontSize: \"0.75rem\", color: vlak.gray, display: \"flex\", flexWrap: \"wrap\", gap: \"0.25rem 0.75rem\" },\n  description: { margin: 0, fontSize: \"0.875rem\", maxWidth: \"66ch\" },\n});\n\n/** A sourced reading with explicit data availability, without clinical interpretation. */\nexport const HealthMetric = React.forwardRef<HTMLDivElement, HealthMetricProps>(function HealthMetric({ label, value, unit, status = \"available\", statusLabel, dateTime, timeLabel, source, description, className, style, children, ...props }, ref) {\n  const hasValue = typeof value === \"number\" ? Number.isFinite(value) : typeof value === \"string\" && value.trim().length > 0;\n  const state = !hasValue && (status === \"available\" || status === \"stale\") ? \"unavailable\" : status;\n  const showValue = hasValue && (state === \"available\" || state === \"stale\");\n  const labels: Record<HealthMetricStatus, string> = { available: \"Recorded\", pending: \"Pending\", unavailable: \"Unavailable\", stale: \"Last recorded, stale\" };\n  const root = rs([\"rs-health-metric\", className], styles.root);\n  const labelStyle = rs([\"rs-health-metric-label\"], styles.label);\n  const reading = rs([\"rs-health-metric-reading\"], styles.reading);\n  const valueStyle = rs([\"rs-health-metric-value\"], styles.value);\n  const unitStyle = rs([\"rs-health-metric-unit\"], styles.unit);\n  const statusStyle = rs([\"rs-health-metric-status\"], styles.status);\n  const meta = rs([\"rs-health-metric-meta\"], styles.meta);\n  const descriptionStyle = rs([\"rs-health-metric-description\"], styles.description);\n  return <div ref={ref} {...props} className={root.className} style={{ ...root.style, ...style }} data-status={state}>\n    <p {...labelStyle}>{label}</p>\n    {showValue && <p {...reading}><span {...valueStyle}>{value}</span>{unit && <span {...unitStyle}>{unit}</span>}</p>}\n    <p {...statusStyle}>{statusLabel ?? labels[state]}</p>\n    {(dateTime || timeLabel || source != null) && <p {...meta}>\n      {(dateTime || timeLabel) && <time dateTime={dateTime}>{timeLabel ?? dateTime}</time>}\n      {source != null && <span>{source}</span>}\n    </p>}\n    {description != null && <div {...descriptionStyle}>{description}</div>}\n    {children}\n  </div>;\n});\n",
      "type": "registry:component",
      "target": "components/vlak/health-metric.tsx"
    },
    {
      "path": "vlak/styles/health-metric.css",
      "content": "/* ── health-metric: generated from packages/react/src/components/health-metric.tsx ── */\n.rs-health-metric{display:grid;gap:0.5rem;min-width:0;color:var(--text);padding-block:1rem;border-top-width:1px;border-top-style:solid;border-top-color:var(--divider);line-height:1.45;overflow-wrap:anywhere}\n.rs-health-metric-label{margin:0;font-size:0.875rem;font-weight:500}\n.rs-health-metric-reading{margin:0;display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;font-variant-numeric:tabular-nums}\n.rs-health-metric-value{font-size:2rem;line-height:1.2;font-weight:500;letter-spacing:-0.04em}\n.rs-health-metric-unit{font-size:0.875rem;color:var(--text-secondary)}\n.rs-health-metric-status{margin:0;font-size:0.75rem;font-weight:500}\n.rs-health-metric-meta{margin:0;font-size:0.75rem;color:var(--text-secondary);display:flex;flex-wrap:wrap;gap:0.25rem 0.75rem}\n.rs-health-metric-description{margin:0;font-size:0.875rem;max-width:66ch}\n",
      "type": "registry:file",
      "target": "styles/vlak/health-metric.css"
    }
  ],
  "meta": {
    "vlak": {
      "category": "health",
      "classes": [
        "rs-health-metric",
        "rs-health-metric-label",
        "rs-health-metric-reading",
        "rs-health-metric-value",
        "rs-health-metric-unit",
        "rs-health-metric-status",
        "rs-health-metric-meta",
        "rs-health-metric-description"
      ],
      "snippet": "<div class=\"rs-health-metric\" data-status=\"stale\">\n  <p class=\"rs-health-metric-label\">Resting heart rate</p>\n  <p class=\"rs-health-metric-reading\"><span class=\"rs-health-metric-value\">64</span> <span class=\"rs-health-metric-unit\">bpm</span></p>\n  <p class=\"rs-health-metric-status\">Last recorded, stale</p>\n  <p class=\"rs-health-metric-meta\"><time datetime=\"2026-09-05T07:20:00+02:00\">5 Sep, 07:20 CEST</time><span>Wrist sensor</span></p>\n</div>",
      "cssOnly": false,
      "registryDependencies": [
        "vlak-lib"
      ],
      "aliases": [
        "Vital sign",
        "Vital metric",
        "Health reading",
        "Patient observation",
        "Biometric card",
        "Wellness metric"
      ],
      "example": "import { HealthMetric } from \"@noorddev/vlak-react\";\n\n<HealthMetric\n  label=\"Resting heart rate\"\n  value={64}\n  unit=\"bpm\"\n  status=\"stale\"\n  dateTime=\"2026-09-05T07:20:00+02:00\"\n  timeLabel=\"5 Sep, 07:20 CEST\"\n  source=\"Wrist sensor\"\n  description=\"Waiting for the next device sync\"\n/>\n<HealthMetric label=\"Sleep duration\" status=\"pending\" />",
      "usage": {
        "use": [
          "Patient summaries and wellness dashboards with a known source for each reading.",
          "Pass status from the application's data policy; the component does not infer freshness.",
          "Pass timeLabel with the relevant timezone when a human-readable time is needed."
        ],
        "avoid": [
          "Deriving a diagnosis, clinical flag or urgency from the number.",
          "Using zero as a placeholder for missing data; omit value instead."
        ]
      },
      "keyboard": [],
      "a11y": [
        "Visible labels, units, status, source and time accompany the reading.",
        "Zero is preserved; empty strings and non-finite values become unavailable. Pending and unavailable states suppress any supplied reading.",
        "Stale values remain visible with a textual stale label. No clinical status is calculated.",
        "A native time element preserves the supplied machine-readable timestamp. Native attributes and the div ref pass through.",
        "The component adds no live region or tab stop. The application can announce updates in context."
      ]
    }
  }
}
