diff --git a/example/src/GameOverlay.tsx b/example/src/GameOverlay.tsx deleted file mode 100755 index d9d8c59..0000000 --- a/example/src/GameOverlay.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import type { GameStatus } from "@vimazing/vim-maze"; -import type { UseScoreType } from "@vimazing/vim-maze"; -import { useIsMobile } from "./useIsMobile"; -import { MobileGameOverlay } from "./MobileGameOverlay"; - -type GameOverlayProps = { - gameStatus: GameStatus; - scoreManager: UseScoreType; -}; - -export const GameOverlay = ({ gameStatus, scoreManager }: GameOverlayProps) => { - const isMobile = useIsMobile(); - if (isMobile) return - - // 🧠 Only show overlay when the game has ended - if (['started', 'hasKey'].includes(gameStatus)) return null; - // console.log('gameStatus:', gameStatus) - - return ( - - {gameStatus === "waiting" && } - {gameStatus === "game-over" && } - {gameStatus === "game-won" && } - - ); -}; - -export const GameWaitingContent = () => { - return ( -
-
-

Press i to play...

-

h,j,k,l to move around

-

try other vim motions
you're familiar with

-

- $,^,0,G,gg only valid if
- the edges are reachable -

-
-
- ); -}; - -export const GameWonContent = ({ scoreManager }: { scoreManager: UseScoreType }) => { - const finalScore = scoreManager.finalScore ?? 0; - - return ( -
-

Congratulations!

-

Final Score:

-

{finalScore.toLocaleString()}

-

- min - ( - 100000 - , ( - optimalTime - / - actualTime - ) * - 100000 - ) -

-

Press i to play again

-
- ); -}; - -export const GameOverContent = () => { - return ( -
-

Game Over

-

Press i to play again

-
- ); -}; - -export const GameOverlayContainer = ({ - children, -}: { - children: React.ReactNode; -}) => { - return ( -
- {children} -
- ); -}; - - - diff --git a/example/src/MobileGameOverlay.tsx b/example/src/MobileGameOverlay.tsx deleted file mode 100755 index f804e3f..0000000 --- a/example/src/MobileGameOverlay.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import type { GameStatus } from "@vimazing/vim-maze"; -import type { UseScoreType } from "@vimazing/vim-maze"; - -type MobileGameOverlayProps = { - gameStatus: GameStatus; - scoreManager: UseScoreType; -}; - -export const MobileGameOverlay = ({ gameStatus, scoreManager }: MobileGameOverlayProps) => { - // 🧠 Only show overlay when the game has ended - if (['started', 'hasKey'].includes(gameStatus)) return null; - // console.log('gameStatus:', gameStatus) - - return ( - - {gameStatus === "waiting" && } - {gameStatus === "game-over" && } - {gameStatus === "game-won" && } - - ); -}; - -export const GameWaitingContent = () => { - return ( -
-
-

Press here to play

-

all the vim motions
available on desktop

-
-
- ); -}; - -export const GameWonContent = ({ scoreManager }: { scoreManager: UseScoreType }) => { - const finalScore = scoreManager.finalScore ?? 0; - - return ( -
-

Congratulations!

-

Final Score:

-

{finalScore.toLocaleString()}

-

- min - ( - 100000 - , ( - optimalTime - / - actualTime - ) * - 100000 - ) -

-

Press to play again

-
- ); -}; - -export const GameOverContent = () => { - return ( -
- Game Over -
- ); -}; - -export const GameOverlayContainer = ({ - children, -}: { - children: React.ReactNode; -}) => { - return ( -
- {children} -
- ); -}; - - diff --git a/example/src/testStateMachines.ts b/example/src/testStateMachines.ts deleted file mode 100644 index 7edbd77..0000000 --- a/example/src/testStateMachines.ts +++ /dev/null @@ -1,167 +0,0 @@ -import type { GameMode } from '@vimazing/typing-chud'; - -export type ModeTransition = { - fromMode: GameMode; - threshold: number; - targetMode: GameMode; - description: string; -}; - -export type ScoreTransition = { - scoreThreshold: number; - targetMode: GameMode; - description: string; -}; - -export type TestScenario = { - id: string; - name: string; - description: string; - initialMode: GameMode; - transitions?: ModeTransition[]; - scoreTransitions?: ScoreTransition[]; -}; - -export const testScenarios: Record = { - scoreBasedProgression: { - id: 'scoreBasedProgression', - name: 'Score-Based Progression', - description: 'Change modes based on score: score 10 → words, score 50 → sentences, score 100 → paragraphs. Tests delayed application until current item completes.', - initialMode: 'letters', - scoreTransitions: [ - { - scoreThreshold: 10, - targetMode: 'words', - description: 'At score 10, request switch to words', - }, - { - scoreThreshold: 50, - targetMode: 'sentences', - description: 'At score 50, request switch to sentences', - }, - { - scoreThreshold: 100, - targetMode: 'paragraphs', - description: 'At score 100, request switch to paragraphs', - }, - ], - }, - - progressive: { - id: 'progressive', - name: 'Progressive Mode Ladder', - description: 'Automatically progress through all modes: 10 letters → 10 words → 5 sentences → 3 paragraphs', - initialMode: 'letters', - transitions: [ - { - fromMode: 'letters', - threshold: 10, - targetMode: 'words', - description: 'After 10 letters, switch to words', - }, - { - fromMode: 'words', - threshold: 10, - targetMode: 'sentences', - description: 'After 10 words, switch to sentences', - }, - { - fromMode: 'sentences', - threshold: 5, - targetMode: 'paragraphs', - description: 'After 5 sentences, switch to paragraphs', - }, - ], - }, - - lettersOnly: { - id: 'lettersOnly', - name: 'Letters Only', - description: 'Stay in letters mode (baseline)', - initialMode: 'letters', - transitions: [], - }, - - wordsOnly: { - id: 'wordsOnly', - name: 'Words Only', - description: 'Start in words mode (baseline)', - initialMode: 'words', - transitions: [], - }, - - sentencesOnly: { - id: 'sentencesOnly', - name: 'Sentences Only', - description: 'Start in sentences mode (baseline)', - initialMode: 'sentences', - transitions: [], - }, - - paragraphsOnly: { - id: 'paragraphsOnly', - name: 'Paragraphs Only', - description: 'Start in paragraphs mode (baseline)', - initialMode: 'paragraphs', - transitions: [], - }, - - rapidTransitions: { - id: 'rapidTransitions', - name: 'Rapid Transitions', - description: 'Quick transitions: 3 letters → 3 words → 2 sentences → 1 paragraph', - initialMode: 'letters', - transitions: [ - { - fromMode: 'letters', - threshold: 3, - targetMode: 'words', - description: 'After 3 letters, switch to words', - }, - { - fromMode: 'words', - threshold: 3, - targetMode: 'sentences', - description: 'After 3 words, switch to sentences', - }, - { - fromMode: 'sentences', - threshold: 2, - targetMode: 'paragraphs', - description: 'After 2 sentences, switch to paragraphs', - }, - ], - }, - - backAndForth: { - id: 'backAndForth', - name: 'Back and Forth', - description: 'Oscillate between modes: 5 letters ↔ 5 words ↔ 5 letters', - initialMode: 'letters', - transitions: [ - { - fromMode: 'letters', - threshold: 5, - targetMode: 'words', - description: 'After 5 letters, switch to words', - }, - { - fromMode: 'words', - threshold: 5, - targetMode: 'letters', - description: 'After 5 words, switch back to letters', - }, - ], - }, -}; - -export function getScenario(id: string): TestScenario { - return testScenarios[id] || testScenarios.progressive; -} - -export function getScenarioNames(): { id: string; name: string }[] { - return Object.entries(testScenarios).map(([id, scenario]) => ({ - id, - name: scenario.name, - })); -} diff --git a/example/src/useIsMobile.ts b/example/src/useIsMobile.ts deleted file mode 100755 index 6b77170..0000000 --- a/example/src/useIsMobile.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from "react"; - -const MOBILE_BREAKPOINT = 768; - -export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState( - typeof window !== "undefined" - ? window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`).matches - : false - ); - - React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); - - const onChange = (event: MediaQueryListEvent) => { - setIsMobile(event.matches); - }; - - // Set initial value - setIsMobile(mql.matches); - - // Add listener - mql.addEventListener("change", onChange); - - // Cleanup - return () => mql.removeEventListener("change", onChange); - }, []); - - return isMobile; -} diff --git a/example/src/useKeyBindings.ts b/example/src/useKeyBindings.ts deleted file mode 100755 index 641ebf1..0000000 --- a/example/src/useKeyBindings.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { useEffect } from "react"; -import type { GameManager } from "../../src"; - -export const useKeyBindings = (gameManager: GameManager) => { - useEffect(() => { - const handler = (ev: KeyboardEvent) => { - // start game - if (ev.code === "Space") { - ev.preventDefault(); // Prevent button activation - if (["waiting", "game-over", "game-won"].includes(gameManager.gameStatus)) { - gameManager.clearKeyLog(); - gameManager.renderBoard(); - if (gameManager.gameStatus === "game-over" || gameManager.gameStatus === "game-won") { - gameManager.quitGame(); - setTimeout(() => gameManager.startGame(), 0); - } else { - gameManager.startGame(); - } - return; - } - } - - // ignore other keys while waiting - if (gameManager.gameStatus === "waiting") return; - - // quit - if (ev.key === "Escape") { - ev.preventDefault(); - gameManager.quitGame(); - return; - } - - // handle letter and punctuation typing during game - if (gameManager.gameStatus === "started") { - if (ev.key.length === 1 && /[a-zA-Z.,!? ]/.test(ev.key)) { - gameManager.handleTypedLetter(ev.key); - } - } - }; - - window.addEventListener("keydown", handler); - return () => window.removeEventListener("keydown", handler); - }, [gameManager.gameStatus]); -}; - diff --git a/example/src/useMounted.ts b/example/src/useMounted.ts deleted file mode 100755 index 7da354e..0000000 --- a/example/src/useMounted.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useState, useEffect } from 'react'; - -export const useMounted = () => { - const [mounted, setMounted] = useState(false); - - useEffect(() => { - setMounted(true); - }, []); - - return mounted; -};