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

@orbat-mapper/tactical-draw

v0.2.0-alpha.23

Published

Engine-agnostic draw/edit core for tactical control measures (MIL-STD-2525 / APP-6). The MapAdapter ABI and bring-your-own-engine entry point for the tactical-draw package family.

Downloads

2,786

Readme

@orbat-mapper/tactical-draw

The engine-agnostic draw/edit core for @orbat-mapper tactical graphics: draw and edit controllers, sessions and draw rules, the MapAdapter contract and base adapter, pixel-space hit-testing, handle rendering, interaction styles, and pick helpers.

It only depends on @orbat-mapper/control-measures and geojson, with no concrete map engine in sight. Bring your own: pair this package with one of the engine adapters, or implement MapAdapter against whatever you're already using.

Point symbols are also optional: the core contains only their lightweight model and capability interface. Add @orbat-mapper/point-symbols and milsymbol when an application needs MIL-STD-2525/APP-6 unit icons.

Installation

# npm
npm install @orbat-mapper/tactical-draw @orbat-mapper/control-measures

# pnpm
pnpm add @orbat-mapper/tactical-draw @orbat-mapper/control-measures

Then add an engine adapter (or implement MapAdapter against your own engine):

# pick one — npm
npm install @orbat-mapper/tactical-draw-adapter-openlayers ol
npm install @orbat-mapper/tactical-draw-adapter-maplibre maplibre-gl
npm install @orbat-mapper/tactical-draw-adapter-leaflet leaflet

# pick one — pnpm
pnpm add @orbat-mapper/tactical-draw-adapter-openlayers ol
pnpm add @orbat-mapper/tactical-draw-adapter-maplibre maplibre-gl
pnpm add @orbat-mapper/tactical-draw-adapter-leaflet leaflet

What's inside

  • TacticalDraw — the draw/edit controller hosting draw and edit sessions driven by per-measure draw rules.
  • MapAdapter — the type-only ABI every engine adapter implements, plus BaseMapAdapter with the shared implementation to extend.
  • Hit-testing & pointer driver — pixel-space hitTestFeature, hit tolerances, and the EditPointerDriver contract adapters implement for the edit controller.
  • Interaction stylescoerceHandleStyle and the InteractionStyle / GuideStyle / HandleStyle shapes. (Handle rendering itself is not part of the public API.)
  • Pick helpers — hit tolerance and control-measure identification utilities.

Pick to edit

Use onGraphicPick to subscribe to committed graphics without accessing internal layer ids:

const unsubscribe = td.onGraphicPick((event) => {
  const graphic = graphics.find((candidate) => candidate.id === event.id);
  if (graphic) void td.edit(graphic);
});

The handler receives the full PickEvent, with event.id set to the graphic id. The returned unsubscribe function is idempotent, and onGraphicPick(handler, { signal }) also supports abort-driven teardown.

Cancel and inspect the active interaction

Use cancel() for a host Cancel button. It aborts draws and edits, including fixed-length draws that do not expose a session:

cancelButton.onclick = () => td.cancel();

activeSession exposes the live DrawSession or EditSession when one exists, and returns null while idle or during a fixed-length draw:

const session = td.activeSession;
if (session && "canCommit" in session) {
  doneButton.disabled = !session.canCommit;
}

Live edit and transform sessions expose a session-local history. Completed gestures and authored programmatic mutations are undoable without settling the session; pointer-move preview frames are not history steps:

const active = td.activeSession;
const history =
  (active && "history" in active ? active.history : null) ?? td.activeTransformSession?.history;
if (history) history.undo();

history.subscribe(...) reports canUndo, canRedo, and optional operation labels. Committing folds only the selected working state into the host document as one operation. Changing a transform session's members with setGraphics() establishes a new local baseline and clears both stacks.

Bring your own engine

Implement MapAdapter (or extend BaseMapAdapter) against your map engine and hand it to TacticalDraw. The controllers, sessions, gestures, and handle rendering above the adapter don't need to know or care which engine is underneath.

License

MIT