CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pigeon-maps

ReactJS maps without external dependencies - performance-first React-centric extendable map engine

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

geojson.mddocs/

GeoJSON

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.

Capabilities

GeoJson Component

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>
  );
}

GeoJsonLoader Component

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>
  );
}

GeoJsonFeature Component

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;

Geometry Components

Point Rendering

/**
 * 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;
}

Line Rendering

/**
 * 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;

Polygon Rendering

/**
 * 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;

Geometry Collection

/**
 * 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>;
}

Styling System

Default SVG Attributes

const defaultSvgAttributes = {
  fill: '#93c0d099',
  strokeWidth: '2',
  stroke: 'white',
  r: '30'
};

Static Styling

<GeoJson
  data={geoJsonData}
  svgAttributes={{
    fill: 'rgba(255, 0, 0, 0.5)',
    stroke: 'darkred',
    strokeWidth: '3',
    strokeDasharray: '5,5'
  }}
/>

Dynamic Styling with Callbacks

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>
  );
}

Custom Path Styling for Points

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
  }}
/>

Event Handling

Event Parameters

All GeoJSON events receive a GeoJsonEventParams object:

interface GeoJsonEventParams {
  event: React.MouseEvent<SVGElement>;
  anchor: Point;
  payload: any; // The GeoJSON feature object
}

Event Types

// 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;

Event Example

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>
  );
}

Hover States

Automatic Hover

Features automatically track hover state internally:

<GeoJson
  data={geoJsonData}
  styleCallback={(feature, hover) => ({
    fill: hover ? '#ff0000' : '#0000ff',
    stroke: 'white'
  })}
/>

Controlled Hover

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>
  );
}

Performance Considerations

  • GeoJSON is rendered as SVG, which performs well for moderate numbers of features
  • For large datasets (>1000 features), consider:
    • Simplifying geometries at lower zoom levels
    • Using feature filtering based on map bounds
    • Implementing level-of-detail rendering
  • Complex polygons with many vertices may impact performance
  • SVG styling is more performant than DOM manipulation for dynamic styling

Install with Tessl CLI

npx tessl i tessl/npm-pigeon-maps

docs

controls.md

draggable.md

geojson.md

index.md

map.md

markers-overlays.md

providers.md

tile.json