@acronis-platform/ui-react 5.4.4 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/components/ui/area-chart/area-chart.js +114 -113
  2. package/dist/components/ui/area-chart/area-chart.js.map +1 -1
  3. package/dist/components/ui/bar-chart/bar-chart.js +53 -49
  4. package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
  5. package/dist/components/ui/chart/chart.js +108 -97
  6. package/dist/components/ui/chart/chart.js.map +1 -1
  7. package/dist/components/ui/composed-chart/composed-chart.js +134 -130
  8. package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
  9. package/dist/components/ui/confidence-cone/confidence-cone.js +36 -35
  10. package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
  11. package/dist/components/ui/dialog/dialog.js +69 -67
  12. package/dist/components/ui/dialog/dialog.js.map +1 -1
  13. package/dist/components/ui/funnel-chart/funnel-chart.js +38 -37
  14. package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
  15. package/dist/components/ui/line-chart/line-chart.js +35 -34
  16. package/dist/components/ui/line-chart/line-chart.js.map +1 -1
  17. package/dist/components/ui/pie-chart/pie-chart.js +28 -27
  18. package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
  19. package/dist/components/ui/radar-chart/radar-chart.js +68 -65
  20. package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
  21. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +64 -63
  22. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
  23. package/dist/components/ui/scatter-chart/scatter-chart.js +26 -26
  24. package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
  25. package/dist/components/ui/treemap/treemap.js +22 -22
  26. package/dist/components/ui/treemap/treemap.js.map +1 -1
  27. package/dist/index.js +106 -106
  28. package/dist/llms/area-chart.md +1 -0
  29. package/dist/llms/bar-chart.md +1 -0
  30. package/dist/llms/chart.md +10 -0
  31. package/dist/llms/composed-chart.md +1 -0
  32. package/dist/llms/confidence-cone.md +1 -0
  33. package/dist/llms/funnel-chart.md +1 -0
  34. package/dist/llms/line-chart.md +1 -0
  35. package/dist/llms/pie-chart.md +1 -0
  36. package/dist/llms/radar-chart.md +1 -0
  37. package/dist/llms/radial-bar-chart.md +1 -0
  38. package/dist/llms/scatter-chart.md +1 -0
  39. package/dist/llms/treemap.md +1 -0
  40. package/dist/llms.txt +1 -1
  41. package/dist/react.js +106 -106
  42. package/dist/src/components/ui/area-chart/area-chart.d.ts +6 -1
  43. package/dist/src/components/ui/bar-chart/bar-chart.d.ts +8 -2
  44. package/dist/src/components/ui/category-bar/category-bar.d.ts +1 -1
  45. package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +16 -0
  46. package/dist/src/components/ui/chart/chart.d.ts +12 -1
  47. package/dist/src/components/ui/chart/index.d.ts +1 -1
  48. package/dist/src/components/ui/composed-chart/composed-chart.d.ts +6 -1
  49. package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +6 -1
  50. package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +6 -1
  51. package/dist/src/components/ui/grid/grid.d.ts +1 -1
  52. package/dist/src/components/ui/line-chart/line-chart.d.ts +6 -1
  53. package/dist/src/components/ui/pie-chart/pie-chart.d.ts +6 -1
  54. package/dist/src/components/ui/progress-circle/progress-circle.d.ts +1 -1
  55. package/dist/src/components/ui/radar-chart/radar-chart.d.ts +9 -1
  56. package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +6 -1
  57. package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +6 -1
  58. package/dist/src/components/ui/spinner/spinner.d.ts +1 -1
  59. package/dist/src/components/ui/stack/stack.d.ts +1 -1
  60. package/dist/src/components/ui/treemap/treemap.d.ts +6 -1
  61. package/dist/ui-react.css +1 -1
  62. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../../src/components/ui/radar-chart/radar-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n LabelList,\n PolarAngleAxis,\n PolarGrid,\n PolarRadiusAxis,\n Radar,\n RadarChart as RechartsRadarChart,\n type AxisDomainItem,\n} from 'recharts';\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n toLabelFormatter,\n resolveLabelFillClass,\n CHART_LABEL_FONT_SIZE,\n type ChartConfig,\n type ChartPalette,\n type ChartAnimationProps,\n type ChartDataLabelProps,\n type CartesianLabelPosition,\n toCssKey,\n type ResolvedAnimation,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives — the first\n// polar chart type. The single CVA axis is the design's Radar-chart variant set:\n// `gridType` (the polar web is drawn as straight-edged `polygon` rings or smooth\n// `circle` rings). The class stays empty because recharts' SVG — not CSS — draws\n// the web: `gridType` drives `<PolarGrid gridType>`. CVA is kept so the variant\n// set is a first-class, spec-conformant part of the API (matched against\n// ui-spec's api.yaml enums) and exposed via `VariantProps`; the resolved value is\n// also mirrored onto `data-grid-type`.\nconst radarChartVariants = cva('', {\n variants: {\n gridType: {\n polygon: '',\n circle: '',\n },\n },\n defaultVariants: {\n gridType: 'polygon',\n },\n});\n\n/** Per-series overrides, keyed by the series' `dataKeys` entry. */\nexport interface RadarChartSeriesSettings {\n /**\n * Fill for this series' area, overriding its `config` color. Reference an\n * existing semantic `--ui-*` token, same as `config`.\n */\n color?: string;\n /**\n * Outline color, when it should read differently from the fill (e.g. a solid\n * outline over a barely-tinted area). Defaults to the fill.\n *\n * recharts derives a Radar's legend/tooltip color from its stroke first, so\n * setting this alone also recolors that series' legend swatch and tooltip dot\n * — set `color` too if the marker should keep following the fill.\n */\n stroke?: string;\n /** Fill opacity for this series, overriding the chart-level `fillOpacity`. */\n fillOpacity?: number;\n /** Outline width for this series, overriding the chart-level `strokeWidth`. */\n strokeWidth?: number;\n /** Per-point dots for this series, overriding the chart-level `showDots`. */\n dot?: boolean;\n /** Dot radius for this series, overriding the chart-level `dotRadius`. */\n dotRadius?: number;\n /**\n * Highlight this series' hovered point, overriding the chart-level\n * `activeDot`.\n */\n activeDot?: boolean;\n}\n\n/**\n * Map the `radiusAxisDomain` preset to a recharts radius-axis `domain`. Exported\n * for unit tests; not part of the package's public API.\n *\n * The radius axis is what scales the web, so this is the difference between \"the\n * largest value in the data reaches the outer ring\" (recharts' own behavior, and\n * what an unset preset keeps) and \"the outer ring is a known maximum\" (`fixed`\n * plus `radiusAxisDomainMax`). The two only mean something together: a `fixed`\n * preset with no maximum falls back to the data's own top, i.e. that same\n * default.\n */\nexport function radarRadiusAxisDomain(\n preset: 'auto' | 'fixed' | undefined,\n max: number | undefined\n): Readonly<[AxisDomainItem, AxisDomainItem]> | undefined {\n switch (preset) {\n case 'auto':\n return ['auto', 'auto'];\n case 'fixed':\n // A maximum that isn't a positive, finite number can't bound a scale that\n // grows outward from 0: `[0, 0]` collapses the web onto its centre and a\n // negative inverts it. A computed max (`Math.max` over an empty or all-zero\n // series) reaches this, so fall back to the data's own top — the same\n // behavior as `fixed` with no maximum at all.\n return [0, max !== undefined && Number.isFinite(max) && max > 0 ? max : 'auto'];\n default:\n return undefined;\n }\n}\n\n/** The chart-level styling a `seriesSettings` entry overrides. */\nexport interface RadarSeriesDefaults {\n fillOpacity: number;\n strokeWidth: number;\n showDots: boolean;\n dotRadius: number;\n activeDot: boolean | undefined;\n}\n\n/** Resolved recharts `<Radar>` styling for one series. */\nexport interface RadarSeriesStyle {\n fill: string;\n stroke: string;\n fillOpacity: number;\n strokeWidth: number;\n dot: { r: number } | false;\n activeDot: boolean | undefined;\n}\n\n/**\n * Fold a series' `seriesSettings` entry over the chart-level styling. Exported\n * for unit tests; not part of the package's public API.\n *\n * Every fallback is `??`, not `||`, so a deliberate falsy override survives —\n * `fillOpacity: 0` (outline only), `strokeWidth: 0` (fill only), `dot: false`\n * and `activeDot: false` all have to beat a truthy chart-level value. An\n * un-overridden fill stays the `--color-<key>` custom property the shared\n * `ChartContainer` injects from `config`, so the series a caller doesn't name\n * keeps reading its config color.\n */\nexport function radarSeriesStyle(\n key: string,\n settings: RadarChartSeriesSettings | undefined,\n defaults: RadarSeriesDefaults\n): RadarSeriesStyle {\n const fill = settings?.color ?? `var(--color-${toCssKey(key)})`;\n const dot = settings?.dot ?? defaults.showDots;\n return {\n fill,\n stroke: settings?.stroke ?? fill,\n fillOpacity: settings?.fillOpacity ?? defaults.fillOpacity,\n strokeWidth: settings?.strokeWidth ?? defaults.strokeWidth,\n dot: dot ? { r: settings?.dotRadius ?? defaults.dotRadius } : false,\n activeDot: settings?.activeDot ?? defaults.activeDot,\n };\n}\n\nexport interface RadarChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n VariantProps<typeof radarChartVariants>,\n ChartAnimationProps,\n ChartDataLabelProps {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /**\n * Row-per-axis data. Each object holds the `angleKey` label + one numeric field\n * per series. Every plotted series needs a value in every row: recharts places a\n * missing one at the centre, which reads as a zero rather than as a gap.\n */\n data: ReadonlyArray<Record<string, string | number>>;\n /**\n * Per-series map of `label` / `icon` / `tone` (imported from the shared\n * `Chart` primitives). Turned into `--color-<key>` custom properties. Series\n * take their colour from the container's `palette`; each entry maps a key to a\n * `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Series to plot — one `<Radar>` per key. Each must exist in `config` and in every data row. */\n dataKeys: string[];\n /** The categorical axis key placed around the web (e.g. `\"subject\"`). */\n angleKey: string;\n /**\n * Per-series style overrides, keyed by a `dataKeys` entry — color, outline, and\n * dots for one series while the rest keep the chart-level values. Keys that\n * aren't plotted are ignored. An overridden `color` — or `stroke`, which\n * recharts reads first — follows through to that series' legend swatch and\n * tooltip dot.\n */\n seriesSettings?: Record<string, RadarChartSeriesSettings>;\n /** Fill opacity of each radar area. */\n fillOpacity?: number;\n /** Stroke width of each radar outline. */\n strokeWidth?: number;\n /** Render a dot at each axis point. Defaults to `true`. */\n showDots?: boolean;\n /** Radius of the per-point dots when `showDots` is on. Defaults to `2`. */\n dotRadius?: number;\n /**\n * Enlarge the hovered point's dot. On by default (recharts' behavior) — pass\n * `false` for a chart that shouldn't react to the pointer at all.\n */\n activeDot?: boolean;\n /** Render the polar grid (the web). */\n showGrid?: boolean;\n /**\n * Draw the grid's spokes — the radial lines from the centre out to each\n * category. Defaults to `true`; off leaves only the concentric rings.\n */\n radialLines?: boolean;\n /**\n * Render the categorical axis around the web (its spoke labels, tick lines,\n * and outer line). Defaults to `true`. Turning it off keeps the axis itself —\n * so the tooltip still names each category — and only hides its chrome.\n */\n showAngleAxis?: boolean;\n /** Place the spoke labels outside the web (default) or inside it. */\n angleAxisOrientation?: 'inner' | 'outer';\n /** Draw the line around the web that the spoke labels sit against. Defaults to `true`. */\n angleAxisLine?: boolean;\n /**\n * Shape of that line: straight-edged `polygon` (recharts' default) or a smooth\n * `circle`. Independent of `gridType`, so pair them to keep a circular web's\n * outline circular too.\n */\n angleAxisLineType?: 'polygon' | 'circle';\n /** Draw a tick line from the axis line to each spoke label. Defaults to `true`. */\n angleTickLine?: boolean;\n /**\n * Distance from each polygon vertex to its outer category label, in px.\n * Defaults to `4` (Figma geometry). When `showLabels` is on and no explicit\n * value is given, widens automatically to clear the value labels.\n */\n angleTickSize?: number;\n /**\n * Render the value scale — a radial axis of ticks from the centre outward, so\n * an area can be read as a number and not only compared to its neighbours.\n * Defaults to `false` (recharts draws no radius axis unless asked).\n *\n * `radiusAxisAngle` and `radiusAxisOrientation` only describe the drawn scale,\n * so they need it shown. `radiusAxisDomain`, `radiusAxisReversed` and\n * `radiusAxisTickCount` apply while it's hidden too — the first two scale the\n * web, and the third sets how many rings the grid draws (recharts takes the\n * grid's concentric radii from the radius axis' ticks).\n */\n showRadiusAxis?: boolean;\n /**\n * Angle the value scale is drawn at, in degrees counter-clockwise from 3\n * o'clock (recharts' default is `0`). Point it *between* two spokes: on a\n * spoke, the outermost tick collides with that category's own label.\n *\n * The ticks sit over the areas at any angle — a radar's plot area is its\n * areas — so this trades one overlap for none of the other.\n */\n radiusAxisAngle?: number;\n /** Which side of the scale its tick labels sit on. Defaults to `right`. */\n radiusAxisOrientation?: 'left' | 'right' | 'middle';\n /**\n * How the value scale is bounded — and with it the web, since the radius axis\n * is what maps a value to a radius:\n *\n * - unset — recharts' own scaling: the data's largest value reaches the outer\n * ring, so two charts of the same metric aren't comparable.\n * - `fixed` — pin the outer ring to `radiusAxisDomainMax` (the metric's own\n * maximum, e.g. a score out of 150), which is what makes a radar readable as\n * an absolute profile rather than a relative one.\n * - `auto` — fit the data at both ends; the scale need not start at 0.\n *\n * Takes effect whether or not the scale is shown, so a chart can be scaled to a\n * known maximum without displaying the ticks.\n */\n radiusAxisDomain?: 'auto' | 'fixed';\n /**\n * The value at the outer ring when `radiusAxisDomain` is `fixed`. Must be\n * positive — a `0` or negative maximum can't bound an outward-growing scale, so\n * it falls back to the data's own top.\n */\n radiusAxisDomainMax?: number;\n /**\n * Desired number of ticks on the value scale (a hint, not exact). Defaults to\n * recharts' `5`. Also sets how many rings the grid draws, whether or not the\n * scale itself is shown.\n */\n radiusAxisTickCount?: number;\n /**\n * Invert the value scale — the maximum at the centre and 0 at the outer ring —\n * for a metric where less is better (latency, error rate), so a good profile\n * still reads as a large area.\n */\n radiusAxisReversed?: boolean;\n /** Horizontal centre of the web, in px or a percentage of the width. Defaults to `50%`. */\n cx?: number | string;\n /**\n * Vertical centre of the web, in px or a percentage of the height. Defaults to\n * the middle of the plot band — i.e. `50%` of what the legend leaves, not of\n * the whole box (see `radarPlotBox`).\n */\n cy?: number | string;\n /** Angle the first category sits at, in degrees. Defaults to `90` (12 o'clock). */\n startAngle?: number;\n /**\n * Angle the sweep ends at, in degrees. Defaults to `-270` — a full turn\n * clockwise from `startAngle`. Together the two rotate the web (or wrap the\n * categories into a partial sweep).\n */\n endAngle?: number;\n /**\n * Radius of the hole at the centre, in px or a percentage of the available\n * radius. Defaults to `0`. Also lifts the grid and the areas off the centre,\n * which separates the series where they all bottom out.\n */\n innerRadius?: number | string;\n /**\n * Outer radius of the web, in px or a percentage of the available radius.\n * Defaults to `78px`, matching the Figma radar geometry. The legend and labels\n * do not change the radius — they change the box it is drawn in (see\n * `radarPlotBox`).\n */\n outerRadius?: number | string;\n /**\n * Plot-area margin, in px. Omit it entirely to use recharts' default (5 on\n * every side) — passing the object replaces all four, and recharts fills the\n * sides you leave out with `0`, not with `5`. Name every side you want.\n */\n margin?: { top?: number; right?: number; bottom?: number; left?: number };\n showTooltip?: boolean;\n showLegend?: boolean;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting, per-series rows, or extra fields without composing\n * recharts yourself. Ignored when `showTooltip` is false.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n /** Position of the value labels when `showLabels` is on. Defaults to `top`. */\n labelPosition?: CartesianLabelPosition;\n}\n\n// Distance from the polygon to the category tick text when value labels are on\n// (recharts' default is 8). Has to clear a CHART_LABEL_FONT_SIZE line plus the\n// LabelList's own 5px offset, or the topmost vertex's value overlaps its tick.\nconst RADAR_LABEL_TICK_SIZE = 30;\n\n// Vertical geometry of the chart's own box, in px.\n//\n// recharts centres a polar chart on the *whole* SVG: `cy` falls back to\n// `height / 2` and — unlike a percentage `outerRadius`, which it does fit to the\n// plot area — takes no account of the legend band it reserves at the bottom.\n// With the fixed-px `outerRadius` the Figma geometry asks for, that leaves the\n// ring the category labels are drawn on centred over rows the legend has\n// already claimed: the bottom label lands behind the legend and the top one runs\n// off the edge. `radarPlotBox` derives the box height and `cy` together so the\n// ring always has somewhere to go.\n\n// Half a `text-xs` line (16px). recharts anchors the top and bottom category\n// ticks' text *on* their point (`verticalAnchor: 'middle'`), so this much of the\n// text falls beyond the ring on each side.\nconst RADAR_TICK_TEXT_HALF_LINE = 8;\n// Figma's plot band. Holds the 78px web plus its 4px tick ring and that half\n// line (90px each side of the centre) with a little to spare.\nconst RADAR_PLOT_BAND = 187;\n// What a chart whose category ring outgrows RADAR_PLOT_BAND gets instead:\n// 2 × (78 + RADAR_LABEL_TICK_SIZE + RADAR_TICK_TEXT_HALF_LINE) — the cost of\n// `showLabels` at the Figma radius — rounded up to keep the same few px of slack\n// Figma's 187 leaves around the 4px ring.\nconst RADAR_LABELLED_PLOT_BAND = 240;\n// Figma's legend row, and what recharts' wrapper occupies too: it parks the\n// wrapper at `margin.bottom` (5) and `ChartLegendContent` is a `pt-3` above a\n// 16px line.\nconst RADAR_LEGEND_BAND = 32;\n\n/** The chart's own box: the height it reserves, and the polar centre inside it. */\nexport interface RadarPlotBox {\n /**\n * Tailwind height for the outer element. Merged *before* the consumer's\n * `className`, so a caller-supplied height still wins.\n */\n heightClass: string;\n /** `cy` for recharts, or `undefined` to keep its own `height / 2` default. */\n cy: string | undefined;\n}\n\n/**\n * Size the chart's box around its category ring, and centre the web in the part\n * of that box the legend does not take. Exported for unit tests; not part of the\n * package's public API.\n *\n * `ringRadius` is how far the category labels reach from the centre —\n * `outerRadius + angleTickSize + RADAR_TICK_TEXT_HALF_LINE` — or `undefined`\n * when `outerRadius` is a percentage, which recharts already fits to the plot\n * area (legend included) on its own.\n *\n * `cy` comes back as a percentage rather than the px it resolves to at the\n * default height, so a caller-supplied height keeps the proportion instead of\n * pinning the web to an absolute offset. On a taller box that lifts the web a\n * little further than the legend alone needs — towards the side with the slack.\n */\nexport function radarPlotBox(\n ringRadius: number | undefined,\n showLegend: boolean\n): RadarPlotBox {\n const tall = ringRadius !== undefined && ringRadius > RADAR_PLOT_BAND / 2;\n const plotBand = tall ? RADAR_LABELLED_PLOT_BAND : RADAR_PLOT_BAND;\n if (!showLegend) {\n // 240 / 187 — the plot band on its own.\n return { heightClass: tall ? 'h-[240px]' : 'h-[187px]', cy: undefined };\n }\n return {\n // 240 + 32 / 187 + 32 — the plot band above the legend band. Tailwind only\n // sees classes it can read in the source, so these stay literal.\n heightClass: tall ? 'h-[272px]' : 'h-[219px]',\n // Truncated rather than rounded: the leftover fraction has to come off the\n // top, the side with the slack, and never off the legend's.\n cy: `${Math.floor((plotBand / 2 / (plotBand + RADAR_LEGEND_BAND)) * 1e5) / 1e3}%`,\n };\n}\n\n/**\n * One series' `<Radar>` (and its value labels).\n *\n * Called as a plain function rather than mounted as `<RadarSeries />`, purely\n * to keep the chart's children readable as a flat list — recharts imposes no\n * constraint here. `RadarChart` picks up the series from the store `<Radar>`\n * registers itself in, and `Radar` passes its children straight through to a\n * label-list context instead of scanning them by type. `<Cell>` is the only\n * child recharts still looks up by element type, and a radar series has none.\n */\nfunction radarSeries({\n seriesKey,\n style,\n animation,\n showLabels,\n labelPosition,\n labelFormatter,\n}: {\n seriesKey: string;\n style: RadarSeriesStyle;\n animation: ResolvedAnimation;\n showLabels: boolean;\n labelPosition: CartesianLabelPosition;\n labelFormatter: ChartDataLabelProps['labelFormatter'];\n}) {\n return (\n <Radar\n key={seriesKey}\n dataKey={seriesKey}\n stroke={style.stroke}\n fill={style.fill}\n fillOpacity={style.fillOpacity}\n strokeWidth={style.strokeWidth}\n dot={style.dot}\n activeDot={style.activeDot}\n {...animation}\n >\n {showLabels && (\n <LabelList\n dataKey={seriesKey}\n position={labelPosition}\n formatter={toLabelFormatter(labelFormatter)}\n // A radar area is a flat `fillOpacity`, so an `inside*` label sits on\n // the *surface tinted by* the series color, not on the color itself —\n // the white on-fill token disappears into it in light mode. Same call\n // as the other translucent families (Area, the composed chart's areas).\n className={resolveLabelFillClass(labelPosition, {\n translucentSeries: true,\n })}\n fontSize={CHART_LABEL_FONT_SIZE}\n />\n )}\n </Radar>\n );\n}\n\nconst RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n (\n {\n className,\n config,\n palette,\n data,\n dataKeys,\n angleKey,\n seriesSettings,\n gridType = 'polygon',\n fillOpacity = 0.3,\n strokeWidth = 2,\n showDots = true,\n dotRadius = 2,\n activeDot,\n showGrid = true,\n radialLines = true,\n showAngleAxis = true,\n angleAxisOrientation,\n angleAxisLine = true,\n angleAxisLineType,\n angleTickLine = true,\n angleTickSize,\n showRadiusAxis = false,\n radiusAxisAngle,\n radiusAxisOrientation,\n radiusAxisDomain,\n radiusAxisDomainMax,\n radiusAxisTickCount,\n radiusAxisReversed = false,\n cx,\n cy,\n startAngle,\n endAngle,\n innerRadius,\n outerRadius: outerRadiusProp,\n margin,\n showTooltip = true,\n showLegend = true,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n showLabels = false,\n labelPosition,\n labelFormatter,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n const radarLabelPosition = labelPosition ?? 'top';\n const radiusDomain = radarRadiusAxisDomain(\n radiusAxisDomain,\n radiusAxisDomainMax\n );\n // The radius axis is only mounted when it has something to do: it either\n // paints the scale, or it carries a domain/reversal that rescales the web\n // (recharts registers those from the element even when nothing is drawn).\n // Without one of the three, leaving the element out keeps recharts' own\n // implicit axis — and every existing chart's geometry.\n const hasRadiusAxis =\n showRadiusAxis || radiusDomain !== undefined || radiusAxisReversed;\n const seriesDefaults: RadarSeriesDefaults = {\n fillOpacity,\n strokeWidth,\n showDots,\n dotRadius,\n activeDot,\n };\n const outerRadius = outerRadiusProp ?? 78;\n const resolvedTickSize =\n angleTickSize ?? (showLabels ? RADAR_LABEL_TICK_SIZE : 4);\n // A percentage `outerRadius` is already fitted to the plot area by recharts,\n // so only a fixed radius has a ring whose reach the box has to be sized to.\n const plotBox = radarPlotBox(\n typeof outerRadius === 'number'\n ? outerRadius + resolvedTickSize + RADAR_TICK_TEXT_HALF_LINE\n : undefined,\n showLegend\n );\n // When the consumer supplies their own height (size-*, h-*, min-h-*, max-h-*)\n // the plotBox.cy percentage — calibrated for the compact default heights — would\n // shift the web too far up in a taller box. Fall back to recharts' default\n // cy = height/2 in that case; a large container has room for ring + legend\n // without the legend-band compensation radarPlotBox does.\n const consumerOwnsHeight = /(?:^|\\s)(?:h-|size-|min-h-|max-h-)/.test(\n className ?? ''\n );\n return (\n <div\n ref={ref}\n data-grid-type={gridType}\n // Default height matches the Figma geometry (187px plot + 32px legend),\n // widening only when the category ring outgrows it (see `radarPlotBox`).\n // The consumer's `className` is merged after the default, so a\n // caller-supplied height (e.g. `h-[380px]`) wins via Tailwind's\n // last-class-wins rule.\n className={cn(\n radarChartVariants({ gridType }),\n plotBox.heightClass,\n className\n )}\n {...props}\n >\n <ChartContainer\n config={config}\n palette={palette}\n // The shared container themes cartesian axis ticks but not polar ones,\n // so scope the angle-axis (spoke) labels and the radius-axis scale to\n // the muted-foreground / border tokens here — otherwise they render\n // near-black (or recharts' raw `#ccc`) and vanish in dark mode. This\n // is a shared-primitives gap (a Chart task); worked around locally, not\n // by editing chart.tsx.\n className={cn(\n 'size-full',\n \"[&_.recharts-polar-angle-axis-tick_text]:fill-[var(--ui-text-on-surface-secondary)]! [&_.recharts-polar-angle-axis-tick_text]:text-xs [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-[var(--ui-border-on-surface-divider)]! [&_.recharts-polar-radius-axis-line]:stroke-[var(--ui-border-on-surface-divider)]! [&_.recharts-polar-radius-axis-tick_text]:fill-[var(--ui-text-on-surface-secondary)]! [&_.recharts-polar-radius-axis-tick_text]:text-xs\"\n )}\n >\n <RechartsRadarChart\n data={data as readonly unknown[]}\n cx={cx}\n cy={cy ?? (consumerOwnsHeight ? undefined : plotBox.cy)}\n startAngle={startAngle}\n endAngle={endAngle}\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n margin={margin}\n >\n {showTooltip && (\n <ChartTooltip content={tooltipContent ?? <ChartTooltipContent />} />\n )}\n {showGrid && (\n <PolarGrid gridType={gridType ?? 'polygon'} radialLines={radialLines} />\n )}\n <PolarAngleAxis\n dataKey={angleKey}\n orientation={angleAxisOrientation}\n axisLineType={angleAxisLineType}\n // `showAngleAxis` hides the chrome rather than dropping the axis:\n // the angle axis is also what maps a row to its category name, so\n // removing it would leave the tooltip labelling rows by index.\n tick={showAngleAxis}\n axisLine={showAngleAxis && angleAxisLine}\n tickLine={showAngleAxis && angleTickLine}\n // Push the category ticks out when value labels are on. recharts\n // gives a Radar's label list a *cartesian* viewBox (width/height 0\n // at the vertex), so `top` offsets straight up in screen space —\n // at the topmost vertex the value lands on its own category tick.\n // The tick text is drawn at `outerRadius + tickSize`, so this is\n // the only lever that adds *absolute* clearance: shrinking\n // outerRadius scales the tick ring down with the polygon and keeps\n // the overlap. Default 4px matches the Figma geometry when labels\n // are off. The box grows to fit whatever this resolves to — see\n // `radarPlotBox`.\n tickSize={resolvedTickSize}\n />\n {hasRadiusAxis && (\n <PolarRadiusAxis\n angle={radiusAxisAngle}\n orientation={radiusAxisOrientation}\n domain={radiusDomain}\n tickCount={radiusAxisTickCount}\n reversed={radiusAxisReversed}\n tick={showRadiusAxis}\n axisLine={showRadiusAxis}\n />\n )}\n {showLegend && (\n <ChartLegend\n verticalAlign=\"bottom\"\n content={<ChartLegendContent verticalAlign=\"bottom\" />}\n />\n )}\n {dataKeys.map((key) =>\n radarSeries({\n seriesKey: key,\n style: radarSeriesStyle(\n key,\n seriesSettings?.[key],\n seriesDefaults\n ),\n animation,\n showLabels,\n labelPosition: radarLabelPosition,\n labelFormatter,\n })\n )}\n </RechartsRadarChart>\n </ChartContainer>\n </div>\n );\n }\n);\nRadarChart.displayName = 'RadarChart';\n\nexport { RadarChart, radarChartVariants };\n"],"mappings":"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"}
