Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/api-reference/components/advanced-marker.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ marker will be clickable and will be interactive for accessibility purposes
By default, this will automatically be set to true when the `onClick` prop
is specified.

It is also automatically set to true when `onKeyDown` or `onKeyUp` is
specified.

#### `draggable`: boolean

Controls if the marker can be repositioned by dragging.
Expand All @@ -223,6 +226,14 @@ specified in the position can't be dragged.

This event is fired when the marker is clicked.

#### `onKeyDown`: (e: KeyboardEvent) => void

This event is fired when a key is pressed while the marker is focused.

#### `onKeyUp`: (e: KeyboardEvent) => void

This event is fired when a pressed key is released while the marker is focused.

#### `onMouseEnter`: (e: [google.maps.MapMouseEvent['domEvent']][gmp-map-mouse-ev-dom]) => void

This event is fired when the mouse enters the marker.
Expand Down
54 changes: 52 additions & 2 deletions src/components/__tests__/advanced-marker.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React from 'react';

import {initialize, mockInstances} from '@googlemaps/jest-mocks';
import {cleanup, queryByTestId, render} from '@testing-library/react';
import {
cleanup,
fireEvent,
queryByTestId,
render
} from '@testing-library/react';
import '@testing-library/jest-dom';

import {AdvancedMarker, AdvancedMarkerAnchorPoint} from '../advanced-marker';
Expand Down Expand Up @@ -195,8 +200,53 @@ describe('map and marker-library loaded', () => {
expect((marker.content as HTMLElement).style.cursor).toBe('');
});

test('binds gmp-click events to onClick', async () => {
const handleClick = jest.fn();

render(
<AdvancedMarker position={{lat: 1, lng: 2}} onClick={handleClick} />
);

const marker = await waitForMockInstance(
google.maps.marker.AdvancedMarkerElement
);

const clickEvent = new Event('gmp-click');
fireEvent(marker, clickEvent);

expect(handleClick).toHaveBeenCalledWith(clickEvent);
expect(marker.gmpClickable).toBe(true);
});

test('binds keyboard events and infers clickability from them', async () => {
const handleKeyDown = jest.fn();
const handleKeyUp = jest.fn();

render(
<AdvancedMarker
position={{lat: 1, lng: 2}}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
/>
);

const marker = await waitForMockInstance(
google.maps.marker.AdvancedMarkerElement
);

expect(marker.gmpClickable).toBe(true);

const keyDownEvent = new KeyboardEvent('keydown', {key: 'Enter'});
const keyUpEvent = new KeyboardEvent('keyup', {key: ' '});

fireEvent(marker, keyDownEvent);
fireEvent(marker, keyUpEvent);

expect(handleKeyDown).toHaveBeenCalledWith(keyDownEvent);
expect(handleKeyUp).toHaveBeenCalledWith(keyUpEvent);
});

test.todo('marker should work with options');
test.todo('marker should have a click listener');

describe('anchoring with modern API', () => {
beforeEach(() => {
Expand Down
28 changes: 23 additions & 5 deletions src/components/advanced-marker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ export type AdvancedMarkerAnchorPoint =
(typeof AdvancedMarkerAnchorPoint)[keyof typeof AdvancedMarkerAnchorPoint];

type AdvancedMarkerEventProps = {
onClick?: (e: google.maps.MapMouseEvent) => void;
onClick?: (e: google.maps.marker.AdvancedMarkerClickEvent) => void;
onKeyDown?: (e: KeyboardEvent) => void;
onKeyUp?: (e: KeyboardEvent) => void;
onMouseEnter?: (e: google.maps.MapMouseEvent['domEvent']) => void;
onMouseLeave?: (e: google.maps.MapMouseEvent['domEvent']) => void;
onDrag?: (e: google.maps.MapMouseEvent) => void;
Expand Down Expand Up @@ -211,6 +213,8 @@ function useAdvancedMarker(props: AdvancedMarkerProps) {
const {
children,
onClick,
onKeyDown,
onKeyUp,
className,
onMouseEnter,
onMouseLeave,
Expand Down Expand Up @@ -296,8 +300,8 @@ function useAdvancedMarker(props: AdvancedMarkerProps) {
else marker.gmpDraggable = false;
}, [marker, draggable, onDrag, onDragEnd, onDragStart]);

// set gmpClickable from props (when unspecified, it's true if the onClick or one of
// the hover events callbacks are specified)
// set gmpClickable from props (when unspecified, it's true if any interactive
// event callbacks are specified)
useEffect(() => {
if (!marker) return;

Expand All @@ -306,7 +310,11 @@ function useAdvancedMarker(props: AdvancedMarkerProps) {
const gmpClickable =
clickable !== undefined
? clickable
: Boolean(onClick) || Boolean(onMouseEnter) || Boolean(onMouseLeave);
: Boolean(onClick) ||
Boolean(onKeyDown) ||
Boolean(onKeyUp) ||
Boolean(onMouseEnter) ||
Boolean(onMouseLeave);

// gmpClickable is only available in beta version of the
// maps api (as of 2024-10-10)
Expand All @@ -319,13 +327,23 @@ function useAdvancedMarker(props: AdvancedMarkerProps) {
marker.content.style.pointerEvents = gmpClickable ? 'all' : 'none';
marker.content.style.cursor = gmpClickable && onClick ? 'pointer' : '';
}
}, [marker, clickable, onClick, onMouseEnter, onMouseLeave]);
}, [
marker,
clickable,
onClick,
onKeyDown,
onKeyUp,
onMouseEnter,
onMouseLeave
]);

useMapsEventListener(marker, 'drag', onDrag);
useMapsEventListener(marker, 'dragstart', onDragStart);
useMapsEventListener(marker, 'dragend', onDragEnd);

useDomEventListener(marker, 'gmp-click', onClick);
useDomEventListener(marker, 'keydown', onKeyDown);
useDomEventListener(marker, 'keyup', onKeyUp);
useDomEventListener(marker, 'mouseenter', onMouseEnter);
useDomEventListener(marker, 'mouseleave', onMouseLeave);

Expand Down