{"spec_id":"point-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// point-basic: Point Estimate Plot\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 87/100 | Created: 2026-09-05\n//# anyplot-orientation: landscape\n// anyplot.ai\n// point-basic: Point Estimate Plot\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-09-05\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { ChartsGrid } from \"@mui/x-charts/ChartsGrid\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport { useXScale, useYScale } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data: effect of an after-school tutoring program on standardized test\n// scores (Cohen's d), independently estimated at 8 pilot sites with 95% CIs.\n// Sorted descending by estimate so the visual hierarchy reads top-to-bottom.\nconst sites = [\n  { site: \"Denver\", estimate: 0.55, lower: 0.3, upper: 0.8 },\n  { site: \"Portland\", estimate: 0.45, lower: 0.22, upper: 0.68 },\n  { site: \"Boston\", estimate: 0.42, lower: 0.18, upper: 0.66 },\n  { site: \"Austin\", estimate: 0.38, lower: 0.15, upper: 0.61 },\n  { site: \"Chicago\", estimate: 0.31, lower: 0.05, upper: 0.57 },\n  { site: \"Seattle\", estimate: 0.28, lower: 0.02, upper: 0.54 },\n  { site: \"Atlanta\", estimate: 0.12, lower: -0.1, upper: 0.34 },\n  { site: \"Miami\", estimate: -0.05, lower: -0.28, upper: 0.18 },\n];\n\nconst TITLE_HEIGHT = 68;\n\n// --- Custom overlay: MUI X community has no built-in error-bar series, so the\n// point + CI whiskers are drawn directly against the cartesian scales via the\n// public useXScale/useYScale hooks (this stays entirely within community\n// @mui/x-charts — no Pro chart types involved).\nfunction PointEstimates() {\n  const xScale = useXScale();\n  const yScale = useYScale();\n  const capHalf = (yScale.bandwidth?.() ?? 0) * 0.22;\n\n  return (\n    <g>\n      {sites.map((row) => {\n        const y = (yScale(row.site) ?? 0) + (yScale.bandwidth?.() ?? 0) / 2;\n        const xLow = xScale(row.lower);\n        const xHigh = xScale(row.upper);\n        const xEst = xScale(row.estimate);\n        return (\n          <g key={row.site}>\n            <line x1={xLow} x2={xHigh} y1={y} y2={y} stroke={t.palette[0]} strokeWidth={3} strokeLinecap=\"round\" />\n            <line x1={xLow} x2={xLow} y1={y - capHalf} y2={y + capHalf} stroke={t.palette[0]} strokeWidth={3} />\n            <line x1={xHigh} x2={xHigh} y1={y - capHalf} y2={y + capHalf} stroke={t.palette[0]} strokeWidth={3} />\n            <circle cx={xEst} cy={y} r={10} fill={t.palette[0]} stroke={t.pageBg} strokeWidth={2.5} />\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\nexport default function Chart() {\n  const chartHeight = window.ANYPLOT_SIZE.height - TITLE_HEIGHT;\n\n  return (\n    <div style={{ width: window.ANYPLOT_SIZE.width, height: window.ANYPLOT_SIZE.height }}>\n      <div\n        style={{\n          height: TITLE_HEIGHT,\n          display: \"flex\",\n          alignItems: \"center\",\n          paddingLeft: 24,\n          fontSize: 22,\n          fontWeight: 600,\n          color: t.ink,\n          fontFamily: \"inherit\",\n        }}\n      >\n        point-basic · javascript · muix · anyplot.ai\n      </div>\n      <ChartContainer\n        width={window.ANYPLOT_SIZE.width}\n        height={chartHeight}\n        series={[]}\n        skipAnimation\n        margin={{ top: 20, bottom: 60, left: 130, right: 40 }}\n        xAxis={[\n          {\n            id: \"effect-size\",\n            scaleType: \"linear\",\n            min: -0.4,\n            max: 1.0,\n            label: \"Effect Size (Cohen's d)\",\n            labelStyle: { fontSize: 15 },\n            tickLabelStyle: { fontSize: 14 },\n            tickInterval: [-0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1.0],\n          },\n        ]}\n        yAxis={[\n          {\n            id: \"site\",\n            scaleType: \"band\",\n            data: sites.map((row) => row.site),\n            tickLabelStyle: { fontSize: 14 },\n          },\n        ]}\n      >\n        <ChartsGrid vertical />\n        <ChartsReferenceLine\n          x={0}\n          label=\"No effect\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"6 4\", strokeWidth: 1.5 }}\n          labelStyle={{ fontSize: 13, fill: t.inkSoft }}\n        />\n        <PointEstimates />\n        <ChartsXAxis axisId=\"effect-size\" />\n        <ChartsYAxis axisId=\"site\" disableTicks />\n      </ChartContainer>\n    </div>\n  );\n}\n"}