1
+ {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../../src/components/ui/radar-chart/radar-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport {\n LabelList,\n PolarAngleAxis,\n PolarGrid,\n PolarRadiusAxis,\n Radar,\n RadarChart as RechartsRadarChart,\n type AxisDomainItem,\n} from 'recharts';\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n toLabelFormatter,\n resolveLabelFillClass,\n CHART_LABEL_FONT_SIZE,\n type ChartConfig,\n type ChartLegendFontSize,\n type ChartPalette,\n type ChartAnimationProps,\n type ChartDataLabelProps,\n type CartesianLabelPosition,\n toCssKey,\n type ResolvedAnimation,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives — the first\n// polar chart type. The single CVA axis is the design's Radar-chart variant set:\n// `gridType` (the polar web is drawn as straight-edged `polygon` rings or smooth\n// `circle` rings). The class stays empty because recharts' SVG — not CSS — draws\n// the web: `gridType` drives `<PolarGrid gridType>`. CVA is kept so the variant\n// set is a first-class, spec-conformant part of the API (matched against\n// ui-spec's api.yaml enums) and exposed via `VariantProps`; the resolved value is\n// also mirrored onto `data-grid-type`.\nconst radarChartVariants = cva('', {\n variants: {\n gridType: {\n polygon: '',\n circle: '',\n },\n },\n defaultVariants: {\n gridType: 'polygon',\n },\n});\n\n/** Per-series overrides, keyed by the series' `dataKeys` entry. */\nexport interface RadarChartSeriesSettings {\n /**\n * Fill for this series' area, overriding its `config` color. Reference an\n * existing semantic `--ui-*` token, same as `config`.\n */\n color?: string;\n /**\n * Outline color, when it should read differently from the fill (e.g. a solid\n * outline over a barely-tinted area). Defaults to the fill.\n *\n * recharts derives a Radar's legend/tooltip color from its stroke first, so\n * setting this alone also recolors that series' legend swatch and tooltip dot\n * — set `color` too if the marker should keep following the fill.\n */\n stroke?: string;\n /** Fill opacity for this series, overriding the chart-level `fillOpacity`. */\n fillOpacity?: number;\n /** Outline width for this series, overriding the chart-level `strokeWidth`. */\n strokeWidth?: number;\n /** Per-point dots for this series, overriding the chart-level `showDots`. */\n dot?: boolean;\n /** Dot radius for this series, overriding the chart-level `dotRadius`. */\n dotRadius?: number;\n /**\n * Highlight this series' hovered point, overriding the chart-level\n * `activeDot`.\n */\n activeDot?: boolean;\n}\n\n/**\n * Map the `radiusAxisDomain` preset to a recharts radius-axis `domain`. Exported\n * for unit tests; not part of the package's public API.\n *\n * The radius axis is what scales the web, so this is the difference between \"the\n * largest value in the data reaches the outer ring\" (recharts' own behavior, and\n * what an unset preset keeps) and \"the outer ring is a known maximum\" (`fixed`\n * plus `radiusAxisDomainMax`). The two only mean something together: a `fixed`\n * preset with no maximum falls back to the data's own top, i.e. that same\n * default.\n */\nexport function radarRadiusAxisDomain(\n preset: 'auto' | 'fixed' | undefined,\n max: number | undefined\n): Readonly<[AxisDomainItem, AxisDomainItem]> | undefined {\n switch (preset) {\n case 'auto':\n return ['auto', 'auto'];\n case 'fixed':\n // A maximum that isn't a positive, finite number can't bound a scale that\n // grows outward from 0: `[0, 0]` collapses the web onto its centre and a\n // negative inverts it. A computed max (`Math.max` over an empty or all-zero\n // series) reaches this, so fall back to the data's own top — the same\n // behavior as `fixed` with no maximum at all.\n return [0, max !== undefined && Number.isFinite(max) && max > 0 ? max : 'auto'];\n default:\n return undefined;\n }\n}\n\n/** The chart-level styling a `seriesSettings` entry overrides. */\nexport interface RadarSeriesDefaults {\n fillOpacity: number;\n strokeWidth: number;\n showDots: boolean;\n dotRadius: number;\n activeDot: boolean | undefined;\n}\n\n/** Resolved recharts `<Radar>` styling for one series. */\nexport interface RadarSeriesStyle {\n fill: string;\n stroke: string;\n fillOpacity: number;\n strokeWidth: number;\n dot: { r: number } | false;\n activeDot: boolean | undefined;\n}\n\n/**\n * Fold a series' `seriesSettings` entry over the chart-level styling. Exported\n * for unit tests; not part of the package's public API.\n *\n * Every fallback is `??`, not `||`, so a deliberate falsy override survives —\n * `fillOpacity: 0` (outline only), `strokeWidth: 0` (fill only), `dot: false`\n * and `activeDot: false` all have to beat a truthy chart-level value. An\n * un-overridden fill stays the `--color-<key>` custom property the shared\n * `ChartContainer` injects from `config`, so the series a caller doesn't name\n * keeps reading its config color.\n */\nexport function radarSeriesStyle(\n key: string,\n settings: RadarChartSeriesSettings | undefined,\n defaults: RadarSeriesDefaults\n): RadarSeriesStyle {\n const fill = settings?.color ?? `var(--color-${toCssKey(key)})`;\n const dot = settings?.dot ?? defaults.showDots;\n return {\n fill,\n stroke: settings?.stroke ?? fill,\n fillOpacity: settings?.fillOpacity ?? defaults.fillOpacity,\n strokeWidth: settings?.strokeWidth ?? defaults.strokeWidth,\n dot: dot ? { r: settings?.dotRadius ?? defaults.dotRadius } : false,\n activeDot: settings?.activeDot ?? defaults.activeDot,\n };\n}\n\nexport interface RadarChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n VariantProps<typeof radarChartVariants>,\n ChartAnimationProps,\n ChartDataLabelProps {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /**\n * Row-per-axis data. Each object holds the `angleKey` label + one numeric field\n * per series. Every plotted series needs a value in every row: recharts places a\n * missing one at the centre, which reads as a zero rather than as a gap.\n */\n data: ReadonlyArray<Record<string, string | number>>;\n /**\n * Per-series map of `label` / `icon` / `tone` (imported from the shared\n * `Chart` primitives). Turned into `--color-<key>` custom properties. Series\n * take their colour from the container's `palette`; each entry maps a key to a\n * `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Series to plot — one `<Radar>` per key. Each must exist in `config` and in every data row. */\n dataKeys: string[];\n /** The categorical axis key placed around the web (e.g. `\"subject\"`). */\n angleKey: string;\n /**\n * Per-series style overrides, keyed by a `dataKeys` entry — color, outline, and\n * dots for one series while the rest keep the chart-level values. Keys that\n * aren't plotted are ignored. An overridden `color` — or `stroke`, which\n * recharts reads first — follows through to that series' legend swatch and\n * tooltip dot.\n */\n seriesSettings?: Record<string, RadarChartSeriesSettings>;\n /** Fill opacity of each radar area. */\n fillOpacity?: number;\n /** Stroke width of each radar outline. */\n strokeWidth?: number;\n /** Render a dot at each axis point. Defaults to `true`. */\n showDots?: boolean;\n /** Radius of the per-point dots when `showDots` is on. Defaults to `2`. */\n dotRadius?: number;\n /**\n * Enlarge the hovered point's dot. On by default (recharts' behavior) — pass\n * `false` for a chart that shouldn't react to the pointer at all.\n */\n activeDot?: boolean;\n /** Render the polar grid (the web). */\n showGrid?: boolean;\n /**\n * Draw the grid's spokes — the radial lines from the centre out to each\n * category. Defaults to `true`; off leaves only the concentric rings.\n */\n radialLines?: boolean;\n /**\n * Render the categorical axis around the web (its spoke labels, tick lines,\n * and outer line). Defaults to `true`. Turning it off keeps the axis itself —\n * so the tooltip still names each category — and only hides its chrome.\n */\n showAngleAxis?: boolean;\n /** Place the spoke labels outside the web (default) or inside it. */\n angleAxisOrientation?: 'inner' | 'outer';\n /** Draw the line around the web that the spoke labels sit against. Defaults to `true`. */\n angleAxisLine?: boolean;\n /**\n * Shape of that line: straight-edged `polygon` (recharts' default) or a smooth\n * `circle`. Independent of `gridType`, so pair them to keep a circular web's\n * outline circular too.\n */\n angleAxisLineType?: 'polygon' | 'circle';\n /** Draw a tick line from the axis line to each spoke label. Defaults to `true`. */\n angleTickLine?: boolean;\n /**\n * Distance from each polygon vertex to its outer category label, in px.\n * Defaults to `4` (Figma geometry). When `showLabels` is on and no explicit\n * value is given, widens automatically to clear the value labels.\n */\n angleTickSize?: number;\n /**\n * Render the value scale — a radial axis of ticks from the centre outward, so\n * an area can be read as a number and not only compared to its neighbours.\n * Defaults to `false` (recharts draws no radius axis unless asked).\n *\n * `radiusAxisAngle` and `radiusAxisOrientation` only describe the drawn scale,\n * so they need it shown. `radiusAxisDomain`, `radiusAxisReversed` and\n * `radiusAxisTickCount` apply while it's hidden too — the first two scale the\n * web, and the third sets how many rings the grid draws (recharts takes the\n * grid's concentric radii from the radius axis' ticks).\n */\n showRadiusAxis?: boolean;\n /**\n * Angle the value scale is drawn at, in degrees counter-clockwise from 3\n * o'clock (recharts' default is `0`). Point it *between* two spokes: on a\n * spoke, the outermost tick collides with that category's own label.\n *\n * The ticks sit over the areas at any angle — a radar's plot area is its\n * areas — so this trades one overlap for none of the other.\n */\n radiusAxisAngle?: number;\n /** Which side of the scale its tick labels sit on. Defaults to `right`. */\n radiusAxisOrientation?: 'left' | 'right' | 'middle';\n /**\n * How the value scale is bounded — and with it the web, since the radius axis\n * is what maps a value to a radius:\n *\n * - unset — recharts' own scaling: the data's largest value reaches the outer\n * ring, so two charts of the same metric aren't comparable.\n * - `fixed` — pin the outer ring to `radiusAxisDomainMax` (the metric's own\n * maximum, e.g. a score out of 150), which is what makes a radar readable as\n * an absolute profile rather than a relative one.\n * - `auto` — fit the data at both ends; the scale need not start at 0.\n *\n * Takes effect whether or not the scale is shown, so a chart can be scaled to a\n * known maximum without displaying the ticks.\n */\n radiusAxisDomain?: 'auto' | 'fixed';\n /**\n * The value at the outer ring when `radiusAxisDomain` is `fixed`. Must be\n * positive — a `0` or negative maximum can't bound an outward-growing scale, so\n * it falls back to the data's own top.\n */\n radiusAxisDomainMax?: number;\n /**\n * Desired number of ticks on the value scale (a hint, not exact). Defaults to\n * recharts' `5`. Also sets how many rings the grid draws, whether or not the\n * scale itself is shown.\n */\n radiusAxisTickCount?: number;\n /**\n * Invert the value scale — the maximum at the centre and 0 at the outer ring —\n * for a metric where less is better (latency, error rate), so a good profile\n * still reads as a large area.\n */\n radiusAxisReversed?: boolean;\n /** Horizontal centre of the web, in px or a percentage of the width. Defaults to `50%`. */\n cx?: number | string;\n /**\n * Vertical centre of the web, in px or a percentage of the height. Defaults to\n * the middle of the plot band — i.e. `50%` of what the legend leaves, not of\n * the whole box (see `radarPlotBox`).\n */\n cy?: number | string;\n /** Angle the first category sits at, in degrees. Defaults to `90` (12 o'clock). */\n startAngle?: number;\n /**\n * Angle the sweep ends at, in degrees. Defaults to `-270` — a full turn\n * clockwise from `startAngle`. Together the two rotate the web (or wrap the\n * categories into a partial sweep).\n */\n endAngle?: number;\n /**\n * Radius of the hole at the centre, in px or a percentage of the available\n * radius. Defaults to `0`. Also lifts the grid and the areas off the centre,\n * which separates the series where they all bottom out.\n */\n innerRadius?: number | string;\n /**\n * Outer radius of the web, in px or a percentage of the available radius.\n * Defaults to `78px`, matching the Figma radar geometry. The legend and labels\n * do not change the radius — they change the box it is drawn in (see\n * `radarPlotBox`).\n */\n outerRadius?: number | string;\n /**\n * Plot-area margin, in px. Omit it entirely to use recharts' default (5 on\n * every side) — passing the object replaces all four, and recharts fills the\n * sides you leave out with `0`, not with `5`. Name every side you want.\n */\n margin?: { top?: number; right?: number; bottom?: number; left?: number };\n showTooltip?: boolean;\n showLegend?: boolean;\n /**\n * Font size of the legend text. Defaults to `'xs'` — the size the legend has\n * always rendered at. A larger size grows the legend band the plot is centred\n * above (the band is sized for `xs`; see `radarPlotBox`), so pair it with a\n * taller `className` height if the legend crowds the web. See\n * `ChartLegendFontSize`.\n */\n legendFontSize?: ChartLegendFontSize;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting, per-series rows, or extra fields without composing\n * recharts yourself. Ignored when `showTooltip` is false.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n /** Position of the value labels when `showLabels` is on. Defaults to `top`. */\n labelPosition?: CartesianLabelPosition;\n}\n\n// Distance from the polygon to the category tick text when value labels are on\n// (recharts' default is 8). Has to clear a CHART_LABEL_FONT_SIZE line plus the\n// LabelList's own 5px offset, or the topmost vertex's value overlaps its tick.\nconst RADAR_LABEL_TICK_SIZE = 30;\n\n// Vertical geometry of the chart's own box, in px.\n//\n// recharts centres a polar chart on the *whole* SVG: `cy` falls back to\n// `height / 2` and — unlike a percentage `outerRadius`, which it does fit to the\n// plot area — takes no account of the legend band it reserves at the bottom.\n// With the fixed-px `outerRadius` the Figma geometry asks for, that leaves the\n// ring the category labels are drawn on centred over rows the legend has\n// already claimed: the bottom label lands behind the legend and the top one runs\n// off the edge. `radarPlotBox` derives the box height and `cy` together so the\n// ring always has somewhere to go.\n\n// Half a `text-xs` line (16px). recharts anchors the top and bottom category\n// ticks' text *on* their point (`verticalAnchor: 'middle'`), so this much of the\n// text falls beyond the ring on each side.\nconst RADAR_TICK_TEXT_HALF_LINE = 8;\n// Figma's plot band. Holds the 78px web plus its 4px tick ring and that half\n// line (90px each side of the centre) with a little to spare.\nconst RADAR_PLOT_BAND = 187;\n// What a chart whose category ring outgrows RADAR_PLOT_BAND gets instead:\n// 2 × (78 + RADAR_LABEL_TICK_SIZE + RADAR_TICK_TEXT_HALF_LINE) — the cost of\n// `showLabels` at the Figma radius — rounded up to keep the same few px of slack\n// Figma's 187 leaves around the 4px ring.\nconst RADAR_LABELLED_PLOT_BAND = 240;\n// Figma's legend row, and what recharts' wrapper occupies too: it parks the\n// wrapper at `margin.bottom` (5) and `ChartLegendContent` is a `pt-3` above a\n// 16px line.\nconst RADAR_LEGEND_BAND = 32;\n\n/** The chart's own box: the height it reserves, and the polar centre inside it. */\nexport interface RadarPlotBox {\n /**\n * Tailwind height for the outer element. Merged *before* the consumer's\n * `className`, so a caller-supplied height still wins.\n */\n heightClass: string;\n /** `cy` for recharts, or `undefined` to keep its own `height / 2` default. */\n cy: string | undefined;\n}\n\n/**\n * Size the chart's box around its category ring, and centre the web in the part\n * of that box the legend does not take. Exported for unit tests; not part of the\n * package's public API.\n *\n * `ringRadius` is how far the category labels reach from the centre —\n * `outerRadius + angleTickSize + RADAR_TICK_TEXT_HALF_LINE` — or `undefined`\n * when `outerRadius` is a percentage, which recharts already fits to the plot\n * area (legend included) on its own.\n *\n * `cy` comes back as a percentage rather than the px it resolves to at the\n * default height, so a caller-supplied height keeps the proportion instead of\n * pinning the web to an absolute offset. On a taller box that lifts the web a\n * little further than the legend alone needs — towards the side with the slack.\n */\nexport function radarPlotBox(\n ringRadius: number | undefined,\n showLegend: boolean\n): RadarPlotBox {\n const tall = ringRadius !== undefined && ringRadius > RADAR_PLOT_BAND / 2;\n const plotBand = tall ? RADAR_LABELLED_PLOT_BAND : RADAR_PLOT_BAND;\n if (!showLegend) {\n // 240 / 187 — the plot band on its own.\n return { heightClass: tall ? 'h-[240px]' : 'h-[187px]', cy: undefined };\n }\n return {\n // 240 + 32 / 187 + 32 — the plot band above the legend band. Tailwind only\n // sees classes it can read in the source, so these stay literal.\n heightClass: tall ? 'h-[272px]' : 'h-[219px]',\n // Truncated rather than rounded: the leftover fraction has to come off the\n // top, the side with the slack, and never off the legend's.\n cy: `${Math.floor((plotBand / 2 / (plotBand + RADAR_LEGEND_BAND)) * 1e5) / 1e3}%`,\n };\n}\n\n/**\n * One series' `<Radar>` (and its value labels).\n *\n * Called as a plain function rather than mounted as `<RadarSeries />`, purely\n * to keep the chart's children readable as a flat list — recharts imposes no\n * constraint here. `RadarChart` picks up the series from the store `<Radar>`\n * registers itself in, and `Radar` passes its children straight through to a\n * label-list context instead of scanning them by type. `<Cell>` is the only\n * child recharts still looks up by element type, and a radar series has none.\n */\nfunction radarSeries({\n seriesKey,\n style,\n animation,\n showLabels,\n labelPosition,\n labelFormatter,\n}: {\n seriesKey: string;\n style: RadarSeriesStyle;\n animation: ResolvedAnimation;\n showLabels: boolean;\n labelPosition: CartesianLabelPosition;\n labelFormatter: ChartDataLabelProps['labelFormatter'];\n}) {\n return (\n <Radar\n key={seriesKey}\n dataKey={seriesKey}\n stroke={style.stroke}\n fill={style.fill}\n fillOpacity={style.fillOpacity}\n strokeWidth={style.strokeWidth}\n dot={style.dot}\n activeDot={style.activeDot}\n {...animation}\n >\n {showLabels && (\n <LabelList\n dataKey={seriesKey}\n position={labelPosition}\n formatter={toLabelFormatter(labelFormatter)}\n // A radar area is a flat `fillOpacity`, so an `inside*` label sits on\n // the *surface tinted by* the series color, not on the color itself —\n // the white on-fill token disappears into it in light mode. Same call\n // as the other translucent families (Area, the composed chart's areas).\n className={resolveLabelFillClass(labelPosition, {\n translucentSeries: true,\n })}\n fontSize={CHART_LABEL_FONT_SIZE}\n />\n )}\n </Radar>\n );\n}\n\nconst RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n (\n {\n className,\n config,\n palette,\n data,\n dataKeys,\n angleKey,\n seriesSettings,\n gridType = 'polygon',\n fillOpacity = 0.3,\n strokeWidth = 2,\n showDots = true,\n dotRadius = 2,\n activeDot,\n showGrid = true,\n radialLines = true,\n showAngleAxis = true,\n angleAxisOrientation,\n angleAxisLine = true,\n angleAxisLineType,\n angleTickLine = true,\n angleTickSize,\n showRadiusAxis = false,\n radiusAxisAngle,\n radiusAxisOrientation,\n radiusAxisDomain,\n radiusAxisDomainMax,\n radiusAxisTickCount,\n radiusAxisReversed = false,\n cx,\n cy,\n startAngle,\n endAngle,\n innerRadius,\n outerRadius: outerRadiusProp,\n margin,\n showTooltip = true,\n showLegend = true,\n legendFontSize,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n showLabels = false,\n labelPosition,\n labelFormatter,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n const radarLabelPosition = labelPosition ?? 'top';\n const radiusDomain = radarRadiusAxisDomain(\n radiusAxisDomain,\n radiusAxisDomainMax\n );\n // The radius axis is only mounted when it has something to do: it either\n // paints the scale, or it carries a domain/reversal that rescales the web\n // (recharts registers those from the element even when nothing is drawn).\n // Without one of the three, leaving the element out keeps recharts' own\n // implicit axis — and every existing chart's geometry.\n const hasRadiusAxis =\n showRadiusAxis || radiusDomain !== undefined || radiusAxisReversed;\n const seriesDefaults: RadarSeriesDefaults = {\n fillOpacity,\n strokeWidth,\n showDots,\n dotRadius,\n activeDot,\n };\n const outerRadius = outerRadiusProp ?? 78;\n const resolvedTickSize =\n angleTickSize ?? (showLabels ? RADAR_LABEL_TICK_SIZE : 4);\n // A percentage `outerRadius` is already fitted to the plot area by recharts,\n // so only a fixed radius has a ring whose reach the box has to be sized to.\n const plotBox = radarPlotBox(\n typeof outerRadius === 'number'\n ? outerRadius + resolvedTickSize + RADAR_TICK_TEXT_HALF_LINE\n : undefined,\n showLegend\n );\n // When the consumer supplies their own height (size-*, h-*, min-h-*, max-h-*)\n // the plotBox.cy percentage — calibrated for the compact default heights — would\n // shift the web too far up in a taller box. Fall back to recharts' default\n // cy = height/2 in that case; a large container has room for ring + legend\n // without the legend-band compensation radarPlotBox does.\n const consumerOwnsHeight = /(?:^|\\s)(?:h-|size-|min-h-|max-h-)/.test(\n className ?? ''\n );\n return (\n <div\n ref={ref}\n data-grid-type={gridType}\n // Default height matches the Figma geometry (187px plot + 32px legend),\n // widening only when the category ring outgrows it (see `radarPlotBox`).\n // The consumer's `className` is merged after the default, so a\n // caller-supplied height (e.g. `h-[380px]`) wins via Tailwind's\n // last-class-wins rule.\n className={cn(\n radarChartVariants({ gridType }),\n plotBox.heightClass,\n className\n )}\n {...props}\n >\n <ChartContainer\n config={config}\n palette={palette}\n // The shared container themes cartesian axis ticks but not polar ones,\n // so scope the angle-axis (spoke) labels and the radius-axis scale to\n // the muted-foreground / border tokens here — otherwise they render\n // near-black (or recharts' raw `#ccc`) and vanish in dark mode. This\n // is a shared-primitives gap (a Chart task); worked around locally, not\n // by editing chart.tsx.\n className={cn(\n 'size-full',\n \"[&_.recharts-polar-angle-axis-tick_text]:fill-[var(--ui-text-on-surface-secondary)]! [&_.recharts-polar-angle-axis-tick_text]:text-xs [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-[var(--ui-border-on-surface-divider)]! [&_.recharts-polar-radius-axis-line]:stroke-[var(--ui-border-on-surface-divider)]! [&_.recharts-polar-radius-axis-tick_text]:fill-[var(--ui-text-on-surface-secondary)]! [&_.recharts-polar-radius-axis-tick_text]:text-xs\"\n )}\n >\n <RechartsRadarChart\n data={data as readonly unknown[]}\n cx={cx}\n cy={cy ?? (consumerOwnsHeight ? undefined : plotBox.cy)}\n startAngle={startAngle}\n endAngle={endAngle}\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n margin={margin}\n >\n {showTooltip && (\n <ChartTooltip content={tooltipContent ?? <ChartTooltipContent />} />\n )}\n {showGrid && (\n <PolarGrid gridType={gridType ?? 'polygon'} radialLines={radialLines} />\n )}\n <PolarAngleAxis\n dataKey={angleKey}\n orientation={angleAxisOrientation}\n axisLineType={angleAxisLineType}\n // `showAngleAxis` hides the chrome rather than dropping the axis:\n // the angle axis is also what maps a row to its category name, so\n // removing it would leave the tooltip labelling rows by index.\n tick={showAngleAxis}\n axisLine={showAngleAxis && angleAxisLine}\n tickLine={showAngleAxis && angleTickLine}\n // Push the category ticks out when value labels are on. recharts\n // gives a Radar's label list a *cartesian* viewBox (width/height 0\n // at the vertex), so `top` offsets straight up in screen space —\n // at the topmost vertex the value lands on its own category tick.\n // The tick text is drawn at `outerRadius + tickSize`, so this is\n // the only lever that adds *absolute* clearance: shrinking\n // outerRadius scales the tick ring down with the polygon and keeps\n // the overlap. Default 4px matches the Figma geometry when labels\n // are off. The box grows to fit whatever this resolves to — see\n // `radarPlotBox`.\n tickSize={resolvedTickSize}\n />\n {hasRadiusAxis && (\n <PolarRadiusAxis\n angle={radiusAxisAngle}\n orientation={radiusAxisOrientation}\n domain={radiusDomain}\n tickCount={radiusAxisTickCount}\n reversed={radiusAxisReversed}\n tick={showRadiusAxis}\n axisLine={showRadiusAxis}\n />\n )}\n {showLegend && (\n <ChartLegend\n verticalAlign=\"bottom\"\n content={\n <ChartLegendContent\n verticalAlign=\"bottom\"\n fontSize={legendFontSize}\n />\n }\n />\n )}\n {dataKeys.map((key) =>\n radarSeries({\n seriesKey: key,\n style: radarSeriesStyle(\n key,\n seriesSettings?.[key],\n seriesDefaults\n ),\n animation,\n showLabels,\n labelPosition: radarLabelPosition,\n labelFormatter,\n })\n )}\n </RechartsRadarChart>\n </ChartContainer>\n </div>\n );\n }\n);\nRadarChart.displayName = 'RadarChart';\n\nexport { RadarChart, radarChartVariants };\n"],"mappings":"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"}
@@ -128,7 +128,7 @@ function ee({ seriesKeys: e, seriesData: t, isMultiMetric: n, config: r, nameKey
128
128
  ]
129
129
  }, e));
