npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@georeferencing/leaflet

v0.6.0

Published

Leaflet map adapter for georeferencing: overlay, control points, drawing (Terra Draw), snapping and reference layers

Readme

@georeferencing/leaflet

npm

Leaflet map adapter for georeferencing. It connects a GeoreferencerController from @georeferencing/core to an existing, host-owned Leaflet map:

  • the warped image preview as an image overlay, with opacity and visibility
  • control-point markers with labels, draggable while matching, and residual vectors
  • picking map coordinates for control points, with optional reference snapping
  • drawing and editing points, lines and polygons with Terra Draw
  • reference layers: WFS (GeoJSON responses), static GeoJSON and custom loaders
  • linked image/map navigation and map view history

📖 API documentation · 🗺️ Live demo

Installation

npm install @georeferencing/core @georeferencing/leaflet leaflet
# for drawing (digitizing: true):
npm install terra-draw terra-draw-leaflet-adapter
# with the React editor and export plugins:
npm install @georeferencing/react @georeferencing/plugins react react-dom

Peers: @georeferencing/core (same version as this package), Leaflet ^1.9.4, and optionally terra-draw ^1.36.0 with terra-draw-leaflet-adapter ^1.3.0. Install the same version of every @georeferencing/* package. Import leaflet/dist/leaflet.css as for any Leaflet map. TypeScript projects also need Leaflet's type declarations, which this package's types refer to: npm install -D @types/leaflet.

Use with the React editor

Pass the Leaflet module as lib. The adapter never imports Leaflet itself, because Leaflet accesses window when it is imported: this package can be imported during server-side rendering and works with a Leaflet loaded as a global.

import { useMemo } from "react";
import L from "leaflet";
import { leaflet } from "@georeferencing/leaflet";
import { Georeferencer, type GeoreferencerController } from "@georeferencing/react";
import "@georeferencing/react/styles.css";

export function Editor({ map, controller }: { map: L.Map; controller: GeoreferencerController }) {
  // Create the adapter once per map: a new adapter re-attaches the editor.
  const adapter = useMemo(() => leaflet(map, { lib: L }), [map]);
  return <Georeferencer controller={controller} map={adapter} />;
}

The editor attaches the adapter when it mounts and detaches it when it unmounts; your map, its layers and its view stay as they are. To create the map inside the editor's guided layout (its referenceView), use the useHostMap pattern from the React and map libraries guide, which has a complete Leaflet example.

Use without React

attachLeaflet(map, controller, options) attaches directly and returns the binding (leaflet(map, options)(controller) does the same):

import type { GeoreferencerController } from "@georeferencing/core";
import { attachLeaflet } from "@georeferencing/leaflet";
import L from "leaflet";

export function connect(map: L.Map, controller: GeoreferencerController) {
  const binding = attachLeaflet(map, controller, { lib: L });
  return {
    zoomToImage: () => binding.fitOverlay(),
    disconnect: () => binding.detach(),
  };
}

Your UI drives the controller: load an image, activate the control-point tool, set the image point of a pair, run the fit, confirm. The adapter completes pairs from map clicks and shows the result. The core usage guide walks through a complete page.

The binding implements MapBinding from @georeferencing/core/map:

| Member | Purpose | | --- | --- | | detach() | Remove every layer, marker and listener the adapter added; idempotent | | fitOverlay() | Zoom the map to the aligned preview | | cancelDrawing(), finishDrawing() | Abort a pending pair or sketch; complete a line or polygon | | navigateHistory(-1 \| 1) | Step back and forward through recorded map views | | resize() | Call map.invalidateSize() after the container changed size |

There is no capture(); see PDF reports.

Options

const adapter = leaflet(map, {
  lib: L,
  references: [
    {
      kind: "geojson",
      id: "parcels",
      label: "Parcels",
      data: parcels,
      crs: "EPSG:4326",
      snapping: { vertices: true, edges: true },
    },
  ],
  digitizingSnapping: { references: true },
});

| Option | Purpose | | --- | --- | | lib | Required Leaflet module (import L from "leaflet", or window.L) | | references | Reference providers: wfs (GeoJSON responses), geojson and custom, from @georeferencing/core/map. Add snapping to a provider to snap control points to it | | definitions, datumGrids | Projection definitions and NTv2 grids for references, targets, a custom map CRS and the working CRS; pass the same to the worker engine | | initialView | { extent, crs } to frame the map when attaching; it never georeferences the image | | digitizingSnapping | Snap drawings to references (references: true) and/or other drafts (drafts: true) | | debounceMs | Delay before refreshing viewport references after navigation (150 ms) | | onReferenceStatus | Observe loading, error and completeness feedback per provider |

The adapter reads its options once when attaching. Keep the options object stable, or create a new adapter when they change.

WFS GML responses and layers already owned by the host are supported by the OpenLayers adapter only. Request GeoJSON output (responseFormat: "geojson") from your WFS. See the reference data guide for axis order, paging, authentication and custom loaders.

How it displays results

Leaflet places image overlays as rectangles in the map CRS. While attached, the adapter calls controller.setPreviewCrs() with the map CRS (map.options.crs.code, Web Mercator by default), so previews line up exactly. Maps with a custom Proj4Leaflet CRS need its definition in definitions; L.CRS.Simple is not supported. Fitting, residuals and raster exports keep using the document's working CRS.

What it adds to your map

| Element | Details | | --- | --- | | Layers | A GeoJSON layer per reference provider, residual lines, a GeoJSON layer for drafts and an image overlay for the preview, kept below the other overlays | | Markers | L.markers with a divIcon of class georef-gcp-marker and the point label; draggable while matching points | | Drawing | Terra Draw's layers, only while drawing tools are in use | | Events | click and moveend on the map, keydown (Escape cancels a pending pair) on the container | | Cursor | Crosshair on the map container while a map click places a control point |

detach() removes everything listed here, restores the cursor and resets the preview CRS. Leaflet's shared default vector renderer belongs to the map and stays.

Drawing

When the controller enables digitizing, the drawing tools use Terra Draw, loaded on first use (its Leaflet adapter imports leaflet as a module). Finished sketches become controller features with stable IDs in longitude/latitude; the modify tool loads the current drafts into Terra Draw and commits each edit. Without the optional peers, choosing a drawing tool reports an error and the rest of the editor keeps working.

PDF reports

Leaflet renders tiles as DOM images rather than a canvas, so the binding has no capture() and PDF reports omit the map page. All other report content is available: configure pdf() without capture.

Troubleshooting

| Symptom | Check | | --- | --- | | Attaching fails with "Cannot read properties of undefined" | lib: L is passed in the options | | Tiles or markers are misplaced | leaflet/dist/leaflet.css is imported | | The preview does not appear on a custom-CRS map | The Proj4Leaflet CRS's definition is in definitions; L.CRS.Simple is not supported | | The map is cut off after a layout change | Call map.invalidateSize() (or the binding's resize()) | | Reference data does not appear | The WFS returns GeoJSON; the provider's onReferenceStatus and the editor's reference panel show errors | | Drawing tools report missing dependencies | terra-draw and terra-draw-leaflet-adapter are installed |

License

MIT