leaflet-html 0.3.4 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/package.json +5 -1
  2. package/.github/workflows/master.yml +0 -15
  3. package/.github/workflows/npm-publish.yml +0 -37
  4. package/.prettierignore +0 -2
  5. package/.prettierrc +0 -1
  6. package/docs/config.toml +0 -16
  7. package/docs/content/_index.md +0 -89
  8. package/docs/content/articles/_index.md +0 -5
  9. package/docs/content/articles/basic.md +0 -110
  10. package/docs/content/articles/htmx.md +0 -84
  11. package/docs/content/articles/icons.md +0 -47
  12. package/docs/content/articles/style.md +0 -14
  13. package/docs/public/icons/leaf-green.png +0 -0
  14. package/docs/public/icons/leaf-orange.png +0 -0
  15. package/docs/public/icons/leaf-red.png +0 -0
  16. package/docs/public/icons/leaf-shadow.png +0 -0
  17. package/docs/static/htmx/clicked.html +0 -1
  18. package/docs/static/htmx/marker.html +0 -3
  19. package/docs/static/htmx/tile-esri.html +0 -3
  20. package/docs/static/htmx/tile-osm.html +0 -4
  21. package/docs/static/htmx/tile-voyager.html +0 -4
  22. package/docs/static/icons/leaf-green.png +0 -0
  23. package/docs/static/icons/leaf-orange.png +0 -0
  24. package/docs/static/icons/leaf-red.png +0 -0
  25. package/docs/static/icons/leaf-shadow.png +0 -0
  26. package/docs/static/style.css +0 -48
  27. package/docs/templates/article-page.html +0 -8
  28. package/docs/templates/article.html +0 -12
  29. package/docs/templates/base.html +0 -43
  30. package/docs/templates/index.html +0 -6
  31. package/docs/templates/shortcodes/url.html +0 -1
  32. package/example/geojson/index.html +0 -44
  33. package/example/index.html +0 -113
  34. package/example/overlays/index.html +0 -78
  35. package/src/events.js +0 -3
  36. package/src/index.js +0 -33
  37. package/src/l-base-layers.js +0 -16
  38. package/src/l-control-layers.js +0 -39
  39. package/src/l-geojson.js +0 -27
  40. package/src/l-icon.js +0 -124
  41. package/src/l-image-overlay.js +0 -54
  42. package/src/l-lat-lng-bounds.js +0 -21
  43. package/src/l-layer-group.js +0 -51
  44. package/src/l-layer.js +0 -8
  45. package/src/l-map.js +0 -56
  46. package/src/l-marker.js +0 -95
  47. package/src/l-overlay-layers.js +0 -16
  48. package/src/l-popup.js +0 -22
  49. package/src/l-tile-layer.js +0 -32
  50. package/src/l-video-overlay.js +0 -34
  51. package/vite.config.js +0 -7
