{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"area-chart","type":"registry:ui","title":"Area Chart","description":"Values over time as filled areas: one series, several, or stacked into a total, with a dashed one for a comparison. Plain SVG.","dependencies":[],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/lib-chart.json","https://dashral.com/r/lib-locale.json"],"files":[{"path":"registry/dashral/area-chart.tsx","type":"registry:file","target":"components/dashral/area-chart.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\n\nimport { areaPath, type CartesianChartProps, ChartAxes, ChartLegend, ChartReading, type Curve, linePath, seriesColor, useCartesianChart } from \"./lib/chart\"\nimport { useLocale } from \"./lib/locale\"\nimport { cn } from \"./lib/utils\"\n\ntype AreaChartProps = Omit<React.ComponentProps<\"div\">, \"children\"> &\n  CartesianChartProps & {\n    /** Stacks the series on one another, so the top line is their total. */\n    stacked?: boolean\n    /** How the line bends between points: smoothly (never past a value it didn't have), straight, or in steps. */\n    curve?: Curve\n    classNames?: { legend?: string; tooltip?: string }\n  }\n\n/**\n * Values over time as filled areas: one series, several side by side, or stacked into a total, with a dashed series\n * for a comparison (last year). Hover, or focus it and use the arrow keys, to read a point: a line marks it and a\n * tooltip lists every series there. The axis writes values compactly; the tooltip in full. Plain SVG, fills its\n * container's width; it draws in from the left when it first shows and moves to new data.\n */\nfunction AreaChart({\n  data,\n  index,\n  labelKey,\n  series,\n  height,\n  locale,\n  formatOptions,\n  timeFormat,\n  showLegend,\n  showGrid,\n  showYAxis,\n  stacked = false,\n  curve = \"smooth\",\n  className,\n  classNames,\n  \"aria-label\": ariaLabel,\n  ...props\n}: AreaChartProps) {\n  const { t } = useLocale()\n  const id = React.useId().replace(/:/g, \"\")\n  const h = useCartesianChart({ data, index, labelKey, series, height, locale, formatOptions, timeFormat, showLegend, showGrid, showYAxis, stacked, \"aria-label\": ariaLabel, roledescription: t(\"areaChart\") })\n  const n = data.length\n  const points = (k: number, edge: \"top\" | \"base\") => h.columns.map((cell, i) => ({ x: h.x(i), y: h.y(cell[k]![edge]) }))\n\n  return (\n    <div data-slot=\"area-chart\" {...h.root} className={cn(\"grid gap-3 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring/50\", className)} {...props}>\n      {h.showLegend && <ChartLegend series={series} className={classNames?.legend} />}\n\n      <div ref={h.box} dir=\"ltr\" className=\"relative w-full touch-none select-none\" style={{ height: h.height }} {...h.plot}>\n        {h.width !== null && n > 0 && (\n          <>\n            <ChartAxes chart={h} band={false} />\n\n            {/* The areas, drawn in from the left when the chart first shows; new data moves them to their new shape. */}\n            <svg\n              aria-hidden\n              width={h.width}\n              height={h.height}\n              className=\"absolute inset-0 transition-[clip-path] duration-(--duration-considered) ease-enter motion-reduce:transition-none\"\n              style={{ clipPath: h.drawn ? \"inset(0 0 0 0)\" : `inset(0 ${h.width}px 0 0)` }}\n            >\n              <defs>\n                {series.map((s, k) => (\n                  <linearGradient key={s.key} id={`${id}-${k}`} x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n                    <stop offset=\"0%\" stopColor={seriesColor(s, k)} stopOpacity={stacked ? 0.45 : 0.28} />\n                    <stop offset=\"100%\" stopColor={seriesColor(s, k)} stopOpacity={stacked ? 0.12 : 0} />\n                  </linearGradient>\n                ))}\n              </defs>\n              {series.map((s, k) => (\n                <g key={s.key}>\n                  {!s.dashed && (\n                    <path\n                      d={areaPath(points(k, \"top\"), stacked ? points(k, \"base\") : h.columns.map((_, i) => ({ x: h.x(i), y: h.y(Math.max(0, h.ticks[0]!)) })), curve)}\n                      fill={`url(#${id}-${k})`}\n                      className=\"transition-[d] duration-(--duration-considered) ease-standard motion-reduce:transition-none\"\n                    />\n                  )}\n                  <path\n                    d={linePath(points(k, \"top\"), curve)}\n                    fill=\"none\"\n                    stroke={seriesColor(s, k)}\n                    strokeWidth={s.dashed ? 1.5 : 2}\n                    strokeDasharray={s.dashed ? \"4 4\" : undefined}\n                    strokeOpacity={s.dashed ? 0.7 : 1}\n                    strokeLinejoin=\"round\"\n                    strokeLinecap=\"round\"\n                    className=\"transition-[d] duration-(--duration-considered) ease-standard motion-reduce:transition-none\"\n                  />\n                </g>\n              ))}\n            </svg>\n\n            <ChartReading chart={h} series={series} band={false} className={classNames?.tooltip} />\n          </>\n        )}\n        {n === 0 && <p className=\"grid h-full place-items-center text-sm text-muted-foreground\">{t(\"noData\")}</p>}\n      </div>\n      <p aria-live=\"polite\" className=\"sr-only\">\n        {h.announce}\n      </p>\n    </div>\n  )\n}\n\nexport { AreaChart, type AreaChartProps }\nexport type { ChartDatum, ChartSeries } from \"./lib/chart\"\n"}],"cssVars":{"theme":{"ease-standard":"var(--ease-standard)","ease-enter":"var(--ease-enter)","ease-exit":"var(--ease-exit)","ease-spring":"var(--ease-spring)"},"light":{"duration-fast":"160ms","duration-standard":"240ms","duration-considered":"480ms","ease-standard":"cubic-bezier(0.2, 0, 0, 1)","ease-enter":"cubic-bezier(0, 0, 0, 1)","ease-exit":"cubic-bezier(0.3, 0, 1, 1)","ease-spring":"linear(0, 0.071 4%, 0.234 8%, 0.433 12%, 0.626 17%, 0.791 21%, 0.917 25%, 1.004 29%, 1.055 33%, 1.079 38%, 1.083 42%, 1.075 46%, 1.06 50%, 1.043 54%, 1.027 58%, 1.015 62%, 1.005 67%, 0.998 71%, 0.995 75%, 0.993 79%, 0.993 83%, 0.994 88%, 0.995 92%, 0.997 96%, 1)"},"dark":{}}}