{"version":3,"file":"index.mjs","names":[],"sources":["../../src/BenchmarkScatterChart/index.tsx"],"sourcesContent":["'use client';\n\nimport { A } from '@lobehub/ui';\nimport { Segmented, Skeleton, Tooltip } from '@lobehub/ui/base-ui';\nimport { useSize } from 'ahooks';\nimport { cssVar, cx, useTheme } from 'antd-style';\nimport { type CSSProperties, type ReactNode, forwardRef, useMemo, useRef, useState } from 'react';\n\nimport ChartTooltip from '@/common/ChartTooltip';\nimport NoData from '@/common/NoData';\nimport {\n  type BenchmarkBaseProps,\n  type BenchmarkEventProps,\n  type BenchmarkPointShape,\n  type NormalizedBenchmarkItem,\n  defaultBenchmarkErrorFormatter,\n  defaultBenchmarkValueFormatter,\n  normalizeBenchmarkData,\n} from '@/common/benchmark';\nimport { constructCategoryColors } from '@/common/utils';\nimport { useThemeColorRange } from '@/hooks/useThemeColorRange';\nimport { getTextWidth } from '@/utils/getMaxLabelLength';\n\nimport { styles } from './styles';\nimport {\n  type Box,\n  type LabelCandidate,\n  type PlacedLabel,\n  type ScaleType,\n  createScale,\n  getParetoFrontier,\n  placeLabels,\n} from './utils';\n\nexport interface BenchmarkScatterMetric {\n  /**\n   * Axis title; falls back to `label`\n   */\n  axisLabel?: string;\n  /**\n   * Which direction is better on this axis (drives the Pareto frontier)\n   * @default 'lower'\n   */\n  direction?: 'lower' | 'higher';\n  formatter?: (value: number) => string;\n  /**\n   * Record field holding this metric\n   */\n  key: string;\n  /**\n   * Label shown in the metric switcher and tooltip\n   */\n  label: string;\n  max?: number;\n  min?: number;\n  /**\n   * @default 'linear'\n   */\n  scale?: ScaleType;\n}\n\nexport interface BenchmarkScatterChartProps extends Omit<BenchmarkBaseProps, 'sortOrder'> {\n  /**\n   * Initially selected metric key when `metrics` is provided (uncontrolled)\n   */\n  defaultMetric?: string;\n  /**\n   * Pareto frontier line color\n   * @default theme.orange\n   */\n  frontierColor?: string;\n  /**\n   * @default 2\n   */\n  frontierWidth?: number;\n  /**\n   * Size of consumer-provided icons; should match the size the icon renders at.\n   * Icons are scaled down from this size in the legend.\n   * @default 20\n   */\n  iconSize?: number;\n  /**\n   * Font size for the point name label\n   * @default 12\n   */\n  labelFontSize?: number;\n  /**\n   * Size of the fallback shape marker when an item has no icon\n   * @default 12\n   */\n  markerSize?: number;\n  maxX?: number;\n  maxY?: number;\n  /**\n   * Selected metric key (controlled)\n   */\n  metric?: string;\n  /**\n   * Switchable X metrics (e.g. Cost / Speed). Overrides `xKey`, `xScale`,\n   * `xFormatter`, `xAxisLabel` and `xDirection` for the active metric.\n   */\n  metrics?: BenchmarkScatterMetric[];\n  minX?: number;\n  minY?: number;\n  onMetricChange?: (metric: string) => void;\n  /**\n   * On hover, shade the region the point dominates (worse X and lower Y)\n   * and gray out the points inside it. When off, all other points are dimmed instead.\n   * @default true\n   */\n  showDominatedArea?: boolean;\n  /**\n   * Draw vertical error bars when records have `error`\n   * @default true\n   */\n  showErrorBars?: boolean;\n  /**\n   * Connect non-dominated points with a Pareto frontier line\n   * @default true\n   */\n  showFrontier?: boolean;\n  /**\n   * @default true\n   */\n  showGridLines?: boolean;\n  /**\n   * Show name labels next to points (placed automatically to avoid overlap)\n   * @default true\n   */\n  showLabels?: boolean;\n  /**\n   * @default true\n   */\n  showLegend?: boolean;\n  /**\n   * @default true\n   */\n  showTooltip?: boolean;\n  /**\n   * Show `y · x` values under each point label\n   * @default true\n   */\n  showValueLabel?: boolean;\n  /**\n   * @default true\n   */\n  showXAxis?: boolean;\n  /**\n   * @default true\n   */\n  showYAxis?: boolean;\n  /**\n   * Font size for the `y · x` value line\n   * @default 11\n   */\n  valueLabelFontSize?: number;\n  xAxisLabel?: string;\n  /**\n   * Which direction is better on X (drives the Pareto frontier)\n   * @default 'lower'\n   */\n  xDirection?: 'lower' | 'higher';\n  xFormatter?: (value: number) => string;\n  /**\n   * Record field used for the X axis\n   * @default 'x'\n   */\n  xKey?: string;\n  /**\n   * X axis scale\n   * @default 'linear'\n   */\n  xScale?: ScaleType;\n  yAxisLabel?: string;\n}\n\ninterface PlotPoint {\n  color: string;\n  item: NormalizedBenchmarkItem;\n  key: string | number;\n  x: number;\n  y: number;\n}\n\nconst labelPriority = (point: PlotPoint, frontierKeys: ReadonlySet<string | number>) =>\n  (frontierKeys.has(point.key) ? 0 : 2) + (point.item.highlighted ? 0 : 1);\n\nconst MARGIN_TOP = 12;\nconst MARGIN_RIGHT = 16;\nconst TICK_GAP = 8;\nconst AXIS_TITLE_SIZE = 22;\n// Monospace glyph advance relative to font size (Geist Mono / SF Mono ≈ 0.6em)\nconst MONO_CHAR_RATIO = 0.62;\n\nconst renderShape = (\n  shape: BenchmarkPointShape | undefined,\n  color: string,\n  size: number,\n  ring = false,\n) => {\n  const half = size / 2;\n  let node: ReactNode;\n  switch (shape) {\n    case 'square': {\n      node = (\n        <rect\n          fill={color}\n          height={size * 0.84}\n          width={size * 0.84}\n          x={size * 0.08}\n          y={size * 0.08}\n        />\n      );\n      break;\n    }\n    case 'diamond': {\n      node = <path d={`M${half},0 L${size},${half} L${half},${size} L0,${half} Z`} fill={color} />;\n      break;\n    }\n    case 'triangle': {\n      node = <path d={`M${half},0 L${size},${size * 0.9} L0,${size * 0.9} Z`} fill={color} />;\n      break;\n    }\n    default: {\n      node = <circle cx={half} cy={half} fill={color} r={half} />;\n    }\n  }\n  return (\n    <svg height={size} style={{ display: 'block', overflow: 'visible' }} width={size}>\n      {ring ? (\n        <g paintOrder=\"stroke\" stroke={cssVar.colorBgContainer} strokeWidth={4}>\n          {node}\n        </g>\n      ) : (\n        node\n      )}\n    </svg>\n  );\n};\n\nconst toLabelText = (name: ReactNode) => String(name ?? '').replaceAll('\\n', ' ');\n\nconst BenchmarkScatterChart = forwardRef<HTMLDivElement, BenchmarkScatterChartProps>(\n  (props, ref) => {\n    const theme = useTheme();\n    const themeColorRange = useThemeColorRange();\n    const {\n      data = [],\n      index,\n      valueKey,\n      providerKey,\n      iconKey,\n      colorKey,\n      errorKey,\n      renderIcon,\n      valueFormatter = defaultBenchmarkValueFormatter,\n      accuracyFormatter,\n      errorFormatter = defaultBenchmarkErrorFormatter,\n      showError = true,\n      showErrorBars = true,\n      showAnimation = false,\n      onValueChange,\n      className,\n      style,\n      loading,\n      width = '100%',\n      height = 420,\n      noDataText,\n      highlightColor,\n      frontierColor,\n      frontierWidth = 2,\n      iconSize = 20,\n      markerSize = 12,\n      labelFontSize = 12,\n      valueLabelFontSize = 11,\n      metrics,\n      metric,\n      defaultMetric,\n      onMetricChange,\n      minX,\n      maxX,\n      minY,\n      maxY,\n      showDominatedArea = true,\n      showFrontier = true,\n      showGridLines = true,\n      showLabels = true,\n      showLegend = true,\n      showTooltip = true,\n      showValueLabel = true,\n      showXAxis = true,\n      showYAxis = true,\n      xAxisLabel,\n      xDirection = 'lower',\n      xFormatter = defaultBenchmarkValueFormatter,\n      xKey = 'x',\n      xScale = 'linear',\n      yAxisLabel,\n      ...rest\n    } = props;\n\n    const plotRef = useRef<HTMLDivElement>(null);\n    const size = useSize(plotRef);\n    const [innerMetric, setInnerMetric] = useState(defaultMetric);\n    const [hoverKey, setHoverKey] = useState<string | number | undefined>();\n    const [selectedKey, setSelectedKey] = useState<string | number | undefined>();\n\n    const resolvedHighlightColor = highlightColor ?? theme.gold;\n    const resolvedFrontierColor = frontierColor ?? theme.orange;\n    const yFormatter = accuracyFormatter ?? valueFormatter;\n    const yName = yAxisLabel || (accuracyFormatter ? 'Accuracy' : 'Score');\n\n    const activeMetric = useMemo(() => {\n      if (metrics?.length) {\n        const key = metric ?? innerMetric;\n        const found = metrics.find((m) => m.key === key) ?? metrics[0];\n        return {\n          axisLabel: found.axisLabel ?? found.label,\n          direction: found.direction ?? 'lower',\n          formatter: found.formatter ?? defaultBenchmarkValueFormatter,\n          key: found.key,\n          label: found.label,\n          max: found.max ?? maxX,\n          min: found.min ?? minX,\n          scale: found.scale ?? 'linear',\n        };\n      }\n      return {\n        axisLabel: xAxisLabel,\n        direction: xDirection,\n        formatter: xFormatter,\n        key: xKey,\n        label: xAxisLabel || 'X',\n        max: maxX,\n        min: minX,\n        scale: xScale,\n      };\n    }, [\n      innerMetric,\n      maxX,\n      metric,\n      metrics,\n      minX,\n      xAxisLabel,\n      xDirection,\n      xFormatter,\n      xKey,\n      xScale,\n    ]);\n\n    const items = useMemo(\n      () =>\n        normalizeBenchmarkData({\n          colorKey,\n          data,\n          errorKey,\n          iconKey,\n          index,\n          providerKey,\n          renderIcon,\n          sortOrder: 'descending',\n          valueKey,\n        }),\n      [colorKey, data, errorKey, iconKey, index, providerKey, renderIcon, valueKey],\n    );\n\n    const categoryColors = useMemo(\n      () =>\n        constructCategoryColors(\n          items.map((item) => String(item.key)),\n          themeColorRange,\n        ),\n      [items, themeColorRange],\n    );\n\n    const points: PlotPoint[] = useMemo(\n      () =>\n        items\n          .map((item) => ({\n            color: item.color ?? categoryColors.get(String(item.key)) ?? cssVar.colorPrimary,\n            item,\n            key: item.key,\n            x: Number(item.original[activeMetric.key]),\n            y: item.value,\n          }))\n          .filter(\n            (p) =>\n              Number.isFinite(p.x) &&\n              Number.isFinite(p.y) &&\n              (activeMetric.scale !== 'log' || p.x > 0),\n          ),\n      [activeMetric.key, activeMetric.scale, categoryColors, items],\n    );\n\n    const frontier = useMemo(\n      () => (showFrontier ? getParetoFrontier(points, activeMetric.direction) : []),\n      [activeMetric.direction, points, showFrontier],\n    );\n    const frontierKeys = useMemo(() => new Set(frontier.map((p) => p.key)), [frontier]);\n\n    const enableErrorBars = showError && showErrorBars;\n    const yValues = useMemo(\n      () =>\n        points.flatMap((p) =>\n          enableErrorBars && p.item.error ? [p.y - p.item.error, p.y + p.item.error] : [p.y],\n        ),\n      [enableErrorBars, points],\n    );\n\n    const labelSizes = useMemo(() => {\n      const map = new Map<string | number, { height: number; width: number }>();\n      if (!showLabels) return map;\n      const nameScale = (labelFontSize / 12) * 1.1;\n      for (const p of points) {\n        const nameWidth = getTextWidth(toLabelText(p.item.name)) * nameScale;\n        const valueWidth = showValueLabel\n          ? `${yFormatter(p.y)} · ${activeMetric.formatter(p.x)}`.length *\n            valueLabelFontSize *\n            MONO_CHAR_RATIO\n          : 0;\n        map.set(p.key, {\n          height: Math.ceil(labelFontSize * 1.3 + (showValueLabel ? valueLabelFontSize * 1.3 : 0)),\n          width: Math.ceil(Math.max(nameWidth, valueWidth)) + 2,\n        });\n      }\n      return map;\n    }, [\n      activeMetric,\n      labelFontSize,\n      points,\n      showLabels,\n      showValueLabel,\n      valueLabelFontSize,\n      yFormatter,\n    ]);\n\n    const plotWidth = size?.width || (typeof width === 'number' ? width : 0);\n    const plotHeight = typeof height === 'number' ? height : 420;\n\n    const layout = useMemo(() => {\n      if (!plotWidth || !points.length) return null;\n\n      const probeY = createScale({ max: maxY, min: minY, range: [0, 1], values: yValues });\n      const yTickWidth = showYAxis\n        ? Math.max(...probeY.ticks.map((t) => yFormatter(t).length * 12 * MONO_CHAR_RATIO), 0)\n        : 0;\n\n      const left = (showYAxis ? yTickWidth + TICK_GAP + 4 : 4) + (yAxisLabel ? AXIS_TITLE_SIZE : 0);\n      const bottom = (showXAxis ? 26 : 4) + (activeMetric.axisLabel ? AXIS_TITLE_SIZE : 0);\n      const innerRight = plotWidth - MARGIN_RIGHT;\n      const innerBottom = plotHeight - bottom;\n\n      const xScaleObj = createScale({\n        max: activeMetric.max,\n        min: activeMetric.min,\n        range: [left, innerRight],\n        type: activeMetric.scale,\n        values: points.map((p) => p.x),\n      });\n      const yScaleObj = createScale({\n        max: maxY,\n        min: minY,\n        range: [innerBottom, MARGIN_TOP],\n        values: yValues,\n      });\n\n      const positions = new Map<string | number, { px: number; py: number; radius: number }>();\n      for (const p of points) {\n        positions.set(p.key, {\n          px: xScaleObj.map(p.x),\n          py: yScaleObj.map(p.y),\n          radius: (p.item.icon ? iconSize : markerSize) / 2,\n        });\n      }\n\n      const frontierPath = frontier\n        .map((p, i) => {\n          const pos = positions.get(p.key)!;\n          return `${i === 0 ? 'M' : 'L'}${pos.px.toFixed(2)},${pos.py.toFixed(2)}`;\n        })\n        .join(' ');\n\n      let labels = new Map<string | number, PlacedLabel>();\n      if (showLabels) {\n        const lineBoxes: Box[] = [];\n        for (let i = 1; i < frontier.length; i++) {\n          const a = positions.get(frontier[i - 1].key)!;\n          const b = positions.get(frontier[i].key)!;\n          const steps = Math.max(1, Math.ceil(Math.hypot(b.px - a.px, b.py - a.py) / 10));\n          for (let s = 0; s <= steps; s++) {\n            const t = s / steps;\n            lineBoxes.push({\n              height: 6,\n              width: 6,\n              x: a.px + (b.px - a.px) * t - 3,\n              y: a.py + (b.py - a.py) * t - 3,\n            });\n          }\n        }\n\n        const ordered = [...points].sort(\n          (a, b) => labelPriority(a, frontierKeys) - labelPriority(b, frontierKeys) || b.y - a.y,\n        );\n        const candidates: LabelCandidate[] = ordered.map((p) => {\n          const pos = positions.get(p.key)!;\n          const labelSize = labelSizes.get(p.key) ?? { height: 16, width: 40 };\n          return { ...labelSize, key: p.key, ...pos };\n        });\n\n        labels = placeLabels(\n          candidates,\n          { height: innerBottom, width: plotWidth - left + MARGIN_RIGHT, x: left, y: 0 },\n          { lines: lineBoxes },\n        );\n      }\n\n      return {\n        bottom,\n        frontierPath,\n        innerBottom,\n        innerRight,\n        labels,\n        left,\n        positions,\n        xScale: xScaleObj,\n        yScale: yScaleObj,\n      };\n    }, [\n      activeMetric,\n      frontier,\n      frontierKeys,\n      iconSize,\n      labelSizes,\n      markerSize,\n      maxY,\n      minY,\n      plotHeight,\n      plotWidth,\n      points,\n      showLabels,\n      showXAxis,\n      showYAxis,\n      yAxisLabel,\n      yFormatter,\n      yValues,\n    ]);\n\n    if (loading || !data) return <Skeleton height={plotHeight} width={width} />;\n\n    const focusKey = hoverKey ?? selectedKey;\n    const focusPoint =\n      focusKey === undefined ? undefined : points.find((point) => point.key === focusKey);\n    const dominatedKeys = new Set<string | number>();\n    if (showDominatedArea && focusPoint) {\n      for (const point of points) {\n        if (point.key === focusPoint.key || point.y > focusPoint.y) continue;\n        const worseX =\n          activeMetric.direction === 'lower' ? point.x >= focusPoint.x : point.x <= focusPoint.x;\n        if (worseX) dominatedKeys.add(point.key);\n      }\n    }\n    const getEmphasis = (key: string | number): 'normal' | 'dimmed' | 'dominated' => {\n      if (focusKey === undefined || key === focusKey) return 'normal';\n      if (!showDominatedArea) return 'dimmed';\n      return dominatedKeys.has(key) ? 'dominated' : 'normal';\n    };\n    const isDimmed = (key: string | number) => getEmphasis(key) !== 'normal';\n    const animatedCls = showAnimation ? undefined : styles.noTransition;\n\n    const handleClick = (item: NormalizedBenchmarkItem) => {\n      if (!onValueChange) return;\n      if (selectedKey === item.key) {\n        setSelectedKey(undefined);\n        onValueChange(null);\n        return;\n      }\n      setSelectedKey(item.key);\n      const payload: BenchmarkEventProps = {\n        ...item.original,\n        eventType: 'point',\n        rank: item.rank,\n        value: item.value,\n      };\n      onValueChange(payload);\n    };\n\n    const handleMetricChange = (key: string) => {\n      if (metric === undefined) setInnerMetric(key);\n      onMetricChange?.(key);\n    };\n\n    const renderTooltip = (point: PlotPoint, child: ReactNode) => {\n      if (!showTooltip) return child;\n\n      const { item } = point;\n      const rows: Array<{ format: (_value: number) => string; name: string; value: number }> = [];\n      if (metrics?.length) {\n        for (const m of metrics) {\n          const value = Number(item.original[m.key]);\n          if (!Number.isFinite(value)) continue;\n          rows.push({\n            format: m.formatter ?? defaultBenchmarkValueFormatter,\n            name: m.label,\n            value,\n          });\n        }\n      } else {\n        rows.push({ format: activeMetric.formatter, name: activeMetric.label, value: point.x });\n      }\n      rows.reverse();\n      rows.push({\n        format: (v) =>\n          showError && item.error !== undefined\n            ? `${yFormatter(v)} ± ${errorFormatter(item.error)}`\n            : yFormatter(v),\n        name: yName,\n        value: point.y,\n      });\n\n      const formatters = new Map(rows.map((row) => [row.name, row.format]));\n      const modelName = toLabelText(item.name);\n\n      return (\n        <Tooltip\n          arrow={false}\n          mouseEnterDelay={0.05}\n          mouseLeaveDelay={0}\n          styles={{\n            container: {\n              background: 'transparent',\n              boxShadow: 'none',\n              maxWidth: 'none',\n              padding: 0,\n              pointerEvents: 'none',\n              width: 'max-content',\n            },\n            content: {\n              color: cssVar.colorText,\n              fontSize: cssVar.fontSize,\n              lineHeight: cssVar.lineHeight,\n              maxWidth: 'none',\n              overflow: 'visible',\n              padding: 0,\n            },\n            root: { maxWidth: 'none', pointerEvents: 'none' },\n          }}\n          title={\n            <ChartTooltip\n              active\n              categoryColors={new Map(rows.map((row) => [row.name, point.color]))}\n              label={item.provider ? `${modelName} · ${String(item.provider)}` : modelName}\n              payload={rows.map((row) => ({ dataKey: row.name, name: row.name, value: row.value }))}\n              valueFormatter={(value: number, name?: string) =>\n                (formatters.get(name ?? '') ?? String)(Number(value))\n              }\n            />\n          }\n        >\n          {child}\n        </Tooltip>\n      );\n    };\n\n    const renderMarker = (point: PlotPoint, markerSizePx: number, ring = false) =>\n      point.item.icon ? (\n        <span\n          className={ring ? styles.markerIconRing : undefined}\n          style={{\n            alignItems: 'center',\n            display: 'flex',\n            flexShrink: 0,\n            height: iconSize,\n            justifyContent: 'center',\n            transform: markerSizePx === iconSize ? undefined : `scale(${markerSizePx / iconSize})`,\n            width: iconSize,\n          }}\n        >\n          {point.item.icon}\n        </span>\n      ) : (\n        renderShape(point.item.original.shape, point.color, markerSizePx, ring)\n      );\n\n    const hasMetricSwitch = (metrics?.length ?? 0) > 1;\n\n    return (\n      <div\n        className={cx(styles.container, className)}\n        ref={ref}\n        style={\n          {\n            '--benchmark-label-font-size': `${labelFontSize}px`,\n            '--benchmark-value-label-font-size': `${valueLabelFontSize}px`,\n            'width': width,\n            ...style,\n          } as CSSProperties\n        }\n        {...rest}\n      >\n        {(showLegend && points.length > 0) || hasMetricSwitch ? (\n          <div className={styles.header}>\n            <div className={styles.legend}>\n              {showLegend\n                ? points.map((point) => (\n                    <span\n                      className={styles.legendItem}\n                      key={`legend-${point.key}`}\n                      onClick={() => handleClick(point.item)}\n                      onMouseEnter={() => setHoverKey(point.key)}\n                      onMouseLeave={() => setHoverKey(undefined)}\n                      style={{\n                        color: point.item.highlighted ? resolvedHighlightColor : undefined,\n                        cursor: onValueChange ? 'pointer' : undefined,\n                        opacity: isDimmed(point.key) ? 0.4 : 1,\n                      }}\n                    >\n                      <span className={styles.legendMarker}>{renderMarker(point, 12)}</span>\n                      {toLabelText(point.item.name)}\n                    </span>\n                  ))\n                : null}\n            </div>\n            {hasMetricSwitch ? (\n              <Segmented\n                onChange={(value) => handleMetricChange(String(value))}\n                options={metrics!.map((m) => ({ label: m.label, value: m.key }))}\n                size=\"small\"\n                value={activeMetric.key}\n              />\n            ) : null}\n          </div>\n        ) : null}\n\n        <div className={styles.plot} ref={plotRef} style={{ height: plotHeight }}>\n          {!points.length ? <NoData noDataText={noDataText} /> : null}\n          {layout ? (\n            <>\n              <svg\n                height={plotHeight}\n                role=\"img\"\n                style={{ display: 'block', overflow: 'visible' }}\n                width={plotWidth}\n              >\n                {showGridLines ? (\n                  <g>\n                    {layout.yScale.ticks.map((tick) => {\n                      const y = layout.yScale.map(tick);\n                      return (\n                        <line\n                          className={styles.gridLine}\n                          key={`gy-${tick}`}\n                          x1={layout.left}\n                          x2={layout.innerRight}\n                          y1={y}\n                          y2={y}\n                        />\n                      );\n                    })}\n                    {layout.xScale.ticks.map((tick) => {\n                      const x = layout.xScale.map(tick);\n                      return (\n                        <line\n                          className={styles.gridLine}\n                          key={`gx-${tick}`}\n                          x1={x}\n                          x2={x}\n                          y1={MARGIN_TOP}\n                          y2={layout.innerBottom}\n                        />\n                      );\n                    })}\n                  </g>\n                ) : null}\n\n                {showYAxis ? (\n                  <g>\n                    {layout.yScale.ticks.map((tick) => (\n                      <text\n                        className={styles.tickLabel}\n                        dominantBaseline=\"middle\"\n                        key={`ty-${tick}`}\n                        textAnchor=\"end\"\n                        x={layout.left - TICK_GAP}\n                        y={layout.yScale.map(tick)}\n                      >\n                        {yFormatter(tick)}\n                      </text>\n                    ))}\n                  </g>\n                ) : null}\n\n                {showXAxis ? (\n                  <g>\n                    <line\n                      className={styles.axisLine}\n                      x1={layout.left}\n                      x2={layout.innerRight}\n                      y1={layout.innerBottom}\n                      y2={layout.innerBottom}\n                    />\n                    {layout.xScale.ticks.map((tick) => (\n                      <text\n                        className={styles.tickLabel}\n                        dominantBaseline=\"hanging\"\n                        key={`tx-${tick}`}\n                        textAnchor=\"middle\"\n                        x={layout.xScale.map(tick)}\n                        y={layout.innerBottom + TICK_GAP}\n                      >\n                        {activeMetric.formatter(tick)}\n                      </text>\n                    ))}\n                  </g>\n                ) : null}\n\n                {yAxisLabel ? (\n                  <text\n                    className={styles.axisLabel}\n                    dominantBaseline=\"hanging\"\n                    textAnchor=\"middle\"\n                    transform={`rotate(-90, 0, ${(MARGIN_TOP + layout.innerBottom) / 2})`}\n                    x={0}\n                    y={(MARGIN_TOP + layout.innerBottom) / 2}\n                  >\n                    {yAxisLabel}\n                  </text>\n                ) : null}\n\n                {activeMetric.axisLabel ? (\n                  <text\n                    className={styles.axisLabel}\n                    dominantBaseline=\"auto\"\n                    textAnchor=\"middle\"\n                    x={(layout.left + layout.innerRight) / 2}\n                    y={plotHeight - 4}\n                  >\n                    {activeMetric.axisLabel}\n                  </text>\n                ) : null}\n\n                {showDominatedArea && focusPoint\n                  ? (() => {\n                      const pos = layout.positions.get(focusPoint.key)!;\n                      const toRight = activeMetric.direction === 'lower';\n                      const x0 = toRight ? pos.px : layout.left;\n                      const x1 = toRight ? layout.innerRight : pos.px;\n                      return (\n                        <g\n                          className={styles.dominatedArea}\n                          data-testid=\"benchmark-scatter-dominated-area\"\n                        >\n                          <rect\n                            fill={resolvedFrontierColor}\n                            fillOpacity={0.08}\n                            height={Math.max(0, layout.innerBottom - pos.py)}\n                            width={Math.max(0, x1 - x0)}\n                            x={x0}\n                            y={pos.py}\n                          />\n                          <line\n                            className={styles.dominatedGuide}\n                            x1={x0}\n                            x2={x1}\n                            y1={pos.py}\n                            y2={pos.py}\n                          />\n                          <line\n                            className={styles.dominatedGuide}\n                            x1={pos.px}\n                            x2={pos.px}\n                            y1={pos.py}\n                            y2={layout.innerBottom}\n                          />\n                        </g>\n                      );\n                    })()\n                  : null}\n\n                {enableErrorBars\n                  ? points.map((point) => {\n                      const { error } = point.item;\n                      if (!error) return null;\n                      const pos = layout.positions.get(point.key)!;\n                      const top = layout.yScale.map(point.y + error);\n                      const bottom = layout.yScale.map(point.y - error);\n                      return (\n                        <g\n                          className={styles.errorBar}\n                          data-testid=\"benchmark-scatter-error-bar\"\n                          key={`err-${point.key}`}\n                          opacity={isDimmed(point.key) ? 0.25 : 0.7}\n                          stroke={point.color}\n                        >\n                          <line x1={pos.px} x2={pos.px} y1={top} y2={bottom} />\n                          <line x1={pos.px - 4} x2={pos.px + 4} y1={top} y2={top} />\n                          <line x1={pos.px - 4} x2={pos.px + 4} y1={bottom} y2={bottom} />\n                        </g>\n                      );\n                    })\n                  : null}\n\n                {layout.frontierPath ? (\n                  <path\n                    className={styles.frontier}\n                    d={layout.frontierPath}\n                    data-testid=\"benchmark-scatter-frontier\"\n                    opacity={\n                      !showDominatedArea && focusKey !== undefined && !frontierKeys.has(focusKey)\n                        ? 0.35\n                        : 1\n                    }\n                    stroke={resolvedFrontierColor}\n                    strokeWidth={frontierWidth}\n                    style={showAnimation ? { transition: `d 0.4s, opacity 0.2s` } : undefined}\n                  />\n                ) : null}\n              </svg>\n\n              <div className={styles.overlay}>\n                {points.map((point) => {\n                  const pos = layout.positions.get(point.key)!;\n                  const markerPx = point.item.icon ? iconSize : markerSize;\n                  return (\n                    <div key={`marker-${point.key}`}>\n                      {renderTooltip(\n                        point,\n                        <div\n                          aria-label={`${toLabelText(point.item.name)}: ${yFormatter(point.y)}, ${activeMetric.formatter(point.x)}`}\n                          className={cx(styles.marker, animatedCls)}\n                          onClick={() => handleClick(point.item)}\n                          onMouseEnter={() => setHoverKey(point.key)}\n                          onMouseLeave={() => setHoverKey(undefined)}\n                          role=\"button\"\n                          style={{\n                            cursor: onValueChange ? 'pointer' : 'default',\n                            filter:\n                              getEmphasis(point.key) === 'dominated' ? 'grayscale(1)' : undefined,\n                            height: markerPx,\n                            left: pos.px,\n                            opacity: { dimmed: 0.25, dominated: 0.5, normal: 1 }[\n                              getEmphasis(point.key)\n                            ],\n                            top: pos.py,\n                            width: markerPx,\n                          }}\n                        >\n                          {renderMarker(point, markerPx, true)}\n                        </div>,\n                      )}\n                    </div>\n                  );\n                })}\n\n                {showLabels\n                  ? points.map((point) => {\n                      const label = layout.labels.get(point.key);\n                      if (!label) return null;\n                      const emphasis = getEmphasis(point.key);\n                      const textColor =\n                        emphasis === 'dominated'\n                          ? cssVar.colorTextQuaternary\n                          : point.item.highlighted\n                            ? resolvedHighlightColor\n                            : undefined;\n                      const isKeyLabel =\n                        emphasis !== 'dominated' &&\n                        (frontierKeys.has(point.key) ||\n                          point.item.highlighted ||\n                          point.key === focusKey);\n                      const align = label.placement.endsWith('left')\n                        ? 'right'\n                        : label.placement === 'top' || label.placement === 'bottom'\n                          ? 'center'\n                          : 'left';\n                      const name = toLabelText(point.item.name);\n\n                      return (\n                        <div\n                          className={cx(styles.label, animatedCls)}\n                          key={`label-${point.key}`}\n                          onClick={() => handleClick(point.item)}\n                          onMouseEnter={() => setHoverKey(point.key)}\n                          onMouseLeave={() => setHoverKey(undefined)}\n                          style={{\n                            cursor: onValueChange ? 'pointer' : 'default',\n                            height: label.height,\n                            left: label.x,\n                            opacity: emphasis === 'dimmed' ? 0.25 : 1,\n                            textAlign: align,\n                            top: label.y,\n                            width: label.width,\n                          }}\n                        >\n                          <div\n                            className={cx(styles.labelName, isKeyLabel && styles.labelNameEmphasis)}\n                            style={textColor ? { color: textColor } : undefined}\n                          >\n                            {point.item.href ? (\n                              <A\n                                className={styles.labelNameLink}\n                                href={point.item.href}\n                                onClick={(event) => event.stopPropagation()}\n                                target={point.item.target}\n                              >\n                                {name}\n                              </A>\n                            ) : (\n                              name\n                            )}\n                          </div>\n                          {showValueLabel ? (\n                            <div className={styles.labelValue}>\n                              {yFormatter(point.y)} · {activeMetric.formatter(point.x)}\n                            </div>\n                          ) : null}\n                        </div>\n                      );\n                    })\n                  : null}\n              </div>\n            </>\n          ) : null}\n        </div>\n      </div>\n    );\n  },\n);\n\nBenchmarkScatterChart.displayName = 'BenchmarkScatterChart';\n\nexport default BenchmarkScatterChart;\n"],"mappings":"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"}