ReactJS maps without external dependencies - performance-first React-centric extendable map engine
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
SVG-based rendering system for GeoJSON data with interactive features and styling capabilities. Supports all GeoJSON geometry types including Points, LineStrings, Polygons, and their Multi- variants, with comprehensive event handling and dynamic styling.
Main component for rendering GeoJSON data as interactive SVG overlays.
/**
* Renders GeoJSON data as interactive SVG overlays
* @param props - GeoJSON configuration and styling options
* @returns JSX.Element representing the GeoJSON overlay
*/
function GeoJson(props: GeoJsonProps): JSX.Element;
interface GeoJsonProps extends PigeonProps {
// Data and configuration
data?: any;
svgAttributes?: any;
styleCallback?: (feature: any, hover: boolean) => any;
hover?: any;
feature?: any;
// Styling
className?: string;
style?: CSSProperties;
// Content
children?: React.ReactNode;
// Event handlers
onClick?: (params: GeoJsonEventParams) => void;
onContextMenu?: (params: GeoJsonEventParams) => void;
onMouseOver?: (params: GeoJsonEventParams) => void;
onMouseOut?: (params: GeoJsonEventParams) => void;
}
interface GeoJsonEventParams {
event: React.MouseEvent<SVGElement>;
anchor: Point;
payload: any;
}Usage Examples:
import React from "react";
import { Map, GeoJson } from "pigeon-maps";
// Basic GeoJSON rendering
function BasicGeoJson() {
const geoJsonData = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [4.6997, 50.879]
},
properties: {
name: "Brussels"
}
}
]
};
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJson data={geoJsonData} />
</Map>
);
}
// Styled GeoJSON with events
function StyledGeoJson() {
const polygonData = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[
[4.68, 50.87],
[4.72, 50.87],
[4.72, 50.89],
[4.68, 50.89],
[4.68, 50.87]
]]
},
properties: {
name: "Brussels Center"
}
}
]
};
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJson
data={polygonData}
svgAttributes={{
fill: 'rgba(255, 0, 0, 0.3)',
stroke: 'red',
strokeWidth: '2'
}}
onClick={({ payload }) => {
console.log('Clicked feature:', payload.properties.name);
}}
/>
</Map>
);
}Component that fetches GeoJSON data from a URL and renders it.
/**
* Fetches and renders GeoJSON data from a URL
* @param props - GeoJSON loader configuration
* @returns JSX.Element representing the loaded GeoJSON or null while loading
*/
function GeoJsonLoader(props: GeoJsonLoaderProps): JSX.Element;
interface GeoJsonLoaderProps extends GeoJsonProps {
link?: string;
}Usage Example:
import React from "react";
import { Map, GeoJsonLoader } from "pigeon-maps";
function RemoteGeoJson() {
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJsonLoader
link="https://example.com/data.geojson"
svgAttributes={{
fill: 'rgba(0, 255, 0, 0.3)',
stroke: 'green',
strokeWidth: '1'
}}
/>
</Map>
);
}Component for rendering individual GeoJSON features with interactive capabilities.
/**
* Renders individual GeoJSON features with interactive capabilities
* @param props - Feature configuration and styling
* @returns JSX.Element representing the feature
*/
function GeoJsonFeature(props: GeoJsonProps): JSX.Element;/**
* Renders GeoJSON Point geometry
* @param props - Point geometry configuration
* @returns JSX.Element representing the point
*/
function PointComponent(props: GeometryProps): JSX.Element;
/**
* Renders GeoJSON MultiPoint geometry
* @param props - MultiPoint geometry configuration
* @returns JSX.Element representing multiple points
*/
function MultiPoint(props: GeometryProps): JSX.Element;
interface GeometryProps {
coordinates?: [number, number] | Array<[number, number]> | Array<Array<[number, number]>> | Array<Array<Array<[number, number]>>>;
latLngToPixel?: (latLng: Point, center?: Point, zoom?: number) => Point;
svgAttributes?: SVGProps<SVGElement>;
geometry?: GeoJsonGeometry;
}/**
* Renders GeoJSON LineString geometry
* @param props - LineString geometry configuration
* @returns JSX.Element representing the line
*/
function LineString(props: GeometryProps): JSX.Element;
/**
* Renders GeoJSON MultiLineString geometry
* @param props - MultiLineString geometry configuration
* @returns JSX.Element representing multiple lines
*/
function MultiLineString(props: GeometryProps): JSX.Element;/**
* Renders GeoJSON Polygon geometry
* @param props - Polygon geometry configuration
* @returns JSX.Element representing the polygon
*/
function Polygon(props: GeometryProps): JSX.Element;
/**
* Renders GeoJSON MultiPolygon geometry
* @param props - MultiPolygon geometry configuration
* @returns JSX.Element representing multiple polygons
*/
function MultiPolygon(props: GeometryProps): JSX.Element;/**
* Renders GeoJSON GeometryCollection
* @param props - GeometryCollection configuration
* @returns JSX.Element representing the collection
*/
function GeometryCollection(props: GeometryProps): JSX.Element;
interface GeoJsonGeometry {
type: string;
coordinates?: [number, number] | Array<[number, number]> | Array<Array<[number, number]>> | Array<Array<Array<[number, number]>>>;
geometries?: Array<GeoJsonGeometry>;
}const defaultSvgAttributes = {
fill: '#93c0d099',
strokeWidth: '2',
stroke: 'white',
r: '30'
};<GeoJson
data={geoJsonData}
svgAttributes={{
fill: 'rgba(255, 0, 0, 0.5)',
stroke: 'darkred',
strokeWidth: '3',
strokeDasharray: '5,5'
}}
/>styleCallback?: (feature: any, hover: boolean) => any;Usage Example:
function DynamicStyledGeoJson() {
const styleCallback = (feature, hover) => {
const baseStyle = {
fill: feature.properties.color || '#93c0d099',
stroke: 'white',
strokeWidth: '2'
};
if (hover) {
return {
...baseStyle,
fill: '#ff000080',
strokeWidth: '4'
};
}
return baseStyle;
};
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJson
data={geoJsonData}
styleCallback={styleCallback}
onClick={({ payload }) => {
console.log('Feature properties:', payload.properties);
}}
/>
</Map>
);
}Points can use custom SVG paths instead of circles:
<GeoJson
data={pointData}
svgAttributes={{
fill: '#ff6b6b',
stroke: 'white',
strokeWidth: '2',
path: 'c-5,-10 -10,-10 -10,0 0,10 10,10 10,0z' // Custom marker shape
}}
/>All GeoJSON events receive a GeoJsonEventParams object:
interface GeoJsonEventParams {
event: React.MouseEvent<SVGElement>;
anchor: Point;
payload: any; // The GeoJSON feature object
}// Mouse click on feature
onClick?: (params: GeoJsonEventParams) => void;
// Right-click or context menu on feature
onContextMenu?: (params: GeoJsonEventParams) => void;
// Mouse enters feature area
onMouseOver?: (params: GeoJsonEventParams) => void;
// Mouse leaves feature area
onMouseOut?: (params: GeoJsonEventParams) => void;function InteractiveGeoJson() {
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJson
data={geoJsonData}
onClick={({ event, anchor, payload }) => {
console.log('Clicked at coordinates:', anchor);
console.log('Feature data:', payload);
console.log('Mouse event:', event);
}}
onMouseOver={({ payload }) => {
console.log('Hovering over:', payload.properties.name);
}}
/>
</Map>
);
}Features automatically track hover state internally:
<GeoJson
data={geoJsonData}
styleCallback={(feature, hover) => ({
fill: hover ? '#ff0000' : '#0000ff',
stroke: 'white'
})}
/>function ControlledHoverGeoJson() {
const [hoveredFeature, setHoveredFeature] = useState(null);
return (
<Map height={400} center={[50.879, 4.6997]} zoom={11}>
<GeoJson
data={geoJsonData}
hover={hoveredFeature}
onMouseOver={({ payload }) => setHoveredFeature(payload)}
onMouseOut={() => setHoveredFeature(null)}
styleCallback={(feature, hover) => ({
fill: hover ? '#ff0000' : '#0000ff'
})}
/>
</Map>
);
}Install with Tessl CLI
npx tessl i tessl/npm-pigeon-maps