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

cartis

v0.5.0

Published

Library for rendering maps as SVG or vector graphics.

Readme

Cartis

Cartis is a library for rendering maps as vector graphics, which abstracts away the complexity of TopoJSON and D3.

This library is under active development (0.x).
Breaking changes may occur between minor versions.

Currently only Portugal (Country.PORTUGAL) is supported.

Install

npm install cartis

Quick start

import { Country, CountryMap } from "cartis";

const container = document.getElementById("map")!; // must already have a non-zero size

const map = await CountryMap.create(Country.PORTUGAL, container);

map.styleMunicipalities(["Sintra"], { fill: "#86c227" });
map.fitToMunicipalities(["Sintra"], { zoom: 1.5 });

// later, e.g. on component unmount:
map.destroy();

Framework-agnostic lifecycle note: CountryMap.create() only resolves once the map is fully built, so you never hold a half-built instance. If you might call create() again before an earlier call resolves (e.g. React StrictMode remounting a component), guard against keeping a stale result:

let cancelled = false;

CountryMap.create(Country.PORTUGAL, container).then((map) => {
	if (cancelled) {
		map.destroy(); // discard — a newer call already took over
		return;
	}
	// ...store `map` somewhere you can call .destroy() on later
});

// on cleanup:
cancelled = true;

API reference

CountryMap

The core class. No public constructor — build one with CountryMap.create().

| Member | Signature | What it does | | --- | --- | --- | | CountryMap.create | (country, container, options?) => Promise<CountryMap> | Builds and renders a map into container. Resolves once fully usable. | | destroy | () => void | Removes this instance's <svg> and releases its state. Always safe to call. | | styleMunicipalities | (municipalities, options?) => void | Colors the listed municipalities with one shared style. Omit options to reset them to the default style. | | styleDistricts | (districts, options?) => void | Colors every municipality belonging to the listed districts with one shared style (no separate district polygons — see caveat below). | | fitToCountry | (options?) => void | Zooms/pans back to the full-country view. | | fitToMunicipalities | (municipalities, options) => void | Zooms/pans to frame the given municipalities. Requires a non-empty list. | | fitToDistricts | (districts, options) => void | Zooms/pans to frame the given districts. Requires a non-empty list. | | zoomIn | () => void | Zooms in by a fixed 1.25x step (capped at 10x). | | zoomOut | () => void | Zooms out by a fixed 0.75x step (capped at 1x). |

Full parameter docs (including options shapes and edge cases) are in the source as JSDoc — your editor will show them on hover/autocomplete.

Caveat: cartis has no separate district-boundary topology. styleDistricts/fitToDistricts work by matching each municipality's district property, so what renders is municipality borders sharing a color — set strokeWidth: 0 if you want same-district municipalities to visually merge into one shape.

Types

| Export | What it is | | --- | --- | | Country | Enum of supported countries. Only Country.PORTUGAL today. | | District | Literal union of all 18 Portuguese district names. | | Municipality | Literal union of all 278 Portuguese municipality names. | | MapOptions | Options for CountryMap.create() (initial styling; padding/zoom fields are reserved, not yet implemented). | | StyleOptions | { fill?, strokeColor?, strokeWidth? } — used by styleMunicipalities/styleDistricts. | | FitOptions | { zoom?, duration? } — used by fitToMunicipalities/fitToDistricts. |

Utilities

| Export | Signature | What it does | | --- | --- | --- | | getDistrictsArray | () => District[] | All 18 district names. | | getMunicipalitiesArray | () => Municipality[] | All 278 municipality names. | | randomMunicipality | (country) => Municipality | A random municipality name. | | getDistrictFromString | (input) => District \| undefined | Exact, accent/case-insensitive match. | | getMunicipalityFromString | (input) => Municipality \| undefined | Exact, accent/case-insensitive match. | | getDistrictsFromString | (input) => District[] | Prefix match — for search-as-you-type. | | getMunicipalitiesFromString | (input) => Municipality[] | Prefix match — for search-as-you-type. | | getMissingDistricts | (existing) => District[] | The complement of a district list. | | getMissingMunicipalities | (existing) => Municipality[] | The complement of a municipality list. | | doStringsMatch | (a, b) => boolean | Accent/case/whitespace-insensitive equality check. | | stringToSlug | (text) => string | Lowercase, hyphenated, accent-stripped slug. | | stringToTitleCase | (text) => string | Title-cases words, keeping Portuguese articles/prepositions lowercase. |

What's not here yet

  • Multi-country support (only Portugal)
  • Custom/runtime TopoJSON loading (the topology is bundled)
  • Click/hover event listeners
  • Per-feature choropleth coloring in a single call (each style* call applies one shared style to every match)
  • Tooltips, labels, markers/overlays

See docs/ROADMAP.md and docs/PRODUCT_PRIORITIES.md for internal planning notes on these.