import { type ContextType, PureComponent } from 'react' import { unregisterEvents, applyUpdatersToPropsAndRegisterEvents, } from '../../utils/helper.js' import MapContext from '../../map-context.js' const eventMap = { onDirectionsChanged: 'directions_changed', } const updaterMap = { directions( instance: google.maps.DirectionsRenderer, directions: google.maps.DirectionsResult ): void { instance.setDirections(directions) }, map(instance: google.maps.DirectionsRenderer, map: google.maps.Map): void { instance.setMap(map) }, options( instance: google.maps.DirectionsRenderer, options: google.maps.DirectionsRendererOptions ): void { instance.setOptions(options) }, panel(instance: google.maps.DirectionsRenderer, panel: HTMLElement): void { instance.setPanel(panel) }, routeIndex( instance: google.maps.DirectionsRenderer, routeIndex: number ): void { instance.setRouteIndex(routeIndex) }, } type DirectionsRendererState = { directionsRenderer: google.maps.DirectionsRenderer | null } export type DirectionsRendererProps = { options?: google.maps.DirectionsRendererOptions | undefined /** The directions to display on the map and/or in a
panel, retrieved as a DirectionsResult object from DirectionsService. */ directions?: google.maps.DirectionsResult | undefined /** The
in which to display the directions steps. */ panel?: HTMLElement | undefined /** The index of the route within the DirectionsResult object. The default value is 0. */ routeIndex?: number | undefined /** This event is fired when the rendered directions change, either when a new DirectionsResult is set or when the user finishes dragging a change to the directions path. */ onDirectionsChanged?: (() => void) | undefined /** This callback is called when the directionsRenderer instance has loaded. It is called with the directionsRenderer instance. */ onLoad?: | ((directionsRenderer: google.maps.DirectionsRenderer) => void) | undefined /** This callback is called when the component unmounts. It is called with the directionsRenderer instance. */ onUnmount?: | ((directionsRenderer: google.maps.DirectionsRenderer) => void) | undefined } export class DirectionsRenderer extends PureComponent< DirectionsRendererProps, DirectionsRendererState > { static override contextType = MapContext declare context: ContextType registeredEvents: google.maps.MapsEventListener[] = [] override state: DirectionsRendererState = { directionsRenderer: null, } setDirectionsRendererCallback = (): void => { if (this.state.directionsRenderer !== null) { this.state.directionsRenderer.setMap(this.context) if (this.props.onLoad) { this.props.onLoad(this.state.directionsRenderer) } } } override componentDidMount(): void { const directionsRenderer = new google.maps.DirectionsRenderer( this.props.options ) this.registeredEvents = applyUpdatersToPropsAndRegisterEvents({ updaterMap, eventMap, prevProps: {}, nextProps: this.props, instance: directionsRenderer, }) this.setState(function setDirectionsRenderer() { return { directionsRenderer, } }, this.setDirectionsRendererCallback) } override componentDidUpdate(prevProps: DirectionsRendererProps): void { if (this.state.directionsRenderer !== null) { unregisterEvents(this.registeredEvents) this.registeredEvents = applyUpdatersToPropsAndRegisterEvents({ updaterMap, eventMap, prevProps, nextProps: this.props, instance: this.state.directionsRenderer, }) } } override componentWillUnmount(): void { if (this.state.directionsRenderer !== null) { if (this.props.onUnmount) { this.props.onUnmount(this.state.directionsRenderer) } unregisterEvents(this.registeredEvents) if (this.state.directionsRenderer) { this.state.directionsRenderer.setMap(null) } } } override render(): null { return null } } export default DirectionsRenderer