{"spec_id":"range-interval","library":"muix","language":"javascript","code":"// anyplot.ai\n// range-interval: Range Interval Chart\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 88/100 | Created: 2026-09-02\nimport { BarChart } from \"@mui/x-charts/BarChart\";\nimport { useXScale, useYScale } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\nconst TITLE = \"range-interval · javascript · muix · anyplot.ai\";\nconst TITLE_HEIGHT = 56;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Annual base-salary ranges by department at a mid-size tech company ($k).\nconst departments = [\n  \"Customer Support\",\n  \"Marketing\",\n  \"Sales\",\n  \"Data Analytics\",\n  \"Product Management\",\n  \"DevOps & Infrastructure\",\n  \"Software Engineering\",\n  \"Engineering Leadership\",\n];\nconst minSalary = [42, 48, 45, 62, 78, 88, 85, 120];\nconst maxSalary = [58, 72, 95, 98, 125, 145, 165, 210];\n\nconst axisMin = 30;\nconst axisMax = 220;\n\n// --- Range bars ---------------------------------------------------------\n// Community BarChart has no native floating-bar / range primitive. Rather than\n// faking one out of two stacked series (transparent spacer + visible span —\n// which hits a real react-spring paint bug on the first stacked item), the\n// range is drawn directly with the chart's own x/y scale hooks: the same\n// documented extension point the community surface offers for custom\n// overlays (see e.g. ChartsReferenceLine). No animation, no clip-path — a\n// single deterministic <rect> per category.\nfunction RangeBars() {\n  const xScale = useXScale();\n  const yScale = useYScale();\n  const barHeight = yScale.bandwidth() * 0.72;\n  const capRadius = barHeight * 0.34;\n\n  return (\n    <g>\n      {departments.map((dept, i) => {\n        const x0 = xScale(minSalary[i]);\n        const x1 = xScale(maxSalary[i]);\n        const yMid = yScale(dept) + yScale.bandwidth() / 2;\n        const y = yMid - barHeight / 2;\n        return (\n          <g key={dept}>\n            <rect\n              x={Math.min(x0, x1)}\n              y={y}\n              width={Math.abs(x1 - x0)}\n              height={barHeight}\n              rx={4}\n              fill={t.palette[0]}\n              stroke={t.ink}\n              strokeWidth={1}\n            >\n              <title>\n                {dept}: ${minSalary[i]}k – ${maxSalary[i]}k\n              </title>\n            </rect>\n            {/* Endpoint markers: small ink-ringed caps pin the exact min/max bounds. */}\n            <circle\n              cx={x0}\n              cy={yMid}\n              r={capRadius}\n              fill={t.palette[0]}\n              stroke={t.ink}\n              strokeWidth={1}\n            />\n            <circle\n              cx={x1}\n              cy={yMid}\n              r={capRadius}\n              fill={t.palette[0]}\n              stroke={t.ink}\n              strokeWidth={1}\n            />\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\n// --- Chart (default-exported component — the harness mounts it) -------------\nexport default function Chart() {\n  const chartHeight = window.ANYPLOT_SIZE.height - TITLE_HEIGHT;\n\n  return (\n    <div\n      style={{\n        width: window.ANYPLOT_SIZE.width,\n        height: window.ANYPLOT_SIZE.height,\n      }}\n    >\n      <div\n        style={{\n          height: TITLE_HEIGHT,\n          lineHeight: `${TITLE_HEIGHT}px`,\n          paddingLeft: 24,\n          fontSize: 22,\n          fontWeight: 500,\n          color: t.ink,\n        }}\n      >\n        {TITLE}\n      </div>\n      <BarChart\n        width={window.ANYPLOT_SIZE.width}\n        height={chartHeight}\n        layout=\"horizontal\"\n        skipAnimation\n        margin={{ left: 240, right: 40, top: 24, bottom: 70 }}\n        series={[]}\n        xAxis={[\n          {\n            min: axisMin,\n            max: axisMax,\n            domainLimit: \"strict\",\n            valueFormatter: (v) => `$${v}k`,\n            label: \"Annual Base Salary ($ thousands)\",\n            labelStyle: { fontSize: 16 },\n            tickLabelStyle: { fontSize: 14 },\n          },\n        ]}\n        yAxis={[\n          {\n            scaleType: \"band\",\n            data: departments,\n            tickLabelStyle: { fontSize: 14 },\n          },\n        ]}\n        grid={{ vertical: true }}\n        slots={{ noDataOverlay: () => null }}\n        slotProps={{ legend: { hidden: true } }}\n      >\n        <RangeBars />\n      </BarChart>\n    </div>\n  );\n}\n"}