{"spec_id":"line-filled","library":"muix","language":"javascript","code":"// anyplot.ai\n// line-filled: Filled Line Plot\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 84/100 | Created: 2026-09-05\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic LCG PRNG — no fetch, no Math.random) ----\nlet seed = 11;\nfunction rand() {\n  seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n  return seed / 0x7fffffff;\n}\n\nconst DAYS = 60;\nconst startDate = new Date(2026, 0, 5); // Mon Jan 5, 2026\nconst dates: Date[] = [];\nconst visitors: number[] = [];\nconst baseVisitors = 3200; // pre-launch daily unique visitors\nconst dailyGrowth = 0.013; // sustained lift from a content-marketing push\n\nfor (let i = 0; i < DAYS; i++) {\n  const date = new Date(startDate);\n  date.setDate(startDate.getDate() + i);\n  dates.push(date);\n\n  const weekday = date.getDay();\n  const weekendDip = weekday === 0 || weekday === 6 ? 0.7 : 1;\n  const trend = 1 + i * dailyGrowth;\n  const noise = 1 + (rand() - 0.5) * 0.16;\n  visitors.push(Math.round(baseVisitors * trend * weekendDip * noise));\n}\nconst avgVisitors = Math.round(visitors.reduce((sum, v) => sum + v, 0) / visitors.length);\n\nconst TITLE = \"Website Traffic Growth · line-filled · javascript · muix · anyplot.ai\";\n\n// --- Chart (default-exported component — the harness mounts it) -----------\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n  const titleSize = TITLE.length > 67 ? Math.max(14, Math.round((22 * 67) / TITLE.length)) : 22;\n\n  const TITLE_H = 64;\n  const chartH = H - TITLE_H;\n  // MUI X's y-axis `label` offsets itself from a hardcoded tickFontSize guess\n  // rather than the tick labels' real measured width, so a 4-digit tick\n  // (\"3,000\") collides with it. A hand-rotated label in its own flex column\n  // sidesteps that and gives predictable, collision-free spacing.\n  const yLabelWidth = 40;\n  const chartW = W - yLabelWidth;\n\n  return (\n    <Box\n      sx={{\n        width: W,\n        height: H,\n        bgcolor: t.pageBg,\n        display: \"flex\",\n        flexDirection: \"column\",\n        fontFamily: \"'Roboto', 'Helvetica Neue', Arial, sans-serif\",\n        boxSizing: \"border-box\",\n      }}\n    >\n      <Box sx={{ height: TITLE_H, display: \"flex\", alignItems: \"center\", justifyContent: \"center\" }}>\n        <Typography sx={{ color: t.ink, fontSize: titleSize, fontWeight: 600 }}>{TITLE}</Typography>\n      </Box>\n\n      <Box sx={{ display: \"flex\", flexDirection: \"row\", height: chartH }}>\n        <Box sx={{ width: yLabelWidth, display: \"flex\", alignItems: \"center\", justifyContent: \"center\" }}>\n          <Typography sx={{ fontSize: 15, color: t.ink, whiteSpace: \"nowrap\", transform: \"rotate(-90deg)\" }}>\n            Unique Visitors\n          </Typography>\n        </Box>\n\n        <LineChart\n          width={chartW}\n          height={chartH}\n          skipAnimation\n          series={[\n            {\n              id: \"visitors\",\n              data: visitors,\n              showMark: false,\n              area: true,\n              color: t.palette[0],\n              curve: \"monotoneX\",\n              valueFormatter: (v: number | null) => (v == null ? \"\" : `${v.toLocaleString(\"en-US\")} visitors`),\n            },\n          ]}\n          xAxis={[\n            {\n              data: dates,\n              scaleType: \"time\",\n              label: \"Date\",\n              valueFormatter: (d: Date) => d.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" }),\n              tickLabelStyle: { fontSize: 13, fill: t.inkSoft },\n              labelStyle: { fontSize: 15, fill: t.ink },\n            },\n          ]}\n          yAxis={[\n            {\n              valueFormatter: (v: number) => v.toLocaleString(\"en-US\"),\n              tickLabelStyle: { fontSize: 13, fill: t.inkSoft },\n            },\n          ]}\n          grid={{ horizontal: true }}\n          slotProps={{ legend: { hidden: true } }}\n          margin={{ top: 24, right: 40, bottom: 64, left: 66 }}\n          sx={{\n            \"& .MuiLineElement-root\": { strokeWidth: 3 },\n            \"& .MuiAreaElement-series-visitors\": { fill: \"url(#visitorsFillGradient)\" },\n            \"& .MuiChartsAxis-line\": { stroke: t.inkSoft, strokeOpacity: 0.4 },\n            \"& .MuiChartsAxis-tick\": { stroke: t.inkSoft, strokeOpacity: 0.4 },\n            \"& .MuiChartsGrid-line\": { stroke: t.grid },\n          }}\n        >\n          <defs>\n            <linearGradient id=\"visitorsFillGradient\" x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\">\n              <stop offset=\"5%\" stopColor={t.palette[0]} stopOpacity={0.75} />\n              <stop offset=\"95%\" stopColor={t.palette[0]} stopOpacity={0.05} />\n            </linearGradient>\n          </defs>\n          <ChartsReferenceLine\n            y={avgVisitors}\n            label={`Avg ${avgVisitors.toLocaleString(\"en-US\")}`}\n            labelAlign=\"end\"\n            lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"6 4\", strokeOpacity: 0.7 }}\n            labelStyle={{ fontSize: 12, fill: t.inkSoft }}\n          />\n        </LineChart>\n      </Box>\n    </Box>\n  );\n}\n"}