From 4335166c555d7a408e794cbdf565ce95f242775e Mon Sep 17 00:00:00 2001 From: Lukas0912 <109222100+Lukas0912@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:34:38 +0100 Subject: [PATCH] Feature/f 30 implement map with selectable countries (#22) * feat: setup geojson and implement selectable countries * feat: introduce mapbox as an example * feat: change hovering to mapbox components * feat: refactor and add roads * feat: adjust colors according to Figma * fix: code style changes --------- Co-authored-by: marinovl7 --- .env_template | 2 + package.json | 3 + src/components/Map/Map.tsx | 72 +------- src/components/Map/VectorTileLayer.tsx | 34 ++++ src/domain/entities/map/MapColorsType.ts | 7 + src/operations/map/MapOperations.ts | 187 +++++++++++++++++++ src/styles/MapColors.ts | 9 + yarn.lock | 217 ++++++++++++++++++++++- 8 files changed, 462 insertions(+), 69 deletions(-) create mode 100644 src/components/Map/VectorTileLayer.tsx create mode 100644 src/domain/entities/map/MapColorsType.ts create mode 100644 src/operations/map/MapOperations.ts create mode 100644 src/styles/MapColors.ts diff --git a/.env_template b/.env_template index 69bfa8d3..2bb34396 100644 --- a/.env_template +++ b/.env_template @@ -1 +1,3 @@ NEXT_PUBLIC_API_URL=https://api.hungermapdata.org/v2 +NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN= +NEXT_PUBLIC_CHATBOT_API_URL= \ No newline at end of file diff --git a/package.json b/package.json index 886dbd79..791fbaa7 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@nextui-org/tooltip": "^2.0.41", "@react-aria/ssr": "3.9.4", "@react-aria/visually-hidden": "3.8.12", + "@react-leaflet/core": "^2.1.0", "@tanstack/react-query": "^5.59.17", "clsx": "2.1.1", "framer-motion": "~11.1.1", @@ -47,6 +48,8 @@ "leaflet-defaulticon-compatibility": "^0.1.2", "leaflet-geosearch": "^4.0.0", "lucide-react": "^0.454.0", + "mapbox-gl": "^3.7.0", + "mapbox-gl-leaflet": "^0.0.16", "next": "14.2.10", "next-themes": "^0.2.1", "nextui-cli": "^0.3.4", diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx index 9cdccb30..0fd45f99 100644 --- a/src/components/Map/Map.tsx +++ b/src/components/Map/Map.tsx @@ -1,72 +1,12 @@ -/* eslint-disable */ import 'leaflet/dist/leaflet.css'; -import { Feature, FeatureCollection } from 'geojson'; -import { LeafletMouseEvent } from 'leaflet'; -import { GeoJSON, MapContainer, TileLayer, ZoomControl } from 'react-leaflet'; +import { MapContainer, ZoomControl } from 'react-leaflet'; -import { CountryMapData } from '@/domain/entities/country/CountryMapData.ts'; import { MapProps } from '@/domain/props/MapProps'; -export default function Map({ countries }: MapProps) { - const countryStyle: L.PathOptions = { - fillColor: 'var(--color-active-countries)', - weight: 0.5, - color: 'var(--color-background)', - fillOpacity: 0.4, - }; - - const highlightCountry = (event: LeafletMouseEvent) => { - const layer = event.target; - const countryData: CountryMapData = layer.feature as CountryMapData; - if (countryData.properties.interactive) { - layer.setStyle({ - fillColor: 'var(--color-hover)', - fillOpacity: 0.8, - }); - } else { - layer.getElement().style.cursor = 'grab'; - } - }; - - const resetHighlight = (event: LeafletMouseEvent) => { - const layer = event.target; - const countryData: CountryMapData = layer.feature as CountryMapData; - if (countryData.properties.interactive) { - layer.setStyle(countryStyle); - } - }; - - const onCountryClick = (event: LeafletMouseEvent) => { - const countryData: CountryMapData = event.target.feature as CountryMapData; - if (countryData.properties.interactive) { - alert(`You clicked on ${countryData.properties.adm0_name}`); - } - }; - - const onEachCountry = (country: Feature, layer: L.Layer) => { - if ((layer as L.GeoJSON).feature) { - const leafletLayer = layer as L.Path; - leafletLayer.setStyle(countryStyle); - if (!(country as CountryMapData).properties.interactive) { - leafletLayer.setStyle({ fillColor: 'var(--color-inactive-countries)', fillOpacity: 0.85 }); - } - leafletLayer.on({ - mouseover: highlightCountry, - mouseout: resetHighlight, - click: onCountryClick, - mousedown: () => { - const element = leafletLayer.getElement() as HTMLElement | null; - if (element) element.style.cursor = 'grabbing'; - }, - mouseup: () => { - const element = leafletLayer.getElement() as HTMLElement | null; - if (element) element.style.cursor = 'grab'; - }, - }); - } - }; +import VectorTileLayer from './VectorTileLayer'; +export default function Map({ countries, disputedAreas }: MapProps) { return ( - - {countries && } + {countries && } ); diff --git a/src/components/Map/VectorTileLayer.tsx b/src/components/Map/VectorTileLayer.tsx new file mode 100644 index 00000000..ad6db229 --- /dev/null +++ b/src/components/Map/VectorTileLayer.tsx @@ -0,0 +1,34 @@ +import 'mapbox-gl/dist/mapbox-gl.css'; + +import { LeafletContextInterface, useLeafletContext } from '@react-leaflet/core'; +import mapboxgl from 'mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax +import { useTheme } from 'next-themes'; +import React, { RefObject, useEffect, useRef } from 'react'; + +import { MapProps } from '@/domain/props/MapProps'; +import { MapOperations } from '@/operations/map/MapOperations.ts'; + +export default function VectorTileLayer({ countries, disputedAreas }: MapProps) { + const { theme } = useTheme(); + const context: LeafletContextInterface = useLeafletContext(); + const mapContainer: RefObject = useRef(null); + + mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN as string; + + useEffect(() => { + const baseMap: mapboxgl.Map = MapOperations.createMapboxMap( + theme === 'dark', + { countries, disputedAreas }, + mapContainer + ); + MapOperations.setMapInteractionFunctionality(baseMap); + MapOperations.synchronizeLeafletMapbox(baseMap, mapContainer, context); + + return () => { + baseMap.remove(); + context.map.off('move'); + }; + }, [context, theme]); + + return
; +} diff --git a/src/domain/entities/map/MapColorsType.ts b/src/domain/entities/map/MapColorsType.ts new file mode 100644 index 00000000..5882016a --- /dev/null +++ b/src/domain/entities/map/MapColorsType.ts @@ -0,0 +1,7 @@ +export interface MapColorsType { + activeCountries: string; + inactiveCountries: string; + ocean: string; + outline: string; + roads: string; +} diff --git a/src/operations/map/MapOperations.ts b/src/operations/map/MapOperations.ts new file mode 100644 index 00000000..4f5afcba --- /dev/null +++ b/src/operations/map/MapOperations.ts @@ -0,0 +1,187 @@ +import { LeafletContextInterface } from '@react-leaflet/core'; +import { FeatureCollection } from 'geojson'; +import mapboxgl from 'mapbox-gl'; +import { RefObject } from 'react'; + +import { CountryMapData } from '@/domain/entities/country/CountryMapData.ts'; +import { MapColorsType } from '@/domain/entities/map/MapColorsType.ts'; +import { MapProps } from '@/domain/props/MapProps'; +import { getColors } from '@/styles/MapColors.ts'; + +export class MapOperations { + static createMapboxMap( + isDark: boolean, + { countries }: MapProps, + mapContainer: RefObject + ): mapboxgl.Map { + const mapColors: MapColorsType = getColors(isDark); + + return new mapboxgl.Map({ + container: mapContainer.current as unknown as string | HTMLElement, + style: { + version: 8, + name: 'HungerMap LIVE', + metadata: '{metadata}', + sources: { + countries: { + type: 'geojson', + data: countries as FeatureCollection, + generateId: true, + }, + mapboxStreets: { + type: 'vector', + url: 'mapbox://mapbox.mapbox-streets-v8', + }, + }, + layers: [ + { + id: 'ocean', + type: 'background', + paint: { + 'background-color': mapColors.ocean, + }, + }, + { + id: 'country-fills', + type: 'fill', + source: 'countries', + layout: {}, + paint: { + 'fill-color': [ + 'case', + ['boolean', ['coalesce', ['get', 'interactive'], false]], + mapColors.activeCountries, + mapColors.inactiveCountries, + ], + 'fill-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 0.7, 1], + }, + }, + { + id: 'country-borders', + type: 'line', + source: 'countries', + layout: {}, + paint: { + 'line-color': mapColors.outline, + 'line-width': 0.7, + }, + }, + + { + id: 'mapbox-roads', + type: 'line', + source: 'mapboxStreets', + 'source-layer': 'road', + filter: ['in', 'class', 'motorway', 'trunk'], + paint: { + 'line-color': mapColors.roads, + 'line-width': ['interpolate', ['exponential', 1.5], ['zoom'], 5, 0.5, 18, 10], + }, + minzoom: 5, + }, + ], + }, + interactive: false, + }); + } + + static setMapInteractionFunctionality(baseMap: mapboxgl.Map): void { + let hoveredPolygonId: string | number | undefined; + + baseMap.on('mousemove', 'country-fills', (e) => { + if (e.features && e.features.length > 0 && (e.features[0] as unknown as CountryMapData).properties.interactive) { + if (hoveredPolygonId) { + baseMap.setFeatureState({ source: 'countries', id: hoveredPolygonId }, { hover: false }); + } + hoveredPolygonId = e.features[0].id; + if (hoveredPolygonId) { + baseMap.setFeatureState({ source: 'countries', id: hoveredPolygonId }, { hover: true }); + } + } + }); + + baseMap.on('mouseleave', 'country-fills', () => { + if (hoveredPolygonId) { + baseMap.setFeatureState({ source: 'countries', id: hoveredPolygonId }, { hover: false }); + } + hoveredPolygonId = undefined; + }); + + let isDragging = false; + baseMap.on('mousedown', () => { + isDragging = false; + }); + + baseMap.on('mousemove', () => { + isDragging = true; + }); + + baseMap.on('mouseup', 'country-fills', (e) => { + if (!isDragging && e.features && (e.features[0] as unknown as CountryMapData).properties.interactive) { + alert(`You clicked on ${(e.features[0] as unknown as CountryMapData).properties.adm0_name}`); + } + }); + } + + static synchronizeLeafletMapbox( + baseMap: mapboxgl.Map, + mapContainer: RefObject, + context: LeafletContextInterface + ): void { + baseMap.dragRotate.disable(); + + const syncZoom = () => { + baseMap.setZoom(context.map.getZoom() - 1); + baseMap.setMaxZoom(context.map.getMaxZoom() - 1); + baseMap.setMinZoom(context.map.getMinZoom() - 1); + }; + + const container = context.layerContainer || context.map; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const leafletMap = container.getContainer(); + leafletMap.appendChild(mapContainer.current); + + baseMap.setZoom(context.map.getZoom()); + baseMap.setMaxZoom(context.map.getMaxZoom() - 1); + baseMap.setMinZoom(context.map.getMinZoom() - 1); + + const { lat, lng } = context.map.getCenter(); + baseMap.setCenter([lng, lat]); + baseMap.setZoom(context.map.getZoom() - 1); + + context.map.on('move', () => { + const { lat: moveLat, lng: moveLng } = context.map.getCenter(); + baseMap.setCenter([moveLng, moveLat]); + syncZoom(); + }); + + context.map.on('zoom', () => { + const { lat: zoomLat, lng: zoomLng } = context.map.getCenter(); + baseMap.setCenter([zoomLng, zoomLat]); + syncZoom(); + }); + + context.map.on('movestart', () => { + const { lat: moveStartLat, lng: moveStartLng } = context.map.getCenter(); + baseMap.setCenter([moveStartLng, moveStartLat]); + syncZoom(); + }); + + context.map.on('zoomstart', () => { + syncZoom(); + }); + + context.map.on('moveend', () => { + const { lat: moveEndLat, lng: moveEndLng } = context.map.getCenter(); + baseMap.setCenter([moveEndLng, moveEndLat]); + syncZoom(); + }); + + context.map.on('zoomend', () => { + const { lat: zoomEndLat, lng: zoomEndLng } = context.map.getCenter(); + baseMap.setCenter([zoomEndLng, zoomEndLat]); + syncZoom(); + }); + } +} diff --git a/src/styles/MapColors.ts b/src/styles/MapColors.ts new file mode 100644 index 00000000..1e81d65c --- /dev/null +++ b/src/styles/MapColors.ts @@ -0,0 +1,9 @@ +import { MapColorsType } from '@/domain/entities/map/MapColorsType.ts'; + +export const getColors = (isDark: boolean): MapColorsType => ({ + activeCountries: isDark ? '#0e6397' : '#fefeff', + inactiveCountries: isDark ? '#5a819b' : '#e8e8e8', + ocean: isDark ? '#111111' : '#91cccb', + outline: isDark ? '#0e2a3a' : '#306f96', + roads: isDark ? '#404040' : '#808080', +}); diff --git a/yarn.lock b/yarn.lock index 0e34c1e0..66262a9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -369,6 +369,16 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@mapbox/jsonlint-lines-primitives@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234" + integrity sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ== + +"@mapbox/mapbox-gl-supported@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-3.0.0.tgz#bebd3d5da3c1fd988011bb79718a39f63f5e16ac" + integrity sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg== + "@mapbox/node-pre-gyp@^1.0.0": version "1.0.11" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" @@ -384,6 +394,33 @@ semver "^7.3.5" tar "^6.1.11" +"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2" + integrity sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ== + +"@mapbox/tiny-sdf@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz#9a1d33e5018093e88f6a4df2343e886056287282" + integrity sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA== + +"@mapbox/unitbezier@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01" + integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw== + +"@mapbox/vector-tile@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666" + integrity sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw== + dependencies: + "@mapbox/point-geometry" "~0.1.0" + +"@mapbox/whoots-js@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" + integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== + "@next/env@14.2.10": version "14.2.10" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.10.tgz#1d3178340028ced2d679f84140877db4f420333c" @@ -2774,7 +2811,14 @@ dependencies: "@types/node" "*" -"@types/geojson@*", "@types/geojson@^7946.0.14": +"@types/geojson-vt@^3.2.5": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/geojson-vt/-/geojson-vt-3.2.5.tgz#b6c356874991d9ab4207533476dfbcdb21e38408" + integrity sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g== + dependencies: + "@types/geojson" "*" + +"@types/geojson@*", "@types/geojson@^7946.0.14", "@types/geojson@^7946.0.14": version "7946.0.14" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== @@ -2803,6 +2847,20 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.13.tgz#786e2d67cfd95e32862143abe7463a7f90c300eb" integrity sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg== +"@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz#0ef017b75eedce02ff6243b4189210e2e6d5e56d" + integrity sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA== + +"@types/mapbox__vector-tile@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz#ad757441ef1d34628d9e098afd9c91423c1f8734" + integrity sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg== + dependencies: + "@types/geojson" "*" + "@types/mapbox__point-geometry" "*" + "@types/pbf" "*" + "@types/node@*": version "22.9.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" @@ -2815,6 +2873,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== +"@types/pbf@*", "@types/pbf@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.5.tgz#a9495a58d8c75be4ffe9a0bd749a307715c07404" + integrity sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA== + "@types/prop-types@*": version "15.7.13" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" @@ -2835,6 +2898,13 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/supercluster@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/supercluster/-/supercluster-7.1.3.tgz#1a1bc2401b09174d9c9e44124931ec7874a72b27" + integrity sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA== + dependencies: + "@types/geojson" "*" + "@types/tinycolor2@^1.4.0": version "1.4.6" resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz#670cbc0caf4e58dd61d1e3a6f26386e473087f06" @@ -3279,6 +3349,11 @@ chalk@^4.0.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +cheap-ruler@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cheap-ruler/-/cheap-ruler-4.0.0.tgz#bdc984de7e0e3f748bdfd2dbe23ec6b9dc820a09" + integrity sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw== + chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -3461,6 +3536,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +csscolorparser@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b" + integrity sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -3608,6 +3688,11 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" +earcut@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.0.tgz#a8d5bf891224eaea8287201b5e787c6c0318af89" + integrity sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -4216,6 +4301,16 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +geojson-vt@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-4.0.2.tgz#1162f6c7d61a0ba305b1030621e6e111f847828a" + integrity sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A== + +geojson@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0" + integrity sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ== + geojson@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0" @@ -4272,6 +4367,11 @@ git-raw-commits@^4.0.0: meow "^12.0.1" split2 "^4.0.0" +gl-matrix@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9" + integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -4357,6 +4457,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +grid-index@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7" + integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -4433,6 +4538,11 @@ iconsax-react@^0.0.8: dependencies: prop-types "^15.7.2" +ieee754@^1.1.12: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -4820,6 +4930,11 @@ jsonparse@^1.2.0: object.assign "^4.1.4" object.values "^1.1.6" +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -5011,6 +5126,45 @@ make-event-props@^1.6.0: resolved "https://registry.yarnpkg.com/make-event-props/-/make-event-props-1.6.2.tgz#c8e0e48eb28b9b808730de38359f6341de7ec5a2" integrity sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA== +mapbox-gl-leaflet@^0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/mapbox-gl-leaflet/-/mapbox-gl-leaflet-0.0.16.tgz#25208897bbffbe8e2c1f15d3710f253c19a0a533" + integrity sha512-w4bpZrKHOWDZqUzhDOjIPL6Pc4tD10TVR/z8Iwp3hlUaf8PVqfxPINrcBLkcOg0+xFZSX3uka6Vl6NeO7KUYXw== + +mapbox-gl@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-3.7.0.tgz#1c81826226ab21a8ec046e1686d4dd2794f9a756" + integrity sha512-dCbVyH1uGobwv6f4QKRv2Z2wuVT/RmspsudK3sTxGRFxZi6Pd2P9axdbVyZpmGddCAREy44pHhvzvO0qgpdKAg== + dependencies: + "@mapbox/jsonlint-lines-primitives" "^2.0.2" + "@mapbox/mapbox-gl-supported" "^3.0.0" + "@mapbox/point-geometry" "^0.1.0" + "@mapbox/tiny-sdf" "^2.0.6" + "@mapbox/unitbezier" "^0.0.1" + "@mapbox/vector-tile" "^1.3.1" + "@mapbox/whoots-js" "^3.1.0" + "@types/geojson" "^7946.0.14" + "@types/geojson-vt" "^3.2.5" + "@types/mapbox__point-geometry" "^0.1.4" + "@types/mapbox__vector-tile" "^1.3.4" + "@types/pbf" "^3.0.5" + "@types/supercluster" "^7.1.3" + cheap-ruler "^4.0.0" + csscolorparser "~1.0.3" + earcut "^3.0.0" + geojson-vt "^4.0.2" + gl-matrix "^3.4.3" + grid-index "^1.1.0" + kdbush "^4.0.2" + murmurhash-js "^1.0.0" + pbf "^3.2.1" + potpack "^2.0.0" + quickselect "^3.0.0" + serialize-to-js "^3.1.2" + supercluster "^8.0.1" + tinyqueue "^3.0.0" + vt-pbf "^3.1.3" + meow@^12.0.1: version "12.1.1" resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" @@ -5098,6 +5252,11 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +murmurhash-js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51" + integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -5407,6 +5566,14 @@ pathe@1.1.2: resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== +pbf@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.3.0.tgz#1790f3d99118333cc7f498de816028a346ef367f" + integrity sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q== + dependencies: + ieee754 "^1.1.12" + resolve-protobuf-schema "^2.1.0" + pdfjs-dist@4.4.168: version "4.4.168" resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-4.4.168.tgz#4487716376a33c68753ed37f782ae91d1c9ef8fa" @@ -5511,6 +5678,11 @@ postcss@^8.4.23: picocolors "^1.1.0" source-map-js "^1.2.1" +potpack@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" + integrity sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -5537,6 +5709,11 @@ prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +protocol-buffers-schema@^3.3.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" + integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -5547,6 +5724,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quickselect@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-3.0.0.tgz#a37fc953867d56f095a20ac71c6d27063d2de603" + integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== + react-dom@18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" @@ -5701,6 +5883,13 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve-protobuf-schema@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" + integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== + dependencies: + protocol-buffers-schema "^3.3.1" + resolve@^1.1.7, resolve@^1.22.2, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" @@ -5799,6 +5988,11 @@ semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +serialize-to-js@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-3.1.2.tgz#844b8a1c2d72412f68ea30da55090b3fc8e95790" + integrity sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w== + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -6061,6 +6255,13 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -6190,6 +6391,11 @@ tinygradient@^1.1.5: "@types/tinycolor2" "^1.4.0" tinycolor2 "^1.0.0" +tinyqueue@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-3.0.0.tgz#101ea761ccc81f979e29200929e78f1556e3661e" + integrity sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -6360,6 +6566,15 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +vt-pbf@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac" + integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA== + dependencies: + "@mapbox/point-geometry" "0.1.0" + "@mapbox/vector-tile" "^1.3.1" + pbf "^3.2.1" + warning@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"