From a5c9aab71637fc50955711931f4115c5df691d43 Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Tue, 2 Jun 2026 02:26:52 +0200 Subject: [PATCH 01/13] Add URL query to load a trainer in the mapper by ID --- src/components/Mapper/Mapper.jsx | 47 ++++++++++++++++++++++++++++++++ src/utils/dex/index.js | 3 +- src/utils/dex/trainers.js | 20 ++++++++++++-- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 4b79870142..b59114f4db 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -19,6 +19,7 @@ import './style.css'; import { getAreaEncounters, getTrainersFromZoneId, + getZoneIdFromTrainerId, getFieldItemsFromZoneID, getHiddenItemsFromZoneID, getPokemonIdFromName @@ -158,6 +159,52 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { SELECT: "select", ENCOUNTER: "enc", } + + // Handle URL query parameters for trainer ID + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const trainerId = params.get('trainerId'); + + if (trainerId && canvasRef.current) { + const zoneId = getZoneIdFromTrainerId(trainerId, GAMEDATA3); + if (zoneId) { + const location = getLocationCoordsFromZoneId(zoneId); + if (location) { + // Select the location + if (previousRectangle.select !== null) { + clearRect(CLEAR_MODE.SELECT); + } + drawRect(location, CLEAR_MODE.SELECT); + previousRectangle.select = { x: location.x, y: location.y, width: location.width, height: location.height }; + locationId.current = location.zoneId; + setSelectedZone(location.name); + setSelectedZoneId(location.zoneId); + setEncounterList(setAllEncounters(location.zoneId)); + setTrainerList(getTrainersFromZoneId(location.zoneId, GAMEDATA3)); + setFieldItems(getFieldItemsFromZoneID(location.zoneId)); + setHiddenItems(getHiddenItemsFromZoneID(location.zoneId)); + setShopItems(getRegularShopItems(location.zoneId)); + setScriptItems(getScriptItems(location.zoneId)); + setFixedShops(getFixedShops(location.zoneId)); + setHeartScaleShop(getHeartScaleShopItems(location.zoneId)); + } + } + } + }, [canvasRef.current]); + + // Select trainer after trainerList is populated + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const trainerId = params.get('trainerId'); + + if (trainerId && trainerList.length > 0) { + const trainer = trainerList.find(t => t.trainer_id === parseInt(trainerId)); + if (trainer) { + setSelectedTrainer(trainer); + setShowTrainerModal(true); + } + } + }, [trainerList]); //Component onMount useEffect(() => { const context = canvasRef.current.getContext('2d', {willReadFrequently: true}); diff --git a/src/utils/dex/index.js b/src/utils/dex/index.js index 1ca7b7aaac..070d8fd34b 100644 --- a/src/utils/dex/index.js +++ b/src/utils/dex/index.js @@ -51,7 +51,7 @@ import { getTimeOfDayEncounters, getAllHoneyTreeEncounters } from './encounters' -import { getTrainersFromZoneId } from './trainers'; +import { getTrainersFromZoneId, getZoneIdFromTrainerId } from './trainers'; import { getFieldItemsFromZoneID, getHiddenItemsFromZoneID } from './location'; import { getEvolutionTree } from './evolution'; import { getEggGroupNameById, getEggGroupViaPokemonId } from './egggroup'; @@ -196,6 +196,7 @@ export { getTimeOfDayEncounters, getAllHoneyTreeEncounters, getTrainersFromZoneId, + getZoneIdFromTrainerId, getFieldItemsFromZoneID, getHiddenItemsFromZoneID }; diff --git a/src/utils/dex/trainers.js b/src/utils/dex/trainers.js index 3ac5b52a24..0252c58ea1 100644 --- a/src/utils/dex/trainers.js +++ b/src/utils/dex/trainers.js @@ -12,6 +12,22 @@ function getTrainersFromZoneId(zoneId, mode = GAMEDATA2) { return []; }; +function getZoneIdFromTrainerId(trainerId, mode = GAMEDATA2) { + if (!trainerId) return null; + + for (const zoneKey in TrainerLocations[mode]) { + const trainers = TrainerLocations[mode][zoneKey]; + const trainer = trainers.find(t => t.trainer_id === parseInt(trainerId)); + if (trainer) { + return parseInt(zoneKey); + } + } + + console.warn(`Trainer ID ${trainerId} not found in any zone.`); + return null; +}; + export { - getTrainersFromZoneId -} \ No newline at end of file + getTrainersFromZoneId, + getZoneIdFromTrainerId +} From 15f74155c3d4ff21f06ef53e556d1fe25e8450ae Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Mon, 8 Jun 2026 04:46:07 +0200 Subject: [PATCH 02/13] Remove now deprecated canvas code --- src/components/Mapper/Mapper.jsx | 355 +------------------------------ 1 file changed, 4 insertions(+), 351 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 22741ebd4d..9f58489f8d 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -5,6 +5,7 @@ import useIsBrowser from '@docusaurus/useIsBrowser'; import { sortedCoordinates, getSelectedLocation, + getLocationCoordsFromZoneId, } from './coordinates'; import { SearchBar } from './SearchBar'; import { MapperTabPanel } from './TabPanel/MapperTabPanel'; @@ -53,12 +54,6 @@ const canvasDimensions = { const versionNumber = "Beta 1.2.0"; -export const CLEAR_MODE = { - HIGHLIGHT: "highlight", - SELECT: "select", - ENCOUNTER: "enc", -}; - export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const isBrowser = useIsBrowser(); if (!isBrowser) { @@ -106,44 +101,22 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const [fixedShopList, setFixedShops] = useState([]); const [heartScaleShopList, setHeartScaleShop] = useState([]); - const canvasRef = useRef(null); - const CLEAR_MODE = { - HIGHLIGHT: "highlight", - SELECT: "select", - ENCOUNTER: "enc", - } - // Handle URL query parameters for trainer ID useEffect(() => { const params = new URLSearchParams(window.location.search); const trainerId = params.get('trainerId'); - if (trainerId && canvasRef.current) { + if (trainerId) { const zoneId = getZoneIdFromTrainerId(trainerId, GAMEDATA3); if (zoneId) { const location = getLocationCoordsFromZoneId(zoneId); if (location) { - // Select the location - if (previousRectangle.select !== null) { - clearRect(CLEAR_MODE.SELECT); - } - drawRect(location, CLEAR_MODE.SELECT); - previousRectangle.select = { x: location.x, y: location.y, width: location.width, height: location.height }; - locationId.current = location.zoneId; setSelectedZone(location.name); - setSelectedZoneId(location.zoneId); - setEncounterList(setAllEncounters(location.zoneId)); - setTrainerList(getTrainersFromZoneId(location.zoneId, GAMEDATA3)); - setFieldItems(getFieldItemsFromZoneID(location.zoneId)); - setHiddenItems(getHiddenItemsFromZoneID(location.zoneId)); - setShopItems(getRegularShopItems(location.zoneId)); - setScriptItems(getScriptItems(location.zoneId)); - setFixedShops(getFixedShops(location.zoneId)); - setHeartScaleShop(getHeartScaleShopItems(location.zoneId)); } + handleSetLocationZoneId(zoneId); } } - }, [canvasRef.current]); + }, []); // Select trainer after trainerList is populated useEffect(() => { @@ -158,326 +131,6 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { } } }, [trainerList]); - //Component onMount - useEffect(() => { - const context = canvasRef.current.getContext('2d', {willReadFrequently: true}); - const image = new Image(); - image.src = require('@site/static/img/new_small_mapper.png').default; - image.onload = () => { - context.drawImage(image, 0, 0); - drawOverlay(context); - }; - - }, []) // Empty dependency array means this effect runs once after the initial render - - function drawOverlay(ctx) { - MapperCoordinates.forEach(coord => { - // Draw zone outlines - ctx.beginPath(); - ctx.moveTo(coord.x, coord.y); - ctx.lineTo(coord.x + coord.width, coord.y); - ctx.lineTo(coord.x + coord.width, coord.y + coord.height); - ctx.lineTo(coord.x, coord.y + coord.height); - ctx.closePath(); - ctx.strokeStyle = 'rgba(0, 0, 0, 1)'; - ctx.lineWidth = 1; - ctx.stroke(); - }); - }; - - /** Listener Events for the Canvas updates */ - const updateLocationDataFromDropdown = (event) => { - // This is using the custom event that was created by the SearchBar - // After adding a listener, this is used to directly interact with the canvas - // This CANNOT pull the state from a useState or other async func. - // You must add a customEvent alongside where a state is updated - const selectedName = event.detail; - if (!selectedName) { - return; - } - const location = getLocationCoordsFromName(selectedName); - const locationCheck = { x: location.x, y: location.y, width: location.width, height: location.height} - - for (let key in previousRectangle) { - if (previousRectangle[key] === locationCheck && previousRectangle[key] !== null) { - // This is to delete any highlights that are present in the current area - // specifically enc highlights when that comes up. - clearRect(key); - } - } - if(previousRectangle.select !== null) { - clearRect(CLEAR_MODE.SELECT); - } - drawRect(location, CLEAR_MODE.SELECT); - previousRectangle.select = { x: location.x, y: location.y, width: location.width, height: location.height }; - locationId.current = location.zoneId; - - setEncounterList(setAllEncounters(location.zoneId)); - setTrainerList(getTrainersFromZoneId(location.zoneId, GAMEDATA3)); - - setFieldItems(getFieldItemsFromZoneID(location.zoneId)); - setHiddenItems(getHiddenItemsFromZoneID(location.zoneId)); - setShopItems(getRegularShopItems(location.zoneId)); - setScriptItems(getScriptItems(location.zoneId)); - setFixedShops(getFixedShops(location.zoneId)); - setHeartScaleShop(getHeartScaleShopItems(location.zoneId)); - }; - - const updatePokemonLocationsFromDropdown = (event) => { - // This is using the custom event that was created by the SearchBar - // After adding a listener, this is used to directly interact with the canvas - // This CANNOT pull the state from a useState or other async func. - // You must add a customEvent alongside where a state is updated - const selectedName = event.detail; - if (!selectedName) { - return; - } - const locations = getMapperRoutesFromPokemonId(selectedName.id); - const locationChecks = locations.map(([locationName, zoneId]) => { - const zoneLocationCoords = getLocationCoordsFromZoneId(zoneId); - const locationCoords = getLocationCoordsFromName(locationName); - if (zoneLocationCoords) { - const locationCheck = { - name: locationName, - x: zoneLocationCoords.x, - y: zoneLocationCoords.y, - width: zoneLocationCoords.width, - height: zoneLocationCoords.height, - zoneId: zoneLocationCoords.zoneId, - zone: "", - }; - return locationCheck - } else if (locationCoords) { - const locationCheck = { - name: locationName, - x: locationCoords.x, - y: locationCoords.y, - width: locationCoords.width, - height: locationCoords.height, - zoneId: location.zoneId, - location: "", - }; - return locationCheck - } - return null; - }); - const prevLocations = previousRectangle.enc // There are multiple rectangles that are highlighted - const prevSelected = previousRectangle.select; - if (prevLocations) { - for (const locationIndex in prevLocations) { - if ( - prevSelected && - !isLocationExactlyEqual( - prevLocations[locationIndex], - prevSelected - ) - ) { - clearRect(CLEAR_MODE.ENCOUNTER, prevLocations[locationIndex]); - } else { - clearRect(CLEAR_MODE.ENCOUNTER, prevLocations[locationIndex]); - drawRect(prevLocations[locationIndex], CLEAR_MODE.SELECT) - } - } - previousRectangle.enc = null; - } - - for (const locationIndex in locationChecks) { - const location = locationChecks[locationIndex]; - if (location) { - if (location.zoneId !== locationId.current && location.name !== hoveredZone) { - drawRect(location, CLEAR_MODE.ENCOUNTER); - } else if (location.name === hoveredZone) { - drawRect(location); - } else if (location.zoneId === locationId.current) { - drawRect(location, CLEAR_MODE.SELECT); - } - } - } - }; - - const updateColorSettings = (event) => { - const newColorSettings = event.detail; - colorSettings = newColorSettings; - const prevLocations = previousRectangle.enc // There are multiple rectangles that are highlighted - const prevHighlight = previousRectangle.highlight; - const prevSelected = previousRectangle.select; - if (prevLocations) { - for (const locationIndex in prevLocations) { - if ( - prevHighlight && - isLocationExactlyEqual( - prevLocations[locationIndex], - prevHighlight - ) - ) { - clearRect(CLEAR_MODE.HIGHLIGHT); - setHoveredZone(null); - previousRectangle.highlight = null; - } - if ( - prevSelected && - !isLocationExactlyEqual( - prevLocations[locationIndex], - prevSelected - ) - ) { - clearRect(CLEAR_MODE.ENCOUNTER, prevLocations[locationIndex]); - } else { - clearRect(CLEAR_MODE.ENCOUNTER, prevLocations[locationIndex]); - } - } - previousRectangle.enc = null; - } - if (previousRectangle.select !== null) { - const location = previousRectangle.select; - drawRect(location, CLEAR_MODE.SELECT); - } - setPokemonName("Bulbasaur"); - setSelectedPokemon(pokemonList3[0]) - } - - const handleClick = (event) => { - if(rect === null) { - console.error('Bad Rect:', rect, canvasRef.current) - return setRect(canvasRef.current.getBoundingClientRect()); - } - - let scrollLeft = window.scrollX || document.documentElement.scrollLeft; - let scrollTop = window.scrollY || document.documentElement.scrollTop; - - const x = event.clientX - rect.left + scrollLeft; - const y = event.clientY - rect.top + scrollTop; - - const location = getSelectedLocation( x,y ) - if(location === null || location.length === 0) return; - - if (previousRectangle.highlight !== null) { - // Make sure to clear any lower hierarchy rects before setting higher ones - // If this is not done, the lower mode's highlight will be set as the previous state for the higher mode - // Here's how the bug would come up: - // 1. Hover over an area. - // 2. Select that area. - // 3. Hover over a different area. - // 4. Select that different area. - // 5. From this you'll see how the first area selected will have the hover color. - // This will also affect any future areas in the same way. - // We want the old selected area to not have the hover's color. - // See clearRect for hierarchy info. - clearRect(CLEAR_MODE.HIGHLIGHT); - } - if (previousRectangle.enc !== null) { - const selectedEnc = previousRectangle.enc.find( - (encLocation) => { - return (isLocationExactlyEqual(location, encLocation)); - } - ) - if (selectedEnc) { - clearRect(CLEAR_MODE.ENCOUNTER, selectedEnc); - } - } - if(previousRectangle.select !== null) { - clearRect(CLEAR_MODE.SELECT); - } - drawRect(location, CLEAR_MODE.SELECT); // Change the fill color - previousRectangle.select = { x: location.x, y: location.y, width: location.width, height: location.height }; - - locationId.current = location.zoneId; - setSelectedZone(location.name); - setSelectedZoneId(location.zoneId) - setEncounterList(setAllEncounters(location.zoneId)); - setTrainerList(getTrainersFromZoneId(location.zoneId, GAMEDATA3)); - - setFieldItems(getFieldItemsFromZoneID(location.zoneId)); - setHiddenItems(getHiddenItemsFromZoneID(location.zoneId)); - setShopItems(getRegularShopItems(location.zoneId)); - setScriptItems(getScriptItems(location.zoneId)); - setFixedShops(getFixedShops(location.zoneId)); - setHeartScaleShop(getHeartScaleShopItems(location.zoneId)); - }; - - function handleMouseMove(event) { - if(rect === null) {//Shouldn't happen but let's make sure - return setRect(canvasRef.current.getBoundingClientRect()); - } - - // This system allows mobile users to make use of the mapper too - let scrollLeft = window.scrollX || document.documentElement.scrollLeft; - let scrollTop = window.scrollY || document.documentElement.scrollTop; - - const mouseX = event.clientX - rect.left + scrollLeft; - const mouseY = event.clientY - rect.top + scrollTop; - - const location = getSelectedLocation(mouseX, mouseY); - if (location && location.zoneId !== locationId.current) { - setHoveredZone(location.name); - drawRect(location); // Change the fill color - } else if (location && location.zoneId === locationId.current) { - // This prevents the selected location from being highlighted by the hover color - drawRect(location, CLEAR_MODE.SELECT); - } else { - if (location && previousRectangle.enc !== null) { - const hoveredEnc = previousRectangle.enc.find( - (encLocation) => { - return (isLocationExactlyEqual(location, encLocation)); - } - ) - if (hoveredEnc) { - clearRect(CLEAR_MODE.ENCOUNTER, hoveredEnc); - } - } - setHoveredZone(null); - if (previousRectangle.highlight !== null) { - clearRect(CLEAR_MODE.HIGHLIGHT); - previousRectangle.highlight = null; - } - } - } - - const handleMouseLeave = () => { - // Clear the hovered zone when mouse leaves - setHoveredZone(null); - if (previousRectangle.highlight !== null) { - clearRect(CLEAR_MODE.HIGHLIGHT); - } - if (previousRectangle.enc !== null) { - clearRect(CLEAR_MODE.ENCOUNTER); - } - }; - - useEffect(() => { - const canvas = canvasRef.current; - if (canvas) { - // Get the bounding rectangle of the canvas - const r = canvas.getBoundingClientRect(); - setRect(r); - - // The passLocationNameToParent event was required so that the child could update the DOM - // This listener is created in the SearchBar.jsx and is listened to here - // This is how you would allow a useState from react to partially interact with the canvas - // Partially because useState is async and this is direct dom manipulation. - const eventListener = (locationNameEvent) => updateLocationDataFromDropdown(locationNameEvent); - const pokemonLocationsListener = (pokemonName) => updatePokemonLocationsFromDropdown(pokemonName); - const colorListener = (changeColorSettings) => updateColorSettings(changeColorSettings); - - canvas.addEventListener('click', handleClick); - canvas.addEventListener('mousemove', handleMouseMove); - canvas.addEventListener('mouseleave', handleMouseLeave); - canvas.addEventListener('passLocationNameToParent', eventListener); - canvas.addEventListener('passPokemonNameLocation', pokemonLocationsListener); - canvas.addEventListener('changeColorSettings', colorListener); - - // Clean up the event listener when the component is unmounted - return () => { - canvas.removeEventListener('click', handleClick); - canvas.removeEventListener('mousemove', handleMouseMove); - canvas.removeEventListener('mouseleave', handleMouseLeave); - canvas.removeEventListener('passLocationNameToParent', eventListener); - canvas.removeEventListener('passPokemonNameLocation', pokemonLocationsListener); - canvas.removeEventListener('changeColorSettings', colorListener); - }; - } - }, [canvasRef.current]); // Add canvasRef.current to the dependency array - const locationId = useRef(null); useEffect(() => { if(locationId !== null) { From 0a9a9dbd7267046bbfa439504dcf9a22e51df678 Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Mon, 8 Jun 2026 04:48:16 +0200 Subject: [PATCH 03/13] Change the tab to Trainers when loading from query --- src/components/Mapper/Mapper.jsx | 3 +++ src/components/Mapper/TabPanel/MapperTabPanel.jsx | 5 +++-- src/components/Mapper/TabPanel/PokemonTabs.jsx | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 9f58489f8d..5908263873 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -101,6 +101,8 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const [fixedShopList, setFixedShops] = useState([]); const [heartScaleShopList, setHeartScaleShop] = useState([]); + const defaultTab = new URLSearchParams(window.location.search).has('trainerId') ? 1 : 0; + // Handle URL query parameters for trainer ID useEffect(() => { const params = new URLSearchParams(window.location.search); @@ -346,6 +348,7 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setSelectedTrainer={setSelectedTrainer} openTrainerModal={openTrainerModal} routeId={selectedLocation} + defaultTab={defaultTab} /> { return ( - + { const PokemonTabPanel = ({ tabNames, - children + children, + initialTab = 0, }) => { - const [selectedTab, setSelectedTab] = useState(0); + const [selectedTab, setSelectedTab] = useState(initialTab); const handleTabChange = (event, newTab) => { setSelectedTab(newTab); }; From 327b1785c7b9bcb8de72f8c3503a09fa40f20c22 Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Mon, 8 Jun 2026 05:14:38 +0200 Subject: [PATCH 04/13] Add Trainer search bar --- src/components/Mapper/Mapper.jsx | 32 +++++++++- src/components/Mapper/SearchBar.jsx | 59 ++++++++++++++++++- .../Mapper/TabPanel/MapperTabPanel.jsx | 4 +- .../Mapper/TabPanel/PokemonTabs.jsx | 12 +++- src/components/Mapper/style.css | 4 +- src/utils/dex/index.js | 4 +- src/utils/dex/trainers.js | 39 +++++++++++- 7 files changed, 143 insertions(+), 11 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 5908263873..0a76b8e93e 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -16,6 +16,8 @@ import { getAreaEncounters, getTrainersFromZoneId, getZoneIdFromTrainerId, + getFullTrainerById, + getAllTrainers, getFieldItemsFromZoneID, getHiddenItemsFromZoneID, getPokemonIdFromName @@ -101,7 +103,13 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const [fixedShopList, setFixedShops] = useState([]); const [heartScaleShopList, setHeartScaleShop] = useState([]); - const defaultTab = new URLSearchParams(window.location.search).has('trainerId') ? 1 : 0; + const [selectedTab, setSelectedTab] = useState( + new URLSearchParams(window.location.search).has('trainerId') ? 1 : 0 + ); + + const handleTabChange = (newTab) => { + setSelectedTab(newTab); + }; // Handle URL query parameters for trainer ID useEffect(() => { @@ -151,6 +159,23 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setShowTrainerModal(false); }; + const allTrainers = React.useMemo(() => getAllTrainers(GAMEDATA3), []); + + const handleTrainerSelect = (trainer) => { + const zoneId = trainer.zoneId; + if (zoneId) { + const location = getLocationCoordsFromZoneId(zoneId); + if (location) { + setSelectedZone(location.name); + } + handleSetLocationZoneId(zoneId); + const fullTrainer = getFullTrainerById(trainer.trainer_id, GAMEDATA3); + setSelectedTrainer(fullTrainer || trainer); + setShowTrainerModal(true); + setSelectedTab(1); + } + }; + const handleOptionChange = (option, value) => { setEncOptions({ ...encOptions, @@ -348,7 +373,8 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setSelectedTrainer={setSelectedTrainer} openTrainerModal={openTrainerModal} routeId={selectedLocation} - defaultTab={defaultTab} + selectedTab={selectedTab} + onTabChange={handleTabChange} /> { selectedPokemon={selectedPokemon} setSelectedPokemon={setSelectedPokemon} handleShowSettings={handleShowSettings} + allTrainers={allTrainers} + onTrainerSelect={handleTrainerSelect} /> { + const [searchText, setSearchText] = useState(""); + const [selectedTrainer, setSelectedTrainer] = useState(null); + + const handleTrainerChange = (_, value, reason) => { + if (reason !== "clear" && value) { + setSelectedTrainer(value); + setSearchText(value.label); + onTrainerSelect(value); + } else { + setSelectedTrainer(null); + setSearchText(""); + } + }; + + const handleInputChange = (_, value) => { + setSearchText(value); + }; + + return ( +
+ option.label} + value={selectedTrainer} + onChange={handleTrainerChange} + inputValue={searchText} + onInputChange={handleInputChange} + renderInput={(params) => ( + + )} + /> +
+ ); +}; + const SettingsButton = ({handleShowSettings}) => { return (
@@ -126,6 +177,8 @@ export const SearchBar = ({ selectedPokemon, setSelectedPokemon, handleShowSettings, + allTrainers, + onTrainerSelect, }) => { return (
+ { return ( - + { @@ -32,10 +32,16 @@ const PokemonTabPanel = ({ tabNames, children, initialTab = 0, + selectedTab: controlledTab, + onTabChange, }) => { - const [selectedTab, setSelectedTab] = useState(initialTab); + const [internalTab, setInternalTab] = useState(initialTab); + const selectedTab = controlledTab !== undefined ? controlledTab : internalTab; const handleTabChange = (event, newTab) => { - setSelectedTab(newTab); + if (onTabChange) { + onTabChange(newTab); + } + setInternalTab(newTab); }; return ( diff --git a/src/components/Mapper/style.css b/src/components/Mapper/style.css index 4e15c09a75..f8c47c15df 100755 --- a/src/components/Mapper/style.css +++ b/src/components/Mapper/style.css @@ -55,7 +55,7 @@ top: 122px; justify-content: end; display: grid; - grid-template-rows: 60px 25px; + grid-template-rows: auto auto auto; pointer-events: none; touch-action: manipulation; } @@ -69,7 +69,7 @@ .location { pointer-events: auto; - margin-top: 16px; + margin-top: 10px; margin-right: 10px; } diff --git a/src/utils/dex/index.js b/src/utils/dex/index.js index 070d8fd34b..9a89effd5a 100644 --- a/src/utils/dex/index.js +++ b/src/utils/dex/index.js @@ -51,7 +51,7 @@ import { getTimeOfDayEncounters, getAllHoneyTreeEncounters } from './encounters' -import { getTrainersFromZoneId, getZoneIdFromTrainerId } from './trainers'; +import { getTrainersFromZoneId, getZoneIdFromTrainerId, getFullTrainerById, getAllTrainers } from './trainers'; import { getFieldItemsFromZoneID, getHiddenItemsFromZoneID } from './location'; import { getEvolutionTree } from './evolution'; import { getEggGroupNameById, getEggGroupViaPokemonId } from './egggroup'; @@ -197,6 +197,8 @@ export { getAllHoneyTreeEncounters, getTrainersFromZoneId, getZoneIdFromTrainerId, + getFullTrainerById, + getAllTrainers, getFieldItemsFromZoneID, getHiddenItemsFromZoneID }; diff --git a/src/utils/dex/trainers.js b/src/utils/dex/trainers.js index 78d35111df..cf6c36c6d5 100644 --- a/src/utils/dex/trainers.js +++ b/src/utils/dex/trainers.js @@ -30,7 +30,44 @@ function getZoneIdFromTrainerId(trainerId, mode = GAMEDATA2) { return null; }; +function getFullTrainerById(trainerId, mode = GAMEDATA2) { + if (!trainerId) return null; + + for (const zoneKey in TrainerLocations[mode]) { + const trainers = TrainerLocations[mode][zoneKey]; + const trainer = trainers.find(t => t.trainer_id === parseInt(trainerId)); + if (trainer) { + return { ...trainer, zoneId: parseInt(zoneKey) }; + } + } + + return null; +}; + +function getAllTrainers(mode = GAMEDATA2) { + const seen = new Set(); + const trainers = []; + for (const zoneKey in TrainerLocations[mode]) { + for (const trainer of TrainerLocations[mode][zoneKey]) { + if (seen.has(trainer.trainer_id)) continue; + seen.add(trainer.trainer_id); + trainers.push({ + trainer_id: trainer.trainer_id, + zoneId: parseInt(zoneKey), + name: trainer.name, + route: trainer.route, + team_name: trainer.team_name, + trainerType: trainer.trainerType, + label: `${trainer.team_name} (${trainer.trainer_id})`, + }); + } + } + return trainers; +}; + export { getTrainersFromZoneId, - getZoneIdFromTrainerId + getZoneIdFromTrainerId, + getFullTrainerById, + getAllTrainers, } From af33083a7beca8f15aec31b3af2debfabc7b027b Mon Sep 17 00:00:00 2001 From: AarCon01 Date: Sun, 7 Jun 2026 22:40:18 -0600 Subject: [PATCH 05/13] Fix Jubilife zoneId check --- src/components/Mapper/Mapper.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 0a76b8e93e..a7448bfc44 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -163,7 +163,7 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const handleTrainerSelect = (trainer) => { const zoneId = trainer.zoneId; - if (zoneId) { + if (zoneId || zoneId === 0) { const location = getLocationCoordsFromZoneId(zoneId); if (location) { setSelectedZone(location.name); From 985c6027f32008873fa1fdab9f65e2c59f1590c6 Mon Sep 17 00:00:00 2001 From: github-actions-bot Date: Sun, 7 Jun 2026 23:32:24 +0000 Subject: [PATCH 06/13] Updating 3.0 TM Learnset files --- .../gamedata3.0/TMLearnset/monsno_150_formno_5.json | 6 +++--- .../gamedata3.0/TMLearnset/monsno_194_formno_1.json | 10 +++++----- .../gamedata3.0/TMLearnset/monsno_195_formno_0.json | 2 +- .../gamedata3.0/TMLearnset/monsno_249_formno_1.json | 8 ++++---- .../gamedata3.0/TMLearnset/monsno_383_formno_2.json | 2 +- .../gamedata3.0/TMLearnset/monsno_384_formno_2.json | 4 ++-- .../gamedata3.0/TMLearnset/monsno_483_formno_2.json | 10 ++++++++++ .../gamedata3.0/TMLearnset/monsno_484_formno_2.json | 10 ++++++++++ .../gamedata3.0/TMLearnset/monsno_542_formno_0.json | 2 +- .../gamedata3.0/TMLearnset/monsno_902_formno_0.json | 10 +++++----- .../gamedata3.0/TMLearnset/monsno_980_formno_0.json | 4 ++-- .../gamedata3.0/TMLearnset/monsno_981_formno_0.json | 8 ++++---- .../gamedata3.0/TMLearnset/monsno_983_formno_0.json | 8 ++++---- 13 files changed, 52 insertions(+), 32 deletions(-) create mode 100644 __gamedata/gamedata3.0/TMLearnset/monsno_483_formno_2.json create mode 100644 __gamedata/gamedata3.0/TMLearnset/monsno_484_formno_2.json diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_150_formno_5.json b/__gamedata/gamedata3.0/TMLearnset/monsno_150_formno_5.json index b5360a45e3..eb1d6db812 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_150_formno_5.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_150_formno_5.json @@ -1,8 +1,8 @@ { "set01": 4159438061, - "set02": 1536723959, - "set03": 2331939308, - "set04": 33616074, + "set02": 1536732151, + "set03": 2331955694, + "set04": 33616066, "set05": 330762, "set06": 0, "set07": 0, diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_194_formno_1.json b/__gamedata/gamedata3.0/TMLearnset/monsno_194_formno_1.json index b87b4898b0..b5c2966dd2 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_194_formno_1.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_194_formno_1.json @@ -1,9 +1,9 @@ { - "set01": 2320171044, - "set02": 33561176, - "set03": 1108248672, - "set04": 134267012, - "set05": 133248, + "set01": 167968804, + "set02": 33557080, + "set03": 1108248640, + "set04": 134275460, + "set05": 149632, "set06": 0, "set07": 0, "set08": 0 diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_195_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_195_formno_0.json index 699a2158c4..9839b1501a 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_195_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_195_formno_0.json @@ -2,7 +2,7 @@ "set01": 3393941605, "set02": 42547800, "set03": 3259400296, - "set04": 49542, + "set04": 134267270, "set05": 542848, "set06": 0, "set07": 0, diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_249_formno_1.json b/__gamedata/gamedata3.0/TMLearnset/monsno_249_formno_1.json index e1937200f6..522270dd8c 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_249_formno_1.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_249_formno_1.json @@ -1,8 +1,8 @@ { - "set01": 3016750204, - "set02": 121948819, - "set03": 3805680040, - "set04": 8446439, + "set01": 3016750200, + "set02": 1199991735, + "set03": 2731962794, + "set04": 8446177, "set05": 262154, "set06": 0, "set07": 0, diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_383_formno_2.json b/__gamedata/gamedata3.0/TMLearnset/monsno_383_formno_2.json index c976b3a292..6185f58c52 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_383_formno_2.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_383_formno_2.json @@ -2,7 +2,7 @@ "set01": 3421062322, "set02": 109710070, "set03": 2454101337, - "set04": 1360010, + "set04": 1360002, "set05": 17122, "set06": 0, "set07": 0, diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_384_formno_2.json b/__gamedata/gamedata3.0/TMLearnset/monsno_384_formno_2.json index 80d4395a3b..d597d2803b 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_384_formno_2.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_384_formno_2.json @@ -1,9 +1,9 @@ { - "set01": 3286463670, + "set01": 3287512246, "set02": 110758646, "set03": 3804665801, "set04": 546357750, - "set05": 2, + "set05": 4098, "set06": 0, "set07": 0, "set08": 0 diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_483_formno_2.json b/__gamedata/gamedata3.0/TMLearnset/monsno_483_formno_2.json new file mode 100644 index 0000000000..8f420be484 --- /dev/null +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_483_formno_2.json @@ -0,0 +1,10 @@ +{ + "set01": 3284890802, + "set02": 100797174, + "set03": 2655426921, + "set04": 49314, + "set05": 65730, + "set06": 0, + "set07": 0, + "set08": 0 +} \ No newline at end of file diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_484_formno_2.json b/__gamedata/gamedata3.0/TMLearnset/monsno_484_formno_2.json new file mode 100644 index 0000000000..f6e881df1c --- /dev/null +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_484_formno_2.json @@ -0,0 +1,10 @@ +{ + "set01": 3280696567, + "set02": 113773302, + "set03": 3662057929, + "set04": 49570, + "set05": 65730, + "set06": 0, + "set07": 0, + "set08": 0 +} \ No newline at end of file diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_542_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_542_formno_0.json index 7eb68919df..f0acd01c24 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_542_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_542_formno_0.json @@ -1,7 +1,7 @@ { "set01": 2150614312, "set02": 573594241, - "set03": 310051883, + "set03": 326829099, "set04": 3250636928, "set05": 3147792, "set06": 0, diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_902_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_902_formno_0.json index aad463d662..53b583bf19 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_902_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_902_formno_0.json @@ -1,9 +1,9 @@ { - "set01": 537096196, - "set02": 2560, - "set03": 1107427336, - "set04": 4, - "set05": 0, + "set01": 2953007212, + "set02": 268507648, + "set03": 1128267784, + "set04": 203022726, + "set05": 1026, "set06": 0, "set07": 0, "set08": 0 diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_980_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_980_formno_0.json index 27b9a5fb2d..b258ff80a6 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_980_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_980_formno_0.json @@ -2,8 +2,8 @@ "set01": 167985188, "set02": 33557080, "set03": 1108248648, - "set04": 4, - "set05": 0, + "set04": 134275460, + "set05": 149632, "set06": 0, "set07": 0, "set08": 0 diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_981_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_981_formno_0.json index 8d3bc5999b..714fad750b 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_981_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_981_formno_0.json @@ -1,9 +1,9 @@ { - "set01": 865322008, + "set01": 865322040, "set02": 1125165569, - "set03": 170266888, - "set04": 32, - "set05": 0, + "set03": 136712456, + "set04": 1167520, + "set05": 280584, "set06": 0, "set07": 0, "set08": 0 diff --git a/__gamedata/gamedata3.0/TMLearnset/monsno_983_formno_0.json b/__gamedata/gamedata3.0/TMLearnset/monsno_983_formno_0.json index 714e29708d..585c927470 100644 --- a/__gamedata/gamedata3.0/TMLearnset/monsno_983_formno_0.json +++ b/__gamedata/gamedata3.0/TMLearnset/monsno_983_formno_0.json @@ -1,9 +1,9 @@ { - "set01": 1275283456, + "set01": 1275283488, "set02": 44575696, - "set03": 103509321, - "set04": 0, - "set05": 0, + "set03": 371420489, + "set04": 2183184514, + "set05": 2, "set06": 0, "set07": 0, "set08": 0 From 788ebafcbae3e57bd38df054536442122d4ebc99 Mon Sep 17 00:00:00 2001 From: AarCon01 Date: Sun, 7 Jun 2026 21:56:41 -0600 Subject: [PATCH 07/13] Fix some tests and remove the unused \Pokedex components --- package-lock.json | 555 ++++-------------- package.json | 5 +- .../pokedex-data-plugin/dex/functions.test.js | 2 +- plugins/pokedex-data-plugin/dex/name.test.js | 4 +- src/components/Pokedex/EvolutionGraph.jsx | 28 - src/components/Pokedex/FormSection.js | 33 -- src/components/Pokedex/PokemonAbilities.jsx | 53 -- .../Pokedex/PokemonAbilities.test.jsx | 71 --- src/components/Pokedex/PokemonAccordion.jsx | 18 - .../Pokedex/PokemonAlternativeFormsList.jsx | 42 -- src/components/Pokedex/PokemonEggGroups.jsx | 30 - src/components/Pokedex/PokemonGenderRatio.jsx | 36 -- src/components/Pokedex/PokemonMovesetList.jsx | 182 ------ src/components/Pokedex/PokemonSearch.jsx | 36 -- src/components/Pokedex/PokemonStats.jsx | 149 ----- src/components/Pokedex/index.js | 109 ---- src/components/Pokedex/styles.module.css | 46 -- src/components/Pokedex/type.js | 60 -- src/components/Pokedex2/PokemonAbilities.jsx | 2 +- src/pages/dex.js | 17 - src/utils/dex/functions.test.js | 2 +- src/utils/dex/name.test.js | 4 +- 22 files changed, 115 insertions(+), 1369 deletions(-) delete mode 100644 src/components/Pokedex/EvolutionGraph.jsx delete mode 100644 src/components/Pokedex/FormSection.js delete mode 100644 src/components/Pokedex/PokemonAbilities.jsx delete mode 100644 src/components/Pokedex/PokemonAbilities.test.jsx delete mode 100644 src/components/Pokedex/PokemonAccordion.jsx delete mode 100644 src/components/Pokedex/PokemonAlternativeFormsList.jsx delete mode 100644 src/components/Pokedex/PokemonEggGroups.jsx delete mode 100644 src/components/Pokedex/PokemonGenderRatio.jsx delete mode 100644 src/components/Pokedex/PokemonMovesetList.jsx delete mode 100644 src/components/Pokedex/PokemonSearch.jsx delete mode 100644 src/components/Pokedex/PokemonStats.jsx delete mode 100644 src/components/Pokedex/index.js delete mode 100644 src/components/Pokedex/styles.module.css delete mode 100644 src/components/Pokedex/type.js delete mode 100644 src/pages/dex.js diff --git a/package-lock.json b/package-lock.json index 1d59b89cbc..208d4069d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,8 +35,9 @@ "@babel/preset-env": "^7.21.4", "@docusaurus/eslint-plugin": "^3.9.2", "@docusaurus/module-type-aliases": "^3.9.2", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^12.1.5", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/jest": "^29.5.1", "babel-jest": "^29.5.0", "eslint": "^8.38.0", @@ -55,10 +56,11 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", - "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", - "dev": true + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" }, "node_modules/@algolia/abtesting": { "version": "1.13.0", @@ -7089,22 +7091,23 @@ } }, "node_modules/@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", + "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", "pretty-format": "^27.0.2" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@testing-library/dom/node_modules/ansi-styles": { @@ -7112,6 +7115,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7119,11 +7123,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, "node_modules/@testing-library/dom/node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -7137,59 +7149,55 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", "dev": true, + "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", + "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", - "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", "redent": "^3.0.0" }, "engines": { - "node": ">=8", + "node": ">=14", "npm": ">=6", "yarn": ">=1" } }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@testing-library/react": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", - "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0", - "@types/react-dom": "<18.0.0" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">=12" + "node": ">=18" }, "peerDependencies": { - "react": "<18.0.0", - "react-dom": "<18.0.0" + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, "node_modules/@tootallnate/once": { @@ -7220,10 +7228,11 @@ } }, "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.0", @@ -7554,26 +7563,6 @@ "csstype": "^3.0.2" } }, - "node_modules/@types/react-dom": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", - "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", - "dev": true, - "dependencies": { - "@types/react": "^17" - } - }, - "node_modules/@types/react-dom/node_modules/@types/react": { - "version": "17.0.58", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.58.tgz", - "integrity": "sha512-c1GzVY97P0fGxwGxhYq989j4XwlcHQoto6wQISOC2v6wm3h0PORRWJFHlkRjfGsiG3y1609WdQ+J+tKxvrEd6A==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, "node_modules/@types/react-router": { "version": "5.1.19", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.19.tgz", @@ -7693,15 +7682,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "dependencies": { - "@types/jest": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", @@ -8345,12 +8325,13 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "node_modules/array-buffer-byte-length": { @@ -10356,40 +10337,6 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -10598,10 +10545,11 @@ } }, "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" }, "node_modules/dom-converter": { "version": "0.2.0", @@ -10962,32 +10910,6 @@ "node": ">= 0.4" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", @@ -13815,22 +13737,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -14072,15 +13978,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -14210,15 +14107,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -14297,15 +14185,6 @@ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "license": "MIT" }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -14318,19 +14197,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -15542,6 +15408,7 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, + "license": "MIT", "bin": { "lz-string": "bin/bin.js" } @@ -18227,22 +18094,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -22197,18 +22048,6 @@ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "license": "MIT" }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -24005,21 +23844,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -24331,9 +24155,9 @@ }, "dependencies": { "@adobe/css-tools": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", - "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", "dev": true }, "@algolia/abtesting": { @@ -28487,18 +28311,18 @@ } }, "@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", + "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", "pretty-format": "^27.0.2" }, "dependencies": { @@ -28508,6 +28332,12 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true }, + "dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, "pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -28528,43 +28358,26 @@ } }, "@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", "dev": true, "requires": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", + "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", - "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", "redent": "^3.0.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } } }, "@testing-library/react": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", - "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, "requires": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0", - "@types/react-dom": "<18.0.0" + "@babel/runtime": "^7.12.5" } }, "@tootallnate/once": { @@ -28588,9 +28401,9 @@ } }, "@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true }, "@types/babel__core": { @@ -28895,28 +28708,6 @@ "csstype": "^3.0.2" } }, - "@types/react-dom": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", - "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", - "dev": true, - "requires": { - "@types/react": "^17" - }, - "dependencies": { - "@types/react": { - "version": "17.0.58", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.58.tgz", - "integrity": "sha512-c1GzVY97P0fGxwGxhYq989j4XwlcHQoto6wQISOC2v6wm3h0PORRWJFHlkRjfGsiG3y1609WdQ+J+tKxvrEd6A==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - } - } - }, "@types/react-router": { "version": "5.1.19", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.19.tgz", @@ -29026,15 +28817,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "requires": { - "@types/jest": "*" - } - }, "@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", @@ -29507,12 +29289,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "requires": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "array-buffer-byte-length": { @@ -30829,39 +30611,6 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -30992,9 +30741,9 @@ } }, "dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", "dev": true }, "dom-converter": { @@ -31261,31 +31010,6 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, "es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", @@ -33193,16 +32917,6 @@ "is-decimal": "^2.0.0" } }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -33345,12 +33059,6 @@ "is-path-inside": "^3.0.2" } }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -33425,12 +33133,6 @@ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, "is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -33481,12 +33183,6 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -33496,16 +33192,6 @@ "call-bind": "^1.0.2" } }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -35880,16 +35566,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -38346,15 +38022,6 @@ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==" }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -39540,18 +39207,6 @@ "is-symbol": "^1.0.3" } }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, "which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", diff --git a/package.json b/package.json index 31b3ef795b..039f08252f 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,9 @@ "@babel/preset-env": "^7.21.4", "@docusaurus/eslint-plugin": "^3.9.2", "@docusaurus/module-type-aliases": "^3.9.2", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^12.1.5", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/jest": "^29.5.1", "babel-jest": "^29.5.0", "eslint": "^8.38.0", diff --git a/plugins/pokedex-data-plugin/dex/functions.test.js b/plugins/pokedex-data-plugin/dex/functions.test.js index a480f8671d..671b8bfcf1 100644 --- a/plugins/pokedex-data-plugin/dex/functions.test.js +++ b/plugins/pokedex-data-plugin/dex/functions.test.js @@ -195,7 +195,7 @@ describe('Dex utils function tests', () => { describe('3.0 Functions Tests', () => { const MODE = GAMEDATA3; test('should return the correct Pokemon ID for a different monsno and formno', () => { - expect(getPokemonIdFromMonsNoAndForm(493, 1, MODE)).toEqual(1210); + expect(getPokemonIdFromMonsNoAndForm(493, 1, MODE)).toEqual(1212); }); it('Should return the form_no when provided accurate monsno and pokemon ID', () => { const result = getPokemonIdFromFormMap(3, 3, MODE); //Clone Venusaur diff --git a/plugins/pokedex-data-plugin/dex/name.test.js b/plugins/pokedex-data-plugin/dex/name.test.js index 99ace5c4e1..19cd620a56 100644 --- a/plugins/pokedex-data-plugin/dex/name.test.js +++ b/plugins/pokedex-data-plugin/dex/name.test.js @@ -162,14 +162,14 @@ describe('Dex utils Name getters', () => { }); test('getPokemonNames() returns an array of all pokemon names when maxMonsno is greater than the number of pokemon', () => { const names = getPokemonNames(10000, 0, MODE); - expect(names).toHaveLength(1440); + expect(names).toHaveLength(1442); expect(names[0]).toBe('Egg'); expect(names[808]).toBe('Meltan'); }); it('should return the correct index for a valid form ID', () => { expect(getPokemonFormId(25, 1042, MODE)).toBe(2); expect(getPokemonFormId(133, 133, MODE)).toBe(0); - expect(getPokemonFormId(800, 1362, MODE)).toBe(2); + expect(getPokemonFormId(800, 1364, MODE)).toBe(2); }); }); }); diff --git a/src/components/Pokedex/EvolutionGraph.jsx b/src/components/Pokedex/EvolutionGraph.jsx deleted file mode 100644 index 37f84bf5ab..0000000000 --- a/src/components/Pokedex/EvolutionGraph.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { Box, Typography } from '@mui/material'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -/** - * WIP, styling and logic implementation is TBD - */ -export default function EvolutionGraph() { - return ( -
-
- - - Evolutions - - -
- - - Stage 1 Evo - - Stage 2 Evo - - Stage 3 Evo - -
- ); -} diff --git a/src/components/Pokedex/FormSection.js b/src/components/Pokedex/FormSection.js deleted file mode 100644 index 1599f82f02..0000000000 --- a/src/components/Pokedex/FormSection.js +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from 'react'; -import { Typography } from '@mui/material'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -export default function FormSection(props) { - const {dexId} = props; - return ( -
-
- - Forms - -
-
-
- Stage 1 Evo -
-
- -
-
- Stage 2 Evo -
-
- -
-
- Stage 3 Evo -
-
-
- ) -} diff --git a/src/components/Pokedex/PokemonAbilities.jsx b/src/components/Pokedex/PokemonAbilities.jsx deleted file mode 100644 index 6511d3126b..0000000000 --- a/src/components/Pokedex/PokemonAbilities.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { Box } from '@mui/system'; -import { Typography } from '@mui/material'; - -export const PokemonAbilities = ({ abilityName1, abilityName2, abilityNameHidden }) => { - const allAbilitiesAreEqual = abilityName1 === abilityName2 && abilityName2 === abilityNameHidden; - const hiddenAbilityIsDifferent = abilityName1 === abilityName2 && abilityName1 !== abilityNameHidden; - const abilityIsSameAsHidden = abilityName1 === abilityNameHidden || abilityName2 === abilityNameHidden; - - if (allAbilitiesAreEqual) { - return ( - - - - ); - } - - if (hiddenAbilityIsDifferent) { - return ( - - - - - ); - } - - if (abilityIsSameAsHidden) { - return ( - - - - - ); - } - - return ( - - - - - - ); -}; - -export const PokemonAbility = ({ abilityName, isHiddenAbility, needsSpacing }) => { - return ( - - {abilityName} - {isHiddenAbility && ' (H)'} - {needsSpacing && ','} - - ); -}; diff --git a/src/components/Pokedex/PokemonAbilities.test.jsx b/src/components/Pokedex/PokemonAbilities.test.jsx deleted file mode 100644 index a8fbbe0dfc..0000000000 --- a/src/components/Pokedex/PokemonAbilities.test.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen } from '@testing-library/react'; -import { PokemonAbilities } from './PokemonAbilities'; - -describe('Pokemon Abilities', () => { - test('all three are the same', () => { - const name = 'Blaze'; - - render( -
- -
, - ); - - expect(screen.queryByTestId('abilities')).toHaveTextContent(/^Blaze$/); - }); - - test('ability1 same as ability2, but hidden ability is different', () => { - const name1 = 'Blaze'; - const name2 = 'Levitate'; - - render( -
- -
, - ); - - expect(screen.queryByTestId('abilities')).toHaveTextContent(/^Blaze,Levitate \(H\)$/); - }); - - test('ability1 same as hidden ability', () => { - const name1 = 'Blaze'; - const name2 = 'Shield Dust'; - - render( -
- -
, - ); - - expect(screen.queryByTestId('abilities')).toHaveTextContent(/^Blaze,Shield Dust$/); - }); - - test('ability2 same as hidden ability', () => { - const name1 = 'Levitate'; - const name2 = 'Shield Dust'; - - render( -
- -
, - ); - - expect(screen.queryByTestId('abilities')).toHaveTextContent(/^Shield Dust,Levitate$/); - }); - - test('all abilities are different', () => { - const name1 = 'Blaze'; - const name2 = 'Levitate'; - const name3 = 'Shield Dust'; - - render( -
- -
, - ); - - expect(screen.queryByTestId('abilities')).toHaveTextContent(/^Blaze,Levitate,Shield Dust \(H\)$/); - }); -}); diff --git a/src/components/Pokedex/PokemonAccordion.jsx b/src/components/Pokedex/PokemonAccordion.jsx deleted file mode 100644 index 38b19b4df7..0000000000 --- a/src/components/Pokedex/PokemonAccordion.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; - -export const PokemonAccordion = ({ children, title, id }) => { - return ( - - } - aria-controls={`panel-${id}-content`} - id={`panel-${id}-header`} - > - {title} - - {children} - - ); -}; diff --git a/src/components/Pokedex/PokemonAlternativeFormsList.jsx b/src/components/Pokedex/PokemonAlternativeFormsList.jsx deleted file mode 100644 index 4854e2a99e..0000000000 --- a/src/components/Pokedex/PokemonAlternativeFormsList.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { Box, Container, Typography } from '@mui/material'; -import { POKEMON_FORM_ID_MAP, getPokemonFormIndexById, getPokemonImageFilename } from '../../core/pokemonFormSelector'; -import { ImageWithFallback } from '../common/ImageWithFallback'; - -export const PokemonAlternativeFormsList = ({ pokemonDexId }) => { - const allPokemonForms = POKEMON_FORM_ID_MAP[pokemonDexId].map((form) => { - const formIndex = getPokemonFormIndexById(pokemonDexId, form.pokemonId); - const formFilename = getPokemonImageFilename(pokemonDexId, formIndex); - - return { - formName: form.formName, - formFilename: formFilename, - }; - }); - - return allPokemonForms.length > 1 ? ( - - Alternative Forms - - - {allPokemonForms.map((form, i) => { - return ( - - - - {form.formName} - {i < allPokemonForms.length - 1 && ','} - - - ); - })} - - - - ) : null; -}; diff --git a/src/components/Pokedex/PokemonEggGroups.jsx b/src/components/Pokedex/PokemonEggGroups.jsx deleted file mode 100644 index 36722a2c64..0000000000 --- a/src/components/Pokedex/PokemonEggGroups.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import { Box, Container, Typography } from '@mui/material'; -import { getEggGroupNameById } from '../../utils/dex/egggroup'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -export const PokemonEggGroups = ({ eggGroupIds, sx }) => { - return ( - - Egg Groups: - - - Pokemon Egg - {eggGroupIds.map((eggGroupId, i) => { - try { - const eggGroupName = getEggGroupNameById(eggGroupId); - return ( - - {eggGroupName} - {i < eggGroupIds.length - 1 && ','} - - ); - } catch (err) { - return {err.message}; - } - })} - - - - ); -}; diff --git a/src/components/Pokedex/PokemonGenderRatio.jsx b/src/components/Pokedex/PokemonGenderRatio.jsx deleted file mode 100644 index 9a7ff9c661..0000000000 --- a/src/components/Pokedex/PokemonGenderRatio.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { Typography, Box, Container } from '@mui/material'; -import { convertGenderRatioFromDecimal } from '../../core/genderRatioConverter'; - -export const PokemonGenderRatio = ({ genderDecimalValue }) => { - const genderRatio = convertGenderRatioFromDecimal(genderDecimalValue); - - return ( - - Gender ratio: - - - - - ); -}; - -const PokemonGenderText = ({ malePercentage, femalePercentage }) => { - if (malePercentage === 0.0 && femalePercentage === 0.0) { - return 100% genderless; - } - - if (malePercentage === 100.0 && femalePercentage === 0.0) { - return 100% male; - } - - if (femalePercentage === 100.0 && malePercentage === 0.0) { - return 100% female; - } - - return ( - - {malePercentage.toFixed(2)}% male, {femalePercentage.toFixed(2)}% female - - ); -}; diff --git a/src/components/Pokedex/PokemonMovesetList.jsx b/src/components/Pokedex/PokemonMovesetList.jsx deleted file mode 100644 index f2db518191..0000000000 --- a/src/components/Pokedex/PokemonMovesetList.jsx +++ /dev/null @@ -1,182 +0,0 @@ -import { Box, Container, Typography } from '@mui/material'; -import React from 'react'; -import { POKEMON_MOVE_LEVEL_TYPE, getMoveProperties } from '../../utils/dex'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -const DMG_TYPE_ICONS = { - 0: '/img/status_dmg_type.png', - 1: '/img/phys_dmg_type.png', - 2: '/img/special_dmg_type.png', -}; - -const TYPE_COLOR_MAP = { - 0: { name: 'Normal', color: '#929da3', iconFilename: 'Normal.webp' }, - 1: { name: 'Fighting', color: '#ce436a', iconFilename: 'Fighting.webp' }, - 2: { name: 'Flying', color: '#8caadc', iconFilename: 'Flying.webp' }, - 3: { name: 'Poison', color: '#ac66c8', iconFilename: 'Poison.webp' }, - 4: { name: 'Ground', color: '#d97946', iconFilename: 'Ground.webp' }, - 5: { name: 'Rock', color: '#c7b887', iconFilename: 'Rock.webp' }, - 6: { name: 'Bug', color: '#90c127', iconFilename: 'Bug.webp' }, - 7: { name: 'Ghost', color: '#4e6caa', iconFilename: 'Ghost.webp' }, - 8: { name: 'Steel', color: '#518ea3', iconFilename: 'Steel.webp' }, - 9: { name: 'Fire', color: '#ff9d54', iconFilename: 'Fire.webp' }, - 10: { name: 'Water', color: '#4f92d6', iconFilename: 'Water.webp' }, - 11: { name: 'Grass', color: '#65bd55', iconFilename: 'Grass.webp' }, - 12: { name: 'Electric', color: '#fad143', iconFilename: 'Electric.webp' }, - 13: { name: 'Psychic', color: '#f97175', iconFilename: 'Psychic.webp' }, - 14: { name: 'Ice', color: '#72cfbd', iconFilename: 'Ice.webp' }, - 15: { name: 'Dragon', color: '#116ac4', iconFilename: 'Dragon.webp' }, - 16: { name: 'Dark', color: '#5b5464', iconFilename: 'Dark.webp' }, - 17: { name: 'Fairy', color: '#eb92e4', iconFilename: 'Fairy.webp' }, -}; - -const responsiveFontSize = { fontSize: { xs: '0.5rem', sm: '0.6rem', md: '0.9rem', lg: '1rem' } }; - -export const PokemonMovesetList = ({ moveset, movesetPrefix, pokemonDexId }) => { - if (moveset.length === 0) { - return ( - - There are no moves here. - - ); - } - - return ( - - {moveset.map((move, i) => ( - - ))} - - ); -}; - -const MoveIcon = ({ moveIconType, moveTypeId }) => { - if (typeof moveIconType === 'number') { - return ( - - {moveIconType} - - ); - } - - if (moveIconType === POKEMON_MOVE_LEVEL_TYPE.EGG) { - return ( - - Egg Move - - ); - } - - if (moveIconType === POKEMON_MOVE_LEVEL_TYPE.TM) { - return ( - - Technical Machine - - ); - } - - return null; -}; - -const MovesetListItem = ({ moveLevel, move }) => { - return ( - <> - - - - - - - {move.name} - - - - - - - - - Damage Type - - - - {move.power > 0 && ( - <> - Power - {move.power} - - )} - - - - Accuracy - {move.accuracy === 101 ? '--' : move.accuracy} - - - - PP - {move.maxPP} - - - - - {move.desc} - - - - ); -}; - -const PokemonMoveType = ({ typeName, typeColor }) => { - return ( - - - {typeName} - - - ); -}; diff --git a/src/components/Pokedex/PokemonSearch.jsx b/src/components/Pokedex/PokemonSearch.jsx deleted file mode 100644 index e24e323986..0000000000 --- a/src/components/Pokedex/PokemonSearch.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { useMemo, useState } from 'react'; -import { Autocomplete, TextField } from '@mui/material'; -import { getPokemonNames, getPokemonIdFromName } from '../../utils/dex'; -import { MAX_CURRENT_POKEMON } from '../Pokedex2/pokedexConstants'; - -export const PokemonSearch = ({ setPokemonDexId }) => { - // pokemonNameEndRange number is not including - const pokemonNames = useMemo(() => getPokemonNames(MAX_CURRENT_POKEMON + 1), []); - const [selectedPokemonName, setSelectedPokemonName] = useState(pokemonNames[1]); - const [inputValue, setInputValue] = React.useState(''); - - return ( - { - setSelectedPokemonName(newValue); - - if (!newValue) { - return; - } - - const pokemonId = getPokemonIdFromName(newValue); - setPokemonDexId(pokemonId); - }} - inputValue={inputValue} - onInputChange={(_, newInputValue) => { - setInputValue(newInputValue); - }} - renderInput={(params) => } - /> - ); -}; diff --git a/src/components/Pokedex/PokemonStats.jsx b/src/components/Pokedex/PokemonStats.jsx deleted file mode 100644 index 42a3fb8126..0000000000 --- a/src/components/Pokedex/PokemonStats.jsx +++ /dev/null @@ -1,149 +0,0 @@ -import React, { Fragment, useState } from 'react'; -import { Box, Typography, TextField } from '@mui/material'; -import { calcMaxPosStat, calcMaxStat, calcMinNegStat, calcMinStat } from '../../core/pokemonStatCalculation'; - -const POKEMON_MIN_LEVEL = 1; -const POKEMON_MAX_LEVEL = 100; - -function getStatBarValues(stat) { - let width = Math.floor((stat * 200) / 200); - if (width > 200) width = 200; - let color = Math.floor((stat * 180) / 255); - if (color > 360) color = 360; - return { width, color }; -} - -export const PokemonStats = ({ baseStats, baseStatsTotal }) => { - const [level, setLevel] = useState(100); - const pokemonStatValues = [ - { label: 'HP:', value: baseStats.hp, isHpStat: true }, - { label: 'Attack:', value: baseStats.atk, isHpStat: false }, - { label: 'Defense:', value: baseStats.def, isHpStat: false }, - { label: 'Sp.Atk:', value: baseStats.spa, isHpStat: false }, - { label: 'Sp.Def:', value: baseStats.spd, isHpStat: false }, - { label: 'Speed:', value: baseStats.spe, isHpStat: false }, - ]; - - return ( -
- - <> - - Base Stats: - - - - min- - - - - - min - - - - - max - - - - - max+ - - - - - - {pokemonStatValues.map((stat) => { - const { width, color } = getStatBarValues(stat.value); - - return ( - - - {stat.label} - - - {stat.value} - - - - - - - - - - {calcMinNegStat(stat.value, stat.isHpStat, level)} - - - - - {calcMinStat(stat.value, stat.isHpStat, level)} - - - - - {calcMaxStat(stat.value, stat.isHpStat, level)} - - - - - {calcMaxPosStat(stat.value, stat.isHpStat, level)} - - - - - ); - })} - - <> - - Total: - - - {baseStatsTotal} - - - - - - at level - - { - let value = parseInt(e.target.value); - - if (value > POKEMON_MAX_LEVEL) value = POKEMON_MAX_LEVEL; - if (value < POKEMON_MIN_LEVEL) value = POKEMON_MIN_LEVEL; - setLevel(value); - }} - label="Level" - /> - - - - -
- ); -}; - -const PokemonStatBar = ({ width, color }) => { - return ( - - ); -}; diff --git a/src/components/Pokedex/index.js b/src/components/Pokedex/index.js deleted file mode 100644 index 91032ce16a..0000000000 --- a/src/components/Pokedex/index.js +++ /dev/null @@ -1,109 +0,0 @@ -import React, { useState } from 'react'; -import style from './styles.module.css'; -import { Box, Typography, Avatar, Container } from '@mui/material'; -import { getPokemonInfo, getPokemonLearnset, getEggMoves } from '../../utils/dex'; -import Type from './type'; -import EvolutionGraph from './EvolutionGraph'; -import { PokemonStats } from './PokemonStats'; -import { PokemonSearch } from './PokemonSearch'; -import { PokemonMovesetList } from './PokemonMovesetList'; -import { PokemonAccordion } from './PokemonAccordion'; -import { PokemonAlternativeFormsList } from './PokemonAlternativeFormsList'; -import { PokemonAbilities } from './PokemonAbilities'; -import { PokemonGenderRatio } from './PokemonGenderRatio'; -import { PokemonEggGroups } from './PokemonEggGroups'; -import { getEggGroupViaPokemonId } from '../../utils/dex/egggroup'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -export default function PokedexFeatures() { - const [pokemonDexId, setPokemonDexId] = useState(1); - const pokemonInfo = getPokemonInfo(pokemonDexId ?? 0); - - const learnset = getPokemonLearnset(pokemonDexId); - const moveList = []; - for (let i = 0; i < learnset.length; i += 2) { - moveList.push({ level: learnset[i], moveId: learnset[i + 1] }); - } - - const tmLearnset = pokemonInfo.tmLearnset; - const eggLearnset = getEggMoves(pokemonDexId); - - return ( - - - - - - -
-
- - {pokemonInfo.name} - -
-
-
-
-
- {pokemonInfo.name} -
-
- -
-
- -

Size:

- {pokemonInfo.height}m, {pokemonInfo.weight}kg -
- - Grass Knot: {pokemonInfo.grassKnotPower} - -
-
-
-
- - - - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/src/components/Pokedex/styles.module.css b/src/components/Pokedex/styles.module.css deleted file mode 100644 index 3095049cb9..0000000000 --- a/src/components/Pokedex/styles.module.css +++ /dev/null @@ -1,46 +0,0 @@ -:root { - --color-vibrant-border: hsl(0 0% 0% / 0.2); - --color-vibrant-border1: hsl(0 0% 0% / 0.6); - --type-min-width: 80px; -} - -.typeBg { - margin: 4px; - padding: 4px; - background: var(--type-color, #333); - font-size: 1rem; - text-align: center; - line-height: 1.25; - font-weight: 700; - border-color: var(--color-vibrant-border); - color: #fff; - border-style: solid; - border-width: 1px; - border-radius: 0.25rem; - text-shadow: 0 1px 0 #000,0 0 1px rgba(0,0,0,.6),0 0 2px rgba(0,0,0,.7),0 0 3px rgba(0,0,0,.8),0 0 4px rgba(0,0,0,.9); - width: 30%; -} - -.bTransparent { - border-color: transparent; - border-radius: 0.125rem; - border-style: solid; - border-width: 1px; - color: #fff; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.flex { - display: flex; - flex-wrap: wrap; - gap: '0.25rem' -} - -.col { - float: left; - padding-top: 7px; - height: 22px; - font-size: 0.85rem; -} diff --git a/src/components/Pokedex/type.js b/src/components/Pokedex/type.js deleted file mode 100644 index 9d6f111ea4..0000000000 --- a/src/components/Pokedex/type.js +++ /dev/null @@ -1,60 +0,0 @@ -import React, { useState } from 'react'; -import style from './styles.module.css'; -import { Typography } from '@mui/material'; - -const TYPECOLOR_MAP = { - 'Normal': { '--type-color': '#929da3', padding: '2px' }, - 'Fighting': { '--type-color': '#ce436a', padding: '2px' }, - 'Flying': { '--type-color': '#8caadc', padding: '2px' }, - 'Poison': { '--type-color': '#ac66c8', padding: '2px' }, - 'Ground': { '--type-color': '#d97946', padding: '2px' }, - 'Rock': { '--type-color': '#c6b887', padding: '2px' }, - 'Bug': { '--type-color': '#90c127', padding: '2px' }, - 'Steel': { '--type-color': '#518ea3', padding: '2px' }, - 'Fire': { '--type-color': '#ff9d54', padding: '2px' }, - 'Water': { '--type-color': '#4f92d6', padding: '2px' }, - 'Grass': { '--type-color': '#65bd55', padding: '2px' }, - 'Electric': { '--type-color': '#fad143', padding: '2px' }, - 'Psychic': { '--type-color': '#f97175', padding: '2px' }, - 'Ice': { '--type-color': '#72cfbd', padding: '2px' }, - 'Dragon': { '--type-color': '#116ac4', padding: '2px' }, - 'Dark': { '--type-color': '#5b5464', padding: '2px' }, - 'Ghost': { '--type-color': '#4e6caa', padding: '2px' }, - 'Fairy': { '--type-color': '#eb92e4', padding: '2px' }, -} - - -export default function Type(props) { - if (!props.type1 || !props.type2) return ( -
Error acquiring types: {props.type1}, {props.type2}
- ) - - if (props.type1 === props.type2) { - return ( - - Types:
-
-
- {props.type1} -
-
-
- ) - } - - return ( - -

Types:

-
-
- {props.type1} -
-
-
-
- {props.type2} -
-
-
- ) -} \ No newline at end of file diff --git a/src/components/Pokedex2/PokemonAbilities.jsx b/src/components/Pokedex2/PokemonAbilities.jsx index ed04d4280d..eb43a31b71 100644 --- a/src/components/Pokedex2/PokemonAbilities.jsx +++ b/src/components/Pokedex2/PokemonAbilities.jsx @@ -72,7 +72,7 @@ export const PokemonAbility = ({ sx={{ textDecoration: 'underline', fontSize: '0.9rem', - marginRight: needsSpacing && '8px', + marginRight: needsSpacing ? '8px' : '', cursor: 'pointer', ...sx }} diff --git a/src/pages/dex.js b/src/pages/dex.js deleted file mode 100644 index 278aaa9585..0000000000 --- a/src/pages/dex.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import PokedexFeatures from '@site/src/components/Pokedex'; - -export default function PokedexPage() { - const { siteConfig } = useDocusaurusContext(); - - return ( - - - - ); -} diff --git a/src/utils/dex/functions.test.js b/src/utils/dex/functions.test.js index 2df2268be7..7fbc95e90a 100644 --- a/src/utils/dex/functions.test.js +++ b/src/utils/dex/functions.test.js @@ -148,7 +148,7 @@ describe('Dex utils function tests', () => { describe('3.0 Functions Tests', () => { const MODE = "3.0"; test('should return the correct Pokemon ID for a different monsno and formno', () => { - expect(getPokemonIdFromMonsNoAndForm(493, 1, MODE)).toEqual(1210); + expect(getPokemonIdFromMonsNoAndForm(493, 1, MODE)).toEqual(1212); }); it('Should return the form_no when provided accurate monsno and pokemon ID', () => { const result = getPokemonIdFromFormMap(3, 3, MODE); //Clone Venusaur diff --git a/src/utils/dex/name.test.js b/src/utils/dex/name.test.js index cff4a20e2d..6afe943acd 100644 --- a/src/utils/dex/name.test.js +++ b/src/utils/dex/name.test.js @@ -162,14 +162,14 @@ describe('Dex utils Name getters', () => { }); test('getPokemonNames() returns an array of all pokemon names when maxMonsno is greater than the number of pokemon', () => { const names = getPokemonNames(10000, 0, MODE); - expect(names).toHaveLength(1440); + expect(names).toHaveLength(1442); expect(names[0]).toBe('Egg'); expect(names[808]).toBe('Meltan'); }); it('should return the correct index for a valid form ID', () => { expect(getPokemonFormId(25, 1042, MODE)).toBe(2); expect(getPokemonFormId(133, 133, MODE)).toBe(0); - expect(getPokemonFormId(800, 1362, MODE)).toBe(2); + expect(getPokemonFormId(800, 1364, MODE)).toBe(2); }); }); }); From d755d8bff52cbddb2ac740e7d51bdba7f544f52d Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Mon, 8 Jun 2026 12:02:36 +0200 Subject: [PATCH 08/13] Clean up unused imports and fix typo --- src/components/Mapper/SearchBar.jsx | 2 -- src/components/Mapper/TabPanel/EncountersPanel.jsx | 2 +- src/components/Mapper/TabPanel/MapperTabPanel.jsx | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/Mapper/SearchBar.jsx b/src/components/Mapper/SearchBar.jsx index 2f0338430e..abed268033 100644 --- a/src/components/Mapper/SearchBar.jsx +++ b/src/components/Mapper/SearchBar.jsx @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react'; import IconButton from '@mui/material/IconButton'; import SettingsIcon from '@mui/icons-material/Settings'; import { Autocomplete, TextField, createFilterOptions } from '@mui/material'; -import Fuse from 'fuse.js'; const trainerFilterOptions = createFilterOptions({ limit: 100, @@ -68,7 +67,6 @@ const LocationNameDropdown = ({ locationName, setLocationName, setLocationZoneId, - canvasRef }) => { const locations = getLocationNames(); const handleLocationChange = (e, value, reason) => { diff --git a/src/components/Mapper/TabPanel/EncountersPanel.jsx b/src/components/Mapper/TabPanel/EncountersPanel.jsx index 718825f2c3..144483a87c 100644 --- a/src/components/Mapper/TabPanel/EncountersPanel.jsx +++ b/src/components/Mapper/TabPanel/EncountersPanel.jsx @@ -32,7 +32,7 @@ const EncountersPanel = ({ encOptions, handleOptionChange, encounterList, pokemo }; const getGroundTextColor = () => { - if (encounterList.GroundEnc.lenth === 0) { + if (encounterList.GroundEnc.length === 0) { return modeChangeTextColor; } else if (groundEncountersIds.includes(routeId)) { return "#000000" diff --git a/src/components/Mapper/TabPanel/MapperTabPanel.jsx b/src/components/Mapper/TabPanel/MapperTabPanel.jsx index 0f8b3e2634..5440a06827 100644 --- a/src/components/Mapper/TabPanel/MapperTabPanel.jsx +++ b/src/components/Mapper/TabPanel/MapperTabPanel.jsx @@ -17,12 +17,11 @@ export const MapperTabPanel = ({ setSelectedTrainer, openTrainerModal, routeId, - defaultTab = 0, selectedTab, onTabChange, }) => { return ( - + Date: Mon, 8 Jun 2026 12:09:24 +0200 Subject: [PATCH 09/13] Fix mapper settings button --- src/components/Mapper/style.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/Mapper/style.css b/src/components/Mapper/style.css index f8c47c15df..30c33b4dcc 100755 --- a/src/components/Mapper/style.css +++ b/src/components/Mapper/style.css @@ -53,11 +53,13 @@ .infoCol { position: absolute; top: 122px; - justify-content: end; display: grid; grid-template-rows: auto auto auto; + align-content: start; + justify-content: end; pointer-events: none; touch-action: manipulation; + overflow: hidden; } .monSearchBar { @@ -74,13 +76,11 @@ } .settings { - display: grid; - align-content: end; - justify-content: end; + position: absolute; + bottom: 10px; + right: 10px; width: fit-content; height: fit-content; - margin-left: 16rem; - margin-top: 36rem; pointer-events: auto; } From a11e237e3c27207a9ce636f659dd4cf41390f393 Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:18:01 +0200 Subject: [PATCH 10/13] Address PR comments: - Simplify PokemonTabs to just use the controlled selectedTab from the parent instead of juggling internal and controlled state - Combine the two separate useEffect hooks in Mapper into one - Normalize trainer_id to trainerId - Replace the hardcoded filterOptions limit on the trainer search with a ListboxComponent using react-window, so the dropdown handles the full list without an arbitrary cap (could be applied to the other searchbars?) --- src/components/Mapper/Mapper.jsx | 25 ++++------ src/components/Mapper/SearchBar.jsx | 46 ++++++++++++++++--- .../Mapper/TabPanel/PokemonTabs.jsx | 8 +--- src/components/Mapper/Trainers/Trainers.jsx | 2 +- .../Mapper/Trainers/TrainersModal.jsx | 8 ++-- src/utils/dex/trainers.js | 6 +-- 6 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index a7448bfc44..560da77e33 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -54,7 +54,7 @@ const canvasDimensions = { height: 720 } -const versionNumber = "Beta 1.2.0"; +const versionNumber = "Beta 1.2.1"; export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const isBrowser = useIsBrowser(); @@ -124,23 +124,16 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setSelectedZone(location.name); } handleSetLocationZoneId(zoneId); + + const trainers = getTrainersFromZoneId(zoneId, GAMEDATA3); + const trainer = trainers.find(t => t.trainerId === parseInt(trainerId)); + if (trainer) { + setSelectedTrainer(trainer); + setShowTrainerModal(true); + } } } }, []); - - // Select trainer after trainerList is populated - useEffect(() => { - const params = new URLSearchParams(window.location.search); - const trainerId = params.get('trainerId'); - - if (trainerId && trainerList.length > 0) { - const trainer = trainerList.find(t => t.trainer_id === parseInt(trainerId)); - if (trainer) { - setSelectedTrainer(trainer); - setShowTrainerModal(true); - } - } - }, [trainerList]); const locationId = useRef(null); useEffect(() => { if(locationId !== null) { @@ -169,7 +162,7 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setSelectedZone(location.name); } handleSetLocationZoneId(zoneId); - const fullTrainer = getFullTrainerById(trainer.trainer_id, GAMEDATA3); + const fullTrainer = getFullTrainerById(trainer.trainerId, GAMEDATA3); setSelectedTrainer(fullTrainer || trainer); setShowTrainerModal(true); setSelectedTab(1); diff --git a/src/components/Mapper/SearchBar.jsx b/src/components/Mapper/SearchBar.jsx index abed268033..ebbc253ff1 100644 --- a/src/components/Mapper/SearchBar.jsx +++ b/src/components/Mapper/SearchBar.jsx @@ -1,11 +1,8 @@ import React, { useEffect, useState } from 'react'; import IconButton from '@mui/material/IconButton'; import SettingsIcon from '@mui/icons-material/Settings'; -import { Autocomplete, TextField, createFilterOptions } from '@mui/material'; - -const trainerFilterOptions = createFilterOptions({ - limit: 100, -}); +import { Autocomplete, TextField } from '@mui/material'; +import { FixedSizeList } from 'react-window'; import { getLocationCoordsFromName, getLocationNames } from './coordinates'; import './style.css'; @@ -107,6 +104,43 @@ const LocationNameDropdown = ({ ); }; +const LISTBOX_PADDING = 8; +const ITEM_SIZE = 48; +const MAX_VISIBLE_ITEMS = 8; + +const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { + const { children, ...other } = props; + const itemData = React.Children.toArray(children); + const itemCount = itemData.length; + + const height = itemCount > MAX_VISIBLE_ITEMS + ? MAX_VISIBLE_ITEMS * ITEM_SIZE + 2 * LISTBOX_PADDING + : itemCount * ITEM_SIZE + 2 * LISTBOX_PADDING; + + return ( +
+ + {({ data, index, style }) => + React.cloneElement(data[index], { + style: { + ...data[index].props.style, + ...style, + }, + }) + } + +
+ ); +}); + const TrainerSearchInput = ({ allTrainers, onTrainerSelect, @@ -136,7 +170,7 @@ const TrainerSearchInput = ({ clearOnBlur={false} blurOnSelect options={allTrainers} - filterOptions={trainerFilterOptions} + ListboxComponent={ListboxComponent} getOptionLabel={(option) => option.label} value={selectedTrainer} onChange={handleTrainerChange} diff --git a/src/components/Mapper/TabPanel/PokemonTabs.jsx b/src/components/Mapper/TabPanel/PokemonTabs.jsx index b4896b2ac8..d0cdd96b64 100644 --- a/src/components/Mapper/TabPanel/PokemonTabs.jsx +++ b/src/components/Mapper/TabPanel/PokemonTabs.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Box, Tab, Tabs } from '@mui/material'; const PokemonPanel = ({ id, selectedTab, children }) => { @@ -31,17 +31,13 @@ const PokemonTabs = ({ tabNames, selectedTab, handleTabChange }) => { const PokemonTabPanel = ({ tabNames, children, - initialTab = 0, - selectedTab: controlledTab, + selectedTab = 0, onTabChange, }) => { - const [internalTab, setInternalTab] = useState(initialTab); - const selectedTab = controlledTab !== undefined ? controlledTab : internalTab; const handleTabChange = (event, newTab) => { if (onTabChange) { onTabChange(newTab); } - setInternalTab(newTab); }; return ( diff --git a/src/components/Mapper/Trainers/Trainers.jsx b/src/components/Mapper/Trainers/Trainers.jsx index 98cdf4cf23..184bda492e 100644 --- a/src/components/Mapper/Trainers/Trainers.jsx +++ b/src/components/Mapper/Trainers/Trainers.jsx @@ -53,7 +53,7 @@ export const TrainerDropdown = ({ trainer, setTrainer, trainerList, smallest }) `${option.team_name} (${option.trainer_id})`} + getOptionLabel={(option) => `${option.team_name} (${option.trainerId ?? option.trainer_id})`} defaultValue={defaultTrainer} value={trainer} onChange={(e, value) => setTrainer(value)} diff --git a/src/components/Mapper/Trainers/TrainersModal.jsx b/src/components/Mapper/Trainers/TrainersModal.jsx index 2712897fe1..d4fd89aa48 100644 --- a/src/components/Mapper/Trainers/TrainersModal.jsx +++ b/src/components/Mapper/Trainers/TrainersModal.jsx @@ -31,9 +31,9 @@ const TrainersModal = ({ }; const handleOpenShowdown = () => { - if (!selectedTrainer?.trainer_id) return; + if (!selectedTrainer?.trainerId) return; - const url = `https://calc.relumishowdown.dpdns.org/?mode=ingame&setSource=ingame&trainerId=${selectedTrainer.trainer_id}`; + const url = `https://calc.relumishowdown.dpdns.org/?mode=ingame&setSource=ingame&trainerId=${selectedTrainer.trainerId}`; window.open(url, '_blank', 'noopener,noreferrer'); }; @@ -69,7 +69,7 @@ ${moves}`; maxWidth="1108px" > - Trainer: {selectedTrainer?.team_name} ({selectedTrainer?.trainer_id}) + Trainer: {selectedTrainer?.team_name} ({selectedTrainer?.trainerId}) ({ ...t, trainerId: t.trainer_id })); } console.warn(`${zoneKey} is not in the Trainer List.`); return []; @@ -37,7 +37,7 @@ function getFullTrainerById(trainerId, mode = GAMEDATA2) { const trainers = TrainerLocations[mode][zoneKey]; const trainer = trainers.find(t => t.trainer_id === parseInt(trainerId)); if (trainer) { - return { ...trainer, zoneId: parseInt(zoneKey) }; + return { ...trainer, trainerId: trainer.trainer_id, zoneId: parseInt(zoneKey) }; } } @@ -52,7 +52,7 @@ function getAllTrainers(mode = GAMEDATA2) { if (seen.has(trainer.trainer_id)) continue; seen.add(trainer.trainer_id); trainers.push({ - trainer_id: trainer.trainer_id, + trainerId: trainer.trainer_id, zoneId: parseInt(zoneKey), name: trainer.name, route: trainer.route, From 9a2c949d465af67c33aaeaa215245b0c205a2d10 Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:28:25 +0200 Subject: [PATCH 11/13] Change MAX_VISIBLE_ITEMS of trainer search bar to 14 to match other lists --- src/components/Mapper/SearchBar.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Mapper/SearchBar.jsx b/src/components/Mapper/SearchBar.jsx index ebbc253ff1..75e0a5e33c 100644 --- a/src/components/Mapper/SearchBar.jsx +++ b/src/components/Mapper/SearchBar.jsx @@ -106,7 +106,7 @@ const LocationNameDropdown = ({ const LISTBOX_PADDING = 8; const ITEM_SIZE = 48; -const MAX_VISIBLE_ITEMS = 8; +const MAX_VISIBLE_ITEMS = 14; const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { const { children, ...other } = props; @@ -238,4 +238,4 @@ export const SearchBar = ({
) -}; \ No newline at end of file +}; From 8eb49d94d307fec3b8cca6b7342581430a06ea2d Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:06:11 +0200 Subject: [PATCH 12/13] Fix scrollbar duplication in trainer search bar --- src/components/Mapper/SearchBar.jsx | 55 +++++++++++++++++++---------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/components/Mapper/SearchBar.jsx b/src/components/Mapper/SearchBar.jsx index 75e0a5e33c..efc620e3dd 100644 --- a/src/components/Mapper/SearchBar.jsx +++ b/src/components/Mapper/SearchBar.jsx @@ -108,6 +108,28 @@ const LISTBOX_PADDING = 8; const ITEM_SIZE = 48; const MAX_VISIBLE_ITEMS = 14; +function renderRow(props) { + const { data, index, style } = props; + const inlineStyle = { + ...style, + top: (style.top ?? 0) + LISTBOX_PADDING, + }; + + return React.cloneElement(data[index], { + style: { + ...data[index].props.style, + ...inlineStyle, + }, + }); +} + +const OuterElementContext = React.createContext({}); + +const OuterElementType = React.forwardRef(function OuterElementType(props, ref) { + const outerProps = React.useContext(OuterElementContext); + return
; +}); + const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { const { children, ...other } = props; const itemData = React.Children.toArray(children); @@ -118,25 +140,20 @@ const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) : itemCount * ITEM_SIZE + 2 * LISTBOX_PADDING; return ( -
- - {({ data, index, style }) => - React.cloneElement(data[index], { - style: { - ...data[index].props.style, - ...style, - }, - }) - } - +
+ + + {renderRow} + +
); }); From 0f305e88e5e9293588185f17887462b3558ff38b Mon Sep 17 00:00:00 2001 From: BlupBlurp <44441061+BlupBlurp@users.noreply.github.com> Date: Sun, 21 Jun 2026 02:44:24 +0200 Subject: [PATCH 13/13] Clear trainer SearchBar when the location or trainer selection changes --- src/components/Mapper/Mapper.jsx | 16 + src/components/Mapper/SearchBar.jsx | 528 ++++++++++++++-------------- 2 files changed, 286 insertions(+), 258 deletions(-) diff --git a/src/components/Mapper/Mapper.jsx b/src/components/Mapper/Mapper.jsx index 560da77e33..9c9e6c2b1c 100644 --- a/src/components/Mapper/Mapper.jsx +++ b/src/components/Mapper/Mapper.jsx @@ -81,6 +81,9 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const [trainerList, setTrainerList] = useState([]); const [showTrainerModal, setShowTrainerModal] = useState(false); + const [searchBarTrainer, setSearchBarTrainer] = useState(null); + const skipSearchClear = useRef(false); + const [showSettings, setShowSettings] = useState(false); const [colors, setColors] = useState({ hov: { r: 247, g: 100, b: 200, a: 0.7 }, @@ -145,6 +148,15 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { setEncounterLocations(getMapperRoutesFromPokemonId(selectedPokemon?.id, GAMEDATA3)); }, [selectedPokemon]); + // Clear SearchBar trainer selection when location or selected trainer changes + useEffect(() => { + if (skipSearchClear.current) { + skipSearchClear.current = false; + return; + } + setSearchBarTrainer(null); + }, [selectedZone, selectedTrainer]); + const openTrainerModal = () => { setShowTrainerModal(true); }; @@ -155,6 +167,8 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { const allTrainers = React.useMemo(() => getAllTrainers(GAMEDATA3), []); const handleTrainerSelect = (trainer) => { + skipSearchClear.current = true; + setSearchBarTrainer(trainer); const zoneId = trainer.zoneId; if (zoneId || zoneId === 0) { const location = getLocationCoordsFromZoneId(zoneId); @@ -383,6 +397,8 @@ export const Mapper = ({ pokemonList3, pokemonList, pokemonListV }) => { handleShowSettings={handleShowSettings} allTrainers={allTrainers} onTrainerSelect={handleTrainerSelect} + searchBarTrainer={searchBarTrainer} + setSearchBarTrainer={setSearchBarTrainer} /> { - const [searchText, setSearchText] = useState(""); - - useEffect(() => { - const timer = setTimeout(() => { - setDebouncedText(searchText); - }, 300); - return () => clearTimeout(timer); - }, [searchText, setDebouncedText]); - - const handlePokemonNameChange = (_, value, reason) => { - if (reason !== "clear" && value) { - setSelectedPokemon(value); - setSearchText(value?.name ?? ""); - } else { - setSelectedPokemon(null); - setSearchText(""); - } - }; - - const handleInputChange = (_, value) => { - setSearchText(value); - }; - - return ( -
- option.name} - value={selectedPokemon} - onChange={handlePokemonNameChange} - inputValue={searchText} - onInputChange={handleInputChange} - renderInput={(params) => ( - - )} - /> -
- ); -}; - -const LocationNameDropdown = ({ - locationName, - setLocationName, - setLocationZoneId, -}) => { - const locations = getLocationNames(); - const handleLocationChange = (e, value, reason) => { - if (reason !== "clear" && value) { - setLocationName(value); - const location = getLocationCoordsFromName(value); - setLocationZoneId(location?.zoneId); - } else { - setLocationName(null); - setLocationZoneId(null); - } - }; - - const defaultOption = locations.length > 0 ? locations[0] : ''; - return ( -
- option} - value={locationName} - onChange={handleLocationChange} - inputValue={locationName ?? ""} - onInputChange={(_, value) => { - setLocationName(value); - }} - renderInput={(params) => ( - - )} - /> -
- ); -}; - -const LISTBOX_PADDING = 8; -const ITEM_SIZE = 48; -const MAX_VISIBLE_ITEMS = 14; - -function renderRow(props) { - const { data, index, style } = props; - const inlineStyle = { - ...style, - top: (style.top ?? 0) + LISTBOX_PADDING, - }; - - return React.cloneElement(data[index], { - style: { - ...data[index].props.style, - ...inlineStyle, - }, - }); -} - -const OuterElementContext = React.createContext({}); - -const OuterElementType = React.forwardRef(function OuterElementType(props, ref) { - const outerProps = React.useContext(OuterElementContext); - return
; -}); - -const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { - const { children, ...other } = props; - const itemData = React.Children.toArray(children); - const itemCount = itemData.length; - - const height = itemCount > MAX_VISIBLE_ITEMS - ? MAX_VISIBLE_ITEMS * ITEM_SIZE + 2 * LISTBOX_PADDING - : itemCount * ITEM_SIZE + 2 * LISTBOX_PADDING; - - return ( -
- - - {renderRow} - - -
- ); -}); - -const TrainerSearchInput = ({ - allTrainers, - onTrainerSelect, -}) => { - const [searchText, setSearchText] = useState(""); - const [selectedTrainer, setSelectedTrainer] = useState(null); - - const handleTrainerChange = (_, value, reason) => { - if (reason !== "clear" && value) { - setSelectedTrainer(value); - setSearchText(value.label); - onTrainerSelect(value); - } else { - setSelectedTrainer(null); - setSearchText(""); - } - }; - - const handleInputChange = (_, value) => { - setSearchText(value); - }; - - return ( -
- option.label} - value={selectedTrainer} - onChange={handleTrainerChange} - inputValue={searchText} - onInputChange={handleInputChange} - renderInput={(params) => ( - - )} - /> -
- ); -}; - -const SettingsButton = ({handleShowSettings}) => { - return ( -
- - - -
- ); -} - -export const SearchBar = ({ - canvasDimensions, - pokemonList, - handleDebouncedTextChange, - locationName, - setLocationName, - setLocationZoneId, - canvasRef, - selectedPokemon, - setSelectedPokemon, - handleShowSettings, - allTrainers, - onTrainerSelect, -}) => { - return ( -
- - - - -
- ) -}; +import React, { useEffect, useState } from 'react'; +import IconButton from '@mui/material/IconButton'; +import SettingsIcon from '@mui/icons-material/Settings'; +import { Autocomplete, TextField } from '@mui/material'; +import { FixedSizeList } from 'react-window'; + +import { getLocationCoordsFromName, getLocationNames } from './coordinates'; +import './style.css'; + +const PokemonSearchInput = ({ + allPokemons, + setDebouncedText, + selectedPokemon, + setSelectedPokemon, +}) => { + const [searchText, setSearchText] = useState(""); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedText(searchText); + }, 300); + return () => clearTimeout(timer); + }, [searchText, setDebouncedText]); + + const handlePokemonNameChange = (_, value, reason) => { + if (reason !== "clear" && value) { + setSelectedPokemon(value); + setSearchText(value?.name ?? ""); + } else { + setSelectedPokemon(null); + setSearchText(""); + } + }; + + const handleInputChange = (_, value) => { + setSearchText(value); + }; + + return ( +
+ option.name} + value={selectedPokemon} + onChange={handlePokemonNameChange} + inputValue={searchText} + onInputChange={handleInputChange} + renderInput={(params) => ( + + )} + /> +
+ ); +}; + +const LocationNameDropdown = ({ + locationName, + setLocationName, + setLocationZoneId, +}) => { + const locations = getLocationNames(); + const handleLocationChange = (e, value, reason) => { + if (reason !== "clear" && value) { + setLocationName(value); + const location = getLocationCoordsFromName(value); + setLocationZoneId(location?.zoneId); + } else { + setLocationName(null); + setLocationZoneId(null); + } + }; + + const defaultOption = locations.length > 0 ? locations[0] : ''; + return ( +
+ option} + value={locationName} + onChange={handleLocationChange} + inputValue={locationName ?? ""} + onInputChange={(_, value) => { + setLocationName(value); + }} + renderInput={(params) => ( + + )} + /> +
+ ); +}; + +const LISTBOX_PADDING = 8; +const ITEM_SIZE = 48; +const MAX_VISIBLE_ITEMS = 14; + +function renderRow(props) { + const { data, index, style } = props; + const inlineStyle = { + ...style, + top: (style.top ?? 0) + LISTBOX_PADDING, + }; + + return React.cloneElement(data[index], { + style: { + ...data[index].props.style, + ...inlineStyle, + }, + }); +} + +const OuterElementContext = React.createContext({}); + +const OuterElementType = React.forwardRef(function OuterElementType(props, ref) { + const outerProps = React.useContext(OuterElementContext); + return
; +}); + +const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { + const { children, ...other } = props; + const itemData = React.Children.toArray(children); + const itemCount = itemData.length; + + const height = itemCount > MAX_VISIBLE_ITEMS + ? MAX_VISIBLE_ITEMS * ITEM_SIZE + 2 * LISTBOX_PADDING + : itemCount * ITEM_SIZE + 2 * LISTBOX_PADDING; + + return ( +
+ + + {renderRow} + + +
+ ); +}); + +const TrainerSearchInput = ({ + allTrainers, + onTrainerSelect, + value, + onChange, +}) => { + const [searchText, setSearchText] = useState(""); + + // Clear internal text when value is cleared externally + useEffect(() => { + if (!value) { + setSearchText(""); + } + }, [value]); + + const handleTrainerChange = (_, newValue, reason) => { + if (reason !== "clear" && newValue) { + onChange(newValue); + setSearchText(newValue.label); + onTrainerSelect(newValue); + } else { + onChange(null); + setSearchText(""); + } + }; + + const handleInputChange = (_, newInputValue) => { + setSearchText(newInputValue); + }; + + return ( +
+ option.label} + value={value} + onChange={handleTrainerChange} + inputValue={searchText} + onInputChange={handleInputChange} + renderInput={(params) => ( + + )} + /> +
+ ); +}; + +const SettingsButton = ({handleShowSettings}) => { + return ( +
+ + + +
+ ); +} + +export const SearchBar = ({ + canvasDimensions, + pokemonList, + handleDebouncedTextChange, + locationName, + setLocationName, + setLocationZoneId, + canvasRef, + selectedPokemon, + setSelectedPokemon, + handleShowSettings, + allTrainers, + onTrainerSelect, + searchBarTrainer, + setSearchBarTrainer, +}) => { + return ( +
+ + + + +
+ ) +};