UNPKG

@mapka/react-maplibre-map

Version:
102 lines (101 loc) 3.61 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import * as maplibre from "maplibre-gl"; import { isEqual } from "es-toolkit"; import { useCallback, useEffect, useMemo, useRef } from "react"; import { MapLibreContainer } from "./MapLibreContainer.js"; import { isEmpty } from "es-toolkit/compat"; import { MapLibreStyles } from "./MapLibreStyles.js"; const noopTransformRequest = (url) => { return { url, }; }; const createTransformRequest = (apiKey, transformRequest) => (url) => { if ((!isEmpty(apiKey) && url.includes("mapka.dev")) || url.includes("mapka.localhost")) { return { url, headers: { Authorization: `Bearer ${apiKey}`, }, }; } return transformRequest ? transformRequest(url) : noopTransformRequest(url); }; export function MapLibreMap(props) { const { BaseMap, width = "100%", height = "100%", center, zoom, style, transformRequest, onMapLoaded, apiKey, injectMaplibreStyles, } = props; const container = useRef(null); const map = useRef(null); /* * 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) { const mapOption = { container: element, style, center, zoom, transformRequest: createTransformRequest(apiKey, transformRequest), }; if (BaseMap) { mapOption.apiKey = apiKey; } const mapInstance = BaseMap ? new BaseMap(mapOption) : new maplibre.Map(mapOption); container.current = element; map.current = mapInstance; if (onMapLoaded) { mapInstance.once("load", () => { onMapLoaded(mapInstance); }); } } return () => { if (map.current) { map.current.remove(); map.current = null; } }; }, [apiKey]); const currentMap = map.current; useEffect(() => { if (!currentMap) return; if (!Number.isInteger(zoom)) return; const currentZoom = currentMap.getZoom(); if (!isEqual(currentZoom, zoom)) { currentMap.setZoom(zoom); } }, [currentMap, zoom]); useEffect(() => { if (!currentMap) return; if (!Array.isArray(center)) return; const currentCenter = currentMap.getCenter().toArray(); if (!isEqual(currentCenter, center)) { currentMap.setCenter(center); } }, [currentMap, center]); useEffect(() => { if (!currentMap) return; currentMap.setStyle(style ?? null); }, [currentMap, style]); const styles = useMemo(() => { return { width: typeof width === "number" ? `${width}px` : width, height: typeof height === "number" ? `${height}px` : height, }; }, [width, height]); if (!injectMaplibreStyles) { return _jsx(MapLibreContainer, { ref: initMap, style: styles }); } else { return (_jsxs(_Fragment, { children: [_jsx(MapLibreStyles, {}), _jsx(MapLibreContainer, { ref: initMap, style: styles })] })); } } MapLibreMap.displayName = "MapLibreMap";