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

markers-overlays.mddocs/

Markers and Overlays

Interactive markers and custom overlays for positioning content on the map. Markers provide pre-styled map pins with hover effects and event handling, while Overlays offer a generic container for custom positioned content.

Capabilities

Marker Component

Interactive map markers with customizable appearance and comprehensive event handling.

/**
 * Interactive map marker with customizable styling and events
 * @param props - Marker configuration and event handlers
 * @returns JSX.Element representing the marker
 */
function Marker(props: MarkerProps): JSX.Element;

interface MarkerProps extends PigeonProps {
  // Styling options
  color?: string;
  width?: number;
  height?: number;
  hover?: boolean;
  style?: React.CSSProperties;
  className?: string;
  
  // Data and content
  payload?: any;
  children?: JSX.Element;
  
  // Event handlers
  onClick?: (params: MarkerEventParams) => void;
  onContextMenu?: (params: MarkerEventParams) => void;
  onMouseOver?: (params: MarkerEventParams) => void;
  onMouseOut?: (params: MarkerEventParams) => void;
}

interface MarkerEventParams {
  event: React.MouseEvent;
  anchor: Point;
  payload: any;
}

Usage Examples:

import React from "react";
import { Map, Marker } from "pigeon-maps";

// Basic marker
function BasicMarker() {
  return (
    <Map height={400} center={[50.879, 4.6997]} zoom={11}>
      <Marker anchor={[50.879, 4.6997]} />
    </Map>
  );
}

// Styled marker with events
function StyledMarker() {
  return (
    <Map height={400} center={[50.879, 4.6997]} zoom={11}>
      <Marker
        anchor={[50.879, 4.6997]}
        color="#ff6b6b"
        width={40}
        height={40}
        payload={{ name: "Brussels", id: 1 }}
        onClick={({ anchor, payload }) => {
          console.log(`Clicked ${payload.name} at`, anchor);
        }}
        onMouseOver={({ payload }) => {
          console.log(`Hovering over ${payload.name}`);
        }}
      />
    </Map>
  );
}

// Custom marker content
function CustomMarker() {
  return (
    <Map height={400} center={[50.879, 4.6997]} zoom={11}>
      <Marker anchor={[50.879, 4.6997]}>
        <div style={{
          background: 'white',
          padding: '5px',
          borderRadius: '3px',
          boxShadow: '0 2px 4px rgba(0,0,0,0.3)'
        }}>
          Custom Content
        </div>
      </Marker>
    </Map>
  );
}

Overlay Component

Generic container for positioning custom content on the map at specific coordinates.

/**
 * Generic overlay container for custom positioned content
 * @param props - Overlay configuration and content
 * @returns JSX.Element representing the overlay
 */
function Overlay(props: OverlayProps): JSX.Element;

interface OverlayProps extends PigeonProps {
  style?: React.CSSProperties;
  className?: string;
  children?: React.ReactNode;
}

Usage Examples:

import React from "react";
import { Map, Overlay } from "pigeon-maps";

// Text overlay
function TextOverlay() {
  return (
    <Map height={400} center={[50.879, 4.6997]} zoom={11}>
      <Overlay anchor={[50.879, 4.6997]} offset={[10, -20]}>
        <div style={{
          background: 'rgba(0,0,0,0.8)',
          color: 'white',
          padding: '8px',
          borderRadius: '4px',
          fontSize: '14px'
        }}>
          Brussels, Belgium
        </div>
      </Overlay>
    </Map>
  );
}

// Complex overlay with multiple elements
function ComplexOverlay() {
  return (
    <Map height={400} center={[50.879, 4.6997]} zoom={11}>
      <Overlay anchor={[50.879, 4.6997]} offset={[0, -50]}>
        <div style={{
          background: 'white',
          border: '2px solid #333',
          borderRadius: '8px',
          padding: '12px',
          minWidth: '200px',
          boxShadow: '0 4px 8px rgba(0,0,0,0.2)'
        }}>
          <h3 style={{ margin: '0 0 8px 0' }}>Location Info</h3>
          <p style={{ margin: '0' }}>Brussels, Belgium</p>
          <button style={{ marginTop: '8px' }}>
            Get Directions
          </button>
        </div>
      </Overlay>
    </Map>
  );
}

Positioning System

PigeonProps Interface

Base props interface for all positioned elements on the map.

interface PigeonProps {
  // Geographic positioning
  anchor?: Point;
  offset?: Point;
  
  // Pixel positioning (set automatically by Map)
  left?: number;
  top?: number;
  
  // Map context (provided automatically by Map)
  mapState?: MapState;
  mapProps?: MapProps;
  
  // Coordinate conversion functions (provided by Map)
  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;
}

Positioning Options

Geographic Positioning:

  • anchor: Geographic coordinates [lat, lng] where the element should be positioned
  • offset: Pixel offset [x, y] from the anchor point (positive x is right, positive y is down)

Pixel Positioning:

  • left and top: Exact pixel coordinates (calculated automatically by the Map component)

Map Context

Elements positioned on the map automatically receive:

  • Current map state (bounds, zoom, center, dimensions)
  • Map configuration props
  • Coordinate conversion functions
  • Map control functions

Event Handling

Marker Events

All marker events receive a MarkerEventParams object:

interface MarkerEventParams {
  event: React.MouseEvent;
  anchor: Point;
  payload: any;
}
  • event: The original React mouse event
  • anchor: Geographic coordinates of the marker
  • payload: Custom data attached to the marker

Event Types

// Mouse click (left button)
onClick?: (params: MarkerEventParams) => void;

// Right-click or context menu
onContextMenu?: (params: MarkerEventParams) => void;

// Mouse enters marker area
onMouseOver?: (params: MarkerEventParams) => void;

// Mouse leaves marker area
onMouseOut?: (params: MarkerEventParams) => void;

Styling and Customization

Marker Styling

interface MarkerStyling {
  color?: string;        // Marker color (default: '#93C0D0')
  width?: number;        // Marker width in pixels
  height?: number;       // Marker height in pixels
  hover?: boolean;       // Controlled hover state
  style?: React.CSSProperties;  // Additional CSS styles
  className?: string;    // CSS class name
}

Default Marker Dimensions

  • Default width: 29 pixels
  • Default height: 34 pixels
  • Aspect ratio is maintained when only width or height is specified

Hover Effects

Markers support automatic and controlled hover states:

// Automatic hover (internal state)
<Marker anchor={[50.879, 4.6997]} />

// Controlled hover (external state)
const [isHovered, setIsHovered] = useState(false);
<Marker 
  anchor={[50.879, 4.6997]} 
  hover={isHovered}
  onMouseOver={() => setIsHovered(true)}
  onMouseOut={() => setIsHovered(false)}
/>

CSS Classes

Default Classes

  • Markers: pigeon-click-block (prevents map clicks when clicking marker)
  • Overlays: pigeon-click-block (prevents map clicks when clicking overlay)

Custom Classes

<Marker 
  anchor={[50.879, 4.6997]} 
  className="my-custom-marker"
/>

<Overlay 
  anchor={[50.879, 4.6997]} 
  className="my-custom-overlay"
>
  Content
</Overlay>

Performance Considerations

  • Markers and overlays are re-rendered when the map moves/zooms
  • Use React.memo() for expensive custom marker content
  • Consider virtualization for large numbers of markers
  • Markers automatically prevent event bubbling to the map

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