diff --git a/src/components/DevPalette.tsx b/src/components/DevPalette.tsx
index 2186e62..96030ab 100644
--- a/src/components/DevPalette.tsx
+++ b/src/components/DevPalette.tsx
@@ -80,25 +80,18 @@ export function DevPalette() {
},
}
: null
- // Dev-only "mature island" preview — flips the sparse-by-default
- // Flowers/Tree/Butterflies views into showAll so we can see what a
- // saturated island looks like without scripting captures. Toggle off
- // restores the sparse state (only what the student has actually
- // earned through captures remains visible).
- const matureIsland: Command | null = import.meta.env.DEV
- ? {
- id: 'mature-island',
- label: matureIslandOn ? 'Hide mature island' : 'Show mature island',
- hint: 'dev preview',
- run: () => {
- setOpen(false)
- window.dispatchEvent(
- new CustomEvent('ss:mature-island-toggle', { detail: { on: !matureIslandOn } }),
- )
- setMatureIslandOn((v) => !v)
- },
- }
- : null
+ const matureIsland: Command = {
+ id: 'mature-island',
+ label: matureIslandOn ? 'Hide mature island' : 'Show mature island',
+ hint: 'island preview',
+ run: () => {
+ setOpen(false)
+ window.dispatchEvent(
+ new CustomEvent('ss:mature-island-toggle', { detail: { on: !matureIslandOn } }),
+ )
+ setMatureIslandOn((v) => !v)
+ },
+ }
return [
{ id: 'ui', label: 'Switch to UI mode', hint: '/', run: go('/') },
{
@@ -118,7 +111,7 @@ export function DevPalette() {
},
...(cameraTuner ? [cameraTuner] : []),
...(hatchTuner ? [hatchTuner] : []),
- ...(matureIsland ? [matureIsland] : []),
+ matureIsland,
{
id: 'restart-onboarding',
label: 'Restart onboarding',
diff --git a/src/components/student-space/EngineHost.tsx b/src/components/student-space/EngineHost.tsx
index 90da055..445fab0 100644
--- a/src/components/student-space/EngineHost.tsx
+++ b/src/components/student-space/EngineHost.tsx
@@ -279,7 +279,7 @@ export function EngineHost({
{showOnboardingFlow ? : null}
{import.meta.env.DEV && game ? : null}
- {import.meta.env.DEV && game ? : null}
+ {game ? : null}
{children}
@@ -292,12 +292,6 @@ export function EngineHost({
* static framing without a remount. The HUD itself is hidden until the
* palette dispatches CAMERA_TUNER_OPEN_EVENT.
*/
-/**
- * DEV-only bridge: listens for the dev palette's `ss:mature-island-toggle`
- * event and flips the sparse-by-default Flowers / Tree / Butterflies views
- * into showAll (or back to hidden — only what the student has earned by
- * capturing stays visible).
- */
function MatureIslandBridge({ game }: { game: Game }) {
useEffect(() => {
const view = (
diff --git a/test/components/DevPalette.test.tsx b/test/components/DevPalette.test.tsx
index 80d2f0b..f985dcc 100644
--- a/test/components/DevPalette.test.tsx
+++ b/test/components/DevPalette.test.tsx
@@ -63,7 +63,9 @@ beforeEach(() => {
afterEach(() => {
document.body.classList.remove('is-dev-overlay-hidden')
+ document.body.classList.remove('is-world-controls-visible')
navigate.mockClear()
+ vi.unstubAllEnvs()
Object.defineProperty(window.location, 'assign', {
configurable: true,
writable: true,
@@ -117,14 +119,35 @@ describe('DevPalette', () => {
render()
await user.keyboard('{Meta>}k{/Meta}')
+ await user.click(screen.getByRole('option', { name: /show world controls/i }))
+ expect(document.body).toHaveClass('is-world-controls-visible')
+ expect(localStorage.getItem('sm:world-controls-visible')).toBe('1')
+
+ await user.keyboard('{Meta>}k{/Meta}')
await user.click(screen.getByRole('option', { name: /hide world controls/i }))
- expect(document.body).toHaveClass('is-dev-overlay-hidden')
- expect(localStorage.getItem('sm:dev-overlay-hidden')).toBe('1')
+ expect(document.body).not.toHaveClass('is-world-controls-visible')
+ expect(localStorage.getItem('sm:world-controls-visible')).toBeNull()
+ })
+
+ it('keeps mature island preview available in production builds', async () => {
+ vi.stubEnv('DEV', false)
+ const user = userEvent.setup()
+ const matureIslandListener = vi.fn()
+ window.addEventListener('ss:mature-island-toggle', matureIslandListener)
+ render()
await user.keyboard('{Meta>}k{/Meta}')
- await user.click(screen.getByRole('option', { name: /show world controls/i }))
- expect(document.body).not.toHaveClass('is-dev-overlay-hidden')
- expect(localStorage.getItem('sm:dev-overlay-hidden')).toBeNull()
+ expect(screen.getByRole('option', { name: /show mature island/i })).toBeInTheDocument()
+ expect(screen.queryByRole('option', { name: /show camera tuner/i })).not.toBeInTheDocument()
+ expect(screen.queryByRole('option', { name: /show hatch tuner/i })).not.toBeInTheDocument()
+
+ await user.click(screen.getByRole('option', { name: /show mature island/i }))
+ expect(matureIslandListener).toHaveBeenCalledTimes(1)
+ expect(matureIslandListener.mock.calls[0]?.[0]).toMatchObject({
+ detail: { on: true },
+ })
+
+ window.removeEventListener('ss:mature-island-toggle', matureIslandListener)
})
it('restarts onboarding from Cmd-K without clearing the full student-space state', async () => {