fix: resolve Three.js Text component error and modal close issues

- Downgrade three.js from 0.182 to 0.168 to fix customDepthMaterial
  getter-only property breaking change (drei issue #2403)
- Add stable useCallback for modal close handler to prevent
  reference instability
- Improve ESC key handler with ref pattern and capture phase
  to ensure reliable modal closing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-19 15:08:55 -05:00
parent 0e7b0aa44f
commit db070f47ee
4 changed files with 23 additions and 13 deletions

8
package-lock.json generated
View File

@ -60,7 +60,7 @@
"react-router-dom": "^7.0.2",
"recoil": "^0.7.7",
"sharp": "^0.33.5",
"three": "^0.182.0",
"three": "^0.168.0",
"tldraw": "^3.15.4",
"use-whisper": "^0.0.1",
"webcola": "^3.4.0"
@ -20865,9 +20865,9 @@
}
},
"node_modules/three": {
"version": "0.182.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.182.0.tgz",
"integrity": "sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==",
"version": "0.168.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.168.0.tgz",
"integrity": "sha512-6m6jXtDwMJEK/GGMbAOTSAmxNdzKvvBzgd7q8bE/7Tr6m7PaBh5kKLrN7faWtlglXbzj7sVba48Idwx+NRsZXw==",
"license": "MIT"
},
"node_modules/three-mesh-bvh": {

View File

@ -86,7 +86,7 @@
"react-router-dom": "^7.0.2",
"recoil": "^0.7.7",
"sharp": "^0.33.5",
"three": "^0.182.0",
"three": "^0.168.0",
"tldraw": "^3.15.4",
"use-whisper": "^0.0.1",
"webcola": "^3.4.0"

View File

@ -249,6 +249,11 @@ export function NetworkGraphMinimap({
const [selectedNode, setSelectedNode] = useState<{ node: GraphNode; x: number; y: number } | null>(null);
const [isConnecting, setIsConnecting] = useState(false);
// Stable callback for closing search modal (prevents ESC handler issues)
const handleCloseSearch = useCallback(() => {
setIsSearchOpen(false);
}, []);
// Three-state display mode: minimized, normal, maximized
const [displayMode, setDisplayMode] = useState<DisplayMode>(isCollapsed ? 'minimized' : 'normal');
@ -963,7 +968,7 @@ export function NetworkGraphMinimap({
<UserSearchModal
isOpen={isSearchOpen}
onClose={() => setIsSearchOpen(false)}
onClose={handleCloseSearch}
onConnect={onConnect}
onDisconnect={onDisconnect ? (userId) => {
// Find the connection ID for this user

View File

@ -256,19 +256,24 @@ export function UserSearchModal({
}
}, [onConnect, onDisconnect]);
// Handle escape key
// Handle escape key - use a ref to avoid stale closure issues
const onCloseRef = useRef(onClose);
onCloseRef.current = onClose;
useEffect(() => {
if (!isOpen) return;
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onClose();
e.preventDefault();
e.stopPropagation();
onCloseRef.current();
}
};
if (isOpen) {
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}
}, [isOpen, onClose]);
window.addEventListener('keydown', handleKeyDown, true); // Use capture phase
return () => window.removeEventListener('keydown', handleKeyDown, true);
}, [isOpen]);
if (!isOpen) return null;