diff --git a/plugins/minimap/web/CanvasMinimapPage.tsx b/plugins/minimap/web/CanvasMinimapPage.tsx index 33383810..7e1bbd1c 100644 --- a/plugins/minimap/web/CanvasMinimapPage.tsx +++ b/plugins/minimap/web/CanvasMinimapPage.tsx @@ -934,12 +934,41 @@ export default function CanvasMinimapPage() { // Set up keyboard and mouse event listeners (one-time setup) useEffect(() => { + const isTypingInInput = (): boolean => { + const activeElement = document.activeElement; + if (!activeElement) return false; + + const tagName = activeElement.tagName.toLowerCase(); + const inputTypes = ['input', 'textarea', 'select']; + const isContentEditable = activeElement.getAttribute('contenteditable') === 'true'; + + // Check if it's an input field or contenteditable element + if (inputTypes.includes(tagName) || isContentEditable) { + return true; + } + + // Check if it's an Ant Design Select dropdown (they use divs with specific classes) + if (activeElement.closest('.ant-select-dropdown') || + activeElement.closest('.ant-select-selector') || + activeElement.classList.contains('ant-select-selection-search-input')) { + return true; + } + + return false; + }; + const handleKeyDown = (e: KeyboardEvent) => { + // Don't handle keyboard shortcuts if user is typing in an input field + if (isTypingInInput()) { + return; + } + const key = e.key.toLowerCase(); // Track movement keys for smooth animation if (["w", "a", "s", "d"].includes(key)) { keysPressed.current.add(key); + e.preventDefault(); // Prevent default behavior (scrolling, etc.) return; } @@ -980,6 +1009,11 @@ export default function CanvasMinimapPage() { }; const handleKeyUp = (e: KeyboardEvent) => { + // Don't handle keyboard shortcuts if user is typing in an input field + if (isTypingInInput()) { + return; + } + const key = e.key.toLowerCase(); // Remove movement keys when released @@ -2141,88 +2175,242 @@ export default function CanvasMinimapPage() { - - {surfaceForceData.surfaces.map(surface => ( - - {surface} - - ))} - - - - - Timelapse: - - {isTimelapseMode && ( - - {availableTicks.length} snapshots - - )} - - - Chart Tags: - - {showChartTags && ( - - {getVisibleChartTags().length} visible - - )} - - - Recipes: - - {showRecipes && ( - {recipeCache.current.size} active - )} - - - Players: - - {showPlayerPositions && ( - {playerPositions.size} online - )} - - + title={ + + Factorio Instance Minimap + {selectedInstance && ( + + • {instances.get(selectedInstance)?.name || "Unknown Instance"} + + )} } + styles={{ + header: { padding: "16px 24px" }, + body: { padding: "16px 24px" }, + }} > + {/* Control Panel */} +
+ + {/* Instance Selection */} + + + INSTANCE + { + setSelectedSurface(value); + // Return focus to canvas after selection + setTimeout(() => { + if (canvasRef.current) { + canvasRef.current.focus(); + } + }, 100); + }} + disabled={!selectedInstance} + > + {surfaceForceData.surfaces.map(surface => ( + + {surface} + + ))} + + + + + + + {/* Display Options */} + + + DISPLAY OPTIONS +
+ {/* Timelapse Toggle */} +
+ Timelapse +
+ { + toggleTimelapseMode(checked); + }} + loading={loading} + disabled={!selectedInstance} + /> + + {isTimelapseMode ? `${availableTicks.length} snaps` : "Live"} + +
+
+ + {/* Chart Tags Toggle */} +
+ Chart Tags +
+ { + setShowChartTags(checked); + }} + disabled={!selectedInstance} + /> + + {showChartTags ? `${getVisibleChartTags().length} shown` : "Hidden"} + +
+
+ + {/* Recipes Toggle */} +
+ Recipes +
+ { + setShowRecipes(checked); + }} + disabled={!selectedInstance} + /> + + {showRecipes ? `${recipeCache.current.size} active` : "Hidden"} + +
+
+ + {/* Players Toggle */} +
+ Players +
+ { + setShowPlayerPositions(checked); + }} + disabled={!selectedInstance} + /> + + {showPlayerPositions ? `${playerPositions.size} online` : "Hidden"} + +
+
+
+
+ +
+
{selectedInstance ? (
{isTimelapseMode && availableTicks.length > 0 && ( @@ -2317,10 +2505,10 @@ export default function CanvasMinimapPage() {