{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "metrics-grid",
  "title": "Metrics Grid",
  "type": "registry:block",
  "description": "Six-tile KPI status grid. Each tile pairs a stat header (count / percentage) with a small pie or horizontal bar chart that breaks the metric down. Different tiles use different chart types so each KPI reads at a glance.",
  "categories": [
    "analytics",
    "dashboard"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/metrics-grid/metrics-grid.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\n// Side-effect imports: register the composed elements for standalone use\n// (consumers who install only this block still get working primitives).\nimport '../../components/charts/pie-chart'\nimport '../../components/charts/bar-chart'\n\n// Six-tile KPI grid. Each tile renders a labeled KPI header (title + big\n// number / percentage / count) above a small chart -- pie or horizontal bar\n// -- that gives the breakdown. Tile shapes are spelled out inline as siblings.\n\nconst totalRuns = 770\nconst runsByStatus = [\n  { name: 'Successful', value: 638 },\n  { name: 'Partial', value: 0 },\n  { name: 'Error / Skipped', value: 132 },\n]\n\nconst totalProcessed = 638\nconst dispositionSplit = [\n  { name: 'Non-disputable', value: 168 },\n  { name: 'Disputable', value: 470 },\n]\n\nconst totalClassified = 638\nconst classification = [\n  { name: 'Type A', value: 525 },\n  { name: 'Type B', value: 113 },\n]\n\nconst skipReasons = [\n  { reason: 'CREDIT_NOTE', count: 11 },\n  { reason: 'CUSTOMS_INSPECT', count: 5 },\n  { reason: 'NEGATIVE_COST', count: 8 },\n]\nconst totalSkipped = skipReasons.reduce((a, r) => a + r.count, 0)\n\nconst errorReasons = [\n  { reason: 'INVALID_CUTOFF', count: 3 },\n  { reason: 'NO_SHIPMENT_DATA', count: 20 },\n  { reason: 'SELF_BILLING', count: 42 },\n  { reason: 'MISSING_OBLIGATORY_FIELD', count: 2 },\n  { reason: 'MISSING_OBLIGATORY_TIME', count: 4 },\n  { reason: 'UNABLE_TO_CLASSIFY', count: 40 },\n]\nconst totalErrors = errorReasons.reduce((a, r) => a + r.count, 0)\n\nconst openShare = 0.7602\nconst workflowStatus = [\n  { name: 'Open', value: 485 },\n  { name: 'Pending', value: 151 },\n  { name: 'Closed', value: 2 },\n]\n\nconst pieOption = {\n  legend: { show: false },\n  series: [\n    {\n      radius: ['0%', '70%'],\n      label: {\n        show: true,\n        formatter: (p: any) => `${p.value}\\n(${p.percent}%)`,\n        fontSize: 11,\n        color: '#fff',\n        fontWeight: 600,\n      },\n      labelLine: { show: false },\n    },\n  ],\n}\n\nconst donutOption = {\n  legend: { show: false },\n  series: [\n    {\n      radius: ['40%', '70%'],\n      label: {\n        show: true,\n        formatter: (p: any) => `${p.value}\\n(${p.percent}%)`,\n        fontSize: 11,\n        color: '#fff',\n        fontWeight: 600,\n      },\n      labelLine: { show: false },\n    },\n  ],\n}\n\nconst horizontalBarOption = {\n  legend: { show: false },\n  xAxis: { type: 'value' as const, axisLabel: { fontSize: 10 } },\n  yAxis: { type: 'category' as const, axisLabel: { fontSize: 10 } },\n  grid: { left: 16, right: 16, top: 8, bottom: 24, containLabel: true },\n  series: [\n    {\n      type: 'bar' as const,\n      barMaxWidth: 18,\n      itemStyle: { borderRadius: [0, 3, 3, 0] },\n    },\n  ],\n}\n\n/**\n * <uip-metrics-grid> — the registry MetricsGrid block as a web component.\n *\n * Datasets, option objects, and classes are React's verbatim. Tiles are\n * spelled out inline (different chart types per tile are the point of the\n * layout). No props, no events. Chart data/options are properties bound from\n * the module constants above.\n */\nexport class UipMetricsGrid extends LitElement {\n  static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n  // :host display can't be a utility class (the host has no template of its own).\n  static styles = [tailwind, css`:host { display: block; }`]\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'metrics-grid')\n  }\n\n  render() {\n    return html`\n      <div data-slot=\"metrics-grid\" class=\"space-y-4\">\n        <h2 class=\"text-primary text-sm font-semibold tracking-tight\">Results Overview</h2>\n\n        <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Runs by status</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${totalRuns} runs</div>\n            <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-xs\">\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-1)\"></span>\n                Successful\n              </span>\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-4)\"></span>\n                Error / Skipped\n              </span>\n            </div>\n            <uip-pie-chart .data=${runsByStatus} .option=${pieOption} height=\"220\"></uip-pie-chart>\n          </article>\n\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Disposition split</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${totalProcessed} processed</div>\n            <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-xs\">\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-1)\"></span>\n                Non-disputable\n              </span>\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-3)\"></span>\n                Disputable\n              </span>\n            </div>\n            <uip-pie-chart .data=${dispositionSplit} .option=${pieOption} height=\"220\"></uip-pie-chart>\n          </article>\n\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Classification</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${totalClassified} classified</div>\n            <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-xs\">\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-1)\"></span>\n                Type A\n              </span>\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-3)\"></span>\n                Type B\n              </span>\n            </div>\n            <uip-pie-chart .data=${classification} .option=${pieOption} height=\"220\"></uip-pie-chart>\n          </article>\n\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Top skip reasons</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${totalSkipped} skipped</div>\n            <div class=\"text-muted-foreground mb-3 text-xs\">By trigger</div>\n            <uip-bar-chart\n              .data=${skipReasons}\n              x-field=\"reason\"\n              y-field=\"count\"\n              .option=${horizontalBarOption}\n              height=\"220\"\n            ></uip-bar-chart>\n          </article>\n\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Top error reasons</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${totalErrors} errors</div>\n            <div class=\"text-muted-foreground mb-3 text-xs\">By failure mode</div>\n            <uip-bar-chart\n              .data=${errorReasons}\n              x-field=\"reason\"\n              y-field=\"count\"\n              .option=${horizontalBarOption}\n              height=\"220\"\n            ></uip-bar-chart>\n          </article>\n\n          <article class=\"bg-card border-border rounded-lg border p-4\">\n            <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Workflow status</h3>\n            <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">${(openShare * 100).toFixed(2)}% open</div>\n            <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-xs\">\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-1)\"></span>\n                Open\n              </span>\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-5)\"></span>\n                Pending\n              </span>\n              <span class=\"inline-flex items-center gap-1.5\">\n                <span class=\"size-2 rounded-full\" style=\"background:var(--chart-3)\"></span>\n                Closed\n              </span>\n            </div>\n            <uip-pie-chart .data=${workflowStatus} .option=${donutOption} donut height=\"220\"></uip-pie-chart>\n          </article>\n        </div>\n      </div>\n    `\n  }\n}\n\ncustomElements.get('uip-metrics-grid') || customElements.define('uip-metrics-grid', UipMetricsGrid)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-metrics-grid': UipMetricsGrid\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/metrics-grid/metrics-grid.ts"
    }
  ],
  "dependencies": [
    "lit"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/bar-chart.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/pie-chart.json"
  ]
}