@@ -1,113 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <title>Leaflet HTML</title>
5
- <meta charset="utf-8" />
6
- <link
7
- rel="stylesheet"
8
- href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
9
- integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
10
- crossorigin=""
11
- />
12
- <script type="importmap">
13
- {
14
- "imports": {
15
- "leaflet": "https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js"
16
- }
17
- }
18
- </script>
19
- <script
20
- src="/src/index.js"
21
- type="module"
22
- defer
23
- ></script>
24
- <style>
25
- * {
26
- margin: 0;
27
- }
28
-
29
- l-map {
30
- block-size: 100vh;
31
- isolation: isolate;
32
- z-index: 1;
33
- }
34
-
35
- .btn-group {
36
- z-index: 2;
37
- position: absolute;
38
- bottom: 0;
39
- left: 0;
40
- margin: 1rem;
41
- }
42
-
43
- button {
44
- padding: 1rem;
45
- background-color: #337;
46
- color: white;
47
- border-radius: 0.25rem;
48
- cursor: pointer;
49
- font-size: 1.2rem;
50
- }
51
-
52
- body {
53
- display: grid;
54
- grid-template-columns: 1fr 1fr;
55
- }
56
- </style>
57
- </head>
58
- <body>
59
- <l-map center="[39.61, -105.02]" zoom="10">
60
- <l-control-layers>
61
- <l-base-layers>
62
- <l-tile-layer
63
- name="OpenStreetMap"
64
- url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
65
- attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
66
- max-zoom="12"
67
- ></l-tile-layer>
68
- <l-tile-layer
69
- name="CartoDB_Voyager"
70
- url-template="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
71
- attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
72
- max-zoom="20"
73
- subdomains="abcd"
74
- ></l-tile-layer>
75
- </l-base-layers>
76
- <l-overlay-layers>
77
- <l-layer-group name="Cities">
78
- <l-marker lat-lng="[39.61, -105.02]">
79
- <l-popup content="This is Littleton, CO."></l-popup>
80
- </l-marker>
81
- <l-marker lat-lng="[39.74, -104.99]">
82
- <l-popup content="This is Denver, CO."></l-popup>
83
- </l-marker>
84
- <l-marker lat-lng="[39.73, -104.8]" opacity="0.7">
85
- <l-popup content="This is Aurora, CO."></l-popup>
86
- </l-marker>
87
- <l-marker lat-lng="[39.77, -105.23]">
88
- <l-popup content="This is Golden, CO."></l-popup>
89
- </l-marker>
90
- </l-layer-group>
91
- </l-overlay-layers>
92
- </l-control-layers>
93
- </l-map>
94
- <div class="btn-group">
95
- <button id="btn-move">Move Denver</button>
96
- <button id="btn-remove">Remove Denver</button>
97
- </div>
98
- <script type="module">
99
- // Manual tests
100
- document.getElementById("btn-remove").addEventListener("click", () => {
101
- // Remove Denver
102
- let el = document.querySelector('[lat-lng="[39.74, -104.99]"]');
103
- el.remove();
104
- });
105
- document.getElementById("btn-move").addEventListener("click", () => {
106
- // Move Denver
107
- let el = document.querySelector('[lat-lng="[39.74, -104.99]"]');
108
- el.setAttribute("lat-lng", "[39.74, -104.89]");
109
- el.setAttribute("opacity", "0.5");
110
- });
111
- </script>
112
- </body>
113
- </html>
@@ -1,78 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head lang="en">
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Leaflet HTML imageOverlay</title>
7
- <link
8
- rel="stylesheet"
9
- href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
10
- integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
11
- crossorigin=""
12
- />
13
- <script type="importmap">
14
- {
15
- "imports": {
16
- "leaflet": "https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js"
17
- }
18
- }
19
- </script>
20
- <script type="module" src="/src/index.js"></script>
21
- <style>
22
- * {
23
- margin: 0;
24
- }
25
-
26
- l-map {
27
- display: block;
28
- block-size: 100vh;
29
- outline: 1px solid hotpink;
30
- isolation: isolate;
31
- z-index: 1;
32
- }
33
- </style>
34
- </head>
35
- <body>
36
- <l-map center="[37.8, -96]" zoom="4">
37
- <l-lat-lng-bounds
38
- bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
39
- ></l-lat-lng-bounds>
40
- <l-tile-layer
41
- name="OpenStreetMap"
42
- url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
43
- attribution=""
44
- ></l-tile-layer>
45
- <!-- Newark -->
46
- <l-image-overlay
47
- url="https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
48
- bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
49
- opacity="0.8"
50
- interactive="true"
51
- error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
52
- alt="Image of Newark, N.J. in 1922. Source: The University of Texas at Austin, UT Libraries Map Collection."
53
- ></l-image-overlay>
54
- <!-- Hurricane Patricia -->
55
- <l-video-overlay
56
- url='["https://www.mapbox.com/bites/00188/patricia_nasa.webm", "https://www.mapbox.com/bites/00188/patricia_nasa.mp4"]'
57
- error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
58
- bounds="[[32, -130], [13, -100]]"
59
- ></l-video-overlay>
60
- </l-map>
61
-
62
- <script>
63
- el = document.querySelector("l-lat-lng-bounds")
64
- let counter = 0
65
- document.body.addEventListener("click", () => {
66
- el.setAttribute("method", "flyToBounds")
67
- if (counter === 0) {
68
- const bounds = document.querySelector("l-video-overlay").getAttribute("bounds")
69
- el.setAttribute("bounds", bounds)
70
- } else {
71
- const bounds = document.querySelector("l-image-overlay").getAttribute("bounds")
72
- el.setAttribute("bounds", bounds)
73
- }
74
- counter += 1
75
- })
76
- </script>
77
- </body>
78
- </html>
package/src/events.js DELETED
@@ -1,3 +0,0 @@
1
- export const mapAddTo = "map:addTo";
2
- export const popupAdd = "popup:add";
3
- export const layerRemove = "layer:remove";
package/src/index.js DELETED
@@ -1,33 +0,0 @@
1
- // @ts-check
2
- import LBaseLayers from "./l-base-layers.js";
3
- import LControlLayers from "./l-control-layers.js";
4
- import LLayerGroup from "./l-layer-group.js";
5
- import LMap from "./l-map.js";
6
- import LMarker from "./l-marker.js";
7
- import LOverlayLayers from "./l-overlay-layers.js";
8
- import LPopup from "./l-popup.js";
9
- import LTileLayer from "./l-tile-layer.js";
10
- import LLatLngBounds from "./l-lat-lng-bounds.js";
11
- import LImageOverlay from "./l-image-overlay.js";
12
- import LVideoOverlay from "./l-video-overlay.js";
13
- import LGeoJSON from "./l-geojson.js";
14
- import LIcon from "./l-icon.js";
15
-
16
- const init = (() => {
17
- // Custom elements (order of definition is important)
18
- customElements.define("l-map", LMap);
19
- customElements.define("l-control-layers", LControlLayers);
20
- customElements.define("l-base-layers", LBaseLayers);
21
- customElements.define("l-overlay-layers", LOverlayLayers);
22
- customElements.define("l-layer-group", LLayerGroup);
23
- customElements.define("l-tile-layer", LTileLayer);
24
- customElements.define("l-marker", LMarker);
25
- customElements.define("l-popup", LPopup);
26
- customElements.define("l-lat-lng-bounds", LLatLngBounds);
27
- customElements.define("l-image-overlay", LImageOverlay);
28
- customElements.define("l-video-overlay", LVideoOverlay);
29
- customElements.define("l-geojson", LGeoJSON);
30
- customElements.define("l-icon", LIcon);
31
- })();
32
-
33
- export default init;
@@ -1,16 +0,0 @@
1
- // @ts-check
2
- import { mapAddTo } from "./events.js";
3
-
4
- class LBaseLayers extends HTMLElement {
5
- constructor() {
6
- super();
7
- }
8
-
9
- connectedCallback() {
10
- this.addEventListener(mapAddTo, (ev) => {
11
- ev.detail["type"] = "base";
12
- });
13
- }
14
- }
15
-
16
- export default LBaseLayers;
@@ -1,39 +0,0 @@
1
- // @ts-check
2
- /** @typedef {import("leaflet").Layer} Layer */
3
- import { control } from "leaflet";
4
- import { mapAddTo } from "./events.js";
5
-
6
- class LControlLayers extends HTMLElement {
7
- constructor() {
8
- super();
9
- }
10
-
11
- connectedCallback() {
12
- /** @type {{ [key: string]: Layer }} */
13
- const base = {};
14
- /** @type {{ [key: string]: Layer }} */
15
- const overlay = {};
16
- const controlLayers = control.layers(base, overlay);
17
-
18
- this.addEventListener(mapAddTo, (ev) => {
19
- const { type, name, layer } = ev.detail;
20
- if (type === "overlay") {
21
- controlLayers.addOverlay(layer, name);
22
- } else if (type === "base") {
23
- controlLayers.addBaseLayer(layer, name);
24
- }
25
- ev.preventDefault();
26
- });
27
-
28
- const event = new CustomEvent(mapAddTo, {
29
- cancelable: true,
30
- bubbles: true,
31
- detail: {
32
- layer: controlLayers,
33
- },
34
- });
35
- this.dispatchEvent(event);
36
- }
37
- }
38
-
39
- export default LControlLayers;
package/src/l-geojson.js DELETED
@@ -1,27 +0,0 @@
1
- // @ts-check
2
- import { geoJSON } from "leaflet";
3
- import { mapAddTo } from "./events.js";
4
-
5
- class LGeoJSON extends HTMLElement {
6
- constructor() {
7
- super();
8
- }
9
-
10
- connectedCallback() {
11
- const value = this.getAttribute("geojson");
12
- if (value !== null) {
13
- const layer = geoJSON(JSON.parse(value));
14
- this.dispatchEvent(
15
- new CustomEvent(mapAddTo, {
16
- bubbles: true,
17
- cancelable: true,
18
- detail: {
19
- layer,
20
- },
21
- }),
22
- );
23
- }
24
- }
25
- }
26
-
27
- export default LGeoJSON;
package/src/l-icon.js DELETED
@@ -1,124 +0,0 @@
1
- // @vitest-environment happy-dom
2
- import * as L from "leaflet";
3
-
4
- const camelCase = (kebab) => kebab.replace(/-./g, (x) => x[1].toUpperCase());
5
-
6
- class LIcon extends HTMLElement {
7
- constructor() {
8
- super();
9
- this.icon = null;
10
- }
11
-
12
- connectedCallback() {
13
- const options = {};
14
-
15
- // Strings
16
- let keys = [
17
- "icon-url",
18
- "icon-retina-url",
19
- "shadow-url",
20
- "shadow-retina-url",
21
- "class-name",
22
- ];
23
- keys.forEach((key) => {
24
- if (this.hasAttribute(key)) {
25
- options[camelCase(key)] = this.getAttribute(key);
26
- }
27
- });
28
-
29
- // Points
30
- let points = [
31
- "icon-anchor",
32
- "icon-size",
33
- "shadow-anchor",
34
- "shadow-size",
35
- "tooltip-anchor",
36
- "popup-anchor",
37
- ];
38
- points.forEach((key) => {
39
- if (this.hasAttribute(key)) {
40
- options[camelCase(key)] = JSON.parse(this.getAttribute(key));
41
- }
42
- });
43
-
44
- if (this.hasAttribute("cross-origin")) {
45
- options.crossOrigin = this.getAttribute("cross-origin") === "true";
46
- }
47
- this.icon = L.icon(options);
48
-
49
- const event = new CustomEvent("icon:add", {
50
- cancelable: true,
51
- bubbles: true,
52
- detail: {
53
- icon: this.icon,
54
- },
55
- });
56
- this.dispatchEvent(event);
57
- }
58
- }
59
-
60
- if (import.meta.vitest) {
61
- const { it, expect, beforeAll } = import.meta.vitest;
62
-
63
- beforeAll(() => {
64
- customElements.define("l-icon", LIcon);
65
- });
66
-
67
- it("default", () => {
68
- const el = document.createElement("l-icon");
69
- document.body.appendChild(el);
70
-
71
- let actual = el.icon;
72
- let expected = L.icon();
73
- expect(actual).toEqual(expected);
74
- });
75
-
76
- it("emits icon:add event", async () => {
77
- const el = document.createElement("l-icon");
78
- let promise = new Promise((resolve) => {
79
- el.addEventListener("icon:add", (ev) => {
80
- resolve(ev.detail.icon);
81
- });
82
- });
83
- document.body.appendChild(el);
84
- let actual = await promise;
85
- let expected = L.icon();
86
- expect(actual).toEqual(expected);
87
- });
88
-
89
- it("options", () => {
90
- const el = document.createElement("l-icon");
91
- el.setAttribute("icon-url", "url.png");
92
- el.setAttribute("icon-retina-url", "retina.png");
93
- el.setAttribute("icon-size", "[0, 0]");
94
- el.setAttribute("icon-anchor", "[0, 0]");
95
- el.setAttribute("popup-anchor", "[0, 0]");
96
- el.setAttribute("tooltip-anchor", "[0, 0]");
97
- el.setAttribute("shadow-url", "urlShadow.png");
98
- el.setAttribute("shadow-retina-url", "retinaShadow.png");
99
- el.setAttribute("shadow-size", "[0, 0]");
100
- el.setAttribute("shadow-anchor", "[0, 0]");
101
- el.setAttribute("class-name", "foo");
102
- el.setAttribute("cross-origin", "true");
103
- document.body.appendChild(el);
104
-
105
- let actual = el.icon;
106
- let expected = L.icon({
107
- iconUrl: "url.png",
108
- iconRetinaUrl: "retina.png",
109
- iconSize: [0, 0],
110
- iconAnchor: [0, 0],
111
- popupAnchor: [0, 0],
112
- tooltipAnchor: [0, 0],
113
- shadowUrl: "urlShadow.png",
114
- shadowRetinaUrl: "retinaShadow.png",
115
- shadowSize: [0, 0],
116
- shadowAnchor: [0, 0],
117
- className: "foo",
118
- crossOrigin: true,
119
- });
120
- expect(actual).toEqual(expected);
121
- });
122
- }
123
-
124
- export default LIcon;
@@ -1,54 +0,0 @@
1
- // @ts-check
2
- import { imageOverlay } from "leaflet";
3
- import { mapAddTo } from "./events.js";
4
- import LLayer from "./l-layer.js";
5
-
6
- class LImageOverlay extends LLayer {
7
- static observedAttributes = ["url", "bounds", "opacity"];
8
-
9
- constructor() {
10
- super();
11
- this.layer = null;
12
- }
13
-
14
- connectedCallback() {
15
- const url = this.getAttribute("url");
16
- if (url === null) {
17
- console.warn("attribute 'url' not set");
18
- return;
19
- }
20
- let bounds = this.getAttribute("bounds");
21
- if (bounds === null) {
22
- console.warn("attribute 'bounds' not set");
23
- return;
24
- }
25
- const options = {
26
- opacity: parseFloat(this.getAttribute("opacity") || "1.0"),
27
- alt: this.getAttribute("alt") || "",
28
- };
29
- this.layer = imageOverlay(url, JSON.parse(bounds), options);
30
- this.dispatchEvent(
31
- new CustomEvent(mapAddTo, {
32
- cancelable: true,
33
- bubbles: true,
34
- detail: {
35
- layer: this.layer,
36
- },
37
- }),
38
- );
39
- }
40
-
41
- attributeChangedCallback(name, _oldValue, newValue) {
42
- if (this.layer !== null) {
43
- if (name === "url") {
44
- this.layer.setUrl(newValue);
45
- } else if (name === "bounds") {
46
- this.layer.setBounds(JSON.parse(newValue));
47
- } else if (name === "opacity") {
48
- this.layer.setOpacity(parseFloat(newValue));
49
- }
50
- }
51
- }
52
- }
53
-
54
- export default LImageOverlay;
@@ -1,21 +0,0 @@
1
- // @ts-check
2
- class LLatLngBounds extends HTMLElement {
3
- static observedAttributes = ["bounds"];
4
-
5
- constructor() {
6
- super();
7
- }
8
-
9
- attributeChangedCallback(_name, _oldValue, newValue) {
10
- const event = new CustomEvent("map:bounds", {
11
- bubbles: true,
12
- detail: {
13
- bounds: JSON.parse(newValue),
14
- method: this.getAttribute("method") || "fitBounds",
15
- },
16
- });
17
- this.dispatchEvent(event);
18
- }
19
- }
20
-
21
- export default LLatLngBounds;
@@ -1,51 +0,0 @@
1
- // @ts-check
2
- import { layerGroup } from "leaflet";
3
- import { mapAddTo } from "./events.js";
4
- import LLayer from "./l-layer.js";
5
-
6
- class LLayerGroup extends LLayer {
7
- constructor() {
8
- super();
9
- this.layer = null;
10
- }
11
-
12
- connectedCallback() {
13
- const name = this.getAttribute("name");
14
- const group = layerGroup();
15
- this.layer = group;
16
-
17
- const event = new CustomEvent(mapAddTo, {
18
- cancelable: true,
19
- bubbles: true,
20
- detail: {
21
- layer: group,
22
- name,
23
- },
24
- });
25
- this.dispatchEvent(event);
26
-
27
- this.addEventListener(mapAddTo, (ev) => {
28
- ev.stopPropagation();
29
- group.addLayer(ev.detail.layer);
30
- });
31
-
32
- const observer = new MutationObserver(function (mutations) {
33
- mutations.forEach((mutation) => {
34
- mutation.removedNodes.forEach((node) => {
35
- if (node instanceof HTMLElement) {
36
- const leafletId = node.getAttribute("leaflet-id");
37
- if (leafletId !== null) {
38
- const layer = group.getLayer(parseInt(leafletId));
39
- if (typeof layer !== "undefined") {
40
- group.removeLayer(layer);
41
- }
42
- }
43
- }
44
- });
45
- });
46
- });
47
- observer.observe(this, { childList: true });
48
- }
49
- }
50
-
51
- export default LLayerGroup;
package/src/l-layer.js DELETED
@@ -1,8 +0,0 @@
1
- class LLayer extends HTMLElement {
2
- constructor() {
3
- super()
4
- this.layer = null
5
- }
6
- }
7
-
8
- export default LLayer
package/src/l-map.js DELETED
@@ -1,56 +0,0 @@
1
- // @ts-check
2
- import * as L from "leaflet";
3
- import { layerRemove, mapAddTo } from "./events.js";
4
- import LLayer from "./l-layer.js";
5
-
6
- class LMap extends HTMLElement {
7
- constructor() {
8
- super();
9
-
10
- this.map = null;
11
- this.addEventListener("map:bounds", (ev) => {
12
- const { bounds, method } = ev.detail;
13
- if (this.map !== null) {
14
- this.map[method](bounds);
15
- }
16
- });
17
-
18
- // Observe removed l-tile-layers
19
- const observer = new MutationObserver(function(mutations) {
20
- mutations.forEach((mutation) => {
21
- if (mutation.target instanceof LMap) {
22
- const el = mutation.target
23
- mutation.removedNodes.forEach((node) => {
24
- if (node instanceof LLayer) {
25
- if ((el.map !== null) && (node.layer !== null)) {
26
- el.map.removeLayer(node.layer)
27
- }
28
- }
29
- })
30
- }
31
- })
32
- })
33
- observer.observe(this, { childList: true })
34
- }
35
-
36
- connectedCallback() {
37
- this.map = L.map(this);
38
- const center = this.getAttribute("center");
39
- const zoom = this.getAttribute("zoom");
40
- if (center !== null && zoom !== null) {
41
- this.map.setView(JSON.parse(center), parseInt(zoom));
42
- }
43
- this.addEventListener(mapAddTo, (ev) => {
44
- const layer = ev.detail.layer;
45
- layer.addTo(this.map);
46
- });
47
-
48
- this.addEventListener(layerRemove, (ev) => {
49
- if (this.map !== null) {
50
- this.map.removeLayer(ev.detail.layer);
51
- }
52
- });
53
- }
54
- }
55
-
56
- export default LMap;