UNPKG

@mapka/react-maplibre-map

Version:

MapLibre react web component

109 lines (108 loc) 4.16 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { memo, useCallback, useEffect, useMemo, useRef, version } from "react"; import { MapLibreContainer } from "./MapLibreContainer.js"; import { MapLibreStyles } from "./MapLibreStyles.js"; import { isEqual } from "es-toolkit"; const defaultCenter = [0, 0]; const defaultZoom = 1; const defaultStyle = "https://demotiles.maplibre.org/style.json"; export const MapLibreMap = memo((props) => { const { width = "100%", height = "100%", center = defaultCenter, zoom = defaultZoom, style = defaultStyle, onMapLoaded, mapkaApiKey, showFeatureTooltip, } = props; const container = useRef(null); const map = useRef(null); const mapkaAPIkeyRef = useRef(mapkaApiKey); if (mapkaApiKey !== mapkaAPIkeyRef.current) { mapkaAPIkeyRef.current = mapkaApiKey; } /* * We want to this callback ref to be created only once. Deps update will be handled in dedicated useEffect * biome-ignore lint/correctness/useExhaustiveDependencies: ref callback is created only once */ const initMap = useCallback((element) => { if (!map.current && element) { import("maplibre-gl").then(({ default: maplibre }) => { const mapLibreMap = new maplibre.Map({ container: element, style, center, zoom, transformRequest: (url) => { if (url.includes("mapka.dev") || url.includes("mapka.localhost")) { if (mapkaAPIkeyRef.current) { return { url, headers: { Authorization: `Bearer ${mapkaAPIkeyRef.current}`, }, }; } } return { url, }; }, }); container.current = element; map.current = mapLibreMap; if (onMapLoaded) { mapLibreMap.once("load", () => { onMapLoaded(mapLibreMap); }); } }); } if (!version?.startsWith("19")) { return; } return () => { if (map.current) { map.current.remove(); map.current = null; } }; }, []); const currentMap = map.current; useEffect(() => { if (!currentMap) return; const currentZoom = currentMap.getZoom(); if (!isEqual(currentZoom, zoom)) { currentMap.setZoom(zoom); } }, [currentMap, zoom]); useEffect(() => { if (!currentMap) return; const currentCenter = currentMap.getCenter().toArray(); if (!isEqual(currentCenter, center)) { currentMap.setCenter(center); } }, [currentMap, center]); useEffect(() => { if (!currentMap) return; currentMap.setStyle(style); }, [currentMap, style]); useEffect(() => { if (!showFeatureTooltip) return; const onClick = (event) => { const features = currentMap?.queryRenderedFeatures(event.point); if (!features) return; console.log(features); }; currentMap?.on("click", onClick); return () => { currentMap?.off("click", onClick); }; }, [currentMap, showFeatureTooltip]); const styles = useMemo(() => { return { width: typeof width === "number" ? `${width}px` : width, height: typeof height === "number" ? `${height}px` : height, }; }, [width, height]); return (_jsxs(_Fragment, { children: [_jsx(MapLibreStyles, {}), _jsx(MapLibreContainer, { ref: initMap, style: styles })] })); }); MapLibreMap.displayName = "MapLibreMap";