/ concept-collection / ans-visualizer
Sign in
concept-collection / ans-visualizer
ans-visualizer / src / App.tsx
97 lines · 3.0 KBBlameHistoryRaw
1import { useState, useEffect } from 'react';
2import { Container, Typography, Box, CssBaseline, ThemeProvider, createTheme, Paper } from '@mui/material';
3import ReactMarkdown from 'react-markdown';
4import remarkMath from 'remark-math';
5import rehypeKatex from 'rehype-katex';
6import 'katex/dist/katex.min.css';
7import MobileWarning from './components/MobileWarning';
8import FrequencyInput from './components/FrequencyInput';
9import StateGrid from './components/StateGrid';
10import type { Symbol } from './types';
11import { isMobileDevice } from './utils/deviceDetection';
12import { getDefaultColors } from './utils/ansLogic';
13import explanationText from './explanation.md?raw';
15const theme = createTheme({
16 palette: {
17 mode: 'light',
18 primary: {
19 main: '#1976d2',
20 },
21 },
22});
24function App() {
25 const [isMobile, setIsMobile] = useState(false);
26 const [symbols, setSymbols] = useState<Symbol[]>([]);
28 useEffect(() => {
29 // Check if mobile
30 setIsMobile(isMobileDevice());
32 // Initialize with default symbols: A-1, B-1, C-1
33 const defaultColors = getDefaultColors();
34 const defaultSymbols: Symbol[] = [
35 { name: 'A', frequency: 3, color: defaultColors[0] },
36 { name: 'B', frequency: 2, color: defaultColors[1] },
37 { name: 'C', frequency: 1, color: defaultColors[2] },
38 ];
39 setSymbols(defaultSymbols);
41 // Re-check on resize
42 const handleResize = () => {
43 setIsMobile(isMobileDevice());
44 };
45 window.addEventListener('resize', handleResize);
46 return () => window.removeEventListener('resize', handleResize);
47 }, []);
49 if (isMobile) {
50 return (
51 <ThemeProvider theme={theme}>
52 <CssBaseline />
53 <MobileWarning />
54 </ThemeProvider>
55 );
56 }
58 return (
59 <ThemeProvider theme={theme}>
60 <CssBaseline />
61 <Container maxWidth="xl" sx={{ py: 2 }}>
62 <Box sx={{ mb: 2 }}>
63 <Typography variant="h4" component="h1" gutterBottom>
64 ANS Visualizer
65 </Typography>
66 <Typography variant="body2" color="text.secondary">
67 Illustration of the Asymmetric Numeral Systems algorithm. Duda et al., 2015.{' '}
68 <a href="https://ieeexplore.ieee.org/abstract/document/7170048" target="_blank" rel="noopener noreferrer">
69 [Link to paper]
70 </a>
71 </Typography>
72 </Box>
74 <Box sx={{ display: 'flex', gap: 3 }}>
75 <Box sx={{ flex: 1 }}>
76 <FrequencyInput symbols={symbols} onSymbolsChange={setSymbols} />
78 <Paper sx={{ p: 2, mt: 3, maxHeight: '600px', overflowY: 'auto' }}>
79 <ReactMarkdown
80 remarkPlugins={[remarkMath]}
81 rehypePlugins={[rehypeKatex]}
82 >
83 {explanationText}
84 </ReactMarkdown>
85 </Paper>
86 </Box>
88 <Box sx={{ flex: 1 }}>
89 <StateGrid symbols={symbols} />
90 </Box>
91 </Box>
92 </Container>
93 </ThemeProvider>
94 );
97export default App;
moveopenescclose