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

@htmlbricks/hb-map

v0.76.5

Published

Interactive map: `center`, `zoom`, `source` (OSM or CARTO vector styles), `options` (e.g. `centerFromGeometries`, marker text layout), and `data` with markers (lng/lat, icon, popup HTML, text). CARTO vector uses `source.style` in light mode; in dark mode

Downloads

4,625

Readme

hb-map

Category: maps · Tags: maps · Package: @htmlbricks/hb-map

Description

hb-map is an interactive map web component built with OpenLayers. You configure center and zoom, a source (OpenStreetMap raster, custom XYZ tiles, or CARTO vector basemaps), options (fit view to markers, label layout), and data for on-map markers (longitude/latitude, optional icon, HTML popup, and optional text label).

The component listens for single clicks: clicks on empty map emit coordinates and current view; clicks on markers open optional popup HTML and emit a marker event. Setting screenshot to yes captures the visible map to PNG and emits a base64 payload when rendering completes.

Basemap sources (source)

Set source as a JSON string (see Attributes).

| source.type | Behavior | |---------------|----------| | osm | OpenStreetMap raster tiles. | | xyz | Raster tiles from source.url (XYZ template with {z}, {x}, {y}). | | carto_vector | CARTO vector tiles (default tile URL if url is omitted). Styling uses built-in presets. |

CARTO vector: source.style

For carto_vector, source.style may be positron, dark_matter, or voyager when the page uses a light color scheme.

When the component detects a dark scheme, the vector basemap always uses the dark_matter palette, regardless of source.style. Detection order:

  1. hb-map, then document.documentElement, then document.body: data-theme="dark" or class theme-dark → dark; data-theme="light" or theme-light → light.
  2. If neither is set explicitly, prefers-color-scheme: dark selects dark.

The host and document are observed for data-theme and class changes, and the media query is listened to, so the basemap updates when the theme toggles.

CARTO vector: boundaries and labels

  • boundaries_only: When true, only the boundary layer is drawn as lines (plus country names from the place layer where class === "country"). Land, roads, water fills, and other layers are not drawn.
  • national_boundaries_only: When true, only international / country boundaries (OSM admin_level 2) are shown as solid lines. When false, level 2 stays solid and other allowed levels use a dashed stroke.
  • boundary_admin_levels: Optional JSON array string of numeric admin levels to keep, e.g. "[2]" for countries only, "[2,4]" for countries and other divisions present in the tiles. Empty or omitted means no extra filter (all boundary features at the current zoom still pass the national-only rule when that flag applies). With national_boundaries_only, the effective set is the intersection with level 2; if the list excludes 2, no boundaries render.

Boolean fields in serialized source may use yes / no (or true / false / 1 / 0 for compatibility).

OSM in dark mode

For osm, raster tiles are rendered with a grayscale + invert filter when the same dark detection applies, so the map stays readable on dark UIs.

Marker data (data)

data is a JSON array of objects. Each object may include a marker field. The current implementation renders only marker entries (icons, labels, popups, and click handling). The TypeScript Component type also describes optional point and line shapes for consistency with the schema; those are not drawn by this version of the component.

Marker object (marker)

| Field | Description | |-------|-------------| | lngLat | [longitude, latitude] in EPSG:4326 (same order as OpenLayers fromLonLat). | | icon | Optional: uri (image URL), scale, anchor [x, y], opacity, color (tint). | | id | Optional string passed through on markerClick. | | popupHtml | Optional HTML string shown in the map popup when the marker is clicked. | | text | Optional label next to or around the icon (or alone if there is no icon.uri). | | text_position | Per-marker override: top, right, bottom, left (default from options.text_position or right). | | text_offset | Per-marker pixel gap for label placement; falls back to options.text_offset, then an internal default. |

If there is no custom icon and no text, a default pin icon is used.

Options (options)

JSON string. Common fields:

| Field | Description | |-------|-------------| | centerFromGeometries | When truthy, the view is centered or fitted from marker positions (fit when there are multiple markers with valid extent). | | text_position | Default label side relative to the icon: top, right, bottom, left. | | text_offset | Default pixel gap between icon and label. | | text_scale | Multiplier for label font size (default scale 1 → base ~13px). |

Screenshots

Set the attribute screenshot="yes" to request a capture after the next render completes. The component dispatches screenshotTaken with { base64 } (PNG data URL). Clear or change the attribute between captures if your host framework does not re-trigger on repeated yes.

Styling (Bulma and host size)

The map canvas sits on a host whose background can follow Bulma’s scheme variable --bulma-scheme-main. Size is controlled by --hb-map-width, --hb-map-height, and fallback --hb-map-default-size (default 200px when width/height are unset). See Bulma CSS variables and extra/docs.ts (styleSetup.vars).

| Variable | Purpose | |----------|---------| | --bulma-scheme-main | Background behind the map. | | --hb-map-default-size | Fallback width and height when explicit size vars are empty. | | --hb-map-width | Optional explicit host width. | | --hb-map-height | Optional explicit host height. |

CSS parts

None.

HTML slots

None.

