@vinctus/react-maplibre 0.2.26 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import React, { Component, ErrorInfo, ReactNode } from 'react';
1
+ import { Component, ErrorInfo, ReactNode } from 'react';
2
2
  interface Props {
3
3
  children?: ReactNode;
4
4
  fallback?: ReactNode;
@@ -10,6 +10,6 @@ export declare class ErrorBoundary extends Component<Props, State> {
10
10
  constructor(props: any);
11
11
  static getDerivedStateFromError(_: Error): State;
12
12
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
13
- render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
13
+ render(): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
14
14
  }
15
15
  export {};
@@ -13,8 +13,9 @@ export class ErrorBoundary extends Component {
13
13
  console.error('Uncaught map error:', error, errorInfo);
14
14
  }
15
15
  render() {
16
- if (this.state.hasError)
16
+ if (this.state.hasError) {
17
17
  return this.props.fallback || _jsx("h1", { children: "Sorry.. there was a map error" });
18
+ }
18
19
  return this.props.children;
19
20
  }
20
21
  }
@@ -1,6 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { GeolocateControlOptions } from 'maplibre-gl';
3
- import { ControlPosition } from './types';
2
+ import { GeolocateControlOptions, ControlPosition } from 'maplibre-gl';
4
3
  export type GeolocateControlProps = {
5
4
  position?: ControlPosition;
6
5
  options?: GeolocateControlOptions;
@@ -1,18 +1,24 @@
1
- import { useEffect } from 'react';
1
+ import { useContext, useEffect } from 'react';
2
2
  import maplibre from 'maplibre-gl';
3
- import { useMap } from './Map';
3
+ import { MapContext } from './Map';
4
4
  export const GeolocateControl = ({ position = 'bottom-right', options = { showUserLocation: false }, }) => {
5
- const { map } = useMap();
5
+ const { map, mapLoaded } = useContext(MapContext);
6
+ const optionsString = JSON.stringify(options || {});
6
7
  useEffect(() => {
7
- const control = new maplibre.GeolocateControl(options);
8
- if (map && position) {
8
+ const control = new maplibre.GeolocateControl(JSON.parse(optionsString));
9
+ if (map && mapLoaded && position) {
9
10
  map.addControl(control, position);
10
11
  }
11
12
  return () => {
12
- if (map && map.hasControl(control)) {
13
- map.removeControl(control);
13
+ try {
14
+ if (map && !map._removed && map.hasControl(control)) {
15
+ map.removeControl(control);
16
+ }
17
+ }
18
+ catch (_a) {
19
+ console.warn('Error cleaning up GeolocateControl');
14
20
  }
15
21
  };
16
- }, [position, options, map]);
22
+ }, [position, optionsString, map, mapLoaded]);
17
23
  return null;
18
24
  };
package/dist/Layer.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { LayerSpecification, GeoJSONSourceSpecification } from 'maplibre-gl';
2
+ import { GeoJSONSourceSpecification, LayerSpecification } from 'maplibre-gl';
3
3
  export type LayerProps = {
4
4
  layer: Omit<LayerSpecification, 'source'>;
5
5
  source: GeoJSONSourceSpecification;
package/dist/Layer.js CHANGED
@@ -1,7 +1,7 @@
1
- import { useEffect } from 'react';
2
- import { useMap } from './Map';
1
+ import { useContext, useEffect } from 'react';
2
+ import { MapContext } from './Map';
3
3
  export const Layer = ({ layer, source }) => {
4
- const { map, mapLoaded } = useMap();
4
+ const { map, mapLoaded } = useContext(MapContext);
5
5
  const layerString = JSON.stringify(Object.assign({ source: layer.id }, layer));
6
6
  const sourceString = JSON.stringify(source);
7
7
  useEffect(() => {
@@ -12,16 +12,19 @@ export const Layer = ({ layer, source }) => {
12
12
  map.addLayer(parsedLayer);
13
13
  }
14
14
  return () => {
15
- if (map) {
16
- // Check if layer exists before removing
17
- if (map.getLayer(parsedLayer.id)) {
18
- map.removeLayer(parsedLayer.id); // when removing, the layer must be removed first, and then the source
19
- }
20
- // Check if source exists before removing
21
- if (map.getSource(parsedLayer.id)) {
22
- map.removeSource(parsedLayer.id);
15
+ try {
16
+ if (map && mapLoaded && !map._removed) {
17
+ if (map.getLayer(parsedLayer.id)) {
18
+ map.removeLayer(parsedLayer.id); // when removing, the layer must be removed first, and then the source
19
+ }
20
+ if (map.getSource(parsedLayer.id)) {
21
+ map.removeSource(parsedLayer.id);
22
+ }
23
23
  }
24
24
  }
25
+ catch (_a) {
26
+ console.warn('Error cleaning up Layer');
27
+ }
25
28
  };
26
29
  }, [layerString, sourceString, map, mapLoaded]);
27
30
  return null;
package/dist/Map.d.ts CHANGED
@@ -1,48 +1,25 @@
1
- import React, { FC, RefAttributes, ReactNode, CSSProperties } from 'react';
2
- import maplibre, { MapLibreEvent, StyleSpecification } from 'maplibre-gl';
3
- export type ViewState = {
4
- longitude: number;
5
- latitude: number;
6
- zoom: number;
7
- };
8
- export type ViewStateChangeEvent = (MapLibreEvent<MouseEvent | TouchEvent | WheelEvent | undefined> & {
9
- type: 'movestart' | 'move' | 'moveend' | 'zoomstart' | 'zoom' | 'zoomend';
10
- viewState: ViewState;
11
- }) | (MapLibreEvent<MouseEvent | TouchEvent | undefined> & {
12
- type: 'rotatestart' | 'rotate' | 'rotateend' | 'dragstart' | 'drag' | 'dragend' | 'pitchstart' | 'pitch' | 'pitchend';
13
- viewState: ViewState;
14
- });
15
- export declare const viewStateFromMap: (map: maplibre.Map) => {
16
- longitude: number;
17
- latitude: number;
18
- zoom: number;
19
- };
20
- export declare const useMap: () => {
1
+ import maplibre, { MapLibreEvent } from 'maplibre-gl';
2
+ import { ReactNode } from 'react';
3
+ export declare const MapContext: import("react").Context<{
21
4
  map: maplibre.Map | null;
22
- setMap: React.Dispatch<React.SetStateAction<maplibre.Map | null>>;
23
5
  mapLoaded: boolean;
24
- setMapLoaded: React.Dispatch<React.SetStateAction<boolean>>;
25
- };
26
- export declare const MapProvider: FC<{
27
- children?: ReactNode;
28
6
  }>;
29
- export type MapProps = {
30
- accessToken?: string;
31
- antialias?: boolean;
32
- children?: ReactNode | ReactNode[];
33
- fallback?: ReactNode;
34
- id?: string;
7
+ export type MapDragEndEvent = MapLibreEvent & {
8
+ viewState: {
9
+ longitude: number;
10
+ latitude: number;
11
+ zoom: number;
12
+ };
13
+ };
14
+ type MapProps = {
35
15
  longitude: number;
36
16
  latitude: number;
37
- logoPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
38
- maxPitch?: number;
39
- mapStyle?: StyleSpecification | string;
40
- onLoad?: (e: import('maplibre-gl').MapLibreEvent) => void;
41
- onDragEnd?: (e: ViewStateChangeEvent) => void;
42
- onMoveEnd?: (e: ViewStateChangeEvent) => void;
43
- onZoomEnd?: (e: ViewStateChangeEvent) => void;
44
- ref?: RefAttributes<maplibre.Map | null>;
45
- style?: CSSProperties;
46
- zoom: number;
17
+ mapStyle: string;
18
+ fallback?: ReactNode;
19
+ children?: ReactNode | ReactNode[];
20
+ onLoad?: (e: MapLibreEvent) => void;
21
+ onZoomEnd?: (e: MapLibreEvent) => void;
22
+ onDragEnd?: (e: MapDragEndEvent) => void;
47
23
  };
48
- export declare const Map: React.ForwardRefExoticComponent<Omit<MapProps, "ref"> & React.RefAttributes<maplibre.Map | null>>;
24
+ export declare const Map: import("react").ForwardRefExoticComponent<MapProps & import("react").RefAttributes<maplibre.Map | null>>;
25
+ export {};
package/dist/Map.js CHANGED
@@ -1,75 +1,68 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
1
  import { jsx as _jsx } from "react/jsx-runtime";
13
- import React, { useRef, useEffect, useState, useContext, useImperativeHandle, useMemo, } from 'react';
14
2
  import maplibre from 'maplibre-gl';
15
- import { ErrorBoundary } from './ErrorBoundary'; // eslint-disable-line import/no-webpack-loader-syntax
16
- const DEFAULT_STYLE = 'https://demotiles.maplibre.org/style.json';
17
- const DISABLE_PITCH = 0;
18
- const MapContext = React.createContext({
3
+ import { createContext, forwardRef, useEffect, useImperativeHandle, useRef, useState, } from 'react';
4
+ import { ErrorBoundary } from './ErrorBoundary';
5
+ export const MapContext = createContext({
19
6
  map: null,
20
- setMap: () => {
21
- throw new Error('Use <MapProvider>');
22
- },
23
7
  mapLoaded: false,
24
- setMapLoaded: () => {
25
- throw new Error('Use <MapProvider>');
26
- },
27
- });
28
- export const viewStateFromMap = (map) => ({
29
- longitude: map.getCenter().lng,
30
- latitude: map.getCenter().lat,
31
- zoom: map.getZoom(),
32
8
  });
33
- export const useMap = () => useContext(MapContext);
34
- export const MapProvider = ({ children }) => {
35
- const [map, setMap] = useState(null);
36
- const [mapLoaded, setMapLoaded] = useState(false);
37
- return (_jsx(MapContext.Provider, { value: { map, setMap, mapLoaded, setMapLoaded }, children: children }));
38
- };
39
- function addEventHandler(map, type, handler) {
40
- map.on(type, (ev) => handler(Object.assign({ viewState: viewStateFromMap(map) }, ev)));
41
- }
42
- export const Map = React.forwardRef((_a, ref) => {
43
- var { children, style, id, longitude, latitude, maxPitch = DISABLE_PITCH, mapStyle = DEFAULT_STYLE, zoom, onDragEnd, onLoad, onMoveEnd, onZoomEnd, fallback } = _a, options = __rest(_a, ["children", "style", "id", "longitude", "latitude", "maxPitch", "mapStyle", "zoom", "onDragEnd", "onLoad", "onMoveEnd", "onZoomEnd", "fallback"]);
9
+ export const Map = forwardRef(({ longitude, latitude, mapStyle, fallback, children, onLoad, onZoomEnd, onDragEnd }, ref) => {
44
10
  const mapContainer = useRef(null);
45
- const mapInstanceRef = useRef(null);
46
- const { map, setMap, setMapLoaded } = useMap();
47
- useImperativeHandle(ref, () => map, [map]);
11
+ const [mapInstance, setMapInstance] = useState(null);
12
+ const [mapLoaded, setMapLoaded] = useState(false);
13
+ useImperativeHandle(ref, () => mapInstance, [
14
+ mapInstance,
15
+ ]);
48
16
  useEffect(() => {
49
- if (map)
50
- return; // initialize map only once
17
+ let newMap;
51
18
  if (mapContainer.current) {
52
- const m = new maplibre.Map(Object.assign({ container: mapContainer.current, style: mapStyle, center: [longitude, latitude], zoom }, options));
53
- mapInstanceRef.current = m;
54
- if (onDragEnd)
55
- addEventHandler(m, 'dragend', onDragEnd);
56
- if (onLoad)
57
- addEventHandler(m, 'load', (ev) => {
19
+ newMap = new maplibre.Map({
20
+ container: mapContainer.current,
21
+ style: mapStyle,
22
+ zoom: 15,
23
+ maxPitch: 0,
24
+ });
25
+ setMapInstance(newMap);
26
+ newMap.on('load', (ev) => {
27
+ if (onLoad) {
58
28
  onLoad(ev);
29
+ }
30
+ setTimeout(() => {
59
31
  setMapLoaded(true);
32
+ }, 1000);
33
+ });
34
+ if (onZoomEnd) {
35
+ newMap.on('zoomend', onZoomEnd);
36
+ }
37
+ if (onDragEnd) {
38
+ newMap.on('dragend', (ev) => {
39
+ const newEvent = Object.assign(Object.assign({}, ev), { viewState: {
40
+ longitude: newMap.getCenter().lng,
41
+ latitude: newMap.getCenter().lat,
42
+ zoom: newMap.getZoom(),
43
+ } });
44
+ onDragEnd(newEvent);
60
45
  });
61
- if (onMoveEnd)
62
- addEventHandler(m, 'moveend', onMoveEnd);
63
- if (onZoomEnd)
64
- addEventHandler(m, 'zoomend', onZoomEnd);
65
- setMap(m);
66
- // Cleanup when component unmounts
67
- return () => {
68
- m.remove(); // This destroys the map and cleans up all layers/sources
69
- mapInstanceRef.current = null;
70
- };
46
+ }
47
+ }
48
+ return () => {
49
+ try {
50
+ if (newMap) {
51
+ newMap.remove();
52
+ }
53
+ setMapInstance(null);
54
+ setMapLoaded(false);
55
+ }
56
+ catch (_a) {
57
+ console.warn('Error cleaning up Map');
58
+ }
59
+ };
60
+ }, [mapStyle, onLoad, onZoomEnd, onDragEnd]);
61
+ useEffect(() => {
62
+ if (mapInstance) {
63
+ mapInstance.setCenter([longitude, latitude]);
71
64
  }
72
- }, []); // Empty deps - only run once on mount
73
- const memoizedStyle = useMemo(() => (Object.assign({ position: 'relative', width: '100%', height: '100%' }, style)), [style]);
74
- return (_jsx(ErrorBoundary, { fallback: fallback, children: _jsx("div", { id: id, ref: mapContainer, style: memoizedStyle, children: children }) }));
65
+ }, [mapInstance, latitude, longitude]);
66
+ return (_jsx(ErrorBoundary, { fallback: fallback, children: _jsx(MapContext.Provider, { value: { map: mapInstance, mapLoaded }, children: _jsx("div", { ref: mapContainer, style: { width: '100%', height: '100%' }, children: children }) }) }));
75
67
  });
68
+ Map.displayName = 'Map';
package/dist/Marker.d.ts CHANGED
@@ -1,14 +1,15 @@
1
- import { FC, ReactElement, ReactNode } from 'react';
1
+ import { FC, ReactNode, ReactElement } from 'react';
2
2
  import { PositionAnchor } from 'maplibre-gl';
3
3
  export type MarkerProps = {
4
4
  longitude: number;
5
5
  latitude: number;
6
+ className?: string;
7
+ anchor?: PositionAnchor;
8
+ color?: string;
9
+ children?: ReactNode;
6
10
  popup?: ReactElement;
7
11
  popupClassName?: string;
8
12
  closeOnClick?: boolean;
9
13
  closeButton?: boolean;
10
- anchor?: PositionAnchor;
11
- color?: string;
12
- children?: ReactNode;
13
14
  };
14
15
  export declare const Marker: FC<MarkerProps>;
package/dist/Marker.js CHANGED
@@ -1,92 +1,69 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { useEffect, useState, useRef } from 'react';
1
+ import { useEffect, useState, useContext } from 'react';
13
2
  import maplibre from 'maplibre-gl';
14
- import { useMap } from './Map';
15
3
  import ReactDOM from 'react-dom';
16
4
  import ReactDOMServer from 'react-dom/server';
17
- export const Marker = (_a) => {
18
- var { children, longitude, latitude, popup, popupClassName, closeOnClick = false, closeButton = true } = _a, options = __rest(_a, ["children", "longitude", "latitude", "popup", "popupClassName", "closeOnClick", "closeButton"]);
19
- const { map } = useMap();
5
+ import { MapContext } from './Map';
6
+ export const Marker = ({ children, longitude, latitude, className, anchor, color, popup, popupClassName, closeOnClick = false, closeButton = false, }) => {
7
+ const { map, mapLoaded } = useContext(MapContext);
20
8
  const [result, setResult] = useState(null);
21
- const markerRef = useRef(null);
22
- const popupRef = useRef(null);
23
- const cleanupRef = useRef(null);
24
- const optionsString = JSON.stringify(options);
25
9
  useEffect(() => {
26
- if (!map)
27
- return;
28
- const element = document.createElement('div');
29
- const parsedOptions = JSON.parse(optionsString);
30
- if (children) {
10
+ let marker;
11
+ let newPopup;
12
+ let handleMarkerClick;
13
+ if (map && mapLoaded) {
14
+ // We create the DOM element that we will attach to the marker, and then
15
+ // render the `children` props into the DOM element.
16
+ const element = document.createElement('div');
31
17
  setResult(ReactDOM.createPortal(children, element));
18
+ marker = new maplibre.Marker({ anchor, className, color, element })
19
+ .setLngLat([longitude, latitude])
20
+ .addTo(map);
21
+ if (popup) {
22
+ const popupHTML = ReactDOMServer.renderToStaticMarkup(popup);
23
+ handleMarkerClick = (e) => {
24
+ e.stopPropagation();
25
+ newPopup = new maplibre.Popup({
26
+ offset: [0, -15],
27
+ closeButton,
28
+ closeOnClick,
29
+ className: popupClassName,
30
+ })
31
+ .setLngLat([longitude, latitude])
32
+ .setHTML(popupHTML)
33
+ .addTo(map);
34
+ };
35
+ marker.getElement().addEventListener('click', handleMarkerClick);
36
+ }
32
37
  }
33
- // Create marker
34
- const marker = children
35
- ? new maplibre.Marker(Object.assign(Object.assign({}, parsedOptions), { element }))
36
- : new maplibre.Marker(Object.assign({}, parsedOptions));
37
- marker.setLngLat([longitude, latitude]).addTo(map);
38
- markerRef.current = marker;
39
- // Handle popup manually if provided
40
- if (popup) {
41
- const popupHTML = ReactDOMServer.renderToStaticMarkup(popup);
42
- const handleMarkerClick = (e) => {
43
- e.stopPropagation();
44
- // Close existing popup if any
45
- if (popupRef.current) {
46
- popupRef.current.remove();
47
- popupRef.current = null;
48
- return; // Toggle behavior - close if already open
38
+ return () => {
39
+ try {
40
+ if (marker) {
41
+ marker.remove();
49
42
  }
50
- // Create new popup directly on the map
51
- const newPopup = new maplibre.Popup({
52
- offset: [0, -15],
53
- closeOnClick,
54
- closeButton,
55
- className: popupClassName,
56
- })
57
- .setLngLat([longitude, latitude])
58
- .setHTML(popupHTML)
59
- .addTo(map);
60
- popupRef.current = newPopup;
61
- // Listen for popup close to clean up reference
62
- newPopup.on('close', () => {
63
- popupRef.current = null;
64
- });
65
- };
66
- // Add click listener to marker element
67
- const markerElement = marker.getElement();
68
- markerElement.style.cursor = 'pointer';
69
- markerElement.addEventListener('click', handleMarkerClick);
70
- // Cleanup function
71
- const cleanup = () => {
72
- markerElement.removeEventListener('click', handleMarkerClick);
73
- if (popupRef.current) {
74
- popupRef.current.remove();
75
- popupRef.current = null;
43
+ if (newPopup) {
44
+ newPopup.remove();
45
+ }
46
+ if (marker && handleMarkerClick) {
47
+ marker.getElement().removeEventListener('click', handleMarkerClick);
76
48
  }
77
- };
78
- cleanupRef.current = cleanup;
79
- }
80
- return () => {
81
- if (cleanupRef.current) {
82
- cleanupRef.current();
83
- cleanupRef.current = null;
84
49
  }
85
- if (markerRef.current) {
86
- markerRef.current.remove();
87
- markerRef.current = null;
50
+ catch (_a) {
51
+ console.warn('Error cleaning up Marker');
88
52
  }
89
53
  };
90
- }, [map, optionsString, children, longitude, latitude, popup, closeOnClick, closeButton]);
54
+ }, [
55
+ anchor,
56
+ className,
57
+ children,
58
+ color,
59
+ latitude,
60
+ longitude,
61
+ map,
62
+ popup,
63
+ popupClassName,
64
+ closeOnClick,
65
+ closeButton,
66
+ mapLoaded,
67
+ ]);
91
68
  return result;
92
69
  };
@@ -1,6 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { NavigationControlOptions } from 'maplibre-gl';
3
- import { ControlPosition } from './types';
2
+ import { NavigationControlOptions, ControlPosition } from 'maplibre-gl';
4
3
  export type NavigationControlProps = {
5
4
  position?: ControlPosition;
6
5
  options?: NavigationControlOptions;
@@ -1,21 +1,27 @@
1
- import { useEffect } from 'react';
1
+ import { useContext, useEffect } from 'react';
2
2
  import maplibre from 'maplibre-gl';
3
- import { useMap } from './Map';
3
+ import { MapContext } from './Map';
4
4
  export const NavigationControl = ({ position = 'bottom-right', options = {
5
5
  showZoom: true,
6
6
  showCompass: false,
7
7
  }, }) => {
8
- const { map } = useMap();
8
+ const { map, mapLoaded } = useContext(MapContext);
9
+ const optionsString = JSON.stringify(options || {});
9
10
  useEffect(() => {
10
- const control = new maplibre.NavigationControl(options);
11
- if (map && position) {
11
+ const control = new maplibre.NavigationControl(JSON.parse(optionsString));
12
+ if (map && mapLoaded && position) {
12
13
  map.addControl(control, position);
13
14
  }
14
15
  return () => {
15
- if (map && map.hasControl(control)) {
16
- map.removeControl(control);
16
+ try {
17
+ if (map && !map._removed && map.hasControl(control)) {
18
+ map.removeControl(control);
19
+ }
20
+ }
21
+ catch (_a) {
22
+ console.warn('Error cleaning up NavigationControl');
17
23
  }
18
24
  };
19
- }, [position, options, map]);
25
+ }, [position, optionsString, map, mapLoaded]);
20
26
  return null;
21
27
  };
package/dist/Popup.js CHANGED
@@ -1,34 +1,27 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { useEffect } from 'react';
1
+ import { useEffect, useContext } from 'react';
13
2
  import maplibre from 'maplibre-gl';
14
- import { useMap } from './Map';
15
- import ReactDOMServer from 'react-dom/server'; // eslint-disable-line import/no-webpack-loader-syntax
16
- export const Popup = (_a) => {
17
- var { children, longitude, latitude } = _a, options = __rest(_a, ["children", "longitude", "latitude"]);
18
- const { map } = useMap();
19
- const optionsString = JSON.stringify(options);
3
+ import ReactDOMServer from 'react-dom/server';
4
+ import { MapContext } from './Map';
5
+ export const Popup = ({ children, longitude, latitude, className, closeOnClick, closeButton, }) => {
6
+ const { map, mapLoaded } = useContext(MapContext);
20
7
  useEffect(() => {
21
8
  let popup = null;
22
- if (map) {
23
- popup = new maplibre.Popup(Object.assign({ offset: [0, -15] }, JSON.parse(optionsString)))
9
+ if (map && mapLoaded) {
10
+ popup = new maplibre.Popup({ offset: [0, -15], className, closeOnClick, closeButton })
24
11
  .setLngLat([longitude, latitude])
25
12
  .setHTML(ReactDOMServer.renderToStaticMarkup(children))
26
13
  .addTo(map);
27
14
  }
28
15
  return () => {
29
- if (popup)
30
- popup.remove();
16
+ try {
17
+ if (popup) {
18
+ popup.remove();
19
+ }
20
+ }
21
+ catch (_a) {
22
+ console.warn('Error cleaning up Popup');
23
+ }
31
24
  };
32
- }, [children, latitude, longitude, map, optionsString]);
25
+ }, [children, latitude, longitude, map, className, closeOnClick, closeButton, mapLoaded]);
33
26
  return null;
34
27
  };
@@ -1,6 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { ScaleControlOptions } from 'maplibre-gl';
3
- import { ControlPosition } from './types';
2
+ import { ScaleControlOptions, ControlPosition } from 'maplibre-gl';
4
3
  export type ScaleControlProps = {
5
4
  position?: ControlPosition;
6
5
  options?: ScaleControlOptions;
@@ -1,18 +1,24 @@
1
- import { useEffect } from 'react';
1
+ import { useContext, useEffect } from 'react';
2
2
  import maplibre from 'maplibre-gl';
3
- import { useMap } from './Map';
4
- export const ScaleControl = ({ position = 'bottom-right', options, }) => {
5
- const { map } = useMap();
3
+ import { MapContext } from './Map';
4
+ export const ScaleControl = ({ position = 'bottom-right', options }) => {
5
+ const { map, mapLoaded } = useContext(MapContext);
6
+ const optionsString = JSON.stringify(options || {});
6
7
  useEffect(() => {
7
- const control = new maplibre.ScaleControl(options);
8
- if (map && position) {
8
+ const control = new maplibre.ScaleControl(JSON.parse(optionsString));
9
+ if (map && mapLoaded && position) {
9
10
  map.addControl(control, position);
10
11
  }
11
12
  return () => {
12
- if (map && map.hasControl(control)) {
13
- map.removeControl(control);
13
+ try {
14
+ if (map && !map._removed && map.hasControl(control)) {
15
+ map.removeControl(control);
16
+ }
17
+ }
18
+ catch (_a) {
19
+ console.warn('Error cleaning up ScaleControl');
14
20
  }
15
21
  };
16
- }, [position, options, map]);
22
+ }, [position, optionsString, map, mapLoaded]);
17
23
  return null;
18
24
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { Map, useMap, MapProvider, viewStateFromMap } from './Map';
2
- export type { ViewState } from './Map';
1
+ export { Map, MapContext } from './Map';
2
+ export type { MapDragEndEvent } from './Map';
3
3
  export { Marker } from './Marker';
4
4
  export { Popup } from './Popup';
5
5
  export { Layer } from './Layer';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Map, useMap, MapProvider, viewStateFromMap } from './Map';
1
+ export { Map, MapContext } from './Map';
2
2
  export { Marker } from './Marker';
3
3
  export { Popup } from './Popup';
4
4
  export { Layer } from './Layer';
@@ -1 +1 @@
1
- {"root":["../src/ErrorBoundary.tsx","../src/GeolocateControl.tsx","../src/Layer.tsx","../src/Map.tsx","../src/Marker.tsx","../src/NavigationControl.tsx","../src/Popup.tsx","../src/ScaleControl.tsx","../src/index.tsx","../src/types.tsx"],"version":"5.8.2"}
1
+ {"root":["../src/ErrorBoundary.tsx","../src/GeolocateControl.tsx","../src/Layer.tsx","../src/Map.tsx","../src/Marker.tsx","../src/NavigationControl.tsx","../src/Popup.tsx","../src/ScaleControl.tsx","../src/index.ts"],"version":"5.8.2"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vinctus/react-maplibre",
3
- "version": "0.2.26",
3
+ "version": "1.0.0",
4
4
  "description": "Minimalist MapLibre GL JS React wrapper library",
5
5
  "type": "module",
6
6
  "types": "dist/index.d.ts",
package/dist/types.d.ts DELETED
@@ -1 +0,0 @@
1
- export type ControlPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};