diff --git a/types/react-leaflet/index.d.ts b/types/react-leaflet/index.d.ts index c362a1f23c..04fe17a04f 100644 --- a/types/react-leaflet/index.d.ts +++ b/types/react-leaflet/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for react-leaflet 1.1 +// Type definitions for react-leaflet 2.2 // Project: https://github.com/PaulLeCam/react-leaflet // Definitions by: Dave Leaver , David Schneider , Yui T. // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -118,12 +118,20 @@ export type LeafletEvents = MapEvents // These type parameters aren't needed for instantiating a component, but they are useful for // extending react-leaflet classes. -export class MapComponent extends React.Component

{ +export interface MapComponentProps { + leaflet?: LeafletContext; + pane?: string; +} + +export class MapEvented extends React.Component

{ _leafletEvents: LeafletEvents; leafletElement: E; extractLeafletEvents(props: P): LeafletEvents; bindLeafletEvents(next: LeafletEvents, prev: LeafletEvents): LeafletEvents; fireLeafletEvent(type: string, data: any): void; +} + +export class MapComponent

extends MapEvented { getOptions(props: P): P; } @@ -131,221 +139,313 @@ export interface MapProps extends MapEvents, Leaflet.MapOptions, Leaflet.LocateO animate?: boolean; bounds?: Leaflet.LatLngBoundsExpression; boundsOptions?: Leaflet.FitBoundsOptions; - center?: Leaflet.LatLngExpression; - children?: Children; + children: Children; className?: string; id?: string; - maxBounds?: Leaflet.LatLngBoundsExpression; - maxZoom?: number; - minZoom?: number; style?: React.CSSProperties; useFlyTo?: boolean; - zoom?: number; + viewport?: Viewport; + whenReady?: () => void; } -export class Map

