{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "analytics-overview",
  "title": "Analytics Overview",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/analytics-overview/AnalyticsOverview.tsx",
      "content": "'use client'\n\n// Two-pane analytics dashboard: a combo chart (stacked bars with a\n// dot overlay on a dual y-axis) sits above an interactive drill-down\n// line chart. Click a bar in the top pane to filter the bottom pane\n// to that route. The block bakes in a realistic dummy dataset; swap\n// `routes`, `partners`, and `drillSeries` with your own to repoint.\n//\n// Built on raw ECharts rather than `BarChart` because combo charts\n// (bar + scatter + dual y-axes) sit outside the opinionated wrapper's\n// single-series-type contract -- this is the documented escape hatch.\n// We register the chart types this block needs at module load (mirroring\n// the wrappers in `@/components/ui/charts`) and read palette tokens from\n// `useChartTheme()` so the colours stay in sync with the rest of the registry.\nimport * as React from 'react'\nimport * as echartsCore from 'echarts/core'\nimport { use } from 'echarts/core'\nimport { CanvasRenderer } from 'echarts/renderers'\nimport { BarChart as EBar, ScatterChart as EScatter, LineChart as ELine } from 'echarts/charts'\nimport { GridComponent, TooltipComponent, LegendComponent, MarkLineComponent } from 'echarts/components'\nimport ReactECharts from 'echarts-for-react/lib/core'\nimport { useChartTheme } from '@/components/ui/charts'\n\nuse([CanvasRenderer, EBar, EScatter, ELine, GridComponent, TooltipComponent, LegendComponent, MarkLineComponent])\n\n// Each route declares the per-partner volume (stack segments) + the\n// avg overlay value (dot on the right y-axis).\nconst partners = ['ALPHA', 'BETA', 'GAMMA', 'DELTA', 'EPSILON'] as const\ntype Partner = (typeof partners)[number]\n\ninterface Route {\n  id: string\n  label: string\n  volumes: Record<Partner, number>\n  overlay: number\n}\n\nconst routes: Route[] = [\n  {\n    id: 'r1',\n    label: 'NODE A → NODE B',\n    volumes: { ALPHA: 90, BETA: 25, GAMMA: 18, DELTA: 12, EPSILON: 8 },\n    overlay: 12,\n  },\n  {\n    id: 'r2',\n    label: 'NODE C → NODE D',\n    volumes: { ALPHA: 4, BETA: 100, GAMMA: 14, DELTA: 12, EPSILON: 24 },\n    overlay: 14.7,\n  },\n  {\n    id: 'r3',\n    label: 'NODE E → NODE F',\n    volumes: { ALPHA: 14, BETA: 38, GAMMA: 18, DELTA: 32, EPSILON: 28 },\n    overlay: 8,\n  },\n  { id: 'r4', label: 'NODE G → NODE H', volumes: { ALPHA: 130, BETA: 0, GAMMA: 0, DELTA: 0, EPSILON: 0 }, overlay: 6 },\n  { id: 'r5', label: 'NODE I → NODE J', volumes: { ALPHA: 0, BETA: 0, GAMMA: 60, DELTA: 0, EPSILON: 70 }, overlay: 17 },\n  { id: 'r6', label: 'NODE K → NODE L', volumes: { ALPHA: 60, BETA: 50, GAMMA: 16, DELTA: 0, EPSILON: 0 }, overlay: 8 },\n  { id: 'r7', label: 'NODE M → NODE N', volumes: { ALPHA: 70, BETA: 0, GAMMA: 0, DELTA: 0, EPSILON: 0 }, overlay: 22 },\n  { id: 'r8', label: 'NODE O → NODE P', volumes: { ALPHA: 0, BETA: 0, GAMMA: 0, DELTA: 0, EPSILON: 110 }, overlay: 29 },\n  { id: 'r9', label: 'NODE Q → NODE R', volumes: { ALPHA: 40, BETA: 0, GAMMA: 60, DELTA: 0, EPSILON: 0 }, overlay: 19 },\n  {\n    id: 'r10',\n    label: 'NODE S → NODE T',\n    volumes: { ALPHA: 60, BETA: 30, GAMMA: 0, DELTA: 0, EPSILON: 0 },\n    overlay: 23,\n  },\n]\n\n// Drill-down monthly series for a few partners. In a real app you'd\n// fetch this per-route on selection; the dummy block shows the same\n// shape regardless of which route is active.\nconst drillMonths = ['Mar 2026', 'Apr 2026', 'May 2026']\nconst drillSeries: Record<string, number[]> = {\n  ALPHA: [22, 25, 20],\n  GAMMA: [19, 17, 18],\n  EPSILON: [-1, 29, -1], // sparse point — left out of line by NaN-like handling\n}\n\nexport function AnalyticsOverview() {\n  const theme = useChartTheme()\n  const [overviewMetric, setOverviewMetric] = React.useState<'overlay' | 'volume'>('overlay')\n  const [activeRoute, setActiveRoute] = React.useState<string | null>(null)\n  const [drillView, setDrillView] = React.useState<'Month' | 'Quarter'>('Month')\n\n  const overviewOption = React.useMemo(() => {\n    const x = routes.map((r) => r.label)\n    const stacks = partners.map((p, i) => ({\n      name: p,\n      type: 'bar' as const,\n      stack: 'vol',\n      barMaxWidth: 36,\n      emphasis: { focus: 'series' as const },\n      itemStyle: { color: theme.colors[i % theme.colors.length] },\n      data: routes.map((r) => r.volumes[p]),\n    }))\n    const overlay = {\n      name: 'Avg metric',\n      type: 'scatter' as const,\n      yAxisIndex: 1,\n      symbolSize: 12,\n      itemStyle: { color: theme.colors[2], borderColor: 'var(--background)', borderWidth: 2 },\n      data: routes.map((r) => r.overlay),\n    }\n\n    return {\n      color: theme.colors,\n      tooltip: {\n        trigger: 'axis',\n        axisPointer: { type: 'shadow' },\n        backgroundColor: theme.tooltipBg,\n        borderColor: theme.tooltipBorder,\n        textStyle: { color: theme.tooltipText, fontSize: 12 },\n      },\n      legend: {\n        top: 8,\n        icon: 'circle',\n        itemWidth: 8,\n        itemHeight: 8,\n        textStyle: { color: theme.textColor, fontSize: 11 },\n      },\n      grid: { left: 56, right: 56, top: 42, bottom: 72, containLabel: false },\n      xAxis: {\n        type: 'category' as const,\n        data: x,\n        axisLine: { lineStyle: { color: theme.axisColor } },\n        axisLabel: {\n          interval: 0,\n          rotate: 35,\n          fontSize: 10,\n          color: theme.textColor,\n          formatter: (val: string) => val.replace(' → ', '\\n'),\n        },\n        axisTick: { show: false },\n      },\n      yAxis: [\n        {\n          type: 'value' as const,\n          name: 'Volume',\n          nameTextStyle: { color: theme.textColor, fontSize: 10 },\n          splitLine: { lineStyle: { color: theme.splitLineColor } },\n          axisLabel: { color: theme.textColor, fontSize: 10 },\n        },\n        {\n          type: 'value' as const,\n          name: 'Metric',\n          nameTextStyle: { color: theme.textColor, fontSize: 10 },\n          splitLine: { show: false },\n          axisLabel: { color: theme.textColor, fontSize: 10 },\n        },\n      ],\n      series: [...stacks, overlay],\n    }\n  }, [theme])\n\n  const drillOption = React.useMemo(() => {\n    const series = Object.entries(drillSeries).map(([name, values], i) => ({\n      name,\n      type: 'line' as const,\n      smooth: true,\n      symbolSize: 8,\n      connectNulls: false,\n      lineStyle: { width: 2, color: theme.colors[i % theme.colors.length] },\n      itemStyle: { color: theme.colors[i % theme.colors.length] },\n      data: values.map((v) => (v < 0 ? null : v)),\n    }))\n\n    return {\n      color: theme.colors,\n      tooltip: {\n        trigger: 'axis',\n        backgroundColor: theme.tooltipBg,\n        borderColor: theme.tooltipBorder,\n        textStyle: { color: theme.tooltipText, fontSize: 12 },\n      },\n      legend: {\n        top: 8,\n        icon: 'circle',\n        itemWidth: 8,\n        itemHeight: 8,\n        textStyle: { color: theme.textColor, fontSize: 11 },\n      },\n      grid: { left: 48, right: 24, top: 42, bottom: 48, containLabel: false },\n      xAxis: {\n        type: 'category' as const,\n        data: drillMonths,\n        boundaryGap: false,\n        axisLine: { lineStyle: { color: theme.axisColor } },\n        axisLabel: { color: theme.textColor, fontSize: 11 },\n        axisTick: { show: false },\n      },\n      yAxis: {\n        type: 'value' as const,\n        splitLine: { lineStyle: { color: theme.splitLineColor } },\n        axisLabel: { color: theme.textColor, fontSize: 11, formatter: (v: number) => `${v}d` },\n      },\n      series,\n    }\n  }, [theme])\n\n  const activeLabel = routes.find((r) => r.id === activeRoute)?.label ?? null\n\n  function onOverviewClick(params: any) {\n    if (!params?.name) return\n    const r = routes.find((rt) => rt.label === params.name)\n    if (r) setActiveRoute(r.id)\n  }\n\n  function resetDrill() {\n    setActiveRoute(null)\n  }\n\n  return (\n    <div className=\"space-y-6\">\n      {/* Overview pane */}\n      <section className=\"bg-card border-border rounded-lg border p-5\">\n        <div className=\"mb-3 flex items-start justify-between gap-4\">\n          <div>\n            <h2 className=\"text-[15px] font-semibold tracking-tight text-[var(--accent-tint)]\">Overview</h2>\n            <p className=\"text-muted-foreground mt-1 text-xs\">\n              <span className=\"text-foreground font-medium\">Metric</span> measures the avg performance signal aggregated\n              per route.\n            </p>\n          </div>\n          <div className=\"text-muted-foreground text-xs\">\n            <span>Performance Metric:</span>\n            <select\n              value={overviewMetric}\n              onChange={(e) => setOverviewMetric(e.target.value as 'overlay' | 'volume')}\n              className=\"border-border text-foreground ml-2 rounded-md border bg-transparent px-2 py-1 font-medium\"\n            >\n              <option value=\"overlay\">Avg metric</option>\n              <option value=\"volume\">Total volume</option>\n            </select>\n          </div>\n        </div>\n        <div role=\"img\" tabIndex={0} style={{ height: '320px' }} className=\"focus-visible:ring-ring w-full focus-visible:ring-2 focus-visible:outline-none\">\n          <ReactECharts\n            echarts={echartsCore as any}\n            option={overviewOption}\n            notMerge\n            lazyUpdate\n            onEvents={{ click: onOverviewClick }}\n            style={{ width: '100%', height: '100%' }}\n          />\n        </div>\n        <p className=\"text-muted-foreground mt-2 text-[11px]\">Click a bar to drill into that route&apos;s monthly trend.</p>\n      </section>\n\n      {/* Drill-down pane */}\n      <section className=\"bg-card border-border rounded-lg border p-5\">\n        <div className=\"mb-3 flex items-center justify-between gap-4\">\n          <div className=\"flex items-center gap-3\">\n            <h3 className=\"text-[15px] font-semibold tracking-tight\">\n              {activeLabel ? (\n                <>\n                  <span className=\"text-muted-foreground font-normal\">Drill-down:</span>\n                  <span className=\"text-foreground ml-1\">{activeLabel}</span>\n                </>\n              ) : (\n                <span className=\"text-muted-foreground font-normal\">Select a route above to drill in</span>\n              )}\n            </h3>\n            {activeRoute && (\n              <button\n                type=\"button\"\n                className=\"border-border text-muted-foreground hover:text-foreground rounded-md border px-2 py-1 font-mono text-[11px] transition hover:border-[var(--accent-tint-soft)]\"\n                onClick={resetDrill}\n              >\n                ← Back to Overview\n              </button>\n            )}\n          </div>\n          <div className=\"text-muted-foreground text-xs\">\n            <span>View By:</span>\n            <select\n              value={drillView}\n              onChange={(e) => setDrillView(e.target.value as 'Month' | 'Quarter')}\n              className=\"border-border text-foreground ml-2 rounded-md border bg-transparent px-2 py-1 font-medium\"\n            >\n              <option value=\"Month\">Month</option>\n              <option value=\"Quarter\">Quarter</option>\n            </select>\n          </div>\n        </div>\n        {activeRoute ? (\n          <div role=\"img\" tabIndex={0} style={{ height: '280px' }} className=\"focus-visible:ring-ring w-full focus-visible:ring-2 focus-visible:outline-none\">\n            <ReactECharts\n              echarts={echartsCore as any}\n              option={drillOption}\n              notMerge\n              lazyUpdate\n              style={{ width: '100%', height: '100%' }}\n            />\n          </div>\n        ) : (\n          <div className=\"text-muted-foreground border-border grid h-[260px] place-items-center rounded-md border border-dashed text-xs\">\n            No route selected. Click a bar above.\n          </div>\n        )}\n      </section>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/AnalyticsOverview.tsx"
    }
  ],
  "dependencies": [
    "echarts",
    "echarts-for-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/raw-chart.json"
  ],
  "description": "Two-pane analytics dashboard: stacked bar with dot overlay on a dual y-axis above, and an interactive drill-down line chart below. Click a bar to filter the bottom pane to that route.",
  "categories": [
    "dashboard",
    "analytics"
  ]
}