Mercurial
diff react_games/src/Games.tsx @ 37:fb9bcd3145cb
[ReactGames] Few games I made using react just to practice few things.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 01 Dec 2025 20:22:47 -0800 |
| parents | |
| children | 49b611c808e7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/react_games/src/Games.tsx Mon Dec 01 20:22:47 2025 -0800 @@ -0,0 +1,147 @@ +import ReactDOM from 'react-dom/client'; +import React, { CSSProperties, lazy, LazyExoticComponent, Suspense, useEffect, useState } from "react"; + +const LazyTicTacToe = lazy(() => import("./Tictactoe/main.tsx").then(m => ({ default: m.TicTacToe }))); +const LazyConnectFour = lazy(() => import("./Connectfour/main.tsx").then(m => ({ default: m.ConnectFour }))); +const LazyMemoryGame = lazy(() => import("./CardMatchiing/main.tsx").then(m => ({ default: m.MemoryGame }))); +const LazyLightsOut = lazy(() => import("./LightsOut/main.tsx").then(m => ({ default: m.LightsOut }))); +const LazyWordle = lazy(() => import("./Wordle/main.tsx").then(m => ({ default: m.Wordle }))); +const LazyMinesweeper = lazy(() => import("./Minesweeper/main.tsx").then(m => ({ default: m.Minesweeper }))); + + + +const wrapperStyle: CSSProperties = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + minHeight: '100vh', + fontFamily: 'system-ui, sans-serif', +}; + +const menuStyle: CSSProperties = { + listStyle: 'none', + padding: 0, + margin: '2rem auto', + width: 280, + display: 'flex', + flexDirection: 'column', + gap: '1rem', + cursor: 'pointer', +}; + +const menuItemStyle: CSSProperties = { + padding: '0.75rem 1rem', + borderRadius: 8, + background: '#f3f4f6', + textAlign: 'center', + transition: 'background 120ms', +}; + +type ComponentLabels = + | "tictactoe" + | "connectfour" + | "memorygame" + | "lightsout" + | "wordle" + | "minesweeper" + +interface ComponentData { + LazyComponent: LazyExoticComponent<() => React.ReactNode>; + title: string; +} + +const gameMap: (Record<ComponentLabels, ComponentData>) = { + tictactoe: { + LazyComponent: LazyTicTacToe, + title: "TicTacToe", + }, + connectfour: { + LazyComponent: LazyConnectFour, + title: "Connect Four", + }, + memorygame: { + LazyComponent: LazyMemoryGame, + title: "Memory Game", + }, + lightsout: { + LazyComponent: LazyLightsOut, + title: "Lights out", + }, + wordle: { + LazyComponent: LazyWordle, + title: "Wordle", + }, + minesweeper: { + LazyComponent: LazyMinesweeper, + title: "Minesweeper", + }, +} + +type GameKey = ComponentLabels | null; + +const BASE = "/games"; +const Games = () => { + const getKey = (p: string): GameKey => { + const m = p.match(/^\/games\/?([^/]+)?/i); + const k = (m?.[1] || '').toLowerCase() as GameKey; + return k && k in gameMap ? k : null; + }; + + const [game, setGame] = useState<GameKey>(() => getKey(location.pathname)); + + useEffect(() => { + const onPop = () => setGame(getKey(location.pathname)); + addEventListener('popstate', onPop); + return () => removeEventListener('popstate', onPop); + }, []); + + useEffect(() => { + history.pushState(null, '', game ? `${BASE}/${game}` : BASE); + }, [game]); + + const selected = game ? gameMap[game] : null; + + return ( + <main style={wrapperStyle}> + <section> + <h1 style={{ textAlign: "center" }}>MAI React Playground</h1> + + {selected?.LazyComponent ? ( + <Suspense fallback={<div>loading...</div>}> + <div style={ + { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + gap: 10, + }}> + <selected.LazyComponent /> + </div> + </Suspense> + ) : ( + <ul style={menuStyle}> + {Object.entries(gameMap).map(([key, value]) => ( + <li key={key} style={menuItemStyle} onClick={() => setGame(key as GameKey)}> + {value.title} + </li> + ))} + </ul> + )} + + {game && ( + <button style={{ display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "cetner", margin: "1.5rem auto 0" }} onClick={() => setGame(null)}> + Back to menu + </button> + )} + + </section> + </main> + ); +}; + +export { + Games, +} + +ReactDOM.createRoot(document.getElementById('root')!).render(<Games />);