Skip to content

Commit

Permalink
feat: Allow <Pin> glyphs to be passed as children (close #98) (#99)
Browse files Browse the repository at this point in the history
Allows the glyph prop of to be passed via JSX children. Functionality is implemented like discussed in #98.
  • Loading branch information
benschlegel authored Nov 28, 2023
1 parent b834a7d commit 6374453
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
6 changes: 6 additions & 0 deletions examples/markers-and-infowindows/assets/info-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions examples/markers-and-infowindows/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ const App = () => {
glyphColor={'#0f677a'}></Pin>
</AdvancedMarker>

{/* advanced marker with html pin glyph */}
<AdvancedMarker
position={{lat: 15, lng: 20}}
title={'AdvancedMarker with customized pin.'}>
<Pin background={'#22ccff'} borderColor={'#1e89a1'} scale={1.4}>
{/* child gets rendered as 'glyph' element of pin */}
<img
src="../assets/info-circle.svg"
style={{height: '24px', width: '24px'}}
/>
</Pin>
</AdvancedMarker>

{/* advanced marker with html-content */}
<AdvancedMarker
position={{lat: 30, lng: 10}}
Expand Down
33 changes: 30 additions & 3 deletions src/components/pin.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import {useContext, useEffect} from 'react';
import {
Children,
PropsWithChildren,
useContext,
useEffect,
useMemo
} from 'react';
import {AdvancedMarkerContext} from './advanced-marker';
import {createPortal} from 'react-dom';
import {logErrorOnce} from '../libraries/errors';

/**
* Props for the Pin component
Expand All @@ -9,8 +17,9 @@ export type PinProps = google.maps.marker.PinElementOptions;
/**
* Component to render a google maps marker Pin View
*/
export const Pin = (props: PinProps) => {
export const Pin = (props: PropsWithChildren<PinProps>) => {
const advancedMarker = useContext(AdvancedMarkerContext)?.marker;
const glyphContainer = useMemo(() => document.createElement('div'), []);

// Create Pin View instance
useEffect(() => {
Expand All @@ -24,15 +33,33 @@ export const Pin = (props: PinProps) => {
return;
}

if (props.glyph && props.children) {
logErrorOnce(
'The <Pin> component only uses children to render the glyph if both the glyph property and children are present.'
);
}

if (Children.count(props.children) > 1) {
logErrorOnce(
'Passing multiple children to the <Pin> component might lead to unexpected results.'
);
}

const pinViewOptions: google.maps.marker.PinElementOptions = {
...props
};

const pinElement = new google.maps.marker.PinElement(pinViewOptions);

// Set glyph to glyph container if children are present (rendered via portal).
// If both props.glyph and props.children are present, props.children takes priority.
if (props.children) {
pinElement.glyph = glyphContainer;
}

// Set content of Advanced Marker View to the Pin View element
advancedMarker.content = pinElement.element;
}, [advancedMarker, props]);

Check warning on line 62 in src/components/pin.tsx

View workflow job for this annotation

GitHub Actions / test

React Hook useEffect has a missing dependency: 'glyphContainer'. Either include it or remove the dependency array

return null;
return createPortal(props.children, glyphContainer);
};

0 comments on commit 6374453

Please sign in to comment.