@acronis-platform/ui-react 5.2.0 → 5.3.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.
- package/dist/components/ui/area-chart/area-chart.js +107 -107
- package/dist/components/ui/area-chart/area-chart.js.map +1 -1
- package/dist/components/ui/bar-chart/bar-chart.js +162 -162
- package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
- package/dist/components/ui/category-bar/category-bar.js +50 -50
- package/dist/components/ui/category-bar/category-bar.js.map +1 -1
- package/dist/components/ui/chart/chart.js +53 -40
- package/dist/components/ui/chart/chart.js.map +1 -1
- package/dist/components/ui/composed-chart/composed-chart.js +146 -146
- package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
- package/dist/components/ui/confidence-cone/confidence-cone.js +97 -97
- package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
- package/dist/components/ui/funnel-chart/funnel-chart.js +120 -120
- package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
- package/dist/components/ui/histogram/histogram.js +58 -58
- package/dist/components/ui/histogram/histogram.js.map +1 -1
- package/dist/components/ui/line-chart/line-chart.js +91 -91
- package/dist/components/ui/line-chart/line-chart.js.map +1 -1
- package/dist/components/ui/pie-chart/pie-chart.js +92 -92
- package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
- package/dist/components/ui/radar-chart/radar-chart.js +37 -37
- package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +112 -112
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
- package/dist/components/ui/sankey-chart/sankey-chart.js +78 -78
- package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
- package/dist/components/ui/scatter-chart/scatter-chart.js +57 -57
- package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
- package/dist/components/ui/treemap/treemap.js +87 -87
- package/dist/components/ui/treemap/treemap.js.map +1 -1
- package/dist/index.js +111 -111
- package/dist/llms.txt +1 -1
- package/dist/react.js +111 -111
- package/dist/src/components/ui/chart/chart.d.ts +1 -0
- package/dist/src/components/ui/chart/index.d.ts +1 -1
- package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +3 -2
- package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +1 -1
- package/dist/src/components/ui/treemap/treemap.d.ts +3 -2
- 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 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-${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 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,24 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../../../lib/utils.js";
|
|
3
3
|
import { CHART_DEFAULT_PALETTE as t } from "../chart/chart-palette.js";
|
|
4
|
-
import { ChartContainer as n, ChartLegendContent as r, ChartTooltip as i, ChartTooltipContent as a, resolveChartColors as o } from "../chart/chart.js";
|
|
5
|
-
import { resolveAnimation as
|
|
6
|
-
import * as
|
|
7
|
-
import { Fragment as
|
|
8
|
-
import { Cell as
|
|
4
|
+
import { ChartContainer as n, ChartLegendContent as r, ChartTooltip as i, ChartTooltipContent as a, resolveChartColors as o, toCssKey as s } from "../chart/chart.js";
|
|
5
|
+
import { resolveAnimation as c, resolveLabelFillClass as l } from "../chart/chart-format.js";
|
|
6
|
+
import * as u from "react";
|
|
7
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
8
|
+
import { Cell as m, Label as h, LabelList as g, PolarAngleAxis as _, PolarGrid as v, RadialBar as y, RadialBarChart as b } from "recharts";
|
|
9
9
|
//#region src/components/ui/radial-bar-chart/radial-bar-chart.tsx
|
|
10
|
-
function
|
|
11
|
-
return /* @__PURE__ */
|
|
10
|
+
function x({ centerLabel: e }) {
|
|
11
|
+
return /* @__PURE__ */ f(h, { content: ({ viewBox: t }) => {
|
|
12
12
|
if (!t || !("cx" in t)) return null;
|
|
13
13
|
let { cx: n = 0, cy: r = 0 } = t, i = e.value != null, a = e.label != null, o = i && a;
|
|
14
|
-
return /* @__PURE__ */
|
|
14
|
+
return /* @__PURE__ */ p("g", { children: [i && /* @__PURE__ */ f("text", {
|
|
15
15
|
x: n,
|
|
16
16
|
y: o ? r - 10 : r,
|
|
17
17
|
textAnchor: "middle",
|
|
18
18
|
dominantBaseline: "central",
|
|
19
19
|
className: "fill-foreground text-2xl font-semibold",
|
|
20
20
|
children: e.value
|
|
21
|
-
}), a && /* @__PURE__ */
|
|
21
|
+
}), a && /* @__PURE__ */ f("text", {
|
|
22
22
|
x: n,
|
|
23
23
|
y: o ? r + 13 : r,
|
|
24
24
|
textAnchor: "middle",
|
|
@@ -28,14 +28,14 @@ function b({ centerLabel: e }) {
|
|
|
28
28
|
})] });
|
|
29
29
|
} });
|
|
30
30
|
}
|
|
31
|
-
function
|
|
31
|
+
function S(e) {
|
|
32
32
|
let { format: t, name: n, value: r, formatter: i } = e;
|
|
33
33
|
if (r == null) return "";
|
|
34
34
|
let a = i ? i(r) : String(r);
|
|
35
35
|
return t === "name-value" && n != null ? `${n}: ${a}` : a;
|
|
36
36
|
}
|
|
37
|
-
var
|
|
38
|
-
function
|
|
37
|
+
var C = 3;
|
|
38
|
+
function w(e) {
|
|
39
39
|
let { value: t, domain: n, segments: r, sweep: i, closed: a } = e, o = a ? r : r - 1, s = o > 0 ? Math.min(Math.max(e.gap, 0), i / (2 * o)) : 0, c = (i - s * o) / r, [l, u] = n, d = u - l, f = (d > 0 ? Math.min(Math.max((t - l) / d, 0), 1) : 0) * c * r, p = [];
|
|
40
40
|
for (let e = 0; e < r; e++) {
|
|
41
41
|
let t = Math.min(Math.max(f, 0), c);
|
|
@@ -55,10 +55,10 @@ function C(e) {
|
|
|
55
55
|
}
|
|
56
56
|
return p;
|
|
57
57
|
}
|
|
58
|
-
function
|
|
59
|
-
return e === "gap" ? "transparent" : e === "track" ? "var(--ui-border-on-status-neutral)" : `var(--color-${t})`;
|
|
58
|
+
function T(e, t) {
|
|
59
|
+
return e === "gap" ? "transparent" : e === "track" ? "var(--ui-border-on-status-neutral)" : `var(--color-${s(String(t))})`;
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function E(e) {
|
|
62
62
|
let { config: t, row: n, nameKey: r, dataKey: i, domainMax: a } = e, o = String(n[r]), s = n[i], c = typeof s == "number" ? s.toLocaleString() : String(s ?? "");
|
|
63
63
|
return {
|
|
64
64
|
colorName: o,
|
|
@@ -66,52 +66,52 @@ function T(e) {
|
|
|
66
66
|
valueText: a == null ? c : `${c} / ${a.toLocaleString()}`
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
function
|
|
70
|
-
let { colorName: r, label: i, valueText: o } =
|
|
71
|
-
return /* @__PURE__ */
|
|
69
|
+
function D({ active: e, payload: t, ...n }) {
|
|
70
|
+
let { colorName: r, label: i, valueText: o } = E(n);
|
|
71
|
+
return /* @__PURE__ */ f(a, {
|
|
72
72
|
active: e,
|
|
73
73
|
payload: t?.slice(0, 1),
|
|
74
74
|
hideLabel: !0,
|
|
75
|
-
formatter: () => /* @__PURE__ */
|
|
75
|
+
formatter: () => /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f("div", {
|
|
76
76
|
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
77
|
-
style: { backgroundColor: `var(--color-${r})` }
|
|
78
|
-
}), /* @__PURE__ */
|
|
77
|
+
style: { backgroundColor: `var(--color-${s(r)})` }
|
|
78
|
+
}), /* @__PURE__ */ p("div", {
|
|
79
79
|
className: "flex flex-1 items-center justify-between gap-2 leading-none",
|
|
80
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ f("span", {
|
|
81
81
|
className: "text-muted-foreground",
|
|
82
82
|
children: i
|
|
83
|
-
}), /* @__PURE__ */
|
|
83
|
+
}), /* @__PURE__ */ f("span", {
|
|
84
84
|
className: "font-medium tabular-nums text-foreground",
|
|
85
85
|
children: o
|
|
86
86
|
})]
|
|
87
87
|
})] })
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
|
-
function
|
|
90
|
+
function O(e, t) {
|
|
91
91
|
let n = e?.[t];
|
|
92
92
|
return n == null ? "" : String(n);
|
|
93
93
|
}
|
|
94
|
-
function
|
|
94
|
+
function k(e) {
|
|
95
95
|
let { key: t, row: n, isMultiMetric: r, nameKey: i, config: a } = e;
|
|
96
96
|
if (!r) return n?.[i];
|
|
97
97
|
let o = a[t]?.label;
|
|
98
98
|
return typeof o == "string" || typeof o == "number" ? o : t;
|
|
99
99
|
}
|
|
100
|
-
function ee({ seriesKeys: e, seriesData: t, isMultiMetric: n, config: r, nameKey: i, showBackground: a, cornerRadius: o, minPointSize:
|
|
101
|
-
return e.map((e,
|
|
100
|
+
function ee({ seriesKeys: e, seriesData: t, isMultiMetric: n, config: r, nameKey: i, showBackground: a, cornerRadius: o, minPointSize: c, animation: u, centerLabel: d, showLabels: h, labelPosition: _, labelFormat: v, labelFormatter: b }) {
|
|
101
|
+
return e.map((e, C) => /* @__PURE__ */ p(y, {
|
|
102
102
|
dataKey: e,
|
|
103
|
-
fill: n ? `var(--color-${e})` : void 0,
|
|
103
|
+
fill: n ? `var(--color-${s(e)})` : void 0,
|
|
104
104
|
background: a ? { fill: "var(--ui-border-on-status-neutral)" } : !1,
|
|
105
105
|
cornerRadius: o,
|
|
106
|
-
minPointSize:
|
|
107
|
-
...
|
|
106
|
+
minPointSize: c,
|
|
107
|
+
...u,
|
|
108
108
|
children: [
|
|
109
|
-
!n && t.map((e, t) => /* @__PURE__ */
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
valueAccessor: (t) =>
|
|
113
|
-
format:
|
|
114
|
-
name:
|
|
109
|
+
!n && t.map((e, t) => /* @__PURE__ */ f(m, { fill: `var(--color-${s(String(e[i]))})` }, t)),
|
|
110
|
+
C === 0 && d && /* @__PURE__ */ f(x, { centerLabel: d }),
|
|
111
|
+
h && /* @__PURE__ */ f(g, {
|
|
112
|
+
valueAccessor: (t) => S({
|
|
113
|
+
format: v,
|
|
114
|
+
name: k({
|
|
115
115
|
key: e,
|
|
116
116
|
row: t.payload,
|
|
117
117
|
isMultiMetric: n,
|
|
@@ -119,159 +119,159 @@ function ee({ seriesKeys: e, seriesData: t, isMultiMetric: n, config: r, nameKey
|
|
|
119
119
|
config: r
|
|
120
120
|
}),
|
|
121
121
|
value: t.value,
|
|
122
|
-
formatter:
|
|
122
|
+
formatter: b
|
|
123
123
|
}),
|
|
124
|
-
position:
|
|
125
|
-
className:
|
|
124
|
+
position: _,
|
|
125
|
+
className: l(_),
|
|
126
126
|
fontSize: 12
|
|
127
127
|
})
|
|
128
128
|
]
|
|
129
129
|
}, e));
|
|
130
130
|
}
|
|
131
131
|
function te({ ringSegments: e, row: t, nameKey: n, cornerRadius: r, animation: i, centerLabel: a }) {
|
|
132
|
-
return e.map((e, o) => /* @__PURE__ */
|
|
132
|
+
return e.map((e, o) => /* @__PURE__ */ f(y, {
|
|
133
133
|
dataKey: e.key,
|
|
134
134
|
stackId: "segments",
|
|
135
135
|
name: String(t[n]),
|
|
136
|
-
fill:
|
|
136
|
+
fill: T(e.kind, t[n]),
|
|
137
137
|
cornerRadius: r,
|
|
138
138
|
...i,
|
|
139
|
-
children: o === 0 && a && /* @__PURE__ */
|
|
139
|
+
children: o === 0 && a && /* @__PURE__ */ f(x, { centerLabel: a })
|
|
140
140
|
}, e.key));
|
|
141
141
|
}
|
|
142
|
-
var
|
|
143
|
-
let W =
|
|
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
144
|
animate: z,
|
|
145
145
|
animationDuration: B,
|
|
146
146
|
animationBegin: V,
|
|
147
147
|
animationEasing: H
|
|
148
|
-
}), G =
|
|
149
|
-
value:
|
|
150
|
-
domain:
|
|
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({
|
|
149
|
+
value: h[0][g],
|
|
150
|
+
domain: A ?? [0, h[0][g]],
|
|
151
151
|
segments: P,
|
|
152
|
-
gap:
|
|
152
|
+
gap: se,
|
|
153
153
|
sweep: Y,
|
|
154
154
|
closed: Y >= 360
|
|
155
|
-
}) : [], Z = K ?
|
|
155
|
+
}) : [], Z = K ? h : h.map((e) => ({
|
|
156
156
|
...e,
|
|
157
|
-
fill: `var(--color-${e[
|
|
157
|
+
fill: `var(--color-${s(String(e[x]))})`
|
|
158
158
|
})), Q = q ? [{
|
|
159
|
-
...
|
|
159
|
+
...h[0],
|
|
160
160
|
...Object.fromEntries(X.map((e) => [e.key, e.degrees]))
|
|
161
|
-
}] : Z,
|
|
161
|
+
}] : Z, _e = N === void 0 ? void 0 : k < E ? -N : N, $ = u.useMemo(() => I ? o(d, m ?? t) : null, [
|
|
162
162
|
I,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
]),
|
|
163
|
+
d,
|
|
164
|
+
m
|
|
165
|
+
]), ve = u.useMemo(() => $ ? K ? J.map((e) => ({
|
|
166
166
|
value: e,
|
|
167
167
|
dataKey: e,
|
|
168
|
-
color: $[e]?.color ?? `var(--color-${e})`,
|
|
168
|
+
color: $[e]?.color ?? `var(--color-${s(e)})`,
|
|
169
169
|
type: "rect",
|
|
170
170
|
payload: {}
|
|
171
|
-
})) :
|
|
172
|
-
value: String(e[
|
|
173
|
-
dataKey:
|
|
174
|
-
color: $[String(e[
|
|
171
|
+
})) : h.map((e) => ({
|
|
172
|
+
value: String(e[x]),
|
|
173
|
+
dataKey: x,
|
|
174
|
+
color: $[String(e[x])]?.color ?? `var(--color-${s(String(e[x]))})`,
|
|
175
175
|
type: "rect",
|
|
176
176
|
payload: e
|
|
177
177
|
})) : [], [
|
|
178
178
|
$,
|
|
179
179
|
K,
|
|
180
180
|
J,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
]),
|
|
181
|
+
h,
|
|
182
|
+
x
|
|
183
|
+
]), ye = I && !q && !!$, be = /* @__PURE__ */ p(b, {
|
|
184
184
|
data: Q,
|
|
185
|
-
dataKey: K || q ? void 0 :
|
|
185
|
+
dataKey: K || q ? void 0 : g,
|
|
186
186
|
cx: ne,
|
|
187
|
-
cy:
|
|
188
|
-
innerRadius:
|
|
189
|
-
outerRadius:
|
|
190
|
-
startAngle:
|
|
191
|
-
endAngle:
|
|
187
|
+
cy: M,
|
|
188
|
+
innerRadius: S,
|
|
189
|
+
outerRadius: T,
|
|
190
|
+
startAngle: E,
|
|
191
|
+
endAngle: k,
|
|
192
192
|
barSize: re,
|
|
193
193
|
barGap: ie,
|
|
194
194
|
barCategoryGap: ae,
|
|
195
|
-
margin:
|
|
195
|
+
margin: oe ?? {
|
|
196
196
|
top: 0,
|
|
197
197
|
right: 0,
|
|
198
198
|
bottom: 0,
|
|
199
199
|
left: 0
|
|
200
200
|
},
|
|
201
201
|
children: [
|
|
202
|
-
|
|
202
|
+
le && /* @__PURE__ */ f(v, {
|
|
203
203
|
gridType: "circle",
|
|
204
204
|
radialLines: !1
|
|
205
205
|
}),
|
|
206
|
-
(
|
|
206
|
+
(A || q) && /* @__PURE__ */ f(_, {
|
|
207
207
|
type: "number",
|
|
208
|
-
domain: q ? [0, Y] :
|
|
208
|
+
domain: q ? [0, Y] : A,
|
|
209
209
|
tick: !1,
|
|
210
210
|
axisLine: !1
|
|
211
211
|
}),
|
|
212
|
-
|
|
212
|
+
ue && /* @__PURE__ */ f(i, {
|
|
213
213
|
cursor: !q && void 0,
|
|
214
|
-
content: R ?? (q ? /* @__PURE__ */
|
|
215
|
-
config:
|
|
216
|
-
row:
|
|
217
|
-
nameKey:
|
|
218
|
-
dataKey:
|
|
219
|
-
domainMax:
|
|
220
|
-
}) : K ? /* @__PURE__ */
|
|
221
|
-
nameKey:
|
|
214
|
+
content: R ?? (q ? /* @__PURE__ */ f(D, {
|
|
215
|
+
config: d,
|
|
216
|
+
row: h[0],
|
|
217
|
+
nameKey: x,
|
|
218
|
+
dataKey: g,
|
|
219
|
+
domainMax: A?.[1]
|
|
220
|
+
}) : K ? /* @__PURE__ */ f(a, { labelFormatter: (e, t) => O(t?.[0]?.payload, x) }) : /* @__PURE__ */ f(a, {
|
|
221
|
+
nameKey: x,
|
|
222
222
|
hideLabel: !0
|
|
223
223
|
}))
|
|
224
224
|
}),
|
|
225
|
-
q ? /* @__PURE__ */
|
|
225
|
+
q ? /* @__PURE__ */ f(te, {
|
|
226
226
|
ringSegments: X,
|
|
227
|
-
row:
|
|
228
|
-
nameKey:
|
|
229
|
-
cornerRadius:
|
|
227
|
+
row: h[0],
|
|
228
|
+
nameKey: x,
|
|
229
|
+
cornerRadius: j,
|
|
230
230
|
animation: W,
|
|
231
231
|
centerLabel: F
|
|
232
|
-
}) : /* @__PURE__ */
|
|
233
|
-
seriesKeys:
|
|
232
|
+
}) : /* @__PURE__ */ f(ee, {
|
|
233
|
+
seriesKeys: ge,
|
|
234
234
|
seriesData: Z,
|
|
235
235
|
isMultiMetric: K,
|
|
236
|
-
config:
|
|
237
|
-
nameKey:
|
|
238
|
-
showBackground:
|
|
239
|
-
cornerRadius:
|
|
240
|
-
minPointSize:
|
|
236
|
+
config: d,
|
|
237
|
+
nameKey: x,
|
|
238
|
+
showBackground: ce,
|
|
239
|
+
cornerRadius: j,
|
|
240
|
+
minPointSize: _e,
|
|
241
241
|
animation: W,
|
|
242
242
|
centerLabel: F,
|
|
243
243
|
showLabels: U,
|
|
244
244
|
labelPosition: G,
|
|
245
|
-
labelFormat:
|
|
246
|
-
labelFormatter:
|
|
245
|
+
labelFormat: fe,
|
|
246
|
+
labelFormatter: pe
|
|
247
247
|
})
|
|
248
248
|
]
|
|
249
|
-
}),
|
|
250
|
-
return /* @__PURE__ */
|
|
251
|
-
ref:
|
|
252
|
-
className: e("flex flex-row items-center gap-4", !
|
|
253
|
-
...
|
|
254
|
-
children: [/* @__PURE__ */
|
|
255
|
-
className: e(
|
|
256
|
-
children: /* @__PURE__ */
|
|
257
|
-
config:
|
|
258
|
-
palette:
|
|
249
|
+
}), xe = U && (G === "outside" || G === "end") ? "size-[200px]" : "size-[120px]";
|
|
250
|
+
return /* @__PURE__ */ p("div", {
|
|
251
|
+
ref: he,
|
|
252
|
+
className: e("flex flex-row items-center gap-4", !ye && "justify-center", l),
|
|
253
|
+
...me,
|
|
254
|
+
children: [/* @__PURE__ */ f("div", {
|
|
255
|
+
className: e(xe, "shrink-0"),
|
|
256
|
+
children: /* @__PURE__ */ f(n, {
|
|
257
|
+
config: d,
|
|
258
|
+
palette: m,
|
|
259
259
|
className: "size-full",
|
|
260
|
-
children:
|
|
260
|
+
children: be
|
|
261
261
|
})
|
|
262
|
-
}), I && !q && $ && /* @__PURE__ */
|
|
262
|
+
}), I && !q && $ && /* @__PURE__ */ f(r, {
|
|
263
263
|
variant: "list",
|
|
264
|
-
payload:
|
|
264
|
+
payload: ve,
|
|
265
265
|
config: $,
|
|
266
|
-
nameKey: K ? void 0 :
|
|
267
|
-
valueKey: K ? void 0 :
|
|
266
|
+
nameKey: K ? void 0 : x,
|
|
267
|
+
valueKey: K ? void 0 : g,
|
|
268
268
|
valueFormatter: K ? void 0 : L,
|
|
269
269
|
className: "min-w-0 flex-1"
|
|
270
270
|
})]
|
|
271
271
|
});
|
|
272
272
|
});
|
|
273
|
-
|
|
273
|
+
A.displayName = "RadialBarChart";
|
|
274
274
|
//#endregion
|
|
275
|
-
export {
|
|
275
|
+
export { A as RadialBarChart, D as RadialBarChartSegmentedTooltipContent, O as radialBarChartBandName, S as radialBarChartLabelText, T as radialBarChartSegmentFill, E as radialBarChartSegmentedReading, w as radialBarChartSegments };
|
|
276
276
|
|
|
277
277
|
//# sourceMappingURL=radial-bar-chart.js.map
|