-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The MapControl component allows users to add custom react components to the controls of a Map instance.
- Loading branch information
1 parent
9fa403b
commit 110247b
Showing
3 changed files
with
110 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import '@testing-library/jest-dom'; | ||
|
||
import React, {ReactElement} from 'react'; | ||
import {initialize} from '@googlemaps/jest-mocks'; | ||
import {cleanup, render} from '@testing-library/react'; | ||
|
||
import {APIProvider} from '../api-provider'; | ||
import {Map} from '../map'; | ||
import {ControlPosition, MapControl} from '../map-control'; | ||
import {waitForMockInstance} from './__utils__/wait-for-mock-instance'; | ||
|
||
jest.mock('../../libraries/google-maps-api-loader'); | ||
|
||
let wrapper: ({children}: {children: React.ReactNode}) => ReactElement | null; | ||
|
||
beforeEach(() => { | ||
initialize(); | ||
|
||
wrapper = ({children}: {children: React.ReactNode}) => ( | ||
<APIProvider apiKey={'apikey'}> | ||
<Map zoom={10} center={{lat: 0, lng: 0}}> | ||
{children} | ||
</Map> | ||
</APIProvider> | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
cleanup(); | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
test('control is added to the map', async () => { | ||
render( | ||
<MapControl position={ControlPosition.TOP_LEFT}> | ||
<button>control button</button> | ||
</MapControl>, | ||
{wrapper} | ||
); | ||
|
||
const map = await waitForMockInstance(google.maps.Map); | ||
const controlsArray = map.controls[google.maps.ControlPosition.TOP_LEFT]; | ||
|
||
expect(controlsArray.push).toHaveBeenCalled(); | ||
|
||
const [controlEl] = (controlsArray.push as jest.Mock).mock.calls[0]; | ||
expect(controlEl).toHaveTextContent('control button'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {useEffect, useMemo} from 'react'; | ||
import {createPortal} from 'react-dom'; | ||
import {useMap} from '../hooks/use-map'; | ||
|
||
import type {PropsWithChildren} from 'react'; | ||
|
||
type MapControlProps = PropsWithChildren<{ | ||
position: ControlPosition; | ||
}>; | ||
|
||
/** | ||
* Names of the `google.maps.ControlPosition` constants. | ||
* They have to be duplicated here since we can't wait for the maps API to load. | ||
*/ | ||
export enum ControlPosition { | ||
BLOCK_END_INLINE_CENTER = 'BLOCK_END_INLINE_CENTER', | ||
BLOCK_END_INLINE_END = 'BLOCK_END_INLINE_END', | ||
BLOCK_END_INLINE_START = 'BLOCK_END_INLINE_START', | ||
BLOCK_START_INLINE_CENTER = 'BLOCK_START_INLINE_CENTER', | ||
BLOCK_START_INLINE_END = 'BLOCK_START_INLINE_END', | ||
BLOCK_START_INLINE_START = 'BLOCK_START_INLINE_START', | ||
BOTTOM_CENTER = 'BOTTOM_CENTER', | ||
BOTTOM_LEFT = 'BOTTOM_LEFT', | ||
BOTTOM_RIGHT = 'BOTTOM_RIGHT', | ||
INLINE_END_BLOCK_CENTER = 'INLINE_END_BLOCK_CENTER', | ||
INLINE_END_BLOCK_END = 'INLINE_END_BLOCK_END', | ||
INLINE_END_BLOCK_START = 'INLINE_END_BLOCK_START', | ||
INLINE_START_BLOCK_CENTER = 'INLINE_START_BLOCK_CENTER', | ||
INLINE_START_BLOCK_END = 'INLINE_START_BLOCK_END', | ||
INLINE_START_BLOCK_START = 'INLINE_START_BLOCK_START', | ||
LEFT_BOTTOM = 'LEFT_BOTTOM', | ||
LEFT_CENTER = 'LEFT_CENTER', | ||
LEFT_TOP = 'LEFT_TOP', | ||
RIGHT_BOTTOM = 'RIGHT_BOTTOM', | ||
RIGHT_CENTER = 'RIGHT_CENTER', | ||
RIGHT_TOP = 'RIGHT_TOP', | ||
TOP_CENTER = 'TOP_CENTER', | ||
TOP_LEFT = 'TOP_LEFT', | ||
TOP_RIGHT = 'TOP_RIGHT' | ||
} | ||
|
||
export const MapControl = ({children, position}: MapControlProps) => { | ||
const controlContainer = useMemo(() => document.createElement('div'), []); | ||
const map = useMap(); | ||
|
||
useEffect(() => { | ||
if (!map) return; | ||
|
||
const controlPosition = google.maps.ControlPosition[position]; | ||
const controls = map.controls[controlPosition]; | ||
|
||
controls.push(controlContainer); | ||
|
||
return () => { | ||
const index = controls.getArray().indexOf(controlContainer); | ||
controls.removeAt(index); | ||
}; | ||
}, [map, position]); | ||
|
||
return createPortal(children, controlContainer); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters