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 🙏

© 2024 – Pkg Stats / Ryan Hefner

leaflet-html

v0.13.2

Published

Leaflet maps expressed in HTML suitable for HTMX

Downloads

328

Readme

Leaflet HTML

Leaflet expressed in HTML adds map capabilities to Hypermedia Driven Applications (HDA).

npm version tests

Motivation

Expressing Leaflet in HTML enables compatibility with a wide range of front end frameworks.

Fine grained reactive frameworks such as Solid JS or Van JS are ideal candidates for client side development.

RESTful frameworks, like HTMX, that serve HTML over the wire are perfect choices for server rendered content.

Even static site generators like Zola are ideal for this approach.

Documentation

A comprehensive documentation site is available.

leaflet-html docs

Installation

Include Leaflet JS/CSS assets and Leaflet HTML in the document. This can be achieved using importmap to point both leaflet and leaflet-html at ES modules.

<link
  rel="stylesheet"
  href="https://unpkg.com/[email protected]/dist/leaflet.css"
  integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
  crossorigin=""
/>

CDN

Leaflet HTML is available via a Content Delivery Network (CDN) on unpkg.com. This is a good option for use cases that don't need a build step.

<script type="importmap">
  {
    "imports": {
      "leaflet": "https://unpkg.com/[email protected]/dist/leaflet-src.esm.js",
      "leaflet-html": "https://unpkg.com/leaflet-html@latest/dist/leaflet-html.js"
    }
  }
</script>

Execute the library by importing it in a script tag. Leaflet dependencies are detected via the importmap.

<script type="module">
  import "leaflet-html";
</script>

NPM

Leaflet HTML can be added to a project using npm.

npm install leaflet-html

If using a build tool like vite, the following script tag and some CSS is all that is needed to get going.

<script type="module">
  import "leaflet-html";
</script>

Style

In both CDN and npm installation approaches some minimal styling needs to be applied. Custom elements are display: inline by default. Leaflet maps, l-map elements, need to be set to display: block to have a vertical size.

l-map {
  display: block;
  block-size: 100vh;
}

[!NOTE] Only l-map tag needs dimensions. All other l-* elements are purely semantic. They do not take up space on the page. They just indicate the state of the map.

Quick start

To show a map with a base map background, add a <l-tile-layer> tag with a url-template and attribution inside a <l-map>.

<l-map center="[0, 0]" zoom="1">
  <l-tile-layer
    url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  ></l-tile-layer>
</l-map>

Adding layers, layer groups, and controls follows the Leaflet JS one-to-one. E.g. to add a marker to the above example.

<l-map center="[0, 0]" zoom="1">
  <l-tile-layer
    url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  ></l-tile-layer>
  <l-marker lat-lng="[51.5, -0.09]"></l-marker>
</l-map>

Custom elements

Leaflet HTML uses Custom elements to declare the state of each map on the page.

The most common elements are described below. The naming convention followed here makes it easy to map from a Leaflet method, e.g. L.method(), to a custom element, e.g. <l-method></l-method>.

Positional arguments and options are specified as kebab-case equivalents of the camelCase name from the Leaflet docs. E.g. <l-method foo-bar="42"></l-method> translates to L.method({fooBar: 42}). Type conversions and correct call positions are handled by the library.

Name | Leaflet docs | Description -- | -- | -- l-map | L.map | Parent element for a map. Child elements addTo this element. l-tile-layer | L.tileLayer | TileLayer, can be attached to a l-map or l-base-layers element. l-marker | L.marker | Marker, can be attached to a l-map or l-layer-group. l-icon | L.icon | Icon attachable to l-marker. l-popup | L.popup | Popup. l-tooltip | L.tooltip | Tooltip. l-image-overlay | L.imageOverlay | Image overlay. l-video-overlay | L.videoOverlay | Video overlay. l-control-layers | L.control.layers | Adds l-base-layers and l-overlay-layers to control UI. l-base-layers | L.control.layers | Child of l-control-layers. Contains l-tile-layer elements. l-overlay-layers | L.control.layers | Child of l-control-layers. Contains either layer or layer group elements. l-layer-group | L.layerGroup | Parent element to group layers inside control UI. Makes adding/removing groups of UI to a map simple. l-circle | L.circle | Vector layer. l-rectangle | L.rectangle | Vector layer. l-polygon | L.polygon | Vector layer. l-polyline | L.polyline | Vector layer.

Each custom element can be configured using HTML attributes with the same naming convention as the Leaflet docs.

[!NOTE] Attributes are specified by changing camelCase to kebab-case. E.g. maxZoom becomes max-zoom.

For example, a marker with a custom icon in Leaflet JS has attributes like { shadowSize: [50, 64] } in JS, which translates to shadow-size="[50,64]" in HTML.

<l-map center="[51.5, -0.09]" zoom="12">
  <l-tile-layer
    url-template="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
  ></l-tile-layer>
  <l-marker lat-lng="[51.5, -0.09]"><l-icon
      icon-url="icons/leaf-green.png"
      shadow-url="icons/leaf-shadow.png"
      icon-size="[38, 95]"
      shadow-size="[50, 64]" 
      icon-anchor="[22, 94]" 
      shadow-anchor="[4, 62]" 
      popup-anchor="[-3, -76]" 
    ></l-icon>
  </l-marker>
</l-map>

Events

By default, the "ready" event is triggered by the map element. It can be accessed via the detail property of a CustomEvent.

<l-map id="map" ...>
  ...
</l-map>

<script>
  const el = document.getElementById("map")
  el.addEventListener("ready", (ev) => {
    const map = ev.detail
    console.log({ map })
  })
</script>

Arbitrary map events can be listened to by specifying a space-separated list of map events in the on attribute, e.g. on="resize zoomend".

This adds a forwarding mechanism to the CustomElement. To add JS listeners use addEventListener("resize", ...) and inspect the CustomEvent detail property to access the Leaflet Event.

<l-map id="map" ... on="resize">
  ...
</l-map>

<script>
  // Note: both addEventListener and on="eventName" needed
  const el = document.getElementById("map")
  el.addEventListener("resize", (ev) => {
    const leafletResizeEvent = ev.detail
    console.log(leafletResizeEvent)
  })
</script>

CustomEvents

Leaflet HTML wires up a Leaflet JS application by firing and listening to CustomEvents. These events can be observed to add additional functionality to an application.

| Key | Description | | -- | -- | | l:layer:connected | Triggered when a layer is connected to the DOM | | l:layer:removed | Triggered when a layer is removed from the DOM but before the disconnectedCallback fires | | l:popup:connected | Triggered when a popup element is connected to the DOM. Used to bind popup to parent marker | | l:icon:connected | Triggered when a icon element is connected to the DOM. Used to bind icon to parent marker | | l:tooltip:connected | Triggered when a tooltip element is connected to the DOM | | l:latlngbounds:connected | Triggered when a lat-lng-bounds element is connected to the DOM | | l:latlngbounds:changed | Triggered when a lat-lng-bounds element attribute changed |

[!NOTE] At present, only the event keys needed to connect core functionality have been exposed. Future releases may add additional events based on user needs.

Realistic example

The HTML in example/index.html is a simple demonstration of the API.

image

<!-- Note: Leaflet JS/CSS must be included in <head> and l-map styled to an appropriate size. -->
<l-map center="[39.61, -105.02]" zoom="10">
  <l-control-layers>
    <l-base-layers>
      <l-tile-layer
        name="OpenStreetMap"
        url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        max-zoom="12"
      ></l-tile-layer>
      <l-tile-layer
        name="Toner"
        url-template="https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}{r}.png"
        attribution=""
        max-zoom="12"
      ></l-tile-layer>
    </l-base-layers>
    <l-overlay-layers>
      <l-layer-group name="Cities">
        <l-marker lat-lng="[39.61, -105.02]">
          <l-popup content="This is Littleton, CO."></l-popup>
        </l-marker>
        <l-marker lat-lng="[39.74, -104.99]">
          <l-popup content="This is Denver, CO."></l-popup>
        </l-marker>
        <l-marker lat-lng="[39.73, -104.8]">
          <l-popup content="This is Aurora, CO."></l-popup>
        </l-marker>
        <l-marker lat-lng="[39.77, -105.23]">
          <l-popup content="This is Golden, CO."></l-popup>
        </l-marker>
      </l-layer-group>
    </l-overlay-layers>
  </l-control-layers>
</l-map>

Build

To build the source code run.

yarn build

Contributing

Leaflet HTML, while a simple idea, requires contributions from talented and generous people. Please see our contributing guide for how to help make this library better.

CONTRIBUTING.md