diff --git a/apps/editor/components/editor.tsx b/apps/editor/components/editor.tsx
index e6347c5a..0365f853 100644
--- a/apps/editor/components/editor.tsx
+++ b/apps/editor/components/editor.tsx
@@ -7,7 +7,7 @@ import {
useScene,
WallNode,
} from "@pascal-app/core";
-import { Viewer } from "@pascal-app/viewer";
+import { useViewer, Viewer } from "@pascal-app/viewer";
import { Stats } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useMemo, useRef } from "react";
@@ -264,8 +264,8 @@ const Selector = () => {
};
const LevelModeSwitcher = () => {
- const setLevelMode = useScene((state) => state.setLevelMode);
- const levelMode = useScene((state) => state.levelMode);
+ const setLevelMode = useViewer((state) => state.setLevelMode);
+ const levelMode = useViewer((state) => state.levelMode);
return (
diff --git a/bun.lock b/bun.lock
index 67d0817c..0d9a67a7 100644
--- a/bun.lock
+++ b/bun.lock
@@ -7,6 +7,7 @@
"@react-three/drei": "^10",
"@react-three/fiber": "^9",
"three": "^0.182.0",
+ "zustand": "^5.0.10",
},
"devDependencies": {
"@biomejs/biome": "^2.3.11",
@@ -47,7 +48,6 @@
"mitt": "^3.0.1",
"nanoid": "^5.1.6",
"zod": "^4.3.5",
- "zustand": "^5.0.10",
},
"devDependencies": {
"@repo/typescript-config": "*",
diff --git a/package.json b/package.json
index 6f20998e..6eeaa96d 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,8 @@
"dependencies": {
"@react-three/drei": "^10",
"@react-three/fiber": "^9",
- "three": "^0.182.0"
+ "three": "^0.182.0",
+ "zustand": "^5.0.10"
},
"devDependencies": {
"@biomejs/biome": "^2.3.11",
diff --git a/packages/core/package.json b/packages/core/package.json
index bc6872dd..f1a09c67 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -25,7 +25,6 @@
"dedent": "^1.7.1",
"mitt": "^3.0.1",
"nanoid": "^5.1.6",
- "zod": "^4.3.5",
- "zustand": "^5.0.10"
+ "zod": "^4.3.5"
}
}
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index fc5dde13..d7b02c5d 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,5 +1,5 @@
// Store
-export { default as useScene } from "./store/useScene";
+export { default as useScene } from "./store/use-scene";
// Hooks
export {
@@ -8,7 +8,7 @@ export {
} from "./hooks/scene-registry/scene-registry";
// Systems
-export { LevelSystem } from "./systems/level/level-system";
+export { LevelSystem } from "../../viewer/src/systems/level/level-system";
export { WallSystem } from "./systems/wall/wall-system";
// Events
diff --git a/packages/core/src/store/useScene.ts b/packages/core/src/store/use-scene.ts
similarity index 92%
rename from packages/core/src/store/useScene.ts
rename to packages/core/src/store/use-scene.ts
index b8b766c4..4b7e1ef9 100644
--- a/packages/core/src/store/useScene.ts
+++ b/packages/core/src/store/use-scene.ts
@@ -20,9 +20,6 @@ type SceneState = {
loadScene: () => void;
markDirty: (id: AnyNodeId) => void;
clearDirty: (id: AnyNodeId) => void;
-
- levelMode: "stacked" | "exploded" | "solo" | "manual";
- setLevelMode: (mode: "stacked" | "exploded" | "solo" | "manual") => void;
};
const useScene = create()((set, get) => ({
@@ -117,9 +114,6 @@ const useScene = create()((set, get) => ({
clearDirty: (id) => {
get().dirtyNodes.delete(id);
},
-
- levelMode: "exploded",
- setLevelMode: (mode) => set({ levelMode: mode }),
}));
useScene.getState().loadScene();
diff --git a/packages/core/src/systems/wall/wall-system.tsx b/packages/core/src/systems/wall/wall-system.tsx
index e31cdfa5..eb6cdc40 100644
--- a/packages/core/src/systems/wall/wall-system.tsx
+++ b/packages/core/src/systems/wall/wall-system.tsx
@@ -2,7 +2,7 @@ import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { sceneRegistry } from "../../hooks/scene-registry/scene-registry";
import { AnyNode, WallNode } from "../../schema";
-import useScene from "../../store/useScene";
+import useScene from "../../store/use-scene";
export const WallSystem = () => {
const { nodes, dirtyNodes, clearDirty } = useScene();
diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json
index a47d5777..d2c35871 100644
--- a/packages/core/tsconfig.json
+++ b/packages/core/tsconfig.json
@@ -4,6 +4,6 @@
"outDir": "dist",
"rootDir": "src"
},
- "include": ["src"],
+ "include": ["src", "../viewer/src/systems/level"],
"exclude": ["node_modules", "dist"]
}
diff --git a/packages/viewer/src/index.ts b/packages/viewer/src/index.ts
index f9d9c119..fdc2b577 100644
--- a/packages/viewer/src/index.ts
+++ b/packages/viewer/src/index.ts
@@ -1 +1,3 @@
export { default as Viewer } from "./components/viewer/viewer";
+
+export { default as useViewer } from "./store/use-viewer";
diff --git a/packages/viewer/src/store/use-viewer.ts b/packages/viewer/src/store/use-viewer.ts
new file mode 100644
index 00000000..b247ea9a
--- /dev/null
+++ b/packages/viewer/src/store/use-viewer.ts
@@ -0,0 +1,21 @@
+"use client";
+
+import { LevelNode } from "@pascal-app/core";
+import { create } from "zustand";
+
+type ViewerState = {
+ levelMode: "stacked" | "exploded" | "solo" | "manual";
+ setLevelMode: (mode: "stacked" | "exploded" | "solo" | "manual") => void;
+
+ currentLevelId: LevelNode["id"] | null;
+ setCurrentLevelId: (id: LevelNode["id"] | null) => void;
+};
+
+const useViewer = create()((set, get) => ({
+ levelMode: "exploded",
+ setLevelMode: (mode) => set({ levelMode: mode }),
+ currentLevelId: null,
+ setCurrentLevelId: (id) => set({ currentLevelId: id }),
+}));
+
+export default useViewer;
diff --git a/packages/core/src/systems/level/level-system.tsx b/packages/viewer/src/systems/level/level-system.tsx
similarity index 75%
rename from packages/core/src/systems/level/level-system.tsx
rename to packages/viewer/src/systems/level/level-system.tsx
index 6b005030..cf3941ab 100644
--- a/packages/core/src/systems/level/level-system.tsx
+++ b/packages/viewer/src/systems/level/level-system.tsx
@@ -1,15 +1,14 @@
+import { LevelNode, sceneRegistry, useScene } from "@pascal-app/core";
import { useFrame } from "@react-three/fiber";
import { lerp } from "three/src/math/MathUtils.js";
-import { sceneRegistry } from "../../hooks/scene-registry/scene-registry";
-import { LevelNode } from "../../schema";
-import useScene from "../../store/useScene";
+import useViewer from "../../store/use-viewer";
const LEVEL_HEIGHT = 2.5;
const EXPLODED_GAP = 5;
export const LevelSystem = () => {
useFrame((_, delta) => {
- const levelMode = useScene.getState().levelMode;
+ const levelMode = useViewer.getState().levelMode;
sceneRegistry.byType.level.forEach((levelId) => {
const obj = sceneRegistry.nodes.get(levelId);
if (obj) {