130
130
  }
131
- function te({ ringSegments: e, row: t, nameKey: n, cornerRadius: r, animation: i, centerLabel: a }) {
131
+ function A({ ringSegments: e, row: t, nameKey: n, cornerRadius: r, animation: i, centerLabel: a }) {
132
132
  return e.map((e, o) => /* @__PURE__ */ f(y, {
133
133
  dataKey: e.key,
134
134
  stackId: "segments",
@@ -139,30 +139,30 @@ function te({ ringSegments: e, row: t, nameKey: n, cornerRadius: r, animation: i
139
139
  children: o === 0 && a && /* @__PURE__ */ f(x, { centerLabel: a })
140
140
  }, e.key));
141
141
  }
142
- var A = u.forwardRef(({ className: l, config: d, palette: m, data: h, dataKey: g, dataKeys: y, nameKey: x, innerRadius: S = 20, outerRadius: T = 60, startAngle: E = 90, endAngle: k = -270, valueDomain: A, cornerRadius: j = 4, cx: ne, cy: M, barSize: re, barGap: ie, barCategoryGap: ae, minAngle: N, margin: oe, segments: P, segmentGap: se = C, showBackground: ce = !0, showPolarGrid: le = !1, centerLabel: F, showTooltip: ue = !0, showLegend: I = !0, legendValueFormatter: L, tooltipContent: R, animate: z, animationDuration: B, animationBegin: V, animationEasing: H, showLabels: U = !1, labelPosition: de, labelFormat: fe = "value", labelFormatter: pe, ...me }, he) => {
143
- let W = c({
144
- animate: z,
145
- animationDuration: B,
146
- animationBegin: V,
147
- animationEasing: H
148
- }), G = de ?? "insideStart", K = !!y?.length, q = P != null && P > 1 && !K && h.length === 1 && typeof h[0][g] == "number", ge = K ? y : [g], J = u.useMemo(() => y?.length ? y : [g], [y, g]), Y = Math.abs(k - E), X = q ? w({
142
+ var j = u.forwardRef(({ className: l, config: d, palette: m, data: h, dataKey: g, dataKeys: y, nameKey: x, innerRadius: S = 20, outerRadius: T = 60, startAngle: E = 90, endAngle: k = -270, valueDomain: j, cornerRadius: M = 4, cx: te, cy: N, barSize: ne, barGap: re, barCategoryGap: ie, minAngle: P, margin: ae, segments: F, segmentGap: oe = C, showBackground: se = !0, showPolarGrid: ce = !1, centerLabel: I, showTooltip: le = !0, showLegend: L = !0, legendFontSize: R, legendValueFormatter: z, tooltipContent: B, animate: V, animationDuration: H, animationBegin: U, animationEasing: ue, showLabels: W = !1, labelPosition: de, labelFormat: fe = "value", labelFormatter: pe, ...me }, he) => {
143
+ let G = c({
144
+ animate: V,
145
+ animationDuration: H,
146
+ animationBegin: U,
147
+ animationEasing: ue
148
+ }), K = de ?? "insideStart", q = !!y?.length, J = F != null && F > 1 && !q && h.length === 1 && typeof h[0][g] == "number", ge = q ? y : [g], Y = u.useMemo(() => y?.length ? y : [g], [y, g]), X = Math.abs(k - E), Z = J ? w({
149
149
  value: h[0][g],
150
- domain: A ?? [0, h[0][g]],
151
- segments: P,
152
- gap: se,
153
- sweep: Y,
154
- closed: Y >= 360
155
- }) : [], Z = K ? h : h.map((e) => ({
150
+ domain: j ?? [0, h[0][g]],
151
+ segments: F,
152
+ gap: oe,
153
+ sweep: X,
154
+ closed: X >= 360
155
+ }) : [], Q = q ? h : h.map((e) => ({
156
156
  ...e,
157
157
  fill: `var(--color-${s(String(e[x]))})`
158
- })), Q = q ? [{
158
+ })), _e = J ? [{
159
159
  ...h[0],
160
- ...Object.fromEntries(X.map((e) => [e.key, e.degrees]))
161
- }] : Z, _e = N === void 0 ? void 0 : k < E ? -N : N, $ = u.useMemo(() => I ? o(d, m ?? t) : null, [
162
- I,
160
+ ...Object.fromEntries(Z.map((e) => [e.key, e.degrees]))
161
+ }] : Q, ve = P === void 0 ? void 0 : k < E ? -P : P, $ = u.useMemo(() => L ? o(d, m ?? t) : null, [
162
+ L,
163
163
  d,
164
164
  m
165
- ]), ve = u.useMemo(() => $ ? K ? J.map((e) => ({
165
+ ]), ye = u.useMemo(() => $ ? q ? Y.map((e) => ({
166
166
  value: e,
167
167
  dataKey: e,
168
168
  color: $[e]?.color ?? `var(--color-${s(e)})`,
@@ -176,102 +176,103 @@ var A = u.forwardRef(({ className: l, config: d, palette: m, data: h, dataKey: g
176
176
  payload: e
177
177
  })) : [], [
178
178
  $,
179
- K,
180
- J,
179
+ q,
180
+ Y,
181
181
  h,
182
182
  x
183
- ]), ye = I && !q && !!$, be = /* @__PURE__ */ p(b, {
184
- data: Q,
185
- dataKey: K || q ? void 0 : g,
186
- cx: ne,
187
- cy: M,
183
+ ]), be = L && !J && !!$, xe = /* @__PURE__ */ p(b, {
184
+ data: _e,
185
+ dataKey: q || J ? void 0 : g,
186
+ cx: te,
187
+ cy: N,
188
188
  innerRadius: S,
189
189
  outerRadius: T,
190
190
  startAngle: E,
191
191
  endAngle: k,
192
- barSize: re,
193
- barGap: ie,
194
- barCategoryGap: ae,
195
- margin: oe ?? {
192
+ barSize: ne,
193
+ barGap: re,
194
+ barCategoryGap: ie,
195
+ margin: ae ?? {
196
196
  top: 0,
197
197
  right: 0,
198
198
  bottom: 0,
199
199
  left: 0
200
200
  },
201
201
  children: [
202
- le && /* @__PURE__ */ f(v, {
202
+ ce && /* @__PURE__ */ f(v, {
203
203
  gridType: "circle",
204
204
  radialLines: !1
205
205
  }),
206
- (A || q) && /* @__PURE__ */ f(_, {
206
+ (j || J) && /* @__PURE__ */ f(_, {
207
207
  type: "number",
208
- domain: q ? [0, Y] : A,
208
+ domain: J ? [0, X] : j,
209
209
  tick: !1,
210
210
  axisLine: !1
211
211
  }),
212
- ue && /* @__PURE__ */ f(i, {
213
- cursor: !q && void 0,
214
- content: R ?? (q ? /* @__PURE__ */ f(D, {
212
+ le && /* @__PURE__ */ f(i, {
213
+ cursor: !J && void 0,
214
+ content: B ?? (J ? /* @__PURE__ */ f(D, {
215
215
  config: d,
216
216
  row: h[0],
217
217
  nameKey: x,
218
218
  dataKey: g,
219
- domainMax: A?.[1]
220
- }) : K ? /* @__PURE__ */ f(a, { labelFormatter: (e, t) => O(t?.[0]?.payload, x) }) : /* @__PURE__ */ f(a, {
219
+ domainMax: j?.[1]
220
+ }) : q ? /* @__PURE__ */ f(a, { labelFormatter: (e, t) => O(t?.[0]?.payload, x) }) : /* @__PURE__ */ f(a, {
221
221
  nameKey: x,
222
222
  hideLabel: !0
223
223
  }))
224
224
  }),
225
- q ? /* @__PURE__ */ f(te, {
226
- ringSegments: X,
225
+ J ? /* @__PURE__ */ f(A, {
226
+ ringSegments: Z,
227
227
  row: h[0],
228
228
  nameKey: x,
229
- cornerRadius: j,
230
- animation: W,
231
- centerLabel: F
229
+ cornerRadius: M,
230
+ animation: G,
231
+ centerLabel: I
232
232
  }) : /* @__PURE__ */ f(ee, {
233
233
  seriesKeys: ge,
234
- seriesData: Z,
235
- isMultiMetric: K,
234
+ seriesData: Q,
235
+ isMultiMetric: q,
236
236
  config: d,
237
237
  nameKey: x,
238
- showBackground: ce,
239
- cornerRadius: j,
240
- minPointSize: _e,
241
- animation: W,
242
- centerLabel: F,
243
- showLabels: U,
244
- labelPosition: G,
238
+ showBackground: se,
239
+ cornerRadius: M,
240
+ minPointSize: ve,
241
+ animation: G,
242
+ centerLabel: I,
243
+ showLabels: W,
244
+ labelPosition: K,
245
245
  labelFormat: fe,
246
246
  labelFormatter: pe
247
247
  })
248
248
  ]
249
- }), xe = U && (G === "outside" || G === "end") ? "size-[200px]" : "size-[120px]";
249
+ }), Se = W && (K === "outside" || K === "end") ? "size-[200px]" : "size-[120px]";
250
250
  return /* @__PURE__ */ p("div", {
251
251
  ref: he,
252
- className: e("flex flex-row items-center gap-4", !ye && "justify-center", l),
252
+ className: e("flex flex-row items-center gap-4", !be && "justify-center", l),
253
253
  ...me,
254
254
  children: [/* @__PURE__ */ f("div", {
255
- className: e(xe, "shrink-0"),
255
+ className: e(Se, "shrink-0"),
256
256
  children: /* @__PURE__ */ f(n, {
257
257
  config: d,
258
258
  palette: m,
259
259
  className: "size-full",
260
- children: be
260
+ children: xe
261
261
  })
262
- }), I && !q && $ && /* @__PURE__ */ f(r, {
262
+ }), L && !J && $ && /* @__PURE__ */ f(r, {
263
263
  variant: "list",
264
- payload: ve,
264
+ payload: ye,
265
265
  config: $,
266
- nameKey: K ? void 0 : x,
267
- valueKey: K ? void 0 : g,
268
- valueFormatter: K ? void 0 : L,
266
+ nameKey: q ? void 0 : x,
267
+ fontSize: R,
268
+ valueKey: q ? void 0 : g,
269
+ valueFormatter: q ? void 0 : z,
269
270
  className: "min-w-0 flex-1"
270
271
  })]
271
272
  });
272
273
  });
273
- A.displayName = "RadialBarChart";
274
+ j.displayName = "RadialBarChart";
274
275
  //#endregion
275
- export { A as RadialBarChart, D as RadialBarChartSegmentedTooltipContent, O as radialBarChartBandName, S as radialBarChartLabelText, T as radialBarChartSegmentFill, E as radialBarChartSegmentedReading, w as radialBarChartSegments };
276
+ export { j as RadialBarChart, D as RadialBarChartSegmentedTooltipContent, O as radialBarChartBandName, S as radialBarChartLabelText, T as radialBarChartSegmentFill, E as radialBarChartSegmentedReading, w as radialBarChartSegments };
276
277
 
277
278
  //# sourceMappingURL=radial-bar-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radial-bar-chart.js","names":[],"sources":["../../../../src/components/ui/radial-bar-chart/radial-bar-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n Cell,\n Label,\n LabelList,\n PolarAngleAxis,\n PolarGrid,\n RadialBar,\n RadialBarChart as RechartsRadialBarChart,\n} from 'recharts';\n\nimport type { LegendPayload } from 'recharts/types/component/DefaultLegendContent';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n resolveChartColors,\n resolveLabelFillClass,\n CHART_DEFAULT_PALETTE,\n CHART_LABEL_FONT_SIZE,\n type ChartConfig,\n type ChartPalette,\n type ChartAnimationProps,\n type ChartDataLabelProps,\n type ChartTooltipContentProps,\n type PolarLabelPosition,\n toCssKey,\n type ResolvedAnimation,\n type TickFormatter,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives (a polar/radial\n// type). Rows become concentric arcs sized by `dataKey`, each colored from its\n// `--color-<name>` var; `dataKeys` switches to one arc per metric instead. Like\n// ScatterChart/ComposedChart there's no CVA variant: a radial bar's\n// expressiveness is geometry (angles/radii, plain props) and the data mapping,\n// not a visual \"mode\". The angular sweep is exposed as startAngle/endAngle props\n// so a caller can build a gauge or a full ring.\n\n/** Row-per-arc datum: the `nameKey` label plus each metric's numeric value. */\ntype RadialBarChartDatum = Record<string, string | number>;\n\n/** What an arc's data label reads. */\nexport type RadialBarChartLabelFormat = 'value' | 'name-value';\n\nexport interface RadialBarChartCenterLabel {\n // Rendered as SVG <text>, which only lays out text — hence string | number,\n // not ReactNode.\n /** Headline metric rendered large in the hole (e.g. the gauge's value). */\n value?: string | number;\n /** Caption rendered under the value. */\n label?: string | number;\n}\n\n/**\n * The readout in the hole at the centre of the arcs — a headline value over a\n * caption. Rendered as a recharts `<Label>`, which is what supplies the polar\n * viewBox the text centres itself on.\n *\n * There is one readout for the whole chart, so it hangs off the first series\n * drawn — every series shares the same viewBox.\n */\nfunction RadialBarChartCenterLabelContent({\n centerLabel,\n}: {\n centerLabel: RadialBarChartCenterLabel;\n}) {\n return (\n <Label\n content={({ viewBox }) => {\n if (!viewBox || !('cx' in viewBox)) return null;\n const { cx: centerX = 0, cy: centerY = 0 } = viewBox as {\n cx?: number;\n cy?: number;\n };\n const hasValue = centerLabel.value != null;\n const hasLabel = centerLabel.label != null;\n // Straddle the centre when both lines show, so the value + label block\n // is centered as a whole (not just the value).\n const both = hasValue && hasLabel;\n return (\n <g>\n {hasValue && (\n <text\n x={centerX}\n y={both ? centerY - 10 : centerY}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-foreground text-2xl font-semibold\"\n >\n {centerLabel.value}\n </text>\n )}\n {hasLabel && (\n <text\n x={centerX}\n y={both ? centerY + 13 : centerY}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-muted-foreground text-sm\"\n >\n {centerLabel.label}\n </text>\n )}\n </g>\n );\n }}\n />\n );\n}\n\n/**\n * Compose one arc's data-label text. Exported for unit tests; not part of the\n * package's public API.\n *\n * `labelFormatter` only ever formats the numeric part, so a chart's labels and\n * its tooltip stay in the same units under either format. A nullish value yields\n * an empty label, which recharts renders as no `<text>` at all.\n */\nexport function radialBarChartLabelText(options: {\n format: RadialBarChartLabelFormat;\n name: string | number | undefined;\n value: string | number | undefined;\n formatter?: TickFormatter;\n}): string {\n const { format, name, value, formatter } = options;\n if (value == null) return '';\n const valueText = formatter ? formatter(value) : String(value);\n return format === 'name-value' && name != null\n ? `${name}: ${valueText}`\n : valueText;\n}\n\n/** One piece of a segmented gauge's ring: a length in degrees and what it is. */\nexport interface RadialBarChartSegment {\n /** Synthetic series key — stable for a given (index, kind). */\n key: string;\n /** Angular length of the piece, in degrees. */\n degrees: number;\n /** `value` is the metric, `track` the unreached remainder, `gap` the notch. */\n kind: 'value' | 'track' | 'gap';\n}\n\n/** Fallback gap between a segmented gauge's segments, in degrees. */\nconst SEGMENT_GAP = 3;\n\n/**\n * Cut a gauge's sweep into equal segments separated by gaps, and split the\n * segment the value ends inside into its reached and unreached parts. Exported\n * for unit tests; not part of the package's public API.\n *\n * Lengths come back in **degrees**, which is what lets the ring be built as one\n * stack of synthetic series over a `[0, sweep]` angular scale: recharts lays\n * stacked radial bars out sequentially along the angle, so a transparent series\n * between two colored ones reads as a real notch in the ring. A `gap` that\n * would leave no room for the segments themselves is clamped.\n */\nexport function radialBarChartSegments(options: {\n value: number;\n domain: [number, number];\n segments: number;\n gap: number;\n /** Absolute sweep of the chart, in degrees. */\n sweep: number;\n /** A full-circle sweep also needs a gap between the last segment and the first. */\n closed: boolean;\n}): RadialBarChartSegment[] {\n const { value, domain, segments, sweep, closed } = options;\n const gapCount = closed ? segments : segments - 1;\n // Leave at least half the sweep for the segments, however wide a gap is asked\n // for — an all-gap ring would render as nothing at all. A negative gap would\n // stretch the pieces past the sweep and overlap them, so it floors at zero.\n const gap =\n gapCount > 0\n ? Math.min(Math.max(options.gap, 0), sweep / (2 * gapCount))\n : 0;\n const segmentDegrees = (sweep - gap * gapCount) / segments;\n const [min, max] = domain;\n const span = max - min;\n // A domain with no span (`[n, n]`) or an inverted one (`[max, min]`) cannot\n // place a value on the ring at all, so there is no fraction to draw and the\n // ring stays empty. It deliberately does not fall back to comparing the value\n // against zero: that reported a *full* ring for `{ value: 5, domain: [100,\n // 100] }`, i.e. claimed completion the data never supported. For a gauge,\n // under-reading a domain that says nothing is the safe direction.\n const fraction =\n span > 0 ? Math.min(Math.max((value - min) / span, 0), 1) : 0;\n // The value maps onto the *drawn* ring, so the gaps never eat into it.\n let remainingValue = fraction * segmentDegrees * segments;\n\n const pieces: RadialBarChartSegment[] = [];\n for (let index = 0; index < segments; index++) {\n const reached = Math.min(Math.max(remainingValue, 0), segmentDegrees);\n remainingValue -= reached;\n // Both halves are always emitted, including at zero length: a stable key set\n // keeps recharts' series identities steady as the value changes.\n pieces.push({ key: `seg-${index}-value`, degrees: reached, kind: 'value' });\n pieces.push({\n key: `seg-${index}-track`,\n degrees: segmentDegrees - reached,\n kind: 'track',\n });\n if (gap > 0 && (closed || index < segments - 1)) {\n pieces.push({ key: `seg-${index}-gap`, degrees: gap, kind: 'gap' });\n }\n }\n return pieces;\n}\n\n/**\n * Fill for one piece of a segmented gauge's ring. Exported for unit tests and so\n * the forced-open tooltip story can build a ring from the real implementation\n * rather than a copy of it; not part of the package's public API.\n */\nexport function radialBarChartSegmentFill(\n kind: RadialBarChartSegment['kind'],\n colorName: string | number\n): string {\n if (kind === 'gap') return 'transparent';\n // The unreached remainder plays the part `showBackground`'s track plays on a\n // continuous arc, so it takes the same muted surface.\n return kind === 'track'\n ? 'var(--ui-border-on-status-neutral)'\n : `var(--color-${toCssKey(String(colorName))})`;\n}\n\n/**\n * What a segmented gauge's tooltip reads. Exported for unit tests; not part of\n * the package's public API.\n *\n * A segmented ring's series are pieces of geometry, so recharts would offer the\n * hovered piece's own name and length (\"seg-3-value\", 41.2°). Hovering anywhere\n * on the ring should read the metric instead, so the reading is rebuilt from the\n * data row.\n */\nexport function radialBarChartSegmentedReading(options: {\n config: ChartConfig;\n row: RadialBarChartDatum;\n nameKey: string;\n dataKey: string;\n /** The `valueDomain` maximum, when the gauge has one. */\n domainMax?: number;\n}): { colorName: string; label: React.ReactNode; valueText: string } {\n const { config, row, nameKey, dataKey, domainMax } = options;\n const colorName = String(row[nameKey]);\n const value = row[dataKey];\n const valueText =\n typeof value === 'number' ? value.toLocaleString() : String(value ?? '');\n return {\n colorName,\n label: config[colorName]?.label ?? colorName,\n // The gauge's scale is the other half of the reading, so a known maximum\n // comes along: \"29 / 38\", not a bare \"29\".\n valueText:\n domainMax == null\n ? valueText\n : `${valueText} / ${domainMax.toLocaleString()}`,\n };\n}\n\n/**\n * The tooltip a segmented gauge shows — the same swatch/name/value layout the\n * default `ChartTooltipContent` row uses, dot included, over the reading from\n * `radialBarChartSegmentedReading`. Exported for the forced-open\n * visual-regression story; not part of the package's public API.\n *\n * `payload` is trimmed to one row: a radial tooltip is axis-shared and collects a\n * row from every series — two dozen identical rows for one metric.\n * (`tooltipType=\"none\"` only tags them, and scoping the tooltip to the hovered\n * item instead would drop it in the corner — unlike Pie/Bar sectors, a RadialBar\n * sector carries no tooltip coordinate.)\n *\n * A real component rather than a closure so it can be handed to `ChartTooltip`\n * as an *element*: recharts `cloneElement`s an element but `createElement`s a\n * function, and a closure rebuilt each render is a new element *type* — which\n * remounts the tooltip on every parent render instead of updating it.\n */\nexport function RadialBarChartSegmentedTooltipContent({\n active,\n payload,\n ...reading\n}: {\n active?: boolean;\n // Loosely typed on purpose: recharts' own payload generics are wider than the\n // shared `ChartTooltipContentProps` accepts, and only the row count matters.\n payload?: readonly unknown[];\n config: ChartConfig;\n row: RadialBarChartDatum;\n nameKey: string;\n dataKey: string;\n domainMax?: number;\n}) {\n const { colorName, label, valueText } =\n radialBarChartSegmentedReading(reading);\n\n return (\n <ChartTooltipContent\n active={active}\n payload={payload?.slice(0, 1) as ChartTooltipContentProps['payload']}\n hideLabel\n formatter={() => (\n <>\n <div\n className=\"h-2.5 w-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: `var(--color-${toCssKey(colorName)})` }}\n />\n <div className=\"flex flex-1 items-center justify-between gap-2 leading-none\">\n <span className=\"text-muted-foreground\">{label}</span>\n <span className=\"font-medium tabular-nums text-foreground\">\n {valueText}\n </span>\n </div>\n </>\n )}\n />\n );\n}\n\n/**\n * The band a multi-metric tooltip's header names. Exported for unit tests; not\n * part of the package's public API.\n *\n * Each tooltip row is one metric, so the header names the band the hovered arc\n * belongs to. recharts' own label is the radius-axis index, which reads as a\n * bare number.\n */\nexport function radialBarChartBandName(\n row: RadialBarChartDatum | undefined,\n nameKey: string\n): string {\n const name = row?.[nameKey];\n return name == null ? '' : String(name);\n}\n\n/**\n * What an arc's data label calls the arc: the row's own `nameKey` value, or — in\n * multi-metric mode, where one arc *is* one metric — that metric's `config` label.\n */\nfunction radialBarChartArcName(options: {\n key: string;\n row: RadialBarChartDatum | undefined;\n isMultiMetric: boolean;\n nameKey: string;\n config: ChartConfig;\n}): string | number | undefined {\n const { key, row, isMultiMetric, nameKey, config } = options;\n if (!isMultiMetric) return row?.[nameKey];\n // ChartConfig labels are ReactNode; only a plain string/number can go into an\n // SVG <text>.\n const label = config[key]?.label;\n return typeof label === 'string' || typeof label === 'number' ? label : key;\n}\n\n/**\n * The default mapping's arcs: one `RadialBar` per series — one for the single\n * `dataKey`, or one per `dataKeys` entry in multi-metric mode — drawn\n * concentrically.\n *\n * recharts collects its graphical items from the store (each `RadialBar`\n * registers itself on render) rather than by scanning the chart's children for\n * their types, so grouping them inside a component of our own is invisible to it.\n * The `Cell`s stay direct children of their `RadialBar`, which *does* read its own\n * children by type.\n */\nfunction RadialBarChartSeries({\n seriesKeys,\n seriesData,\n isMultiMetric,\n config,\n nameKey,\n showBackground,\n cornerRadius,\n minPointSize,\n animation,\n centerLabel,\n showLabels,\n labelPosition,\n labelFormat,\n labelFormatter,\n}: {\n seriesKeys: string[];\n seriesData: RadialBarChartDatum[];\n isMultiMetric: boolean;\n config: ChartConfig;\n nameKey: string;\n showBackground: boolean;\n cornerRadius: number;\n minPointSize: number | undefined;\n animation: ResolvedAnimation;\n centerLabel: RadialBarChartCenterLabel | undefined;\n showLabels: boolean;\n labelPosition: PolarLabelPosition;\n labelFormat: RadialBarChartLabelFormat;\n labelFormatter?: TickFormatter;\n}) {\n return seriesKeys.map((key, seriesIndex) => (\n <RadialBar\n key={key}\n dataKey={key}\n fill={isMultiMetric ? `var(--color-${toCssKey(key)})` : undefined}\n background={showBackground ? { fill: 'var(--ui-border-on-status-neutral)' } : false}\n cornerRadius={cornerRadius}\n minPointSize={minPointSize}\n {...animation}\n >\n {!isMultiMetric &&\n seriesData.map((entry, index) => (\n // Keyed by index, not the name: two arcs could share a nameKey\n // value, which would collide as a React key. Same-named arcs\n // intentionally share a color/config entry via `--color-<name>`.\n <Cell key={index} fill={`var(--color-${toCssKey(String(entry[nameKey]))})`} />\n ))}\n {seriesIndex === 0 && centerLabel && (\n <RadialBarChartCenterLabelContent centerLabel={centerLabel} />\n )}\n {showLabels && (\n <LabelList\n // `valueAccessor` rather than `dataKey`: the label text can\n // carry the arc's name, which only the whole row (single\n // metric) or the metric's config entry can supply. recharts\n // ignores the accessor when a dataKey is set, so the two\n // can't be combined.\n valueAccessor={(entry) =>\n radialBarChartLabelText({\n format: labelFormat,\n name: radialBarChartArcName({\n key,\n row: entry.payload as RadialBarChartDatum | undefined,\n isMultiMetric,\n nameKey,\n config,\n }),\n value: entry.value as string | number | undefined,\n formatter: labelFormatter,\n })\n }\n position={labelPosition}\n className={resolveLabelFillClass(labelPosition)}\n fontSize={CHART_LABEL_FONT_SIZE}\n />\n )}\n </RadialBar>\n ));\n}\n\n/**\n * A segmented gauge's ring: the pieces from `radialBarChartSegments` as one stack\n * of synthetic series, so they lay out sequentially around the ring instead of\n * concentrically and the `gap` pieces read as notches.\n */\nfunction RadialBarChartSegmentedSeries({\n ringSegments,\n row,\n nameKey,\n cornerRadius,\n animation,\n centerLabel,\n}: {\n ringSegments: RadialBarChartSegment[];\n row: RadialBarChartDatum;\n nameKey: string;\n cornerRadius: number;\n animation: ResolvedAnimation;\n centerLabel: RadialBarChartCenterLabel | undefined;\n}) {\n return ringSegments.map((segment, index) => (\n <RadialBar\n key={segment.key}\n dataKey={segment.key}\n stackId=\"segments\"\n // The metric's name, so the hover has a row to key off at all\n // (`ChartTooltipContent` keys its row off `name`).\n name={String(row[nameKey])}\n fill={radialBarChartSegmentFill(segment.kind, row[nameKey])}\n cornerRadius={cornerRadius}\n {...animation}\n >\n {index === 0 && centerLabel && (\n <RadialBarChartCenterLabelContent centerLabel={centerLabel} />\n )}\n </RadialBar>\n ));\n}\n\nexport interface RadialBarChartProps\n extends\n Omit<React.ComponentProps<'div'>, 'children'>,\n ChartAnimationProps,\n ChartDataLabelProps {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /** Row-per-arc data. Each object holds the arc's `nameKey` label + its `dataKey` numeric value. */\n data: ReadonlyArray<RadialBarChartDatum>;\n /**\n * Per-arc map of `label` / `icon` / `tone`, keyed by the arc's `nameKey` value\n * — or, in multi-metric mode, by each `dataKeys` entry (imported from the\n * shared `Chart` primitives). Turned into `--color-<name>` custom properties.\n * Series take their colour from the container's `palette`; each entry maps a\n * key to a `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Numeric field that sizes each arc. Ignored when `dataKeys` is set. */\n dataKey: string;\n /**\n * Plot several metrics instead of one arc per row: one arc per key, colored and\n * named from `config` keyed by the **key** (not by `nameKey`) — the same\n * convention as the cartesian charts. Every metric shares one angular scale, so\n * pair it with `valueDomain` when the metrics are measured against a known\n * maximum. `nameKey` still names the band each metric's arc sits in.\n */\n dataKeys?: string[];\n /**\n * Label field that names each arc (drives the legend, tooltip, and\n * `--color-<name>` lookup). Values should be unique per chart (arcs sharing a\n * name share one `config`/color entry); they are sanitized automatically to a\n * valid CSS custom-property fragment (CSS-safe values are preferred to avoid\n * dev-mode warnings). In multi-metric mode it names the band rather than the\n * arc, so the legend and colors come from `dataKeys` instead.\n */\n nameKey: string;\n /** Inner radius of the innermost arc. */\n innerRadius?: number;\n /** Outer radius of the outermost arc. */\n outerRadius?: number;\n /** Angle (degrees) the arcs sweep from. */\n startAngle?: number;\n /** Angle (degrees) the arcs sweep to (default is a full clockwise circle). */\n endAngle?: number;\n /**\n * The value range the sweep represents, as `[min, max]`. Without it every arc\n * is drawn relative to the largest value in the data — so a **single** value\n * always fills the whole sweep, which is never what a gauge means. Set it to\n * the metric's own scale (e.g. `[0, 100]` for a percentage) and each arc\n * becomes that fraction of the sweep, over the `showBackground` track.\n */\n valueDomain?: [number, number];\n /** Corner radius on each arc's ends. */\n cornerRadius?: number;\n /**\n * Horizontal center of the arcs, in px or a percentage of the width.\n * Defaults to the middle (`50%`).\n */\n cx?: number | string;\n /**\n * Vertical center of the arcs, in px or a percentage of the height. Defaults to\n * the middle (`50%`) — worth moving for a half-circle gauge, whose drawn half\n * otherwise sits in the upper half of the surface.\n */\n cy?: number | string;\n /** Thickness of each arc, in px. Omit to let the radii and the gaps size it. */\n barSize?: number;\n /** Gap between the arcs of different metrics in one band, in px. */\n barGap?: number | string;\n /** Gap between bands, in px or a percentage string. */\n barCategoryGap?: number | string;\n /**\n * Smallest angle a non-zero arc may occupy, in degrees, so a tiny value stays\n * visible (and hoverable). recharts applies the floor to a `0` as well, which\n * reads as a small positive value — leave this unset when a metric can\n * legitimately be zero.\n */\n minAngle?: number;\n /** Plot-area margin, in px. Omit to use recharts' default (5 on every side). */\n margin?: { top?: number; right?: number; bottom?: number; left?: number };\n /**\n * Draw the gauge's ring as this many equal segments, notched apart — the\n * segmented-gauge look. Applies to a **single-value gauge** only and needs\n * `valueDomain` to know what a full ring means. Anything that isn't one — more\n * than one row, `dataKeys` set, fewer than two segments, or a `dataKey` value\n * that isn't a number (a stringified `\"29\"` off an API) — falls back to the\n * normal concentric arcs, legend included, rather than erroring.\n *\n * The ring is then synthetic geometry rather than data rows, so the arc labels\n * and the legend are suppressed: put the readout in `centerLabel`. The tooltip\n * stays, and reads the metric (with the `valueDomain` maximum when there is\n * one) wherever on the ring it is hovered. `showBackground` is redundant too —\n * the unreached segments *are* the track.\n */\n segments?: number;\n /** Gap between a segmented gauge's segments, in degrees. Defaults to `3`. */\n segmentGap?: number;\n /** Render a muted background track behind each arc. */\n showBackground?: boolean;\n /** Draw the concentric polar grid behind the arcs. */\n showPolarGrid?: boolean;\n /**\n * Custom content for the hole at the center — a headline `value` and/or a\n * `label` caption, stacked and centered. Needs an `innerRadius` big enough to\n * hold the text; it is not clipped to the hole.\n */\n centerLabel?: RadialBarChartCenterLabel;\n showTooltip?: boolean;\n showLegend?: boolean;\n /**\n * Format each arc's value in the list legend. In single-metric mode each arc\n * row gets its formatted value next to its label; in multi-metric mode values\n * are per-row (not per-series) so this is ignored.\n */\n legendValueFormatter?: (value: string | number) => string;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting, per-arc rows, or extra fields without composing\n * recharts yourself. Ignored when `showTooltip` is false.\n *\n * On a segmented gauge it takes over from the built-in reading, and the payload\n * it receives is the ring's synthetic pieces (`seg-2-track`, a length in\n * degrees) rather than data rows — read the metric off `payload[0].payload`.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n /**\n * Position of the value labels when `showLabels` is on. Defaults to\n * `insideStart` — the labels sit inside each arc, and therefore render in the\n * on-fill label token so they stay legible over the arc colour.\n */\n labelPosition?: PolarLabelPosition;\n /**\n * What each data label reads when `showLabels` is on — the value alone (the\n * default), or the arc's name and its value. The name is the row's `nameKey`\n * value, or the metric's `config` label in multi-metric mode.\n */\n labelFormat?: RadialBarChartLabelFormat;\n}\n\nconst RadialBarChart = React.forwardRef<HTMLDivElement, RadialBarChartProps>(\n (\n {\n className,\n config,\n palette,\n data,\n dataKey,\n dataKeys,\n nameKey,\n innerRadius = 20,\n outerRadius = 60,\n startAngle = 90,\n endAngle = -270,\n valueDomain,\n cornerRadius = 4,\n cx,\n cy,\n barSize,\n barGap,\n barCategoryGap,\n minAngle,\n margin,\n segments,\n segmentGap = SEGMENT_GAP,\n showBackground = true,\n showPolarGrid = false,\n centerLabel,\n showTooltip = true,\n showLegend = true,\n legendValueFormatter,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n showLabels = false,\n labelPosition,\n labelFormat = 'value',\n labelFormatter,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n const arcLabelPosition = labelPosition ?? 'insideStart';\n const isMultiMetric = !!dataKeys?.length;\n // A segmented ring is one metric cut into pieces, so it only means anything\n // for a single-row, single-metric chart.\n const isSegmented =\n segments != null &&\n segments > 1 &&\n !isMultiMetric &&\n data.length === 1 &&\n typeof data[0][dataKey] === 'number';\n const seriesKeys = isMultiMetric ? dataKeys! : [dataKey];\n // Stable across renders so the memoized legend content below keeps its\n // identity; `seriesKeys` itself is a fresh array every render.\n const legendKeys = React.useMemo(\n () => (dataKeys?.length ? dataKeys : [dataKey]),\n [dataKeys, dataKey]\n );\n const sweep = Math.abs(endAngle - startAngle);\n const ringSegments = isSegmented\n ? radialBarChartSegments({\n value: data[0][dataKey] as number,\n // Without a domain a lone value is its own maximum, so the ring fills.\n domain: valueDomain ?? [0, data[0][dataKey] as number],\n segments: segments!,\n gap: segmentGap,\n sweep,\n closed: sweep >= 360,\n })\n : [];\n\n // Stamp each row with its `fill` (the shadcn data-driven pattern) so a real\n // hover resolves the arc color in the tooltip — recharts' RadialBar, like\n // Funnel, carries no per-arc color on the tooltip payload item. Only in\n // single-metric mode: with one color per *metric*, a row-level fill would\n // paint every tooltip swatch the same.\n const seriesData: RadialBarChartDatum[] = isMultiMetric\n ? (data as RadialBarChartDatum[])\n : data.map((row) => ({\n ...row,\n fill: `var(--color-${toCssKey(String(row[nameKey]))})`,\n }));\n\n // Each piece of the ring becomes a synthetic series on the one row, measured\n // in degrees — see `radialBarChartSegments`. Built from the raw row, *not*\n // from `seriesData`: a row-level `fill` wins over a series' own `fill` in\n // recharts, which would paint the track and the notches the arc's color.\n const plotData: RadialBarChartDatum[] = isSegmented\n ? [\n {\n ...data[0],\n ...Object.fromEntries(ringSegments.map((s) => [s.key, s.degrees])),\n },\n ]\n : seriesData;\n\n // recharts measures the radial floor in degrees, then extends the arc by\n // `mathSign(deltaAngle || minPointSize)`, where `deltaAngle` is the *arc's*\n // own angular length (RadialBar.js). So for a non-zero arc the floor already\n // grows along the arc's direction whatever sign it carries; the sign only\n // decides which way an arc of exactly zero degrees grows. Carry the sweep's\n // sign so that one grows forwards on a counter-clockwise chart too.\n const minPointSize =\n minAngle === undefined\n ? undefined\n : endAngle < startAngle\n ? -minAngle\n : minAngle;\n\n // Resolve colors so the external list legend has the same values as the chart\n // plot without needing to be inside ChartContainer's context.\n const resolvedConfigForLegend = React.useMemo(\n () => (showLegend ? resolveChartColors(config, palette ?? CHART_DEFAULT_PALETTE) : null),\n [showLegend, config, palette]\n );\n const rightLegendPayload: LegendPayload[] = React.useMemo(() => {\n if (!resolvedConfigForLegend) return [];\n if (isMultiMetric) {\n // Multi-metric: one entry per dataKey. No per-series row value is\n // meaningful (each metric spans multiple rows), so values are omitted.\n return legendKeys.map((key) => ({\n value: key,\n dataKey: key,\n color: resolvedConfigForLegend[key]?.color ?? `var(--color-${toCssKey(key)})`,\n type: 'rect' as const,\n payload: {} as Record<string, unknown>,\n }));\n }\n // Single-metric: one entry per data row.\n return data.map((row) => ({\n value: String(row[nameKey]),\n dataKey: nameKey,\n color:\n resolvedConfigForLegend[String(row[nameKey])]?.color ??\n `var(--color-${toCssKey(String(row[nameKey]))})`,\n type: 'rect' as const,\n payload: row as Record<string, unknown>,\n }));\n }, [resolvedConfigForLegend, isMultiMetric, legendKeys, data, nameKey]);\n\n const hasLegend = showLegend && !isSegmented && !!resolvedConfigForLegend;\n\n // The built-in tooltip reading, which each mapping composes differently: a\n // segmented ring rebuilds it from the data row, multi-metric renames the\n // header after the band, and the default mapping reads the hovered arc.\n const getDefaultTooltipContent = () => {\n if (isSegmented) {\n return (\n <RadialBarChartSegmentedTooltipContent\n config={config}\n row={data[0]}\n nameKey={nameKey}\n dataKey={dataKey}\n domainMax={valueDomain?.[1]}\n />\n );\n }\n\n if (isMultiMetric) {\n return (\n <ChartTooltipContent\n labelFormatter={(_, payload) =>\n radialBarChartBandName(\n payload?.[0]?.payload as RadialBarChartDatum | undefined,\n nameKey\n )\n }\n />\n );\n }\n\n return <ChartTooltipContent nameKey={nameKey} hideLabel />;\n };\n\n // Shared recharts chart composition (used in both layout modes).\n const radialChartContent = (\n <RechartsRadialBarChart\n data={plotData}\n // Only meaningful for the single-metric mapping; in multi-metric and\n // segmented mode each <RadialBar> carries its own key and the scale\n // spans them all.\n dataKey={isMultiMetric || isSegmented ? undefined : dataKey}\n cx={cx}\n cy={cy}\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n startAngle={startAngle}\n endAngle={endAngle}\n barSize={barSize}\n barGap={barGap}\n barCategoryGap={barCategoryGap}\n margin={margin ?? { top: 0, right: 0, bottom: 0, left: 0 }}\n >\n {showPolarGrid && (\n <PolarGrid gridType=\"circle\" radialLines={false} />\n )}\n {(valueDomain || isSegmented) && (\n // The angular scale itself, not chrome: it maps a value onto a\n // fraction of the sweep. Ticks/axis line stay off — the arcs and\n // the optional center readout are the readout. A segmented ring is\n // already measured in degrees, so its scale *is* the sweep.\n <PolarAngleAxis\n type=\"number\"\n domain={isSegmented ? [0, sweep] : valueDomain}\n tick={false}\n axisLine={false}\n />\n )}\n {showTooltip && (\n <ChartTooltip\n // The hover cursor marks which band of the angular axis is\n // active, which on a segmented ring is one metric either way —\n // it just draws a hairline across the gauge.\n cursor={isSegmented ? false : undefined}\n content={tooltipContent ?? getDefaultTooltipContent()}\n />\n )}\n {isSegmented ? (\n <RadialBarChartSegmentedSeries\n ringSegments={ringSegments}\n row={data[0]}\n nameKey={nameKey}\n cornerRadius={cornerRadius}\n animation={animation}\n centerLabel={centerLabel}\n />\n ) : (\n <RadialBarChartSeries\n seriesKeys={seriesKeys}\n seriesData={seriesData}\n isMultiMetric={isMultiMetric}\n config={config}\n nameKey={nameKey}\n showBackground={showBackground}\n cornerRadius={cornerRadius}\n minPointSize={minPointSize}\n animation={animation}\n centerLabel={centerLabel}\n showLabels={showLabels}\n labelPosition={arcLabelPosition}\n labelFormat={labelFormat}\n labelFormatter={labelFormatter}\n />\n )}\n </RechartsRadialBarChart>\n );\n\n const chartDivSize =\n showLabels && (arcLabelPosition === 'outside' || arcLabelPosition === 'end')\n ? 'size-[200px]'\n : 'size-[120px]';\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-row items-center gap-4', !hasLegend && 'justify-center', className)}\n {...props}\n >\n <div className={cn(chartDivSize, 'shrink-0')}>\n <ChartContainer config={config} palette={palette} className=\"size-full\">\n {radialChartContent}\n </ChartContainer>\n </div>\n {showLegend && !isSegmented && resolvedConfigForLegend && (\n <ChartLegendContent\n variant=\"list\"\n payload={rightLegendPayload}\n config={resolvedConfigForLegend}\n nameKey={isMultiMetric ? undefined : nameKey}\n valueKey={isMultiMetric ? undefined : dataKey}\n valueFormatter={isMultiMetric ? undefined : legendValueFormatter}\n className=\"min-w-0 flex-1\"\n />\n )}\n </div>\n );\n }\n);\nRadialBarChart.displayName = 'RadialBarChart';\n\nexport { RadialBarChart };\n"],"mappings":"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"}
1
+ {"version":3,"file":"radial-bar-chart.js","names":[],"sources":["../../../../src/components/ui/radial-bar-chart/radial-bar-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n Cell,\n Label,\n LabelList,\n PolarAngleAxis,\n PolarGrid,\n RadialBar,\n RadialBarChart as RechartsRadialBarChart,\n} from 'recharts';\n\nimport type { LegendPayload } from 'recharts/types/component/DefaultLegendContent';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n resolveChartColors,\n resolveLabelFillClass,\n CHART_DEFAULT_PALETTE,\n CHART_LABEL_FONT_SIZE,\n type ChartConfig,\n type ChartLegendFontSize,\n type ChartPalette,\n type ChartAnimationProps,\n type ChartDataLabelProps,\n type ChartTooltipContentProps,\n type PolarLabelPosition,\n toCssKey,\n type ResolvedAnimation,\n type TickFormatter,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives (a polar/radial\n// type). Rows become concentric arcs sized by `dataKey`, each colored from its\n// `--color-<name>` var; `dataKeys` switches to one arc per metric instead. Like\n// ScatterChart/ComposedChart there's no CVA variant: a radial bar's\n// expressiveness is geometry (angles/radii, plain props) and the data mapping,\n// not a visual \"mode\". The angular sweep is exposed as startAngle/endAngle props\n// so a caller can build a gauge or a full ring.\n\n/** Row-per-arc datum: the `nameKey` label plus each metric's numeric value. */\ntype RadialBarChartDatum = Record<string, string | number>;\n\n/** What an arc's data label reads. */\nexport type RadialBarChartLabelFormat = 'value' | 'name-value';\n\nexport interface RadialBarChartCenterLabel {\n // Rendered as SVG <text>, which only lays out text — hence string | number,\n // not ReactNode.\n /** Headline metric rendered large in the hole (e.g. the gauge's value). */\n value?: string | number;\n /** Caption rendered under the value. */\n label?: string | number;\n}\n\n/**\n * The readout in the hole at the centre of the arcs — a headline value over a\n * caption. Rendered as a recharts `<Label>`, which is what supplies the polar\n * viewBox the text centres itself on.\n *\n * There is one readout for the whole chart, so it hangs off the first series\n * drawn — every series shares the same viewBox.\n */\nfunction RadialBarChartCenterLabelContent({\n centerLabel,\n}: {\n centerLabel: RadialBarChartCenterLabel;\n}) {\n return (\n <Label\n content={({ viewBox }) => {\n if (!viewBox || !('cx' in viewBox)) return null;\n const { cx: centerX = 0, cy: centerY = 0 } = viewBox as {\n cx?: number;\n cy?: number;\n };\n const hasValue = centerLabel.value != null;\n const hasLabel = centerLabel.label != null;\n // Straddle the centre when both lines show, so the value + label block\n // is centered as a whole (not just the value).\n const both = hasValue && hasLabel;\n return (\n <g>\n {hasValue && (\n <text\n x={centerX}\n y={both ? centerY - 10 : centerY}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-foreground text-2xl font-semibold\"\n >\n {centerLabel.value}\n </text>\n )}\n {hasLabel && (\n <text\n x={centerX}\n y={both ? centerY + 13 : centerY}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"fill-muted-foreground text-sm\"\n >\n {centerLabel.label}\n </text>\n )}\n </g>\n );\n }}\n />\n );\n}\n\n/**\n * Compose one arc's data-label text. Exported for unit tests; not part of the\n * package's public API.\n *\n * `labelFormatter` only ever formats the numeric part, so a chart's labels and\n * its tooltip stay in the same units under either format. A nullish value yields\n * an empty label, which recharts renders as no `<text>` at all.\n */\nexport function radialBarChartLabelText(options: {\n format: RadialBarChartLabelFormat;\n name: string | number | undefined;\n value: string | number | undefined;\n formatter?: TickFormatter;\n}): string {\n const { format, name, value, formatter } = options;\n if (value == null) return '';\n const valueText = formatter ? formatter(value) : String(value);\n return format === 'name-value' && name != null\n ? `${name}: ${valueText}`\n : valueText;\n}\n\n/** One piece of a segmented gauge's ring: a length in degrees and what it is. */\nexport interface RadialBarChartSegment {\n /** Synthetic series key — stable for a given (index, kind). */\n key: string;\n /** Angular length of the piece, in degrees. */\n degrees: number;\n /** `value` is the metric, `track` the unreached remainder, `gap` the notch. */\n kind: 'value' | 'track' | 'gap';\n}\n\n/** Fallback gap between a segmented gauge's segments, in degrees. */\nconst SEGMENT_GAP = 3;\n\n/**\n * Cut a gauge's sweep into equal segments separated by gaps, and split the\n * segment the value ends inside into its reached and unreached parts. Exported\n * for unit tests; not part of the package's public API.\n *\n * Lengths come back in **degrees**, which is what lets the ring be built as one\n * stack of synthetic series over a `[0, sweep]` angular scale: recharts lays\n * stacked radial bars out sequentially along the angle, so a transparent series\n * between two colored ones reads as a real notch in the ring. A `gap` that\n * would leave no room for the segments themselves is clamped.\n */\nexport function radialBarChartSegments(options: {\n value: number;\n domain: [number, number];\n segments: number;\n gap: number;\n /** Absolute sweep of the chart, in degrees. */\n sweep: number;\n /** A full-circle sweep also needs a gap between the last segment and the first. */\n closed: boolean;\n}): RadialBarChartSegment[] {\n const { value, domain, segments, sweep, closed } = options;\n const gapCount = closed ? segments : segments - 1;\n // Leave at least half the sweep for the segments, however wide a gap is asked\n // for — an all-gap ring would render as nothing at all. A negative gap would\n // stretch the pieces past the sweep and overlap them, so it floors at zero.\n const gap =\n gapCount > 0\n ? Math.min(Math.max(options.gap, 0), sweep / (2 * gapCount))\n : 0;\n const segmentDegrees = (sweep - gap * gapCount) / segments;\n const [min, max] = domain;\n const span = max - min;\n // A domain with no span (`[n, n]`) or an inverted one (`[max, min]`) cannot\n // place a value on the ring at all, so there is no fraction to draw and the\n // ring stays empty. It deliberately does not fall back to comparing the value\n // against zero: that reported a *full* ring for `{ value: 5, domain: [100,\n // 100] }`, i.e. claimed completion the data never supported. For a gauge,\n // under-reading a domain that says nothing is the safe direction.\n const fraction =\n span > 0 ? Math.min(Math.max((value - min) / span, 0), 1) : 0;\n // The value maps onto the *drawn* ring, so the gaps never eat into it.\n let remainingValue = fraction * segmentDegrees * segments;\n\n const pieces: RadialBarChartSegment[] = [];\n for (let index = 0; index < segments; index++) {\n const reached = Math.min(Math.max(remainingValue, 0), segmentDegrees);\n remainingValue -= reached;\n // Both halves are always emitted, including at zero length: a stable key set\n // keeps recharts' series identities steady as the value changes.\n pieces.push({ key: `seg-${index}-value`, degrees: reached, kind: 'value' });\n pieces.push({\n key: `seg-${index}-track`,\n degrees: segmentDegrees - reached,\n kind: 'track',\n });\n if (gap > 0 && (closed || index < segments - 1)) {\n pieces.push({ key: `seg-${index}-gap`, degrees: gap, kind: 'gap' });\n }\n }\n return pieces;\n}\n\n/**\n * Fill for one piece of a segmented gauge's ring. Exported for unit tests and so\n * the forced-open tooltip story can build a ring from the real implementation\n * rather than a copy of it; not part of the package's public API.\n */\nexport function radialBarChartSegmentFill(\n kind: RadialBarChartSegment['kind'],\n colorName: string | number\n): string {\n if (kind === 'gap') return 'transparent';\n // The unreached remainder plays the part `showBackground`'s track plays on a\n // continuous arc, so it takes the same muted surface.\n return kind === 'track'\n ? 'var(--ui-border-on-status-neutral)'\n : `var(--color-${toCssKey(String(colorName))})`;\n}\n\n/**\n * What a segmented gauge's tooltip reads. Exported for unit tests; not part of\n * the package's public API.\n *\n * A segmented ring's series are pieces of geometry, so recharts would offer the\n * hovered piece's own name and length (\"seg-3-value\", 41.2°). Hovering anywhere\n * on the ring should read the metric instead, so the reading is rebuilt from the\n * data row.\n */\nexport function radialBarChartSegmentedReading(options: {\n config: ChartConfig;\n row: RadialBarChartDatum;\n nameKey: string;\n dataKey: string;\n /** The `valueDomain` maximum, when the gauge has one. */\n domainMax?: number;\n}): { colorName: string; label: React.ReactNode; valueText: string } {\n const { config, row, nameKey, dataKey, domainMax } = options;\n const colorName = String(row[nameKey]);\n const value = row[dataKey];\n const valueText =\n typeof value === 'number' ? value.toLocaleString() : String(value ?? '');\n return {\n colorName,\n label: config[colorName]?.label ?? colorName,\n // The gauge's scale is the other half of the reading, so a known maximum\n // comes along: \"29 / 38\", not a bare \"29\".\n valueText:\n domainMax == null\n ? valueText\n : `${valueText} / ${domainMax.toLocaleString()}`,\n };\n}\n\n/**\n * The tooltip a segmented gauge shows — the same swatch/name/value layout the\n * default `ChartTooltipContent` row uses, dot included, over the reading from\n * `radialBarChartSegmentedReading`. Exported for the forced-open\n * visual-regression story; not part of the package's public API.\n *\n * `payload` is trimmed to one row: a radial tooltip is axis-shared and collects a\n * row from every series — two dozen identical rows for one metric.\n * (`tooltipType=\"none\"` only tags them, and scoping the tooltip to the hovered\n * item instead would drop it in the corner — unlike Pie/Bar sectors, a RadialBar\n * sector carries no tooltip coordinate.)\n *\n * A real component rather than a closure so it can be handed to `ChartTooltip`\n * as an *element*: recharts `cloneElement`s an element but `createElement`s a\n * function, and a closure rebuilt each render is a new element *type* — which\n * remounts the tooltip on every parent render instead of updating it.\n */\nexport function RadialBarChartSegmentedTooltipContent({\n active,\n payload,\n ...reading\n}: {\n active?: boolean;\n // Loosely typed on purpose: recharts' own payload generics are wider than the\n // shared `ChartTooltipContentProps` accepts, and only the row count matters.\n payload?: readonly unknown[];\n config: ChartConfig;\n row: RadialBarChartDatum;\n nameKey: string;\n dataKey: string;\n domainMax?: number;\n}) {\n const { colorName, label, valueText } =\n radialBarChartSegmentedReading(reading);\n\n return (\n <ChartTooltipContent\n active={active}\n payload={payload?.slice(0, 1) as ChartTooltipContentProps['payload']}\n hideLabel\n formatter={() => (\n <>\n <div\n className=\"h-2.5 w-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: `var(--color-${toCssKey(colorName)})` }}\n />\n <div className=\"flex flex-1 items-center justify-between gap-2 leading-none\">\n <span className=\"text-muted-foreground\">{label}</span>\n <span className=\"font-medium tabular-nums text-foreground\">\n {valueText}\n </span>\n </div>\n </>\n )}\n />\n );\n}\n\n/**\n * The band a multi-metric tooltip's header names. Exported for unit tests; not\n * part of the package's public API.\n *\n * Each tooltip row is one metric, so the header names the band the hovered arc\n * belongs to. recharts' own label is the radius-axis index, which reads as a\n * bare number.\n */\nexport function radialBarChartBandName(\n row: RadialBarChartDatum | undefined,\n nameKey: string\n): string {\n const name = row?.[nameKey];\n return name == null ? '' : String(name);\n}\n\n/**\n * What an arc's data label calls the arc: the row's own `nameKey` value, or — in\n * multi-metric mode, where one arc *is* one metric — that metric's `config` label.\n */\nfunction radialBarChartArcName(options: {\n key: string;\n row: RadialBarChartDatum | undefined;\n isMultiMetric: boolean;\n nameKey: string;\n config: ChartConfig;\n}): string | number | undefined {\n const { key, row, isMultiMetric, nameKey, config } = options;\n if (!isMultiMetric) return row?.[nameKey];\n // ChartConfig labels are ReactNode; only a plain string/number can go into an\n // SVG <text>.\n const label = config[key]?.label;\n return typeof label === 'string' || typeof label === 'number' ? label : key;\n}\n\n/**\n * The default mapping's arcs: one `RadialBar` per series — one for the single\n * `dataKey`, or one per `dataKeys` entry in multi-metric mode — drawn\n * concentrically.\n *\n * recharts collects its graphical items from the store (each `RadialBar`\n * registers itself on render) rather than by scanning the chart's children for\n * their types, so grouping them inside a component of our own is invisible to it.\n * The `Cell`s stay direct children of their `RadialBar`, which *does* read its own\n * children by type.\n */\nfunction RadialBarChartSeries({\n seriesKeys,\n seriesData,\n isMultiMetric,\n config,\n nameKey,\n showBackground,\n cornerRadius,\n minPointSize,\n animation,\n centerLabel,\n showLabels,\n labelPosition,\n labelFormat,\n labelFormatter,\n}: {\n seriesKeys: string[];\n seriesData: RadialBarChartDatum[];\n isMultiMetric: boolean;\n config: ChartConfig;\n nameKey: string;\n showBackground: boolean;\n cornerRadius: number;\n minPointSize: number | undefined;\n animation: ResolvedAnimation;\n centerLabel: RadialBarChartCenterLabel | undefined;\n showLabels: boolean;\n labelPosition: PolarLabelPosition;\n labelFormat: RadialBarChartLabelFormat;\n labelFormatter?: TickFormatter;\n}) {\n return seriesKeys.map((key, seriesIndex) => (\n <RadialBar\n key={key}\n dataKey={key}\n fill={isMultiMetric ? `var(--color-${toCssKey(key)})` : undefined}\n background={showBackground ? { fill: 'var(--ui-border-on-status-neutral)' } : false}\n cornerRadius={cornerRadius}\n minPointSize={minPointSize}\n {...animation}\n >\n {!isMultiMetric &&\n seriesData.map((entry, index) => (\n // Keyed by index, not the name: two arcs could share a nameKey\n // value, which would collide as a React key. Same-named arcs\n // intentionally share a color/config entry via `--color-<name>`.\n <Cell key={index} fill={`var(--color-${toCssKey(String(entry[nameKey]))})`} />\n ))}\n {seriesIndex === 0 && centerLabel && (\n <RadialBarChartCenterLabelContent centerLabel={centerLabel} />\n )}\n {showLabels && (\n <LabelList\n // `valueAccessor` rather than `dataKey`: the label text can\n // carry the arc's name, which only the whole row (single\n // metric) or the metric's config entry can supply. recharts\n // ignores the accessor when a dataKey is set, so the two\n // can't be combined.\n valueAccessor={(entry) =>\n radialBarChartLabelText({\n format: labelFormat,\n name: radialBarChartArcName({\n key,\n row: entry.payload as RadialBarChartDatum | undefined,\n isMultiMetric,\n nameKey,\n config,\n }),\n value: entry.value as string | number | undefined,\n formatter: labelFormatter,\n })\n }\n position={labelPosition}\n className={resolveLabelFillClass(labelPosition)}\n fontSize={CHART_LABEL_FONT_SIZE}\n />\n )}\n </RadialBar>\n ));\n}\n\n/**\n * A segmented gauge's ring: the pieces from `radialBarChartSegments` as one stack\n * of synthetic series, so they lay out sequentially around the ring instead of\n * concentrically and the `gap` pieces read as notches.\n */\nfunction RadialBarChartSegmentedSeries({\n ringSegments,\n row,\n nameKey,\n cornerRadius,\n animation,\n centerLabel,\n}: {\n ringSegments: RadialBarChartSegment[];\n row: RadialBarChartDatum;\n nameKey: string;\n cornerRadius: number;\n animation: ResolvedAnimation;\n centerLabel: RadialBarChartCenterLabel | undefined;\n}) {\n return ringSegments.map((segment, index) => (\n <RadialBar\n key={segment.key}\n dataKey={segment.key}\n stackId=\"segments\"\n // The metric's name, so the hover has a row to key off at all\n // (`ChartTooltipContent` keys its row off `name`).\n name={String(row[nameKey])}\n fill={radialBarChartSegmentFill(segment.kind, row[nameKey])}\n cornerRadius={cornerRadius}\n {...animation}\n >\n {index === 0 && centerLabel && (\n <RadialBarChartCenterLabelContent centerLabel={centerLabel} />\n )}\n </RadialBar>\n ));\n}\n\nexport interface RadialBarChartProps\n extends\n Omit<React.ComponentProps<'div'>, 'children'>,\n ChartAnimationProps,\n ChartDataLabelProps {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /** Row-per-arc data. Each object holds the arc's `nameKey` label + its `dataKey` numeric value. */\n data: ReadonlyArray<RadialBarChartDatum>;\n /**\n * Per-arc map of `label` / `icon` / `tone`, keyed by the arc's `nameKey` value\n * — or, in multi-metric mode, by each `dataKeys` entry (imported from the\n * shared `Chart` primitives). Turned into `--color-<name>` custom properties.\n * Series take their colour from the container's `palette`; each entry maps a\n * key to a `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Numeric field that sizes each arc. Ignored when `dataKeys` is set. */\n dataKey: string;\n /**\n * Plot several metrics instead of one arc per row: one arc per key, colored and\n * named from `config` keyed by the **key** (not by `nameKey`) — the same\n * convention as the cartesian charts. Every metric shares one angular scale, so\n * pair it with `valueDomain` when the metrics are measured against a known\n * maximum. `nameKey` still names the band each metric's arc sits in.\n */\n dataKeys?: string[];\n /**\n * Label field that names each arc (drives the legend, tooltip, and\n * `--color-<name>` lookup). Values should be unique per chart (arcs sharing a\n * name share one `config`/color entry); they are sanitized automatically to a\n * valid CSS custom-property fragment (CSS-safe values are preferred to avoid\n * dev-mode warnings). In multi-metric mode it names the band rather than the\n * arc, so the legend and colors come from `dataKeys` instead.\n */\n nameKey: string;\n /** Inner radius of the innermost arc. */\n innerRadius?: number;\n /** Outer radius of the outermost arc. */\n outerRadius?: number;\n /** Angle (degrees) the arcs sweep from. */\n startAngle?: number;\n /** Angle (degrees) the arcs sweep to (default is a full clockwise circle). */\n endAngle?: number;\n /**\n * The value range the sweep represents, as `[min, max]`. Without it every arc\n * is drawn relative to the largest value in the data — so a **single** value\n * always fills the whole sweep, which is never what a gauge means. Set it to\n * the metric's own scale (e.g. `[0, 100]` for a percentage) and each arc\n * becomes that fraction of the sweep, over the `showBackground` track.\n */\n valueDomain?: [number, number];\n /** Corner radius on each arc's ends. */\n cornerRadius?: number;\n /**\n * Horizontal center of the arcs, in px or a percentage of the width.\n * Defaults to the middle (`50%`).\n */\n cx?: number | string;\n /**\n * Vertical center of the arcs, in px or a percentage of the height. Defaults to\n * the middle (`50%`) — worth moving for a half-circle gauge, whose drawn half\n * otherwise sits in the upper half of the surface.\n */\n cy?: number | string;\n /** Thickness of each arc, in px. Omit to let the radii and the gaps size it. */\n barSize?: number;\n /** Gap between the arcs of different metrics in one band, in px. */\n barGap?: number | string;\n /** Gap between bands, in px or a percentage string. */\n barCategoryGap?: number | string;\n /**\n * Smallest angle a non-zero arc may occupy, in degrees, so a tiny value stays\n * visible (and hoverable). recharts applies the floor to a `0` as well, which\n * reads as a small positive value — leave this unset when a metric can\n * legitimately be zero.\n */\n minAngle?: number;\n /** Plot-area margin, in px. Omit to use recharts' default (5 on every side). */\n margin?: { top?: number; right?: number; bottom?: number; left?: number };\n /**\n * Draw the gauge's ring as this many equal segments, notched apart — the\n * segmented-gauge look. Applies to a **single-value gauge** only and needs\n * `valueDomain` to know what a full ring means. Anything that isn't one — more\n * than one row, `dataKeys` set, fewer than two segments, or a `dataKey` value\n * that isn't a number (a stringified `\"29\"` off an API) — falls back to the\n * normal concentric arcs, legend included, rather than erroring.\n *\n * The ring is then synthetic geometry rather than data rows, so the arc labels\n * and the legend are suppressed: put the readout in `centerLabel`. The tooltip\n * stays, and reads the metric (with the `valueDomain` maximum when there is\n * one) wherever on the ring it is hovered. `showBackground` is redundant too —\n * the unreached segments *are* the track.\n */\n segments?: number;\n /** Gap between a segmented gauge's segments, in degrees. Defaults to `3`. */\n segmentGap?: number;\n /** Render a muted background track behind each arc. */\n showBackground?: boolean;\n /** Draw the concentric polar grid behind the arcs. */\n showPolarGrid?: boolean;\n /**\n * Custom content for the hole at the center — a headline `value` and/or a\n * `label` caption, stacked and centered. Needs an `innerRadius` big enough to\n * hold the text; it is not clipped to the hole.\n */\n centerLabel?: RadialBarChartCenterLabel;\n showTooltip?: boolean;\n showLegend?: boolean;\n /**\n * Font size of the legend text (labels and values). Defaults to `'xs'` —\n * the size the legend has always rendered at. See `ChartLegendFontSize`.\n */\n legendFontSize?: ChartLegendFontSize;\n /**\n * Format each arc's value in the list legend. In single-metric mode each arc\n * row gets its formatted value next to its label; in multi-metric mode values\n * are per-row (not per-series) so this is ignored.\n */\n legendValueFormatter?: (value: string | number) => string;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting, per-arc rows, or extra fields without composing\n * recharts yourself. Ignored when `showTooltip` is false.\n *\n * On a segmented gauge it takes over from the built-in reading, and the payload\n * it receives is the ring's synthetic pieces (`seg-2-track`, a length in\n * degrees) rather than data rows — read the metric off `payload[0].payload`.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n /**\n * Position of the value labels when `showLabels` is on. Defaults to\n * `insideStart` — the labels sit inside each arc, and therefore render in the\n * on-fill label token so they stay legible over the arc colour.\n */\n labelPosition?: PolarLabelPosition;\n /**\n * What each data label reads when `showLabels` is on — the value alone (the\n * default), or the arc's name and its value. The name is the row's `nameKey`\n * value, or the metric's `config` label in multi-metric mode.\n */\n labelFormat?: RadialBarChartLabelFormat;\n}\n\nconst RadialBarChart = React.forwardRef<HTMLDivElement, RadialBarChartProps>(\n (\n {\n className,\n config,\n palette,\n data,\n dataKey,\n dataKeys,\n nameKey,\n innerRadius = 20,\n outerRadius = 60,\n startAngle = 90,\n endAngle = -270,\n valueDomain,\n cornerRadius = 4,\n cx,\n cy,\n barSize,\n barGap,\n barCategoryGap,\n minAngle,\n margin,\n segments,\n segmentGap = SEGMENT_GAP,\n showBackground = true,\n showPolarGrid = false,\n centerLabel,\n showTooltip = true,\n showLegend = true,\n legendFontSize,\n legendValueFormatter,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n showLabels = false,\n labelPosition,\n labelFormat = 'value',\n labelFormatter,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n const arcLabelPosition = labelPosition ?? 'insideStart';\n const isMultiMetric = !!dataKeys?.length;\n // A segmented ring is one metric cut into pieces, so it only means anything\n // for a single-row, single-metric chart.\n const isSegmented =\n segments != null &&\n segments > 1 &&\n !isMultiMetric &&\n data.length === 1 &&\n typeof data[0][dataKey] === 'number';\n const seriesKeys = isMultiMetric ? dataKeys! : [dataKey];\n // Stable across renders so the memoized legend content below keeps its\n // identity; `seriesKeys` itself is a fresh array every render.\n const legendKeys = React.useMemo(\n () => (dataKeys?.length ? dataKeys : [dataKey]),\n [dataKeys, dataKey]\n );\n const sweep = Math.abs(endAngle - startAngle);\n const ringSegments = isSegmented\n ? radialBarChartSegments({\n value: data[0][dataKey] as number,\n // Without a domain a lone value is its own maximum, so the ring fills.\n domain: valueDomain ?? [0, data[0][dataKey] as number],\n segments: segments!,\n gap: segmentGap,\n sweep,\n closed: sweep >= 360,\n })\n : [];\n\n // Stamp each row with its `fill` (the shadcn data-driven pattern) so a real\n // hover resolves the arc color in the tooltip — recharts' RadialBar, like\n // Funnel, carries no per-arc color on the tooltip payload item. Only in\n // single-metric mode: with one color per *metric*, a row-level fill would\n // paint every tooltip swatch the same.\n const seriesData: RadialBarChartDatum[] = isMultiMetric\n ? (data as RadialBarChartDatum[])\n : data.map((row) => ({\n ...row,\n fill: `var(--color-${toCssKey(String(row[nameKey]))})`,\n }));\n\n // Each piece of the ring becomes a synthetic series on the one row, measured\n // in degrees — see `radialBarChartSegments`. Built from the raw row, *not*\n // from `seriesData`: a row-level `fill` wins over a series' own `fill` in\n // recharts, which would paint the track and the notches the arc's color.\n const plotData: RadialBarChartDatum[] = isSegmented\n ? [\n {\n ...data[0],\n ...Object.fromEntries(ringSegments.map((s) => [s.key, s.degrees])),\n },\n ]\n : seriesData;\n\n // recharts measures the radial floor in degrees, then extends the arc by\n // `mathSign(deltaAngle || minPointSize)`, where `deltaAngle` is the *arc's*\n // own angular length (RadialBar.js). So for a non-zero arc the floor already\n // grows along the arc's direction whatever sign it carries; the sign only\n // decides which way an arc of exactly zero degrees grows. Carry the sweep's\n // sign so that one grows forwards on a counter-clockwise chart too.\n const minPointSize =\n minAngle === undefined\n ? undefined\n : endAngle < startAngle\n ? -minAngle\n : minAngle;\n\n // Resolve colors so the external list legend has the same values as the chart\n // plot without needing to be inside ChartContainer's context.\n const resolvedConfigForLegend = React.useMemo(\n () => (showLegend ? resolveChartColors(config, palette ?? CHART_DEFAULT_PALETTE) : null),\n [showLegend, config, palette]\n );\n const rightLegendPayload: LegendPayload[] = React.useMemo(() => {\n if (!resolvedConfigForLegend) return [];\n if (isMultiMetric) {\n // Multi-metric: one entry per dataKey. No per-series row value is\n // meaningful (each metric spans multiple rows), so values are omitted.\n return legendKeys.map((key) => ({\n value: key,\n dataKey: key,\n color: resolvedConfigForLegend[key]?.color ?? `var(--color-${toCssKey(key)})`,\n type: 'rect' as const,\n payload: {} as Record<string, unknown>,\n }));\n }\n // Single-metric: one entry per data row.\n return data.map((row) => ({\n value: String(row[nameKey]),\n dataKey: nameKey,\n color:\n resolvedConfigForLegend[String(row[nameKey])]?.color ??\n `var(--color-${toCssKey(String(row[nameKey]))})`,\n type: 'rect' as const,\n payload: row as Record<string, unknown>,\n }));\n }, [resolvedConfigForLegend, isMultiMetric, legendKeys, data, nameKey]);\n\n const hasLegend = showLegend && !isSegmented && !!resolvedConfigForLegend;\n\n // The built-in tooltip reading, which each mapping composes differently: a\n // segmented ring rebuilds it from the data row, multi-metric renames the\n // header after the band, and the default mapping reads the hovered arc.\n const getDefaultTooltipContent = () => {\n if (isSegmented) {\n return (\n <RadialBarChartSegmentedTooltipContent\n config={config}\n row={data[0]}\n nameKey={nameKey}\n dataKey={dataKey}\n domainMax={valueDomain?.[1]}\n />\n );\n }\n\n if (isMultiMetric) {\n return (\n <ChartTooltipContent\n labelFormatter={(_, payload) =>\n radialBarChartBandName(\n payload?.[0]?.payload as RadialBarChartDatum | undefined,\n nameKey\n )\n }\n />\n );\n }\n\n return <ChartTooltipContent nameKey={nameKey} hideLabel />;\n };\n\n // Shared recharts chart composition (used in both layout modes).\n const radialChartContent = (\n <RechartsRadialBarChart\n data={plotData}\n // Only meaningful for the single-metric mapping; in multi-metric and\n // segmented mode each <RadialBar> carries its own key and the scale\n // spans them all.\n dataKey={isMultiMetric || isSegmented ? undefined : dataKey}\n cx={cx}\n cy={cy}\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n startAngle={startAngle}\n endAngle={endAngle}\n barSize={barSize}\n barGap={barGap}\n barCategoryGap={barCategoryGap}\n margin={margin ?? { top: 0, right: 0, bottom: 0, left: 0 }}\n >\n {showPolarGrid && (\n <PolarGrid gridType=\"circle\" radialLines={false} />\n )}\n {(valueDomain || isSegmented) && (\n // The angular scale itself, not chrome: it maps a value onto a\n // fraction of the sweep. Ticks/axis line stay off — the arcs and\n // the optional center readout are the readout. A segmented ring is\n // already measured in degrees, so its scale *is* the sweep.\n <PolarAngleAxis\n type=\"number\"\n domain={isSegmented ? [0, sweep] : valueDomain}\n tick={false}\n axisLine={false}\n />\n )}\n {showTooltip && (\n <ChartTooltip\n // The hover cursor marks which band of the angular axis is\n // active, which on a segmented ring is one metric either way —\n // it just draws a hairline across the gauge.\n cursor={isSegmented ? false : undefined}\n content={tooltipContent ?? getDefaultTooltipContent()}\n />\n )}\n {isSegmented ? (\n <RadialBarChartSegmentedSeries\n ringSegments={ringSegments}\n row={data[0]}\n nameKey={nameKey}\n cornerRadius={cornerRadius}\n animation={animation}\n centerLabel={centerLabel}\n />\n ) : (\n <RadialBarChartSeries\n seriesKeys={seriesKeys}\n seriesData={seriesData}\n isMultiMetric={isMultiMetric}\n config={config}\n nameKey={nameKey}\n showBackground={showBackground}\n cornerRadius={cornerRadius}\n minPointSize={minPointSize}\n animation={animation}\n centerLabel={centerLabel}\n showLabels={showLabels}\n labelPosition={arcLabelPosition}\n labelFormat={labelFormat}\n labelFormatter={labelFormatter}\n />\n )}\n </RechartsRadialBarChart>\n );\n\n const chartDivSize =\n showLabels && (arcLabelPosition === 'outside' || arcLabelPosition === 'end')\n ? 'size-[200px]'\n : 'size-[120px]';\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-row items-center gap-4', !hasLegend && 'justify-center', className)}\n {...props}\n >\n <div className={cn(chartDivSize, 'shrink-0')}>\n <ChartContainer config={config} palette={palette} className=\"size-full\">\n {radialChartContent}\n </ChartContainer>\n </div>\n {showLegend && !isSegmented && resolvedConfigForLegend && (\n <ChartLegendContent\n variant=\"list\"\n payload={rightLegendPayload}\n config={resolvedConfigForLegend}\n nameKey={isMultiMetric ? undefined : nameKey}\n fontSize={legendFontSize}\n valueKey={isMultiMetric ? undefined : dataKey}\n valueFormatter={isMultiMetric ? undefined : legendValueFormatter}\n className=\"min-w-0 flex-1\"\n />\n )}\n </div>\n );\n }\n);\nRadialBarChart.displayName = 'RadialBarChart';\n\nexport { RadialBarChart };\n"],"mappings":"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"}