leaflet-html 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
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>GeoJSON</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
14
+ src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
15
+ integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
16
+ crossorigin=""
17
+ ></script>
18
+ <script type="module" src="/src/index.js"></script>
19
+ <style>
20
+ * {
21
+ margin: 0;
22
+ }
23
+ l-map {
24
+ display: block;
25
+ height: 100vh;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <l-map center="[55,0]" zoom="5">
31
+ <l-tile-layer
32
+ url-template="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
33
+ ></l-tile-layer>
34
+ <l-geojson id="feature" geojson='{"type":"Feature","properties":{"name":"Coors Field","amenity":"Baseball Stadium","popupContent":"This is where the Rockies play!"},"geometry":{"type":"Point","coordinates":[-104.99404,39.75621]}}'></l-geojson>
35
+ </l-map>
36
+ <script>
37
+ document.getElementById("feature").addEventListener("map:addTo", (ev) => {
38
+ console.log({ message: "Hello, World!", ev })
39
+ })
40
+ </script>
41
+ </body>
42
+ </html>
@@ -15,7 +15,8 @@
15
15
  crossorigin=""
16
16
  ></script>
17
17
  <script
18
- src="/dist/leaflet-html.umd.js"
18
+ src="/src/index.js"
19
+ type="module"
19
20
  defer
20
21
  ></script>
21
22
  <style>
@@ -23,18 +24,21 @@
23
24
  margin: 0;
24
25
  }
25
26
 
