Showing preview only (1,111K chars total). Download the full file or copy to clipboard to get everything.
Repository: reggie3/react-native-webview-leaflet
Branch: master
Commit: a27bc89559bc
Files: 58
Total size: 1.0 MB
Directory structure:
gitextract_wblmb6r9/
├── .gitignore
├── .npmignore
├── .vscode/
│ └── settings.json
├── HTML/
│ ├── .gitignore
│ ├── gulpfile.js
│ ├── package.json
│ ├── public/
│ │ ├── index.html
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── readme.md
│ ├── src/
│ │ ├── MapComponent.test.tsx
│ │ ├── MapComponent.view.test.tsx
│ │ ├── MapLayers.test.tsx
│ │ ├── MapLayers.tsx
│ │ ├── MapMarkers.tsx
│ │ ├── MapShapes.tsx
│ │ ├── __snapshots__/
│ │ │ ├── MapComponent.test.tsx.snap
│ │ │ ├── MapComponent.view.test.tsx.snap
│ │ │ └── MapLayers.test.tsx.snap
│ │ ├── index.css
│ │ ├── index.tsx
│ │ ├── mapComponent.tsx
│ │ ├── mapComponent.view.tsx
│ │ ├── models.ts
│ │ ├── react-app-env.d.ts
│ │ ├── serviceWorker.ts
│ │ ├── setupTests.ts
│ │ ├── styles/
│ │ │ ├── markerAnimations.css
│ │ │ └── markers.css
│ │ ├── testData/
│ │ │ ├── mockMapLayers.ts
│ │ │ ├── mockMapMarkers.ts
│ │ │ ├── mockMapShapes.ts
│ │ │ └── svgIcons.ts
│ │ ├── utilities.test.ts.old
│ │ ├── utilities.ts
│ │ └── webBase64Image.ts
│ └── tsconfig.json
├── WebViewLeaflet/
│ ├── ActivityOverlay.tsx
│ ├── DebugMessageBox.tsx
│ ├── WebViewLeaflet.tsx
│ ├── WebViewLeaflet.view.tsx
│ ├── assets/
│ │ └── index.html
│ ├── index.d.ts
│ ├── index.ts
│ ├── models.ts
│ ├── package.json
│ └── yarn-error.log
├── demoApp/
│ ├── .expo-shared/
│ │ └── assets.json
│ ├── .gitignore
│ ├── App.tsx
│ ├── app.json
│ ├── babel.config.js
│ ├── gulpfile.js
│ ├── package.json
│ ├── tsconfig.json
│ └── yarn-error.log
├── package.json
└── readme.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
web-report/
HTML/dist/*
HTML/cache/*
HTML/build/*
HTML/.cache/*
HTML/node_modules
WebViewLeaflet/dist/*
WebViewLeaflet/cache/*
WebViewLeaflet/build/*
WebViewLeaflet/.cache/*
WebViewLeaflet/node_modules
secrets.js
secrets.ts
/HTML/precompile
/HTML/readyForBuild
/HTML/.cache
node_modules
================================================
FILE: .npmignore
================================================
..\..\..\..\c:\Users\regin\Dropbox\react-native-webview-leaflet-5\html\build\index.html
..\..\..\..\c:\Users\regin\Dropbox\react-native-webview-leaflet-5\html\src\testData
================================================
FILE: .vscode/settings.json
================================================
{
"git.ignoreLimitWarning": true
}
================================================
FILE: HTML/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: HTML/gulpfile.js
================================================
const gulp = require("gulp");
const inlinesource = require("gulp-inline-source");
const replace = require("gulp-replace");
const clean = require("gulp-clean");
const rename = require("gulp-rename");
const REACT_BUILD_DIRECTORY = "build";
const REACT_BUILD_FILES = "./build/*.html";
const FILE_NAME_AFTER_ADDING_INLINE_TAGS = "indexWithTags.html";
const DIST_HTML_FILE_NAME = "index.html";
const DIST_DIRECTORY = "dist";
gulp.task("clean", function() {
return gulp
.src(
[
`${REACT_BUILD_DIRECTORY}/${FILE_NAME_AFTER_ADDING_INLINE_TAGS}`,
DIST_DIRECTORY
],
{
allowEmpty: true,
read: false
}
)
.pipe(clean());
});
gulp.task("disableBrowserTestFlag", () => {
return gulp
.src(["./src/MapComponent.tsx"])
.pipe(
replace(
"const ENABLE_BROWSER_TESTING = true;",
"const ENABLE_BROWSER_TESTING = false;"
)
)
.pipe(gulp.dest("./src"));
});
gulp.task("enableBrowserTestFlag", () => {
return gulp
.src(["./src/MapComponent.tsx"])
.pipe(
replace(
"const ENABLE_BROWSER_TESTING = false;",
"const ENABLE_BROWSER_TESTING = true;"
)
)
.pipe(gulp.dest("./src"));
});
gulp.task("addInlineTags", function() {
return gulp
.src(REACT_BUILD_FILES)
.pipe(replace('rel="stylesheet"', 'rel="stylesheet" inline'))
.pipe(replace("></script>", " inline></script>"))
.pipe(rename(FILE_NAME_AFTER_ADDING_INLINE_TAGS))
.pipe(gulp.dest(REACT_BUILD_DIRECTORY));
});
gulp.task("inlineSource", function() {
return gulp
.src(`./${REACT_BUILD_DIRECTORY}/${FILE_NAME_AFTER_ADDING_INLINE_TAGS}`)
.pipe(inlinesource())
.pipe(rename(DIST_HTML_FILE_NAME))
.pipe(gulp.dest(DIST_DIRECTORY));
});
exports.build = gulp.series("clean", "addInlineTags", "inlineSource");
================================================
FILE: HTML/package.json
================================================
{
"name": "html",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-leaflet": "^2.5.0",
"@types/react-leaflet-markercluster": "^2.0.0",
"@types/react-measure": "^2.0.5",
"leaflet": "^1.6.0",
"leaflet.markercluster": "^1.4.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-leaflet": "^2.6.1",
"react-leaflet-markercluster": "^2.0.0-rc3",
"react-measure": "^2.3.0",
"react-scripts": "3.3.0",
"typescript": "~3.7.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"cleanAssets": "del-cli --force ../WebViewLeaflet/assets/**/*",
"copyDist": "npx copyfiles -u 1 ./dist/index.html ../WebViewLeaflet/assets",
"dist": "gulp disableBrowserTestFlag && yarn build && gulp build && yarn cleanAssets && yarn copyDist && gulp enableBrowserTestFlag",
"cpx": "cpx '../WebViewLeaflet/models.ts' ./src --watch"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"del-cli": "^3.0.0",
"gulp": "^4.0.2",
"gulp-clean": "^0.4.0",
"gulp-inline-source": "^4.0.0",
"gulp-rename": "^2.0.0",
"gulp-replace": "^1.0.0"
}
}
================================================
FILE: HTML/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body style="display:flex; height: 100vh; margin: 0">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root" style="flex:1; background-color:cornflowerblue ;"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
================================================
FILE: HTML/public/manifest.json
================================================
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
================================================
FILE: HTML/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
================================================
FILE: HTML/readme.md
================================================
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `yarn start`
Runs the app in the development mode.<br />
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br />
You will also see any lint errors in the console.
### `yarn test`
Launches the test runner in the interactive watch mode.<br />
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `yarn build`
Builds the app for production to the `build` folder.<br />
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br />
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `yarn eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
================================================
FILE: HTML/src/MapComponent.test.tsx
================================================
import React from "react";
import { render } from "@testing-library/react";
import MapComponent from "./MapComponent";
describe("MapComponent", () => {
test("it renders", () => {
const { asFragment } = render(<MapComponent />);
expect(asFragment()).toMatchSnapshot();
});
});
================================================
FILE: HTML/src/MapComponent.view.test.tsx
================================================
import React from "react";
import { render } from "@testing-library/react";
import MapComponentView from "./MapComponent.view";
describe("MapComponentView", () => {
test("it renders", () => {
const { asFragment } = render(
<MapComponentView
addDebugMessage={() => {}}
debugMessages={[]}
mapCenterPosition={[36.56, -76.17]}
mapLayers={[]}
mapMarkers={[]}
onMapEvent={() => {}}
setMapRef={() => {}}
zoom={13}
/>
);
expect(asFragment()).toMatchSnapshot();
});
});
================================================
FILE: HTML/src/MapLayers.test.tsx
================================================
import * as React from "react";
import { default as MapLayerComponent } from "./MapLayers";
import { render } from "@testing-library/react";
import mockMapLayers from "./testData/mockMapLayers";
import { Map } from "react-leaflet";
describe("MapLayers Component", () => {
test("it renders", () => {
console.log(MapLayerComponent);
const { asFragment } = render(
<Map center={[0, 0]} zoom={13} style={{ width: 100, height: 100 }}>
<MapLayerComponent mapLayers={mockMapLayers} />
</Map>
);
expect(asFragment()).toMatchSnapshot();
});
});
================================================
FILE: HTML/src/MapLayers.tsx
================================================
import * as React from "react";
import {
TileLayer,
LayersControl,
WMSTileLayer,
WMSTileLayerProps,
TileLayerProps,
ImageOverlay,
ImageOverlayProps
} from "react-leaflet";
import { MapLayer, MapLayerType } from "./models";
const { BaseLayer } = LayersControl;
interface MapLayersProps {
mapLayers: MapLayer[];
}
class MapLayers extends React.Component<MapLayersProps> {
private Layer = (props: MapLayer): JSX.Element => {
switch (props.layerType) {
case MapLayerType.IMAGE_LAYER:
return <ImageOverlay {...(props as ImageOverlayProps)} />;
case MapLayerType.WMS_TILE_LAYER:
return <WMSTileLayer {...(props as WMSTileLayerProps)} />;
default:
return <TileLayer {...(props as TileLayerProps)} />;
}
};
private Layers = (): JSX.Element[] => {
const { mapLayers } = this.props;
return mapLayers.map(
(layer: MapLayer, index: number): JSX.Element => {
if (layer.baseLayerName && mapLayers.length > 1) {
return (
<BaseLayer
key={`layer-${index}`}
checked={layer.baseLayerIsChecked ?? false}
name={layer.baseLayerName || `Layer.${index}`}
>
<this.Layer {...layer} />
</BaseLayer>
);
}
return <this.Layer key={`layer-${index}`} {...layer} />;
}
);
};
render() {
const { mapLayers } = this.props;
if (mapLayers.length > 1) {
return <LayersControl>{this.Layers()}</LayersControl>;
} else {
return <>{this.Layers()}</>;
}
}
}
export default MapLayers;
================================================
FILE: HTML/src/MapMarkers.tsx
================================================
import * as React from "react";
import { LayerGroup, Marker, Popup } from "react-leaflet";
import MarkerClusterGroup from "react-leaflet-markercluster";
import { createDivIcon } from "./utilities";
import {
WebViewLeafletEvents,
MapMarker,
OWN_POSTION_MARKER_ID
} from "./models";
import { LatLngExpression } from "leaflet";
require("react-leaflet-markercluster/dist/styles.min.css");
interface MapMarkersProps {
mapMarkers: MapMarker[];
onMapEvent: (mapEvent: WebViewLeafletEvents, payload: any) => void;
useMarkerClustering?: boolean;
}
export default class MapMarkers extends React.Component<MapMarkersProps> {
private MapMarker = ({ mapMarker }: { mapMarker: MapMarker }) => {
return (
<Marker
key={mapMarker.id || Math.random().toString()}
position={mapMarker.position as LatLngExpression}
icon={createDivIcon(mapMarker)}
onClick={() => {
this.props.onMapEvent(WebViewLeafletEvents.ON_MAP_MARKER_CLICKED, {
mapMarkerID: mapMarker.id
});
}}
>
{mapMarker.title && <Popup>{mapMarker.title}</Popup>}
</Marker>
);
};
render() {
const { mapMarkers, useMarkerClustering = true } = this.props;
if (useMarkerClustering) {
return (
<LayerGroup>
<MarkerClusterGroup>
{mapMarkers.map((mapMarker: MapMarker) => {
if (mapMarker.id !== OWN_POSTION_MARKER_ID) {
return (
<this.MapMarker
key={mapMarker.id || Math.random().toString()}
mapMarker={mapMarker}
/>
);
} else {
return null;
}
})}
</MarkerClusterGroup>
{mapMarkers.map((mapMarker: MapMarker) => {
if (mapMarker.id === OWN_POSTION_MARKER_ID) {
return <this.MapMarker mapMarker={mapMarker} />;
} else {
return null;
}
})}
</LayerGroup>
);
} else {
return (
<LayerGroup>
{mapMarkers.map((mapMarker: MapMarker) => {
return <this.MapMarker mapMarker={mapMarker} />;
})}
</LayerGroup>
);
}
}
}
================================================
FILE: HTML/src/MapShapes.tsx
================================================
import * as React from "react";
import {
Circle,
Polygon,
CircleMarker,
Polyline,
Rectangle,
CircleMarkerProps,
PolylineProps,
PolygonProps,
RectangleProps,
CircleProps
} from "react-leaflet";
import { MapShapeType, MapShape, WebViewLeafletEvents } from "./models";
export interface MapMapShapesProps {
mapShapes: MapShape[];
onMapEvent: (mapEvent: WebViewLeafletEvents, payload: any) => void;
}
class MapShapes extends React.Component<MapMapShapesProps> {
private Shape = (props: any) => {
switch (props.shapeType) {
case MapShapeType.CIRCLE:
return <Circle {...(props as CircleProps)} />;
case MapShapeType.CIRCLE_MARKER: {
return <CircleMarker {...(props as CircleMarkerProps)} />;
}
case MapShapeType.POLYGON: {
return <Polygon {...(props as PolygonProps)} />;
}
case MapShapeType.POLYLINE: {
return <Polyline {...(props as PolylineProps)} />;
}
case MapShapeType.RECTANGLE: {
return <Rectangle {...(props as RectangleProps)} />;
}
default:
console.warn("Unknown map shape type", props.shapeType);
return null;
}
};
render() {
return (
<>
{this.props.mapShapes.map(mapShape => {
const props = { ...mapShape, color: mapShape.color ?? "white" };
return <this.Shape {...props} key={Math.random().toString()} />;
})}
</>
);
}
}
export default MapShapes;
================================================
FILE: HTML/src/__snapshots__/MapComponent.test.tsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MapComponent it renders 1`] = `
<DocumentFragment>
<div
id="map-container"
style="position: absolute; top: 0px; bottom: 0px; background-color: greenyellow; left: 0px; right: 0px;"
/>
</DocumentFragment>
`;
================================================
FILE: HTML/src/__snapshots__/MapComponent.view.test.tsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MapComponentView it renders 1`] = `
<DocumentFragment>
<div
id="map-container"
style="position: absolute; top: 0px; bottom: 0px; background-color: greenyellow; left: 0px; right: 0px;"
/>
</DocumentFragment>
`;
================================================
FILE: HTML/src/__snapshots__/MapLayers.test.tsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MapLayers Component it renders 1`] = `
<DocumentFragment>
<div
class="leaflet-container leaflet-grab leaflet-touch-drag"
style="width: 100px; height: 100px; position: relative;"
tabindex="0"
>
<div
class="leaflet-pane leaflet-map-pane"
style="left: 0px; top: 0px;"
>
<div
class="leaflet-pane leaflet-tile-pane"
>
<div
class="leaflet-layer "
style="z-index: 1;"
>
<div
class="leaflet-tile-container leaflet-zoom-animated"
style="left: 0px; top: 0px;"
>
<img
alt=""
class="leaflet-tile"
role="presentation"
src="https://a.tile.openstreetmap.org/13/4095/4095.png"
style="width: 256px; height: 256px; left: -256px; top: -256px;"
/>
<img
alt=""
class="leaflet-tile"
role="presentation"
src="https://b.tile.openstreetmap.org/13/4096/4095.png"
style="width: 256px; height: 256px; left: 0px; top: -256px;"
/>
<img
alt=""
class="leaflet-tile"
role="presentation"
src="https://b.tile.openstreetmap.org/13/4095/4096.png"
style="width: 256px; height: 256px; left: -256px; top: 0px;"
/>
<img
alt=""
class="leaflet-tile"
role="presentation"
src="https://c.tile.openstreetmap.org/13/4096/4096.png"
style="width: 256px; height: 256px; left: 0px; top: 0px;"
/>
</div>
</div>
</div>
<div
class="leaflet-pane leaflet-shadow-pane"
/>
<div
class="leaflet-pane leaflet-overlay-pane"
/>
<div
class="leaflet-pane leaflet-marker-pane"
/>
<div
class="leaflet-pane leaflet-tooltip-pane"
/>
<div
class="leaflet-pane leaflet-popup-pane"
/>
</div>
<div
class="leaflet-control-container"
>
<div
class="leaflet-top leaflet-left"
>
<div
class="leaflet-control-zoom leaflet-bar leaflet-control"
>
<a
aria-label="Zoom in"
class="leaflet-control-zoom-in"
href="#"
role="button"
title="Zoom in"
>
+
</a>
<a
aria-label="Zoom out"
class="leaflet-control-zoom-out"
href="#"
role="button"
title="Zoom out"
>
−
</a>
</div>
</div>
<div
class="leaflet-top leaflet-right"
>
<div
aria-haspopup="true"
class="leaflet-control-layers leaflet-control"
>
<a
class="leaflet-control-layers-toggle"
href="#"
title="Layers"
/>
<section
class="leaflet-control-layers-list"
>
<div
class="leaflet-control-layers-base"
>
<label>
<div>
<input
checked="checked"
class="leaflet-control-layers-selector"
name="leaflet-base-layers_33"
type="radio"
/>
<span>
OpenStreetMap.Mapnik
</span>
</div>
</label>
<label>
<div>
<input
class="leaflet-control-layers-selector"
name="leaflet-base-layers_33"
type="radio"
/>
<span>
OpenStreetMap.BlackAndWhite
</span>
</div>
</label>
</div>
<div
class="leaflet-control-layers-separator"
style="display: none;"
/>
<div
class="leaflet-control-layers-overlays"
/>
</section>
</div>
</div>
<div
class="leaflet-bottom leaflet-left"
/>
<div
class="leaflet-bottom leaflet-right"
>
<div
class="leaflet-control-attribution leaflet-control"
>
<a
href="https://leafletjs.com"
title="A JS library for interactive maps"
>
Leaflet
</a>
| ©
<a
href="http://osm.org/copyright"
>
OpenStreetMap
</a>
contributors
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
================================================
FILE: HTML/src/index.css
================================================
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
================================================
FILE: HTML/src/index.tsx
================================================
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./MapComponent";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(<App />, document.getElementById("root"));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
================================================
FILE: HTML/src/mapComponent.tsx
================================================
import React, { Component } from "react";
import "leaflet/dist/leaflet.css";
import "leaflet/dist/images/layers-2x.png";
import "leaflet/dist/images/layers.png";
import "leaflet/dist/images/marker-icon-2x.png";
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
import MapComponentView from "./MapComponent.view";
import L from "leaflet";
import mockMapLayers from "./testData/mockMapLayers";
import mockMapShapes from "./testData/mockMapShapes";
import mockMapMarkers from "./testData/mockMapMarkers";
import {
WebViewLeafletEvents,
MapEventMessage,
MapLayer,
MapMarker,
MapShape,
INFINITE_ANIMATION_ITERATIONS,
AnimationType,
WebviewLeafletMessagePayload
} from "./models";
import "./styles/markers.css";
import "./styles/markerAnimations.css";
import { LatLng } from "react-leaflet";
export const SHOW_DEBUG_INFORMATION = false;
const ENABLE_BROWSER_TESTING = true;
interface State {
debugMessages: string[];
isFromNative: boolean;
isMobile: boolean;
mapCenterPosition: LatLng;
mapLayers: MapLayer[];
mapMarkers: MapMarker[];
mapShapes: MapShape[];
ownPositionMarker: MapMarker;
mapRef: any;
zoom: number;
}
export default class MapComponent extends Component<{}, State> {
constructor(props: {}) {
super(props);
this.state = {
debugMessages: ["test"],
isFromNative: false,
isMobile: null,
mapCenterPosition: { lat: 36.56, lng: -76.17 },
mapLayers: [],
mapMarkers: [],
mapShapes: [],
mapRef: null,
ownPositionMarker: null,
zoom: 6
};
}
componentDidMount = () => {
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow
});
L.Marker.prototype.options.icon = DefaultIcon;
this.addEventListeners();
this.sendMessage({
msg: WebViewLeafletEvents.MAP_COMPONENT_MOUNTED
});
if (ENABLE_BROWSER_TESTING) {
this.loadMockData();
}
};
componentDidUpdate = (prevProps: any, prevState: State) => {
const { mapRef } = this.state;
if (mapRef && !prevState.mapRef) {
mapRef.current?.leafletElement.invalidateSize();
this.sendMessage({
msg: WebViewLeafletEvents.MAP_READY
});
}
};
private addDebugMessage = (msg: any) => {
if (typeof msg === "object") {
this.addDebugMessage("STRINGIFIED");
this.setState({
debugMessages: [
...this.state.debugMessages,
JSON.stringify(msg, null, 4)
]
});
} else {
this.setState({ debugMessages: [...this.state.debugMessages, msg] });
}
};
private addEventListeners = () => {
if (document) {
document.addEventListener("message", this.handleMessage);
this.addDebugMessage("set document listeners");
this.sendMessage({
msg: WebViewLeafletEvents.DOCUMENT_EVENT_LISTENER_ADDED
});
}
if (window) {
window.addEventListener("message", this.handleMessage);
this.addDebugMessage("setting Window");
this.sendMessage({
msg: WebViewLeafletEvents.WINDOW_EVENT_LISTENER_ADDED
});
}
if (!document && !window) {
this.sendMessage({
error: WebViewLeafletEvents.UNABLE_TO_ADD_EVENT_LISTENER
});
return;
}
};
private handleMessage = (event: any & { data: State }) => {
this.addDebugMessage(event.data);
try {
if (event.data.mapCenterPosition) {
this.state.mapRef.leafletElement.flyTo([
event.data.mapCenterPosition.lat,
event.data.mapCenterPosition.lng
]);
}
this.setState({ ...this.state, ...event.data });
} catch (error) {
this.addDebugMessage({ error: JSON.stringify(error) });
}
};
protected sendMessage = (message: MapEventMessage) => {
// @ts-ignore
if (window.ReactNativeWebView) {
// @ts-ignore
window.ReactNativeWebView.postMessage(JSON.stringify(message));
console.log("sendMessage ", JSON.stringify(message));
}
};
private loadMockData = () => {
this.addDebugMessage("loading mock data");
this.setState({
mapLayers: mockMapLayers,
mapMarkers: mockMapMarkers,
mapShapes: mockMapShapes,
ownPositionMarker: {
id: "Own Position",
position: { lat: 36.56, lng: -76.17 },
icon: "❤️",
size: [32, 32],
animation: {
duration: 1,
delay: 0,
iterationCount: INFINITE_ANIMATION_ITERATIONS,
type: AnimationType.BOUNCE
}
}
});
};
private onMapEvent = (
webViewLeafletEvent: WebViewLeafletEvents,
payload?: WebviewLeafletMessagePayload
) => {
if (!payload && this.state.mapRef?.leafletElement) {
debugger;
const mapCenterPosition: LatLng = {
lat: this.state.mapRef.leafletElement?.getCenter().lat,
lng: this.state.mapRef.leafletElement?.getCenter().lng
};
payload = {
mapCenterPosition: mapCenterPosition,
bounds: this.state.mapRef.leafletElement?.getBounds(),
zoom: this.state.mapRef.leafletElement?.getZoom()
};
}
this.sendMessage({ event: webViewLeafletEvent, payload });
};
private setMapRef = (mapRef: any) => {
if (!this.state.mapRef) {
this.setState({ mapRef });
}
};
render() {
const {
debugMessages,
mapCenterPosition,
mapLayers,
mapMarkers,
mapShapes,
ownPositionMarker,
zoom
} = this.state;
return (
<MapComponentView
addDebugMessage={this.addDebugMessage}
debugMessages={debugMessages}
mapCenterPosition={mapCenterPosition}
mapLayers={mapLayers}
mapMarkers={mapMarkers}
mapShapes={mapShapes}
onMapEvent={this.onMapEvent}
ownPositionMarker={ownPositionMarker}
setMapRef={this.setMapRef}
zoom={zoom}
/>
);
}
}
================================================
FILE: HTML/src/mapComponent.view.tsx
================================================
import * as React from "react";
import { useState, useEffect } from "react";
import Measure from "react-measure";
import { Map, LatLng } from "react-leaflet";
import MapLayers from "./MapLayers";
import MapMarkers from "./MapMarkers";
import { SHOW_DEBUG_INFORMATION } from "./MapComponent";
import { WebViewLeafletEvents, MapLayer, MapMarker, MapShape } from "./models";
import MapShapes from "./MapShapes";
import { LatLngExpression } from "leaflet";
interface MapComponentViewProps {
addDebugMessage: (msg: any) => void;
debugMessages: string[];
mapCenterPosition: LatLng;
mapLayers: MapLayer[];
mapMarkers: MapMarker[];
mapShapes: MapShape[];
onMapEvent: (mapEvent: WebViewLeafletEvents, payload?: any) => void;
ownPositionMarker: MapMarker;
setMapRef: (mapRef: any) => void;
zoom: number;
}
const MapComponentView: React.FC<MapComponentViewProps> = ({
addDebugMessage,
debugMessages,
mapCenterPosition,
mapLayers = [],
mapMarkers = [],
mapShapes = [],
onMapEvent,
ownPositionMarker,
setMapRef,
zoom = 13
}: MapComponentViewProps) => {
const [dimensions, setDimensions] = useState({ height: 0, width: 0 });
const [combinedMapMarkers, setCombinedMapMarkers] = useState([]);
useEffect(() => {
const combinedMapMarkers = mapMarkers;
if (ownPositionMarker) {
combinedMapMarkers.push(ownPositionMarker);
}
setCombinedMapMarkers(combinedMapMarkers);
}, [mapMarkers, ownPositionMarker]);
return (
<>
<Measure
bounds
onResize={contentRect => {
const { height, width } = contentRect.bounds;
setDimensions({ height, width });
}}
>
{({ measureRef }) => (
<div
ref={measureRef}
id="map-container"
style={{
position: "absolute",
top: 0,
bottom: 0,
backgroundColor: "greenyellow",
left: 0,
right: 0
}}
>
{dimensions.height > 0 && (
<Map
ref={ref => {
setMapRef(ref);
}}
center={mapCenterPosition as LatLngExpression}
onClick={(event: any) => {
const { containerPoint, layerPoint, latlng } = event;
onMapEvent(WebViewLeafletEvents.ON_MAP_TOUCHED, {
containerPoint,
layerPoint,
touchLatLng: latlng
});
}}
onZoomLevelsChange={() => {
onMapEvent(WebViewLeafletEvents.ON_ZOOM_LEVELS_CHANGE);
}}
onResize={() => {
onMapEvent(WebViewLeafletEvents.ON_RESIZE);
}}
onZoomStart={() => {
onMapEvent(WebViewLeafletEvents.ON_ZOOM_START);
}}
onMoveStart={() => {
onMapEvent(WebViewLeafletEvents.ON_MOVE_START);
}}
onZoom={() => {
onMapEvent(WebViewLeafletEvents.ON_ZOOM);
}}
onMove={() => {
onMapEvent(WebViewLeafletEvents.ON_MOVE);
}}
onZoomEnd={() => {
onMapEvent(WebViewLeafletEvents.ON_ZOOM_END);
}}
onMoveEnd={() => {
onMapEvent(WebViewLeafletEvents.ON_MOVE_END);
}}
onUnload={() => {
onMapEvent(WebViewLeafletEvents.ON_UNLOAD);
}}
onViewReset={() => {
onMapEvent(WebViewLeafletEvents.ON_VIEW_RESET);
}}
maxZoom={17}
zoom={zoom}
style={{ width: "100%", height: dimensions.height }}
>
<MapLayers mapLayers={mapLayers} />
<MapMarkers
mapMarkers={combinedMapMarkers}
onMapEvent={onMapEvent}
/>
<MapShapes mapShapes={mapShapes} onMapEvent={onMapEvent} />
</Map>
)}
</div>
)}
</Measure>
{SHOW_DEBUG_INFORMATION ? (
<div
style={{
backgroundColor: "orange",
maxHeight: "200px",
overflow: "auto",
padding: 5,
position: "fixed",
bottom: 0,
left: 0,
right: 0,
zIndex: 15000
}}
id="messages"
>
<ul>
{debugMessages.map((message, index) => {
return <li key={index}>{message}</li>;
})}
</ul>
</div>
) : null}
</>
);
};
export default MapComponentView;
================================================
FILE: HTML/src/models.ts
================================================
import * as ReactLeaflet from "react-leaflet";
export type LatLng = ReactLeaflet.LatLng;
export type Point = ReactLeaflet.Point;
export type LatLngBounds = ReactLeaflet.LatLngBounds;
export const OWN_POSTION_MARKER_ID = "OWN_POSTION_MARKER_ID";
export enum WebViewLeafletEvents {
MAP_COMPONENT_MOUNTED = "MAP_COMPONENT_MOUNTED",
MAP_READY = "MAP_READY",
DOCUMENT_EVENT_LISTENER_ADDED = "DOCUMENT_EVENT_LISTENER_ADDED",
WINDOW_EVENT_LISTENER_ADDED = "WINDOW_EVENT_LISTENER_ADDED",
UNABLE_TO_ADD_EVENT_LISTENER = "UNABLE_TO_ADD_EVENT_LISTENER",
DOCUMENT_EVENT_LISTENER_REMOVED = "DOCUMENT_EVENT_LISTENER_REMOVED",
WINDOW_EVENT_LISTENER_REMOVED = "WINDOW_EVENT_LISTENER_REMOVED",
ON_MOVE_END = "onMoveEnd",
ON_MOVE_START = "onMoveStart",
ON_MOVE = "onMove",
ON_RESIZE = "onResize",
ON_UNLOAD = "onUnload",
ON_VIEW_RESET = "onViewReset",
ON_ZOOM_END = "onZoomEnd",
ON_ZOOM_LEVELS_CHANGE = "onZoomLevelsChange",
ON_ZOOM_START = "onZoomStart",
ON_ZOOM = "onZoom",
ON_MAP_TOUCHED = "onMapClicked",
ON_MAP_MARKER_CLICKED = "onMapMarkerClicked"
// ON_MAP_SHAPE_CLICKED = "onMapShapeClicked" cannot click on shapes yet
}
export enum AnimationType {
BOUNCE = "bounce",
FADE = "fade",
PULSE = "pulse",
JUMP = "jump",
SPIN = "spin",
WAGGLE = "waggle"
}
export enum MapLayerType {
IMAGE_LAYER = "ImageOverlay",
TILE_LAYER = "TileLayer",
VECTOR_LAYER = "VectorLayer",
VIDEO_LAYER = "VideoOverlay",
WMS_TILE_LAYER = "WMSTileLayer"
}
export enum MapShapeType {
CIRCLE = "Circle",
CIRCLE_MARKER = "CircleMarker",
POLYLINE = "Polyline",
POLYGON = "Polygon",
RECTANGLE = "Rectangle"
}
export const INFINITE_ANIMATION_ITERATIONS: string = "infinite";
export enum AnimationDirection {
NORMAL = "nomal",
REVERSE = "reverse",
ALTERNATE = "alternate",
ALTERNATE_REVERSE = "alternate-reverse"
}
export interface MapMarkerAnimation {
type: AnimationType;
duration?: number;
delay?: number;
direction?: AnimationDirection;
iterationCount?: number | typeof INFINITE_ANIMATION_ITERATIONS;
}
export interface MapMarker {
animation?: MapMarkerAnimation;
position: LatLng;
divIcon?: L.DivIcon;
icon: any;
iconAnchor?: Point;
id?: string;
size?: Point;
title?: string;
}
export interface MapEventMessage {
event?: any;
msg?: string;
error?: string;
payload?: any;
}
export interface MapLayer {
attribution?: string;
baseLayer?: boolean;
baseLayerIsChecked?: boolean;
baseLayerName?: string;
bounds?: LatLngBounds;
id?: string;
layerType?: MapLayerType;
opacity?: number;
pane?: string;
subLayer?: string;
url?: string;
zIndex?: number;
}
export interface MapShape {
bounds?: LatLng[];
center?: LatLng;
color?: string;
id?: string;
positions?: LatLng[] | LatLng[][];
radius?: number;
shapeType: MapShapeType;
}
export interface MapStartupMessage {
mapLayers?: MapLayer[];
mapMarkers?: MapMarker[];
mapShapes?: MapShape[];
mapCenterPosition?: LatLng;
ownPositionMarker?: OwnPositionMarker;
zoom?: number;
}
export type WebviewLeafletMessagePayload = {
bounds?: LatLngBounds;
mapCenterPosition: LatLng;
mapMarkerID?: string;
touchLatLng?: LatLng;
zoom?: number;
};
export interface WebviewLeafletMessage {
event?: any;
msg?: string;
error?: string;
payload?: WebviewLeafletMessagePayload;
}
export type OwnPositionMarker = {
animation: MapMarkerAnimation;
id?: string;
icon: string;
position: LatLng;
size: Point;
};
================================================
FILE: HTML/src/react-app-env.d.ts
================================================
/// <reference types="react-scripts" />
================================================
FILE: HTML/src/serviceWorker.ts
================================================
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
type Config = {
onSuccess?: (registration: ServiceWorkerRegistration) => void;
onUpdate?: (registration: ServiceWorkerRegistration) => void;
};
export function register(config?: Config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(
process.env.PUBLIC_URL,
window.location.href
);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA'
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl: string, config?: Config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl: string, config?: Config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { 'Service-Worker': 'script' }
})
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
================================================
FILE: HTML/src/setupTests.ts
================================================
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
================================================
FILE: HTML/src/styles/markerAnimations.css
================================================
.marker {
background-color: rgba(255, 255, 255, 0);
width: 100%;
height: 100%;
position: relative;
}
/* div containing the marker parent */
.clearMarkerContainer {
background-color: rgba(57, 57, 216, 0);
display: flex;
justify-content: center;
}
/* div containing all the animated portions of the marker */
.animationContainer {
display: flex;
justify-content: center;
align-items: flex-end;
}
@keyframes bounce {
0% {
transform: scale(1, 0.8) translateY(10px);
}
45% {
transform: scale(0.8, 1) translateY(-27px);
}
50% {
transform: scale(0.8, 1) translateY(-30px);
}
55% {
transform: scale(0.8, 1) translateY(-27px);
}
100% {
transform: scale(1, 0.8) translateY(10px);
}
}
@keyframes fade {
0% {
opacity: 0.1;
}
50% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
@keyframes jump {
0% {
transform: none;
}
50% {
transform: translateY(-2em);
}
}
@keyframes waggle {
0% {
transform: none;
}
50% {
transform: rotateZ(-20deg) scale(1.2);
}
60% {
transform: rotateZ(25deg) scale(1.2);
}
67.5% {
transform: rotateZ(-15deg) scale(1.2);
}
75% {
transform: rotateZ(15deg) scale(1.2);
}
82.5% {
transform: rotateZ(-12deg) scale(1.2);
}
85% {
transform: rotateZ(0) scale(1.2);
}
100% {
transform: rotateZ(0) scale(1);
}
}
@keyframes spin {
50% {
transform: rotateZ(-20deg);
animation-timing-function: ease;
}
100% {
transform: rotateZ(360deg);
}
}
@keyframes beat {
to {
transform: scale(0.7);
}
}
================================================
FILE: HTML/src/styles/markers.css
================================================
/*General marker style*/
.marker {
background-color: rgba(255, 255, 255, 0);
width: 100%;
height: 100%;
position: relative;
}
/* div containing the marker parent */
.clearMarkerContainer {
background-color: rgba(57, 57, 216, 0);
display: flex;
justify-content: center;
}
/* div containing all the animated portions of the marker */
.animationContainer {
display: flex;
justify-content: center;
align-items: flex-end;
}
@keyframes bounce {
0% {
transform: scale(1, 0.8) translateY(10px);
}
45% {
transform: scale(0.8, 1) translateY(-27px);
}
50% {
transform: scale(0.8, 1) translateY(-30px);
}
55% {
transform: scale(0.8, 1) translateY(-27px);
}
100% {
transform: scale(1, 0.8) translateY(10px);
}
}
@keyframes fade {
0% {
opacity: 0.1;
}
50% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
@keyframes jump {
0% {
transform: none;
}
50% {
transform: translateY(-2em);
}
}
@keyframes waggle {
0% {
transform: none;
}
50% {
transform: rotateZ(-20deg) scale(1.2);
}
60% {
transform: rotateZ(25deg) scale(1.2);
}
67.5% {
transform: rotateZ(-15deg) scale(1.2);
}
75% {
transform: rotateZ(15deg) scale(1.2);
}
82.5% {
transform: rotateZ(-12deg) scale(1.2);
}
85% {
transform: rotateZ(0) scale(1.2);
}
100% {
transform: rotateZ(0) scale(1);
}
}
@keyframes spin {
50% {
transform: rotateZ(-20deg);
animation-timing-function: ease;
}
100% {
transform: rotateZ(360deg);
}
}
@keyframes beat {
to {
transform: scale(0.7);
}
}
================================================
FILE: HTML/src/testData/mockMapLayers.ts
================================================
import { MapLayer, MapLayerType } from "../models";
const mockMapLayers: MapLayer[] = [
{
attribution:
'&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
baseLayerIsChecked: true,
baseLayerName: "OpenStreetMap.Mapnik",
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
},
{
attribution:
'&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
baseLayerIsChecked: false,
baseLayerName: "OpenStreetMap.BlackAndWhite",
url: "https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png"
},
{
baseLayerName: "WMS Tile Layer",
subLayer: "nasa:bluemarble",
layerType: MapLayerType.WMS_TILE_LAYER,
url: "https://demo.boundlessgeo.com/geoserver/ows"
},
{
baseLayerName: "Image",
layerType: MapLayerType.IMAGE_LAYER,
url: "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
bounds: [
[40.712216, -74.22655],
[40.773941, -74.12544]
]
}
];
export default mockMapLayers;
================================================
FILE: HTML/src/testData/mockMapMarkers.ts
================================================
import * as svgIcons from "./svgIcons";
import { LatLng } from "leaflet";
import { MapMarker, AnimationType } from "../models";
const emoji = ["😴", "😄", "😃", "⛔", "🎠", "🚓", "🚇"];
const duration = Math.floor(Math.random() * 3) + 1;
const delay = Math.floor(Math.random()) * 0.5;
const iterationCount = "infinite";
const mapMarkers: MapMarker[] = [
{
id: "2",
position: { lat: 37.06452161, lng: -75.67364786 },
icon: "😴",
size: [64, 64],
animation: {
duration,
delay,
iterationCount,
type: AnimationType.PULSE
}
},
{
id: "19",
position: { lat: 36.46410354, lng: -75.6432701 },
icon:
"https://www.catster.com/wp-content/uploads/2018/07/Savannah-cat-long-body-shot.jpg",
size: [32, 32],
animation: {
duration,
delay,
iterationCount,
type: AnimationType.BOUNCE
}
},
{
id: "100",
position: new LatLng(37.23310632, -76.23518332),
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
duration,
delay,
iterationCount,
type: AnimationType.WAGGLE
}
},
{
id: "1",
position: { lat: 36.46410354, lng: -75.6432701 },
icon: "😴",
size: [32, 32],
animation: {
type: AnimationType.SPIN,
duration,
delay,
iterationCount
}
},
{
id: "1000",
position: new LatLng(36.60061515, -76.48888338),
icon: svgIcons.greenCircle,
animation: {
duration,
delay,
iterationCount,
type: AnimationType.PULSE
}
},
{
id: Math.floor(Math.random() * 1000).toString(),
position: { lat: 37.0580835, lng: -75.82318747 },
icon: "Fish",
animation: {
type: AnimationType.WAGGLE,
duration,
delay,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000).toString(),
position: { lat: 37.23310632, lng: -76.23518332 },
icon: emoji[Math.floor(Math.random() * emoji.length)],
size: [4, 4],
animation: {
type: AnimationType.PULSE,
duration,
delay,
iterationCount
}
}
/*
{
id: Math.floor(Math.random() * 1000),
coords: [36.94994253, -76.64318409],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.19810239, -76.28058546],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.02416165, -76.56052521],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.91541467, -75.49279245],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.70503123, -76.32755185],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.31605891, -76.45141618],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.59436803, -76.89486842],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.35740877, -75.77910112],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.31509182, -76.76693784],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.91815909, -76.06707072],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.611917, -75.76758822],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.79520769, -76.3959497],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.42854666, -75.95883052],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [36.78673099, -76.90459724],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
},
{
id: Math.floor(Math.random() * 1000),
coords: [37.20966767, -75.58799685],
icon: emoji[Math.floor(Math.random() * emoji.length)],
animation: {
name: animations[Math.floor(Math.random() * animations.length)],
duration: Math.floor(Math.random() * 3) + 1,
delay: Math.floor(Math.random()) * 0.5,
iterationCount
}
} */
];
export default mapMarkers;
================================================
FILE: HTML/src/testData/mockMapShapes.ts
================================================
import { MapShapeType, MapShape } from "../models";
export const circle: MapShape = {
shapeType: MapShapeType.CIRCLE,
color: "#123123",
id: "1",
center: { lat: 34.225727, lng: -77.94471 },
radius: 2000
};
export const circleMarker: MapShape = {
shapeType: MapShapeType.CIRCLE_MARKER,
color: "red",
id: "2",
center: { lat: 38.437424, lng: -78.867912 },
radius: 15
};
export const polygon: MapShape = {
shapeType: MapShapeType.POLYGON,
color: "blue",
id: "3",
positions: [
{ lat: 38.80118939192329, lng: -74.69604492187501 },
{ lat: 38.19502155795575, lng: -74.65209960937501 },
{ lat: 39.07890809706475, lng: -71.46606445312501 }
]
};
export const multiPolygon: MapShape = {
shapeType: MapShapeType.POLYGON,
color: "violet",
id: "4",
positions: [
[
{ lat: 37.13842453422676, lng: -74.28955078125001 },
{ lat: 36.4433803110554, lng: -74.26208496093751 },
{ lat: 36.43896124085948, lng: -73.00964355468751 },
{ lat: 36.43896124085948, lng: -73.00964355468751 }
],
[
{ lat: 37.505368263398104, lng: -72.38891601562501 },
{ lat: 37.309014074275915, lng: -71.96594238281251 },
{ lat: 36.69044623523481, lng: -71.87805175781251 },
{ lat: 36.58024660149866, lng: -72.75146484375001 },
{ lat: 37.36579146999664, lng: -72.88330078125001 }
]
]
};
export const polyline: MapShape = {
shapeType: MapShapeType.POLYLINE,
color: "orange",
id: "5",
positions: [
{ lat: 35.411438052435486, lng: -78.67858886718751 },
{ lat: 35.9602229692967, lng: -79.18945312500001 },
{ lat: 35.97356075349624, lng: -78.30505371093751 }
]
};
export const multiPolyline: MapShape = {
shapeType: MapShapeType.POLYLINE,
color: "purple",
id: "5a",
positions: [
[
{ lat: 36.36822190085111, lng: -79.26086425781251 },
{ lat: 36.659606226479696, lng: -79.28833007812501 },
{ lat: 36.721273880045004, lng: -79.81018066406251 }
],
[
{ lat: 35.43381992014202, lng: -79.79370117187501 },
{ lat: 35.44277092585766, lng: -81.23840332031251 },
{ lat: 35.007502842952896, lng: -80.837402343750017 }
]
]
};
export const rectangle: MapShape = {
shapeType: MapShapeType.RECTANGLE,
color: "yellow",
id: "6",
bounds: [
{ lat: 36.5, lng: -75.7 },
{ lat: 38.01, lng: -73.13 }
]
};
export default [circle, circleMarker, polygon, polyline, rectangle];
================================================
FILE: HTML/src/testData/svgIcons.ts
================================================
export const greenCircle = `<svg xmlns="http://www.w3.org/2000/svg">
<circle id="greencircle" cx="30" cy="30" r="30" fill="green" />
</svg>`;
================================================
FILE: HTML/src/utilities.test.ts.old
================================================
import {
convertWebViewLeafletLatLngToNumberArray,
convertWebViewLeafletLatLngBoundsToLeaftletBounds,
getAnimatedHTMLString
} from "./utilities";
import {
WebViewLeafletLatLng,
WebViewLeafletLatLngBounds
} from "../../WebViewLeaflet/models";
import { AnimationType } from "./models";
const singleLatLng: WebViewLeafletLatLng = { lat: 34.225727, lng: -77.94471 };
const latLngArray: WebViewLeafletLatLng[] = [
{ lat: 38.80118939192329, lng: -74.69604492187501 },
{ lat: 38.19502155795575, lng: -74.65209960937501 },
{ lat: 39.07890809706475, lng: -71.46606445312501 }
];
const latLng2DArray: WebViewLeafletLatLng[][] = [
[
{ lat: 37.13842453422676, lng: -74.28955078125001 },
{ lat: 36.4433803110554, lng: -74.26208496093751 },
{ lat: 36.43896124085948, lng: -73.00964355468751 },
{ lat: 36.43896124085948, lng: -73.00964355468751 }
],
[
{ lat: 37.505368263398104, lng: -72.38891601562501 },
{ lat: 37.309014074275915, lng: -71.96594238281251 },
{ lat: 36.69044623523481, lng: -71.87805175781251 },
{ lat: 36.58024660149866, lng: -72.75146484375001 },
{ lat: 37.36579146999664, lng: -72.88330078125001 }
]
];
/* describe('convertWebViewLeafletLatLngToNumberArray', () => {
it('can covert a single lat lng to a number array ', () => {
const singleConverted = convertWebViewLeafletLatLngToNumberArray(
singleLatLng
);
expect(singleConverted).toEqual([34.225727, -77.94471]);
});
it('can covert a an array of latLng to an array of number arrays', () => {
const convertedLatLongArray = convertWebViewLeafletLatLngToNumberArray(
latLngArray
);
expect(convertedLatLongArray).toEqual([
[38.80118939192329, -74.69604492187501],
[38.19502155795575, -74.65209960937501],
[39.07890809706475, -71.46606445312501]
]);
});
it('can covert a 2D Array of latLngs to a 2D number array ', () => {
const latLng2DArrayConverted = convertWebViewLeafletLatLngToNumberArray(
latLng2DArray
);
expect(latLng2DArrayConverted).toEqual([
[
[37.13842453422676, -74.28955078125001],
[36.4433803110554, -74.26208496093751],
[36.43896124085948, -73.00964355468751],
[36.43896124085948, -73.00964355468751]
],
[
[37.505368263398104, -72.38891601562501],
[37.309014074275915, -71.96594238281251],
[36.69044623523481, -71.87805175781251],
[36.58024660149866, -72.75146484375001],
[37.36579146999664, -72.88330078125001]
]
]);
});
}); */
const cornerBounds: WebViewLeafletLatLngBounds = {
southWest: { lat: 36.665099, lng: -76.842042 },
northEast: { lat: 37.365855, lng: -76.158245 }
};
const arrayBounds: WebViewLeafletLatLngBounds = [
{ lat: 38.89688, lng: -77.302505 },
{ lat: 37.829395, lng: -76.756299 }
];
/* describe('convertWebViewLeafletLatLngBoundsToLeaftletBounds', () => {
it('can covert WebViewLeafletLatLngBoundsCorner objects', () => {
const convertedBounds = convertWebViewLeafletLatLngBoundsToLeaftletBounds(
cornerBounds
);
expect(convertedBounds).toEqual({
southWest: [36.665099, -76.842042],
northEast: [37.365855, -76.158245]
});
});
it('can covert WebViewLeafletLatLngBounds[] objects', () => {
const convertedBounds = convertWebViewLeafletLatLngBoundsToLeaftletBounds(
arrayBounds
);
expect(convertedBounds).toEqual([
[38.89688, -77.302505],
[37.829395, -76.756299]
]);
});
}); */
const mapMarker = {
id: 2,
coords: { lat: 37.06452161, lng: -75.67364786 },
icon: "😴",
size: [64, 64],
animation: {
duration: 1,
delay: 0.5,
type: AnimationType.BOUNCE
}
};
/* describe('getAnimatedHTMLString', () => {
it('returns a div with an animated emoji', () => {
const div = getAnimatedHTMLString(mapMarker.icon, mapMarker.animation);
expect(div).toBe(`<div class='animationContainer' style="
animation-name: bounce;
animation-duration: 1s ;
animation-delay: 0.5s;
animation-direction: normal;
animation-iteration-count: infinite">
<div style='font-size: 24px'>😴</div>
</div>`);
});
}); */
================================================
FILE: HTML/src/utilities.ts
================================================
import L, { DivIcon } from "leaflet";
import base64Image from "./webBase64Image";
import { MapMarker, MapMarkerAnimation } from "./models";
import { Point } from "react-leaflet";
export const createDivIcon = (mapMarker: MapMarker): DivIcon => {
let divIcon: DivIcon = L.divIcon({
className: "clearMarkerContainer",
html: mapMarker.animation
? getAnimatedHTMLString(
mapMarker.icon || "📍",
mapMarker.animation || null,
mapMarker.size || [24, 24]
)
: getUnanimatedHTMLString(mapMarker.icon, mapMarker.size),
iconAnchor: mapMarker.iconAnchor || null
});
return divIcon;
};
/*
Get the HTML string containing the icon div, and animation parameters
*/
export const getAnimatedHTMLString = (
icon: any,
animation: MapMarkerAnimation,
size: Point = [24, 24]
) => {
return `<div class='animationContainer' style="
animation-name: ${animation.type ? animation.type : "bounce"};
animation-duration: ${animation.duration ? animation.duration : 1}s ;
animation-delay: ${animation.delay ? animation.delay : 0}s;
animation-direction: ${animation.direction ? animation.direction : "normal"};
animation-iteration-count: ${
animation.iterationCount ? animation.iterationCount : "infinite"
}">
${getIconFromEmojiOrImageOrSVG(icon, size)}
</div>`;
};
const getUnanimatedHTMLString = (icon: any, size: Point = [24, 24]): string => {
return `<div class='unanimatedIconContainer'>${getIconFromEmojiOrImageOrSVG(
icon,
size
)}</div>`;
};
const getIconFromEmojiOrImageOrSVG = (icon: any, size: Point) => {
if (icon.includes("svg") || icon.includes("SVG")) {
//@ts-ignore
return ` <div style='font-size: ${Math.max(size[0], size[1])}px'>
${icon}
</div>`;
} else if (icon.includes("//") && icon.includes("http")) {
//@ts-ignore
return `<img src="${icon}" style="width:${size[0]}px;height:${size[1]}px;">`;
} else if (icon.includes("base64")) {
//@ts-ignore
return `<img src="${base64Image}" style="width:${size[0]}px;height:${size[1]}px;">`;
} else {
return `<div style='font-size: ${Math.max(
//@ts-ignore
size[0],
//@ts-ignore
size[1]
)}px'>${icon}</div>`;
}
};
================================================
FILE: HTML/src/webBase64Image.ts
================================================
const base64Image =
'data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5NWvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29uc/P9cmJu9MTDImIN+/r7+/vz8/P8VNQGNugV8AAF9fX8swMNgTAFlDOICAgPNSUnNWSMQ5MBAQEJE3QPIGAM9AQMqGcG9vb6MhJsEdGM8vLx8fH98AANIWAMuQeL8fABkTEPPQ0OM5OSYdGFl5jo+Pj/+pqcsTE78wMFNGQLYmID4dGPvd3UBAQJmTkP+8vH9QUK+vr8ZWSHpzcJMmILdwcLOGcHRQUHxwcK9PT9DQ0O/v70w5MLypoG8wKOuwsP/g4P/Q0IcwKEswKMl8aJ9fX2xjdOtGRs/Pz+Dg4GImIP8gIH0sKEAwKKmTiKZ8aB/f39Wsl+LFt8dgUE9PT5x5aHBwcP+AgP+WltdgYMyZfyywz78AAAAAAAD///8AAP9mZv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKgALAAAAAA9AEQAAAj/AFEJHEiwoMGDCBMqXMiwocAbBww4nEhxoYkUpzJGrMixogkfGUNqlNixJEIDB0SqHGmyJSojM1bKZOmyop0gM3Oe2liTISKMOoPy7GnwY9CjIYcSRYm0aVKSLmE6nfq05QycVLPuhDrxBlCtYJUqNAq2bNWEBj6ZXRuyxZyDRtqwnXvkhACDV+euTeJm1Ki7A73qNWtFiF+/gA95Gly2CJLDhwEHMOUAAuOpLYDEgBxZ4GRTlC1fDnpkM+fOqD6DDj1aZpITp0dtGCDhr+fVuCu3zlg49ijaokTZTo27uG7Gjn2P+hI8+PDPERoUB318bWbfAJ5sUNFcuGRTYUqV/3ogfXp1rWlMc6awJjiAAd2fm4ogXjz56aypOoIde4OE5u/F9x199dlXnnGiHZWEYbGpsAEA3QXYnHwEFliKAgswgJ8LPeiUXGwedCAKABACCN+EA1pYIIYaFlcDhytd51sGAJbo3onOpajiihlO92KHGaUXGwWjUBChjSPiWJuOO/LYIm4v1tXfE6J4gCSJEZ7YgRYUNrkji9P55sF/ogxw5ZkSqIDaZBV6aSGYq/lGZplndkckZ98xoICbTcIJGQAZcNmdmUc210hs35nCyJ58fgmIKX5RQGOZowxaZwYA+JaoKQwswGijBV4C6SiTUmpphMspJx9unX4KaimjDv9aaXOEBteBqmuuxgEHoLX6Kqx+yXqqBANsgCtit4FWQAEkrNbpq7HSOmtwag5w57GrmlJBASEU18ADjUYb3ADTinIttsgSB1oJFfA63bduimuqKB1keqwUhoCSK374wbujvOSu4QG6UvxBRydcpKsav++Ca6G8A6Pr1x2kVMyHwsVxUALDq/krnrhPSOzXG1lUTIoffqGR7Goi2MAxbv6O2kEG56I7CSlRsEFKFVyovDJoIRTg7sugNRDGqCJzJgcKE0ywc0ELm6KBCCJo8DIPFeCWNGcyqNFE06ToAfV0HBRgxsvLThHn1oddQMrXj5DyAQgjEHSAJMWZwS3HPxT/QMbabI/iBCliMLEJKX2EEkomBAUCxRi42VDADxyTYDVogV+wSChqmKxEKCDAYFDFj4OmwbY7bDGdBhtrnTQYOigeChUmc1K3QTnAUfEgGFgAWt88hKA6aCRIXhxnQ1yg3BCayK44EWdkUQcBByEQChFXfCB776aQsG0BIlQgQgE8qO26X1h8cEUep8ngRBnOy74E9QgRgEAC8SvOfQkh7FDBDmS43PmGoIiKUUEGkMEC/PJHgxw0xH74yx/3XnaYRJgMB8obxQW6kL9QYEJ0FIFgByfIL7/IQAlvQwEpnAC7DtLNJCKUoO/w45c44GwCXiAFB/OXAATQryUxdN4LfFiwgjCNYg+kYMIEFkCKDs6PKAIJouyGWMS1FSKJOMRB/BoIxYJIUXFUxNwoIkEKPAgCBZSQHQ1A2EWDfDEUVLyADj5AChSIQW6gu10bE/JG2VnCZGfo4R4d0sdQoBAHhPjhIB94v/wRoRKQWGRHgrhGSQJxCS+0pCZbEhAAOw==';
export default base64Image;
================================================
FILE: HTML/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"noEmit": true,
"jsx": "react",
"strict": true,
"strictNullChecks": false,
"isolatedModules": true
},
"include": [
"src"
]
}
================================================
FILE: WebViewLeaflet/ActivityOverlay.tsx
================================================
import React from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
interface Props {}
export const ActivityOverlay: React.FC<Props> = () => {
return (
<View style={styles.activityOverlayStyle}>
<View style={styles.activityIndicatorContainer}>
<ActivityIndicator size="large" animating={this.state.isLoading} />
</View>
</View>
);
};
const styles = StyleSheet.create({
activityOverlayStyle: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(255, 255, 255, .5)',
display: 'flex',
justifyContent: 'center',
alignContent: 'center',
borderRadius: 5
},
activityIndicatorContainer: {
backgroundColor: 'lightgray',
padding: 10,
borderRadius: 50,
alignSelf: 'center',
shadowColor: '#000000',
shadowOffset: {
width: 0,
height: 3
},
shadowRadius: 5,
shadowOpacity: 1.0
}
});
================================================
FILE: WebViewLeaflet/DebugMessageBox.tsx
================================================
import React from "react";
import { ScrollView, Text, View } from "react-native";
export interface Props {
debugMessages: string[];
doShowDebugMessages: boolean;
}
const DebugMessageBox = ({
debugMessages = [],
doShowDebugMessages = false
}: Props) => {
if (doShowDebugMessages) {
return (
<View
style={{
height: 100,
backgroundColor: "aliceblue",
padding: 5,
position: "absolute",
bottom: 0,
left: 0,
right: 0,
zIndex: 1000
}}
>
<ScrollView>
{debugMessages.map((msg, idx) => {
if (typeof msg === "object") {
return (
<Text style={{ fontSize: 10 }} key={idx}>{`- ${JSON.stringify(
msg
)}`}</Text>
);
}
return <Text style={{ fontSize: 10 }} key={idx}>{`- ${msg}`}</Text>;
})}
</ScrollView>
</View>
);
}
return null;
};
export default DebugMessageBox;
================================================
FILE: WebViewLeaflet/WebViewLeaflet.tsx
================================================
import * as React from "react";
import { WebView } from "react-native-webview";
import AssetUtils from "expo-asset-utils";
import { Asset } from "expo-asset";
import WebViewLeafletView from "./WebViewLeaflet.view";
import {
MapMarker,
WebviewLeafletMessage,
MapStartupMessage,
WebViewLeafletEvents,
MapLayer,
MapShape,
OwnPositionMarker,
OWN_POSTION_MARKER_ID
} from "./models";
import { ActivityOverlay } from "./ActivityOverlay";
import * as FileSystem from "expo-file-system";
import { LatLng } from "react-leaflet";
import isEqual from "lodash.isequal";
// @ts-ignore node types
const INDEX_FILE_PATH = require(`./assets/index.html`);
export interface WebViewLeafletProps {
backgroundColor?: string;
doShowDebugMessages?: boolean;
loadingIndicator?: () => React.ReactElement;
onError?: (syntheticEvent: any) => void;
onLoadEnd?: () => void;
onLoadStart?: () => void;
onMessageReceived: (message: WebviewLeafletMessage) => void;
mapLayers?: MapLayer[];
mapMarkers?: MapMarker[];
mapShapes?: MapShape[];
mapCenterPosition?: LatLng;
ownPositionMarker?: OwnPositionMarker;
zoom?: number;
}
interface State {
debugMessages: string[];
mapCurrentCenterPosition: LatLng;
webviewContent: string;
isLoading: boolean;
}
class WebViewLeaflet extends React.Component<WebViewLeafletProps, State> {
private webViewRef: any;
static defaultProps = {
backgroundColor: "#FAEBD7",
doDisplayCenteringButton: true,
doShowDebugMessages: false,
loadingIndicator: () => {
return <ActivityOverlay />;
},
onError: (syntheticEvent: any) => {},
onLoadEnd: () => {},
onLoadStart: () => {}
};
constructor(props) {
super(props);
this.state = {
debugMessages: [],
isLoading: null,
mapCurrentCenterPosition: null,
webviewContent: null
};
this.webViewRef = null;
}
componentDidMount = () => {
this.loadHTMLFile();
};
private loadHTMLFile = async () => {
try {
let asset: Asset = await AssetUtils.resolveAsync(INDEX_FILE_PATH);
let fileString: string = await FileSystem.readAsStringAsync(
asset.localUri
);
this.setState({ webviewContent: fileString });
} catch (error) {
console.warn(error);
console.warn("Unable to resolve index file");
}
};
componentDidUpdate = (prevProps: WebViewLeafletProps, prevState: State) => {
const { webviewContent } = this.state;
const {
mapCenterPosition,
mapMarkers,
mapLayers,
mapShapes,
ownPositionMarker,
zoom
} = this.props;
if (!prevState.webviewContent && webviewContent) {
this.updateDebugMessages("file loaded");
}
if (!isEqual(mapCenterPosition, prevProps.mapCenterPosition)) {
this.sendMessage({ mapCenterPosition });
}
if (!isEqual(mapMarkers, prevProps.mapMarkers)) {
this.sendMessage({ mapMarkers });
}
if (!isEqual(mapLayers, prevProps.mapLayers)) {
this.sendMessage({ mapLayers });
}
if (!isEqual(mapShapes, prevProps.mapShapes)) {
this.sendMessage({ mapShapes });
}
if (!isEqual(ownPositionMarker, prevProps.ownPositionMarker)) {
this.sendMessage({ ownPositionMarker });
}
if (zoom !== prevProps.zoom) {
this.sendMessage({ zoom });
}
};
private setMapCenterPosition = () => {
const { mapCurrentCenterPosition } = this.state;
const { mapCenterPosition } = this.props;
if (!isEqual(mapCenterPosition, mapCurrentCenterPosition)) {
this.setState({
mapCurrentCenterPosition: mapCenterPosition
});
this.sendMessage({
mapCenterPosition
});
}
};
// Handle messages received from webview contents
private handleMessage = (data: string) => {
const { onMessageReceived } = this.props;
let message: WebviewLeafletMessage = JSON.parse(data);
this.updateDebugMessages(`received: ${JSON.stringify(message)}`);
if (message.msg === WebViewLeafletEvents.MAP_READY) {
this.sendStartupMessage();
}
if (message.event === WebViewLeafletEvents.ON_MOVE_END) {
this.setState({
mapCurrentCenterPosition: message.payload.mapCenterPosition
});
}
onMessageReceived(message);
};
// Send message to webview
private sendMessage = (payload: object) => {
this.updateDebugMessages(`sending: ${payload}`);
this.webViewRef?.injectJavaScript(
`window.postMessage(${JSON.stringify(payload)}, '*');`
);
};
// Send a startup message with initalizing values to the map
private sendStartupMessage = () => {
let startupMessage: MapStartupMessage = {};
const {
mapLayers,
mapMarkers,
mapShapes,
mapCenterPosition,
ownPositionMarker,
zoom = 7
} = this.props;
if (mapLayers) {
startupMessage.mapLayers = mapLayers;
}
if (mapMarkers) {
startupMessage.mapMarkers = mapMarkers;
}
if (mapCenterPosition) {
startupMessage.mapCenterPosition = mapCenterPosition;
}
if (mapShapes) {
startupMessage.mapShapes = mapShapes;
}
if (ownPositionMarker) {
startupMessage.ownPositionMarker = {
...ownPositionMarker,
id: OWN_POSTION_MARKER_ID
};
}
startupMessage.zoom = zoom;
this.setState({ isLoading: false });
this.updateDebugMessages("sending startup message");
this.webViewRef.injectJavaScript(
`window.postMessage(${JSON.stringify(startupMessage)}, '*');`
);
};
// Add a new debug message to the debug message array
private updateDebugMessages = (debugMessage: string) => {
this.setState({
debugMessages: [...this.state.debugMessages, debugMessage]
});
};
private onError = (syntheticEvent: any) => {
this.props.onError(syntheticEvent);
};
private onLoadEnd = () => {
this.setState({ isLoading: false });
this.props.onLoadEnd();
};
private onLoadStart = () => {
this.setState({ isLoading: true });
this.props.onLoadStart();
};
// Output rendered item to screen
render() {
const { debugMessages, webviewContent } = this.state;
const {
backgroundColor,
doShowDebugMessages,
loadingIndicator
} = this.props;
if (webviewContent) {
return (
<WebViewLeafletView
backgroundColor={backgroundColor}
debugMessages={debugMessages}
doShowDebugMessages={doShowDebugMessages}
handleMessage={this.handleMessage}
webviewContent={webviewContent}
loadingIndicator={loadingIndicator}
onError={this.onError}
onLoadEnd={this.onLoadEnd}
onLoadStart={this.onLoadStart}
setWebViewRef={(ref: WebView) => {
this.webViewRef = ref;
}}
/>
);
} else {
return null;
}
}
}
export default WebViewLeaflet;
================================================
FILE: WebViewLeaflet/WebViewLeaflet.view.tsx
================================================
import React, { ReactElement } from 'react';
import { StyleSheet, View, NativeSyntheticEvent } from 'react-native';
import { WebView } from 'react-native-webview';
import { Asset } from 'expo-asset';
import DebugMessageBox from './DebugMessageBox';
import { WebViewError } from 'react-native-webview/lib/WebViewTypes';
export interface Props {
backgroundColor: string;
debugMessages: string[];
doShowDebugMessages: boolean;
handleMessage: (data: string) => void;
webviewContent: string;
loadingIndicator: () => ReactElement;
onError: (syntheticEvent: NativeSyntheticEvent<WebViewError>) => void;
onLoadEnd: () => void;
onLoadStart: () => void;
setWebViewRef: (ref: WebView) => void;
}
const WebViewLeafletView = ({
backgroundColor,
debugMessages,
doShowDebugMessages,
handleMessage,
webviewContent,
loadingIndicator,
onError,
onLoadEnd,
onLoadStart,
setWebViewRef
}: Props) => {
return (
<View
style={{
...StyleSheet.absoluteFillObject,
flex: 1,
backgroundColor: backgroundColor
}}
>
{webviewContent && (
<WebView
containerStyle={{
flex: 0,
height: '100%',
width: '100%'
}}
/* style={{ flex: 0, height: '100%', width: '100%' }} */
ref={(component) => {
setWebViewRef(component);
}}
javaScriptEnabled={true}
onLoadEnd={onLoadEnd}
onLoadStart={onLoadStart}
onMessage={(event) => {
if (event && event.nativeEvent && event.nativeEvent.data) {
handleMessage(event.nativeEvent.data);
}
}}
domStorageEnabled={true}
useWebKit={true}
startInLoadingState={true}
onError={onError}
originWhitelist={['*']}
/* renderLoading={loadingIndicator || null} */
source={{
html: webviewContent
}}
allowFileAccess={true}
allowUniversalAccessFromFileURLs={true}
allowFileAccessFromFileURLs={true}
/>
)}
<DebugMessageBox
debugMessages={debugMessages}
doShowDebugMessages={doShowDebugMessages}
/>
</View>
);
};
export default WebViewLeafletView;
================================================
FILE: WebViewLeaflet/assets/index.html
================================================
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><style>.leaflet-image-layer,.leaflet-layer,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane,.leaflet-pane>canvas,.leaflet-pane>svg,.leaflet-tile,.leaflet-tile-container,.leaflet-zoom-box{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-tile::-moz-selection{background:0 0}.leaflet-tile::selection{background:0 0}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-control-layers label,.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-overlay-pane svg,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer{max-width:none!important;max-height:none!important}.leaflet-container.leaflet-touch-zoom{touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{touch-action:none}.leaflet-container{-webkit-tap-highlight-color:transparent}.leaflet-container a{-webkit-tap-highlight-color:rgba(51,181,229,.4);color:#0078a8}.leaflet-tile{-webkit-filter:inherit;filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;box-sizing:border-box;z-index:800}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-pane{z-index:400}.leaflet-map-pane svg,.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:auto}.leaflet-bottom,.leaflet-top{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-tile{will-change:opacity}.leaflet-fade-anim .leaflet-popup{opacity:0;-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{-webkit-transform-origin:0 0;transform-origin:0 0}.leaflet-zoom-anim .leaflet-zoom-animated{will-change:transform;-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1),-webkit-transform .25s cubic-bezier(0,0,.25,1)}.leaflet-pan-anim .leaflet-tile,.leaflet-zoom-anim .leaflet-tile{-webkit-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:-webkit-grab;cursor:grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-control,.leaflet-popup-pane{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:-webkit-grabbing;cursor:grabbing}.leaflet-image-layer,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-image-layer.leaflet-interactive,.leaflet-marker-icon.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive,svg.leaflet-image-layer.leaflet-interactive path{pointer-events:auto}.leaflet-container{background:#ddd;outline:0}.leaflet-container a.leaflet-active{outline:2px solid orange}.leaflet-zoom-box{border:2px dotted #38f;background:rgba(255,255,255,.5)}.leaflet-container{font:12px/1.5 Helvetica Neue,Arial,Helvetica,sans-serif}.leaflet-bar{box-shadow:0 1px 5px rgba(0,0,0,.65);border-radius:4px}.leaflet-bar a,.leaflet-bar a:hover{background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;text-align:center;text-decoration:none;color:#000}.leaflet-bar a:hover{display:block;background-color:#f4f4f4}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50% 50%;background-repeat:no-repeat;display:block}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:none}.leaflet-bar a.leaflet-disabled{cursor:default;background-color:#f4f4f4;color:#bbb}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.leaflet-touch .leaflet-bar a:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.leaflet-control-zoom-in,.leaflet-control-zoom-out{font:700 18px Lucida Console,Monaco,monospace;text-indent:1px}.leaflet-touch .leaflet-control-zoom-in,.leaflet-touch .leaflet-control-zoom-out{font-size:22px}.leaflet-control-layers{box-shadow:0 1px 5px rgba(0,0,0,.4);background:#fff;border-radius:5px}.leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAQAAAADQ4RFAAACf0lEQVR4AY1UM3gkARTePdvdoTxXKc+qTl3aU5U6b2Kbkz3Gtq3Zw6ziLGNPzrYx7946Tr6/ee/XeCQ4D3ykPtL5tHno4n0d/h3+xfuWHGLX81cn7r0iTNzjr7LrlxCqPtkbTQEHeqOrTy4Yyt3VCi/IOB0v7rVC7q45Q3Gr5K6jt+3Gl5nCoDD4MtO+j96Wu8atmhGqcNGHObuf8OM/x3AMx38+4Z2sPqzCxRFK2aF2e5Jol56XTLyggAMTL56XOMoS1W4pOyjUcGGQdZxU6qRh7B9Zp+PfpOFlqt0zyDZckPi1ttmIp03jX8gyJ8a/PG2yutpS/Vol7peZIbZcKBAEEheEIAgFbDkz5H6Zrkm2hVWGiXKiF4Ycw0RWKdtC16Q7qe3X4iOMxruonzegJzWaXFrU9utOSsLUmrc0YjeWYjCW4PDMADElpJSSQ0vQvA1Tm6/JlKnqFs1EGyZiFCqnRZTEJJJiKRYzVYzJck2Rm6P4iH+cmSY0YzimYa8l0EtTODFWhcMIMVqdsI2uiTvKmTisIDHJ3od5GILVhBCarCfVRmo4uTjkhrhzkiBV7SsaqS+TzrzM1qpGGUFt28pIySQHR6h7F6KSwGWm97ay+Z+ZqMcEjEWebE7wxCSQwpkhJqoZA5ivCdZDjJepuJ9IQjGGUmuXJdBFUygxVqVsxFsLMbDe8ZbDYVCGKxs+W080max1hFCarCfV+C1KATwcnvE9gRRuMP2prdbWGowm1KB1y+zwMMENkM755cJ2yPDtqhTI6ED1M/82yIDtC/4j4BijjeObflpO9I9MwXTCsSX8jWAFeHr05WoLTJ5G8IQVS/7vwR6ohirYM7f6HzYpogfS3R2OAAAAAElFTkSuQmCC);width:36px;height:36px}.leaflet-retina .leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAQAAABvcdNgAAAEsklEQVR4AWL4TydIhpZK1kpWOlg0w3ZXP6D2soBtG42jeI6ZmQTHzAxiTbSJsYLjO9HhP+WOmcuhciVnmHVQcJnp7DFvScowZorad/+V/fVzMdMT2g9Cv9guXGv/7pYOrXh2U+RRR3dSd9JRx6bIFc/ekqHI29JC6pJ5ZEh1yWkhkbcFeSjxgx3L2m1cb1C7bceyxA+CNjT/Ifff+/kDk2u/w/33/IeCMOSaWZ4glosqT3DNnNZQ7Cs58/3Ce5HL78iZH/vKVIaYlqzfdLu8Vi7dnvUbEza5Idt36tquZFldl6N5Z/POLof0XLK61mZCmJSWjVF9tEjUluu74IUXvgttuVIHE7YxSkaYhJZam7yiM9Pv82JYfl9nptxZaxMJE4YSPty+vF0+Y2up9d3wwijfjZbabqm/3bZ9ecKHsiGmRflnn1MW4pjHf9oLufyn2z3y1D6n8g8TZhxyzipLNPnAUpsOiuWimg52psrTZYnOWYNDTMuWBWa0tJb4rgq1UvmutpaYEbZlwU3CLJm/ayYjHW5/h7xWLn9Hh1vepDkyf7dE7MtT5LR4e7yYpHrkhOUpEfssBLq2pPhAqoSWKUkk7EDqkmK6RrCEzqDjhNDWNE+XSMvkJRDWlZTmCW0l0PHQGRZY5t1L83kT0Y3l2SItk5JAWHl2dCOBm+fPu3fo5/3v61RMCO9Jx2EEYYhb0rmNQMX/vm7gqOEJLcXTGw3CAuRNeyaPWwjR8PRqKQ1PDA/dpv+on9Shox52WFnx0KY8onHayrJzm87i5h9xGw/tfkev0jGsQizqezUKjk12hBMKJ4kbCqGPVNXudyyrShovGw5CgxsRICxF6aRmSjlBnHRzg7Gx8fKqEubI2rahQYdR1YgDIRQO7JvQyD52hoIQx0mxa0ODtW2Iozn1le2iIRdzwWewedyZzewidueOGqlsn1MvcnQpuVwLGG3/IR1hIKxCjelIDZ8ldqWz25jWAsnldEnK0Zxro19TGVb2ffIZEsIO89EIEDvKMPrzmBOQcKQ+rroye6NgRRxqR4U8EAkz0CL6uSGOm6KQCdWjvjRiSP1BPalCRS5iQYiEIvxuBMJEWgzSoHADcVMuN7IuqqTeyUPq22qFimFtxDyBBJEwNyt6TM88blFHao/6tWWhuuOM4SAK4EI4QmFHA+SEyWlp4EQoJ13cYGzMu7yszEIBOm2rVmHUNqwAIQabISNMRstmdhNWcFLsSm+0tjJH1MdRxO5Nx0WDMhCtgD6OKgZeljJqJKc9po8juskR9XN0Y1lZ3mWjLR9JCO1jRDMd0fpYC2VnvjBSEFg7wBENc0R9HFlb0xvF1+TBEpF68d+DHR6IOWVv2BECtxo46hOFUBd/APU57WIoEwJhIi2CdpyZX0m93BZicktMj1AS9dClteUFAUNUIEygRZCtik5zSxI9MubTBH1GOiHsiLJ3OCoSZkILa9PxiN0EbvhsAo8tdAf9Seepd36lGWHmtNANTv5Jd0z4QYyeo/UEJqxKRpg5LZx6btLPsOaEmdMyxYdlc8LMaJnikDlhclqmPiQnTEpLUIZEwkRagjYkEibQErwhkTAKCLQEbUgkzJQWc/0PstHHcfEdQ+UAAAAASUVORK5CYII=);background-size:26px 26px}.leaflet-touch .leaflet-control-layers-toggle{width:44px;height:44px}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{padding:6px 10px 6px 6px;color:#333;background:#fff}.leaflet-control-layers-scrollbar{overflow-y:scroll;overflow-x:hidden;padding-right:5px}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;margin:5px -10px 5px -6px}.leaflet-default-icon-path{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=)}.leaflet-container .leaflet-control-attribution{background:#fff;background:rgba(255,255,255,.7);margin:0}.leaflet-control-attribution{padding:0 5px;color:#333}.leaflet-control-scale-line{color:#333;border:2px solid #777;border-top:none;line-height:1.1;padding:2px 5px 1px;font-size:11px;white-space:nowrap;overflow:hidden;box-sizing:border-box;background:#fff;background:rgba(255,255,255,.5)}.leaflet-control-attribution a{text-decoration:none}.leaflet-control-attribution a:hover{text-decoration:underline}.leaflet-container .leaflet-control-attribution,.leaflet-container .leaflet-control-scale{font-size:11px}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #777;border-bottom:none;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-touch .leaflet-bar,.leaflet-touch .leaflet-control-attribution,.leaflet-touch .leaflet-control-layers{box-shadow:none}.leaflet-touch .leaflet-bar,.leaflet-touch .leaflet-control-layers{border:2px solid rgba(0,0,0,.2);background-clip:padding-box}.leaflet-popup{position:absolute;text-align:center;margin-bottom:20px}.leaflet-popup-content-wrapper{padding:1px;text-align:left;border-radius:12px}.leaflet-popup-content{margin:13px 19px;line-height:1.4}.leaflet-popup-content p{margin:18px 0}.leaflet-popup-tip-container{width:40px;height:20px;position:absolute;left:50%;margin-left:-20px;overflow:hidden;pointer-events:none}.leaflet-popup-tip{width:17px;height:17px;padding:1px;margin:-10px auto 0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:#fff;color:#333;box-shadow:0 3px 14px rgba(0,0,0,.4)}.leaflet-container a.leaflet-popup-close-button{position:absolute;top:0;right:0;padding:4px 4px 0 0;border:0;text-align:center;width:18px;height:14px;font:16px/14px Tahoma,Verdana,sans-serif;color:#c3c3c3;text-decoration:none;font-weight:700;background:0 0}.leaflet-container a.leaflet-popup-close-button:hover{color:#999}.leaflet-popup-scrolled{overflow:auto;border-bottom:1px solid #ddd;border-top:1px solid #ddd}.leaflet-oldie .leaflet-popup-content-wrapper{zoom:1}.leaflet-oldie .leaflet-popup-tip{width:24px;margin:0 auto;-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";filter:progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678,M12=0.70710678,M21=-0.70710678,M22=0.70710678)}.leaflet-oldie .leaflet-popup-tip-container{margin-top:-1px}.leaflet-oldie .leaflet-control-layers,.leaflet-oldie .leaflet-control-zoom,.leaflet-oldie .leaflet-popup-content-wrapper,.leaflet-oldie .leaflet-popup-tip{border:1px solid #999}.leaflet-div-icon{background:#fff;border:1px solid #666}.leaflet-tooltip{position:absolute;padding:6px;background-color:#fff;border:1px solid #fff;border-radius:3px;color:#222;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;box-shadow:0 1px 3px rgba(0,0,0,.4)}.leaflet-tooltip.leaflet-clickable{cursor:pointer;pointer-events:auto}.leaflet-tooltip-bottom:before,.leaflet-tooltip-left:before,.leaflet-tooltip-right:before,.leaflet-tooltip-top:before{position:absolute;pointer-events:none;border:6px solid transparent;background:0 0;content:""}.leaflet-tooltip-bottom{margin-top:6px}.leaflet-tooltip-top{margin-top:-6px}.leaflet-tooltip-bottom:before{left:50%}.leaflet-tooltip-top:before{left:50%;margin-left:-6px;bottom:0;margin-bottom:-12px;border-top-color:#fff}.leaflet-tooltip-bottom:before{top:0;margin-top:-12px;margin-left:-6px;border-bottom-color:#fff}.leaflet-tooltip-left{margin-left:-6px}.leaflet-tooltip-right{margin-left:6px}.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{top:50%;margin-top:-6px}.leaflet-tooltip-left:before{right:0;margin-right:-12px;border-left-color:#fff}.leaflet-tooltip-right:before{left:0;margin-left:-12px;border-right-color:#fff}.marker-cluster-small{background-color:rgba(181,226,140,.6)}.marker-cluster-small div{background-color:rgba(110,204,57,.6)}.marker-cluster-medium{background-color:rgba(241,211,87,.6)}.marker-cluster-medium div{background-color:rgba(240,194,12,.6)}.marker-cluster-large{background-color:rgba(253,156,115,.6)}.marker-cluster-large div{background-color:rgba(241,128,23,.6)}.leaflet-oldie .marker-cluster-small{background-color:#b5e28c}.leaflet-oldie .marker-cluster-small div{background-color:#6ecc39}.leaflet-oldie .marker-cluster-medium{background-color:#f1d357}.leaflet-oldie .marker-cluster-medium div{background-color:#f0c20c}.leaflet-oldie .marker-cluster-large{background-color:#fd9c73}.leaflet-oldie .marker-cluster-large div{background-color:#f18017}.marker-cluster{background-clip:padding-box;border-radius:20px}.marker-cluster div{width:30px;height:30px;margin-left:5px;margin-top:5px;text-align:center;border-radius:15px;font:12px Helvetica Neue,Arial,Helvetica,sans-serif}.marker-cluster span{line-height:30px}.leaflet-cluster-anim .leaflet-marker-icon,.leaflet-cluster-anim .leaflet-marker-shadow{-webkit-transition:opacity .3s ease-in,-webkit-transform .3s ease-out;transition:transform .3s ease-out,opacity .3s ease-in;transition:transform .3s ease-out,opacity .3s ease-in,-webkit-transform .3s ease-out}.leaflet-cluster-spider-leg{-webkit-transition:-webkit-stroke-dashoffset .3s ease-out,-webkit-stroke-opacity .3s ease-in;-webkit-transition:stroke-dashoffset .3s ease-out,stroke-opacity .3s ease-in;transition:stroke-dashoffset .3s ease-out,stroke-opacity .3s ease-in}</style><style>@-webkit-keyframes bounce{0%,to{-webkit-transform:scaleY(.8) translateY(10px);transform:scaleY(.8) translateY(10px)}45%,55%{-webkit-transform:scaleX(.8) translateY(-27px);transform:scaleX(.8) translateY(-27px)}50%{-webkit-transform:scaleX(.8) translateY(-30px);transform:scaleX(.8) translateY(-30px)}}@keyframes bounce{0%,to{-webkit-transform:scaleY(.8) translateY(10px);transform:scaleY(.8) translateY(10px)}45%,55%{-webkit-transform:scaleX(.8) translateY(-27px);transform:scaleX(.8) translateY(-27px)}50%{-webkit-transform:scaleX(.8) translateY(-30px);transform:scaleX(.8) translateY(-30px)}}@-webkit-keyframes fade{0%,to{opacity:.1}50%{opacity:1}}@keyframes fade{0%,to{opacity:.1}50%{opacity:1}}@-webkit-keyframes pulse{0%,to{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.25);transform:scale(1.25)}}@keyframes pulse{0%,to{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(1.25);transform:scale(1.25)}}@-webkit-keyframes jump{0%{-webkit-transform:none;transform:none}50%{-webkit-transform:translateY(-2em);transform:translateY(-2em)}}@keyframes jump{0%{-webkit-transform:none;transform:none}50%{-webkit-transform:translateY(-2em);transform:translateY(-2em)}}@-webkit-keyframes waggle{0%{-webkit-transform:none;transform:none}50%{-webkit-transform:rotate(-20deg) scale(1.2);transform:rotate(-20deg) scale(1.2)}60%{-webkit-transform:rotate(25deg) scale(1.2);transform:rotate(25deg) scale(1.2)}67.5%{-webkit-transform:rotate(-15deg) scale(1.2);transform:rotate(-15deg) scale(1.2)}75%{-webkit-transform:rotate(15deg) scale(1.2);transform:rotate(15deg) scale(1.2)}82.5%{-webkit-transform:rotate(-12deg) scale(1.2);transform:rotate(-12deg) scale(1.2)}85%{-webkit-transform:rotate(0) scale(1.2);transform:rotate(0) scale(1.2)}to{-webkit-transform:rotate(0) scale(1);transform:rotate(0) scale(1)}}@keyframes waggle{0%{-webkit-transform:none;transform:none}50%{-webkit-transform:rotate(-20deg) scale(1.2);transform:rotate(-20deg) scale(1.2)}60%{-webkit-transform:rotate(25deg) scale(1.2);transform:rotate(25deg) scale(1.2)}67.5%{-webkit-transform:rotate(-15deg) scale(1.2);transform:rotate(-15deg) scale(1.2)}75%{-webkit-transform:rotate(15deg) scale(1.2);transform:rotate(15deg) scale(1.2)}82.5%{-webkit-transform:rotate(-12deg) scale(1.2);transform:rotate(-12deg) scale(1.2)}85%{-webkit-transform:rotate(0) scale(1.2);transform:rotate(0) scale(1.2)}to{-webkit-transform:rotate(0) scale(1);transform:rotate(0) scale(1)}}@-webkit-keyframes spin{50%{-webkit-transform:rotate(-20deg);transform:rotate(-20deg);-webkit-animation-timing-function:ease;animation-timing-function:ease}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes spin{50%{-webkit-transform:rotate(-20deg);transform:rotate(-20deg);-webkit-animation-timing-function:ease;animation-timing-function:ease}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes beat{to{-webkit-transform:scale(.7);transform:scale(.7)}}@keyframes beat{to{-webkit-transform:scale(.7);transform:scale(.7)}}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.marker{background-color:transparent;width:100%;height:100%;position:relative}.clearMarkerContainer{background-color:transparent;display:flex;justify-content:center}.animationContainer{display:flex;justify-content:center;align-items:flex-end}</style></head><body style="display:flex;height:100vh;margin:0"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root" style="flex:1;background-color:#6495ed"></div><script>!function(i){function e(e){for(var t,r,n=e[0],o=e[1],u=e[2],l=0,f=[];l<n.length;l++)r=n[l],Object.prototype.hasOwnProperty.call(p,r)&&p[r]&&f.push(p[r][0]),p[r]=0;for(t in o)Object.prototype.hasOwnProperty.call(o,t)&&(i[t]=o[t]);for(s&&s(e);f.length;)f.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,t=0;t<c.length;t++){for(var r=c[t],n=!0,o=1;o<r.length;o++){var u=r[o];0!==p[u]&&(n=!1)}n&&(c.splice(t--,1),e=l(l.s=r[0]))}return e}var r={},p={1:0},c=[];function l(e){if(r[e])return r[e].exports;var t=r[e]={i:e,l:!1,exports:{}};return i[e].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=i,l.c=r,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(t,e){if(1&e&&(t=l(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)l.d(r,n,function(e){return t[e]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="/";var t=this.webpackJsonphtml=this.webpackJsonphtml||[],n=t.push.bind(t);t.push=e,t=t.slice();for(var o=0;o<t.length;o++)e(t[o]);var s=n;a()}([])</script><script>(this.webpackJsonphtml=this.webpackJsonphtml||[]).push([[2],[function(t,e,n){"use strict";t.exports=n(51)},function(t,e,n){"use strict";function i(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}n.d(e,"a",function(){return i})},function(t,e,n){!function(t){"use strict";var e=Object.freeze;function n(t){var e,n,i,o;for(n=1,i=arguments.length;n<i;n++)for(e in o=arguments[n])t[e]=o[e];return t}Object.freeze=function(t){return t};var i=Object.create||function(){function t(){}return function(e){return t.prototype=e,new t}}();function o(t,e){var n=Array.prototype.slice;if(t.bind)return t.bind.apply(t,n.call(arguments,1));var i=n.call(arguments,2);return function(){return t.apply(e,i.length?i.concat(n.call(arguments)):arguments)}}var r=0;function a(t){return t._leaflet_id=t._leaflet_id||++r,t._leaflet_id}function s(t,e,n){var i,o,r,a;return a=function(){i=!1,o&&(r.apply(n,o),o=!1)},r=function(){i?o=arguments:(t.apply(n,arguments),setTimeout(a,e),i=!0)}}function l(t,e,n){var i=e[1],o=e[0],r=i-o;return t===i&&n?t:((t-o)%r+r)%r+o}function u(){return!1}function c(t,e){var n=Math.pow(10,void 0===e?6:e);return Math.round(t*n)/n}function h(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function f(t){return h(t).split(/\s+/)}function d(t,e){for(var n in t.hasOwnProperty("options")||(t.options=t.options?i(t.options):{}),e)t.options[n]=e[n];return t.options}function p(t,e,n){var i=[];for(var o in t)i.push(encodeURIComponent(n?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(e&&-1!==e.indexOf("?")?"&":"?")+i.join("&")}var m=/\{ *([\w_-]+) *\}/g;function _(t,e){return t.replace(m,function(t,n){var i=e[n];if(void 0===i)throw new Error("No value provided for variable "+t);return"function"==typeof i&&(i=i(e)),i})}var g=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function v(t,e){for(var n=0;n<t.length;n++)if(t[n]===e)return n;return-1}var y="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function b(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var w=0;function x(t){var e=+new Date,n=Math.max(0,16-(e-w));return w=e+n,window.setTimeout(t,n)}var E=window.requestAnimationFrame||b("RequestAnimationFrame")||x,k=window.cancelAnimationFrame||b("CancelAnimationFrame")||b("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function C(t,e,n){if(!n||E!==x)return E.call(window,o(t,e));t.call(e)}function T(t){t&&k.call(window,t)}var P=(Object.freeze||Object)({freeze:e,extend:n,create:i,bind:o,lastId:r,stamp:a,throttle:s,wrapNum:l,falseFn:u,formatNum:c,trim:h,splitWords:f,setOptions:d,getParamString:p,template:_,isArray:g,indexOf:v,emptyImageUrl:y,requestFn:E,cancelFn:k,requestAnimFrame:C,cancelAnimFrame:T});function S(){}S.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},o=e.__super__=this.prototype,r=i(o);for(var a in r.constructor=e,e.prototype=r,this)this.hasOwnProperty(a)&&"prototype"!==a&&"__super__"!==a&&(e[a]=this[a]);return t.statics&&(n(e,t.statics),delete t.statics),t.includes&&(function(t){if("undefined"!=typeof L&&L&&L.Mixin){t=g(t)?t:[t];for(var e=0;e<t.length;e++)t[e]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",(new Error).stack)}}(t.includes),n.apply(null,[r].concat(t.includes)),delete t.includes),r.options&&(t.options=n(i(r.options),t.options)),n(r,t),r._initHooks=[],r.callInitHooks=function(){if(!this._initHooksCalled){o.callInitHooks&&o.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=r._initHooks.length;t<e;t++)r._initHooks[t].call(this)}},e},S.include=function(t){return n(this.prototype,t),this},S.mergeOptions=function(t){return n(this.prototype.options,t),this},S.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),n="function"==typeof t?t:function(){this[t].apply(this,e)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(n),this};var O={on:function(t,e,n){if("object"==typeof t)for(var i in t)this._on(i,t[i],e);else for(var o=0,r=(t=f(t)).length;o<r;o++)this._on(t[o],e,n);return this},off:function(t,e,n){if(t)if("object"==typeof t)for(var i in t)this._off(i,t[i],e);else for(var o=0,r=(t=f(t)).length;o<r;o++)this._off(t[o],e,n);else delete this._events;return this},_on:function(t,e,n){this._events=this._events||{};var i=this._events[t];i||(i=[],this._events[t]=i),n===this&&(n=void 0);for(var o={fn:e,ctx:n},r=i,a=0,s=r.length;a<s;a++)if(r[a].fn===e&&r[a].ctx===n)return;r.push(o)},_off:function(t,e,n){var i,o,r;if(this._events&&(i=this._events[t]))if(e){if(n===this&&(n=void 0),i)for(o=0,r=i.length;o<r;o++){var a=i[o];if(a.ctx===n&&a.fn===e)return a.fn=u,this._firingCount&&(this._events[t]=i=i.slice()),void i.splice(o,1)}}else{for(o=0,r=i.length;o<r;o++)i[o].fn=u;delete this._events[t]}},fire:function(t,e,i){if(!this.listens(t,i))return this;var o=n({},e,{type:t,target:this,sourceTarget:e&&e.sourceTarget||this});if(this._events){var r=this._events[t];if(r){this._firingCount=this._firingCount+1||1;for(var a=0,s=r.length;a<s;a++){var l=r[a];l.fn.call(l.ctx||this,o)}this._firingCount--}}return i&&this._propagateEvent(o),this},listens:function(t,e){var n=this._events&&this._events[t];if(n&&n.length)return!0;if(e)for(var i in this._eventParents)if(this._eventParents[i].listens(t,e))return!0;return!1},once:function(t,e,n){if("object"==typeof t){for(var i in t)this.once(i,t[i],e);return this}var r=o(function(){this.off(t,e,n).off(t,r,n)},this);return this.on(t,e,n).on(t,r,n)},addEventParent:function(t){return this._eventParents=this._eventParents||{},this._eventParents[a(t)]=t,this},removeEventParent:function(t){return this._eventParents&&delete this._eventParents[a(t)],this},_propagateEvent:function(t){for(var e in this._eventParents)this._eventParents[e].fire(t.type,n({layer:t.target,propagatedFrom:t.target},t),!0)}};O.addEventListener=O.on,O.removeEventListener=O.clearAllEventListeners=O.off,O.addOneTimeEventListener=O.once,O.fireEvent=O.fire,O.hasEventListeners=O.listens;var M=S.extend(O);function z(t,e,n){this.x=n?Math.round(t):t,this.y=n?Math.round(e):e}var A=Math.trunc||function(t){return t>0?Math.floor(t):Math.ceil(t)};function j(t,e,n){return t instanceof z?t:g(t)?new z(t[0],t[1]):null==t?t:"object"==typeof t&&"x"in t&&"y"in t?new z(t.x,t.y):new z(t,e,n)}function I(t,e){if(t)for(var n=e?[t,e]:t,i=0,o=n.length;i<o;i++)this.extend(n[i])}function N(t,e){return!t||t instanceof I?t:new I(t,e)}function R(t,e){if(t)for(var n=e?[t,e]:t,i=0,o=n.length;i<o;i++)this.extend(n[i])}function B(t,e){return t instanceof R?t:new R(t,e)}function Z(t,e,n){if(isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=+t,this.lng=+e,void 0!==n&&(this.alt=+n)}function D(t,e,n){return t instanceof Z?t:g(t)&&"object"!=typeof t[0]?3===t.length?new Z(t[0],t[1],t[2]):2===t.length?new Z(t[0],t[1]):null:null==t?t:"object"==typeof t&&"lat"in t?new Z(t.lat,"lng"in t?t.lng:t.lon,t.alt):void 0===e?null:new Z(t,e,n)}z.prototype={clone:function(){return new z(this.x,this.y)},add:function(t){return this.clone()._add(j(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(j(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},scaleBy:function(t){return new z(this.x*t.x,this.y*t.y)},unscaleBy:function(t){return new z(this.x/t.x,this.y/t.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=A(this.x),this.y=A(this.y),this},distanceTo:function(t){var e=(t=j(t)).x-this.x,n=t.y-this.y;return Math.sqrt(e*e+n*n)},equals:function(t){return(t=j(t)).x===this.x&&t.y===this.y},contains:function(t){return t=j(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+c(this.x)+", "+c(this.y)+")"}},I.prototype={extend:function(t){return t=j(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new z((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new z(this.min.x,this.max.y)},getTopRight:function(){return new z(this.max.x,this.min.y)},getTopLeft:function(){return this.min},getBottomRight:function(){return this.max},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,n;return(t="number"==typeof t[0]||t instanceof z?j(t):N(t))instanceof I?(e=t.min,n=t.max):e=n=t,e.x>=this.min.x&&n.x<=this.max.x&&e.y>=this.min.y&&n.y<=this.max.y},intersects:function(t){t=N(t);var e=this.min,n=this.max,i=t.min,o=t.max,r=o.x>=e.x&&i.x<=n.x,a=o.y>=e.y&&i.y<=n.y;return r&&a},overlaps:function(t){t=N(t);var e=this.min,n=this.max,i=t.min,o=t.max,r=o.x>e.x&&i.x<n.x,a=o.y>e.y&&i.y<n.y;return r&&a},isValid:function(){return!(!this.min||!this.max)}},R.prototype={extend:function(t){var e,n,i=this._southWest,o=this._northEast;if(t instanceof Z)e=t,n=t;else{if(!(t instanceof R))return t?this.extend(D(t)||B(t)):this;if(e=t._southWest,n=t._northEast,!e||!n)return this}return i||o?(i.lat=Math.min(e.lat,i.lat),i.lng=Math.min(e.lng,i.lng),o.lat=Math.max(n.lat,o.lat),o.lng=Math.max(n.lng,o.lng)):(this._southWest=new Z(e.lat,e.lng),this._northEast=new Z(n.lat,n.lng)),this},pad:function(t){var e=this._southWest,n=this._northEast,i=Math.abs(e.lat-n.lat)*t,o=Math.abs(e.lng-n.lng)*t;return new R(new Z(e.lat-i,e.lng-o),new Z(n.lat+i,n.lng+o))},getCenter:function(){return new Z((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new Z(this.getNorth(),this.getWest())},getSouthEast:function(){return new Z(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof Z||"lat"in t?D(t):B(t);var e,n,i=this._southWest,o=this._northEast;return t instanceof R?(e=t.getSouthWest(),n=t.getNorthEast()):e=n=t,e.lat>=i.lat&&n.lat<=o.lat&&e.lng>=i.lng&&n.lng<=o.lng},intersects:function(t){t=B(t);var e=this._southWest,n=this._northEast,i=t.getSouthWest(),o=t.getNorthEast(),r=o.lat>=e.lat&&i.lat<=n.lat,a=o.lng>=e.lng&&i.lng<=n.lng;return r&&a},overlaps:function(t){t=B(t);var e=this._southWest,n=this._northEast,i=t.getSouthWest(),o=t.getNorthEast(),r=o.lat>e.lat&&i.lat<n.lat,a=o.lng>e.lng&&i.lng<n.lng;return r&&a},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t,e){return!!t&&(t=B(t),this._southWest.equals(t.getSouthWest(),e)&&this._northEast.equals(t.getNorthEast(),e))},isValid:function(){return!(!this._southWest||!this._northEast)}},Z.prototype={equals:function(t,e){return!!t&&(t=D(t),Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng))<=(void 0===e?1e-9:e))},toString:function(t){return"LatLng("+c(this.lat,t)+", "+c(this.lng,t)+")"},distanceTo:function(t){return F.distance(this,D(t))},wrap:function(){return F.wrapLatLng(this)},toBounds:function(t){var e=180*t/40075017,n=e/Math.cos(Math.PI/180*this.lat);return B([this.lat-e,this.lng-n],[this.lat+e,this.lng+n])},clone:function(){return new Z(this.lat,this.lng,this.alt)}};var U={latLngToPoint:function(t,e){var n=this.projection.project(t),i=this.scale(e);return this.transformation._transform(n,i)},pointToLatLng:function(t,e){var n=this.scale(e),i=this.transformation.untransform(t,n);return this.projection.unproject(i)},project:function(t){return this.projection.project(t)},unproject:function(t){return this.projection.unproject(t)},scale:function(t){return 256*Math.pow(2,t)},zoom:function(t){return Math.log(t/256)/Math.LN2},getProjectedBounds:function(t){if(this.infinite)return null;var e=this.projection.bounds,n=this.scale(t);return new I(this.transformation.transform(e.min,n),this.transformation.transform(e.max,n))},infinite:!1,wrapLatLng:function(t){var e=this.wrapLng?l(t.lng,this.wrapLng,!0):t.lng;return new Z(this.wrapLat?l(t.lat,this.wrapLat,!0):t.lat,e,t.alt)},wrapLatLngBounds:function(t){var e=t.getCenter(),n=this.wrapLatLng(e),i=e.lat-n.lat,o=e.lng-n.lng;if(0===i&&0===o)return t;var r=t.getSouthWest(),a=t.getNorthEast();return new R(new Z(r.lat-i,r.lng-o),new Z(a.lat-i,a.lng-o))}},F=n({},U,{wrapLng:[-180,180],R:6371e3,distance:function(t,e){var n=Math.PI/180,i=t.lat*n,o=e.lat*n,r=Math.sin((e.lat-t.lat)*n/2),a=Math.sin((e.lng-t.lng)*n/2),s=r*r+Math.cos(i)*Math.cos(o)*a*a,l=2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s));return this.R*l}}),W={R:6378137,MAX_LATITUDE:85.0511287798,project:function(t){var e=Math.PI/180,n=this.MAX_LATITUDE,i=Math.max(Math.min(n,t.lat),-n),o=Math.sin(i*e);return new z(this.R*t.lng*e,this.R*Math.log((1+o)/(1-o))/2)},unproject:function(t){var e=180/Math.PI;return new Z((2*Math.atan(Math.exp(t.y/this.R))-Math.PI/2)*e,t.x*e/this.R)},bounds:function(){var t=6378137*Math.PI;return new I([-t,-t],[t,t])}()};function H(t,e,n,i){if(g(t))return this._a=t[0],this._b=t[1],this._c=t[2],void(this._d=t[3]);this._a=t,this._b=e,this._c=n,this._d=i}function V(t,e,n,i){return new H(t,e,n,i)}H.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new z((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}};var G=n({},F,{code:"EPSG:3857",projection:W,transformation:function(){var t=.5/(Math.PI*W.R);return V(t,.5,-t,.5)}()}),q=n({},G,{code:"EPSG:900913"});function K(t){return document.createElementNS("http://www.w3.org/2000/svg",t)}function Q(t,e){var n,i,o,r,a,s,l="";for(n=0,o=t.length;n<o;n++){for(i=0,r=(a=t[n]).length;i<r;i++)l+=(i?"L":"M")+(s=a[i]).x+" "+s.y;l+=e?Tt?"z":"x":""}return l||"M0 0"}var Y=document.documentElement.style,J="ActiveXObject"in window,X=J&&!document.addEventListener,$="msLaunchUri"in navigator&&!("documentMode"in document),tt=St("webkit"),et=St("android"),nt=St("android 2")||St("android 3"),it=parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1],10),ot=et&&St("Google")&&it<537&&!("AudioNode"in window),rt=!!window.opera,at=St("chrome"),st=St("gecko")&&!tt&&!rt&&!J,lt=!at&&St("safari"),ut=St("phantom"),ct="OTransition"in Y,ht=0===navigator.platform.indexOf("Win"),ft=J&&"transition"in Y,dt="WebKitCSSMatrix"in window&&"m11"in new window.WebKitCSSMatrix&&!nt,pt="MozPerspective"in Y,mt=!window.L_DISABLE_3D&&(ft||dt||pt)&&!ct&&!ut,_t="undefined"!=typeof orientation||St("mobile"),gt=_t&&tt,vt=_t&&dt,yt=!window.PointerEvent&&window.MSPointerEvent,bt=!(tt||!window.PointerEvent&&!yt),wt=!window.L_NO_TOUCH&&(bt||"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch),xt=_t&&rt,Lt=_t&&st,Et=(window.devicePixelRatio||window.screen.deviceXDPI/window.screen.logicalXDPI)>1,kt=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("testPassiveEventSupport",u,e),window.removeEventListener("testPassiveEventSupport",u,e)}catch(t){}return t},Ct=!!document.createElement("canvas").getContext,Tt=!(!document.createElementNS||!K("svg").createSVGRect),Pt=!Tt&&function(){try{var t=document.createElement("div");t.innerHTML='<v:shape adj="1"/>';var e=t.firstChild;return e.style.behavior="url(#default#VML)",e&&"object"==typeof e.adj}catch(t){return!1}}();function St(t){return navigator.userAgent.toLowerCase().indexOf(t)>=0}var Ot=(Object.freeze||Object)({ie:J,ielt9:X,edge:$,webkit:tt,android:et,android23:nt,androidStock:ot,opera:rt,chrome:at,gecko:st,safari:lt,phantom:ut,opera12:ct,win:ht,ie3d:ft,webkit3d:dt,gecko3d:pt,any3d:mt,mobile:_t,mobileWebkit:gt,mobileWebkit3d:vt,msPointer:yt,pointer:bt,touch:wt,mobileOpera:xt,mobileGecko:Lt,retina:Et,passiveEvents:kt,canvas:Ct,svg:Tt,vml:Pt}),Mt=yt?"MSPointerDown":"pointerdown",zt=yt?"MSPointerMove":"pointermove",At=yt?"MSPointerUp":"pointerup",jt=yt?"MSPointerCancel":"pointercancel",It=["INPUT","SELECT","OPTION"],Nt={},Rt=!1,Bt=0;function Zt(t,e,n,i){return"touchstart"===e?function(t,e,n){var i=o(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(It.indexOf(t.target.tagName)<0))return;Ne(t)}Wt(t,e)});t["_leaflet_touchstart"+n]=i,t.addEventListener(Mt,i,!1),Rt||(document.documentElement.addEventListener(Mt,Dt,!0),document.documentElement.addEventListener(zt,Ut,!0),document.documentElement.addEventListener(At,Ft,!0),document.documentElement.addEventListener(jt,Ft,!0),Rt=!0)}(t,n,i):"touchmove"===e?function(t,e,n){var i=function(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&Wt(t,e)};t["_leaflet_touchmove"+n]=i,t.addEventListener(zt,i,!1)}(t,n,i):"touchend"===e&&function(t,e,n){var i=function(t){Wt(t,e)};t["_leaflet_touchend"+n]=i,t.addEventListener(At,i,!1),t.addEventListener(jt,i,!1)}(t,n,i),this}function Dt(t){Nt[t.pointerId]=t,Bt++}function Ut(t){Nt[t.pointerId]&&(Nt[t.pointerId]=t)}function Ft(t){delete Nt[t.pointerId],Bt--}function Wt(t,e){for(var n in t.touches=[],Nt)t.touches.push(Nt[n]);t.changedTouches=[t],e(t)}var Ht=yt?"MSPointerDown":bt?"pointerdown":"touchstart",Vt=yt?"MSPointerUp":bt?"pointerup":"touchend",Gt="_leaflet_";function qt(t,e,n){var i,o,r=!1,a=250;function s(t){var e;if(bt){if(!$||"mouse"===t.pointerType)return;e=Bt}else e=t.touches.length;if(!(e>1)){var n=Date.now(),s=n-(i||n);o=t.touches?t.touches[0]:t,r=s>0&&s<=a,i=n}}function l(t){if(r&&!o.cancelBubble){if(bt){if(!$||"mouse"===t.pointerType)return;var n,a,s={};for(a in o)n=o[a],s[a]=n&&n.bind?n.bind(o):n;o=s}o.type="dblclick",o.button=0,e(o),i=null}}return t[Gt+Ht+n]=s,t[Gt+Vt+n]=l,t[Gt+"dblclick"+n]=e,t.addEventListener(Ht,s,!!kt&&{passive:!1}),t.addEventListener(Vt,l,!!kt&&{passive:!1}),t.addEventListener("dblclick",e,!1),this}function Kt(t,e){var n=t[Gt+Ht+e],i=t[Gt+Vt+e],o=t[Gt+"dblclick"+e];return t.removeEventListener(Ht,n,!!kt&&{passive:!1}),t.removeEventListener(Vt,i,!!kt&&{passive:!1}),$||t.removeEventListener("dblclick",o,!1),this}var Qt,Yt,Jt,Xt,$t,te=_e(["transform","webkitTransform","OTransform","MozTransform","msTransform"]),ee=_e(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),ne="webkitTransition"===ee||"OTransition"===ee?ee+"End":"transitionend";function ie(t){return"string"==typeof t?document.getElementById(t):t}function oe(t,e){var n=t.style[e]||t.currentStyle&&t.currentStyle[e];if((!n||"auto"===n)&&document.defaultView){var i=document.defaultView.getComputedStyle(t,null);n=i?i[e]:null}return"auto"===n?null:n}function re(t,e,n){var i=document.createElement(t);return i.className=e||"",n&&n.appendChild(i),i}function ae(t){var e=t.parentNode;e&&e.removeChild(t)}function se(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function le(t){var e=t.parentNode;e&&e.lastChild!==t&&e.appendChild(t)}function ue(t){var e=t.parentNode;e&&e.firstChild!==t&&e.insertBefore(t,e.firstChild)}function ce(t,e){if(void 0!==t.classList)return t.classList.contains(e);var n=pe(t);return n.length>0&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(n)}function he(t,e){if(void 0!==t.classList)for(var n=f(e),i=0,o=n.length;i<o;i++)t.classList.add(n[i]);else if(!ce(t,e)){var r=pe(t);de(t,(r?r+" ":"")+e)}}function fe(t,e){void 0!==t.classList?t.classList.remove(e):de(t,h((" "+pe(t)+" ").replace(" "+e+" "," ")))}function de(t,e){void 0===t.className.baseVal?t.className=e:t.className.baseVal=e}function pe(t){return t.correspondingElement&&(t=t.correspondingElement),void 0===t.className.baseVal?t.className:t.className.baseVal}function me(t,e){"opacity"in t.style?t.style.opacity=e:"filter"in t.style&&function(t,e){var n=!1,i="DXImageTransform.Microsoft.Alpha";try{n=t.filters.item(i)}catch(t){if(1===e)return}e=Math.round(100*e),n?(n.Enabled=100!==e,n.Opacity=e):t.style.filter+=" progid:"+i+"(opacity="+e+")"}(t,e)}function _e(t){for(var e=document.documentElement.style,n=0;n<t.length;n++)if(t[n]in e)return t[n];return!1}function ge(t,e,n){var i=e||new z(0,0);t.style[te]=(ft?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(n?" scale("+n+")":"")}function ve(t,e){t._leaflet_pos=e,mt?ge(t,e):(t.style.left=e.x+"px",t.style.top=e.y+"px")}function ye(t){return t._leaflet_pos||new z(0,0)}if("onselectstart"in document)Qt=function(){Pe(window,"selectstart",Ne)},Yt=function(){Oe(window,"selectstart",Ne)};else{var be=_e(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);Qt=function(){if(be){var t=document.documentElement.style;Jt=t[be],t[be]="none"}},Yt=function(){be&&(document.documentElement.style[be]=Jt,Jt=void 0)}}function we(){Pe(window,"dragstart",Ne)}function xe(){Oe(window,"dragstart",Ne)}function Le(t){for(;-1===t.tabIndex;)t=t.parentNode;t.style&&(Ee(),Xt=t,$t=t.style.outline,t.style.outline="none",Pe(window,"keydown",Ee))}function Ee(){Xt&&(Xt.style.outline=$t,Xt=void 0,$t=void 0,Oe(window,"keydown",Ee))}function ke(t){do{t=t.parentNode}while(!(t.offsetWidth&&t.offsetHeight||t===document.body));return t}function Ce(t){var e=t.getBoundingClientRect();return{x:e.width/t.offsetWidth||1,y:e.height/t.offsetHeight||1,boundingClientRect:e}}var Te=(Object.freeze||Object)({TRANSFORM:te,TRANSITION:ee,TRANSITION_END:ne,get:ie,getStyle:oe,create:re,remove:ae,empty:se,toFront:le,toBack:ue,hasClass:ce,addClass:he,removeClass:fe,setClass:de,getClass:pe,setOpacity:me,testProp:_e,setTransform:ge,setPosition:ve,getPosition:ye,disableTextSelection:Qt,enableTextSelection:Yt,disableImageDrag:we,enableImageDrag:xe,preventOutline:Le,restoreOutline:Ee,getSizedParentNode:ke,getScale:Ce});function Pe(t,e,n,i){if("object"==typeof e)for(var o in e)Me(t,o,e[o],n);else for(var r=0,a=(e=f(e)).length;r<a;r++)Me(t,e[r],n,i);return this}var Se="_leaflet_events";function Oe(t,e,n,i){if("object"==typeof e)for(var o in e)ze(t,o,e[o],n);else if(e)for(var r=0,a=(e=f(e)).length;r<a;r++)ze(t,e[r],n,i);else{for(var s in t[Se])ze(t,s,t[Se][s]);delete t[Se]}return this}function Me(t,e,n,i){var o=e+a(n)+(i?"_"+a(i):"");if(t[Se]&&t[Se][o])return this;var r=function(e){return n.call(i||t,e||window.event)},s=r;bt&&0===e.indexOf("touch")?Zt(t,e,r,o):!wt||"dblclick"!==e||!qt||bt&&at?"addEventListener"in t?"mousewheel"===e?t.addEventListener("onwheel"in t?"wheel":"mousewheel",r,!!kt&&{passive:!1}):"mouseenter"===e||"mouseleave"===e?(r=function(e){e=e||window.event,Ve(t,e)&&s(e)},t.addEventListener("mouseenter"===e?"mouseover":"mouseout",r,!1)):("click"===e&&et&&(r=function(t){!function(t,e){var n=t.timeStamp||t.originalEvent&&t.originalEvent.timeStamp,i=Ue&&n-Ue;i&&i>100&&i<500||t.target._simulatedClick&&!t._simulated?Re(t):(Ue=n,e(t))}(t,s)}),t.addEventListener(e,r,!1)):"attachEvent"in t&&t.attachEvent("on"+e,r):qt(t,r,o),t[Se]=t[Se]||{},t[Se][o]=r}function ze(t,e,n,i){var o=e+a(n)+(i?"_"+a(i):""),r=t[Se]&&t[Se][o];if(!r)return this;bt&&0===e.indexOf("touch")?function(t,e,n){var i=t["_leaflet_"+e+o];"touchstart"===e?t.removeEventListener(Mt,i,!1):"touchmove"===e?t.removeEventListener(zt,i,!1):"touchend"===e&&(t.removeEventListener(At,i,!1),t.removeEventListener(jt,i,!1))}(t,e):!wt||"dblclick"!==e||!Kt||bt&&at?"removeEventListener"in t?"mousewheel"===e?t.removeEventListener("onwheel"in t?"wheel":"mousewheel",r,!!kt&&{passive:!1}):t.removeEventListener("mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,r,!1):"detachEvent"in t&&t.detachEvent("on"+e,r):Kt(t,o),t[Se][o]=null}function Ae(t){return t.stopPropagation?t.stopPropagation():t.originalEvent?t.originalEvent._stopped=!0:t.cancelBubble=!0,He(t),this}function je(t){return Me(t,"mousewheel",Ae),this}function Ie(t){return Pe(t,"mousedown touchstart dblclick",Ae),Me(t,"click",We),this}function Ne(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this}function Re(t){return Ne(t),Ae(t),this}function Be(t,e){if(!e)return new z(t.clientX,t.clientY);var n=Ce(e),i=n.boundingClientRect;return new z((t.clientX-i.left)/n.x-e.clientLeft,(t.clientY-i.top)/n.y-e.clientTop)}var Ze=ht&&at?2*window.devicePixelRatio:st?window.devicePixelRatio:1;function De(t){return $?t.wheelDeltaY/2:t.deltaY&&0===t.deltaMode?-t.deltaY/Ze:t.deltaY&&1===t.deltaMode?20*-t.deltaY:t.deltaY&&2===t.deltaMode?60*-t.deltaY:t.deltaX||t.deltaZ?0:t.wheelDelta?(t.wheelDeltaY||t.wheelDelta)/2:t.detail&&Math.abs(t.detail)<32765?20*-t.detail:t.detail?t.detail/-32765*60:0}var Ue,Fe={};function We(t){Fe[t.type]=!0}function He(t){var e=Fe[t.type];return Fe[t.type]=!1,e}function Ve(t,e){var n=e.relatedTarget;if(!n)return!0;try{for(;n&&n!==t;)n=n.parentNode}catch(t){return!1}return n!==t}var Ge=(Object.freeze||Object)({on:Pe,off:Oe,stopPropagation:Ae,disableScrollPropagation:je,disableClickPropagation:Ie,preventDefault:Ne,stop:Re,getMousePosition:Be,getWheelDelta:De,fakeStop:We,skipped:He,isExternalTarget:Ve,addListener:Pe,removeListener:Oe}),qe=M.extend({run:function(t,e,n,i){this.stop(),this._el=t,this._inProgress=!0,this._duration=n||.25,this._easeOutPower=1/Math.max(i||.5,.2),this._startPos=ye(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=C(this._animate,this),this._step()},_step:function(t){var e=+new Date-this._startTime,n=1e3*this._duration;e<n?this._runFrame(this._easeOut(e/n),t):(this._runFrame(1),this._complete())},_runFrame:function(t,e){var n=this._startPos.add(this._offset.multiplyBy(t));e&&n._round(),ve(this._el,n),this.fire("step")},_complete:function(){T(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),Ke=M.extend({options:{crs:G,center:void 0,zoom:void 0,minZoom:void 0,maxZoom:void 0,layers:[],maxBounds:void 0,renderer:void 0,zoomAnimation:!0,zoomAnimationThreshold:4,fadeAnimation:!0,markerZoomAnimation:!0,transform3DLimit:8388608,zoomSnap:1,zoomDelta:1,trackResize:!0},initialize:function(t,e){e=d(this,e),this._handlers=[],this._layers={},this._zoomBoundLayers={},this._sizeChanged=!0,this._initContainer(t),this._initLayout(),this._onResize=o(this._onResize,this),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),void 0!==e.zoom&&(this._zoom=this._limitZoom(e.zoom)),e.center&&void 0!==e.zoom&&this.setView(D(e.center),e.zoom,{reset:!0}),this.callInitHooks(),this._zoomAnimated=ee&&mt&&!xt&&this.options.zoomAnimation,this._zoomAnimated&&(this._createAnimProxy(),Pe(this._proxy,ne,this._catchTransitionEnd,this)),this._addLayers(this.options.layers)},setView:function(t,e,i){return e=void 0===e?this._zoom:this._limitZoom(e),t=this._limitCenter(D(t),e,this.options.maxBounds),i=i||{},this._stop(),this._loaded&&!i.reset&&!0!==i&&(void 0!==i.animate&&(i.zoom=n({animate:i.animate},i.zoom),i.pan=n({animate:i.animate,duration:i.duration},i.pan)),this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,i.zoom):this._tryAnimatedPan(t,i.pan))?(clearTimeout(this._sizeTimer),this):(this._resetView(t,e),this)},setZoom:function(t,e){return this._loaded?this.setView(this.getCenter(),t,{zoom:e}):(this._zoom=t,this)},zoomIn:function(t,e){return t=t||(mt?this.options.zoomDelta:1),this.setZoom(this._zoom+t,e)},zoomOut:function(t,e){return t=t||(mt?this.options.zoomDelta:1),this.setZoom(this._zoom-t,e)},setZoomAround:function(t,e,n){var i=this.getZoomScale(e),o=this.getSize().divideBy(2),r=(t instanceof z?t:this.latLngToContainerPoint(t)).subtract(o).multiplyBy(1-1/i),a=this.containerPointToLatLng(o.add(r));return this.setView(a,e,{zoom:n})},_getBoundsCenterZoom:function(t,e){e=e||{},t=t.getBounds?t.getBounds():B(t);var n=j(e.paddingTopLeft||e.padding||[0,0]),i=j(e.paddingBottomRight||e.padding||[0,0]),o=this.getBoundsZoom(t,!1,n.add(i));if((o="number"==typeof e.maxZoom?Math.min(e.maxZoom,o):o)===1/0)return{center:t.getCenter(),zoom:o};var r=i.subtract(n).divideBy(2),a=this.project(t.getSouthWest(),o),s=this.project(t.getNorthEast(),o);return{center:this.unproject(a.add(s).divideBy(2).add(r),o),zoom:o}},fitBounds:function(t,e){if(!(t=B(t)).isValid())throw new Error("Bounds are not valid.");var n=this._getBoundsCenterZoom(t,e);return this.setView(n.center,n.zoom,e)},fitWorld:function(t){return this.fitBounds([[-90,-180],[90,180]],t)},panTo:function(t,e){return this.setView(t,this._zoom,{pan:e})},panBy:function(t,e){if(e=e||{},!(t=j(t).round()).x&&!t.y)return this.fire("moveend");if(!0!==e.animate&&!this.getSize().contains(t))return this._resetView(this.unproject(this.project(this.getCenter()).add(t)),this.getZoom()),this;if(this._panAnim||(this._panAnim=new qe,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),!1!==e.animate){he(this._mapPane,"leaflet-pan-anim");var n=this._getMapPanePos().subtract(t).round();this._panAnim.run(this._mapPane,n,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},flyTo:function(t,e,n){if(!1===(n=n||{}).animate||!mt)return this.setView(t,e,n);this._stop();var i=this.project(this.getCenter()),o=this.project(t),r=this.getSize(),a=this._zoom;t=D(t),e=void 0===e?a:e;var s=Math.max(r.x,r.y),l=s*this.getZoomScale(a,e),u=o.distanceTo(i)||1,c=1.42,h=c*c;function f(t){var e=(l*l-s*s+(t?-1:1)*h*h*u*u)/(2*(t?l:s)*h*u),n=Math.sqrt(e*e+1)-e;return n<1e-9?-18:Math.log(n)}function d(t){return(Math.exp(t)-Math.exp(-t))/2}function p(t){return(Math.exp(t)+Math.exp(-t))/2}var m=f(0);var _=Date.now(),g=(f(1)-m)/c,v=n.duration?1e3*n.duration:1e3*g*.8;return this._moveStart(!0,n.noMoveStart),function n(){var r=(Date.now()-_)/v,l=function(t){return 1-Math.pow(1-t,1.5)}(r)*g;r<=1?(this._flyToFrame=C(n,this),this._move(this.unproject(i.add(o.subtract(i).multiplyBy(function(t){return s*(p(m)*(d(e=m+c*t)/p(e))-d(m))/h;var e}(l)/u)),a),this.getScaleZoom(s/function(t){return s*(p(m)/p(m+c*t))}(l),a),{flyTo:!0})):this._move(t,e)._moveEnd(!0)}.call(this),this},flyToBounds:function(t,e){var n=this._getBoundsCenterZoom(t,e);return this.flyTo(n.center,n.zoom,e)},setMaxBounds:function(t){return(t=B(t)).isValid()?(this.options.maxBounds&&this.off("moveend",this._panInsideMaxBounds),this.options.maxBounds=t,this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds)):(this.options.maxBounds=null,this.off("moveend",this._panInsideMaxBounds))},setMinZoom:function(t){var e=this.options.minZoom;return this.options.minZoom=t,this._loaded&&e!==t&&(this.fire("zoomlevelschange"),this.getZoom()<this.options.minZoom)?this.setZoom(t):this},setMaxZoom:function(t){var e=this.options.maxZoom;return this.options.maxZoom=t,this._loaded&&e!==t&&(this.fire("zoomlevelschange"),this.getZoom()>this.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,e){this._enforcingBounds=!0;var n=this.getCenter(),i=this._limitCenter(n,this._zoom,B(t));return n.equals(i)||this.panTo(i,e),this._enforcingBounds=!1,this},panInside:function(t,e){var n=j((e=e||{}).paddingTopLeft||e.padding||[0,0]),i=j(e.paddingBottomRight||e.padding||[0,0]),o=this.getCenter(),r=this.project(o),a=this.project(t),s=this.getPixelBounds(),l=s.getSize().divideBy(2),u=N([s.min.add(n),s.max.subtract(i)]);if(!u.contains(a)){this._enforcingBounds=!0;var c=r.subtract(a),h=j(a.x+c.x,a.y+c.y);(a.x<u.min.x||a.x>u.max.x)&&(h.x=r.x-c.x,c.x>0?h.x+=l.x-n.x:h.x-=l.x-i.x),(a.y<u.min.y||a.y>u.max.y)&&(h.y=r.y-c.y,c.y>0?h.y+=l.y-n.y:h.y-=l.y-i.y),this.panTo(this.unproject(h),e),this._enforcingBounds=!1}return this},invalidateSize:function(t){if(!this._loaded)return this;t=n({animate:!1,pan:!0},!0===t?{animate:!0}:t);var e=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var i=this.getSize(),r=e.divideBy(2).round(),a=i.divideBy(2).round(),s=r.subtract(a);return s.x||s.y?(t.animate&&t.pan?this.panBy(s):(t.pan&&this._rawPanBy(s),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(o(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=n({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o(this._handleGeolocationResponse,this),i=o(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,n=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+n+"."})},_handleGeolocationResponse:function(t){var e=new Z(t.coords.latitude,t.coords.longitude),n=e.toBounds(2*t.coords.accuracy),i=this._locateOptions;if(i.setView){var o=this.getBoundsZoom(n);this.setView(e,i.maxZoom?Math.min(o,i.maxZoom):o)}var r={latlng:e,bounds:n,timestamp:t.timestamp};for(var a in t.coords)"number"==typeof t.coords[a]&&(r[a]=t.coords[a]);this.fire("locationfound",r)},addHandler:function(t,e){if(!e)return this;var n=this[t]=new e(this);return this._handlers.push(n),this.options[t]&&n.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}var t;for(t in void 0!==this._locationWatchId&&this.stopLocate(),this._stop(),ae(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&(T(this._resizeRequest),this._resizeRequest=null),this._clearHandlers(),this._loaded&&this.fire("unload"),this._layers)this._layers[t].remove();for(t in this._panes)ae(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,e){var n=re("div","leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),e||this._mapPane);return t&&(this._panes[t]=n),n},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new R(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,n){t=B(t),n=j(n||[0,0]);var i=this.getZoom()||0,o=this.getMinZoom(),r=this.getMaxZoom(),a=t.getNorthWest(),s=t.getSouthEast(),l=this.getSize().subtract(n),u=N(this.project(s,i),this.project(a,i)).getSize(),c=mt?this.options.zoomSnap:1,h=l.x/u.x,f=l.y/u.y,d=e?Math.max(h,f):Math.min(h,f);return i=this.getScaleZoom(d,i),c&&(i=Math.round(i/(c/100))*(c/100),i=e?Math.ceil(i/c)*c:Math.floor(i/c)*c),Math.max(o,Math.min(r,i))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new z(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,e){var n=this._getTopLeftPoint(t,e);return new I(n,n.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,e){var n=this.options.crs;return e=void 0===e?this._zoom:e,n.scale(t)/n.scale(e)},getScaleZoom:function(t,e){var n=this.options.crs;e=void 0===e?this._zoom:e;var i=n.zoom(t*n.scale(e));return isNaN(i)?1/0:i},project:function(t,e){return e=void 0===e?this._zoom:e,this.options.crs.latLngToPoint(D(t),e)},unproject:function(t,e){return e=void 0===e?this._zoom:e,this.options.crs.pointToLatLng(j(t),e)},layerPointToLatLng:function(t){var e=j(t).add(this.getPixelOrigin());return this.unproject(e)},latLngToLayerPoint:function(t){return this.project(D(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(D(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(B(t))},distance:function(t,e){return this.options.crs.distance(D(t),D(e))},containerPointToLayerPoint:function(t){return j(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return j(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(j(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(D(t)))},mouseEventToContainerPoint:function(t){return Be(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=ie(t);if(!e)throw new Error("Map container not found.");if(e._leaflet_id)throw new Error("Map container is already initialized.");Pe(e,"scroll",this._onScroll,this),this._containerId=a(e)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&mt,he(t,"leaflet-container"+(wt?" leaflet-touch":"")+(Et?" leaflet-retina":"")+(X?" leaflet-oldie":"")+(lt?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var e=oe(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),ve(this._mapPane,new z(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(he(t.markerPane,"leaflet-zoom-hide"),he(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,e){ve(this._mapPane,new z(0,0));var n=!this._loaded;this._loaded=!0,e=this._limitZoom(e),this.fire("viewprereset");var i=this._zoom!==e;this._moveStart(i,!1)._move(t,e)._moveEnd(i),this.fire("viewreset"),n&&this.fire("load")},_moveStart:function(t,e){return t&&this.fire("zoomstart"),e||this.fire("movestart"),this},_move:function(t,e,n){void 0===e&&(e=this._zoom);var i=this._zoom!==e;return this._zoom=e,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(i||n&&n.pinch)&&this.fire("zoom",n),this.fire("move",n)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return T(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){ve(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[a(this._container)]=this;var e=t?Oe:Pe;e(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress keydown keyup",this._handleDOMEvent,this),this.options.trackResize&&e(window,"resize",this._onResize,this),mt&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){T(this._resizeRequest),this._resizeRequest=C(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,e){for(var n,i=[],o="mouseout"===e||"mouseover"===e,r=t.target||t.srcElement,s=!1;r;){if((n=this._targets[a(r)])&&("click"===e||"preclick"===e)&&!t._simulated&&this._draggableMoved(n)){s=!0;break}if(n&&n.listens(e,!0)){if(o&&!Ve(r,t))break;if(i.push(n),o)break}if(r===this._container)break;r=r.parentNode}return i.length||s||o||!Ve(r,t)||(i=[this]),i},_handleDOMEvent:function(t){if(this._loaded&&!He(t)){var e=t.type;"mousedown"!==e&&"keypress"!==e&&"keyup"!==e&&"keydown"!==e||Le(t.target||t.srcElement),this._fireDOMEvent(t,e)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,i){if("click"===t.type){var o=n({},t);o.type="preclick",this._fireDOMEvent(o,o.type,i)}if(!t._stopped&&(i=(i||[]).concat(this._findEventTargets(t,e))).length){var r=i[0];"contextmenu"===e&&r.listens(e,!0)&&Ne(t);var a={originalEvent:t};if("keypress"!==t.type&&"keydown"!==t.type&&"keyup"!==t.type){var s=r.getLatLng&&(!r._radius||r._radius<=10);a.containerPoint=s?this.latLngToContainerPoint(r.getLatLng()):this.mouseEventToContainerPoint(t),a.layerPoint=this.containerPointToLayerPoint(a.containerPoint),a.latlng=s?r.getLatLng():this.layerPointToLatLng(a.layerPoint)}for(var l=0;l<i.length;l++)if(i[l].fire(e,a,!0),a.originalEvent._stopped||!1===i[l].options.bubblingMouseEvents&&-1!==v(this._mouseEvents,e))return}},_draggableMoved:function(t){return(t=t.dragging&&t.dragging.enabled()?t:this).dragging&&t.dragging.moved()||this.boxZoom&&this.boxZoom.moved()},_clearHandlers:function(){for(var t=0,e=this._handlers.length;t<e;t++)this._handlers[t].disable()},whenReady:function(t,e){return this._loaded?t.call(e||this,{target:this}):this.on("load",t,e),this},_getMapPanePos:function(){return ye(this._mapPane)||new z(0,0)},_moved:function(){var t=this._getMapPanePos();return t&&!t.equals([0,0])},_getTopLeftPoint:function(t,e){return(t&&void 0!==e?this._getNewPixelOrigin(t,e):this.getPixelOrigin()).subtract(this._getMapPanePos())},_getNewPixelOrigin:function(t,e){var n=this.getSize()._divideBy(2);return this.project(t,e)._subtract(n)._add(this._getMapPanePos())._round()},_latLngToNewLayerPoint:function(t,e,n){var i=this._getNewPixelOrigin(n,e);return this.project(t,e)._subtract(i)},_latLngBoundsToNewLayerBounds:function(t,e,n){var i=this._getNewPixelOrigin(n,e);return N([this.project(t.getSouthWest(),e)._subtract(i),this.project(t.getNorthWest(),e)._subtract(i),this.project(t.getSouthEast(),e)._subtract(i),this.project(t.getNorthEast(),e)._subtract(i)])},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitCenter:function(t,e,n){if(!n)return t;var i=this.project(t,e),o=this.getSize().divideBy(2),r=new I(i.subtract(o),i.add(o)),a=this._getBoundsOffset(r,n,e);return a.round().equals([0,0])?t:this.unproject(i.add(a),e)},_limitOffset:function(t,e){if(!e)return t;var n=this.getPixelBounds(),i=new I(n.min.add(t),n.max.add(t));return t.add(this._getBoundsOffset(i,e))},_getBoundsOffset:function(t,e,n){var i=N(this.project(e.getNorthEast(),n),this.project(e.getSouthWest(),n)),o=i.min.subtract(t.min),r=i.max.subtract(t.max);return new z(this._rebound(o.x,-r.x),this._rebound(o.y,-r.y))},_rebound:function(t,e){return t+e>0?Math.round(t-e)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(e))},_limitZoom:function(t){var e=this.getMinZoom(),n=this.getMaxZoom(),i=mt?this.options.zoomSnap:1;return i&&(t=Math.round(t/i)*i),Math.max(e,Math.min(n,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){fe(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var n=this._getCenterOffset(t)._trunc();return!(!0!==(e&&e.animate)&&!this.getSize().contains(n)||(this.panBy(n,e),0))},_createAnimProxy:function(){var t=this._proxy=re("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var e=te,n=this._proxy.style[e];ge(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),n===this._proxy.style[e]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",this._animMoveEnd,this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){ae(this._proxy),this.off("load moveend",this._animMoveEnd,this),delete this._proxy},_animMoveEnd:function(){var t=this.getCenter(),e=this.getZoom();ge(this._proxy,this.project(t,e),this.getZoomScale(e,1))},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,n){if(this._animatingZoom)return!0;if(n=n||{},!this._zoomAnimated||!1===n.animate||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var i=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/i);return!(!0!==n.animate&&!this.getSize().contains(o)||(C(function(){this._moveStart(!0,!1)._animateZoom(t,e,!0)},this),0))},_animateZoom:function(t,e,n,i){this._mapPane&&(n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=e,he(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:e,noUpdate:i}),setTimeout(o(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&fe(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),C(function(){this._moveEnd(!0)},this))}}),Qe=S.extend({options:{position:"topright"},initialize:function(t){d(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var e=this._container=this.onAdd(t),n=this.getPosition(),i=t._controlCorners[n];return he(e,"leaflet-control"),-1!==n.indexOf("bottom")?i.insertBefore(e,i.firstChild):i.appendChild(e),this._map.on("unload",this.remove,this),this},remove:function(){return this._map?(ae(this._container),this.onRemove&&this.onRemove(this._map),this._map.off("unload",this.remove,this),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),Ye=function(t){return new Qe(t)};Ke.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){var t=this._controlCorners={},e="leaflet-",n=this._controlContainer=re("div",e+"control-container",this._container);function i(i,o){var r=e+i+" "+e+o;t[i+o]=re("div",r,n)}i("top","left"),i("top","right"),i("bottom","left"),i("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)ae(this._controlCorners[t]);ae(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Je=Qe.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,e,n,i){return n<i?-1:i<n?1:0}},initialize:function(t,e,n){for(var i in d(this,n),this._layerControlInputs=[],this._layers=[],this._lastZIndex=0,this._handlingClick=!1,t)this._addLayer(t[i],i);for(i in e)this._addLayer(e[i],i,!0)},onAdd:function(t){this._initLayout(),this._update(),this._map=t,t.on("zoomend",this._checkDisabledLayers,this);for(var e=0;e<this._layers.length;e++)this._layers[e].layer.on("add remove",this._onLayerChange,this);return this._container},addTo:function(t){return Qe.prototype.addTo.call(this,t),this._expandIfNotCollapsed()},onRemove:function(){this._map.off("zoomend",this._checkDisabledLayers,this);for(var t=0;t<this._layers.length;t++)this._layers[t].layer.off("add remove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._map?this._update():this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._map?this._update():this},removeLayer:function(t){t.off("add remove",this._onLayerChange,this);var e=this._getLayer(a(t));return e&&this._layers.splice(this._layers.indexOf(e),1),this._map?this._update():this},expand:function(){he(this._container,"leaflet-control-layers-expanded"),this._section.style.height=null;var t=this._map.getSize().y-(this._container.offsetTop+50);return t<this._section.clientHeight?(he(this._section,"leaflet-control-layers-scrollbar"),this._section.style.height=t+"px"):fe(this._section,"leaflet-control-layers-scrollbar"),this._checkDisabledLayers(),this},collapse:function(){return fe(this._container,"leaflet-control-layers-expanded"),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=re("div",t),n=this.options.collapsed;e.setAttribute("aria-haspopup",!0),Ie(e),je(e);var i=this._section=re("section",t+"-list");n&&(this._map.on("click",this.collapse,this),et||Pe(e,{mouseenter:this.expand,mouseleave:this.collapse},this));var o=this._layersLink=re("a",t+"-toggle",e);o.href="#",o.title="Layers",wt?(Pe(o,"click",Re),Pe(o,"click",this.expand,this)):Pe(o,"focus",this.expand,this),n||this.expand(),this._baseLayersList=re("div",t+"-base",i),this._separator=re("div",t+"-separator",i),this._overlaysList=re("div",t+"-overlays",i),e.appendChild(i)},_getLayer:function(t){for(var e=0;e<this._layers.length;e++)if(this._layers[e]&&a(this._layers[e].layer)===t)return this._layers[e]},_addLayer:function(t,e,n){this._map&&t.on("add remove",this._onLayerChange,this),this._layers.push({layer:t,name:e,overlay:n}),this.options.sortLayers&&this._layers.sort(o(function(t,e){return this.options.sortFunction(t.layer,e.layer,t.name,e.name)},this)),this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex)),this._expandIfNotCollapsed()},_update:function(){if(!this._container)return this;se(this._baseLayersList),se(this._overlaysList),this._layerControlInputs=[];var t,e,n,i,o=0;for(n=0;n<this._layers.length;n++)i=this._layers[n],this._addItem(i),e=e||i.overlay,t=t||!i.overlay,o+=i.overlay?0:1;return this.options.hideSingleBase&&(t=t&&o>1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=e&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var e=this._getLayer(a(t.target)),n=e.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;n&&this._map.fire(n,e)},_createRadioElement:function(t,e){var n='<input type="radio" class="leaflet-control-layers-selector" name="'+t+'"'+(e?' checked="checked"':"")+"/>",i=document.createElement("div");return i.innerHTML=n,i.firstChild},_addItem:function(t){var e,n=document.createElement("label"),i=this._map.hasLayer(t.layer);t.overlay?((e=document.createElement("input")).type="checkbox",e.className="leaflet-control-layers-selector",e.defaultChecked=i):e=this._createRadioElement("leaflet-base-layers_"+a(this),i),this._layerControlInputs.push(e),e.layerId=a(t.layer),Pe(e,"click",this._onInputClick,this);var o=document.createElement("span");o.innerHTML=" "+t.name;var r=document.createElement("div");return n.appendChild(r),r.appendChild(e),r.appendChild(o),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(n),this._checkDisabledLayers(),n},_onInputClick:function(){var t,e,n=this._layerControlInputs,i=[],o=[];this._handlingClick=!0;for(var r=n.length-1;r>=0;r--)t=n[r],e=this._getLayer(t.layerId).layer,t.checked?i.push(e):t.checked||o.push(e);for(r=0;r<o.length;r++)this._map.hasLayer(o[r])&&this._map.removeLayer(o[r]);for(r=0;r<i.length;r++)this._map.hasLayer(i[r])||this._map.addLayer(i[r]);this._handlingClick=!1,this._refocusOnMap()},_checkDisabledLayers:function(){for(var t,e,n=this._layerControlInputs,i=this._map.getZoom(),o=n.length-1;o>=0;o--)t=n[o],e=this._getLayer(t.layerId).layer,t.disabled=void 0!==e.options.minZoom&&i<e.options.minZoom||void 0!==e.options.maxZoom&&i>e.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Xe=Qe.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",n=re("div",e+" leaflet-bar"),i=this.options;return this._zoomInButton=this._createButton(i.zoomInText,i.zoomInTitle,e+"-in",n,this._zoomIn),this._zoomOutButton=this._createButton(i.zoomOutText,i.zoomOutTitle,e+"-out",n,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),n},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoom<this._map.getMaxZoom()&&this._map.zoomIn(this._map.options.zoomDelta*(t.shiftKey?3:1))},_zoomOut:function(t){!this._disabled&&this._map._zoom>this._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,e,n,i,o){var r=re("a",n,i);return r.innerHTML=t,r.href="#",r.title=e,r.setAttribute("role","button"),r.setAttribute("aria-label",e),Ie(r),Pe(r,"click",Re),Pe(r,"click",o,this),Pe(r,"click",this._refocusOnMap,this),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";fe(this._zoomInButton,e),fe(this._zoomOutButton,e),(this._disabled||t._zoom===t.getMinZoom())&&he(this._zoomOutButton,e),(this._disabled||t._zoom===t.getMaxZoom())&&he(this._zoomInButton,e)}});Ke.mergeOptions({zoomControl:!0}),Ke.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Xe,this.addControl(this.zoomControl))});var $e=Qe.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var e=re("div","leaflet-control-scale"),n=this.options;return this._addScales(n,"leaflet-control-scale-line",e),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),e},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,n){t.metric&&(this._mScale=re("div",e,n)),t.imperial&&(this._iScale=re("div",e,n))},_update:function(){var t=this._map,e=t.getSize().y/2,n=t.distance(t.containerPointToLatLng([0,e]),t.containerPointToLatLng([this.options.maxWidth,e]));this._updateScales(n)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var e=this._getRoundNum(t),n=e<1e3?e+" m":e/1e3+" km";this._updateScale(this._mScale,n,e/t)},_updateImperial:function(t){var e,n,i,o=3.2808399*t;o>5280?(e=o/5280,n=this._getRoundNum(e),this._updateScale(this._iScale,n+" mi",n/e)):(i=this._getRoundNum(o),this._updateScale(this._iScale,i+" ft",i/o))},_updateScale:function(t,e,n){t.style.width=Math.round(this.options.maxWidth*n)+"px",t.innerHTML=e},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),n=t/e;return e*(n>=10?10:n>=5?5:n>=3?3:n>=2?2:1)}}),tn=Qe.extend({options:{position:"bottomright",prefix:'<a href="https://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'},initialize:function(t){d(this,t),this._attributions={}},onAdd:function(t){for(var e in t.attributionControl=this,this._container=re("div","leaflet-control-attribution"),Ie(this._container),t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var n=[];this.options.prefix&&n.push(this.options.prefix),t.length&&n.push(t.join(", ")),this._container.innerHTML=n.join(" | ")}}});Ke.mergeOptions({attributionControl:!0}),Ke.addInitHook(function(){this.options.attributionControl&&(new tn).addTo(this)}),Qe.Layers=Je,Qe.Zoom=Xe,Qe.Scale=$e,Qe.Attribution=tn,Ye.layers=function(t,e,n){return new Je(t,e,n)},Ye.zoom=function(t){return new Xe(t)},Ye.scale=function(t){return new $e(t)},Ye.attribution=function(t){return new tn(t)};var en=S.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}});en.addTo=function(t,e){return t.addHandler(e,this),this};var nn,on={Events:O},rn=wt?"touchstart mousedown":"mousedown",an={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},sn={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},ln=M.extend({options:{clickTolerance:3},initialize:function(t,e,n,i){d(this,i),this._element=t,this._dragStartTarget=e||t,this._preventOutline=n},enable:function(){this._enabled||(Pe(this._dragStartTarget,rn,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(ln._dragging===this&&this.finishDrag(),Oe(this._dragStartTarget,rn,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!ce(this._element,"leaflet-zoom-anim")&&!(ln._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches)&&(ln._dragging=this,this._preventOutline&&Le(this._element),we(),Qt(),!this._moving))){this.fire("down");var e=t.touches?t.touches[0]:t,n=ke(this._element);this._startPoint=new z(e.clientX,e.clientY),this._parentScale=Ce(n),Pe(document,sn[t.type],this._onMove,this),Pe(document,an[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&t.touches.length>1)this._moved=!0;else{var e=t.touches&&1===t.touches.length?t.touches[0]:t,n=new z(e.clientX,e.clientY)._subtract(this._startPoint);(n.x||n.y)&&(Math.abs(n.x)+Math.abs(n.y)<this.options.clickTolerance||(n.x/=this._parentScale.x,n.y/=this._parentScale.y,Ne(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=ye(this._element).subtract(n),he(document.body,"leaflet-dragging"),this._lastTarget=t.target||t.srcElement,window.SVGElementInstance&&this._lastTarget instanceof SVGElementInstance&&(this._lastTarget=this._lastTarget.correspondingUseElement),he(this._lastTarget,"leaflet-drag-target")),this._newPos=this._startPos.add(n),this._moving=!0,T(this._animRequest),this._lastEvent=t,this._animRequest=C(this._updatePosition,this,!0)))}},_updatePosition:function(){var t={originalEvent:this._lastEvent};this.fire("predrag",t),ve(this._element,this._newPos),this.fire("drag",t)},_onUp:function(t){!t._simulated&&this._enabled&&this.finishDrag()},finishDrag:function(){for(var t in fe(document.body,"leaflet-dragging"),this._lastTarget&&(fe(this._lastTarget,"leaflet-drag-target"),this._lastTarget=null),sn)Oe(document,sn[t],this._onMove,this),Oe(document,an[t],this._onUp,this);xe(),Yt(),this._moved&&this._moving&&(T(this._animRequest),this.fire("dragend",{distance:this._newPos.distanceTo(this._startPos)})),this._moving=!1,ln._dragging=!1}});function un(t,e){if(!e||!t.length)return t.slice();var n=e*e;return function(t,e){var n=t.length,i=new(typeof Uint8Array!=void 0+""?Uint8Array:Array)(n);i[0]=i[n-1]=1,function t(e,n,i,o,r){var a,s,l,u=0;for(s=o+1;s<=r-1;s++)(l=mn(e[s],e[o],e[r],!0))>u&&(a=s,u=l);u>i&&(n[a]=1,t(e,n,i,o,a),t(e,n,i,a,r))}(t,i,e,0,n-1);var o,r=[];for(o=0;o<n;o++)i[o]&&r.push(t[o]);return r}(t=function(t,e){for(var n=[t[0]],i=1,o=0,r=t.length;i<r;i++)pn(t[i],t[o])>e&&(n.push(t[i]),o=i);return o<r-1&&n.push(t[r-1]),n}(t,n),n)}function cn(t,e,n){return Math.sqrt(mn(t,e,n,!0))}function hn(t,e,n,i,o){var r,a,s,l=i?nn:dn(t,n),u=dn(e,n);for(nn=u;;){if(!(l|u))return[t,e];if(l&u)return!1;s=dn(a=fn(t,e,r=l||u,n,o),n),r===l?(t=a,l=s):(e=a,u=s)}}function fn(t,e,n,i,o){var r,a,s=e.x-t.x,l=e.y-t.y,u=i.min,c=i.max;return 8&n?(r=t.x+s*(c.y-t.y)/l,a=c.y):4&n?(r=t.x+s*(u.y-t.y)/l,a=u.y):2&n?(r=c.x,a=t.y+l*(c.x-t.x)/s):1&n&&(r=u.x,a=t.y+l*(u.x-t.x)/s),new z(r,a,o)}function dn(t,e){var n=0;return t.x<e.min.x?n|=1:t.x>e.max.x&&(n|=2),t.y<e.min.y?n|=4:t.y>e.max.y&&(n|=8),n}function pn(t,e){var n=e.x-t.x,i=e.y-t.y;return n*n+i*i}function mn(t,e,n,i){var o,r=e.x,a=e.y,s=n.x-r,l=n.y-a,u=s*s+l*l;return u>0&&((o=((t.x-r)*s+(t.y-a)*l)/u)>1?(r=n.x,a=n.y):o>0&&(r+=s*o,a+=l*o)),s=t.x-r,l=t.y-a,i?s*s+l*l:new z(r,a)}function _n(t){return!g(t[0])||"object"!=typeof t[0][0]&&void 0!==t[0][0]}function gn(t){return console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead."),_n(t)}var vn=(Object.freeze||Object)({simplify:un,pointToSegmentDistance:cn,closestPointOnSegment:function(t,e,n){return mn(t,e,n)},clipSegment:hn,_getEdgeIntersection:fn,_getBitCode:dn,_sqClosestPointOnSegment:mn,isFlat:_n,_flat:gn});function yn(t,e,n){var i,o,r,a,s,l,u,c,h,f=[1,4,2,8];for(o=0,u=t.length;o<u;o++)t[o]._code=dn(t[o],e);for(a=0;a<4;a++){for(c=f[a],i=[],o=0,r=(u=t.length)-1;o<u;r=o++)s=t[o],l=t[r],s._code&c?l._code&c||((h=fn(l,s,c,e,n))._code=dn(h,e),i.push(h)):(l._code&c&&((h=fn(l,s,c,e,n))._code=dn(h,e),i.push(h)),i.push(s));t=i}return t}var bn=(Object.freeze||Object)({clipPolygon:yn}),wn={project:function(t){return new z(t.lng,t.lat)},unproject:function(t){return new Z(t.y,t.x)},bounds:new I([-180,-90],[180,90])},xn={R:6378137,R_MINOR:6356752.314245179,bounds:new I([-20037508.34279,-15496570.73972],[20037508.34279,18764656.23138]),project:function(t){var e=Math.PI/180,n=this.R,i=t.lat*e,o=this.R_MINOR/n,r=Math.sqrt(1-o*o),a=r*Math.sin(i),s=Math.tan(Math.PI/4-i/2)/Math.pow((1-a)/(1+a),r/2);return i=-n*Math.log(Math.max(s,1e-10)),new z(t.lng*e*n,i)},unproject:function(t){for(var e,n=180/Math.PI,i=this.R,o=this.R_MINOR/i,r=Math.sqrt(1-o*o),a=Math.exp(-t.y/i),s=Math.PI/2-2*Math.atan(a),l=0,u=.1;l<15&&Math.abs(u)>1e-7;l++)e=r*Math.sin(s),e=Math.pow((1-e)/(1+e),r/2),s+=u=Math.PI/2-2*Math.atan(a*e)-s;return new Z(s*n,t.x*n/i)}},Ln=(Object.freeze||Object)({LonLat:wn,Mercator:xn,SphericalMercator:W}),En=n({},F,{code:"EPSG:3395",projection:xn,transformation:function(){var t=.5/(Math.PI*xn.R);return V(t,.5,-t,.5)}()}),kn=n({},F,{code:"EPSG:4326",projection:wn,transformation:V(1/180,1,-1/180,.5)}),Cn=n({},U,{projection:wn,transformation:V(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,e){var n=e.lng-t.lng,i=e.lat-t.lat;return Math.sqrt(n*n+i*i)},infinite:!0});U.Earth=F,U.EPSG3395=En,U.EPSG3857=G,U.EPSG900913=q,U.EPSG4326=kn,U.Simple=Cn;var Tn=M.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[a(t)]=this,this},removeInteractiveTarget:function(t){return delete this._map._targets[a(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var e=t.target;if(e.hasLayer(this)){if(this._map=e,this._zoomAnimated=e._zoomAnimated,this.getEvents){var n=this.getEvents();e.on(n,this),this.once("remove",function(){e.off(n,this)},this)}this.onAdd(e),this.getAttribution&&e.attributionControl&&e.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),e.fire("layeradd",{layer:this})}}});Ke.include({addLayer:function(t){if(!t._layerAdd)throw new Error("The provided object is not a Layer.");var e=a(t);return this._layers[e]?this:(this._layers[e]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var e=a(t);return this._layers[e]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[e],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&a(t)in this._layers},eachLayer:function(t,e){for(var n in this._layers)t.call(e,this._layers[n]);return this},_addLayers:function(t){for(var e=0,n=(t=t?g(t)?t:[t]:[]).length;e<n;e++)this.addLayer(t[e])},_addZoomLimit:function(t){!isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[a(t)]=t,this._updateZoomLevels())},_removeZoomLimit:function(t){var e=a(t);this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels())},_updateZoomLevels:function(){var t=1/0,e=-1/0,n=this._getZoomSpan();for(var i in this._zoomBoundLayers){var o=this._zoomBoundLayers[i].options;t=void 0===o.minZoom?t:Math.min(t,o.minZoom),e=void 0===o.maxZoom?e:Math.max(e,o.maxZoom)}this._layersMaxZoom=e===-1/0?void 0:e,this._layersMinZoom=t===1/0?void 0:t,n!==this._getZoomSpan()&&this.fire("zoomlevelschange"),void 0===this.options.maxZoom&&this._layersMaxZoom&&this.getZoom()>this._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()<this._layersMinZoom&&this.setZoom(this._layersMinZoom)}});var Pn=Tn.extend({initialize:function(t,e){var n,i;if(d(this,e),this._layers={},t)for(n=0,i=t.length;n<i;n++)this.addLayer(t[n])},addLayer:function(t){var e=this.getLayerId(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=t in this._layers?t:this.getLayerId(t);return this._map&&this._layers[e]&&this._map.removeLayer(this._layers[e]),delete this._layers[e],this},hasLayer:function(t){return!!t&&(t in this._layers||this.getLayerId(t)in this._layers)},clearLayers:function(){return this.eachLayer(this.removeLayer,this)},invoke:function(t){var e,n,i=Array.prototype.slice.call(arguments,1);for(e in this._layers)(n=this._layers[e])[t]&&n[t].apply(n,i);return this},onAdd:function(t){this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t)},eachLayer:function(t,e){for(var n in this._layers)t.call(e,this._layers[n]);return this},getLayer:function(t){return this._layers[t]},getLayers:function(){var t=[];return this.eachLayer(t.push,t),t},setZIndex:function(t){return this.invoke("setZIndex",t)},getLayerId:function(t){return a(t)}}),Sn=Pn.extend({addLayer:function(t){return this.hasLayer(t)?this:(t.addEventParent(this),Pn.prototype.addLayer.call(this,t),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return this.hasLayer(t)?(t in this._layers&&(t=this._layers[t]),t.removeEventParent(this),Pn.prototype.removeLayer.call(this,t),this.fire("layerremove",{layer:t})):this},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new R;for(var e in this._layers){var n=this._layers[e];t.extend(n.getBounds?n.getBounds():n.getLatLng())}return t}}),On=S.extend({options:{popupAnchor:[0,0],tooltipAnchor:[0,0]},initialize:function(t){d(this,t)},createIcon:function(t){return this._createIcon("icon",t)},createShadow:function(t){return this._createIcon("shadow",t)},_createIcon:function(t,e){var n=this._getIconUrl(t);if(!n){if("icon"===t)throw new Error("iconUrl not set in Icon options (see the docs).");return null}var i=this._createImg(n,e&&"IMG"===e.tagName?e:null);return this._setIconStyles(i,t),i},_setIconStyles:function(t,e){var n=this.options,i=n[e+"Size"];"number"==typeof i&&(i=[i,i]);var o=j(i),r=j("shadow"===e&&n.shadowAnchor||n.iconAnchor||o&&o.divideBy(2,!0));t.className="leaflet-marker-"+e+" "+(n.className||""),r&&(t.style.marginLeft=-r.x+"px",t.style.marginTop=-r.y+"px"),o&&(t.style.width=o.x+"px",t.style.height=o.y+"px")},_createImg:function(t,e){return(e=e||document.createElement("img")).src=t,e},_getIconUrl:function(t){return Et&&this.options[t+"RetinaUrl"]||this.options[t+"Url"]}}),Mn=On.extend({options:{iconUrl:"marker-icon.png",iconRetinaUrl:"marker-icon-2x.png",shadowUrl:"marker-shadow.png",iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],tooltipAnchor:[16,-28],shadowSize:[41,41]},_getIconUrl:function(t){return Mn.imagePath||(Mn.imagePath=this._detectIconPath()),(this.options.imagePath||Mn.imagePath)+On.prototype._getIconUrl.call(this,t)},_detectIconPath:function(){var t=re("div","leaflet-default-icon-path",document.body),e=oe(t,"background-image")||oe(t,"backgroundImage");return document.body.removeChild(t),null===e||0!==e.indexOf("url")?"":e.replace(/^url\(["']?/,"").replace(/marker-icon\.png["']?\)$/,"")}}),zn=en.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new ln(t,t,!0)),this._draggable.on({dragstart:this._onDragStart,predrag:this._onPreDrag,drag:this._onDrag,dragend:this._onDragEnd},this).enable(),he(t,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off({dragstart:this._onDragStart,predrag:this._onPreDrag,drag:this._onDrag,dragend:this._onDragEnd},this).disable(),this._marker._icon&&fe(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_adjustPan:function(t){var e=this._marker,n=e._map,i=this._marker.options.autoPanSpeed,o=this._marker.options.autoPanPadding,r=ye(e._icon),a=n.getPixelBounds(),s=n.getPixelOrigin(),l=N(a.min._subtract(s).add(o),a.max._subtract(s).subtract(o));if(!l.contains(r)){var u=j((Math.max(l.max.x,r.x)-l.max.x)/(a.max.x-l.max.x)-(Math.min(l.min.x,r.x)-l.min.x)/(a.min.x-l.min.x),(Math.max(l.max.y,r.y)-l.max.y)/(a.max.y-l.max.y)-(Math.min(l.min.y,r.y)-l.min.y)/(a.min.y-l.min.y)).multiplyBy(i);n.panBy(u,{animate:!1}),this._draggable._newPos._add(u),this._draggable._startPos._add(u),ve(e._icon,this._draggable._newPos),this._onDrag(t),this._panRequest=C(this._adjustPan.bind(this,t))}},_onDragStart:function(){this._oldLatLng=this._marker.getLatLng(),this._marker.closePopup().fire("movestart").fire("dragstart")},_onPreDrag:function(t){this._marker.options.autoPan&&(T(this._panRequest),this._panRequest=C(this._adjustPan.bind(this,t)))},_onDrag:function(t){var e=this._marker,n=e._shadow,i=ye(e._icon),o=e._map.layerPointToLatLng(i);n&&ve(n,i),e._latlng=o,t.latlng=o,t.oldLatLng=this._oldLatLng,e.fire("move",t).fire("drag",t)},_onDragEnd:function(t){T(this._panRequest),delete this._oldLatLng,this._marker.fire("moveend").fire("dragend",t)}}),An=Tn.extend({options:{icon:new Mn,interactive:!0,keyboard:!0,title:"",alt:"",zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250,pane:"markerPane",shadowPane:"shadowPane",bubblingMouseEvents:!1,draggable:!1,autoPan:!1,autoPanPadding:[50,50],autoPanSpeed:10},initialize:function(t,e){d(this,e),this._latlng=D(t)},onAdd:function(t){this._zoomAnimated=this._zoomAnimated&&t.options.markerZoomAnimation,this._zoomAnimated&&t.on("zoomanim",this._animateZoom,this),this._initIcon(),this.update()},onRemove:function(t){this.dragging&&this.dragging.enabled()&&(this.options.draggable=!0,this.dragging.removeHooks()),delete this.dragging,this._zoomAnimated&&t.off("zoomanim",this._animateZoom,this),this._removeIcon(),this._removeShadow()},getEvents:function(){return{zoom:this.update,viewreset:this.update}},getLatLng:function(){return this._latlng},setLatLng:function(t){var e=this._latlng;return this._latlng=D(t),this.update(),this.fire("move",{oldLatLng:e,latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update()},getIcon:function(){return this.options.icon},setIcon:function(t){return this.options.icon=t,this._map&&(this._initIcon(),this.update()),this._popup&&this.bindPopup(this._popup,this._popup.options),this},getElement:function(){return this._icon},update:function(){if(this._icon&&this._map){var t=this._map.latLngToLayerPoint(this._latlng).round();this._setPos(t)}return this},_initIcon:function(){var t=this.options,e="leaflet-zoom-"+(this._zoomAnimated?"animated":"hide"),n=t.icon.createIcon(this._icon),i=!1;n!==this._icon&&(this._icon&&this._removeIcon(),i=!0,t.title&&(n.title=t.title),"IMG"===n.tagName&&(n.alt=t.alt||"")),he(n,e),t.keyboard&&(n.tabIndex="0"),this._icon=n,t.riseOnHover&&this.on({mouseover:this._bringToFront,mouseout:this._resetZIndex});var o=t.icon.createShadow(this._shadow),r=!1;o!==this._shadow&&(this._removeShadow(),r=!0),o&&(he(o,e),o.alt=""),this._shadow=o,t.opacity<1&&this._updateOpacity(),i&&this.getPane().appendChild(this._icon),this._initInteraction(),o&&r&&this.getPane(t.shadowPane).appendChild(this._shadow)},_removeIcon:function(){this.options.riseOnHover&&this.off({mouseover:this._bringToFront,mouseout:this._resetZIndex}),ae(this._icon),this.removeInteractiveTarget(this._icon),this._icon=null},_removeShadow:function(){this._shadow&&ae(this._shadow),this._shadow=null},_setPos:function(t){this._icon&&ve(this._icon,t),this._shadow&&ve(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon&&(this._icon.style.zIndex=this._zIndex+t)},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center).round();this._setPos(e)},_initInteraction:function(){if(this.options.interactive&&(he(this._icon,"leaflet-interactive"),this.addInteractiveTarget(this._icon),zn)){var t=this.options.draggable;this.dragging&&(t=this.dragging.enabled(),this.dragging.disable()),this.dragging=new zn(this),t&&this.dragging.enable()}},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},_updateOpacity:function(){var t=this.options.opacity;this._icon&&me(this._icon,t),this._shadow&&me(this._shadow,t)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)},_getPopupAnchor:function(){return this.options.icon.options.popupAnchor},_getTooltipAnchor:function(){return this.options.icon.options.tooltipAnchor}}),jn=Tn.extend({options:{stroke:!0,color:"#3388ff",weight:3,opacity:1,lineCap:"round",lineJoin:"round",dashArray:null,dashOffset:null,fill:!1,fillColor:null,fillOpacity:.2,fillRule:"evenodd",interactive:!0,bubblingMouseEvents:!0},beforeAdd:function(t){this._renderer=t.getRenderer(this)},onAdd:function(){this._renderer._initPath(this),this._reset(),this._renderer._addPath(this)},onRemove:function(){this._renderer._removePath(this)},redraw:function(){return this._map&&this._renderer._updatePath(this),this},setStyle:function(t){return d(this,t),this._renderer&&(this._renderer._updateStyle(this),this.options.stroke&&t&&t.hasOwnProperty("weight")&&this._updateBounds()),this},bringToFront:function(){return this._renderer&&this._renderer._bringToFront(this),this},bringToBack:function(){return this._renderer&&this._renderer._bringToBack(this),this},getElement:function(){return this._path},_reset:function(){this._project(),this._update()},_clickTolerance:function(){return(this.options.stroke?this.options.weight/2:0)+this._renderer.options.tolerance}}),In=jn.extend({options:{fill:!0,radius:10},initialize:function(t,e){d(this,e),this._latlng=D(t),this._radius=this.options.radius},setLatLng:function(t){var e=this._latlng;return this._latlng=D(t),this.redraw(),this.fire("move",{oldLatLng:e,latlng:this._latlng})},getLatLng:function(){return this._latlng},setRadius:function(t){return this.options.radius=this._radius=t,this.redraw()},getRadius:function(){return this._radius},setStyle:function(t){var e=t&&t.radius||this._radius;return jn.prototype.setStyle.call(this,t),this.setRadius(e),this},_project:function(){this._point=this._map.latLngToLayerPoint(this._latlng),this._updateBounds()},_updateBounds:function(){var t=this._radius,e=this._radiusY||t,n=this._clickTolerance(),i=[t+n,e+n];this._pxBounds=new I(this._point.subtract(i),this._point.add(i))},_update:function(){this._map&&this._updatePath()},_updatePath:function(){this._renderer._updateCircle(this)},_empty:function(){return this._radius&&!this._renderer._bounds.intersects(this._pxBounds)},_containsPoint:function(t){return t.distanceTo(this._point)<=this._radius+this._clickTolerance()}}),Nn=In.extend({initialize:function(t,e,i){if("number"==typeof e&&(e=n({},i,{radius:e})),d(this,e),this._latlng=D(t),isNaN(this.options.radius))throw new Error("Circle radius cannot be NaN");this._mRadius=this.options.radius},setRadius:function(t){return this._mRadius=t,this.redraw()},getRadius:function(){return this._mRadius},getBounds:function(){var t=[this._radius,this._radiusY||this._radius];return new R(this._map.layerPointToLatLng(this._point.subtract(t)),this._map.layerPointToLatLng(this._point.add(t)))},setStyle:jn.prototype.setStyle,_project:function(){var t=this._latlng.lng,e=this._latlng.lat,n=this._map,i=n.options.crs;if(i.distance===F.distance){var o=Math.PI/180,r=this._mRadius/F.R/o,a=n.project([e+r,t]),s=n.project([e-r,t]),l=a.add(s).divideBy(2),u=n.unproject(l).lat,c=Math.acos((Math.cos(r*o)-Math.sin(e*o)*Math.sin(u*o))/(Math.cos(e*o)*Math.cos(u*o)))/o;(isNaN(c)||0===c)&&(c=r/Math.cos(Math.PI/180*e)),this._point=l.subtract(n.getPixelOrigin()),this._radius=isNaN(c)?0:l.x-n.project([u,t-c]).x,this._radiusY=l.y-a.y}else{var h=i.unproject(i.project(this._latlng).subtract([this._mRadius,0]));this._point=n.latLngToLayerPoint(this._latlng),this._radius=this._point.x-n.latLngToLayerPoint(h).x}this._updateBounds()}}),Rn=jn.extend({options:{smoothFactor:1,noClip:!1},initialize:function(t,e){d(this,e),this._setLatLngs(t)},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._setLatLngs(t),this.redraw()},isEmpty:function(){return!this._latlngs.length},closestLayerPoint:function(t){for(var e,n,i=1/0,o=null,r=mn,a=0,s=this._parts.length;a<s;a++)for(var l=this._parts[a],u=1,c=l.length;u<c;u++){var h=r(t,e=l[u-1],n=l[u],!0);h<i&&(i=h,o=r(t,e,n))}return o&&(o.distance=Math.sqrt(i)),o},getCenter:function(){if(!this._map)throw new Error("Must add layer to map before using getCenter()");var t,e,n,i,o,r,a,s=this._rings[0],l=s.length;if(!l)return null;for(t=0,e=0;t<l-1;t++)e+=s[t].distanceTo(s[t+1])/2;if(0===e)return this._map.layerPointToLatLng(s[0]);for(t=0,i=0;t<l-1;t++)if(o=s[t],r=s[t+1],(i+=n=o.distanceTo(r))>e)return a=(i-e)/n,this._map.layerPointToLatLng([r.x-a*(r.x-o.x),r.y-a*(r.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,e){return e=e||this._defaultShape(),t=D(t),e.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new R,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return _n(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var e=[],n=_n(t),i=0,o=t.length;i<o;i++)n?(e[i]=D(t[i]),this._bounds.extend(e[i])):e[i]=this._convertLatLngs(t[i]);return e},_project:function(){var t=new I;this._rings=[],this._projectLatlngs(this._latlngs,this._rings,t),this._bounds.isValid()&&t.isValid()&&(this._rawPxBounds=t,this._updateBounds())},_updateBounds:function(){var t=this._clickTolerance(),e=new z(t,t);this._pxBounds=new I([this._rawPxBounds.min.subtract(e),this._rawPxBounds.max.add(e)])},_projectLatlngs:function(t,e,n){var i,o,r=t[0]instanceof Z,a=t.length;if(r){for(o=[],i=0;i<a;i++)o[i]=this._map.latLngToLayerPoint(t[i]),n.extend(o[i]);e.push(o)}else for(i=0;i<a;i++)this._projectLatlngs(t[i],e,n)},_clipPoints:function(){var t=this._renderer._bounds;if(this._parts=[],this._pxBounds&&this._pxBounds.intersects(t))if(this.options.noClip)this._parts=this._rings;else{var e,n,i,o,r,a,s,l=this._parts;for(e=0,i=0,o=this._rings.length;e<o;e++)for(n=0,r=(s=this._rings[e]).length;n<r-1;n++)(a=hn(s[n],s[n+1],t,n,!0))&&(l[i]=l[i]||[],l[i].push(a[0]),a[1]===s[n+1]&&n!==r-2||(l[i].push(a[1]),i++))}},_simplifyPoints:function(){for(var t=this._parts,e=this.options.smoothFactor,n=0,i=t.length;n<i;n++)t[n]=un(t[n],e)},_update:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),this._updatePath())},_updatePath:function(){this._renderer._updatePoly(this)},_containsPoint:function(t,e){var n,i,o,r,a,s,l=this._clickTolerance();if(!this._pxBounds||!this._pxBounds.contains(t))return!1;for(n=0,r=this._parts.length;n<r;n++)for(i=0,o=(a=(s=this._parts[n]).length)-1;i<a;o=i++)if((e||0!==i)&&cn(t,s[o],s[i])<=l)return!0;return!1}});Rn._flat=gn;var Bn=Rn.extend({options:{fill:!0},isEmpty:function(){return!this._latlngs.length||!this._latlngs[0].length},getCenter:function(){if(!this._map)throw new Error("Must add layer to map before using getCenter()");var t,e,n,i,o,r,a,s,l,u=this._rings[0],c=u.length;if(!c)return null;for(r=a=s=0,t=0,e=c-1;t<c;e=t++)n=u[t],i=u[e],o=n.y*i.x-i.y*n.x,a+=(n.x+i.x)*o,s+=(n.y+i.y)*o,r+=3*o;return l=0===r?u[0]:[a/r,s/r],this._map.layerPointToLatLng(l)},_convertLatLngs:function(t){var e=Rn.prototype._convertLatLngs.call(this,t),n=e.length;return n>=2&&e[0]instanceof Z&&e[0].equals(e[n-1])&&e.pop(),e},_setLatLngs:function(t){Rn.prototype._setLatLngs.call(this,t),_n(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return _n(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,e=this.options.weight,n=new z(e,e);if(t=new I(t.min.subtract(n),t.max.add(n)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t))if(this.options.noClip)this._parts=this._rings;else for(var i,o=0,r=this._rings.length;o<r;o++)(i=yn(this._rings[o],t,!0)).length&&this._parts.push(i)},_updatePath:function(){this._renderer._updatePoly(this,!0)},_containsPoint:function(t){var e,n,i,o,r,a,s,l,u=!1;if(!this._pxBounds||!this._pxBounds.contains(t))return!1;for(o=0,s=this._parts.length;o<s;o++)for(r=0,a=(l=(e=this._parts[o]).length)-1;r<l;a=r++)n=e[r],i=e[a],n.y>t.y!=i.y>t.y&&t.x<(i.x-n.x)*(t.y-n.y)/(i.y-n.y)+n.x&&(u=!u);return u||Rn.prototype._containsPoint.call(this,t,!0)}}),Zn=Sn.extend({initialize:function(t,e){d(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,n,i,o=g(t)?t:t.features;if(o){for(e=0,n=o.length;e<n;e++)((i=o[e]).geometries||i.geometry||i.features||i.coordinates)&&this.addData(i);return this}var r=this.options;if(r.filter&&!r.filter(t))return this;var a=Dn(t,r);return a?(a.feature=qn(t),a.defaultOptions=a.options,this.resetStyle(a),r.onEachFeature&&r.onEachFeature(t,a),this.addLayer(a)):this},resetStyle:function(t){return void 0===t?this.eachLayer(this.resetStyle,this):(t.options=n({},t.defaultOptions),this._setLayerStyle(t,this.options.style),this)},setStyle:function(t){return this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){t.setStyle&&("function"==typeof e&&(e=e(t.feature)),t.setStyle(e))}});function Dn(t,e){var n,i,o,r,a="Feature"===t.type?t.geometry:t,s=a?a.coordinates:null,l=[],u=e&&e.pointToLayer,c=e&&e.coordsToLatLng||Fn;if(!s&&!a)return null;switch(a.type){case"Point":return Un(u,t,n=c(s),e);case"MultiPoint":for(o=0,r=s.length;o<r;o++)n=c(s[o]),l.push(Un(u,t,n,e));return new Sn(l);case"LineString":case"MultiLineString":return i=Wn(s,"LineString"===a.type?0:1,c),new Rn(i,e);case"Polygon":case"MultiPolygon":return i=Wn(s,"Polygon"===a.type?1:2,c),new Bn(i,e);case"GeometryCollection":for(o=0,r=a.geometries.length;o<r;o++){var h=Dn({geometry:a.geometries[o],type:"Feature",properties:t.properties},e);h&&l.push(h)}return new Sn(l);default:throw new Error("Invalid GeoJSON object.")}}function Un(t,e,n,i){return t?t(e,n):new An(n,i&&i.markersInheritOptions&&i)}function Fn(t){return new Z(t[1],t[0],t[2])}function Wn(t,e,n){for(var i,o=[],r=0,a=t.length;r<a;r++)i=e?Wn(t[r],e-1,n):(n||Fn)(t[r]),o.push(i);return o}function Hn(t,e){return e="number"==typeof e?e:6,void 0!==t.alt?[c(t.lng,e),c(t.lat,e),c(t.alt,e)]:[c(t.lng,e),c(t.lat,e)]}function Vn(t,e,n,i){for(var o=[],r=0,a=t.length;r<a;r++)o.push(e?Vn(t[r],e-1,n,i):Hn(t[r],i));return!e&&n&&o.push(o[0]),o}function Gn(t,e){return t.feature?n({},t.feature,{geometry:e}):qn(e)}function qn(t){return"Feature"===t.type||"FeatureCollection"===t.type?t:{type:"Feature",properties:{},geometry:t}}var Kn={toGeoJSON:function(t){return Gn(this,{type:"Point",coordinates:Hn(this.getLatLng(),t)})}};function Qn(t,e){return new Zn(t,e)}An.include(Kn),Nn.include(Kn),In.include(Kn),Rn.include({toGeoJSON:function(t){var e=!_n(this._latlngs);return Gn(this,{type:(e?"Multi":"")+"LineString",coordinates:Vn(this._latlngs,e?1:0,!1,t)})}}),Bn.include({toGeoJSON:function(t){var e=!_n(this._latlngs),n=e&&!_n(this._latlngs[0]),i=Vn(this._latlngs,n?2:e?1:0,!0,t);return e||(i=[i]),Gn(this,{type:(n?"Multi":"")+"Polygon",coordinates:i})}}),Pn.include({toMultiPoint:function(t){var e=[];return this.eachLayer(function(n){e.push(n.toGeoJSON(t).geometry.coordinates)}),Gn(this,{type:"MultiPoint",coordinates:e})},toGeoJSON:function(t){var e=this.feature&&this.feature.geometry&&this.feature.geometry.type;if("MultiPoint"===e)return this.toMultiPoint(t);var n="GeometryCollection"===e,i=[];return this.eachLayer(function(e){if(e.toGeoJSON){var o=e.toGeoJSON(t);if(n)i.push(o.geometry);else{var r=qn(o);"FeatureCollection"===r.type?i.push.apply(i,r.features):i.push(r)}}}),n?Gn(this,{geometries:i,type:"GeometryCollection"}):{type:"FeatureCollection",features:i}}});var Yn=Qn,Jn=Tn.extend({options:{opacity:1,alt:"",interactive:!1,crossOrigin:!1,errorOverlayUrl:"",zIndex:1,className:""},initialize:function(t,e,n){this._url=t,this._bounds=B(e),d(this,n)},onAdd:function(){this._image||(this._initImage(),this.options.opacity<1&&this._updateOpacity()),this.options.interactive&&(he(this._image,"leaflet-interactive"),this.addInteractiveTarget(this._image)),this.getPane().appendChild(this._image),this._reset()},onRemove:function(){ae(this._image),this.options.interactive&&this.removeInteractiveTarget(this._image)},setOpacity:function(t){return this.options.opacity=t,this._image&&this._updateOpacity(),this},setStyle:function(t){return t.opacity&&this.setOpacity(t.opacity),this},bringToFront:function(){return this._map&&le(this._image),this},bringToBack:function(){return this._map&&ue(this._image),this},setUrl:function(t){return this._url=t,this._image&&(this._image.src=t),this},setBounds:function(t){return this._bounds=B(t),this._map&&this._reset(),this},getEvents:function(){var t={zoom:this._reset,viewreset:this._reset};return this._zoomAnimated&&(t.zoomanim=this._animateZoom),t},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},getBounds:function(){return this._bounds},getElement:function(){return this._image},_initImage:function(){var t="IMG"===this._url.tagName,e=this._image=t?this._url:re("img");he(e,"leaflet-image-layer"),this._zoomAnimated&&he(e,"leaflet-zoom-animated"),this.options.className&&he(e,this.options.className),e.onselectstart=u,e.onmousemove=u,e.onload=o(this.fire,this,"load"),e.onerror=o(this._overlayOnError,this,"error"),(this.options.crossOrigin||""===this.options.crossOrigin)&&(e.crossOrigin=!0===this.options.crossOrigin?"":this.options.crossOrigin),this.options.zIndex&&this._updateZIndex(),t?this._url=e.src:(e.src=this._url,e.alt=this.options.alt)},_animateZoom:function(t){var e=this._map.getZoomScale(t.zoom),n=this._map._latLngBoundsToNewLayerBounds(this._bounds,t.zoom,t.center).min;ge(this._image,n,e)},_reset:function(){var t=this._image,e=new I(this._map.latLngToLayerPoint(this._bounds.getNorthWest()),this._map.latLngToLayerPoint(this._bounds.getSouthEast())),n=e.getSize();ve(t,e.min),t.style.width=n.x+"px",t.style.height=n.y+"px"},_updateOpacity:function(){me(this._image,this.options.opacity)},_updateZIndex:function(){this._image&&void 0!==this.options.zIndex&&null!==this.options.zIndex&&(this._image.style.zIndex=this.options.zIndex)},_overlayOnError:function(){this.fire("error");var t=this.options.errorOverlayUrl;t&&this._url!==t&&(this._url=t,this._image.src=t)}}),Xn=Jn.extend({options:{autoplay:!0,loop:!0,keepAspectRatio:!0},_initImage:function(){var t="VIDEO"===this._url.tagName,e=this._image=t?this._url:re("video");if(he(e,"leaflet-image-layer"),this._zoomAnimated&&he(e,"leaflet-zoom-animated"),this.options.className&&he(e,this.options.className),e.onselectstart=u,e.onmousemove=u,e.onloadeddata=o(this.fire,this,"load"),t){for(var n=e.getElementsByTagName("source"),i=[],r=0;r<n.length;r++)i.push(n[r].src);this._url=n.length>0?i:[e.src]}else{g(this._url)||(this._url=[this._url]),!this.options.keepAspectRatio&&e.style.hasOwnProperty("objectFit")&&(e.style.objectFit="fill"),e.autoplay=!!this.options.autoplay,e.loop=!!this.options.loop;for(var a=0;a<this._url.length;a++){var s=re("source");s.src=this._url[a],e.appendChild(s)}}}}),$n=Jn.extend({_initImage:function(){var t=this._image=this._url;he(t,"leaflet-image-layer"),this._zoomAnimated&&he(t,"leaflet-zoom-animated"),this.options.className&&he(t,this.options.className),t.onselectstart=u,t.onmousemove=u}}),ti=Tn.extend({options:{offset:[0,7],className:"",pane:"popupPane"},initialize:function(t,e){d(this,t),this._source=e},onAdd:function(t){this._zoomAnimated=t._zoomAnimated,this._container||this._initLayout(),t._fadeAnimated&&me(this._container,0),clearTimeout(this._removeTimeout),this.getPane().appendChild(this._container),this.update(),t._fadeAnimated&&me(this._container,1),this.bringToFront()},onRemove:function(t){t._fadeAnimated?(me(this._container,0),this._removeTimeout=setTimeout(o(ae,void 0,this._container),200)):ae(this._container)},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=D(t),this._map&&(this._updatePosition(),this._adjustPan()),this},getContent:function(){return this._content},setContent:function(t){return this._content=t,this.update(),this},getElement:function(){return this._container},update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout(),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},getEvents:function(){var t={zoom:this._updatePosition,viewreset:this._updatePosition};return this._zoomAnimated&&(t.zoomanim=this._animateZoom),t},isOpen:function(){return!!this._map&&this._map.hasLayer(this)},bringToFront:function(){return this._map&&le(this._container),this},bringToBack:function(){return this._map&&ue(this._container),this},_prepareOpen:function(t,e,n){if(e instanceof Tn||(n=e,e=t),e instanceof Sn)for(var i in t._layers){e=t._layers[i];break}if(!n)if(e.getCenter)n=e.getCenter();else{if(!e.getLatLng)throw new Error("Unable to get source layer LatLng.");n=e.getLatLng()}return this._source=e,this.update(),n},_updateContent:function(){if(this._content){var t=this._contentNode,e="function"==typeof this._content?this._content(this._source||this):this._content;if("string"==typeof e)t.innerHTML=e;else{for(;t.hasChildNodes();)t.removeChild(t.firstChild);t.appendChild(e)}this.fire("contentupdate")}},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=j(this.options.offset),n=this._getAnchor();this._zoomAnimated?ve(this._container,t.add(n)):e=e.add(t).add(n);var i=this._containerBottom=-e.y,o=this._containerLeft=-Math.round(this._containerWidth/2)+e.x;this._container.style.bottom=i+"px",this._container.style.left=o+"px"}},_getAnchor:function(){return[0,0]}}),ei=ti.extend({options:{maxWidth:300,minWidth:50,maxHeight:null,autoPan:!0,autoPanPaddingTopLeft:null,autoPanPaddingBottomRight:null,autoPanPadding:[5,5],keepInView:!1,closeButton:!0,autoClose:!0,closeOnEscapeKey:!0,className:""},openOn:function(t){return t.openPopup(this),this},onAdd:function(t){ti.prototype.onAdd.call(this,t),t.fire("popupopen",{popup:this}),this._source&&(this._source.fire("popupopen",{popup:this},!0),this._source instanceof jn||this._source.on("preclick",Ae))},onRemove:function(t){ti.prototype.onRemove.call(this,t),t.fire("popupclose",{popup:this}),this._source&&(this._source.fire("popupclose",{popup:this},!0),this._source instanceof jn||this._source.off("preclick",Ae))},getEvents:function(){var t=ti.prototype.getEvents.call(this);return(void 0!==this.options.closeOnClick?this.options.closeOnClick:this._map.options.closePopupOnClick)&&(t.preclick=this._close),this.options.keepInView&&(t.moveend=this._adjustPan),t},_close:function(){this._map&&this._map.closePopup(this)},_initLayout:function(){var t="leaflet-popup",e=this._container=re("div",t+" "+(this.options.className||"")+" leaflet-zoom-animated"),n=this._wrapper=re("div",t+"-content-wrapper",e);if(this._contentNode=re("div",t+"-content",n),Ie(n),je(this._contentNode),Pe(n,"contextmenu",Ae),this._tipContainer=re("div",t+"-tip-container",e),this._tip=re("div",t+"-tip",this._tipContainer),this.options.closeButton){var i=this._closeButton=re("a",t+"-close-button",e);i.href="#close",i.innerHTML="×",Pe(i,"click",this._onCloseButtonClick,this)}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var n=t.offsetWidth;n=Math.min(n,this.options.maxWidth),n=Math.max(n,this.options.minWidth),e.width=n+1+"px",e.whiteSpace="",e.height="";var i=t.offsetHeight,o=this.options.maxHeight;o&&i>o?(e.height=o+"px",he(t,"leaflet-popup-scrolled")):fe(t,"leaflet-popup-scrolled"),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),n=this._getAnchor();ve(this._container,e.add(n))},_adjustPan:function(){if(this.options.autoPan){this._map._panAnim&&this._map._panAnim.stop();var t=this._map,e=parseInt(oe(this._container,"marginBottom"),10)||0,n=this._container.offsetHeight+e,i=this._containerWidth,o=new z(this._containerLeft,-n-this._containerBottom);o._add(ye(this._container));var r=t.layerPointToContainerPoint(o),a=j(this.options.autoPanPadding),s=j(this.options.autoPanPaddingTopLeft||a),l=j(this.options.autoPanPaddingBottomRight||a),u=t.getSize(),c=0,h=0;r.x+i+l.x>u.x&&(c=r.x+i-u.x+l.x),r.x-c-s.x<0&&(c=r.x-s.x),r.y+n+l.y>u.y&&(h=r.y+n-u.y+l.y),r.y-h-s.y<0&&(h=r.y-s.y),(c||h)&&t.fire("autopanstart").panBy([c,h])}},_onCloseButtonClick:function(t){this._close(),Re(t)},_getAnchor:function(){return j(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});Ke.mergeOptions({closePopupOnClick:!0}),Ke.include({openPopup:function(t,e,n){return t instanceof ei||(t=new ei(n).setContent(t)),e&&t.setLatLng(e),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),Tn.include({bindPopup:function(t,e){return t instanceof ei?(d(t,e),this._popup=t,t._source=this):(this._popup&&!e||(this._popup=new ei(e,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,e){return this._popup&&this._map&&(e=this._popup._prepareOpen(this,t,e),this._map.openPopup(this._popup,e)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.cl
gitextract_wblmb6r9/ ├── .gitignore ├── .npmignore ├── .vscode/ │ └── settings.json ├── HTML/ │ ├── .gitignore │ ├── gulpfile.js │ ├── package.json │ ├── public/ │ │ ├── index.html │ │ ├── manifest.json │ │ └── robots.txt │ ├── readme.md │ ├── src/ │ │ ├── MapComponent.test.tsx │ │ ├── MapComponent.view.test.tsx │ │ ├── MapLayers.test.tsx │ │ ├── MapLayers.tsx │ │ ├── MapMarkers.tsx │ │ ├── MapShapes.tsx │ │ ├── __snapshots__/ │ │ │ ├── MapComponent.test.tsx.snap │ │ │ ├── MapComponent.view.test.tsx.snap │ │ │ └── MapLayers.test.tsx.snap │ │ ├── index.css │ │ ├── index.tsx │ │ ├── mapComponent.tsx │ │ ├── mapComponent.view.tsx │ │ ├── models.ts │ │ ├── react-app-env.d.ts │ │ ├── serviceWorker.ts │ │ ├── setupTests.ts │ │ ├── styles/ │ │ │ ├── markerAnimations.css │ │ │ └── markers.css │ │ ├── testData/ │ │ │ ├── mockMapLayers.ts │ │ │ ├── mockMapMarkers.ts │ │ │ ├── mockMapShapes.ts │ │ │ └── svgIcons.ts │ │ ├── utilities.test.ts.old │ │ ├── utilities.ts │ │ └── webBase64Image.ts │ └── tsconfig.json ├── WebViewLeaflet/ │ ├── ActivityOverlay.tsx │ ├── DebugMessageBox.tsx │ ├── WebViewLeaflet.tsx │ ├── WebViewLeaflet.view.tsx │ ├── assets/ │ │ └── index.html │ ├── index.d.ts │ ├── index.ts │ ├── models.ts │ ├── package.json │ └── yarn-error.log ├── demoApp/ │ ├── .expo-shared/ │ │ └── assets.json │ ├── .gitignore │ ├── App.tsx │ ├── app.json │ ├── babel.config.js │ ├── gulpfile.js │ ├── package.json │ ├── tsconfig.json │ └── yarn-error.log ├── package.json └── readme.md
SYMBOL INDEX (75 symbols across 14 files)
FILE: HTML/gulpfile.js
constant REACT_BUILD_DIRECTORY (line 7) | const REACT_BUILD_DIRECTORY = "build";
constant REACT_BUILD_FILES (line 8) | const REACT_BUILD_FILES = "./build/*.html";
constant FILE_NAME_AFTER_ADDING_INLINE_TAGS (line 9) | const FILE_NAME_AFTER_ADDING_INLINE_TAGS = "indexWithTags.html";
constant DIST_HTML_FILE_NAME (line 10) | const DIST_HTML_FILE_NAME = "index.html";
constant DIST_DIRECTORY (line 11) | const DIST_DIRECTORY = "dist";
FILE: HTML/src/MapLayers.tsx
type MapLayersProps (line 15) | interface MapLayersProps {
class MapLayers (line 19) | class MapLayers extends React.Component<MapLayersProps> {
method render (line 51) | render() {
FILE: HTML/src/MapMarkers.tsx
type MapMarkersProps (line 13) | interface MapMarkersProps {
class MapMarkers (line 19) | class MapMarkers extends React.Component<MapMarkersProps> {
method render (line 37) | render() {
FILE: HTML/src/MapShapes.tsx
type MapMapShapesProps (line 16) | interface MapMapShapesProps {
class MapShapes (line 21) | class MapShapes extends React.Component<MapMapShapesProps> {
method render (line 44) | render() {
FILE: HTML/src/mapComponent.tsx
constant SHOW_DEBUG_INFORMATION (line 27) | const SHOW_DEBUG_INFORMATION = false;
constant ENABLE_BROWSER_TESTING (line 28) | const ENABLE_BROWSER_TESTING = true;
type State (line 30) | interface State {
class MapComponent (line 43) | class MapComponent extends Component<{}, State> {
method constructor (line 44) | constructor(props: {}) {
method render (line 194) | render() {
FILE: HTML/src/mapComponent.view.tsx
type MapComponentViewProps (line 12) | interface MapComponentViewProps {
FILE: HTML/src/models.ts
type LatLng (line 2) | type LatLng = ReactLeaflet.LatLng;
type Point (line 3) | type Point = ReactLeaflet.Point;
type LatLngBounds (line 4) | type LatLngBounds = ReactLeaflet.LatLngBounds;
constant OWN_POSTION_MARKER_ID (line 6) | const OWN_POSTION_MARKER_ID = "OWN_POSTION_MARKER_ID";
type WebViewLeafletEvents (line 8) | enum WebViewLeafletEvents {
type AnimationType (line 31) | enum AnimationType {
type MapLayerType (line 40) | enum MapLayerType {
type MapShapeType (line 48) | enum MapShapeType {
constant INFINITE_ANIMATION_ITERATIONS (line 56) | const INFINITE_ANIMATION_ITERATIONS: string = "infinite";
type AnimationDirection (line 58) | enum AnimationDirection {
type MapMarkerAnimation (line 64) | interface MapMarkerAnimation {
type MapMarker (line 72) | interface MapMarker {
type MapEventMessage (line 83) | interface MapEventMessage {
type MapLayer (line 90) | interface MapLayer {
type MapShape (line 105) | interface MapShape {
type MapStartupMessage (line 115) | interface MapStartupMessage {
type WebviewLeafletMessagePayload (line 124) | type WebviewLeafletMessagePayload = {
type WebviewLeafletMessage (line 132) | interface WebviewLeafletMessage {
type OwnPositionMarker (line 139) | type OwnPositionMarker = {
FILE: HTML/src/serviceWorker.ts
type Config (line 23) | type Config = {
function register (line 28) | function register(config?: Config) {
function registerValidSW (line 65) | function registerValidSW(swUrl: string, config?: Config) {
function checkValidServiceWorker (line 109) | function checkValidServiceWorker(swUrl: string, config?: Config) {
function unregister (line 139) | function unregister() {
FILE: WebViewLeaflet/ActivityOverlay.tsx
type Props (line 4) | interface Props {}
FILE: WebViewLeaflet/DebugMessageBox.tsx
type Props (line 4) | interface Props {
FILE: WebViewLeaflet/WebViewLeaflet.tsx
constant INDEX_FILE_PATH (line 21) | const INDEX_FILE_PATH = require(`./assets/index.html`);
type WebViewLeafletProps (line 23) | interface WebViewLeafletProps {
type State (line 39) | interface State {
class WebViewLeaflet (line 46) | class WebViewLeaflet extends React.Component<WebViewLeafletProps, State> {
method constructor (line 60) | constructor(props) {
method render (line 223) | render() {
FILE: WebViewLeaflet/WebViewLeaflet.view.tsx
type Props (line 8) | interface Props {
FILE: WebViewLeaflet/models.ts
type LatLng (line 2) | type LatLng = ReactLeaflet.LatLng;
type Point (line 3) | type Point = ReactLeaflet.Point;
type LatLngBounds (line 4) | type LatLngBounds = ReactLeaflet.LatLngBounds;
constant OWN_POSTION_MARKER_ID (line 6) | const OWN_POSTION_MARKER_ID = "OWN_POSTION_MARKER_ID";
type WebViewLeafletEvents (line 8) | enum WebViewLeafletEvents {
type AnimationType (line 31) | enum AnimationType {
type MapLayerType (line 40) | enum MapLayerType {
type MapShapeType (line 48) | enum MapShapeType {
constant INFINITE_ANIMATION_ITERATIONS (line 56) | const INFINITE_ANIMATION_ITERATIONS: string = "infinite";
type AnimationDirection (line 58) | enum AnimationDirection {
type MapMarkerAnimation (line 64) | interface MapMarkerAnimation {
type MapMarker (line 72) | interface MapMarker {
type MapEventMessage (line 83) | interface MapEventMessage {
type MapLayer (line 90) | interface MapLayer {
type MapShape (line 105) | interface MapShape {
type MapStartupMessage (line 115) | interface MapStartupMessage {
type WebviewLeafletMessagePayload (line 124) | type WebviewLeafletMessagePayload = {
type WebviewLeafletMessage (line 132) | interface WebviewLeafletMessage {
type OwnPositionMarker (line 139) | type OwnPositionMarker = {
FILE: demoApp/App.tsx
type LatLngObject (line 18) | type LatLngObject = { lat: number; lng: number };
function App (line 51) | function App() {
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,143K chars).
[
{
"path": ".gitignore",
"chars": 385,
"preview": "node_modules/**/*\n.expo/*\nnpm-debug.*\n*.jks\n*.p8\n*.p12\n*.key\n*.mobileprovision\n*.orig.*\nweb-build/\nweb-report/\nHTML/dist"
},
{
"path": ".npmignore",
"chars": 172,
"preview": "..\\..\\..\\..\\c:\\Users\\regin\\Dropbox\\react-native-webview-leaflet-5\\html\\build\\index.html\n..\\..\\..\\..\\c:\\Users\\regin\\Dropb"
},
{
"path": ".vscode/settings.json",
"chars": 38,
"preview": "{\n \"git.ignoreLimitWarning\": true\n}"
},
{
"path": "HTML/.gitignore",
"chars": 310,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "HTML/gulpfile.js",
"chars": 1833,
"preview": "const gulp = require(\"gulp\");\nconst inlinesource = require(\"gulp-inline-source\");\nconst replace = require(\"gulp-replace\""
},
{
"path": "HTML/package.json",
"chars": 1743,
"preview": "{\n \"name\": \"html\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"dependencies\": {\n \"@testing-library/jest-dom\": \"^4.2."
},
{
"path": "HTML/public/index.html",
"chars": 785,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-w"
},
{
"path": "HTML/public/manifest.json",
"chars": 492,
"preview": "{\n \"short_name\": \"React App\",\n \"name\": \"Create React App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n "
},
{
"path": "HTML/public/robots.txt",
"chars": 57,
"preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\n"
},
{
"path": "HTML/readme.md",
"chars": 2083,
"preview": "This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).\n\n## Available Scrip"
},
{
"path": "HTML/src/MapComponent.test.tsx",
"chars": 289,
"preview": "import React from \"react\";\nimport { render } from \"@testing-library/react\";\nimport MapComponent from \"./MapComponent\";\n\n"
},
{
"path": "HTML/src/MapComponent.view.test.tsx",
"chars": 554,
"preview": "import React from \"react\";\nimport { render } from \"@testing-library/react\";\nimport MapComponentView from \"./MapComponent"
},
{
"path": "HTML/src/MapLayers.test.tsx",
"chars": 577,
"preview": "import * as React from \"react\";\nimport { default as MapLayerComponent } from \"./MapLayers\";\nimport { render } from \"@tes"
},
{
"path": "HTML/src/MapLayers.tsx",
"chars": 1612,
"preview": "import * as React from \"react\";\nimport {\n TileLayer,\n LayersControl,\n WMSTileLayer,\n WMSTileLayerProps,\n TileLayerP"
},
{
"path": "HTML/src/MapMarkers.tsx",
"chars": 2263,
"preview": "import * as React from \"react\";\nimport { LayerGroup, Marker, Popup } from \"react-leaflet\";\nimport MarkerClusterGroup fro"
},
{
"path": "HTML/src/MapShapes.tsx",
"chars": 1470,
"preview": "import * as React from \"react\";\nimport {\n Circle,\n Polygon,\n CircleMarker,\n Polyline,\n Rectangle,\n CircleMarkerPro"
},
{
"path": "HTML/src/__snapshots__/MapComponent.test.tsx.snap",
"chars": 271,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`MapComponent it renders 1`] = `\n<DocumentFragment>\n <div\n id=\"m"
},
{
"path": "HTML/src/__snapshots__/MapComponent.view.test.tsx.snap",
"chars": 275,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`MapComponentView it renders 1`] = `\n<DocumentFragment>\n <div\n i"
},
{
"path": "HTML/src/__snapshots__/MapLayers.test.tsx.snap",
"chars": 4875,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`MapLayers Component it renders 1`] = `\n<DocumentFragment>\n <div\n "
},
{
"path": "HTML/src/index.css",
"chars": 366,
"preview": "body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Can"
},
{
"path": "HTML/src/index.tsx",
"chars": 461,
"preview": "import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./index.css\";\nimport App from \"./MapComponent\";\nimp"
},
{
"path": "HTML/src/mapComponent.tsx",
"chars": 5929,
"preview": "import React, { Component } from \"react\";\nimport \"leaflet/dist/leaflet.css\";\nimport \"leaflet/dist/images/layers-2x.png\";"
},
{
"path": "HTML/src/mapComponent.view.tsx",
"chars": 4804,
"preview": "import * as React from \"react\";\nimport { useState, useEffect } from \"react\";\nimport Measure from \"react-measure\";\nimport"
},
{
"path": "HTML/src/models.ts",
"chars": 3488,
"preview": "import * as ReactLeaflet from \"react-leaflet\";\nexport type LatLng = ReactLeaflet.LatLng;\nexport type Point = ReactLeafle"
},
{
"path": "HTML/src/react-app-env.d.ts",
"chars": 40,
"preview": "/// <reference types=\"react-scripts\" />\n"
},
{
"path": "HTML/src/serviceWorker.ts",
"chars": 5213,
"preview": "// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the ap"
},
{
"path": "HTML/src/setupTests.ts",
"chars": 255,
"preview": "// jest-dom adds custom jest matchers for asserting on DOM nodes.\n// allows you to do things like:\n// expect(element).to"
},
{
"path": "HTML/src/styles/markerAnimations.css",
"chars": 1717,
"preview": ".marker {\n background-color: rgba(255, 255, 255, 0);\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n/* div con"
},
{
"path": "HTML/src/styles/markers.css",
"chars": 1742,
"preview": "/*General marker style*/\n.marker {\n background-color: rgba(255, 255, 255, 0);\n width: 100%;\n height: 100%;\n position"
},
{
"path": "HTML/src/testData/mockMapLayers.ts",
"chars": 1031,
"preview": "import { MapLayer, MapLayerType } from \"../models\";\n\nconst mockMapLayers: MapLayer[] = [\n {\n attribution:\n '&am"
},
{
"path": "HTML/src/testData/mockMapMarkers.ts",
"chars": 7207,
"preview": "import * as svgIcons from \"./svgIcons\";\nimport { LatLng } from \"leaflet\";\nimport { MapMarker, AnimationType } from \"../m"
},
{
"path": "HTML/src/testData/mockMapShapes.ts",
"chars": 2426,
"preview": "import { MapShapeType, MapShape } from \"../models\";\n\nexport const circle: MapShape = {\n shapeType: MapShapeType.CIRCLE,"
},
{
"path": "HTML/src/testData/svgIcons.ts",
"chars": 146,
"preview": "export const greenCircle = `<svg xmlns=\"http://www.w3.org/2000/svg\">\n <circle id=\"greencircle\" cx=\"30\" cy=\"30\" r=\"30\""
},
{
"path": "HTML/src/utilities.test.ts.old",
"chars": 4140,
"preview": "import {\n convertWebViewLeafletLatLngToNumberArray,\n convertWebViewLeafletLatLngBoundsToLeaftletBounds,\n getAnimatedH"
},
{
"path": "HTML/src/utilities.ts",
"chars": 2207,
"preview": "import L, { DivIcon } from \"leaflet\";\nimport base64Image from \"./webBase64Image\";\nimport { MapMarker, MapMarkerAnimation"
},
{
"path": "HTML/src/webBase64Image.ts",
"chars": 2681,
"preview": "const base64Image =\n 'data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8"
},
{
"path": "HTML/tsconfig.json",
"chars": 522,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"lib\": [\n \"dom\",\n \"dom.iterable\",\n \"esnext\"\n ],\n "
},
{
"path": "WebViewLeaflet/ActivityOverlay.tsx",
"chars": 916,
"preview": "import React from 'react';\nimport { View, ActivityIndicator, StyleSheet } from 'react-native';\n\ninterface Props {}\n\nexpo"
},
{
"path": "WebViewLeaflet/DebugMessageBox.tsx",
"chars": 1039,
"preview": "import React from \"react\";\nimport { ScrollView, Text, View } from \"react-native\";\n\nexport interface Props {\n debugMessa"
},
{
"path": "WebViewLeaflet/WebViewLeaflet.tsx",
"chars": 6885,
"preview": "import * as React from \"react\";\nimport { WebView } from \"react-native-webview\";\nimport AssetUtils from \"expo-asset-utils"
},
{
"path": "WebViewLeaflet/WebViewLeaflet.view.tsx",
"chars": 2276,
"preview": "import React, { ReactElement } from 'react';\nimport { StyleSheet, View, NativeSyntheticEvent } from 'react-native';\nimpo"
},
{
"path": "WebViewLeaflet/assets/index.html",
"chars": 406856,
"preview": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width,initial-sc"
},
{
"path": "WebViewLeaflet/index.d.ts",
"chars": 1089,
"preview": "import React from \"react\";\nimport { WebViewError } from \"react-native-webview/lib/WebViewTypes\";\n\n// Type definitions fo"
},
{
"path": "WebViewLeaflet/index.ts",
"chars": 349,
"preview": "export {\n default as WebViewLeaflet,\n WebViewLeafletProps\n} from \"./WebViewLeaflet\";\nexport {\n LatLng,\n Point,\n Lat"
},
{
"path": "WebViewLeaflet/models.ts",
"chars": 3488,
"preview": "import * as ReactLeaflet from \"react-leaflet\";\nexport type LatLng = ReactLeaflet.LatLng;\nexport type Point = ReactLeafle"
},
{
"path": "WebViewLeaflet/package.json",
"chars": 1346,
"preview": "{\n \"name\": \"react-native-webview-leaflet\",\n \"version\": \"5.0.2\",\n \"description\": \"A React Native component that uses a"
},
{
"path": "WebViewLeaflet/yarn-error.log",
"chars": 308050,
"preview": "Arguments: \n C:\\Program Files\\nodejs\\node.exe C:\\Program Files (x86)\\Yarn\\bin\\yarn.js add FileSystem\n\nPATH: \n C:\\Progr"
},
{
"path": "demoApp/.expo-shared/assets.json",
"chars": 154,
"preview": "{\n \"f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd\": true,\n \"89ed26367cdb9b771858e026f2eb95bfdb90e5a"
},
{
"path": "demoApp/.gitignore",
"chars": 130,
"preview": "node_modules/**/*\n.expo/*\nnpm-debug.*\n*.jks\n*.p8\n*.p12\n*.key\n*.mobileprovision\n*.orig.*\nweb-build/\nweb-report/\n\n# macOS\n"
},
{
"path": "demoApp/App.tsx",
"chars": 10276,
"preview": "import React, { useState, useEffect } from \"react\";\nimport { Alert, StyleSheet, Text, View } from \"react-native\";\nimport"
},
{
"path": "demoApp/app.json",
"chars": 583,
"preview": "{\n \"expo\": {\n \"name\": \"react-native-webview-leaflet-demo\",\n \"slug\": \"demoApp\",\n \"privacy\": \"public\",\n \"sdkV"
},
{
"path": "demoApp/babel.config.js",
"chars": 107,
"preview": "module.exports = function(api) {\n api.cache(true);\n return {\n presets: ['babel-preset-expo'],\n };\n};\n"
},
{
"path": "demoApp/gulpfile.js",
"chars": 231,
"preview": "const gulp = require(\"gulp\");\nconst clean = require(\"gulp-clean\");\nconst run = require(\"gulp-run\");\n\ngulp.task(\"clean\", "
},
{
"path": "demoApp/package.json",
"chars": 1077,
"preview": "{\n \"main\": \"node_modules/expo/AppEntry.js\",\n \"scripts\": {\n \"start\": \"expo start\",\n \"android\": \"expo start --andr"
},
{
"path": "demoApp/tsconfig.json",
"chars": 238,
"preview": "{\n \"compilerOptions\": {\n \"allowSyntheticDefaultImports\": true,\n \"jsx\": \"react-native\",\n \"lib\": [\"dom\", \"esnext"
},
{
"path": "demoApp/yarn-error.log",
"chars": 279188,
"preview": "Arguments: \n C:\\Program Files\\nodejs\\node.exe C:\\Program Files (x86)\\Yarn\\bin\\yarn.js add @types/native-base\n\nPATH: \n "
},
{
"path": "package.json",
"chars": 78,
"preview": "{\n \"devDependencies\": {\n \"gulp\": \"^4.0.2\",\n \"gulp-run\": \"^1.7.1\"\n }\n}\n"
},
{
"path": "readme.md",
"chars": 11678,
"preview": "# React Native Webview Leaflet V5\n\n## A Leaflet map component with no native code for React Native applications\n\n### Why"
}
]
About this extraction
This page contains the full source code of the reggie3/react-native-webview-leaflet GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (1.0 MB), approximately 425.4k tokens, and a symbol index with 75 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.