ReactJS maps without external dependencies - performance-first React-centric extendable map engine
npx @tessl/cli install tessl/npm-pigeon-maps@0.22.0Pigeon Maps is a performance-first React-centric extendable map engine that provides ReactJS maps without external dependencies. It offers zero external dependencies for basic mapping functionality, supporting essential features like tile display, arbitrary overlays and markers, drag and touch interactions, fractional zooming with smooth animations, event handling, and various zoom controls.
npm install pigeon-mapsimport { Map, Marker, Overlay, ZoomControl } from "pigeon-maps";For provider utilities:
import { osm, stamenToner, maptiler } from "pigeon-maps/providers";CommonJS:
const { Map, Marker, Overlay, ZoomControl } = require("pigeon-maps");
const { osm, stamenToner, maptiler } = require("pigeon-maps/providers");import React from "react";
import { Map, Marker } from "pigeon-maps";
function MyMap() {
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<Marker anchor={[50.879, 4.6997]} />
</Map>
);
}Pigeon Maps is built around several key components:
The main Map component that renders interactive maps with tile layers, handles user interactions, and manages the map state.
function Map(props: MapProps): JSX.Element;
interface MapProps {
// Position and size
center?: Point;
defaultCenter?: Point;
zoom?: number;
defaultZoom?: number;
width?: number;
height?: number;
defaultWidth?: number;
defaultHeight?: number;
// Map configuration
provider?: (x: number, y: number, z: number, dpr?: number) => string;
dprs?: number[];
minZoom?: number;
maxZoom?: number;
animate?: boolean;
animateMaxScreens?: number;
// Interaction settings
mouseEvents?: boolean;
touchEvents?: boolean;
metaWheelZoom?: boolean;
twoFingerDrag?: boolean;
zoomSnap?: boolean;
limitBounds?: 'center' | 'edge';
// Event handlers
onClick?: ({ event, latLng, pixel }: ClickEvent) => void;
onBoundsChanged?: ({ center, zoom, bounds, initial }: BoundsChangeEvent) => void;
onAnimationStart?: () => void;
onAnimationStop?: () => void;
// Display options
attribution?: ReactElement | false;
attributionPrefix?: ReactElement | false;
boxClassname?: string;
tileComponent?: TileComponent;
children?: React.ReactNode;
}
type Point = [number, number]; // [latitude, longitude]Interactive markers and custom overlays for positioning content on the map with event handling capabilities.
function Marker(props: MarkerProps): JSX.Element;
function Overlay(props: OverlayProps): JSX.Element;
interface MarkerProps extends PigeonProps {
color?: string;
payload?: any;
width?: number;
height?: number;
hover?: boolean;
style?: React.CSSProperties;
className?: string;
children?: JSX.Element;
onClick?: (params: MarkerEventParams) => void;
onContextMenu?: (params: MarkerEventParams) => void;
onMouseOver?: (params: MarkerEventParams) => void;
onMouseOut?: (params: MarkerEventParams) => void;
}
interface OverlayProps extends PigeonProps {
style?: React.CSSProperties;
className?: string;
children?: React.ReactNode;
}SVG-based rendering system for GeoJSON data with interactive features and styling capabilities.
function GeoJson(props: GeoJsonProps): JSX.Element;
function GeoJsonLoader(props: GeoJsonLoaderProps): JSX.Element;
function GeoJsonFeature(props: GeoJsonProps): JSX.Element;
interface GeoJsonProps extends PigeonProps {
data?: any;
svgAttributes?: any;
styleCallback?: (feature: any, hover: boolean) => any;
hover?: any;
feature?: any;
className?: string;
style?: CSSProperties;
children?: React.ReactNode;
onClick?: (params: GeoJsonEventParams) => void;
onContextMenu?: (params: GeoJsonEventParams) => void;
onMouseOver?: (params: GeoJsonEventParams) => void;
onMouseOut?: (params: GeoJsonEventParams) => void;
}
interface GeoJsonLoaderProps extends GeoJsonProps {
link?: string;
}System for making map elements draggable with touch and mouse support.
function Draggable(props: DraggableProps): JSX.Element;
interface DraggableProps extends PigeonProps {
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
onDragStart?: (anchor: Point) => void;
onDragMove?: (anchor: Point) => void;
onDragEnd?: (anchor: Point) => void;
}UI controls for map interaction including zoom buttons and other control elements.
function ZoomControl(props: ZoomProps): JSX.Element;
interface ZoomProps extends PigeonProps {
style?: React.CSSProperties;
buttonStyle?: React.CSSProperties;
}Built-in tile provider functions for popular map services with customization options.
function osm(x: number, y: number, z: number): string;
function stamenToner(x: number, y: number, z: number, dpr?: number): string;
function stamenTerrain(x: number, y: number, z: number, dpr?: number): string;
function maptiler(apiKey: string, map?: string): TileProvider;
function stadiamaps(style?: string): TileProvider;
type TileProvider = (x: number, y: number, z: number, dpr?: number) => string;// Base props for positioned elements
interface PigeonProps {
anchor?: Point;
offset?: Point;
left?: number;
top?: number;
mapState?: MapState;
mapProps?: MapProps;
latLngToPixel?: (latLng: Point, center?: Point, zoom?: number) => Point;
pixelToLatLng?: (pixel: Point, center?: Point, zoom?: number) => Point;
setCenterZoom?: (center: Point | null, zoom: number, zoomAround?: Point | null, animationDuration?: number) => void;
}
// Map bounds
interface Bounds {
ne: [number, number]; // northeast [lat, lng]
sw: [number, number]; // southwest [lat, lng]
}
// Current map state
interface MapState {
bounds: Bounds;
zoom: number;
center: Point;
width: number;
height: number;
}
// Event parameter types
interface ClickEvent {
event: MouseEvent;
latLng: Point;
pixel: Point;
}
interface BoundsChangeEvent {
center: Point;
zoom: number;
bounds: Bounds;
initial: boolean;
}
interface MarkerEventParams {
event: React.MouseEvent;
anchor: Point;
payload: any;
}
interface GeoJsonEventParams {
event: React.MouseEvent<SVGElement>;
anchor: Point;
payload: any;
}
// Tile system
interface Tile {
key: string;
url: string;
srcSet: string;
left: number;
top: number;
width: number;
height: number;
active: boolean;
}
type TileComponent = (props: TileComponentProps) => ReactElement;
interface TileComponentProps {
tile: Tile;
tileLoaded: () => void;
}