{"spec_id":"streamgraph-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// streamgraph-basic: Basic Stream Graph\n// Library: muix 7.29.1 | JavaScript 22.23.1\n// Quality: 88/100 | Created: 2026-08-05\n\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Monthly listening hours (in thousands) by music genre, two years of data.\n\nconst MONTH_NAMES = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\nconst MONTHS_COUNT = 24;\nconst months = Array.from(\n  { length: MONTHS_COUNT },\n  (_, i) => `${MONTH_NAMES[i % 12]} ${2024 + Math.floor(i / 12)}`,\n);\n\n// Tiny fixed-seed LCG for reproducible micro-variation (no seeded RNG in the browser)\nlet seed = 42;\nfunction nextRandom() {\n  seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n  return seed / 0x7fffffff;\n}\n\n// Genre trajectories: Electronic and Hip-Hop grow steadily, Rock cools off,\n// Jazz and Classical decline slowly, Pop stays roughly flat.\nconst genres = [\n  { name: \"Pop\", base: 380, amp: 55, freq: 0.55, phase: 0.4, trend: 0.4 },\n  { name: \"Hip-Hop\", base: 300, amp: 70, freq: 0.45, phase: 2.1, trend: 5.5 },\n  { name: \"Electronic\", base: 190, amp: 60, freq: 0.65, phase: 4.0, trend: 8.5 },\n  { name: \"Rock\", base: 260, amp: 45, freq: 0.35, phase: 1.2, trend: -3.5 },\n  { name: \"Jazz\", base: 140, amp: 25, freq: 0.5, phase: 3.3, trend: -2.0 },\n  { name: \"Classical\", base: 100, amp: 18, freq: 0.4, phase: 5.1, trend: -1.2 },\n];\n\nconst genreValues = genres.map((g) =>\n  Array.from({ length: MONTHS_COUNT }, (_, i) => {\n    const wave = Math.sin(i * g.freq * 0.5 + g.phase) * g.amp;\n    const noise = (nextRandom() - 0.5) * g.amp * 0.3;\n    return Math.round(Math.max(30, g.base + g.trend * i + wave + noise));\n  }),\n);\n\nconst series = genres.map((g, idx) => ({\n  id: g.name,\n  label: g.name,\n  data: genreValues[idx],\n  area: true,\n  stack: \"listening\",\n  stackOrder: \"insideOut\" as const,\n  stackOffset: \"wiggle\" as const,\n  curve: \"catmullRom\" as const,\n  showMark: false,\n  color: t.palette[idx],\n}));\n\nconst TITLE = \"Genre Streaming Hours · streamgraph-basic · javascript · muix · anyplot.ai\";\nconst TITLE_FONT_SIZE = Math.max(15, Math.round(22 * Math.min(1, 67 / TITLE.length)));\nconst TITLE_HEIGHT = 60;\n\n// --- Chart (default-exported component — the harness mounts it) ------------\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n\n  return (\n    <Box\n      sx={{\n        width,\n        height,\n        display: \"flex\",\n        flexDirection: \"column\",\n      }}\n    >\n      <Typography\n        sx={{\n          color: t.ink,\n          fontSize: TITLE_FONT_SIZE,\n          fontWeight: 500,\n          textAlign: \"center\",\n          lineHeight: 1.2,\n          paddingTop: \"16px\",\n        }}\n      >\n        {TITLE}\n      </Typography>\n      <LineChart\n        width={width}\n        height={height - TITLE_HEIGHT}\n        skipAnimation\n        series={series}\n        xAxis={[\n          {\n            scaleType: \"point\",\n            data: months,\n            tickLabelInterval: (_value: string, index: number) => index % 3 === 0,\n            disableTicks: true,\n          },\n        ]}\n        leftAxis={null}\n        grid={{ horizontal: false, vertical: false }}\n        margin={{ left: 64, right: 24, top: 44, bottom: 56 }}\n        slotProps={{\n          legend: {\n            position: { vertical: \"top\", horizontal: \"middle\" },\n            direction: \"row\",\n            padding: { top: 0, bottom: 12 },\n          },\n        }}\n        sx={{\n          \"& .MuiChartsAxis-tickLabel\": { fontSize: \"14px\", fill: t.inkSoft },\n          \"& .MuiChartsLegend-label\": { fontSize: \"14px\" },\n          \"& .MuiAreaElement-root\": { fillOpacity: 0.92 },\n          \"& .MuiLineElement-root\": { strokeWidth: 1.5 },\n        }}\n      />\n    </Box>\n  );\n}\n"}