Skip to content

Commit e74d8fc

Browse files
committed
refactor: replace map-div with gmp-map custom element
1 parent 5386035 commit e74d8fc

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

examples/basic-map/src/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const API_KEY =
88
globalThis.GOOGLE_MAPS_API_KEY ?? (process.env.GOOGLE_MAPS_API_KEY as string);
99

1010
const App = () => (
11-
<APIProvider apiKey={API_KEY}>
11+
<APIProvider apiKey={API_KEY} version={'beta'}>
1212
<Map
1313
defaultZoom={3}
1414
defaultCenter={{lat: 22.54992, lng: 0}}

examples/multiple-maps/src/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const App = () => {
4141
}, []);
4242

4343
return (
44-
<APIProvider apiKey={API_KEY}>
44+
<APIProvider apiKey={API_KEY} version={'beta'}>
4545
<div
4646
style={{
4747
height: '100%',

src/components/map/index.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
/* eslint-disable complexity */
22
import React, {
33
CSSProperties,
4+
DOMAttributes,
45
PropsWithChildren,
6+
RefAttributes,
57
useContext,
68
useEffect,
79
useLayoutEffect,
@@ -185,18 +187,39 @@ export const Map = (props: PropsWithChildren<MapProps>) => {
185187
}
186188

187189
return (
188-
<div
190+
<gmp-map
189191
ref={mapRef}
190192
data-testid={'map'}
191-
style={className ? undefined : combinedStyle}
193+
style={className ? undefined : (combinedStyle as CSSStyleDeclaration)}
192194
className={className}
193195
{...(id ? {id} : {})}>
194196
{map ? (
195197
<GoogleMapsContext.Provider value={contextValue}>
196198
{children}
197199
</GoogleMapsContext.Provider>
198200
) : null}
199-
</div>
201+
</gmp-map>
200202
);
201203
};
204+
202205
Map.deckGLViewProps = true;
206+
207+
type CustomElement<T> = Partial<
208+
T &
209+
DOMAttributes<T> &
210+
RefAttributes<T> & {
211+
// for whatever reason, anything else doesn't work as children
212+
// of a custom element, so we allow `any` here
213+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
214+
children: any;
215+
}
216+
>;
217+
218+
declare global {
219+
// eslint-disable-next-line @typescript-eslint/no-namespace
220+
namespace JSX {
221+
interface IntrinsicElements {
222+
['gmp-map']: CustomElement<google.maps.MapElement>;
223+
}
224+
}
225+
}

src/components/map/use-map-instance.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import {
1111
useTrackedCameraStateRef
1212
} from './use-tracked-camera-state-ref';
1313

14+
function useMapElementDefined() {
15+
const [isDefined, setIsDefined] = useState(false);
16+
17+
useEffect(() => {
18+
customElements.whenDefined('gmp-map').then(() => setIsDefined(true));
19+
}, []);
20+
21+
return isDefined;
22+
}
23+
1424
/**
1525
* The main hook takes care of creating map-instances and registering them in
1626
* the api-provider context.
@@ -23,12 +33,13 @@ export function useMapInstance(
2333
context: APIProviderContextValue
2434
): readonly [
2535
map: google.maps.Map | null,
26-
containerRef: Ref<HTMLDivElement>,
36+
containerRef: Ref<google.maps.MapElement>,
2737
cameraStateRef: CameraStateRef
2838
] {
2939
const apiIsLoaded = useApiIsLoaded();
40+
const mapElementDefined = useMapElementDefined();
3041
const [map, setMap] = useState<google.maps.Map | null>(null);
31-
const [container, containerRef] = useCallbackRef<HTMLDivElement>();
42+
const [container, containerRef] = useCallbackRef<google.maps.MapElement>();
3243

3344
const cameraStateRef = useTrackedCameraStateRef(map);
3445

@@ -63,11 +74,13 @@ export function useMapInstance(
6374
// create the map instance and register it in the context
6475
useEffect(
6576
() => {
66-
if (!container || !apiIsLoaded) return;
77+
if (!container || !apiIsLoaded || !mapElementDefined) return;
6778

6879
const {addMapInstance, removeMapInstance} = context;
6980
const mapId = props.mapId;
70-
const newMap = new google.maps.Map(container, mapOptions);
81+
// const newMap = new google.maps.Map(container, mapOptions);
82+
const newMap = container.innerMap;
83+
newMap.setOptions(mapOptions);
7184

7285
setMap(newMap);
7386
addMapInstance(newMap, id);
@@ -105,7 +118,7 @@ export function useMapInstance(
105118
// changes should be ignored
106119
// - mapOptions has special hooks that take care of updating the options
107120
// eslint-disable-next-line react-hooks/exhaustive-deps
108-
[container, apiIsLoaded, id, props.mapId]
121+
[container, apiIsLoaded, mapElementDefined, id, props.mapId]
109122
);
110123

111124
return [map, containerRef, cameraStateRef] as const;

0 commit comments

Comments
 (0)