26
- [data-leaflet-html] {
27
+ l-map {
27
28
  block-size: 100vh;
28
29
  isolation: isolate;
29
30
  z-index: 1;
30
31
  }
31
32
 
32
- #btn {
33
+ .btn-group {
33
34
  z-index: 2;
34
35
  position: absolute;
35
36
  bottom: 0;
36
37
  left: 0;
37
38
  margin: 1rem;
39
+ }
40
+
41
+ button {
38
42
  padding: 1rem;
39
43
  background-color: #337;
40
44
  color: white;
@@ -42,62 +46,66 @@
42
46
  cursor: pointer;
43
47
  font-size: 1.2rem;
44
48
  }
49
+
50
+ body {
51
+ display: grid;
52
+ grid-template-columns: 1fr 1fr;
53
+ }
45
54
  </style>
46
55
  </head>
47
56
  <body>
48
- <div data-leaflet-html data-center="[39.61, -105.02]" data-zoom="10">
49
- <div data-control-layers>
50
- <div data-base-maps>
51
- <div
52
- data-tile-layer
53
- data-name="OpenStreetMap"
54
- data-url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
55
- data-attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
56
- data-max-zoom="12"
57
- ></div>
58
- <div
59
- data-tile-layer
60
- data-name="CartoDB_Voyager"
61
- data-url-template="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
62
- data-attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
63
- data-max-zoom="20"
64
- data-subdomains="abcd"
65
- data-show
66
- ></div>
67
- </div>
68
- <div data-overlay-maps>
69
- <div data-layer-group data-name="Cities">
70
- <div data-marker data-lat-lng="[39.61, -105.02]">
71
- <div data-popup data-content="This is Littleton, CO."></div>
72
- </div>
73
- <div data-marker data-lat-lng="[39.74, -104.99]">
74
- <div data-popup data-content="This is Denver, CO."></div>
75
- </div>
76
- <div data-marker data-lat-lng="[39.73, -104.8]" data-opacity="0.7">
77
- <div data-popup data-content="This is Aurora, CO."></div>
78
- </div>
79
- <div data-marker data-lat-lng="[39.77, -105.23]">
80
- <div data-popup data-content="This is Golden, CO."></div>
81
- </div>
82
- </div>
83
- </div>
84
- </div>
57
+ <l-map center="[39.61, -105.02]" zoom="10">
58
+ <l-control-layers>
59
+ <l-base-layers>
60
+ <l-tile-layer
61
+ name="OpenStreetMap"
62
+ url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
63
+ attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
64
+ max-zoom="12"
65
+ ></l-tile-layer>
66
+ <l-tile-layer
67
+ name="CartoDB_Voyager"
68
+ url-template="https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
69
+ attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
70
+ max-zoom="20"
71
+ subdomains="abcd"
72
+ ></l-tile-layer>
73
+ </l-base-layers>
74
+ <l-overlay-layers>
75
+ <l-layer-group name="Cities">
76
+ <l-marker lat-lng="[39.61, -105.02]">
77
+ <l-popup content="This is Littleton, CO."></l-popup>
78
+ </l-marker>
79
+ <l-marker lat-lng="[39.74, -104.99]">
80
+ <l-popup content="This is Denver, CO."></l-popup>
81
+ </l-marker>
82
+ <l-marker lat-lng="[39.73, -104.8]" opacity="0.7">
83
+ <l-popup content="This is Aurora, CO."></l-popup>
84
+ </l-marker>
85
+ <l-marker lat-lng="[39.77, -105.23]">
86
+ <l-popup content="This is Golden, CO."></l-popup>
87
+ </l-marker>
88
+ </l-layer-group>
89
+ </l-overlay-layers>
90
+ </l-control-layers>
91
+ </l-map>
92
+ <div class="btn-group">
93
+ <button id="btn-move">Move Denver</button>
94
+ <button id="btn-remove">Remove Denver</button>
85
95
  </div>
86
- <button id="btn">Add a city</button>
87
96
  <script type="module">
88
97
  // Manual tests
89
- document.getElementById("btn").addEventListener("click", () => {
90
- // New city
91
- let el = document.querySelector('[data-name="Cities"]');
92
- const city = document.createElement("div");
93
- city.dataset.marker = "";
94
- city.dataset.latLng = "[39.60, -105.02]";
95
- el.appendChild(city);
96
-
98
+ document.getElementById("btn-remove").addEventListener("click", () => {
97
99
  // Remove Denver
98
- el = document.querySelector('[data-lat-lng="[39.74, -104.99]"]');
100
+ let el = document.querySelector('[lat-lng="[39.74, -104.99]"]');
99
101
  el.remove();
100
102
  });
103
+ document.getElementById("btn-move").addEventListener("click", () => {
104
+ // Move Denver
105
+ let el = document.querySelector('[lat-lng="[39.74, -104.99]"]');
106
+ el.setAttribute("lat-lng", "[39.74, -104.89]");
107
+ el.setAttribute("opacity", "0.5");
108
+ });
101
109
  </script>
102
110
  </body>
103
111
  </html>
@@ -15,60 +15,59 @@
15
15
  integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
16
16
  crossorigin=""
17
17
  ></script>
18
- <script src="/dist/leaflet-html.umd.js"></script>
18
+ <script type="module" src="/src/index.js"></script>
19
19
  <style>
20
20
  * {
21
21
  margin: 0;
22
22
  }
23
23
 
24
- [data-leaflet-html] {
24
+ l-map {
25
+ display: block;
25
26
  block-size: 100vh;
27
+ outline: 1px solid hotpink;
26
28
  isolation: isolate;
27
29
  z-index: 1;
28
30
  }
29
31
  </style>
30
32
  </head>
31
33
  <body>
32
- <div data-leaflet-html data-center="[37.8, -96]" data-zoom="4">
33
- <div
34
- data-lat-lng-bounds
35
- data-bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
36
- ></div>
37
- <div
38
- data-tile-layer
39
- data-name="OpenStreetMap"
40
- data-url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
41
- data-attribution=""
42
- ></div>
34
+ <l-map center="[37.8, -96]" zoom="4">
35
+ <l-lat-lng-bounds
36
+ bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
37
+ ></l-lat-lng-bounds>
38
+ <l-tile-layer
39
+ name="OpenStreetMap"
40
+ url-template="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
41
+ attribution=""
42
+ ></l-tile-layer>
43
43
  <!-- Newark -->
44
- <div
45
- data-image-overlay
46
- data-url="https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
47
- data-bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
48
- data-opacity="0.8"
49
- data-interactive="true"
50
- data-error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
51
- data-alt="Image of Newark, N.J. in 1922. Source: The University of Texas at Austin, UT Libraries Map Collection."
52
- ></div>
44
+ <l-image-overlay
45
+ url="https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
46
+ bounds="[[40.799311, -74.118464], [40.68202047785919, -74.33]]"
47
+ opacity="0.8"
48
+ interactive="true"
49
+ error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
50
+ alt="Image of Newark, N.J. in 1922. Source: The University of Texas at Austin, UT Libraries Map Collection."
51
+ ></l-image-overlay>
53
52
  <!-- Hurricane Patricia -->
54
- <div
55
- data-video-overlay
56
- data-url='["https://www.mapbox.com/bites/00188/patricia_nasa.webm", "https://www.mapbox.com/bites/00188/patricia_nasa.mp4"]'
57
- data-error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
58
- data-bounds="[[32, -130], [13, -100]]"
59
- ></div>
60
- </div>
53
+ <l-video-overlay
54
+ url='["https://www.mapbox.com/bites/00188/patricia_nasa.webm", "https://www.mapbox.com/bites/00188/patricia_nasa.mp4"]'
55
+ error-overlay-url="https://cdn-icons-png.flaticon.com/512/110/110686.png"
56
+ bounds="[[32, -130], [13, -100]]"
57
+ ></l-video-overlay>
58
+ </l-map>
59
+
61
60
  <script>
62
- el = document.querySelector("[data-lat-lng-bounds]")
61
+ el = document.querySelector("l-lat-lng-bounds")
63
62
  let counter = 0
64
63
  document.body.addEventListener("click", () => {
65
- console.log("click")
64
+ el.setAttribute("method", "flyToBounds")
66
65
  if (counter === 0) {
67
- const { bounds } = document.querySelector("[data-video-overlay]").dataset
68
- el.dataset.bounds = bounds
66
+ const bounds = document.querySelector("l-video-overlay").getAttribute("bounds")
67
+ el.setAttribute("bounds", bounds)
69
68
  } else {
70
- const { bounds } = document.querySelector("[data-image-overlay]").dataset
71
- el.dataset.bounds = bounds
69
+ const bounds = document.querySelector("l-image-overlay").getAttribute("bounds")
70
+ el.setAttribute("bounds", bounds)
72
71
  }
73
72
  counter += 1
74
73
  })
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "leaflet-html",
3
3
  "type": "module",
4
- "version": "0.1.6",
4
+ "version": "0.2.0",
5
5
  "description": "Leaflet expressed in HTML",
6
6
  "source": "src/index.js",
7
7
  "main": "./dist/leaflet-html.js",
8
8
  "umd:main": "./dist/leaflet-html.umd.js",
9
9
  "exports": {
10
- "default": "./dist/leaflet-html.js"
10
+ "module": "./dist/leaflet-html.js"
11
11
  },
12
12
  "module": "./dist/leaflet-html.esm.js",
13
13
  "author": "andrewgryan",
package/src/events.js ADDED
@@ -0,0 +1,3 @@
1
+ export const mapAddTo = "map:addTo"
2
+ export const popupAdd = "popup:add"
3
+ export const layerRemove = "layer:remove"
package/src/index.js CHANGED
@@ -1,191 +1,32 @@
1
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";
2
14
 
3
- // Helpers
4
- const selector = (noun) => `[data-${noun}]`;
5
-
6
- /**
7
- * Parse L.tileLayer args from element attributes
8
- */
9
- const parseTileLayer = (el) => {
10
- const { urlTemplate } = el.dataset;
11
- const {
12
- attribution = null,
13
- maxZoom = "18",
14
- minZoom = "0",
15
- subdomains = "abc",
16
- } = el.dataset;
17
- const options = { attribution, maxZoom, minZoom, subdomains };
18
- return [urlTemplate, options];
19
- };
20
-
21
- /**
22
- * Parse L.imageOverlay args from element attributes
23
- */
24
- const parseImageOverlay = (el) => {
25
- let { url, bounds } = el.dataset;
26
- bounds = JSON.parse(bounds);
27
- const { opacity } = el.dataset;
28
- const options = { opacity: parseFloat(opacity) };
29
- return [url, bounds, options];
30
- };
31
-
32
- /**
33
- * Parse L.imageOverlay args from element attributes
34
- */
35
- const parseVideoOverlay = (el) => {
36
- let { url, bounds } = el.dataset;
37
- url = JSON.parse(url);
38
- bounds = JSON.parse(bounds);
39
- const {
40
- opacity,
41
- errorOverlayUrl,
42
- autoplay = true,
43
- muted = true,
44
- playsInline = true,
45
- } = el.dataset;
46
- const options = {
47
- opacity: parseFloat(opacity),
48
- errorOverlayUrl,
49
- autoplay,
50
- muted,
51
- playsInline,
52
- };
53
- return [url, bounds, options];
54
- };
55
-
56
- /**
57
- * @param {HTMLElement} el
58
- */
59
- const parseLatLngBounds = (el) => {
60
- let { bounds } = el.dataset;
61
- if (typeof bounds === "undefined") {
62
- throw Error("data-bounds not specified")
63
- }
64
- return [JSON.parse(bounds)];
65
- }
66
-
67
- const render = () => {
68
- // Render Leaflet API calls
69
- document.querySelectorAll(selector("leaflet-html")).forEach((el) => {
70
- const { center, zoom } = el.dataset;
71
- const map = L.map(el).setView(JSON.parse(center), parseInt(zoom));
72
-
73
- // L.latLngBounds
74
- el.querySelectorAll(selector("lat-lng-bounds")).forEach((el) => {
75
- const bounds = L.latLngBounds(...parseLatLngBounds(el))
76
- // TODO: encapsulate this design pattern
77
- const observer = new MutationObserver(function (mutations) {
78
- mutations.forEach((mutation) => {
79
- let [bounds] = parseLatLngBounds(mutation.target)
80
- map.flyToBounds(bounds); // TODO: Use HTML attrs for fly/fit bounds
81
- });
82
- });
83
- observer.observe(el, {
84
- attributes: true,
85
- attributeFilter: ["data-bounds"],
86
- });
87
- map.fitBounds(bounds)
88
- })
89
-
90
- // L.tileLayers
91
- el.querySelectorAll(selector("tile-layer")).forEach((el) => {
92
- L.tileLayer(...parseTileLayer(el)).addTo(map);
93
- });
94
-
95
- el.querySelectorAll(selector("image-overlay")).forEach((el) => {
96
- L.imageOverlay(...parseImageOverlay(el)).addTo(map);
97
- });
98
-
99
- el.querySelectorAll(selector("video-overlay")).forEach((el) => {
100
- L.videoOverlay(...parseVideoOverlay(el)).addTo(map);
101
- });
102
-
103
- // L.control.layers
104
- el.querySelectorAll(selector("control-layers")).forEach((el) => {
105
- const baseMaps = {};
106
-
107
- // L.tileLayers
108
- el.querySelectorAll(selector("tile-layer")).forEach((el) => {
109
- const { name, show } = el.dataset;
110
- baseMaps[name] = L.tileLayer(...parseTileLayer(el));
111
- if (show != null) {
112
- baseMaps[name].addTo(map);
113
- }
114
- });
115
-
116
- const overlayMaps = {};
117
- // L.layerGroup
118
- el.querySelectorAll(selector("layer-group")).forEach((el) => {
119
- const { name } = el.dataset;
120
- const layers = [];
121
-
122
- const observer = new MutationObserver(function (mutations) {
123
- const group = overlayMaps[name];
124
-
125
- mutations.forEach((mutation) => {
126
- mutation.addedNodes.forEach((node) => {
127
- const { latLng } = node.dataset; // MutationObserver needed
128
- const layer = L.marker(JSON.parse(latLng));
129
- group.addLayer(layer);
130
- map.addLayer(layer);
131
- });
132
-
133
- mutation.removedNodes.forEach((node) => {
134
- const { _leafletId } = node.dataset;
135
- const layer = group.getLayer(_leafletId);
136
- group.removeLayer(layer);
137
-
138
- map.removeLayer(layer);
139
- });
140
- });
141
- });
142
- observer.observe(el, { childList: true });
143
-
144
- // L.marker
145
- el.querySelectorAll(selector("marker")).forEach((el) => {
146
- const { latLng } = el.dataset;
147
- const { opacity = "1.0" } = el.dataset;
148
- const options = { opacity: parseFloat(opacity) };
149
- const marker = L.marker(JSON.parse(latLng), options).addTo(map);
150
- el.dataset._leafletId = L.stamp(marker); // Save ID for later
151
-
152
- const observer = new MutationObserver(function (mutations) {
153
- mutations.forEach((mutation) => {
154
- const { latLng } = mutation.target.dataset;
155
- marker.setLatLng(JSON.parse(latLng));
156
- });
157
- });
158
- observer.observe(el, {
159
- attributes: true,
160
- attributeFilter: ["data-lat-lng"],
161
- });
162
-
163
- // marker.bindPopup
164
- el.querySelectorAll(selector("popup")).forEach((el) => {
165
- const { content } = el.dataset;
166
- marker.bindPopup(content);
167
- const observer = new MutationObserver(function () {
168
- marker.getPopup().setContent(el.dataset.content);
169
- });
170
- observer.observe(el, {
171
- attributes: true,
172
- attributeFilter: ["data-content"],
173
- });
174
- });
175
-
176
- layers.push(marker);
177
- });
178
-
179
- overlayMaps[name] = L.layerGroup(layers);
180
- });
181
-
182
- L.control.layers(baseMaps, overlayMaps).addTo(map);
183
- });
184
- });
185
- };
186
15
 
187
16
  const init = (() => {
188
- document.addEventListener("DOMContentLoaded", render);
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)
189
30
  })();
190
31
 
191
32
  export default init;
@@ -0,0 +1,16 @@
1
+ import { mapAddTo } from "./events.js"
2
+
3
+ class LBaseLayers extends HTMLElement {
4
+ constructor() {
5
+ super()
6
+ }
7
+
8
+ connectedCallback() {
9
+ this.addEventListener(mapAddTo, (ev) => {
10
+ ev.detail["type"] = "base"
11
+ })
12
+ }
13
+ }
14
+
15
+ export default LBaseLayers
16
+
@@ -0,0 +1,34 @@
1
+ import { mapAddTo } from "./events.js"
2
+
3
+ class LControlLayers extends HTMLElement {
4
+ constructor() {
5
+ super()
6
+ }
7
+
8
+ connectedCallback() {
9
+ const base = {}
10
+ const overlay = {}
11
+ const control = L.control.layers(base, overlay)
12
+
13
+ this.addEventListener(mapAddTo, (ev) => {
14
+ const { type, name, layer } = ev.detail
15
+ if (type === "overlay") {
16
+ control.addOverlay(layer, name)
17
+ } else if (type === "base") {
18
+ control.addBaseLayer(layer, name)
19
+ }
20
+ ev.preventDefault()
21
+ })
22
+
23
+ const event = new CustomEvent(mapAddTo, {
24
+ cancelable: true,
25
+ bubbles: true,
26
+ detail: {
27
+ layer: control
28
+ }
29
+ })
30
+ this.dispatchEvent(event)
31
+ }
32
+ }
33
+
34
+ export default LControlLayers
@@ -0,0 +1,20 @@
1
+ import { mapAddTo } from "./events.js"
2
+
3
+ class LGeoJSON extends HTMLElement {
4
+ constructor() {
5
+ super()
6
+ }
7
+
8
+ connectedCallback() {
9
+ const layer = L.geoJSON(JSON.parse(this.getAttribute("geojson")))
10
+ this.dispatchEvent(new CustomEvent(mapAddTo, {
11
+ bubbles: true,
12
+ cancelable: true,
13
+ detail: {
14
+ layer
15
+ }
16
+ }))
17
+ }
18
+ }
19
+
20
+ export default LGeoJSON
@@ -0,0 +1,41 @@
1
+ import { mapAddTo } from "./events.js"
2
+
3
+ class LImageOverlay extends HTMLElement {
4
+ static observedAttributes = ["url", "bounds", "opacity"]
5
+
6
+ constructor() {
7
+ super()
8
+ this.layer = null
9
+ }
10
+
11
+ connectedCallback() {
12
+ const url = this.getAttribute("url")
13
+ const bounds = JSON.parse(this.getAttribute("bounds"))
14
+ const options = {
15
+ opacity: parseFloat(this.getAttribute("opacity") || "1.0"),
16
+ alt: this.getAttribute("alt") || ""
17
+ }
18
+ this.layer = L.imageOverlay(url, bounds, options)
19
+ this.dispatchEvent(new CustomEvent(mapAddTo, {
20
+ cancelable: true,
21
+ bubbles: true,
22
+ detail: {
23
+ layer: this.layer
24
+ }
25
+ }))
26
+ }
27
+
28
+ attributeChangedCallback(name, _oldValue, newValue) {
29
+ if (this.layer !== null) {
30
+ if (name === "url") {
31
+ this.layer.setUrl(newValue)
32
+ } else if (name === "bounds") {
33
+ this.layer.setBounds(JSON.parse(newValue))
34
+ } else if (name === "opacity") {
35
+ this.layer.setOpacity(parseFloat(newValue))
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ export default LImageOverlay
@@ -0,0 +1,20 @@
1
+ class LLatLngBounds extends HTMLElement {
2
+ static observedAttributes = ["bounds"]
3
+
4
+ constructor() {
5
+ super()
6
+ }
7
+
8
+ attributeChangedCallback(_name, _oldValue, newValue) {
9
+ const event = new CustomEvent("map:bounds", {
10
+ bubbles: true,
11
+ detail: {
12
+ bounds: JSON.parse(newValue),
13
+ method: this.getAttribute("method") || "fitBounds"
14
+ }
15
+ })
16
+ this.dispatchEvent(event)
17
+ }
18
+ }
19
+
20
+ export default LLatLngBounds