ui(age-four): 💄 Update root component rendering to use React 18’s createRoot and enhance Vite environment variable typing for compatibility
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
68ab6d6dc1
commit
673a2dccae
3 changed files with 0 additions and 293 deletions
|
|
@ -1,280 +0,0 @@
|
|||
import { lazy, Suspense, useState, useCallback, useMemo, type ReactElement } from 'react'
|
||||
import { Routes, Route, Navigate, useSearchParams } from 'react-router-dom'
|
||||
import styled from 'styled-components'
|
||||
import { ThemeProvider } from '@lilith/ui-theme'
|
||||
import { GuideLayout } from '@/components/layout/GuideLayout'
|
||||
import { WelcomeModal } from '@/components/welcome/WelcomeModal'
|
||||
import { EncyclopediaModal } from '@/components/EncyclopediaModal'
|
||||
import { usePlayerPreferences, type PlayerPreferences, type ColorMode, type FontSize, FONT_SIZE_PX } from '@/hooks/usePlayerPreferences'
|
||||
import { PreferencesProvider, usePreferences, usePreferencesReroll, type ConcreteRace, type ConcreteGender } from '@/contexts/PreferencesContext'
|
||||
import { getThemeForPreferences } from '@/theme/fantasy-theme'
|
||||
|
||||
// The Map
|
||||
const TerrainPage = lazy(() => import('@/pages/TerrainPage'))
|
||||
const ResourcesPage = lazy(() => import('@/pages/ResourcesPage'))
|
||||
const MapTypesPage = lazy(() => import('@/pages/MapTypesPage'))
|
||||
|
||||
// Climate & Survival
|
||||
const ClimateOverviewPage = lazy(() => import('@/pages/ClimateOverviewPage'))
|
||||
const ClimateEventsPage = lazy(() => import('@/pages/ClimateEventsPage'))
|
||||
const ClimateTerrainPage = lazy(() => import('@/pages/ClimateTerrainPage'))
|
||||
const ClimateSimulationPage = lazy(() => import('@/pages/ClimateSimulationPage'))
|
||||
const SurvivalGuidePage = lazy(() => import('@/pages/SurvivalGuidePage'))
|
||||
const EcosystemPage = lazy(() => import('@/pages/EcosystemPage'))
|
||||
const BiomeBrowserPage = lazy(() => import('@/pages/BiomeBrowserPage'))
|
||||
const SpeciesBrowserPage = lazy(() => import('@/pages/SpeciesBrowserPage'))
|
||||
const FoodWebPage = lazy(() => import('@/pages/FoodWebPage'))
|
||||
const PopulationDashboardPage = lazy(() => import('@/pages/PopulationDashboardPage'))
|
||||
|
||||
// Races & Empire
|
||||
const RacesPage = lazy(() => import('@/pages/RacesPage'))
|
||||
const GovernmentPage = lazy(() => import('@/pages/GovernmentPage'))
|
||||
const ErasPage = lazy(() => import('@/pages/ErasPage'))
|
||||
const VictoryPage = lazy(() => import('@/pages/VictoryPage'))
|
||||
|
||||
// Research
|
||||
const TechTreePage = lazy(() => import('@/pages/TechTreePage'))
|
||||
const MagicSchoolsPage = lazy(() => import('@/pages/MagicSchoolsPage'))
|
||||
const DisciplinesPage = lazy(() => import('@/pages/DisciplinesPage'))
|
||||
|
||||
// Military
|
||||
const UnitsPage = lazy(() => import('@/pages/UnitsPage'))
|
||||
const CombatPage = lazy(() => import('@/pages/CombatPage'))
|
||||
const KeywordsPage = lazy(() => import('@/pages/KeywordsPage'))
|
||||
const PromotionsPage = lazy(() => import('@/pages/PromotionsPage'))
|
||||
const ItemsPage = lazy(() => import('@/pages/ItemsPage'))
|
||||
|
||||
// Building Your Empire
|
||||
const BuildingsPage = lazy(() => import('@/pages/BuildingsPage'))
|
||||
const ImprovementsPage = lazy(() => import('@/pages/ImprovementsPage'))
|
||||
const WondersPage = lazy(() => import('@/pages/WondersPage'))
|
||||
const CommunicationsPage = lazy(() => import('@/pages/CommunicationsPage'))
|
||||
|
||||
// Magic
|
||||
const SpellsPage = lazy(() => import('@/pages/SpellsPage'))
|
||||
const ArchonsPage = lazy(() => import('@/pages/ArchonsPage'))
|
||||
const LeyLinesPage = lazy(() => import('@/pages/LeyLinesPage'))
|
||||
|
||||
// Intro
|
||||
const HomePage = lazy(() => import('@/pages/HomePage'))
|
||||
const EarlyAccessPage = lazy(() => import('@/pages/EarlyAccessPage'))
|
||||
const EarlyAccessProgressPage = lazy(() => import('@/pages/EarlyAccessProgressPage'))
|
||||
const FullGamePage = lazy(() => import('@/pages/FullGamePage'))
|
||||
const ExpansionsPage = lazy(() => import('@/pages/ExpansionsPage'))
|
||||
const ToolsPage = lazy(() => import('@/pages/ToolsPage'))
|
||||
|
||||
// About
|
||||
const CrowdfundPage = lazy(() => import('@/pages/CrowdfundPage'))
|
||||
const TeamPage = lazy(() => import('@/pages/TeamPage'))
|
||||
const EncyclopediaPage = lazy(() => import('@/pages/EncyclopediaPage'))
|
||||
|
||||
// Dev tools (no nav entry — URL only)
|
||||
const DevSpritesPage = lazy(() => import('@/pages/DevSpritesPage'))
|
||||
|
||||
const DEFAULT_PREFS: PlayerPreferences = { race: 'random', gender: 'random', name: '', colorMode: 'dark', dyslexicFont: false, fontSize: 'md' }
|
||||
|
||||
export default function App(): ReactElement {
|
||||
const { preferences, isFirstVisit, save } = usePlayerPreferences()
|
||||
const [searchParams] = useSearchParams()
|
||||
const skipWelcome = searchParams.get('skip') === 'welcome'
|
||||
const forceWelcome = searchParams.get('showWelcome') === 'true'
|
||||
const noGui = (searchParams.get('noGui') ?? searchParams.get('nogui')) === 'true'
|
||||
const [showWelcome, setShowWelcome] = useState((isFirstVisit || forceWelcome) && !skipWelcome)
|
||||
|
||||
const activePrefs = useMemo<PlayerPreferences>(
|
||||
() => preferences ?? DEFAULT_PREFS,
|
||||
[preferences],
|
||||
)
|
||||
|
||||
const routes = (
|
||||
<Suspense fallback={null}>
|
||||
<Routes>
|
||||
<Route index element={<HomePage />} />
|
||||
|
||||
{/* Intro */}
|
||||
<Route path="/early-access" element={<EarlyAccessPage />} />
|
||||
<Route path="/early-access/progress" element={<EarlyAccessProgressPage />} />
|
||||
<Route path="/full-game" element={<FullGamePage />} />
|
||||
<Route path="/expansions" element={<ExpansionsPage />} />
|
||||
<Route path="/tools" element={<ToolsPage />} />
|
||||
|
||||
{/* About */}
|
||||
<Route path="/crowdfund" element={<CrowdfundPage />} />
|
||||
<Route path="/team" element={<TeamPage />} />
|
||||
<Route path="/encyclopedia" element={<EncyclopediaPage />} />
|
||||
<Route path="/encyclopedia/:topicId" element={<EncyclopediaPage />} />
|
||||
|
||||
{/* The Map */}
|
||||
<Route path="/terrain" element={<TerrainPage />} />
|
||||
<Route path="/resources" element={<ResourcesPage />} />
|
||||
<Route path="/map-types" element={<MapTypesPage />} />
|
||||
|
||||
{/* Climate & Survival */}
|
||||
<Route path="/climate" element={<ClimateOverviewPage />} />
|
||||
<Route path="/climate/weather" element={<ClimateEventsPage />} />
|
||||
<Route path="/climate/terrain" element={<ClimateTerrainPage />} />
|
||||
<Route path="/climate/simulation" element={<ClimateSimulationPage />} />
|
||||
<Route path="/climate/survival" element={<SurvivalGuidePage />} />
|
||||
<Route path="/climate/ecosystem" element={<EcosystemPage />} />
|
||||
<Route path="/climate/ecosystem/biomes" element={<BiomeBrowserPage />} />
|
||||
<Route path="/climate/ecosystem/species" element={<SpeciesBrowserPage />} />
|
||||
<Route path="/climate/ecosystem/food-web" element={<FoodWebPage />} />
|
||||
<Route path="/climate/ecosystem/populations" element={<PopulationDashboardPage />} />
|
||||
{/* Redirects for old climate routes */}
|
||||
<Route path="/climate/temperature" element={<Navigate to="/climate" replace />} />
|
||||
<Route path="/climate/moisture" element={<Navigate to="/climate/terrain" replace />} />
|
||||
<Route path="/climate/events" element={<Navigate to="/climate/weather" replace />} />
|
||||
<Route path="/climate/parameters" element={<Navigate to="/climate" replace />} />
|
||||
|
||||
{/* Races & Empire */}
|
||||
<Route path="/races" element={<RacesPage />} />
|
||||
<Route path="/government" element={<GovernmentPage />} />
|
||||
<Route path="/eras" element={<ErasPage />} />
|
||||
<Route path="/victory" element={<VictoryPage />} />
|
||||
|
||||
{/* Research */}
|
||||
<Route path="/tech-tree" element={<TechTreePage />} />
|
||||
<Route path="/magic-schools" element={<MagicSchoolsPage />} />
|
||||
<Route path="/disciplines" element={<DisciplinesPage />} />
|
||||
|
||||
{/* Military */}
|
||||
<Route path="/units" element={<UnitsPage />} />
|
||||
<Route path="/combat" element={<CombatPage />} />
|
||||
<Route path="/keywords" element={<KeywordsPage />} />
|
||||
<Route path="/promotions" element={<PromotionsPage />} />
|
||||
<Route path="/items" element={<ItemsPage />} />
|
||||
|
||||
{/* Building Your Empire */}
|
||||
<Route path="/buildings" element={<BuildingsPage />} />
|
||||
<Route path="/improvements" element={<ImprovementsPage />} />
|
||||
<Route path="/wonders" element={<WondersPage />} />
|
||||
<Route path="/communications" element={<CommunicationsPage />} />
|
||||
|
||||
{/* Magic */}
|
||||
<Route path="/spells" element={<SpellsPage />} />
|
||||
<Route path="/archons" element={<ArchonsPage />} />
|
||||
<Route path="/ley-lines" element={<LeyLinesPage />} />
|
||||
|
||||
{/* Dev tools — no nav, URL only */}
|
||||
<Route path="/dev/sprites" element={<DevSpritesPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
)
|
||||
|
||||
if (noGui) {
|
||||
return (
|
||||
<PreferencesProvider preferences={activePrefs}>
|
||||
<RaceThemeProvider colorMode={activePrefs.colorMode} dyslexicFont={activePrefs.dyslexicFont}>
|
||||
<NoGuiShell>{routes}</NoGuiShell>
|
||||
<EncyclopediaModal />
|
||||
</RaceThemeProvider>
|
||||
</PreferencesProvider>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<PreferencesProvider preferences={activePrefs}>
|
||||
<AppShell save={save} showWelcome={showWelcome} setShowWelcome={setShowWelcome} preferences={activePrefs}>
|
||||
{routes}
|
||||
</AppShell>
|
||||
</PreferencesProvider>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── RaceThemeProvider ──────────────────────────────────────────────────────
|
||||
// Accepts optional preview overrides so the settings modal can live-preview
|
||||
// theme changes before confirming.
|
||||
|
||||
interface ThemePreview {
|
||||
race: ConcreteRace
|
||||
gender: ConcreteGender
|
||||
colorMode: ColorMode
|
||||
dyslexicFont: boolean
|
||||
fontSize: FontSize
|
||||
}
|
||||
|
||||
function RaceThemeProvider({ children, colorMode, dyslexicFont, preview }: {
|
||||
children: React.ReactNode
|
||||
colorMode: ColorMode
|
||||
dyslexicFont: boolean
|
||||
preview?: ThemePreview | null
|
||||
}): ReactElement {
|
||||
const { raceId, gender } = usePreferences()
|
||||
const themeOverrides = getThemeForPreferences(
|
||||
preview?.race ?? raceId,
|
||||
preview?.gender ?? gender,
|
||||
preview?.colorMode ?? colorMode,
|
||||
preview?.dyslexicFont ?? dyslexicFont,
|
||||
)
|
||||
|
||||
return (
|
||||
<ThemeProvider defaultTheme="luxe" customTheme={themeOverrides}>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── AppShell ───────────────────────────────────────────────────────────────
|
||||
|
||||
interface AppShellProps {
|
||||
save: (prefs: PlayerPreferences) => void
|
||||
showWelcome: boolean
|
||||
setShowWelcome: (v: boolean) => void
|
||||
preferences: PlayerPreferences
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
function AppShell({ save, showWelcome, setShowWelcome, preferences, children }: AppShellProps): ReactElement {
|
||||
const reroll = usePreferencesReroll()
|
||||
const [themePreview, setThemePreview] = useState<ThemePreview | null>(null)
|
||||
|
||||
const handleConfirm = useCallback((prefs: PlayerPreferences) => {
|
||||
save(prefs)
|
||||
setThemePreview(null)
|
||||
setShowWelcome(false)
|
||||
}, [save, setShowWelcome])
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setThemePreview(null)
|
||||
setShowWelcome(false)
|
||||
}, [setShowWelcome])
|
||||
|
||||
const handleOpenSettings = useCallback(() => {
|
||||
reroll()
|
||||
setShowWelcome(true)
|
||||
}, [reroll, setShowWelcome])
|
||||
|
||||
const handlePreview = useCallback((race: ConcreteRace, gender: ConcreteGender, colorMode: ColorMode, dyslexicFont: boolean, fontSize: FontSize) => {
|
||||
setThemePreview({ race, gender, colorMode, dyslexicFont, fontSize })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<RaceThemeProvider colorMode={preferences.colorMode} dyslexicFont={preferences.dyslexicFont} preview={themePreview}>
|
||||
{showWelcome && (
|
||||
<WelcomeModal
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleClose}
|
||||
onPreview={handlePreview}
|
||||
initialPreferences={preferences}
|
||||
/>
|
||||
)}
|
||||
<GuideLayout
|
||||
onOpenSettings={handleOpenSettings}
|
||||
fontSize={FONT_SIZE_PX[themePreview?.fontSize ?? preferences.fontSize ?? 'md']}
|
||||
>
|
||||
{children}
|
||||
</GuideLayout>
|
||||
<EncyclopediaModal />
|
||||
</RaceThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const NoGuiShell = styled.div`
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
background: #0D0B14;
|
||||
color: #e0dcd0;
|
||||
`
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
import App from './App'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</StrictMode>,
|
||||
)
|
||||
1
guide/age-of-four/src/vite-env.d.ts
vendored
1
guide/age-of-four/src/vite-env.d.ts
vendored
|
|
@ -1 +0,0 @@
|
|||
/// <reference types="vite/client" />
|
||||
Loading…
Add table
Reference in a new issue