Custom element

hb-map

Attributes (snake_case; string values in HTML)

Web component attributes are strings. Pass objects and arrays as JSON strings. Use yes / no for boolean fields where the project encoding applies; nested source booleans also accept true / false as strings.

| Attribute | Required | Description | |-----------|----------|-------------| | id | No | Optional element id. | | style | No | Optional host inline style (type-level; use CSS variables for layout when possible). | | zoom | Yes* | Zoom level as a string (e.g. "11"). Parsed to a number internally. | | center | Yes* | JSON array string: [longitude, latitude] in EPSG:4326. | | data | Yes* | JSON array of geometry entries; markers use the marker property (see Marker data). | | source | Yes* | JSON object: at minimum { "type": "osm" \| "xyz" \| "carto_vector", ... } with optional url, style, boundaries_only, boundary_admin_levels, national_boundaries_only for vector tiles. | | options | Yes* | JSON object for view and label defaults (see Options). | | screenshot | No | Set to yes to capture the map and emit screenshotTaken. |

*The TypeScript Component type marks these as required for a complete configuration. The implementation still applies defaults when attributes are missing: zoom 6, center [37.5176038, 15.0819224] (same [longitude, latitude] order as elsewhere, passed to fromLonLat), source { type: "osm" }, options {}, data [].

On window resize, the map layout is updated (debounced).

Events

Listen with addEventListener or your framework’s binding. All detail payloads are plain objects.

| Event | detail | |-------|----------| | pointClickCoordinates | { coordinates: { latitude, longitude }, zoom, center }center is [lon, lat] in EPSG:4326 when derived from the view. Emitted when the click does not hit a marker. | | markerClick | { coordinates: { latitude, longitude }, id? }id is present when the feature carries marker.id in data. | | screenshotTaken | { base64 } — PNG data URL string. |

TypeScript (types/webcomponent.type.d.ts)

export type Component = {
  id?: string;
  style?: string;
  zoom: number;
  center: number[];
  data: {
    marker?: {
      lngLat: number[];
      icon?: {
        uri: string;
        scale?: number;
        anchor?: number[];
        opacity?: number;
        color?: string;
      };
      id?: string;
      popupHtml?: string;
      text?: string;
      text_position?: "top" | "right" | "bottom" | "left";
      text_offset?: number;
    };
    point?: {
      lngLat: number[];
      icon?: {
        uri: string;
        scale?: number;
        anchor?: number[];
        opacity?: number;
        color?: string;
      };
      id?: string;
      popupHtml?: string;
    };
    line?: {
      lngLat: number[];
      icon?: {
        uri: string;
        scale?: number;
        anchor?: number[];
        opacity?: number;
        color?: string;
      };
      id?: string;
      popupHtml?: string;
    }[];
  }[];
  source: {
    type: string;
    url?: string;
    /**
     * Basemap palette for light UI. In dark color scheme (`prefers-color-scheme: dark` or
     * `data-theme="dark"` / `.theme-dark` on host or document), `dark_matter` is always used.
     */
    style?: "positron" | "dark_matter" | "voyager";
    /** When `true`, only the vector `boundary` layer is drawn (no land, roads, water fill, etc.). */
    boundaries_only?: boolean;
    /**
     * Optional JSON array string of OSM `admin_level` values to keep for `boundary` features,
     * e.g. `"[2]"` for country borders, `"[2,4]"` for countries plus common internal divisions.
     * Omit or empty to show all boundaries present in the tiles at the current zoom.
     */
    boundary_admin_levels?: string;
    /**
     * When `true`, only international / country boundaries (`admin_level` 2) are drawn; internal
     * regional lines are hidden. Combines with `boundary_admin_levels` by intersection (e.g. if
     * the JSON list excludes `2`, no boundaries render). National lines use a solid stroke;
     * when `false`, level 2 stays solid and other levels stay dashed.
     */
    national_boundaries_only?: boolean;
  };
  options: {
    centerFromGeometries?: boolean;
    text_position?: "top" | "right" | "bottom" | "left";
    text_offset?: number;
    text_scale?: number;
  };
  screenshot?: string;
};

export type Events = {
  pointClickCoordinates: {
    coordinates: { latitude: number; longitude: number };
    zoom: number;
    center: number[];
  };
  markerClick: {
    coordinates: { latitude: number; longitude: number };
    id?: string;
  };
  screenshotTaken: {
    base64: string;
  };
};

Minimal HTML example

<hb-map
  zoom="9"
  center="[10,10]"
  source='{"type":"osm"}'
  options="{}"
  data="[]"
></hb-map>

Example: CARTO Voyager with markers

<hb-map
  zoom="11"
  center="[2.3522,48.8566]"
  source='{"type":"carto_vector","style":"voyager"}'
  options='{"centerFromGeometries":true}'
  data='[{"marker":{"lngLat":[2.36,48.86],"text":"Paris"}}]'
></hb-map>

Inside JSON strings, use standard JSON booleans (true / false). Truthy string values (e.g. "yes") for centerFromGeometries are also treated as enabled when parsed into a plain object.