// @flow import type { Evented } from 'leaflet' import { Component } from 'react' export const EVENTS_RE = /^on(.+)$/i type EventHandler = (event: Event) => void type EventsObject = { [key: string]: EventHandler } export default class MapEvented< LeafletElement: Evented, Props: Object, > extends Component { _leafletEvents: EventsObject leafletElement: LeafletElement constructor(props: Props) { super(props) this._leafletEvents = this.extractLeafletEvents(props) } componentDidMount() { this.bindLeafletEvents(this._leafletEvents) } componentDidUpdate(_prevProps: Props) { this._leafletEvents = this.bindLeafletEvents( this.extractLeafletEvents(this.props), this._leafletEvents, ) } componentWillUnmount() { const el = this.leafletElement if (!el) return Object.keys(this._leafletEvents).forEach((ev) => { el.off(ev, this._leafletEvents[ev]) }) } extractLeafletEvents(props: Props): EventsObject { return Object.keys(props).reduce((res, prop) => { if (EVENTS_RE.test(prop)) { if (props[prop] != null) { const key = prop.replace(EVENTS_RE, (match, p) => p.toLowerCase()) res[key] = props[prop] } } return res }, {}) } bindLeafletEvents( next: EventsObject = {}, prev: EventsObject = {}, ): EventsObject { const el = this.leafletElement if (el == null || el.on == null) return {} const diff = { ...prev } Object.keys(prev).forEach((ev) => { if (next[ev] == null || prev[ev] !== next[ev]) { delete diff[ev] el.off(ev, prev[ev]) } }) Object.keys(next).forEach((ev) => { if (prev[ev] == null || next[ev] !== prev[ev]) { diff[ev] = next[ev] el.on(ev, next[ev]) } }) return diff } fireLeafletEvent(type: string, data: ?any) { const el = this.leafletElement if (el) el.fire(type, data) } }