extends MapComponent { - className?: string; - container: HTMLDivElement; - getChildContext(): { layerContainer: E, map: E }; +export class Map

extends MapEvented { + className: string | null | undefined; + contextValue: LeafletContext | null | undefined; + container: HTMLDivElement | null | undefined; + viewport: Viewport; createLeafletElement(props: P): E; updateLeafletElement(fromProps: P, toProps: P): void; - bindContainer(container: HTMLDivElement): void; + onViewportChange: (viewport: Viewport | null) => void; + onViewportChanged: (viewport: Viewport | null) => void; + bindContainer(container: HTMLDivElement | null | undefined): void; shouldUpdateCenter(next: Leaflet.LatLngExpression, prev: Leaflet.LatLngExpression): boolean; shouldUpdateBounds(next: Leaflet.LatLngBoundsExpression, prev: Leaflet.LatLngBoundsExpression): boolean; } +export interface DivOverlayProps extends MapComponentProps, Leaflet.DivOverlayOptions { + children: Children; + onClose?: () => void; + onOpen?: () => void; +} + +export interface DivOverlayTypes extends Leaflet.Evented { + isOpen: () => boolean; + update: () => void; +} + +export class DivOverlay

extends MapComponent { + createLeafletElement(_props: P): void; + updateLeafletElement(_prevProps: P, _props: P): void; + onClose: () => void; + onOpen: () => void; + onRender: () => void; +} + export interface PaneProps { - name?: string; children?: Children; - map?: Leaflet.Map; className?: string; + leaflet?: LeafletContext; + name?: string; style?: React.CSSProperties; pane?: string; } export interface PaneState { - name?: string; + name: string | null | undefined; + context: LeafletContext | null | undefined; } export class Pane

extends React.Component { - getChildContext(): { pane: string }; createPane(props: P): void; removePane(): void; setStyle(arg: { style?: string, className?: string }): void; - getParentPane(): HTMLElement | undefined; - getPane(name: string): HTMLElement | undefined; + getParentPane(): HTMLElement | null | undefined; + getPane(name: string | null | undefined): HTMLElement | null | undefined; } -export interface MapLayerProps { +export interface MapLayerProps extends MapComponentProps { + attribution?: string; children?: Children; } + +export type AddLayerHandler = (layer: Leaflet.Layer, name: string, checked?: boolean) => void; + +export type RemoveLayerHandler = (layer: Leaflet.Layer) => void; + export interface LayerContainer { - addLayer(layer: Leaflet.Layer): this; - removeLayer(layer: number | Leaflet.Layer): this; + addLayer: AddLayerHandler; + removeLayer: RemoveLayerHandler; } -export class MapLayer

extends MapComponent { + +export interface LeafletContext { + map?: Leaflet.Map; + pane?: string; + layerContainer?: LayerContainer; + popupContainer?: Leaflet.Layer; +} + +export type LatLng = Leaflet.LatLng | number[] | object; + +export type LatLngBounds = Leaflet.LatLngBounds | LatLng[]; + +export type Point = [number, number] | Leaflet.Point; + +export interface Viewport { + center: [number, number] | null | undefined; + zoom: number | null | undefined; +} + +export class MapLayer

extends MapComponent { + contextValue: LeafletContext | null | undefined; + leafletElement: E; createLeafletElement(props: P): E; updateLeafletElement(fromProps: P, toProps: P): void; readonly layerContainer: LayerContainer | Leaflet.Map; } -export interface GridLayerProps extends Leaflet.GridLayerOptions { - children?: Children; +export interface GridLayerProps extends MapLayerProps, Leaflet.GridLayerOptions { } +export class GridLayer

extends MapLayer { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; + getOptions(props: P): P; } -export class GridLayer

extends MapLayer {} -export interface TileLayerProps extends TileLayerEvents, Leaflet.TileLayerOptions { +export interface TileLayerProps extends GridLayerProps, TileLayerEvents, Leaflet.TileLayerOptions { + url: string; +} +export class TileLayer

extends GridLayer { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} + +export interface WMSTileLayerProps extends TileLayerEvents, Leaflet.WMSOptions, GridLayerProps { children?: Children; url: string; } -export class TileLayer

extends GridLayer { } - -export interface WMSTileLayerProps extends TileLayerEvents, Leaflet.WMSOptions { - children?: Children; - url: string; +export class WMSTileLayer

extends GridLayer { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; + getOptions(params: P): P; } -export class WMSTileLayer

extends GridLayer { } -export interface ImageOverlayProps extends Leaflet.ImageOverlayOptions { - bounds: Leaflet.LatLngBoundsExpression; - children?: Children; - url: string; +export interface ImageOverlayProps extends MapLayerProps, Leaflet.ImageOverlayOptions { + bounds?: Leaflet.LatLngBoundsExpression; + url: string | HTMLImageElement; + zIndex?: number; } export class ImageOverlay

extends MapLayer { - getChildContext(): { popupContainer: E }; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; } -export interface LayerGroupProps { - children?: Children; -} -export class LayerGroup

extends MapLayer { - getChildContext(): { layerContainer: E }; +export class LayerGroup

extends MapLayer { + createLeafletElement(props: P): E; } -export interface MarkerProps extends MarkerEvents, Leaflet.MarkerOptions { - children?: Children; +export interface MarkerProps extends MapLayerProps, MarkerEvents, Leaflet.MarkerOptions { position: Leaflet.LatLngExpression; } export class Marker

extends MapLayer { - getChildContext(): { popupContainer: E }; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; } export interface PathProps extends PathEvents, Leaflet.PathOptions, MapLayerProps { } -export abstract class Path

extends MapLayer { +export abstract class Path

extends MapLayer { getChildContext(): { popupContainer: E }; getPathOptions(props: P): Leaflet.PathOptions; setStyle(options: Leaflet.PathOptions): void; setStyleIfChanged(fromProps: P, toProps: P): void; } -export interface CircleProps extends PathEvents, Leaflet.CircleMarkerOptions { +export interface CircleProps extends MapLayerProps, PathEvents, Leaflet.CircleMarkerOptions { center: Leaflet.LatLngExpression; - children?: Children; radius: number; } -export class Circle

extends Path { } +export class Circle

extends Path { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} -export interface CircleMarkerProps extends PathEvents, Leaflet.CircleMarkerOptions { +export interface CircleMarkerProps extends PathProps, PathEvents, Leaflet.CircleMarkerOptions { center: Leaflet.LatLngExpression; - children?: Children; radius: number; } -export class CircleMarker

extends Path { } - -export interface FeatureGroupProps extends FeatureGroupEvents, Leaflet.PathOptions { - children?: Children; -} -export class FeatureGroup

extends Path { - getChildContext(): { layerContainer: E, popupContainer: E }; +export class CircleMarker

extends Path { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; } -export interface GeoJSONProps extends FeatureGroupEvents, Leaflet.GeoJSONOptions { - children?: Children; +export interface FeatureGroupProps extends MapLayerProps, FeatureGroupEvents, Leaflet.PathOptions { } +export class FeatureGroup

extends LayerGroup { + createLeafletElement(props: P): E; +} + +export interface GeoJSONProps extends PathProps, FeatureGroupEvents, Leaflet.GeoJSONOptions { data: GeoJSON.GeoJsonObject; - style?: Leaflet.StyleFunction; } -export class GeoJSON

extends Path { } +export class GeoJSON

extends FeatureGroup { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} -export interface PolylineProps extends PathEvents, Leaflet.PolylineOptions { - children?: Children; +export interface PolylineProps extends PathProps, PathEvents, Leaflet.PolylineOptions { positions: Leaflet.LatLngExpression[] | Leaflet.LatLngExpression[][]; } -export class Polyline

extends Path { } +export class Polyline

extends Path { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} -export interface PolygonProps extends PathEvents, Leaflet.PolylineOptions { - children?: Children; - popupContainer?: Leaflet.FeatureGroup; +export interface PolygonProps extends PathProps, PathEvents, Leaflet.PolylineOptions { positions: Leaflet.LatLngExpression[] | Leaflet.LatLngExpression[][] | Leaflet.LatLngExpression[][][]; } -export class Polygon

extends Path { } - -export interface RectangleProps extends PathEvents, Leaflet.PolylineOptions { - children?: Children; - bounds: Leaflet.LatLngBoundsExpression; - popupContainer?: Leaflet.FeatureGroup; +export class Polygon

extends Path { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; } -export class Rectangle

extends Path { } -export interface PopupProps extends Leaflet.PopupOptions { - children?: Children; +export interface RectangleProps extends PathProps, PathEvents, Leaflet.PolylineOptions { + bounds: Leaflet.LatLngBoundsExpression; +} +export class Rectangle

extends Path { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} + +export interface PopupProps extends Leaflet.PopupOptions, DivOverlayProps { position?: Leaflet.LatLngExpression; } -export class Popup

extends MapComponent { +export class Popup

extends DivOverlay { + getOptions(props: P): P; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; onPopupOpen(arg: { popup: E }): void; onPopupClose(arg: { popup: E }): void; - renderPopupContent(): void; - removePopupContent(): void; + onRender: () => void; } -export interface TooltipProps extends Leaflet.TooltipOptions { - children?: Children; -} -export class Tooltip

extends MapComponent { +export interface TooltipProps extends Leaflet.TooltipOptions, DivOverlayProps { } +export class Tooltip

extends DivOverlay { onTooltipOpen(arg: { tooltip: E }): void; onTooltipClose(arg: { tooltip: E }): void; - renderTooltipContent(): void; - removeTooltipContent(): void; } -export type MapControlProps = Leaflet.ControlOptions; +export type MapControlProps = { + leaflet?: LeafletContext +} & Leaflet.ControlOptions; + export class MapControl

extends React.Component

{ leafletElement: E; createLeafletElement(props: P): E; updateLeafletElement(fromProps: P, toProps: P): void; } -export type AttributionControlProps = Leaflet.Control.AttributionOptions; -export class AttributionControl

extends MapControl { } +export type AttributionControlProps = Leaflet.Control.AttributionOptions & MapControlProps; +export class AttributionControl

extends MapControl { + createLeafletElement(props: P): E; +} -export interface LayersControlProps extends LayersControlEvents, Leaflet.Control.LayersOptions { - baseLayers?: Leaflet.Control.LayersObject; - children?: Children; - overlays?: Leaflet.Control.LayersObject; +export interface LayersControlProps extends MapControlProps, LayersControlEvents, Leaflet.Control.LayersOptions { + children: Children; + collapsed?: boolean; +} +export class LayersControl

extends MapControl { + controlProps: { + addBaseLayer: AddLayerHandler, + addOverlay: AddLayerHandler, + removeLayer: RemoveLayerHandler, + removeLayerControl: RemoveLayerHandler + }; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; + addBaseLayer(layer: Leaflet.Layer, name: string, checked: boolean): void; + addOverlay(layer: Leaflet.Layer, name: string, checked: boolean): void; + removeLayer(layer: Leaflet.Layer): void; + removeLayerControl(layer: Leaflet.Layer): void; } -export class LayersControl

extends MapControl { } export namespace LayersControl { - interface BaseControlledLayerProps { + interface ControlledLayerProps { + addBaseLayer?: AddLayerHandler; + addOverlay?: AddLayerHandler; checked?: boolean; - children?: Children; - removeLayer?(layer: Leaflet.Layer): void; - removeLayerControl?(layer: Leaflet.Layer): void; - } - interface ControlledLayerProps extends BaseControlledLayerProps { - addBaseLayer?(layer: Leaflet.Layer, name: string, checked: boolean): void; - addOverlay?(layer: Leaflet.Layer, name: string, checked: boolean): void; + children: Children; + leaflet?: LeafletContext; name: string; + removeLayer?: RemoveLayerHandler; + removeLayerControl?: RemoveLayerHandler; } - class ControlledLayer

extends React.Component

{ - layer?: Leaflet.Layer; - getChildContext(): { layerContainer: LayerContainer }; - addLayer(): void; + class ControlledLayer

extends React.Component

{ + contextValue: LeafletContext; + layer: Leaflet.Layer | null | undefined; removeLayer(layer: Leaflet.Layer): void; } - class BaseLayer

extends ControlledLayer

{ } - class Overlay

extends ControlledLayer

{ } + class BaseLayer

extends ControlledLayer

{ + constructor(props: ControlledLayerProps); + addLayer: (layer: Leaflet.Layer) => void; + } + class Overlay

extends ControlledLayer

{ + constructor(props: ControlledLayerProps); + addLayer: (layer: Leaflet.Layer) => void; + } } -export type ScaleControlProps = Leaflet.Control.ScaleOptions; -export class ScaleControl

extends MapControl { } +export type ScaleControlProps = Leaflet.Control.ScaleOptions & MapControlProps; +export class ScaleControl

extends MapControl { + createLeafletElement(props: P): E; +} -export type ZoomControlProps = Leaflet.Control.ZoomOptions; -export class ZoomControl

extends MapControl { } +export type ZoomControlProps = Leaflet.Control.ZoomOptions & MapControlProps; +export class ZoomControl

extends MapControl { + createLeafletElement(props: P): E; +} + +// context.js +export const LeafletProvider: React.Provider; +export const LeafletConsumer: React.Consumer; + +export interface ContextProps { + leaflet?: LeafletContext; +} +export type Omit = Pick>; + +export function withLeaflet(WrappedComponent: React.ComponentType): React.ComponentType>; diff --git a/types/react-leaflet/react-leaflet-tests.tsx b/types/react-leaflet/react-leaflet-tests.tsx index fe9825c465..5d1fc2ce7e 100644 --- a/types/react-leaflet/react-leaflet-tests.tsx +++ b/types/react-leaflet/react-leaflet-tests.tsx @@ -16,8 +16,10 @@ import { MapProps, Marker, MarkerProps, + Path, Pane, Polygon, + PolygonProps, Polyline, Popup, PopupProps, @@ -25,7 +27,10 @@ import { TileLayer, Tooltip, WMSTileLayer, - ZoomControl + ZoomControl, + LeafletProvider, + withLeaflet, + Viewport } from 'react-leaflet'; const { BaseLayer, Overlay } = LayersControl; @@ -207,7 +212,7 @@ export class CustomComponent extends Component } } -// SOURCE ??? +// Similar to custom-icons.js export class MarkerWithDivIconExample extends Component { render() { return ( @@ -628,6 +633,43 @@ export class VectorLayersExample extends Component { } } +// viewport.js + +const viewportCenter: [number, number] = [51.505, -0.09]; + +const DEFAULT_VIEWPORT = { + center: viewportCenter, + zoom: 13 +}; + +export class ViewportExample extends Component { + state = { + viewport: DEFAULT_VIEWPORT + }; + + onClickReset = () => { + this.setState({ viewport: DEFAULT_VIEWPORT }); + } + + onViewportChanged = (viewport: Viewport) => { + this.setState({ viewport }); + } + + render() { + return ( + + + + ); + } +} + // wms-tile-layer.js interface WMSTileLayerExampleState { lat: number; @@ -729,6 +771,8 @@ class LegendControl extends MapControl } } +const legendControlComponent = withLeaflet(LegendControl); + const LegendControlExample = () => ( ( ); + +class CustomPolygon extends Path { + createLeafletElement(props: PolygonProps) { + const el = new L.Polygon(props.positions, this.getOptions(props)); + this.contextValue = { ...props.leaflet, popupContainer: el }; + return el; + } + + updateLeafletElement(fromProps: PolygonProps, toProps: PolygonProps) { + if (toProps.positions !== fromProps.positions) { + this.leafletElement.setLatLngs(toProps.positions); + } + this.setStyleIfChanged(fromProps, toProps); + } + + render() { + const { children } = this.props; + return children == null || this.contextValue == null ? null : ( + {children} + ); + } +} +const leafletComponent = withLeaflet(CustomPolygon); diff --git a/types/react-leaflet/v1/index.d.ts b/types/react-leaflet/v1/index.d.ts new file mode 100644 index 0000000000..c362a1f23c --- /dev/null +++ b/types/react-leaflet/v1/index.d.ts @@ -0,0 +1,351 @@ +// Type definitions for react-leaflet 1.1 +// Project: https://github.com/PaulLeCam/react-leaflet +// Definitions by: Dave Leaver , David Schneider , Yui T. +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +import * as Leaflet from 'leaflet'; +import * as React from 'react'; + +// All events need to be lowercase so they don't collide with React.DOMAttributes +// which already declares things with some of the same names + +export type Children = React.ReactNode | React.ReactNode[]; + +export interface MapEvents { + onclick?(event: Leaflet.LeafletMouseEvent): void; + ondblclick?(event: Leaflet.LeafletMouseEvent): void; + onmousedown?(event: Leaflet.LeafletMouseEvent): void; + onmouseup?(event: Leaflet.LeafletMouseEvent): void; + onmouseover?(event: Leaflet.LeafletMouseEvent): void; + onmouseout?(event: Leaflet.LeafletMouseEvent): void; + onmousemove?(event: Leaflet.LeafletMouseEvent): void; + oncontextmenu?(event: Leaflet.LeafletMouseEvent): void; + onfocus?(event: Leaflet.LeafletEvent): void; + onblur?(event: Leaflet.LeafletEvent): void; + onpreclick?(event: Leaflet.LeafletMouseEvent): void; + onload?(event: Leaflet.LeafletEvent): void; + onunload?(event: Leaflet.LeafletEvent): void; + onviewreset?(event: Leaflet.LeafletEvent): void; + onmove?(event: Leaflet.LeafletEvent): void; + onmovestart?(event: Leaflet.LeafletEvent): void; + onmoveend?(event: Leaflet.LeafletEvent): void; + ondragstart?(event: Leaflet.LeafletEvent): void; + ondrag?(event: Leaflet.LeafletEvent): void; + ondragend?(event: Leaflet.DragEndEvent): void; + onzoomstart?(event: Leaflet.LeafletEvent): void; + onzoomend?(event: Leaflet.LeafletEvent): void; + onzoomlevelschange?(event: Leaflet.LeafletEvent): void; + onresize?(event: Leaflet.ResizeEvent): void; + onautopanstart?(event: Leaflet.LeafletEvent): void; + onlayeradd?(event: Leaflet.LayerEvent): void; + onlayerremove?(event: Leaflet.LayerEvent): void; + onbaselayerchange?(event: Leaflet.LayersControlEvent): void; + onoverlayadd?(event: Leaflet.LayersControlEvent): void; + onoverlayremove?(event: Leaflet.LayersControlEvent): void; + onlocationfound?(event: Leaflet.LocationEvent): void; + onlocationerror?(event: Leaflet.ErrorEvent): void; + onpopupopen?(event: Leaflet.PopupEvent): void; + onpopupclose?(event: Leaflet.PopupEvent): void; +} + +export interface MarkerEvents { + onclick?(event: Leaflet.LeafletMouseEvent): void; + ondblclick?(event: Leaflet.LeafletMouseEvent): void; + onmousedown?(event: Leaflet.LeafletMouseEvent): void; + onmouseover?(event: Leaflet.LeafletMouseEvent): void; + onmouseout?(event: Leaflet.LeafletMouseEvent): void; + oncontextmenu?(event: Leaflet.LeafletMouseEvent): void; + ondragstart?(event: Leaflet.LeafletEvent): void; + ondrag?(event: Leaflet.LeafletEvent): void; + ondragend?(event: Leaflet.DragEndEvent): void; + onmove?(event: Leaflet.LeafletEvent): void; + onadd?(event: Leaflet.LeafletEvent): void; + onremove?(event: Leaflet.LeafletEvent): void; + onpopupopen?(event: Leaflet.PopupEvent): void; + onpopupclose?(event: Leaflet.PopupEvent): void; +} + +export interface TileLayerEvents { + onloading?(event: Leaflet.LeafletEvent): void; + onload?(event: Leaflet.LeafletEvent): void; + ontileloadstart?(event: Leaflet.TileEvent): void; + ontileload?(event: Leaflet.TileEvent): void; + ontileunload?(event: Leaflet.TileEvent): void; + ontileerror?(event: Leaflet.TileEvent): void; +} + +export interface PathEvents { + onclick?(event: Leaflet.LeafletMouseEvent): void; + ondblclick?(event: Leaflet.LeafletMouseEvent): void; + onmousedown?(event: Leaflet.LeafletMouseEvent): void; + onmouseover?(event: Leaflet.LeafletMouseEvent): void; + onmouseout?(event: Leaflet.LeafletMouseEvent): void; + oncontextmenu?(event: Leaflet.LeafletMouseEvent): void; + onadd?(event: Leaflet.LeafletEvent): void; + onremove?(event: Leaflet.LeafletEvent): void; + onpopupopen?(event: Leaflet.PopupEvent): void; + onpopupclose?(event: Leaflet.PopupEvent): void; +} + +export interface FeatureGroupEvents { + onclick?(event: Leaflet.LeafletMouseEvent): void; + ondblclick?(event: Leaflet.LeafletMouseEvent): void; + onmouseover?(event: Leaflet.LeafletMouseEvent): void; + onmouseout?(event: Leaflet.LeafletMouseEvent): void; + oncontextmenu?(event: Leaflet.LeafletMouseEvent): void; + onlayeradd?(event: Leaflet.LayerEvent): void; + onlayerremove?(event: Leaflet.LayerEvent): void; +} + +export interface LayersControlEvents { + onbaselayerchange?(event: Leaflet.LayersControlEvent): void; + onoverlayadd?(event: Leaflet.LayersControlEvent): void; + onoverlayremove?(event: Leaflet.LayersControlEvent): void; +} + +export type LeafletEvents = MapEvents + & MarkerEvents + & TileLayerEvents + & PathEvents + & FeatureGroupEvents + & LayersControlEvents; + +// Most react-leaflet components take two type parameters: +// - P : the component's props object +// - E : the corresponding Leaflet element + +// These type parameters aren't needed for instantiating a component, but they are useful for +// extending react-leaflet classes. + +export class MapComponent extends React.Component

{ + _leafletEvents: LeafletEvents; + leafletElement: E; + extractLeafletEvents(props: P): LeafletEvents; + bindLeafletEvents(next: LeafletEvents, prev: LeafletEvents): LeafletEvents; + fireLeafletEvent(type: string, data: any): void; + getOptions(props: P): P; +} + +export interface MapProps extends MapEvents, Leaflet.MapOptions, Leaflet.LocateOptions, Leaflet.FitBoundsOptions { + animate?: boolean; + bounds?: Leaflet.LatLngBoundsExpression; + boundsOptions?: Leaflet.FitBoundsOptions; + center?: Leaflet.LatLngExpression; + children?: Children; + className?: string; + id?: string; + maxBounds?: Leaflet.LatLngBoundsExpression; + maxZoom?: number; + minZoom?: number; + style?: React.CSSProperties; + useFlyTo?: boolean; + zoom?: number; +} + +export class Map

extends MapComponent { + className?: string; + container: HTMLDivElement; + getChildContext(): { layerContainer: E, map: E }; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; + bindContainer(container: HTMLDivElement): void; + shouldUpdateCenter(next: Leaflet.LatLngExpression, prev: Leaflet.LatLngExpression): boolean; + shouldUpdateBounds(next: Leaflet.LatLngBoundsExpression, prev: Leaflet.LatLngBoundsExpression): boolean; +} + +export interface PaneProps { + name?: string; + children?: Children; + map?: Leaflet.Map; + className?: string; + style?: React.CSSProperties; + pane?: string; +} +export interface PaneState { + name?: string; +} +export class Pane

extends React.Component { + getChildContext(): { pane: string }; + createPane(props: P): void; + removePane(): void; + setStyle(arg: { style?: string, className?: string }): void; + getParentPane(): HTMLElement | undefined; + getPane(name: string): HTMLElement | undefined; +} + +export interface MapLayerProps { + children?: Children; +} +export interface LayerContainer { + addLayer(layer: Leaflet.Layer): this; + removeLayer(layer: number | Leaflet.Layer): this; +} +export class MapLayer

extends MapComponent { + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; + readonly layerContainer: LayerContainer | Leaflet.Map; +} + +export interface GridLayerProps extends Leaflet.GridLayerOptions { + children?: Children; +} +export class GridLayer

extends MapLayer {} + +export interface TileLayerProps extends TileLayerEvents, Leaflet.TileLayerOptions { + children?: Children; + url: string; +} +export class TileLayer

extends GridLayer { } + +export interface WMSTileLayerProps extends TileLayerEvents, Leaflet.WMSOptions { + children?: Children; + url: string; +} +export class WMSTileLayer

extends GridLayer { } + +export interface ImageOverlayProps extends Leaflet.ImageOverlayOptions { + bounds: Leaflet.LatLngBoundsExpression; + children?: Children; + url: string; +} +export class ImageOverlay

extends MapLayer { + getChildContext(): { popupContainer: E }; +} + +export interface LayerGroupProps { + children?: Children; +} +export class LayerGroup

extends MapLayer { + getChildContext(): { layerContainer: E }; +} + +export interface MarkerProps extends MarkerEvents, Leaflet.MarkerOptions { + children?: Children; + position: Leaflet.LatLngExpression; +} +export class Marker

extends MapLayer { + getChildContext(): { popupContainer: E }; +} + +export interface PathProps extends PathEvents, Leaflet.PathOptions, MapLayerProps { } +export abstract class Path

extends MapLayer { + getChildContext(): { popupContainer: E }; + getPathOptions(props: P): Leaflet.PathOptions; + setStyle(options: Leaflet.PathOptions): void; + setStyleIfChanged(fromProps: P, toProps: P): void; +} + +export interface CircleProps extends PathEvents, Leaflet.CircleMarkerOptions { + center: Leaflet.LatLngExpression; + children?: Children; + radius: number; +} +export class Circle

extends Path { } + +export interface CircleMarkerProps extends PathEvents, Leaflet.CircleMarkerOptions { + center: Leaflet.LatLngExpression; + children?: Children; + radius: number; +} +export class CircleMarker

extends Path { } + +export interface FeatureGroupProps extends FeatureGroupEvents, Leaflet.PathOptions { + children?: Children; +} +export class FeatureGroup

extends Path { + getChildContext(): { layerContainer: E, popupContainer: E }; +} + +export interface GeoJSONProps extends FeatureGroupEvents, Leaflet.GeoJSONOptions { + children?: Children; + data: GeoJSON.GeoJsonObject; + style?: Leaflet.StyleFunction; +} +export class GeoJSON

extends Path { } + +export interface PolylineProps extends PathEvents, Leaflet.PolylineOptions { + children?: Children; + positions: Leaflet.LatLngExpression[] | Leaflet.LatLngExpression[][]; +} +export class Polyline

extends Path { } + +export interface PolygonProps extends PathEvents, Leaflet.PolylineOptions { + children?: Children; + popupContainer?: Leaflet.FeatureGroup; + positions: Leaflet.LatLngExpression[] | Leaflet.LatLngExpression[][] | Leaflet.LatLngExpression[][][]; +} +export class Polygon

extends Path { } + +export interface RectangleProps extends PathEvents, Leaflet.PolylineOptions { + children?: Children; + bounds: Leaflet.LatLngBoundsExpression; + popupContainer?: Leaflet.FeatureGroup; +} +export class Rectangle

extends Path { } + +export interface PopupProps extends Leaflet.PopupOptions { + children?: Children; + position?: Leaflet.LatLngExpression; +} +export class Popup

extends MapComponent { + onPopupOpen(arg: { popup: E }): void; + onPopupClose(arg: { popup: E }): void; + renderPopupContent(): void; + removePopupContent(): void; +} + +export interface TooltipProps extends Leaflet.TooltipOptions { + children?: Children; +} +export class Tooltip

extends MapComponent { + onTooltipOpen(arg: { tooltip: E }): void; + onTooltipClose(arg: { tooltip: E }): void; + renderTooltipContent(): void; + removeTooltipContent(): void; +} + +export type MapControlProps = Leaflet.ControlOptions; +export class MapControl

extends React.Component

{ + leafletElement: E; + createLeafletElement(props: P): E; + updateLeafletElement(fromProps: P, toProps: P): void; +} + +export type AttributionControlProps = Leaflet.Control.AttributionOptions; +export class AttributionControl

extends MapControl { } + +export interface LayersControlProps extends LayersControlEvents, Leaflet.Control.LayersOptions { + baseLayers?: Leaflet.Control.LayersObject; + children?: Children; + overlays?: Leaflet.Control.LayersObject; +} +export class LayersControl

extends MapControl { } + +export namespace LayersControl { + interface BaseControlledLayerProps { + checked?: boolean; + children?: Children; + removeLayer?(layer: Leaflet.Layer): void; + removeLayerControl?(layer: Leaflet.Layer): void; + } + interface ControlledLayerProps extends BaseControlledLayerProps { + addBaseLayer?(layer: Leaflet.Layer, name: string, checked: boolean): void; + addOverlay?(layer: Leaflet.Layer, name: string, checked: boolean): void; + name: string; + } + class ControlledLayer

extends React.Component

{ + layer?: Leaflet.Layer; + getChildContext(): { layerContainer: LayerContainer }; + addLayer(): void; + removeLayer(layer: Leaflet.Layer): void; + } + class BaseLayer

extends ControlledLayer

{ } + class Overlay

extends ControlledLayer

{ } +} + +export type ScaleControlProps = Leaflet.Control.ScaleOptions; +export class ScaleControl

extends MapControl { } + +export type ZoomControlProps = Leaflet.Control.ZoomOptions; +export class ZoomControl

extends MapControl { } diff --git a/types/react-leaflet/v1/react-leaflet-tests.tsx b/types/react-leaflet/v1/react-leaflet-tests.tsx new file mode 100644 index 0000000000..fe9825c465 --- /dev/null +++ b/types/react-leaflet/v1/react-leaflet-tests.tsx @@ -0,0 +1,747 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as PropTypes from 'prop-types'; +import * as L from 'leaflet'; +import { Component } from 'react'; +import { + Children, + Circle, + CircleMarker, + FeatureGroup, + LayerGroup, + LayersControl, + Map, + MapControl, + MapControlProps, + MapProps, + Marker, + MarkerProps, + Pane, + Polygon, + Polyline, + Popup, + PopupProps, + Rectangle, + TileLayer, + Tooltip, + WMSTileLayer, + ZoomControl +} from 'react-leaflet'; +const { BaseLayer, Overlay } = LayersControl; + +/// animate.js +interface AnimateExampleState { + animate: boolean; + hasLocation: boolean; + latlng: L.LatLngExpression; +} + +export class AnimateExample extends Component { + state = { + animate: false, + hasLocation: false, + latlng: { + lat: 51.505, + lng: -0.09, + }, + }; + + handleClick = (e: L.LeafletMouseEvent) => { + this.setState({ + latlng: e.latlng, + }); + } + + toggleAnimate = () => { + this.setState({ + animate: !this.state.animate, + }); + } + + render() { + const marker = this.state.hasLocation ? ( + + + You are here + + + ) : null; + + return ( +

+ + + + {marker} + +
+ ); + } +} + +// bounds.js +const outer: L.LatLngBoundsLiteral = [ + [50.505, -29.09], + [52.505, 29.09], +]; +const inner: L.LatLngBoundsLiteral = [ + [49.505, -2.09], + [53.505, 2.09], +]; + +interface BoundsExampleState { + bounds: L.LatLngBoundsLiteral; +} + +export class BoundsExample extends Component { + state = { + bounds: outer, + }; + + onClickInner = () => { + this.setState({ bounds: inner }); + } + + onClickOuter = () => { + this.setState({ bounds: outer }); + } + + render() { + return ( + + + + + + ); + } +} + +// custom-component.js +interface MyPopupMarkerProps { + children: Children; + position: L.LatLngExpression; +} + +interface MyMarker extends MyPopupMarkerProps { + key: string; +} + +const MyPopupMarker = ({ children, position }: MyPopupMarkerProps) => ( + + + {children} + + +); + +interface MyMarkersListProps { + markers: MyMarker[]; +} + +const MyMarkersList = ({ markers }: MyMarkersListProps) => { + const items = markers.map(({ key, ...props }) => ( + + )); + return
{items}
; +}; + +interface CustomComponentState { + lat: number; + lng: number; + zoom: number; +} + +export class CustomComponent extends Component { + state = { + lat: 51.505, + lng: -0.09, + zoom: 13, + }; + + render() { + const center: L.LatLngExpression = [this.state.lat, this.state.lng]; + + const markers: MyMarker[] = [ + { key: 'marker1', position: [51.5, -0.1], children: 'My first popup' }, + { key: 'marker2', position: [51.51, -0.1], children: 'My second popup' }, + { key: 'marker3', position: [51.49, -0.05], children: 'My third popup' }, + ]; + return ( + + + + + ); + } +} + +// SOURCE ??? +export class MarkerWithDivIconExample extends Component { + render() { + return ( + + + + ); + } +} + +// draggable-marker.js +interface DraggableExampleState { + center: L.LatLngLiteral; + marker: L.LatLngLiteral; + zoom: number; + draggable: boolean; +} + +export class DraggableExample extends Component { + state = { + center: { + lat: 51.505, + lng: -0.09, + }, + marker: { + lat: 51.505, + lng: -0.09, + }, + zoom: 13, + draggable: true, + }; + + toggleDraggable = () => { + this.setState({ draggable: !this.state.draggable }); + } + + updatePosition = () => { + const { + lat, + lng, + } = (this.refs.marker as Marker).leafletElement.getLatLng(); + this.setState({ + marker: { lat, lng }, + }); + } + + render() { + const position: L.LatLngExpression = [this.state.center.lat, this.state.center.lng]; + const markerPosition: L.LatLngExpression = [this.state.marker.lat, this.state.marker.lng]; + + return ( + + + + + + {this.state.draggable ? 'DRAG MARKER' : 'MARKER FIXED'} + + + + + ); + } +} + +// events.js +interface EventsExampleState { + hasLocation: boolean; + latlng: L.LatLngLiteral; +} + +export class EventsExample extends Component { + state = { + hasLocation: false, + latlng: { + lat: 51.505, + lng: -0.09, + }, + }; + + handleClick = () => { + (this.refs.map as Map).leafletElement.locate(); + } + + handleLocationFound = (e: L.LocationEvent) => { + this.setState({ + hasLocation: true, + latlng: e.latlng, + }); + } + + render() { + const marker = this.state.hasLocation ? ( + + + You are here + + + ) : null; + + return ( + + + {marker} + + ); + } +} + +// layers-control.js +export class LayersControlExample extends Component { + render() { + const center: L.LatLngExpression = [51.505, -0.09]; + const rectangle: L.LatLngBoundsExpression = [ + [51.49, -0.08], + [51.5, -0.06], + ]; + + return ( + + + + + + + + + + + + A pretty CSS3 popup.
Easily customizable.
+
+
+
+ + + + + + + + + + + + + Popup in FeatureGroup + + + + + +
+
+ ); + } +} + +// other-layers.js +export class OtherLayersExample extends Component { + render() { + const center: L.LatLngExpression = [51.505, -0.09]; + const rectangle: L.LatLngBoundsExpression = [ + [51.49, -0.08], + [51.5, -0.06], + ]; + + return ( + + + + + + + + + + + + Popup in FeatureGroup + + + + + + ); + } +} + +// pane.js +interface PaneExampleState { + render: boolean; +} + +export class PaneExample extends Component { + state = { + render: true, + }; + + componentDidMount() { + setInterval(() => { + this.setState({ + render: !this.state.render, + }); + }, 5000); + } + + render() { + return ( + + + {this.state.render ? ( + + + + ) : null} + + + + + + + + ); + } +} + +// simple.js +interface SimpleExampleState { + lat: number; + lng: number; + zoom: number; +} + +export class SimpleExample extends Component { + state = { + lat: 51.505, + lng: -0.09, + zoom: 13, + }; + + render() { + const position: L.LatLngExpression = [this.state.lat, this.state.lng]; + return ( + + + + + A pretty CSS3 popup.
Easily customizable.
+
+
+
+ ); + } +} + +// tooltip.js +interface TooltipExampleState { + clicked: number; +} + +export class TooltipExample extends Component { + state = { + clicked: 0, + }; + + onClickCircle = () => { + this.setState({ clicked: this.state.clicked + 1 }); + } + + render() { + const center: L.LatLngExpression = [51.505, -0.09]; + + const multiPolygon: L.LatLngExpression[][] = [ + [[51.51, -0.12], [51.51, -0.13], [51.53, -0.13]], + [[51.51, -0.05], [51.51, -0.07], [51.53, -0.07]], + ]; + + const rectangle: L.LatLngBoundsExpression = [ + [51.49, -0.08], + [51.5, -0.06], + ]; + + const clickedText = this.state.clicked === 0 + ? 'Click this Circle to change the Tooltip text' + : `Circle click: ${this.state.clicked}`; + + return ( + + + + + {clickedText} + + + + + Tooltip for CircleMarker + + + + + Popup for Marker + + + Tooltip for Marker + + + + + sticky Tooltip for Polygon + + + + + permanent Tooltip for Rectangle + + + + ); + } +} + +// vector-layers.js +export class VectorLayersExample extends Component { + render() { + const center: L.LatLngExpression = [51.505, -0.09]; + + const polyline: L.LatLngExpression[] = [ + [51.505, -0.09], + [51.51, -0.1], + [51.51, -0.12], + ]; + + const multiPolyline: L.LatLngExpression[][] = [ + [[51.5, -0.1], [51.5, -0.12], [51.52, -0.12]], + [[51.5, -0.05], [51.5, -0.06], [51.52, -0.06]], + ]; + + const polygon: L.LatLngExpression[] = [ + [51.515, -0.09], + [51.52, -0.1], + [51.52, -0.12], + ]; + + const multiPolygon: L.LatLngExpression[][] = [ + [[51.51, -0.12], [51.51, -0.13], [51.53, -0.13]], + [[51.51, -0.05], [51.51, -0.07], [51.53, -0.07]], + ]; + + const rectangle: L.LatLngBoundsExpression = [ + [51.49, -0.08], + [51.5, -0.06], + ]; + + return ( + + + + + + Popup in CircleMarker + + + + + + + + + ); + } +} + +// wms-tile-layer.js +interface WMSTileLayerExampleState { + lat: number; + lng: number; + zoom: number; + bluemarble: boolean; +} + +export class WMSTileLayerExample extends Component { + state = { + lat: 51.505, + lng: -0.09, + zoom: 5, + bluemarble: false, + }; + + onClick = () => { + this.setState({ + bluemarble: !this.state.bluemarble, + }); + } + + render() { + return ( + + + + + ); + } +} + +// zoom-control.js +const ZoomControlExample = () => ( + + + + +); + +// MapControl https://github.com/PaulLeCam/react-leaflet/issues/130 +class CenterControl extends MapControl { // note we're extending MapControl from react-leaflet, not Component from react + componentWillMount() { + const centerControl = new L.Control({ position: 'bottomright' }); // see http://leafletjs.com/reference.html#control-positions for other positions + const jsx = ( + // PUT YOUR JSX FOR THE COMPONENT HERE: +
+ {/* add your JSX */} +
+ ); + + centerControl.onAdd = (map) => { + const div = L.DomUtil.create('div', ''); + ReactDOM.render(jsx, div); + return div; + }; + + this.leafletElement = centerControl; + } +} + +const mapControlCenter: L.LatLngExpression = [51.505, -0.09]; + +const CenterControlExample = () => ( + + + +); + +class LegendControl extends MapControl { + componentWillMount() { + const legend = new L.Control({ position: 'bottomright' }); + const jsx = ( +
+ {this.props.children} +
+ ); + + legend.onAdd = (map) => { + const div = L.DomUtil.create('div', ''); + ReactDOM.render(jsx, div); + return div; + }; + + this.leafletElement = legend; + } +} + +const LegendControlExample = () => ( + + + +
    +
  • Strong Support
  • +
  • Weak Support
  • +
  • Weak Oppose
  • +
  • Strong Oppose
  • +
+
+
+); diff --git a/types/react-leaflet/v1/tsconfig.json b/types/react-leaflet/v1/tsconfig.json new file mode 100644 index 0000000000..bb2d85cfe8 --- /dev/null +++ b/types/react-leaflet/v1/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../../", + "jsx": "react", + "typeRoots": [ + "../../" + ], + "types": [], + "paths": { + "react-leaflet": [ + "react-leaflet/v1" + ], + "react-leaflet/*": [ + "react-leaflet/v1/*" + ] + }, + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "react-leaflet-tests.tsx" + ] +} \ No newline at end of file diff --git a/types/react-leaflet/v1/tslint.json b/types/react-leaflet/v1/tslint.json new file mode 100644 index 0000000000..440efbd687 --- /dev/null +++ b/types/react-leaflet/v1/tslint.json @@ -0,0 +1,7 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + // TODO + "no-duplicate-imports": false + } +}